aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/Makefile1
-rw-r--r--arch/powerpc/platforms/cell/Makefile2
-rw-r--r--arch/powerpc/platforms/cell/interrupt.c284
-rw-r--r--arch/powerpc/platforms/cell/interrupt.h62
-rw-r--r--arch/powerpc/platforms/cell/iommu.c381
-rw-r--r--arch/powerpc/platforms/cell/iommu.h65
-rw-r--r--arch/powerpc/platforms/cell/setup.c141
-rw-r--r--arch/powerpc/platforms/cell/smp.c230
-rw-r--r--arch/powerpc/platforms/cell/spider-pic.c191
-rw-r--r--arch/powerpc/platforms/chrp/nvram.c13
-rw-r--r--arch/powerpc/platforms/chrp/pegasos_eth.c1
-rw-r--r--arch/powerpc/platforms/chrp/smp.c39
-rw-r--r--arch/powerpc/platforms/iseries/call_hpt.h4
-rw-r--r--arch/powerpc/platforms/iseries/call_pci.h4
-rw-r--r--arch/powerpc/platforms/iseries/call_sm.h4
-rw-r--r--arch/powerpc/platforms/iseries/hvlog.c6
-rw-r--r--arch/powerpc/platforms/iseries/hvlpconfig.c2
-rw-r--r--arch/powerpc/platforms/iseries/iommu.c2
-rw-r--r--arch/powerpc/platforms/iseries/irq.c6
-rw-r--r--arch/powerpc/platforms/iseries/ksyms.c2
-rw-r--r--arch/powerpc/platforms/iseries/lpardata.c12
-rw-r--r--arch/powerpc/platforms/iseries/lpevents.c8
-rw-r--r--arch/powerpc/platforms/iseries/mf.c8
-rw-r--r--arch/powerpc/platforms/iseries/naca.h24
-rw-r--r--arch/powerpc/platforms/iseries/pci.c4
-rw-r--r--arch/powerpc/platforms/iseries/proc.c4
-rw-r--r--arch/powerpc/platforms/iseries/release_data.h2
-rw-r--r--arch/powerpc/platforms/iseries/setup.c60
-rw-r--r--arch/powerpc/platforms/iseries/smp.c2
-rw-r--r--arch/powerpc/platforms/iseries/vio.c8
-rw-r--r--arch/powerpc/platforms/iseries/viopath.c12
-rw-r--r--arch/powerpc/platforms/iseries/vpdinfo.c2
-rw-r--r--arch/powerpc/platforms/powermac/pic.c8
-rw-r--r--arch/powerpc/platforms/powermac/setup.c3
-rw-r--r--arch/powerpc/platforms/pseries/Kconfig9
-rw-r--r--arch/powerpc/platforms/pseries/Makefile2
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c5
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c13
-rw-r--r--arch/powerpc/platforms/pseries/plpar_wrappers.h120
-rw-r--r--arch/powerpc/platforms/pseries/rtas-fw.c138
-rw-r--r--arch/powerpc/platforms/pseries/rtas-fw.h3
-rw-r--r--arch/powerpc/platforms/pseries/rtasd.c527
-rw-r--r--arch/powerpc/platforms/pseries/setup.c21
-rw-r--r--arch/powerpc/platforms/pseries/smp.c3
44 files changed, 2152 insertions, 286 deletions
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index 172c0db63504..8836b3a00668 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_85xx) += 85xx/
11obj-$(CONFIG_PPC_PSERIES) += pseries/ 11obj-$(CONFIG_PPC_PSERIES) += pseries/
12obj-$(CONFIG_PPC_ISERIES) += iseries/ 12obj-$(CONFIG_PPC_ISERIES) += iseries/
13obj-$(CONFIG_PPC_MAPLE) += maple/ 13obj-$(CONFIG_PPC_MAPLE) += maple/
14obj-$(CONFIG_PPC_CELL) += cell/
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
new file mode 100644
index 000000000000..55e094b96bc0
--- /dev/null
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -0,0 +1,2 @@
1obj-y += interrupt.o iommu.o setup.o spider-pic.o
2obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
new file mode 100644
index 000000000000..7fbe78a9327d
--- /dev/null
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -0,0 +1,284 @@
1/*
2 * Cell Internal Interrupt Controller
3 *
4 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
5 *
6 * Author: Arnd Bergmann <arndb@de.ibm.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <linux/config.h>
24#include <linux/interrupt.h>
25#include <linux/irq.h>
26#include <linux/percpu.h>
27#include <linux/types.h>
28
29#include <asm/io.h>
30#include <asm/pgtable.h>
31#include <asm/prom.h>
32#include <asm/ptrace.h>
33
34#include "interrupt.h"
35
36struct iic_pending_bits {
37 u32 data;
38 u8 flags;
39 u8 class;
40 u8 source;
41 u8 prio;
42};
43
44enum iic_pending_flags {
45 IIC_VALID = 0x80,
46 IIC_IPI = 0x40,
47};
48
49struct iic_regs {
50 struct iic_pending_bits pending;
51 struct iic_pending_bits pending_destr;
52 u64 generate;
53 u64 prio;
54};
55
56struct iic {
57 struct iic_regs __iomem *regs;
58};
59
60static DEFINE_PER_CPU(struct iic, iic);
61
62void iic_local_enable(void)
63{
64 out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
65}
66
67void iic_local_disable(void)
68{
69 out_be64(&__get_cpu_var(iic).regs->prio, 0x0);
70}
71
72static unsigned int iic_startup(unsigned int irq)
73{
74 return 0;
75}
76
77static void iic_enable(unsigned int irq)
78{
79 iic_local_enable();
80}
81
82static void iic_disable(unsigned int irq)
83{
84}
85
86static void iic_end(unsigned int irq)
87{
88 iic_local_enable();
89}
90
91static struct hw_interrupt_type iic_pic = {
92 .typename = " CELL-IIC ",
93 .startup = iic_startup,
94 .enable = iic_enable,
95 .disable = iic_disable,
96 .end = iic_end,
97};
98
99static int iic_external_get_irq(struct iic_pending_bits pending)
100{
101 int irq;
102 unsigned char node, unit;
103
104 node = pending.source >> 4;
105 unit = pending.source & 0xf;
106 irq = -1;
107
108 /*
109 * This mapping is specific to the Cell Broadband
110 * Engine. We might need to get the numbers
111 * from the device tree to support future CPUs.
112 */
113 switch (unit) {
114 case 0x00:
115 case 0x0b:
116 /*
117 * One of these units can be connected
118 * to an external interrupt controller.
119 */
120 if (pending.prio > 0x3f ||
121 pending.class != 2)
122 break;
123 irq = IIC_EXT_OFFSET
124 + spider_get_irq(pending.prio + node * IIC_NODE_STRIDE)
125 + node * IIC_NODE_STRIDE;
126 break;
127 case 0x01 ... 0x04:
128 case 0x07 ... 0x0a:
129 /*
130 * These units are connected to the SPEs
131 */
132 if (pending.class > 2)
133 break;
134 irq = IIC_SPE_OFFSET
135 + pending.class * IIC_CLASS_STRIDE
136 + node * IIC_NODE_STRIDE
137 + unit;
138 break;
139 }
140 if (irq == -1)
141 printk(KERN_WARNING "Unexpected interrupt class %02x, "
142 "source %02x, prio %02x, cpu %02x\n", pending.class,
143 pending.source, pending.prio, smp_processor_id());
144 return irq;
145}
146
147/* Get an IRQ number from the pending state register of the IIC */
148int iic_get_irq(struct pt_regs *regs)
149{
150 struct iic *iic;
151 int irq;
152 struct iic_pending_bits pending;
153
154 iic = &__get_cpu_var(iic);
155 *(unsigned long *) &pending =
156 in_be64((unsigned long __iomem *) &iic->regs->pending_destr);
157
158 irq = -1;
159 if (pending.flags & IIC_VALID) {
160 if (pending.flags & IIC_IPI) {
161 irq = IIC_IPI_OFFSET + (pending.prio >> 4);
162/*
163 if (irq > 0x80)
164 printk(KERN_WARNING "Unexpected IPI prio %02x"
165 "on CPU %02x\n", pending.prio,
166 smp_processor_id());
167*/
168 } else {
169 irq = iic_external_get_irq(pending);
170 }
171 }
172 return irq;
173}
174
175static struct iic_regs __iomem *find_iic(int cpu)
176{
177 struct device_node *np;
178 int nodeid = cpu / 2;
179 unsigned long regs;
180 struct iic_regs __iomem *iic_regs;
181
182 for (np = of_find_node_by_type(NULL, "cpu");
183 np;
184 np = of_find_node_by_type(np, "cpu")) {
185 if (nodeid == *(int *)get_property(np, "node-id", NULL))
186 break;
187 }
188
189 if (!np) {
190 printk(KERN_WARNING "IIC: CPU %d not found\n", cpu);
191 iic_regs = NULL;
192 } else {
193 regs = *(long *)get_property(np, "iic", NULL);
194
195 /* hack until we have decided on the devtree info */
196 regs += 0x400;
197 if (cpu & 1)
198 regs += 0x20;
199
200 printk(KERN_DEBUG "IIC for CPU %d at %lx\n", cpu, regs);
201 iic_regs = __ioremap(regs, sizeof(struct iic_regs),
202 _PAGE_NO_CACHE);
203 }
204 return iic_regs;
205}
206
207#ifdef CONFIG_SMP
208
209/* Use the highest interrupt priorities for IPI */
210static inline int iic_ipi_to_irq(int ipi)
211{
212 return IIC_IPI_OFFSET + IIC_NUM_IPIS - 1 - ipi;
213}
214
215static inline int iic_irq_to_ipi(int irq)
216{
217 return IIC_NUM_IPIS - 1 - (irq - IIC_IPI_OFFSET);
218}
219
220void iic_setup_cpu(void)
221{
222 out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
223}
224
225void iic_cause_IPI(int cpu, int mesg)
226{
227 out_be64(&per_cpu(iic, cpu).regs->generate, (IIC_NUM_IPIS - 1 - mesg) << 4);
228}
229
230static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
231{
232 smp_message_recv(iic_irq_to_ipi(irq), regs);
233 return IRQ_HANDLED;
234}
235
236static void iic_request_ipi(int ipi, const char *name)
237{
238 int irq;
239
240 irq = iic_ipi_to_irq(ipi);
241 /* IPIs are marked SA_INTERRUPT as they must run with irqs
242 * disabled */
243 get_irq_desc(irq)->handler = &iic_pic;
244 get_irq_desc(irq)->status |= IRQ_PER_CPU;
245 request_irq(irq, iic_ipi_action, SA_INTERRUPT, name, NULL);
246}
247
248void iic_request_IPIs(void)
249{
250 iic_request_ipi(PPC_MSG_CALL_FUNCTION, "IPI-call");
251 iic_request_ipi(PPC_MSG_RESCHEDULE, "IPI-resched");
252#ifdef CONFIG_DEBUGGER
253 iic_request_ipi(PPC_MSG_DEBUGGER_BREAK, "IPI-debug");
254#endif /* CONFIG_DEBUGGER */
255}
256#endif /* CONFIG_SMP */
257
258static void iic_setup_spe_handlers(void)
259{
260 int be, isrc;
261
262 /* Assume two threads per BE are present */
263 for (be=0; be < num_present_cpus() / 2; be++) {
264 for (isrc = 0; isrc < IIC_CLASS_STRIDE * 3; isrc++) {
265 int irq = IIC_NODE_STRIDE * be + IIC_SPE_OFFSET + isrc;
266 get_irq_desc(irq)->handler = &iic_pic;
267 }
268 }
269}
270
271void iic_init_IRQ(void)
272{
273 int cpu, irq_offset;
274 struct iic *iic;
275
276 irq_offset = 0;
277 for_each_cpu(cpu) {
278 iic = &per_cpu(iic, cpu);
279 iic->regs = find_iic(cpu);
280 if (iic->regs)
281 out_be64(&iic->regs->prio, 0xff);
282 }
283 iic_setup_spe_handlers();
284}
diff --git a/arch/powerpc/platforms/cell/interrupt.h b/arch/powerpc/platforms/cell/interrupt.h
new file mode 100644
index 000000000000..37d58e6fd0c6
--- /dev/null
+++ b/arch/powerpc/platforms/cell/interrupt.h
@@ -0,0 +1,62 @@
1#ifndef ASM_CELL_PIC_H
2#define ASM_CELL_PIC_H
3#ifdef __KERNEL__
4/*
5 * Mapping of IIC pending bits into per-node
6 * interrupt numbers.
7 *
8 * IRQ FF CC SS PP FF CC SS PP Description
9 *
10 * 00-3f 80 02 +0 00 - 80 02 +0 3f South Bridge
11 * 00-3f 80 02 +b 00 - 80 02 +b 3f South Bridge
12 * 41-4a 80 00 +1 ** - 80 00 +a ** SPU Class 0
13 * 51-5a 80 01 +1 ** - 80 01 +a ** SPU Class 1
14 * 61-6a 80 02 +1 ** - 80 02 +a ** SPU Class 2
15 * 70-7f C0 ** ** 00 - C0 ** ** 0f IPI
16 *
17 * F flags
18 * C class
19 * S source
20 * P Priority
21 * + node number
22 * * don't care
23 *
24 * A node consists of a Cell Broadband Engine and an optional
25 * south bridge device providing a maximum of 64 IRQs.
26 * The south bridge may be connected to either IOIF0
27 * or IOIF1.
28 * Each SPE is represented as three IRQ lines, one per
29 * interrupt class.
30 * 16 IRQ numbers are reserved for inter processor
31 * interruptions, although these are only used in the
32 * range of the first node.
33 *
34 * This scheme needs 128 IRQ numbers per BIF node ID,
35 * which means that with the total of 512 lines
36 * available, we can have a maximum of four nodes.
37 */
38
39enum {
40 IIC_EXT_OFFSET = 0x00, /* Start of south bridge IRQs */
41 IIC_NUM_EXT = 0x40, /* Number of south bridge IRQs */
42 IIC_SPE_OFFSET = 0x40, /* Start of SPE interrupts */
43 IIC_CLASS_STRIDE = 0x10, /* SPE IRQs per class */
44 IIC_IPI_OFFSET = 0x70, /* Start of IPI IRQs */
45 IIC_NUM_IPIS = 0x10, /* IRQs reserved for IPI */
46 IIC_NODE_STRIDE = 0x80, /* Total IRQs per node */
47};
48
49extern void iic_init_IRQ(void);
50extern int iic_get_irq(struct pt_regs *regs);
51extern void iic_cause_IPI(int cpu, int mesg);
52extern void iic_request_IPIs(void);
53extern void iic_setup_cpu(void);
54extern void iic_local_enable(void);
55extern void iic_local_disable(void);
56
57
58extern void spider_init_IRQ(void);
59extern int spider_get_irq(unsigned long int_pending);
60
61#endif
62#endif /* ASM_CELL_PIC_H */
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
new file mode 100644
index 000000000000..74f999b4ac9e
--- /dev/null
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -0,0 +1,381 @@
1/*
2 * IOMMU implementation for Cell Broadband Processor Architecture
3 * We just establish a linear mapping at boot by setting all the
4 * IOPT cache entries in the CPU.
5 * The mapping functions should be identical to pci_direct_iommu,
6 * except for the handling of the high order bit that is required
7 * by the Spider bridge. These should be split into a separate
8 * file at the point where we get a different bridge chip.
9 *
10 * Copyright (C) 2005 IBM Deutschland Entwicklung GmbH,
11 * Arnd Bergmann <arndb@de.ibm.com>
12 *
13 * Based on linear mapping
14 * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org)
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version
19 * 2 of the License, or (at your option) any later version.
20 */
21
22#undef DEBUG
23
24#include <linux/kernel.h>
25#include <linux/pci.h>
26#include <linux/delay.h>
27#include <linux/string.h>
28#include <linux/init.h>
29#include <linux/bootmem.h>
30#include <linux/mm.h>
31#include <linux/dma-mapping.h>
32
33#include <asm/sections.h>
34#include <asm/iommu.h>
35#include <asm/io.h>
36#include <asm/prom.h>
37#include <asm/pci-bridge.h>
38#include <asm/machdep.h>
39#include <asm/pmac_feature.h>
40#include <asm/abs_addr.h>
41#include <asm/system.h>
42#include <asm/ppc-pci.h>
43
44#include "iommu.h"
45
46static inline unsigned long
47get_iopt_entry(unsigned long real_address, unsigned long ioid,
48 unsigned long prot)
49{
50 return (prot & IOPT_PROT_MASK)
51 | (IOPT_COHERENT)
52 | (IOPT_ORDER_VC)
53 | (real_address & IOPT_RPN_MASK)
54 | (ioid & IOPT_IOID_MASK);
55}
56
57typedef struct {
58 unsigned long val;
59} ioste;
60
61static inline ioste
62mk_ioste(unsigned long val)
63{
64 ioste ioste = { .val = val, };
65 return ioste;
66}
67
68static inline ioste
69get_iost_entry(unsigned long iopt_base, unsigned long io_address, unsigned page_size)
70{
71 unsigned long ps;
72 unsigned long iostep;
73 unsigned long nnpt;
74 unsigned long shift;
75
76 switch (page_size) {
77 case 0x1000000:
78 ps = IOST_PS_16M;
79 nnpt = 0; /* one page per segment */
80 shift = 5; /* segment has 16 iopt entries */
81 break;
82
83 case 0x100000:
84 ps = IOST_PS_1M;
85 nnpt = 0; /* one page per segment */
86 shift = 1; /* segment has 256 iopt entries */
87 break;
88
89 case 0x10000:
90 ps = IOST_PS_64K;
91 nnpt = 0x07; /* 8 pages per io page table */
92 shift = 0; /* all entries are used */
93 break;
94
95 case 0x1000:
96 ps = IOST_PS_4K;
97 nnpt = 0x7f; /* 128 pages per io page table */
98 shift = 0; /* all entries are used */
99 break;
100
101 default: /* not a known compile time constant */
102 {
103 /* BUILD_BUG_ON() is not usable here */
104 extern void __get_iost_entry_bad_page_size(void);
105 __get_iost_entry_bad_page_size();
106 }
107 break;
108 }
109
110 iostep = iopt_base +
111 /* need 8 bytes per iopte */
112 (((io_address / page_size * 8)
113 /* align io page tables on 4k page boundaries */
114 << shift)
115 /* nnpt+1 pages go into each iopt */
116 & ~(nnpt << 12));
117
118 nnpt++; /* this seems to work, but the documentation is not clear
119 about wether we put nnpt or nnpt-1 into the ioste bits.
120 In theory, this can't work for 4k pages. */
121 return mk_ioste(IOST_VALID_MASK
122 | (iostep & IOST_PT_BASE_MASK)
123 | ((nnpt << 5) & IOST_NNPT_MASK)
124 | (ps & IOST_PS_MASK));
125}
126
127/* compute the address of an io pte */
128static inline unsigned long
129get_ioptep(ioste iost_entry, unsigned long io_address)
130{
131 unsigned long iopt_base;
132 unsigned long page_size;
133 unsigned long page_number;
134 unsigned long iopt_offset;
135
136 iopt_base = iost_entry.val & IOST_PT_BASE_MASK;
137 page_size = iost_entry.val & IOST_PS_MASK;
138
139 /* decode page size to compute page number */
140 page_number = (io_address & 0x0fffffff) >> (10 + 2 * page_size);
141 /* page number is an offset into the io page table */
142 iopt_offset = (page_number << 3) & 0x7fff8ul;
143 return iopt_base + iopt_offset;
144}
145
146/* compute the tag field of the iopt cache entry */
147static inline unsigned long
148get_ioc_tag(ioste iost_entry, unsigned long io_address)
149{
150 unsigned long iopte = get_ioptep(iost_entry, io_address);
151
152 return IOPT_VALID_MASK
153 | ((iopte & 0x00000000000000ff8ul) >> 3)
154 | ((iopte & 0x0000003fffffc0000ul) >> 9);
155}
156
157/* compute the hashed 6 bit index for the 4-way associative pte cache */
158static inline unsigned long
159get_ioc_hash(ioste iost_entry, unsigned long io_address)
160{
161 unsigned long iopte = get_ioptep(iost_entry, io_address);
162
163 return ((iopte & 0x000000000000001f8ul) >> 3)
164 ^ ((iopte & 0x00000000000020000ul) >> 17)
165 ^ ((iopte & 0x00000000000010000ul) >> 15)
166 ^ ((iopte & 0x00000000000008000ul) >> 13)
167 ^ ((iopte & 0x00000000000004000ul) >> 11)
168 ^ ((iopte & 0x00000000000002000ul) >> 9)
169 ^ ((iopte & 0x00000000000001000ul) >> 7);
170}
171
172/* same as above, but pretend that we have a simpler 1-way associative
173 pte cache with an 8 bit index */
174static inline unsigned long
175get_ioc_hash_1way(ioste iost_entry, unsigned long io_address)
176{
177 unsigned long iopte = get_ioptep(iost_entry, io_address);
178
179 return ((iopte & 0x000000000000001f8ul) >> 3)
180 ^ ((iopte & 0x00000000000020000ul) >> 17)
181 ^ ((iopte & 0x00000000000010000ul) >> 15)
182 ^ ((iopte & 0x00000000000008000ul) >> 13)
183 ^ ((iopte & 0x00000000000004000ul) >> 11)
184 ^ ((iopte & 0x00000000000002000ul) >> 9)
185 ^ ((iopte & 0x00000000000001000ul) >> 7)
186 ^ ((iopte & 0x0000000000000c000ul) >> 8);
187}
188
189static inline ioste
190get_iost_cache(void __iomem *base, unsigned long index)
191{
192 unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR);
193 return mk_ioste(in_be64(&p[index]));
194}
195
196static inline void
197set_iost_cache(void __iomem *base, unsigned long index, ioste ste)
198{
199 unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR);
200 pr_debug("ioste %02lx was %016lx, store %016lx", index,
201 get_iost_cache(base, index).val, ste.val);
202 out_be64(&p[index], ste.val);
203 pr_debug(" now %016lx\n", get_iost_cache(base, index).val);
204}
205
206static inline unsigned long
207get_iopt_cache(void __iomem *base, unsigned long index, unsigned long *tag)
208{
209 unsigned long __iomem *tags = (void *)(base + IOC_PT_CACHE_DIR);
210 unsigned long __iomem *p = (void *)(base + IOC_PT_CACHE_REG);
211
212 *tag = tags[index];
213 rmb();
214 return *p;
215}
216
217static inline void
218set_iopt_cache(void __iomem *base, unsigned long index,
219 unsigned long tag, unsigned long val)
220{
221 unsigned long __iomem *tags = base + IOC_PT_CACHE_DIR;
222 unsigned long __iomem *p = base + IOC_PT_CACHE_REG;
223 pr_debug("iopt %02lx was v%016lx/t%016lx, store v%016lx/t%016lx\n",
224 index, get_iopt_cache(base, index, &oldtag), oldtag, val, tag);
225
226 out_be64(p, val);
227 out_be64(&tags[index], tag);
228}
229
230static inline void
231set_iost_origin(void __iomem *base)
232{
233 unsigned long __iomem *p = base + IOC_ST_ORIGIN;
234 unsigned long origin = IOSTO_ENABLE | IOSTO_SW;
235
236 pr_debug("iost_origin %016lx, now %016lx\n", in_be64(p), origin);
237 out_be64(p, origin);
238}
239
240static inline void
241set_iocmd_config(void __iomem *base)
242{
243 unsigned long __iomem *p = base + 0xc00;
244 unsigned long conf;
245
246 conf = in_be64(p);
247 pr_debug("iost_conf %016lx, now %016lx\n", conf, conf | IOCMD_CONF_TE);
248 out_be64(p, conf | IOCMD_CONF_TE);
249}
250
251/* FIXME: get these from the device tree */
252#define ioc_base 0x20000511000ull
253#define ioc_mmio_base 0x20000510000ull
254#define ioid 0x48a
255#define iopt_phys_offset (- 0x20000000) /* We have a 512MB offset from the SB */
256#define io_page_size 0x1000000
257
258static unsigned long map_iopt_entry(unsigned long address)
259{
260 switch (address >> 20) {
261 case 0x600:
262 address = 0x24020000000ull; /* spider i/o */
263 break;
264 default:
265 address += iopt_phys_offset;
266 break;
267 }
268
269 return get_iopt_entry(address, ioid, IOPT_PROT_RW);
270}
271
272static void iommu_bus_setup_null(struct pci_bus *b) { }
273static void iommu_dev_setup_null(struct pci_dev *d) { }
274
275/* initialize the iommu to support a simple linear mapping
276 * for each DMA window used by any device. For now, we
277 * happen to know that there is only one DMA window in use,
278 * starting at iopt_phys_offset. */
279static void cell_map_iommu(void)
280{
281 unsigned long address;
282 void __iomem *base;
283 ioste ioste;
284 unsigned long index;
285
286 base = __ioremap(ioc_base, 0x1000, _PAGE_NO_CACHE);
287 pr_debug("%lx mapped to %p\n", ioc_base, base);
288 set_iocmd_config(base);
289 iounmap(base);
290
291 base = __ioremap(ioc_mmio_base, 0x1000, _PAGE_NO_CACHE);
292 pr_debug("%lx mapped to %p\n", ioc_mmio_base, base);
293
294 set_iost_origin(base);
295
296 for (address = 0; address < 0x100000000ul; address += io_page_size) {
297 ioste = get_iost_entry(0x10000000000ul, address, io_page_size);
298 if ((address & 0xfffffff) == 0) /* segment start */
299 set_iost_cache(base, address >> 28, ioste);
300 index = get_ioc_hash_1way(ioste, address);
301 pr_debug("addr %08lx, index %02lx, ioste %016lx\n",
302 address, index, ioste.val);
303 set_iopt_cache(base,
304 get_ioc_hash_1way(ioste, address),
305 get_ioc_tag(ioste, address),
306 map_iopt_entry(address));
307 }
308 iounmap(base);
309}
310
311
312static void *cell_alloc_coherent(struct device *hwdev, size_t size,
313 dma_addr_t *dma_handle, gfp_t flag)
314{
315 void *ret;
316
317 ret = (void *)__get_free_pages(flag, get_order(size));
318 if (ret != NULL) {
319 memset(ret, 0, size);
320 *dma_handle = virt_to_abs(ret) | CELL_DMA_VALID;
321 }
322 return ret;
323}
324
325static void cell_free_coherent(struct device *hwdev, size_t size,
326 void *vaddr, dma_addr_t dma_handle)
327{
328 free_pages((unsigned long)vaddr, get_order(size));
329}
330
331static dma_addr_t cell_map_single(struct device *hwdev, void *ptr,
332 size_t size, enum dma_data_direction direction)
333{
334 return virt_to_abs(ptr) | CELL_DMA_VALID;
335}
336
337static void cell_unmap_single(struct device *hwdev, dma_addr_t dma_addr,
338 size_t size, enum dma_data_direction direction)
339{
340}
341
342static int cell_map_sg(struct device *hwdev, struct scatterlist *sg,
343 int nents, enum dma_data_direction direction)
344{
345 int i;
346
347 for (i = 0; i < nents; i++, sg++) {
348 sg->dma_address = (page_to_phys(sg->page) + sg->offset)
349 | CELL_DMA_VALID;
350 sg->dma_length = sg->length;
351 }
352
353 return nents;
354}
355
356static void cell_unmap_sg(struct device *hwdev, struct scatterlist *sg,
357 int nents, enum dma_data_direction direction)
358{
359}
360
361static int cell_dma_supported(struct device *dev, u64 mask)
362{
363 return mask < 0x100000000ull;
364}
365
366void cell_init_iommu(void)
367{
368 cell_map_iommu();
369
370 /* Direct I/O, IOMMU off */
371 ppc_md.iommu_dev_setup = iommu_dev_setup_null;
372 ppc_md.iommu_bus_setup = iommu_bus_setup_null;
373
374 pci_dma_ops.alloc_coherent = cell_alloc_coherent;
375 pci_dma_ops.free_coherent = cell_free_coherent;
376 pci_dma_ops.map_single = cell_map_single;
377 pci_dma_ops.unmap_single = cell_unmap_single;
378 pci_dma_ops.map_sg = cell_map_sg;
379 pci_dma_ops.unmap_sg = cell_unmap_sg;
380 pci_dma_ops.dma_supported = cell_dma_supported;
381}
diff --git a/arch/powerpc/platforms/cell/iommu.h b/arch/powerpc/platforms/cell/iommu.h
new file mode 100644
index 000000000000..490d77abfe85
--- /dev/null
+++ b/arch/powerpc/platforms/cell/iommu.h
@@ -0,0 +1,65 @@
1#ifndef CELL_IOMMU_H
2#define CELL_IOMMU_H
3
4/* some constants */
5enum {
6 /* segment table entries */
7 IOST_VALID_MASK = 0x8000000000000000ul,
8 IOST_TAG_MASK = 0x3000000000000000ul,
9 IOST_PT_BASE_MASK = 0x000003fffffff000ul,
10 IOST_NNPT_MASK = 0x0000000000000fe0ul,
11 IOST_PS_MASK = 0x000000000000000ful,
12
13 IOST_PS_4K = 0x1,
14 IOST_PS_64K = 0x3,
15 IOST_PS_1M = 0x5,
16 IOST_PS_16M = 0x7,
17
18 /* iopt tag register */
19 IOPT_VALID_MASK = 0x0000000200000000ul,
20 IOPT_TAG_MASK = 0x00000001fffffffful,
21
22 /* iopt cache register */
23 IOPT_PROT_MASK = 0xc000000000000000ul,
24 IOPT_PROT_NONE = 0x0000000000000000ul,
25 IOPT_PROT_READ = 0x4000000000000000ul,
26 IOPT_PROT_WRITE = 0x8000000000000000ul,
27 IOPT_PROT_RW = 0xc000000000000000ul,
28 IOPT_COHERENT = 0x2000000000000000ul,
29
30 IOPT_ORDER_MASK = 0x1800000000000000ul,
31 /* order access to same IOID/VC on same address */
32 IOPT_ORDER_ADDR = 0x0800000000000000ul,
33 /* similar, but only after a write access */
34 IOPT_ORDER_WRITES = 0x1000000000000000ul,
35 /* Order all accesses to same IOID/VC */
36 IOPT_ORDER_VC = 0x1800000000000000ul,
37
38 IOPT_RPN_MASK = 0x000003fffffff000ul,
39 IOPT_HINT_MASK = 0x0000000000000800ul,
40 IOPT_IOID_MASK = 0x00000000000007fful,
41
42 IOSTO_ENABLE = 0x8000000000000000ul,
43 IOSTO_ORIGIN = 0x000003fffffff000ul,
44 IOSTO_HW = 0x0000000000000800ul,
45 IOSTO_SW = 0x0000000000000400ul,
46
47 IOCMD_CONF_TE = 0x0000800000000000ul,
48
49 /* memory mapped registers */
50 IOC_PT_CACHE_DIR = 0x000,
51 IOC_ST_CACHE_DIR = 0x800,
52 IOC_PT_CACHE_REG = 0x910,
53 IOC_ST_ORIGIN = 0x918,
54 IOC_CONF = 0x930,
55
56 /* The high bit needs to be set on every DMA address,
57 only 2GB are addressable */
58 CELL_DMA_VALID = 0x80000000,
59 CELL_DMA_MASK = 0x7fffffff,
60};
61
62
63void cell_init_iommu(void);
64
65#endif
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
new file mode 100644
index 000000000000..9a495634d0c2
--- /dev/null
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -0,0 +1,141 @@
1/*
2 * linux/arch/powerpc/platforms/cell/cell_setup.c
3 *
4 * Copyright (C) 1995 Linus Torvalds
5 * Adapted from 'alpha' version by Gary Thomas
6 * Modified by Cort Dougan (cort@cs.nmt.edu)
7 * Modified by PPC64 Team, IBM Corp
8 * Modified by Cell Team, IBM Deutschland Entwicklung GmbH
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15#undef DEBUG
16
17#include <linux/config.h>
18#include <linux/sched.h>
19#include <linux/kernel.h>
20#include <linux/mm.h>
21#include <linux/stddef.h>
22#include <linux/unistd.h>
23#include <linux/slab.h>
24#include <linux/user.h>
25#include <linux/reboot.h>
26#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/irq.h>
29#include <linux/seq_file.h>
30#include <linux/root_dev.h>
31#include <linux/console.h>
32
33#include <asm/mmu.h>
34#include <asm/processor.h>
35#include <asm/io.h>
36#include <asm/pgtable.h>
37#include <asm/prom.h>
38#include <asm/rtas.h>
39#include <asm/pci-bridge.h>
40#include <asm/iommu.h>
41#include <asm/dma.h>
42#include <asm/machdep.h>
43#include <asm/time.h>
44#include <asm/nvram.h>
45#include <asm/cputable.h>
46#include <asm/ppc-pci.h>
47#include <asm/irq.h>
48
49#include "interrupt.h"
50#include "iommu.h"
51
52#ifdef DEBUG
53#define DBG(fmt...) udbg_printf(fmt)
54#else
55#define DBG(fmt...)
56#endif
57
58void cell_show_cpuinfo(struct seq_file *m)
59{
60 struct device_node *root;
61 const char *model = "";
62
63 root = of_find_node_by_path("/");
64 if (root)
65 model = get_property(root, "model", NULL);
66 seq_printf(m, "machine\t\t: CHRP %s\n", model);
67 of_node_put(root);
68}
69
70static void cell_progress(char *s, unsigned short hex)
71{
72 printk("*** %04x : %s\n", hex, s ? s : "");
73}
74
75static void __init cell_setup_arch(void)
76{
77 ppc_md.init_IRQ = iic_init_IRQ;
78 ppc_md.get_irq = iic_get_irq;
79
80#ifdef CONFIG_SMP
81 smp_init_cell();
82#endif
83
84 /* init to some ~sane value until calibrate_delay() runs */
85 loops_per_jiffy = 50000000;
86
87 if (ROOT_DEV == 0) {
88 printk("No ramdisk, default root is /dev/hda2\n");
89 ROOT_DEV = Root_HDA2;
90 }
91
92 /* Find and initialize PCI host bridges */
93 init_pci_config_tokens();
94 find_and_init_phbs();
95 spider_init_IRQ();
96#ifdef CONFIG_DUMMY_CONSOLE
97 conswitchp = &dummy_con;
98#endif
99
100 mmio_nvram_init();
101}
102
103/*
104 * Early initialization. Relocation is on but do not reference unbolted pages
105 */
106static void __init cell_init_early(void)
107{
108 DBG(" -> cell_init_early()\n");
109
110 hpte_init_native();
111
112 cell_init_iommu();
113
114 ppc64_interrupt_controller = IC_CELL_PIC;
115
116 DBG(" <- cell_init_early()\n");
117}
118
119
120static int __init cell_probe(int platform)
121{
122 if (platform != PLATFORM_CELL)
123 return 0;
124
125 return 1;
126}
127
128struct machdep_calls __initdata cell_md = {
129 .probe = cell_probe,
130 .setup_arch = cell_setup_arch,
131 .init_early = cell_init_early,
132 .show_cpuinfo = cell_show_cpuinfo,
133 .restart = rtas_restart,
134 .power_off = rtas_power_off,
135 .halt = rtas_halt,
136 .get_boot_time = rtas_get_boot_time,
137 .get_rtc_time = rtas_get_rtc_time,
138 .set_rtc_time = rtas_set_rtc_time,
139 .calibrate_decr = generic_calibrate_decr,
140 .progress = cell_progress,
141};
diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c
new file mode 100644
index 000000000000..de96eadf419d
--- /dev/null
+++ b/arch/powerpc/platforms/cell/smp.c
@@ -0,0 +1,230 @@
1/*
2 * SMP support for BPA machines.
3 *
4 * Dave Engebretsen, Peter Bergner, and
5 * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
6 *
7 * Plus various changes from other IBM teams...
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 */
14
15#undef DEBUG
16
17#include <linux/config.h>
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/sched.h>
21#include <linux/smp.h>
22#include <linux/interrupt.h>
23#include <linux/delay.h>
24#include <linux/init.h>
25#include <linux/spinlock.h>
26#include <linux/cache.h>
27#include <linux/err.h>
28#include <linux/sysdev.h>
29#include <linux/cpu.h>
30
31#include <asm/ptrace.h>
32#include <asm/atomic.h>
33#include <asm/irq.h>
34#include <asm/page.h>
35#include <asm/pgtable.h>
36#include <asm/io.h>
37#include <asm/prom.h>
38#include <asm/smp.h>
39#include <asm/paca.h>
40#include <asm/time.h>
41#include <asm/machdep.h>
42#include <asm/cputable.h>
43#include <asm/firmware.h>
44#include <asm/system.h>
45#include <asm/rtas.h>
46
47#include "interrupt.h"
48
49#ifdef DEBUG
50#define DBG(fmt...) udbg_printf(fmt)
51#else
52#define DBG(fmt...)
53#endif
54
55/*
56 * The primary thread of each non-boot processor is recorded here before
57 * smp init.
58 */
59static cpumask_t of_spin_map;
60
61extern void pSeries_secondary_smp_init(unsigned long);
62
63/**
64 * smp_startup_cpu() - start the given cpu
65 *
66 * At boot time, there is nothing to do for primary threads which were
67 * started from Open Firmware. For anything else, call RTAS with the
68 * appropriate start location.
69 *
70 * Returns:
71 * 0 - failure
72 * 1 - success
73 */
74static inline int __devinit smp_startup_cpu(unsigned int lcpu)
75{
76 int status;
77 unsigned long start_here = __pa((u32)*((unsigned long *)
78 pSeries_secondary_smp_init));
79 unsigned int pcpu;
80 int start_cpu;
81
82 if (cpu_isset(lcpu, of_spin_map))
83 /* Already started by OF and sitting in spin loop */
84 return 1;
85
86 pcpu = get_hard_smp_processor_id(lcpu);
87
88 /* Fixup atomic count: it exited inside IRQ handler. */
89 paca[lcpu].__current->thread_info->preempt_count = 0;
90
91 /*
92 * If the RTAS start-cpu token does not exist then presume the
93 * cpu is already spinning.
94 */
95 start_cpu = rtas_token("start-cpu");
96 if (start_cpu == RTAS_UNKNOWN_SERVICE)
97 return 1;
98
99 status = rtas_call(start_cpu, 3, 1, NULL, pcpu, start_here, lcpu);
100 if (status != 0) {
101 printk(KERN_ERR "start-cpu failed: %i\n", status);
102 return 0;
103 }
104
105 return 1;
106}
107
108static void smp_iic_message_pass(int target, int msg)
109{
110 unsigned int i;
111
112 if (target < NR_CPUS) {
113 iic_cause_IPI(target, msg);
114 } else {
115 for_each_online_cpu(i) {
116 if (target == MSG_ALL_BUT_SELF
117 && i == smp_processor_id())
118 continue;
119 iic_cause_IPI(i, msg);
120 }
121 }
122}
123
124static int __init smp_iic_probe(void)
125{
126 iic_request_IPIs();
127
128 return cpus_weight(cpu_possible_map);
129}
130
131static void __devinit smp_iic_setup_cpu(int cpu)
132{
133 if (cpu != boot_cpuid)
134 iic_setup_cpu();
135}
136
137static DEFINE_SPINLOCK(timebase_lock);
138static unsigned long timebase = 0;
139
140static void __devinit cell_give_timebase(void)
141{
142 spin_lock(&timebase_lock);
143 rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
144 timebase = get_tb();
145 spin_unlock(&timebase_lock);
146
147 while (timebase)
148 barrier();
149 rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
150}
151
152static void __devinit cell_take_timebase(void)
153{
154 while (!timebase)
155 barrier();
156 spin_lock(&timebase_lock);
157 set_tb(timebase >> 32, timebase & 0xffffffff);
158 timebase = 0;
159 spin_unlock(&timebase_lock);
160}
161
162static void __devinit smp_cell_kick_cpu(int nr)
163{
164 BUG_ON(nr < 0 || nr >= NR_CPUS);
165
166 if (!smp_startup_cpu(nr))
167 return;
168
169 /*
170 * The processor is currently spinning, waiting for the
171 * cpu_start field to become non-zero After we set cpu_start,
172 * the processor will continue on to secondary_start
173 */
174 paca[nr].cpu_start = 1;
175}
176
177static int smp_cell_cpu_bootable(unsigned int nr)
178{
179 /* Special case - we inhibit secondary thread startup
180 * during boot if the user requests it. Odd-numbered
181 * cpus are assumed to be secondary threads.
182 */
183 if (system_state < SYSTEM_RUNNING &&
184 cpu_has_feature(CPU_FTR_SMT) &&
185 !smt_enabled_at_boot && nr % 2 != 0)
186 return 0;
187
188 return 1;
189}
190static struct smp_ops_t bpa_iic_smp_ops = {
191 .message_pass = smp_iic_message_pass,
192 .probe = smp_iic_probe,
193 .kick_cpu = smp_cell_kick_cpu,
194 .setup_cpu = smp_iic_setup_cpu,
195 .cpu_bootable = smp_cell_cpu_bootable,
196};
197
198/* This is called very early */
199void __init smp_init_cell(void)
200{
201 int i;
202
203 DBG(" -> smp_init_cell()\n");
204
205 smp_ops = &bpa_iic_smp_ops;
206
207 /* Mark threads which are still spinning in hold loops. */
208 if (cpu_has_feature(CPU_FTR_SMT)) {
209 for_each_present_cpu(i) {
210 if (i % 2 == 0)
211 /*
212 * Even-numbered logical cpus correspond to
213 * primary threads.
214 */
215 cpu_set(i, of_spin_map);
216 }
217 } else {
218 of_spin_map = cpu_present_map;
219 }
220
221 cpu_clear(boot_cpuid, of_spin_map);
222
223 /* Non-lpar has additional take/give timebase */
224 if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
225 smp_ops->give_timebase = cell_give_timebase;
226 smp_ops->take_timebase = cell_take_timebase;
227 }
228
229 DBG(" <- smp_init_cell()\n");
230}
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
new file mode 100644
index 000000000000..e74132188bdf
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -0,0 +1,191 @@
1/*
2 * External Interrupt Controller on Spider South Bridge
3 *
4 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
5 *
6 * Author: Arnd Bergmann <arndb@de.ibm.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <linux/interrupt.h>
24#include <linux/irq.h>
25
26#include <asm/pgtable.h>
27#include <asm/prom.h>
28#include <asm/io.h>
29
30#include "interrupt.h"
31
32/* register layout taken from Spider spec, table 7.4-4 */
33enum {
34 TIR_DEN = 0x004, /* Detection Enable Register */
35 TIR_MSK = 0x084, /* Mask Level Register */
36 TIR_EDC = 0x0c0, /* Edge Detection Clear Register */
37 TIR_PNDA = 0x100, /* Pending Register A */
38 TIR_PNDB = 0x104, /* Pending Register B */
39 TIR_CS = 0x144, /* Current Status Register */
40 TIR_LCSA = 0x150, /* Level Current Status Register A */
41 TIR_LCSB = 0x154, /* Level Current Status Register B */
42 TIR_LCSC = 0x158, /* Level Current Status Register C */
43 TIR_LCSD = 0x15c, /* Level Current Status Register D */
44 TIR_CFGA = 0x200, /* Setting Register A0 */
45 TIR_CFGB = 0x204, /* Setting Register B0 */
46 /* 0x208 ... 0x3ff Setting Register An/Bn */
47 TIR_PPNDA = 0x400, /* Packet Pending Register A */
48 TIR_PPNDB = 0x404, /* Packet Pending Register B */
49 TIR_PIERA = 0x408, /* Packet Output Error Register A */
50 TIR_PIERB = 0x40c, /* Packet Output Error Register B */
51 TIR_PIEN = 0x444, /* Packet Output Enable Register */
52 TIR_PIPND = 0x454, /* Packet Output Pending Register */
53 TIRDID = 0x484, /* Spider Device ID Register */
54 REISTIM = 0x500, /* Reissue Command Timeout Time Setting */
55 REISTIMEN = 0x504, /* Reissue Command Timeout Setting */
56 REISWAITEN = 0x508, /* Reissue Wait Control*/
57};
58
59static void __iomem *spider_pics[4];
60
61static void __iomem *spider_get_pic(int irq)
62{
63 int node = irq / IIC_NODE_STRIDE;
64 irq %= IIC_NODE_STRIDE;
65
66 if (irq >= IIC_EXT_OFFSET &&
67 irq < IIC_EXT_OFFSET + IIC_NUM_EXT &&
68 spider_pics)
69 return spider_pics[node];
70 return NULL;
71}
72
73static int spider_get_nr(unsigned int irq)
74{
75 return (irq % IIC_NODE_STRIDE) - IIC_EXT_OFFSET;
76}
77
78static void __iomem *spider_get_irq_config(int irq)
79{
80 void __iomem *pic;
81 pic = spider_get_pic(irq);
82 return pic + TIR_CFGA + 8 * spider_get_nr(irq);
83}
84
85static void spider_enable_irq(unsigned int irq)
86{
87 void __iomem *cfg = spider_get_irq_config(irq);
88 irq = spider_get_nr(irq);
89
90 out_be32(cfg, in_be32(cfg) | 0x3107000eu);
91 out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq);
92}
93
94static void spider_disable_irq(unsigned int irq)
95{
96 void __iomem *cfg = spider_get_irq_config(irq);
97 irq = spider_get_nr(irq);
98
99 out_be32(cfg, in_be32(cfg) & ~0x30000000u);
100}
101
102static unsigned int spider_startup_irq(unsigned int irq)
103{
104 spider_enable_irq(irq);
105 return 0;
106}
107
108static void spider_shutdown_irq(unsigned int irq)
109{
110 spider_disable_irq(irq);
111}
112
113static void spider_end_irq(unsigned int irq)
114{
115 spider_enable_irq(irq);
116}
117
118static void spider_ack_irq(unsigned int irq)
119{
120 spider_disable_irq(irq);
121 iic_local_enable();
122}
123
124static struct hw_interrupt_type spider_pic = {
125 .typename = " SPIDER ",
126 .startup = spider_startup_irq,
127 .shutdown = spider_shutdown_irq,
128 .enable = spider_enable_irq,
129 .disable = spider_disable_irq,
130 .ack = spider_ack_irq,
131 .end = spider_end_irq,
132};
133
134
135int spider_get_irq(unsigned long int_pending)
136{
137 void __iomem *regs = spider_get_pic(int_pending);
138 unsigned long cs;
139 int irq;
140
141 cs = in_be32(regs + TIR_CS);
142
143 irq = cs >> 24;
144 if (irq != 63)
145 return irq;
146
147 return -1;
148}
149
150void spider_init_IRQ(void)
151{
152 int node;
153 struct device_node *dn;
154 unsigned int *property;
155 long spiderpic;
156 int n;
157
158/* FIXME: detect multiple PICs as soon as the device tree has them */
159 for (node = 0; node < 1; node++) {
160 dn = of_find_node_by_path("/");
161 n = prom_n_addr_cells(dn);
162 property = (unsigned int *) get_property(dn,
163 "platform-spider-pic", NULL);
164
165 if (!property)
166 continue;
167 for (spiderpic = 0; n > 0; --n)
168 spiderpic = (spiderpic << 32) + *property++;
169 printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic);
170 spider_pics[node] = __ioremap(spiderpic, 0x800, _PAGE_NO_CACHE);
171 for (n = 0; n < IIC_NUM_EXT; n++) {
172 int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE;
173 get_irq_desc(irq)->handler = &spider_pic;
174
175 /* do not mask any interrupts because of level */
176 out_be32(spider_pics[node] + TIR_MSK, 0x0);
177
178 /* disable edge detection clear */
179 /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */
180
181 /* enable interrupt packets to be output */
182 out_be32(spider_pics[node] + TIR_PIEN,
183 in_be32(spider_pics[node] + TIR_PIEN) | 0x1);
184
185 /* Enable the interrupt detection enable bit. Do this last! */
186 out_be32(spider_pics[node] + TIR_DEN,
187 in_be32(spider_pics[node] +TIR_DEN) | 0x1);
188
189 }
190 }
191}
diff --git a/arch/powerpc/platforms/chrp/nvram.c b/arch/powerpc/platforms/chrp/nvram.c
index 4ac7125aa09c..150f67d6f90c 100644
--- a/arch/powerpc/platforms/chrp/nvram.c
+++ b/arch/powerpc/platforms/chrp/nvram.c
@@ -17,6 +17,7 @@
17#include <asm/uaccess.h> 17#include <asm/uaccess.h>
18#include <asm/prom.h> 18#include <asm/prom.h>
19#include <asm/machdep.h> 19#include <asm/machdep.h>
20#include <asm/rtas.h>
20#include "chrp.h" 21#include "chrp.h"
21 22
22static unsigned int nvram_size; 23static unsigned int nvram_size;
@@ -25,7 +26,8 @@ static DEFINE_SPINLOCK(nvram_lock);
25 26
26static unsigned char chrp_nvram_read(int addr) 27static unsigned char chrp_nvram_read(int addr)
27{ 28{
28 unsigned long done, flags; 29 unsigned int done;
30 unsigned long flags;
29 unsigned char ret; 31 unsigned char ret;
30 32
31 if (addr >= nvram_size) { 33 if (addr >= nvram_size) {
@@ -34,7 +36,8 @@ static unsigned char chrp_nvram_read(int addr)
34 return 0xff; 36 return 0xff;
35 } 37 }
36 spin_lock_irqsave(&nvram_lock, flags); 38 spin_lock_irqsave(&nvram_lock, flags);
37 if ((call_rtas("nvram-fetch", 3, 2, &done, addr, __pa(nvram_buf), 1) != 0) || 1 != done) 39 if ((rtas_call(rtas_token("nvram-fetch"), 3, 2, &done, addr,
40 __pa(nvram_buf), 1) != 0) || 1 != done)
38 ret = 0xff; 41 ret = 0xff;
39 else 42 else
40 ret = nvram_buf[0]; 43 ret = nvram_buf[0];
@@ -45,7 +48,8 @@ static unsigned char chrp_nvram_read(int addr)
45 48
46static void chrp_nvram_write(int addr, unsigned char val) 49static void chrp_nvram_write(int addr, unsigned char val)
47{ 50{
48 unsigned long done, flags; 51 unsigned int done;
52 unsigned long flags;
49 53
50 if (addr >= nvram_size) { 54 if (addr >= nvram_size) {
51 printk(KERN_DEBUG "%s: write addr %d > nvram_size %u\n", 55 printk(KERN_DEBUG "%s: write addr %d > nvram_size %u\n",
@@ -54,7 +58,8 @@ static void chrp_nvram_write(int addr, unsigned char val)
54 } 58 }
55 spin_lock_irqsave(&nvram_lock, flags); 59 spin_lock_irqsave(&nvram_lock, flags);
56 nvram_buf[0] = val; 60 nvram_buf[0] = val;
57 if ((call_rtas("nvram-store", 3, 2, &done, addr, __pa(nvram_buf), 1) != 0) || 1 != done) 61 if ((rtas_call(rtas_token("nvram-store"), 3, 2, &done, addr,
62 __pa(nvram_buf), 1) != 0) || 1 != done)
58 printk(KERN_DEBUG "rtas IO error storing 0x%02x at %d", val, addr); 63 printk(KERN_DEBUG "rtas IO error storing 0x%02x at %d", val, addr);
59 spin_unlock_irqrestore(&nvram_lock, flags); 64 spin_unlock_irqrestore(&nvram_lock, flags);
60} 65}
diff --git a/arch/powerpc/platforms/chrp/pegasos_eth.c b/arch/powerpc/platforms/chrp/pegasos_eth.c
index a9052305c35d..29c86781c493 100644
--- a/arch/powerpc/platforms/chrp/pegasos_eth.c
+++ b/arch/powerpc/platforms/chrp/pegasos_eth.c
@@ -14,6 +14,7 @@
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/ioport.h> 15#include <linux/ioport.h>
16#include <linux/device.h> 16#include <linux/device.h>
17#include <linux/platform_device.h>
17#include <linux/mv643xx.h> 18#include <linux/mv643xx.h>
18#include <linux/pci.h> 19#include <linux/pci.h>
19 20
diff --git a/arch/powerpc/platforms/chrp/smp.c b/arch/powerpc/platforms/chrp/smp.c
index 31ee49c25014..bb2315997d45 100644
--- a/arch/powerpc/platforms/chrp/smp.c
+++ b/arch/powerpc/platforms/chrp/smp.c
@@ -35,43 +35,6 @@
35#include <asm/smp.h> 35#include <asm/smp.h>
36#include <asm/mpic.h> 36#include <asm/mpic.h>
37 37
38extern unsigned long smp_chrp_cpu_nr;
39
40static int __init smp_chrp_probe(void)
41{
42 struct device_node *cpus = NULL;
43 unsigned int *reg;
44 int reglen;
45 int ncpus = 0;
46 int cpuid;
47 unsigned int phys;
48
49 /* Count CPUs in the device-tree */
50 cpuid = 1; /* the boot cpu is logical cpu 0 */
51 while ((cpus = of_find_node_by_type(cpus, "cpu")) != NULL) {
52 phys = ncpus;
53 reg = (unsigned int *) get_property(cpus, "reg", &reglen);
54 if (reg && reglen >= sizeof(unsigned int))
55 /* hmmm, not having a reg property would be bad */
56 phys = *reg;
57 if (phys != boot_cpuid_phys) {
58 set_hard_smp_processor_id(cpuid, phys);
59 ++cpuid;
60 }
61 ++ncpus;
62 }
63
64 printk(KERN_INFO "CHRP SMP probe found %d cpus\n", ncpus);
65
66 /* Nothing more to do if less than 2 of them */
67 if (ncpus <= 1)
68 return 1;
69
70 mpic_request_ipis();
71
72 return ncpus;
73}
74
75static void __devinit smp_chrp_kick_cpu(int nr) 38static void __devinit smp_chrp_kick_cpu(int nr)
76{ 39{
77 *(unsigned long *)KERNELBASE = nr; 40 *(unsigned long *)KERNELBASE = nr;
@@ -114,7 +77,7 @@ void __devinit smp_chrp_take_timebase(void)
114/* CHRP with openpic */ 77/* CHRP with openpic */
115struct smp_ops_t chrp_smp_ops = { 78struct smp_ops_t chrp_smp_ops = {
116 .message_pass = smp_mpic_message_pass, 79 .message_pass = smp_mpic_message_pass,
117 .probe = smp_chrp_probe, 80 .probe = smp_mpic_probe,
118 .kick_cpu = smp_chrp_kick_cpu, 81 .kick_cpu = smp_chrp_kick_cpu,
119 .setup_cpu = smp_chrp_setup_cpu, 82 .setup_cpu = smp_chrp_setup_cpu,
120 .give_timebase = smp_chrp_give_timebase, 83 .give_timebase = smp_chrp_give_timebase,
diff --git a/arch/powerpc/platforms/iseries/call_hpt.h b/arch/powerpc/platforms/iseries/call_hpt.h
index 321f3bb7a8f5..a843b0f87b72 100644
--- a/arch/powerpc/platforms/iseries/call_hpt.h
+++ b/arch/powerpc/platforms/iseries/call_hpt.h
@@ -23,8 +23,8 @@
23 * drive the hypervisor from the OS. 23 * drive the hypervisor from the OS.
24 */ 24 */
25 25
26#include <asm/iSeries/HvCallSc.h> 26#include <asm/iseries/hv_call_sc.h>
27#include <asm/iSeries/HvTypes.h> 27#include <asm/iseries/hv_types.h>
28#include <asm/mmu.h> 28#include <asm/mmu.h>
29 29
30#define HvCallHptGetHptAddress HvCallHpt + 0 30#define HvCallHptGetHptAddress HvCallHpt + 0
diff --git a/arch/powerpc/platforms/iseries/call_pci.h b/arch/powerpc/platforms/iseries/call_pci.h
index a86e065b9577..59d4e0ad5cf3 100644
--- a/arch/powerpc/platforms/iseries/call_pci.h
+++ b/arch/powerpc/platforms/iseries/call_pci.h
@@ -25,8 +25,8 @@
25#ifndef _PLATFORMS_ISERIES_CALL_PCI_H 25#ifndef _PLATFORMS_ISERIES_CALL_PCI_H
26#define _PLATFORMS_ISERIES_CALL_PCI_H 26#define _PLATFORMS_ISERIES_CALL_PCI_H
27 27
28#include <asm/iSeries/HvCallSc.h> 28#include <asm/iseries/hv_call_sc.h>
29#include <asm/iSeries/HvTypes.h> 29#include <asm/iseries/hv_types.h>
30 30
31/* 31/*
32 * DSA == Direct Select Address 32 * DSA == Direct Select Address
diff --git a/arch/powerpc/platforms/iseries/call_sm.h b/arch/powerpc/platforms/iseries/call_sm.h
index ef223166cf22..c7e251619f48 100644
--- a/arch/powerpc/platforms/iseries/call_sm.h
+++ b/arch/powerpc/platforms/iseries/call_sm.h
@@ -23,8 +23,8 @@
23 * drive the hypervisor from the OS. 23 * drive the hypervisor from the OS.
24 */ 24 */
25 25
26#include <asm/iSeries/HvCallSc.h> 26#include <asm/iseries/hv_call_sc.h>
27#include <asm/iSeries/HvTypes.h> 27#include <asm/iseries/hv_types.h>
28 28
29#define HvCallSmGet64BitsOfAccessMap HvCallSm + 11 29#define HvCallSmGet64BitsOfAccessMap HvCallSm + 11
30 30
diff --git a/arch/powerpc/platforms/iseries/hvlog.c b/arch/powerpc/platforms/iseries/hvlog.c
index f61e2e9ac9ec..62ec73479687 100644
--- a/arch/powerpc/platforms/iseries/hvlog.c
+++ b/arch/powerpc/platforms/iseries/hvlog.c
@@ -9,9 +9,9 @@
9 9
10#include <asm/page.h> 10#include <asm/page.h>
11#include <asm/abs_addr.h> 11#include <asm/abs_addr.h>
12#include <asm/iSeries/HvCall.h> 12#include <asm/iseries/hv_call.h>
13#include <asm/iSeries/HvCallSc.h> 13#include <asm/iseries/hv_call_sc.h>
14#include <asm/iSeries/HvTypes.h> 14#include <asm/iseries/hv_types.h>
15 15
16 16
17void HvCall_writeLogBuffer(const void *buffer, u64 len) 17void HvCall_writeLogBuffer(const void *buffer, u64 len)
diff --git a/arch/powerpc/platforms/iseries/hvlpconfig.c b/arch/powerpc/platforms/iseries/hvlpconfig.c
index dc28621aea0d..663a1affb4bb 100644
--- a/arch/powerpc/platforms/iseries/hvlpconfig.c
+++ b/arch/powerpc/platforms/iseries/hvlpconfig.c
@@ -17,7 +17,7 @@
17 */ 17 */
18 18
19#include <linux/module.h> 19#include <linux/module.h>
20#include <asm/iSeries/HvLpConfig.h> 20#include <asm/iseries/hv_lp_config.h>
21 21
22HvLpIndex HvLpConfig_getLpIndex_outline(void) 22HvLpIndex HvLpConfig_getLpIndex_outline(void)
23{ 23{
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index 1db26d8be640..1a6845b5c5a4 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -32,7 +32,7 @@
32#include <asm/machdep.h> 32#include <asm/machdep.h>
33#include <asm/abs_addr.h> 33#include <asm/abs_addr.h>
34#include <asm/pci-bridge.h> 34#include <asm/pci-bridge.h>
35#include <asm/iSeries/HvCallXm.h> 35#include <asm/iseries/hv_call_xm.h>
36 36
37extern struct list_head iSeries_Global_Device_List; 37extern struct list_head iSeries_Global_Device_List;
38 38
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index 937ac99b9d33..c1135912cc05 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -36,9 +36,9 @@
36#include <linux/spinlock.h> 36#include <linux/spinlock.h>
37 37
38#include <asm/ppcdebug.h> 38#include <asm/ppcdebug.h>
39#include <asm/iSeries/HvTypes.h> 39#include <asm/iseries/hv_types.h>
40#include <asm/iSeries/HvLpEvent.h> 40#include <asm/iseries/hv_lp_event.h>
41#include <asm/iSeries/HvCallXm.h> 41#include <asm/iseries/hv_call_xm.h>
42 42
43#include "irq.h" 43#include "irq.h"
44#include "call_pci.h" 44#include "call_pci.h"
diff --git a/arch/powerpc/platforms/iseries/ksyms.c b/arch/powerpc/platforms/iseries/ksyms.c
index f271b3539721..a2200842f4e5 100644
--- a/arch/powerpc/platforms/iseries/ksyms.c
+++ b/arch/powerpc/platforms/iseries/ksyms.c
@@ -9,7 +9,7 @@
9#include <linux/module.h> 9#include <linux/module.h>
10 10
11#include <asm/hw_irq.h> 11#include <asm/hw_irq.h>
12#include <asm/iSeries/HvCallSc.h> 12#include <asm/iseries/hv_call_sc.h>
13 13
14EXPORT_SYMBOL(HvCall0); 14EXPORT_SYMBOL(HvCall0);
15EXPORT_SYMBOL(HvCall1); 15EXPORT_SYMBOL(HvCall1);
diff --git a/arch/powerpc/platforms/iseries/lpardata.c b/arch/powerpc/platforms/iseries/lpardata.c
index ed2ffee6f731..bb8c91537f35 100644
--- a/arch/powerpc/platforms/iseries/lpardata.c
+++ b/arch/powerpc/platforms/iseries/lpardata.c
@@ -13,16 +13,16 @@
13#include <linux/bitops.h> 13#include <linux/bitops.h>
14#include <asm/processor.h> 14#include <asm/processor.h>
15#include <asm/ptrace.h> 15#include <asm/ptrace.h>
16#include <asm/naca.h>
17#include <asm/abs_addr.h> 16#include <asm/abs_addr.h>
18#include <asm/iSeries/ItLpNaca.h> 17#include <asm/iseries/it_lp_naca.h>
19#include <asm/lppaca.h> 18#include <asm/lppaca.h>
20#include <asm/iSeries/ItLpRegSave.h> 19#include <asm/iseries/it_lp_reg_save.h>
21#include <asm/paca.h> 20#include <asm/paca.h>
22#include <asm/iSeries/LparMap.h> 21#include <asm/iseries/lpar_map.h>
23#include <asm/iSeries/ItExtVpdPanel.h> 22#include <asm/iseries/it_exp_vpd_panel.h>
24#include <asm/iSeries/ItLpQueue.h> 23#include <asm/iseries/it_lp_queue.h>
25 24
25#include "naca.h"
26#include "vpd_areas.h" 26#include "vpd_areas.h"
27#include "spcomm_area.h" 27#include "spcomm_area.h"
28#include "ipl_parms.h" 28#include "ipl_parms.h"
diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c
index 54c7753dbe05..e9fb98bf895f 100644
--- a/arch/powerpc/platforms/iseries/lpevents.c
+++ b/arch/powerpc/platforms/iseries/lpevents.c
@@ -17,10 +17,10 @@
17 17
18#include <asm/system.h> 18#include <asm/system.h>
19#include <asm/paca.h> 19#include <asm/paca.h>
20#include <asm/iSeries/ItLpQueue.h> 20#include <asm/iseries/it_lp_queue.h>
21#include <asm/iSeries/HvLpEvent.h> 21#include <asm/iseries/hv_lp_event.h>
22#include <asm/iSeries/HvCallEvent.h> 22#include <asm/iseries/hv_call_event.h>
23#include <asm/iSeries/ItLpNaca.h> 23#include <asm/iseries/it_lp_naca.h>
24 24
25/* 25/*
26 * The LpQueue is used to pass event data from the hypervisor to 26 * The LpQueue is used to pass event data from the hypervisor to
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
index e5de31aa0015..49e7e4b85847 100644
--- a/arch/powerpc/platforms/iseries/mf.c
+++ b/arch/powerpc/platforms/iseries/mf.c
@@ -38,10 +38,10 @@
38#include <asm/uaccess.h> 38#include <asm/uaccess.h>
39#include <asm/paca.h> 39#include <asm/paca.h>
40#include <asm/abs_addr.h> 40#include <asm/abs_addr.h>
41#include <asm/iSeries/vio.h> 41#include <asm/iseries/vio.h>
42#include <asm/iSeries/mf.h> 42#include <asm/iseries/mf.h>
43#include <asm/iSeries/HvLpConfig.h> 43#include <asm/iseries/hv_lp_config.h>
44#include <asm/iSeries/ItLpQueue.h> 44#include <asm/iseries/it_lp_queue.h>
45 45
46#include "setup.h" 46#include "setup.h"
47 47
diff --git a/arch/powerpc/platforms/iseries/naca.h b/arch/powerpc/platforms/iseries/naca.h
new file mode 100644
index 000000000000..ab2372eb8d2e
--- /dev/null
+++ b/arch/powerpc/platforms/iseries/naca.h
@@ -0,0 +1,24 @@
1#ifndef _PLATFORMS_ISERIES_NACA_H
2#define _PLATFORMS_ISERIES_NACA_H
3
4/*
5 * c 2001 PPC 64 Team, IBM Corp
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 */
12
13#include <asm/types.h>
14
15struct naca_struct {
16 /* Kernel only data - undefined for user space */
17 void *xItVpdAreas; /* VPD Data 0x00 */
18 void *xRamDisk; /* iSeries ramdisk 0x08 */
19 u64 xRamDiskSize; /* In pages 0x10 */
20};
21
22extern struct naca_struct naca;
23
24#endif /* _PLATFORMS_ISERIES_NACA_H */
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index 959e59fd9c11..7d7d5884343f 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -36,8 +36,8 @@
36#include <asm/iommu.h> 36#include <asm/iommu.h>
37#include <asm/abs_addr.h> 37#include <asm/abs_addr.h>
38 38
39#include <asm/iSeries/HvCallXm.h> 39#include <asm/iseries/hv_call_xm.h>
40#include <asm/iSeries/mf.h> 40#include <asm/iseries/mf.h>
41 41
42#include <asm/ppc-pci.h> 42#include <asm/ppc-pci.h>
43 43
diff --git a/arch/powerpc/platforms/iseries/proc.c b/arch/powerpc/platforms/iseries/proc.c
index 6f1929cac66b..e68b6b5fa89f 100644
--- a/arch/powerpc/platforms/iseries/proc.c
+++ b/arch/powerpc/platforms/iseries/proc.c
@@ -24,8 +24,8 @@
24#include <asm/processor.h> 24#include <asm/processor.h>
25#include <asm/time.h> 25#include <asm/time.h>
26#include <asm/lppaca.h> 26#include <asm/lppaca.h>
27#include <asm/iSeries/ItLpQueue.h> 27#include <asm/iseries/it_lp_queue.h>
28#include <asm/iSeries/HvCallXm.h> 28#include <asm/iseries/hv_call_xm.h>
29 29
30#include "processor_vpd.h" 30#include "processor_vpd.h"
31#include "main_store.h" 31#include "main_store.h"
diff --git a/arch/powerpc/platforms/iseries/release_data.h b/arch/powerpc/platforms/iseries/release_data.h
index c68b9c3e5caf..66189fd2e32d 100644
--- a/arch/powerpc/platforms/iseries/release_data.h
+++ b/arch/powerpc/platforms/iseries/release_data.h
@@ -24,7 +24,7 @@
24 * address of the OS's NACA). 24 * address of the OS's NACA).
25 */ 25 */
26#include <asm/types.h> 26#include <asm/types.h>
27#include <asm/naca.h> 27#include "naca.h"
28 28
29/* 29/*
30 * When we IPL a secondary partition, we will check if if the 30 * When we IPL a secondary partition, we will check if if the
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 1544c6f10a38..fda712b42168 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -27,6 +27,7 @@
27#include <linux/kdev_t.h> 27#include <linux/kdev_t.h>
28#include <linux/major.h> 28#include <linux/major.h>
29#include <linux/root_dev.h> 29#include <linux/root_dev.h>
30#include <linux/kernel.h>
30 31
31#include <asm/processor.h> 32#include <asm/processor.h>
32#include <asm/machdep.h> 33#include <asm/machdep.h>
@@ -40,19 +41,19 @@
40#include <asm/firmware.h> 41#include <asm/firmware.h>
41 42
42#include <asm/time.h> 43#include <asm/time.h>
43#include <asm/naca.h>
44#include <asm/paca.h> 44#include <asm/paca.h>
45#include <asm/cache.h> 45#include <asm/cache.h>
46#include <asm/sections.h> 46#include <asm/sections.h>
47#include <asm/abs_addr.h> 47#include <asm/abs_addr.h>
48#include <asm/iSeries/HvLpConfig.h> 48#include <asm/iseries/hv_lp_config.h>
49#include <asm/iSeries/HvCallEvent.h> 49#include <asm/iseries/hv_call_event.h>
50#include <asm/iSeries/HvCallXm.h> 50#include <asm/iseries/hv_call_xm.h>
51#include <asm/iSeries/ItLpQueue.h> 51#include <asm/iseries/it_lp_queue.h>
52#include <asm/iSeries/mf.h> 52#include <asm/iseries/mf.h>
53#include <asm/iSeries/HvLpEvent.h> 53#include <asm/iseries/hv_lp_event.h>
54#include <asm/iSeries/LparMap.h> 54#include <asm/iseries/lpar_map.h>
55 55
56#include "naca.h"
56#include "setup.h" 57#include "setup.h"
57#include "irq.h" 58#include "irq.h"
58#include "vpd_areas.h" 59#include "vpd_areas.h"
@@ -94,6 +95,8 @@ extern unsigned long iSeries_recal_titan;
94 95
95static int mf_initialized; 96static int mf_initialized;
96 97
98static unsigned long cmd_mem_limit;
99
97struct MemoryBlock { 100struct MemoryBlock {
98 unsigned long absStart; 101 unsigned long absStart;
99 unsigned long absEnd; 102 unsigned long absEnd;
@@ -341,23 +344,6 @@ static void __init iSeries_init_early(void)
341 */ 344 */
342 iommu_init_early_iSeries(); 345 iommu_init_early_iSeries();
343 346
344 iSeries_get_cmdline();
345
346 /* Save unparsed command line copy for /proc/cmdline */
347 strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
348
349 /* Parse early parameters, in particular mem=x */
350 parse_early_param();
351
352 if (memory_limit) {
353 if (memory_limit < systemcfg->physicalMemorySize)
354 systemcfg->physicalMemorySize = memory_limit;
355 else {
356 printk("Ignoring mem=%lu >= ram_top.\n", memory_limit);
357 memory_limit = 0;
358 }
359 }
360
361 /* Initialize machine-dependency vectors */ 347 /* Initialize machine-dependency vectors */
362#ifdef CONFIG_SMP 348#ifdef CONFIG_SMP
363 smp_init_iSeries(); 349 smp_init_iSeries();
@@ -971,6 +957,8 @@ void build_flat_dt(struct iseries_flat_dt *dt)
971 /* /chosen */ 957 /* /chosen */
972 dt_start_node(dt, "chosen"); 958 dt_start_node(dt, "chosen");
973 dt_prop_u32(dt, "linux,platform", PLATFORM_ISERIES_LPAR); 959 dt_prop_u32(dt, "linux,platform", PLATFORM_ISERIES_LPAR);
960 if (cmd_mem_limit)
961 dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit);
974 dt_end_node(dt); 962 dt_end_node(dt);
975 963
976 dt_cpus(dt); 964 dt_cpus(dt);
@@ -990,7 +978,27 @@ void * __init iSeries_early_setup(void)
990 */ 978 */
991 build_iSeries_Memory_Map(); 979 build_iSeries_Memory_Map();
992 980
981 iSeries_get_cmdline();
982
983 /* Save unparsed command line copy for /proc/cmdline */
984 strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
985
986 /* Parse early parameters, in particular mem=x */
987 parse_early_param();
988
993 build_flat_dt(&iseries_dt); 989 build_flat_dt(&iseries_dt);
994 990
995 return (void *) __pa(&iseries_dt); 991 return (void *) __pa(&iseries_dt);
996} 992}
993
994/*
995 * On iSeries we just parse the mem=X option from the command line.
996 * On pSeries it's a bit more complicated, see prom_init_mem()
997 */
998static int __init early_parsemem(char *p)
999{
1000 if (p)
1001 cmd_mem_limit = ALIGN(memparse(p, &p), PAGE_SIZE);
1002 return 0;
1003}
1004early_param("mem", early_parsemem);
diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c
index f720916682f6..3336bad67724 100644
--- a/arch/powerpc/platforms/iseries/smp.c
+++ b/arch/powerpc/platforms/iseries/smp.c
@@ -38,7 +38,7 @@
38#include <asm/io.h> 38#include <asm/io.h>
39#include <asm/smp.h> 39#include <asm/smp.h>
40#include <asm/paca.h> 40#include <asm/paca.h>
41#include <asm/iSeries/HvCall.h> 41#include <asm/iseries/hv_call.h>
42#include <asm/time.h> 42#include <asm/time.h>
43#include <asm/ppcdebug.h> 43#include <asm/ppcdebug.h>
44#include <asm/machdep.h> 44#include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
index c0f7d2e9153f..c27a66876c2c 100644
--- a/arch/powerpc/platforms/iseries/vio.c
+++ b/arch/powerpc/platforms/iseries/vio.c
@@ -17,10 +17,10 @@
17#include <asm/tce.h> 17#include <asm/tce.h>
18#include <asm/abs_addr.h> 18#include <asm/abs_addr.h>
19#include <asm/page.h> 19#include <asm/page.h>
20#include <asm/iSeries/vio.h> 20#include <asm/iseries/vio.h>
21#include <asm/iSeries/HvTypes.h> 21#include <asm/iseries/hv_types.h>
22#include <asm/iSeries/HvLpConfig.h> 22#include <asm/iseries/hv_lp_config.h>
23#include <asm/iSeries/HvCallXm.h> 23#include <asm/iseries/hv_call_xm.h>
24 24
25struct device *iSeries_vio_dev = &vio_bus_device.dev; 25struct device *iSeries_vio_dev = &vio_bus_device.dev;
26EXPORT_SYMBOL(iSeries_vio_dev); 26EXPORT_SYMBOL(iSeries_vio_dev);
diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c
index c0c767bd37f1..fe97bfbf7463 100644
--- a/arch/powerpc/platforms/iseries/viopath.c
+++ b/arch/powerpc/platforms/iseries/viopath.c
@@ -41,12 +41,12 @@
41 41
42#include <asm/system.h> 42#include <asm/system.h>
43#include <asm/uaccess.h> 43#include <asm/uaccess.h>
44#include <asm/iSeries/HvTypes.h> 44#include <asm/iseries/hv_types.h>
45#include <asm/iSeries/ItExtVpdPanel.h> 45#include <asm/iseries/it_exp_vpd_panel.h>
46#include <asm/iSeries/HvLpEvent.h> 46#include <asm/iseries/hv_lp_event.h>
47#include <asm/iSeries/HvLpConfig.h> 47#include <asm/iseries/hv_lp_config.h>
48#include <asm/iSeries/mf.h> 48#include <asm/iseries/mf.h>
49#include <asm/iSeries/vio.h> 49#include <asm/iseries/vio.h>
50 50
51/* Status of the path to each other partition in the system. 51/* Status of the path to each other partition in the system.
52 * This is overkill, since we will only ever establish connections 52 * This is overkill, since we will only ever establish connections
diff --git a/arch/powerpc/platforms/iseries/vpdinfo.c b/arch/powerpc/platforms/iseries/vpdinfo.c
index 9c318849dee7..23a6d1e5b429 100644
--- a/arch/powerpc/platforms/iseries/vpdinfo.c
+++ b/arch/powerpc/platforms/iseries/vpdinfo.c
@@ -32,7 +32,7 @@
32#include <asm/resource.h> 32#include <asm/resource.h>
33#include <asm/abs_addr.h> 33#include <asm/abs_addr.h>
34#include <asm/pci-bridge.h> 34#include <asm/pci-bridge.h>
35#include <asm/iSeries/HvTypes.h> 35#include <asm/iseries/hv_types.h>
36 36
37#include "pci.h" 37#include "pci.h"
38#include "call_pci.h" 38#include "call_pci.h"
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 0037a8c8c81f..83a49e80ac29 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -576,7 +576,7 @@ void __init pmac_pic_init(void)
576#endif /* CONFIG_PPC32 */ 576#endif /* CONFIG_PPC32 */
577} 577}
578 578
579#ifdef CONFIG_PM 579#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
580/* 580/*
581 * These procedures are used in implementing sleep on the powerbooks. 581 * These procedures are used in implementing sleep on the powerbooks.
582 * sleep_save_intrs() saves the states of all interrupt enables 582 * sleep_save_intrs() saves the states of all interrupt enables
@@ -643,7 +643,7 @@ static int pmacpic_resume(struct sys_device *sysdev)
643 return 0; 643 return 0;
644} 644}
645 645
646#endif /* CONFIG_PM */ 646#endif /* CONFIG_PM && CONFIG_PPC32 */
647 647
648static struct sysdev_class pmacpic_sysclass = { 648static struct sysdev_class pmacpic_sysclass = {
649 set_kset_name("pmac_pic"), 649 set_kset_name("pmac_pic"),
@@ -655,10 +655,10 @@ static struct sys_device device_pmacpic = {
655}; 655};
656 656
657static struct sysdev_driver driver_pmacpic = { 657static struct sysdev_driver driver_pmacpic = {
658#ifdef CONFIG_PM 658#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
659 .suspend = &pmacpic_suspend, 659 .suspend = &pmacpic_suspend,
660 .resume = &pmacpic_resume, 660 .resume = &pmacpic_resume,
661#endif /* CONFIG_PM */ 661#endif /* CONFIG_PM && CONFIG_PPC32 */
662}; 662};
663 663
664static int __init init_pmacpic_sysfs(void) 664static int __init init_pmacpic_sysfs(void)
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 6f62af597291..80b58c1ec412 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -75,6 +75,7 @@
75#include <asm/smu.h> 75#include <asm/smu.h>
76#include <asm/pmc.h> 76#include <asm/pmc.h>
77#include <asm/mpic.h> 77#include <asm/mpic.h>
78#include <asm/lmb.h>
78 79
79#include "pmac.h" 80#include "pmac.h"
80 81
@@ -350,7 +351,7 @@ void __init pmac_setup_arch(void)
350 find_via_pmu(); 351 find_via_pmu();
351 smu_init(); 352 smu_init();
352 353
353#ifdef CONFIG_NVRAM 354#if defined(CONFIG_NVRAM) || defined(CONFIG_PPC64)
354 pmac_nvram_init(); 355 pmac_nvram_init();
355#endif 356#endif
356 357
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index 2d57f588151d..e3fc3407bb1f 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -21,15 +21,6 @@ config EEH
21 depends on PPC_PSERIES 21 depends on PPC_PSERIES
22 default y if !EMBEDDED 22 default y if !EMBEDDED
23 23
24config RTAS_PROC
25 bool "Proc interface to RTAS"
26 depends on PPC_RTAS
27 default y
28
29config RTAS_FLASH
30 tristate "Firmware flash interface"
31 depends on PPC64 && RTAS_PROC
32
33config SCANLOG 24config SCANLOG
34 tristate "Scanlog dump interface" 25 tristate "Scanlog dump interface"
35 depends on RTAS_PROC && PPC_PSERIES 26 depends on RTAS_PROC && PPC_PSERIES
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 5ef494e3a70f..b9938fece781 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -1,5 +1,5 @@
1obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \ 1obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \
2 setup.o iommu.o rtas-fw.o ras.o 2 setup.o iommu.o ras.o rtasd.o
3obj-$(CONFIG_SMP) += smp.o 3obj-$(CONFIG_SMP) += smp.o
4obj-$(CONFIG_IBMVIO) += vio.o 4obj-$(CONFIG_IBMVIO) += vio.o
5obj-$(CONFIG_XICS) += xics.o 5obj-$(CONFIG_XICS) += xics.o
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 9e90d41131d8..513e27231493 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -42,13 +42,14 @@
42#include <asm/pci-bridge.h> 42#include <asm/pci-bridge.h>
43#include <asm/machdep.h> 43#include <asm/machdep.h>
44#include <asm/abs_addr.h> 44#include <asm/abs_addr.h>
45#include <asm/plpar_wrappers.h>
46#include <asm/pSeries_reconfig.h> 45#include <asm/pSeries_reconfig.h>
47#include <asm/systemcfg.h> 46#include <asm/systemcfg.h>
48#include <asm/firmware.h> 47#include <asm/firmware.h>
49#include <asm/tce.h> 48#include <asm/tce.h>
50#include <asm/ppc-pci.h> 49#include <asm/ppc-pci.h>
51 50
51#include "plpar_wrappers.h"
52
52#define DBG(fmt...) 53#define DBG(fmt...)
53 54
54extern int is_python(struct device_node *); 55extern int is_python(struct device_node *);
@@ -498,7 +499,7 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti
498 499
499 switch (action) { 500 switch (action) {
500 case PSERIES_RECONFIG_REMOVE: 501 case PSERIES_RECONFIG_REMOVE:
501 if (pci->iommu_table && 502 if (pci && pci->iommu_table &&
502 get_property(np, "ibm,dma-window", NULL)) 503 get_property(np, "ibm,dma-window", NULL))
503 iommu_free_table(np); 504 iommu_free_table(np);
504 break; 505 break;
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 268d8362dde7..e384a5a91796 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -38,7 +38,8 @@
38#include <asm/prom.h> 38#include <asm/prom.h>
39#include <asm/abs_addr.h> 39#include <asm/abs_addr.h>
40#include <asm/cputable.h> 40#include <asm/cputable.h>
41#include <asm/plpar_wrappers.h> 41
42#include "plpar_wrappers.h"
42 43
43#ifdef DEBUG 44#ifdef DEBUG
44#define DBG(fmt...) udbg_printf(fmt) 45#define DBG(fmt...) udbg_printf(fmt)
@@ -260,22 +261,18 @@ out:
260void vpa_init(int cpu) 261void vpa_init(int cpu)
261{ 262{
262 int hwcpu = get_hard_smp_processor_id(cpu); 263 int hwcpu = get_hard_smp_processor_id(cpu);
263 unsigned long vpa = (unsigned long)&(paca[cpu].lppaca); 264 unsigned long vpa = __pa(&paca[cpu].lppaca);
264 long ret; 265 long ret;
265 unsigned long flags;
266
267 /* Register the Virtual Processor Area (VPA) */
268 flags = 1UL << (63 - 18);
269 266
270 if (cpu_has_feature(CPU_FTR_ALTIVEC)) 267 if (cpu_has_feature(CPU_FTR_ALTIVEC))
271 paca[cpu].lppaca.vmxregs_in_use = 1; 268 paca[cpu].lppaca.vmxregs_in_use = 1;
272 269
273 ret = register_vpa(flags, hwcpu, __pa(vpa)); 270 ret = register_vpa(hwcpu, vpa);
274 271
275 if (ret) 272 if (ret)
276 printk(KERN_ERR "WARNING: vpa_init: VPA registration for " 273 printk(KERN_ERR "WARNING: vpa_init: VPA registration for "
277 "cpu %d (hw %d) of area %lx returns %ld\n", 274 "cpu %d (hw %d) of area %lx returns %ld\n",
278 cpu, hwcpu, __pa(vpa), ret); 275 cpu, hwcpu, vpa, ret);
279} 276}
280 277
281long pSeries_lpar_hpte_insert(unsigned long hpte_group, 278long pSeries_lpar_hpte_insert(unsigned long hpte_group,
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h
new file mode 100644
index 000000000000..382f8c5b0e7c
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h
@@ -0,0 +1,120 @@
1#ifndef _PSERIES_PLPAR_WRAPPERS_H
2#define _PSERIES_PLPAR_WRAPPERS_H
3
4#include <asm/hvcall.h>
5
6static inline long poll_pending(void)
7{
8 unsigned long dummy;
9 return plpar_hcall(H_POLL_PENDING, 0, 0, 0, 0, &dummy, &dummy, &dummy);
10}
11
12static inline long prod_processor(void)
13{
14 plpar_hcall_norets(H_PROD);
15 return 0;
16}
17
18static inline long cede_processor(void)
19{
20 plpar_hcall_norets(H_CEDE);
21 return 0;
22}
23
24static inline long vpa_call(unsigned long flags, unsigned long cpu,
25 unsigned long vpa)
26{
27 /* flags are in bits 16-18 (counting from most significant bit) */
28 flags = flags << (63 - 18);
29
30 return plpar_hcall_norets(H_REGISTER_VPA, flags, cpu, vpa);
31}
32
33static inline long unregister_vpa(unsigned long cpu, unsigned long vpa)
34{
35 return vpa_call(0x5, cpu, vpa);
36}
37
38static inline long register_vpa(unsigned long cpu, unsigned long vpa)
39{
40 return vpa_call(0x1, cpu, vpa);
41}
42
43extern void vpa_init(int cpu);
44
45static inline long plpar_pte_remove(unsigned long flags, unsigned long ptex,
46 unsigned long avpn, unsigned long *old_pteh_ret,
47 unsigned long *old_ptel_ret)
48{
49 unsigned long dummy;
50 return plpar_hcall(H_REMOVE, flags, ptex, avpn, 0, old_pteh_ret,
51 old_ptel_ret, &dummy);
52}
53
54static inline long plpar_pte_read(unsigned long flags, unsigned long ptex,
55 unsigned long *old_pteh_ret, unsigned long *old_ptel_ret)
56{
57 unsigned long dummy;
58 return plpar_hcall(H_READ, flags, ptex, 0, 0, old_pteh_ret,
59 old_ptel_ret, &dummy);
60}
61
62static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex,
63 unsigned long avpn)
64{
65 return plpar_hcall_norets(H_PROTECT, flags, ptex, avpn);
66}
67
68static inline long plpar_tce_get(unsigned long liobn, unsigned long ioba,
69 unsigned long *tce_ret)
70{
71 unsigned long dummy;
72 return plpar_hcall(H_GET_TCE, liobn, ioba, 0, 0, tce_ret, &dummy,
73 &dummy);
74}
75
76static inline long plpar_tce_put(unsigned long liobn, unsigned long ioba,
77 unsigned long tceval)
78{
79 return plpar_hcall_norets(H_PUT_TCE, liobn, ioba, tceval);
80}
81
82static inline long plpar_tce_put_indirect(unsigned long liobn,
83 unsigned long ioba, unsigned long page, unsigned long count)
84{
85 return plpar_hcall_norets(H_PUT_TCE_INDIRECT, liobn, ioba, page, count);
86}
87
88static inline long plpar_tce_stuff(unsigned long liobn, unsigned long ioba,
89 unsigned long tceval, unsigned long count)
90{
91 return plpar_hcall_norets(H_STUFF_TCE, liobn, ioba, tceval, count);
92}
93
94static inline long plpar_get_term_char(unsigned long termno,
95 unsigned long *len_ret, char *buf_ret)
96{
97 unsigned long *lbuf = (unsigned long *)buf_ret; /* TODO: alignment? */
98 return plpar_hcall(H_GET_TERM_CHAR, termno, 0, 0, 0, len_ret,
99 lbuf + 0, lbuf + 1);
100}
101
102static inline long plpar_put_term_char(unsigned long termno, unsigned long len,
103 const char *buffer)
104{
105 unsigned long *lbuf = (unsigned long *)buffer; /* TODO: alignment? */
106 return plpar_hcall_norets(H_PUT_TERM_CHAR, termno, len, lbuf[0],
107 lbuf[1]);
108}
109
110static inline long plpar_set_xdabr(unsigned long address, unsigned long flags)
111{
112 return plpar_hcall_norets(H_SET_XDABR, address, flags);
113}
114
115static inline long plpar_set_dabr(unsigned long val)
116{
117 return plpar_hcall_norets(H_SET_DABR, val);
118}
119
120#endif /* _PSERIES_PLPAR_WRAPPERS_H */
diff --git a/arch/powerpc/platforms/pseries/rtas-fw.c b/arch/powerpc/platforms/pseries/rtas-fw.c
deleted file mode 100644
index 15d81d758ca0..000000000000
--- a/arch/powerpc/platforms/pseries/rtas-fw.c
+++ /dev/null
@@ -1,138 +0,0 @@
1/*
2 *
3 * Procedures for firmware flash updates on pSeries systems.
4 *
5 * Peter Bergner, IBM March 2001.
6 * Copyright (C) 2001 IBM.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13
14#include <stdarg.h>
15#include <linux/kernel.h>
16#include <linux/types.h>
17#include <linux/spinlock.h>
18#include <linux/module.h>
19#include <linux/init.h>
20
21#include <asm/prom.h>
22#include <asm/rtas.h>
23#include <asm/semaphore.h>
24#include <asm/machdep.h>
25#include <asm/page.h>
26#include <asm/param.h>
27#include <asm/system.h>
28#include <asm/abs_addr.h>
29#include <asm/udbg.h>
30#include <asm/delay.h>
31#include <asm/uaccess.h>
32#include <asm/systemcfg.h>
33
34#include "rtas-fw.h"
35
36struct flash_block_list_header rtas_firmware_flash_list = {0, NULL};
37
38#define FLASH_BLOCK_LIST_VERSION (1UL)
39
40static void rtas_flash_firmware(void)
41{
42 unsigned long image_size;
43 struct flash_block_list *f, *next, *flist;
44 unsigned long rtas_block_list;
45 int i, status, update_token;
46
47 update_token = rtas_token("ibm,update-flash-64-and-reboot");
48 if (update_token == RTAS_UNKNOWN_SERVICE) {
49 printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot is not available -- not a service partition?\n");
50 printk(KERN_ALERT "FLASH: firmware will not be flashed\n");
51 return;
52 }
53
54 /* NOTE: the "first" block list is a global var with no data
55 * blocks in the kernel data segment. We do this because
56 * we want to ensure this block_list addr is under 4GB.
57 */
58 rtas_firmware_flash_list.num_blocks = 0;
59 flist = (struct flash_block_list *)&rtas_firmware_flash_list;
60 rtas_block_list = virt_to_abs(flist);
61 if (rtas_block_list >= 4UL*1024*1024*1024) {
62 printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n");
63 return;
64 }
65
66 printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n");
67 /* Update the block_list in place. */
68 image_size = 0;
69 for (f = flist; f; f = next) {
70 /* Translate data addrs to absolute */
71 for (i = 0; i < f->num_blocks; i++) {
72 f->blocks[i].data = (char *)virt_to_abs(f->blocks[i].data);
73 image_size += f->blocks[i].length;
74 }
75 next = f->next;
76 /* Don't translate NULL pointer for last entry */
77 if (f->next)
78 f->next = (struct flash_block_list *)virt_to_abs(f->next);
79 else
80 f->next = NULL;
81 /* make num_blocks into the version/length field */
82 f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16);
83 }
84
85 printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size);
86 printk(KERN_ALERT "FLASH: performing flash and reboot\n");
87 rtas_progress("Flashing \n", 0x0);
88 rtas_progress("Please Wait... ", 0x0);
89 printk(KERN_ALERT "FLASH: this will take several minutes. Do not power off!\n");
90 status = rtas_call(update_token, 1, 1, NULL, rtas_block_list);
91 switch (status) { /* should only get "bad" status */
92 case 0:
93 printk(KERN_ALERT "FLASH: success\n");
94 break;
95 case -1:
96 printk(KERN_ALERT "FLASH: hardware error. Firmware may not be not flashed\n");
97 break;
98 case -3:
99 printk(KERN_ALERT "FLASH: image is corrupt or not correct for this platform. Firmware not flashed\n");
100 break;
101 case -4:
102 printk(KERN_ALERT "FLASH: flash failed when partially complete. System may not reboot\n");
103 break;
104 default:
105 printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status);
106 break;
107 }
108}
109
110void rtas_flash_bypass_warning(void)
111{
112 printk(KERN_ALERT "FLASH: firmware flash requires a reboot\n");
113 printk(KERN_ALERT "FLASH: the firmware image will NOT be flashed\n");
114}
115
116
117void rtas_fw_restart(char *cmd)
118{
119 if (rtas_firmware_flash_list.next)
120 rtas_flash_firmware();
121 rtas_restart(cmd);
122}
123
124void rtas_fw_power_off(void)
125{
126 if (rtas_firmware_flash_list.next)
127 rtas_flash_bypass_warning();
128 rtas_power_off();
129}
130
131void rtas_fw_halt(void)
132{
133 if (rtas_firmware_flash_list.next)
134 rtas_flash_bypass_warning();
135 rtas_halt();
136}
137
138EXPORT_SYMBOL(rtas_firmware_flash_list);
diff --git a/arch/powerpc/platforms/pseries/rtas-fw.h b/arch/powerpc/platforms/pseries/rtas-fw.h
deleted file mode 100644
index e70fa69974a3..000000000000
--- a/arch/powerpc/platforms/pseries/rtas-fw.h
+++ /dev/null
@@ -1,3 +0,0 @@
1void rtas_fw_restart(char *cmd);
2void rtas_fw_power_off(void);
3void rtas_fw_halt(void);
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c
new file mode 100644
index 000000000000..e26b0420b6dd
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/rtasd.c
@@ -0,0 +1,527 @@
1/*
2 * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Communication to userspace based on kernel/printk.c
10 */
11
12#include <linux/types.h>
13#include <linux/errno.h>
14#include <linux/sched.h>
15#include <linux/kernel.h>
16#include <linux/poll.h>
17#include <linux/proc_fs.h>
18#include <linux/init.h>
19#include <linux/vmalloc.h>
20#include <linux/spinlock.h>
21#include <linux/cpu.h>
22#include <linux/delay.h>
23
24#include <asm/uaccess.h>
25#include <asm/io.h>
26#include <asm/rtas.h>
27#include <asm/prom.h>
28#include <asm/nvram.h>
29#include <asm/atomic.h>
30#include <asm/systemcfg.h>
31
32#if 0
33#define DEBUG(A...) printk(KERN_ERR A)
34#else
35#define DEBUG(A...)
36#endif
37
38static DEFINE_SPINLOCK(rtasd_log_lock);
39
40DECLARE_WAIT_QUEUE_HEAD(rtas_log_wait);
41
42static char *rtas_log_buf;
43static unsigned long rtas_log_start;
44static unsigned long rtas_log_size;
45
46static int surveillance_timeout = -1;
47static unsigned int rtas_event_scan_rate;
48static unsigned int rtas_error_log_max;
49static unsigned int rtas_error_log_buffer_max;
50
51static int full_rtas_msgs = 0;
52
53extern int no_logging;
54
55volatile int error_log_cnt = 0;
56
57/*
58 * Since we use 32 bit RTAS, the physical address of this must be below
59 * 4G or else bad things happen. Allocate this in the kernel data and
60 * make it big enough.
61 */
62static unsigned char logdata[RTAS_ERROR_LOG_MAX];
63
64static int get_eventscan_parms(void);
65
66static char *rtas_type[] = {
67 "Unknown", "Retry", "TCE Error", "Internal Device Failure",
68 "Timeout", "Data Parity", "Address Parity", "Cache Parity",
69 "Address Invalid", "ECC Uncorrected", "ECC Corrupted",
70};
71
72static char *rtas_event_type(int type)
73{
74 if ((type > 0) && (type < 11))
75 return rtas_type[type];
76
77 switch (type) {
78 case RTAS_TYPE_EPOW:
79 return "EPOW";
80 case RTAS_TYPE_PLATFORM:
81 return "Platform Error";
82 case RTAS_TYPE_IO:
83 return "I/O Event";
84 case RTAS_TYPE_INFO:
85 return "Platform Information Event";
86 case RTAS_TYPE_DEALLOC:
87 return "Resource Deallocation Event";
88 case RTAS_TYPE_DUMP:
89 return "Dump Notification Event";
90 }
91
92 return rtas_type[0];
93}
94
95/* To see this info, grep RTAS /var/log/messages and each entry
96 * will be collected together with obvious begin/end.
97 * There will be a unique identifier on the begin and end lines.
98 * This will persist across reboots.
99 *
100 * format of error logs returned from RTAS:
101 * bytes (size) : contents
102 * --------------------------------------------------------
103 * 0-7 (8) : rtas_error_log
104 * 8-47 (40) : extended info
105 * 48-51 (4) : vendor id
106 * 52-1023 (vendor specific) : location code and debug data
107 */
108static void printk_log_rtas(char *buf, int len)
109{
110
111 int i,j,n = 0;
112 int perline = 16;
113 char buffer[64];
114 char * str = "RTAS event";
115
116 if (full_rtas_msgs) {
117 printk(RTAS_DEBUG "%d -------- %s begin --------\n",
118 error_log_cnt, str);
119
120 /*
121 * Print perline bytes on each line, each line will start
122 * with RTAS and a changing number, so syslogd will
123 * print lines that are otherwise the same. Separate every
124 * 4 bytes with a space.
125 */
126 for (i = 0; i < len; i++) {
127 j = i % perline;
128 if (j == 0) {
129 memset(buffer, 0, sizeof(buffer));
130 n = sprintf(buffer, "RTAS %d:", i/perline);
131 }
132
133 if ((i % 4) == 0)
134 n += sprintf(buffer+n, " ");
135
136 n += sprintf(buffer+n, "%02x", (unsigned char)buf[i]);
137
138 if (j == (perline-1))
139 printk(KERN_DEBUG "%s\n", buffer);
140 }
141 if ((i % perline) != 0)
142 printk(KERN_DEBUG "%s\n", buffer);
143
144 printk(RTAS_DEBUG "%d -------- %s end ----------\n",
145 error_log_cnt, str);
146 } else {
147 struct rtas_error_log *errlog = (struct rtas_error_log *)buf;
148
149 printk(RTAS_DEBUG "event: %d, Type: %s, Severity: %d\n",
150 error_log_cnt, rtas_event_type(errlog->type),
151 errlog->severity);
152 }
153}
154
155static int log_rtas_len(char * buf)
156{
157 int len;
158 struct rtas_error_log *err;
159
160 /* rtas fixed header */
161 len = 8;
162 err = (struct rtas_error_log *)buf;
163 if (err->extended_log_length) {
164
165 /* extended header */
166 len += err->extended_log_length;
167 }
168
169 if (rtas_error_log_max == 0) {
170 get_eventscan_parms();
171 }
172 if (len > rtas_error_log_max)
173 len = rtas_error_log_max;
174
175 return len;
176}
177
178/*
179 * First write to nvram, if fatal error, that is the only
180 * place we log the info. The error will be picked up
181 * on the next reboot by rtasd. If not fatal, run the
182 * method for the type of error. Currently, only RTAS
183 * errors have methods implemented, but in the future
184 * there might be a need to store data in nvram before a
185 * call to panic().
186 *
187 * XXX We write to nvram periodically, to indicate error has
188 * been written and sync'd, but there is a possibility
189 * that if we don't shutdown correctly, a duplicate error
190 * record will be created on next reboot.
191 */
192void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
193{
194 unsigned long offset;
195 unsigned long s;
196 int len = 0;
197
198 DEBUG("logging event\n");
199 if (buf == NULL)
200 return;
201
202 spin_lock_irqsave(&rtasd_log_lock, s);
203
204 /* get length and increase count */
205 switch (err_type & ERR_TYPE_MASK) {
206 case ERR_TYPE_RTAS_LOG:
207 len = log_rtas_len(buf);
208 if (!(err_type & ERR_FLAG_BOOT))
209 error_log_cnt++;
210 break;
211 case ERR_TYPE_KERNEL_PANIC:
212 default:
213 spin_unlock_irqrestore(&rtasd_log_lock, s);
214 return;
215 }
216
217 /* Write error to NVRAM */
218 if (!no_logging && !(err_type & ERR_FLAG_BOOT))
219 nvram_write_error_log(buf, len, err_type);
220
221 /*
222 * rtas errors can occur during boot, and we do want to capture
223 * those somewhere, even if nvram isn't ready (why not?), and even
224 * if rtasd isn't ready. Put them into the boot log, at least.
225 */
226 if ((err_type & ERR_TYPE_MASK) == ERR_TYPE_RTAS_LOG)
227 printk_log_rtas(buf, len);
228
229 /* Check to see if we need to or have stopped logging */
230 if (fatal || no_logging) {
231 no_logging = 1;
232 spin_unlock_irqrestore(&rtasd_log_lock, s);
233 return;
234 }
235
236 /* call type specific method for error */
237 switch (err_type & ERR_TYPE_MASK) {
238 case ERR_TYPE_RTAS_LOG:
239 offset = rtas_error_log_buffer_max *
240 ((rtas_log_start+rtas_log_size) & LOG_NUMBER_MASK);
241
242 /* First copy over sequence number */
243 memcpy(&rtas_log_buf[offset], (void *) &error_log_cnt, sizeof(int));
244
245 /* Second copy over error log data */
246 offset += sizeof(int);
247 memcpy(&rtas_log_buf[offset], buf, len);
248
249 if (rtas_log_size < LOG_NUMBER)
250 rtas_log_size += 1;
251 else
252 rtas_log_start += 1;
253
254 spin_unlock_irqrestore(&rtasd_log_lock, s);
255 wake_up_interruptible(&rtas_log_wait);
256 break;
257 case ERR_TYPE_KERNEL_PANIC:
258 default:
259 spin_unlock_irqrestore(&rtasd_log_lock, s);
260 return;
261 }
262
263}
264
265
266static int rtas_log_open(struct inode * inode, struct file * file)
267{
268 return 0;
269}
270
271static int rtas_log_release(struct inode * inode, struct file * file)
272{
273 return 0;
274}
275
276/* This will check if all events are logged, if they are then, we
277 * know that we can safely clear the events in NVRAM.
278 * Next we'll sit and wait for something else to log.
279 */
280static ssize_t rtas_log_read(struct file * file, char __user * buf,
281 size_t count, loff_t *ppos)
282{
283 int error;
284 char *tmp;
285 unsigned long s;
286 unsigned long offset;
287
288 if (!buf || count < rtas_error_log_buffer_max)
289 return -EINVAL;
290
291 count = rtas_error_log_buffer_max;
292
293 if (!access_ok(VERIFY_WRITE, buf, count))
294 return -EFAULT;
295
296 tmp = kmalloc(count, GFP_KERNEL);
297 if (!tmp)
298 return -ENOMEM;
299
300
301 spin_lock_irqsave(&rtasd_log_lock, s);
302 /* if it's 0, then we know we got the last one (the one in NVRAM) */
303 if (rtas_log_size == 0 && !no_logging)
304 nvram_clear_error_log();
305 spin_unlock_irqrestore(&rtasd_log_lock, s);
306
307
308 error = wait_event_interruptible(rtas_log_wait, rtas_log_size);
309 if (error)
310 goto out;
311
312 spin_lock_irqsave(&rtasd_log_lock, s);
313 offset = rtas_error_log_buffer_max * (rtas_log_start & LOG_NUMBER_MASK);
314 memcpy(tmp, &rtas_log_buf[offset], count);
315
316 rtas_log_start += 1;
317 rtas_log_size -= 1;
318 spin_unlock_irqrestore(&rtasd_log_lock, s);
319
320 error = copy_to_user(buf, tmp, count) ? -EFAULT : count;
321out:
322 kfree(tmp);
323 return error;
324}
325
326static unsigned int rtas_log_poll(struct file *file, poll_table * wait)
327{
328 poll_wait(file, &rtas_log_wait, wait);
329 if (rtas_log_size)
330 return POLLIN | POLLRDNORM;
331 return 0;
332}
333
334struct file_operations proc_rtas_log_operations = {
335 .read = rtas_log_read,
336 .poll = rtas_log_poll,
337 .open = rtas_log_open,
338 .release = rtas_log_release,
339};
340
341static int enable_surveillance(int timeout)
342{
343 int error;
344
345 error = rtas_set_indicator(SURVEILLANCE_TOKEN, 0, timeout);
346
347 if (error == 0)
348 return 0;
349
350 if (error == -EINVAL) {
351 printk(KERN_INFO "rtasd: surveillance not supported\n");
352 return 0;
353 }
354
355 printk(KERN_ERR "rtasd: could not update surveillance\n");
356 return -1;
357}
358
359static int get_eventscan_parms(void)
360{
361 struct device_node *node;
362 int *ip;
363
364 node = of_find_node_by_path("/rtas");
365
366 ip = (int *)get_property(node, "rtas-event-scan-rate", NULL);
367 if (ip == NULL) {
368 printk(KERN_ERR "rtasd: no rtas-event-scan-rate\n");
369 of_node_put(node);
370 return -1;
371 }
372 rtas_event_scan_rate = *ip;
373 DEBUG("rtas-event-scan-rate %d\n", rtas_event_scan_rate);
374
375 /* Make room for the sequence number */
376 rtas_error_log_max = rtas_get_error_log_max();
377 rtas_error_log_buffer_max = rtas_error_log_max + sizeof(int);
378
379 of_node_put(node);
380
381 return 0;
382}
383
384static void do_event_scan(int event_scan)
385{
386 int error;
387 do {
388 memset(logdata, 0, rtas_error_log_max);
389 error = rtas_call(event_scan, 4, 1, NULL,
390 RTAS_EVENT_SCAN_ALL_EVENTS, 0,
391 __pa(logdata), rtas_error_log_max);
392 if (error == -1) {
393 printk(KERN_ERR "event-scan failed\n");
394 break;
395 }
396
397 if (error == 0)
398 pSeries_log_error(logdata, ERR_TYPE_RTAS_LOG, 0);
399
400 } while(error == 0);
401}
402
403static void do_event_scan_all_cpus(long delay)
404{
405 int cpu;
406
407 lock_cpu_hotplug();
408 cpu = first_cpu(cpu_online_map);
409 for (;;) {
410 set_cpus_allowed(current, cpumask_of_cpu(cpu));
411 do_event_scan(rtas_token("event-scan"));
412 set_cpus_allowed(current, CPU_MASK_ALL);
413
414 /* Drop hotplug lock, and sleep for the specified delay */
415 unlock_cpu_hotplug();
416 msleep_interruptible(delay);
417 lock_cpu_hotplug();
418
419 cpu = next_cpu(cpu, cpu_online_map);
420 if (cpu == NR_CPUS)
421 break;
422 }
423 unlock_cpu_hotplug();
424}
425
426static int rtasd(void *unused)
427{
428 unsigned int err_type;
429 int event_scan = rtas_token("event-scan");
430 int rc;
431
432 daemonize("rtasd");
433
434 if (event_scan == RTAS_UNKNOWN_SERVICE || get_eventscan_parms() == -1)
435 goto error;
436
437 rtas_log_buf = vmalloc(rtas_error_log_buffer_max*LOG_NUMBER);
438 if (!rtas_log_buf) {
439 printk(KERN_ERR "rtasd: no memory\n");
440 goto error;
441 }
442
443 printk(KERN_INFO "RTAS daemon started\n");
444
445 DEBUG("will sleep for %d milliseconds\n", (30000/rtas_event_scan_rate));
446
447 /* See if we have any error stored in NVRAM */
448 memset(logdata, 0, rtas_error_log_max);
449
450 rc = nvram_read_error_log(logdata, rtas_error_log_max, &err_type);
451
452 /* We can use rtas_log_buf now */
453 no_logging = 0;
454
455 if (!rc) {
456 if (err_type != ERR_FLAG_ALREADY_LOGGED) {
457 pSeries_log_error(logdata, err_type | ERR_FLAG_BOOT, 0);
458 }
459 }
460
461 /* First pass. */
462 do_event_scan_all_cpus(1000);
463
464 if (surveillance_timeout != -1) {
465 DEBUG("enabling surveillance\n");
466 enable_surveillance(surveillance_timeout);
467 DEBUG("surveillance enabled\n");
468 }
469
470 /* Delay should be at least one second since some
471 * machines have problems if we call event-scan too
472 * quickly. */
473 for (;;)
474 do_event_scan_all_cpus(30000/rtas_event_scan_rate);
475
476error:
477 /* Should delete proc entries */
478 return -EINVAL;
479}
480
481static int __init rtas_init(void)
482{
483 struct proc_dir_entry *entry;
484
485 /* No RTAS, only warn if we are on a pSeries box */
486 if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) {
487 if (systemcfg->platform & PLATFORM_PSERIES)
488 printk(KERN_INFO "rtasd: no event-scan on system\n");
489 return 1;
490 }
491
492 entry = create_proc_entry("ppc64/rtas/error_log", S_IRUSR, NULL);
493 if (entry)
494 entry->proc_fops = &proc_rtas_log_operations;
495 else
496 printk(KERN_ERR "Failed to create error_log proc entry\n");
497
498 if (kernel_thread(rtasd, NULL, CLONE_FS) < 0)
499 printk(KERN_ERR "Failed to start RTAS daemon\n");
500
501 return 0;
502}
503
504static int __init surveillance_setup(char *str)
505{
506 int i;
507
508 if (get_option(&str,&i)) {
509 if (i >= 0 && i <= 255)
510 surveillance_timeout = i;
511 }
512
513 return 1;
514}
515
516static int __init rtasmsgs_setup(char *str)
517{
518 if (strcmp(str, "on") == 0)
519 full_rtas_msgs = 1;
520 else if (strcmp(str, "off") == 0)
521 full_rtas_msgs = 0;
522
523 return 1;
524}
525__initcall(rtas_init);
526__setup("surveillance=", surveillance_setup);
527__setup("rtasmsgs=", rtasmsgs_setup);
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 10cb0f2d9b5b..65bee939eecc 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -58,7 +58,6 @@
58#include <asm/irq.h> 58#include <asm/irq.h>
59#include <asm/time.h> 59#include <asm/time.h>
60#include <asm/nvram.h> 60#include <asm/nvram.h>
61#include <asm/plpar_wrappers.h>
62#include "xics.h" 61#include "xics.h"
63#include <asm/firmware.h> 62#include <asm/firmware.h>
64#include <asm/pmc.h> 63#include <asm/pmc.h>
@@ -67,7 +66,7 @@
67#include <asm/i8259.h> 66#include <asm/i8259.h>
68#include <asm/udbg.h> 67#include <asm/udbg.h>
69 68
70#include "rtas-fw.h" 69#include "plpar_wrappers.h"
71 70
72#ifdef DEBUG 71#ifdef DEBUG
73#define DBG(fmt...) udbg_printf(fmt) 72#define DBG(fmt...) udbg_printf(fmt)
@@ -352,6 +351,16 @@ static void pSeries_mach_cpu_die(void)
352 for(;;); 351 for(;;);
353} 352}
354 353
354static int pseries_set_dabr(unsigned long dabr)
355{
356 if (firmware_has_feature(FW_FEATURE_XDABR)) {
357 /* We want to catch accesses from kernel and userspace */
358 return plpar_set_xdabr(dabr, H_DABRX_KERNEL | H_DABRX_USER);
359 }
360
361 return plpar_set_dabr(dabr);
362}
363
355 364
356/* 365/*
357 * Early initialization. Relocation is on but do not reference unbolted pages 366 * Early initialization. Relocation is on but do not reference unbolted pages
@@ -387,6 +396,8 @@ static void __init pSeries_init_early(void)
387 DBG("Hello World !\n"); 396 DBG("Hello World !\n");
388 } 397 }
389 398
399 if (firmware_has_feature(FW_FEATURE_XDABR | FW_FEATURE_DABR))
400 ppc_md.set_dabr = pseries_set_dabr;
390 401
391 iommu_init_early_pSeries(); 402 iommu_init_early_pSeries();
392 403
@@ -591,9 +602,9 @@ struct machdep_calls __initdata pSeries_md = {
591 .pcibios_fixup = pSeries_final_fixup, 602 .pcibios_fixup = pSeries_final_fixup,
592 .pci_probe_mode = pSeries_pci_probe_mode, 603 .pci_probe_mode = pSeries_pci_probe_mode,
593 .irq_bus_setup = pSeries_irq_bus_setup, 604 .irq_bus_setup = pSeries_irq_bus_setup,
594 .restart = rtas_fw_restart, 605 .restart = rtas_restart,
595 .power_off = rtas_fw_power_off, 606 .power_off = rtas_power_off,
596 .halt = rtas_fw_halt, 607 .halt = rtas_halt,
597 .panic = rtas_os_term, 608 .panic = rtas_os_term,
598 .cpu_die = pSeries_mach_cpu_die, 609 .cpu_die = pSeries_mach_cpu_die,
599 .get_boot_time = rtas_get_boot_time, 610 .get_boot_time = rtas_get_boot_time,
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index 9c9458ddfc25..7a243e8ccd7e 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -44,10 +44,11 @@
44#include <asm/firmware.h> 44#include <asm/firmware.h>
45#include <asm/system.h> 45#include <asm/system.h>
46#include <asm/rtas.h> 46#include <asm/rtas.h>
47#include <asm/plpar_wrappers.h>
48#include <asm/pSeries_reconfig.h> 47#include <asm/pSeries_reconfig.h>
49#include <asm/mpic.h> 48#include <asm/mpic.h>
50 49
50#include "plpar_wrappers.h"
51
51#ifdef DEBUG 52#ifdef DEBUG
52#define DBG(fmt...) udbg_printf(fmt) 53#define DBG(fmt...) udbg_printf(fmt)
53#else 54#else