aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/83xx/misc.c1
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_sys.c1
-rw-r--r--arch/powerpc/platforms/83xx/pci.c6
-rw-r--r--arch/powerpc/platforms/85xx/mpc8540_ads.h1
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ads.c1
-rw-r--r--arch/powerpc/platforms/85xx/pci.c6
-rw-r--r--arch/powerpc/platforms/86xx/Kconfig6
-rw-r--r--arch/powerpc/platforms/86xx/Makefile3
-rw-r--r--arch/powerpc/platforms/86xx/mpc8641_hpcn.h1
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx.h8
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_hpcn.c129
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_smp.c10
-rw-r--r--arch/powerpc/platforms/86xx/pci.c137
-rw-r--r--arch/powerpc/platforms/Makefile1
-rw-r--r--arch/powerpc/platforms/cell/Kconfig2
-rw-r--r--arch/powerpc/platforms/cell/interrupt.c420
-rw-r--r--arch/powerpc/platforms/cell/interrupt.h19
-rw-r--r--arch/powerpc/platforms/cell/pervasive.c1
-rw-r--r--arch/powerpc/platforms/cell/setup.c39
-rw-r--r--arch/powerpc/platforms/cell/smp.c1
-rw-r--r--arch/powerpc/platforms/cell/spider-pic.c394
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c127
-rw-r--r--arch/powerpc/platforms/cell/spufs/backing_ops.c1
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c10
-rw-r--r--arch/powerpc/platforms/cell/spufs/hw_ops.c1
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c1
-rw-r--r--arch/powerpc/platforms/cell/spufs/switch.c11
-rw-r--r--arch/powerpc/platforms/chrp/pci.c16
-rw-r--r--arch/powerpc/platforms/chrp/setup.c102
-rw-r--r--arch/powerpc/platforms/chrp/smp.c2
-rw-r--r--arch/powerpc/platforms/embedded6xx/Kconfig15
-rw-r--r--arch/powerpc/platforms/embedded6xx/Makefile4
-rw-r--r--arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c335
-rw-r--r--arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h26
-rw-r--r--arch/powerpc/platforms/iseries/dt.c2
-rw-r--r--arch/powerpc/platforms/iseries/htab.c4
-rw-r--r--arch/powerpc/platforms/iseries/irq.c110
-rw-r--r--arch/powerpc/platforms/iseries/irq.h2
-rw-r--r--arch/powerpc/platforms/iseries/lpardata.c1
-rw-r--r--arch/powerpc/platforms/iseries/lpevents.c55
-rw-r--r--arch/powerpc/platforms/iseries/proc.c1
-rw-r--r--arch/powerpc/platforms/iseries/setup.c26
-rw-r--r--arch/powerpc/platforms/iseries/smp.c1
-rw-r--r--arch/powerpc/platforms/maple/pci.c22
-rw-r--r--arch/powerpc/platforms/maple/setup.c102
-rw-r--r--arch/powerpc/platforms/maple/time.c1
-rw-r--r--arch/powerpc/platforms/powermac/backlight.c15
-rw-r--r--arch/powerpc/platforms/powermac/bootx_init.c34
-rw-r--r--arch/powerpc/platforms/powermac/cache.S1
-rw-r--r--arch/powerpc/platforms/powermac/cpufreq_32.c5
-rw-r--r--arch/powerpc/platforms/powermac/cpufreq_64.c1
-rw-r--r--arch/powerpc/platforms/powermac/feature.c1
-rw-r--r--arch/powerpc/platforms/powermac/low_i2c.c10
-rw-r--r--arch/powerpc/platforms/powermac/nvram.c6
-rw-r--r--arch/powerpc/platforms/powermac/pci.c73
-rw-r--r--arch/powerpc/platforms/powermac/pfunc_base.c14
-rw-r--r--arch/powerpc/platforms/powermac/pfunc_core.c3
-rw-r--r--arch/powerpc/platforms/powermac/pic.c425
-rw-r--r--arch/powerpc/platforms/powermac/pmac.h2
-rw-r--r--arch/powerpc/platforms/powermac/setup.c13
-rw-r--r--arch/powerpc/platforms/powermac/sleep.S1
-rw-r--r--arch/powerpc/platforms/powermac/smp.c3
-rw-r--r--arch/powerpc/platforms/powermac/time.c1
-rw-r--r--arch/powerpc/platforms/powermac/udbg_adb.c1
-rw-r--r--arch/powerpc/platforms/powermac/udbg_scc.c1
-rw-r--r--arch/powerpc/platforms/pseries/eeh_cache.c2
-rw-r--r--arch/powerpc/platforms/pseries/eeh_driver.c2
-rw-r--r--arch/powerpc/platforms/pseries/eeh_event.c2
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c34
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c5
-rw-r--r--arch/powerpc/platforms/pseries/ras.c82
-rw-r--r--arch/powerpc/platforms/pseries/setup.c255
-rw-r--r--arch/powerpc/platforms/pseries/smp.c33
-rw-r--r--arch/powerpc/platforms/pseries/xics.c732
-rw-r--r--arch/powerpc/platforms/pseries/xics.h17
75 files changed, 2349 insertions, 1590 deletions
diff --git a/arch/powerpc/platforms/83xx/misc.c b/arch/powerpc/platforms/83xx/misc.c
index 1455bcef4892..f0c6df61faa9 100644
--- a/arch/powerpc/platforms/83xx/misc.c
+++ b/arch/powerpc/platforms/83xx/misc.c
@@ -9,7 +9,6 @@
9 * option) any later version. 9 * option) any later version.
10 */ 10 */
11 11
12#include <linux/config.h>
13#include <linux/stddef.h> 12#include <linux/stddef.h>
14#include <linux/kernel.h> 13#include <linux/kernel.h>
15 14
diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.c b/arch/powerpc/platforms/83xx/mpc834x_sys.c
index 7e789d2420ba..3e1c16eb4a63 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_sys.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_sys.c
@@ -11,7 +11,6 @@
11 * option) any later version. 11 * option) any later version.
12 */ 12 */
13 13
14#include <linux/config.h>
15#include <linux/stddef.h> 14#include <linux/stddef.h>
16#include <linux/kernel.h> 15#include <linux/kernel.h>
17#include <linux/init.h> 16#include <linux/init.h>
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c
index 16f7d3b30e1d..3b5e563c279f 100644
--- a/arch/powerpc/platforms/83xx/pci.c
+++ b/arch/powerpc/platforms/83xx/pci.c
@@ -9,7 +9,6 @@
9 * option) any later version. 9 * option) any later version.
10 */ 10 */
11 11
12#include <linux/config.h>
13#include <linux/stddef.h> 12#include <linux/stddef.h>
14#include <linux/kernel.h> 13#include <linux/kernel.h>
15#include <linux/init.h> 14#include <linux/init.h>
@@ -91,9 +90,10 @@ int __init add_bridge(struct device_node *dev)
91 mpc83xx_pci2_busno = hose->first_busno; 90 mpc83xx_pci2_busno = hose->first_busno;
92 } 91 }
93 92
94 printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%08lx. " 93 printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. "
95 "Firmware bus number: %d->%d\n", 94 "Firmware bus number: %d->%d\n",
96 rsrc.start, hose->first_busno, hose->last_busno); 95 (unsigned long long)rsrc.start, hose->first_busno,
96 hose->last_busno);
97 97
98 DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", 98 DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
99 hose, hose->cfg_addr, hose->cfg_data); 99 hose, hose->cfg_addr, hose->cfg_data);
diff --git a/arch/powerpc/platforms/85xx/mpc8540_ads.h b/arch/powerpc/platforms/85xx/mpc8540_ads.h
index f770cadb2080..c0d56d2bb5a5 100644
--- a/arch/powerpc/platforms/85xx/mpc8540_ads.h
+++ b/arch/powerpc/platforms/85xx/mpc8540_ads.h
@@ -17,7 +17,6 @@
17#ifndef __MACH_MPC8540ADS_H__ 17#ifndef __MACH_MPC8540ADS_H__
18#define __MACH_MPC8540ADS_H__ 18#define __MACH_MPC8540ADS_H__
19 19
20#include <linux/config.h>
21#include <linux/initrd.h> 20#include <linux/initrd.h>
22 21
23#define BOARD_CCSRBAR ((uint)0xe0000000) 22#define BOARD_CCSRBAR ((uint)0xe0000000)
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index 5eeff370f5fc..06a497676c99 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -11,7 +11,6 @@
11 * option) any later version. 11 * option) any later version.
12 */ 12 */
13 13
14#include <linux/config.h>
15#include <linux/stddef.h> 14#include <linux/stddef.h>
16#include <linux/kernel.h> 15#include <linux/kernel.h>
17#include <linux/pci.h> 16#include <linux/pci.h>
diff --git a/arch/powerpc/platforms/85xx/pci.c b/arch/powerpc/platforms/85xx/pci.c
index bad290110ed1..1d51f3242ab1 100644
--- a/arch/powerpc/platforms/85xx/pci.c
+++ b/arch/powerpc/platforms/85xx/pci.c
@@ -9,7 +9,6 @@
9 * option) any later version. 9 * option) any later version.
10 */ 10 */
11 11
12#include <linux/config.h>
13#include <linux/stddef.h> 12#include <linux/stddef.h>
14#include <linux/kernel.h> 13#include <linux/kernel.h>
15#include <linux/init.h> 14#include <linux/init.h>
@@ -79,9 +78,10 @@ int __init add_bridge(struct device_node *dev)
79 mpc85xx_pci2_busno = hose->first_busno; 78 mpc85xx_pci2_busno = hose->first_busno;
80 } 79 }
81 80
82 printk(KERN_INFO "Found MPC85xx PCI host bridge at 0x%08lx. " 81 printk(KERN_INFO "Found MPC85xx PCI host bridge at 0x%016llx. "
83 "Firmware bus number: %d->%d\n", 82 "Firmware bus number: %d->%d\n",
84 rsrc.start, hose->first_busno, hose->last_busno); 83 (unsigned long long)rsrc.start, hose->first_busno,
84 hose->last_busno);
85 85
86 DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", 86 DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
87 hose, hose->cfg_addr, hose->cfg_data); 87 hose, hose->cfg_addr, hose->cfg_data);
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
index 3a87863d2876..d1ecc0f9ab58 100644
--- a/arch/powerpc/platforms/86xx/Kconfig
+++ b/arch/powerpc/platforms/86xx/Kconfig
@@ -7,6 +7,7 @@ choice
7 7
8config MPC8641_HPCN 8config MPC8641_HPCN
9 bool "Freescale MPC8641 HPCN" 9 bool "Freescale MPC8641 HPCN"
10 select PPC_I8259
10 help 11 help
11 This option enables support for the MPC8641 HPCN board. 12 This option enables support for the MPC8641 HPCN board.
12 13
@@ -28,9 +29,4 @@ config PPC_INDIRECT_PCI_BE
28 depends on PPC_86xx 29 depends on PPC_86xx
29 default y 30 default y
30 31
31config PPC_STD_MMU
32 bool
33 depends on PPC_86xx
34 default y
35
36endmenu 32endmenu
diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile
index 7be796c5d5c9..476a6eeee710 100644
--- a/arch/powerpc/platforms/86xx/Makefile
+++ b/arch/powerpc/platforms/86xx/Makefile
@@ -2,9 +2,6 @@
2# Makefile for the PowerPC 86xx linux kernel. 2# Makefile for the PowerPC 86xx linux kernel.
3# 3#
4 4
5
6ifeq ($(CONFIG_PPC_86xx),y)
7obj-$(CONFIG_SMP) += mpc86xx_smp.o 5obj-$(CONFIG_SMP) += mpc86xx_smp.o
8endif
9obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o 6obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o
10obj-$(CONFIG_PCI) += pci.o mpc86xx_pcie.o 7obj-$(CONFIG_PCI) += pci.o mpc86xx_pcie.o
diff --git a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
index 5042253758b7..5d2bcf78cef7 100644
--- a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
+++ b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
@@ -14,7 +14,6 @@
14#ifndef __MPC8641_HPCN_H__ 14#ifndef __MPC8641_HPCN_H__
15#define __MPC8641_HPCN_H__ 15#define __MPC8641_HPCN_H__
16 16
17#include <linux/config.h>
18#include <linux/init.h> 17#include <linux/init.h>
19 18
20/* PCI interrupt controller */ 19/* PCI interrupt controller */
diff --git a/arch/powerpc/platforms/86xx/mpc86xx.h b/arch/powerpc/platforms/86xx/mpc86xx.h
index e3c9e4f417d3..2834462590b8 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx.h
+++ b/arch/powerpc/platforms/86xx/mpc86xx.h
@@ -15,11 +15,13 @@
15 * mpc86xx_* files. Mostly for use by mpc86xx_setup(). 15 * mpc86xx_* files. Mostly for use by mpc86xx_setup().
16 */ 16 */
17 17
18extern int __init add_bridge(struct device_node *dev); 18extern int add_bridge(struct device_node *dev);
19 19
20extern void __init setup_indirect_pcie(struct pci_controller *hose, 20extern int mpc86xx_exclude_device(u_char bus, u_char devfn);
21
22extern void setup_indirect_pcie(struct pci_controller *hose,
21 u32 cfg_addr, u32 cfg_data); 23 u32 cfg_addr, u32 cfg_data);
22extern void __init setup_indirect_pcie_nomap(struct pci_controller *hose, 24extern void setup_indirect_pcie_nomap(struct pci_controller *hose,
23 void __iomem *cfg_addr, 25 void __iomem *cfg_addr,
24 void __iomem *cfg_data); 26 void __iomem *cfg_data);
25 27
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 483c21df181e..ebae73eb0063 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -12,7 +12,6 @@
12 * option) any later version. 12 * option) any later version.
13 */ 13 */
14 14
15#include <linux/config.h>
16#include <linux/stddef.h> 15#include <linux/stddef.h>
17#include <linux/kernel.h> 16#include <linux/kernel.h>
18#include <linux/pci.h> 17#include <linux/pci.h>
@@ -36,6 +35,7 @@
36#include <sysdev/fsl_soc.h> 35#include <sysdev/fsl_soc.h>
37 36
38#include "mpc86xx.h" 37#include "mpc86xx.h"
38#include "mpc8641_hpcn.h"
39 39
40#ifndef CONFIG_PCI 40#ifndef CONFIG_PCI
41unsigned long isa_io_base = 0; 41unsigned long isa_io_base = 0;
@@ -186,17 +186,130 @@ mpc86xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
186 return PCI_IRQ_TABLE_LOOKUP + I8259_OFFSET; 186 return PCI_IRQ_TABLE_LOOKUP + I8259_OFFSET;
187} 187}
188 188
189static void __devinit quirk_ali1575(struct pci_dev *dev)
190{
191 unsigned short temp;
192
193 /*
194 * ALI1575 interrupts route table setup:
195 *
196 * IRQ pin IRQ#
197 * PIRQA ---- 3
198 * PIRQB ---- 4
199 * PIRQC ---- 5
200 * PIRQD ---- 6
201 * PIRQE ---- 9
202 * PIRQF ---- 10
203 * PIRQG ---- 11
204 * PIRQH ---- 12
205 *
206 * interrupts for PCI slot0 -- PIRQA / PIRQB / PIRQC / PIRQD
207 * PCI slot1 -- PIRQB / PIRQC / PIRQD / PIRQA
208 */
209 pci_write_config_dword(dev, 0x48, 0xb9317542);
210
211 /* USB 1.1 OHCI controller 1, interrupt: PIRQE */
212 pci_write_config_byte(dev, 0x86, 0x0c);
213
214 /* USB 1.1 OHCI controller 2, interrupt: PIRQF */
215 pci_write_config_byte(dev, 0x87, 0x0d);
216
217 /* USB 1.1 OHCI controller 3, interrupt: PIRQH */
218 pci_write_config_byte(dev, 0x88, 0x0f);
219
220 /* USB 2.0 controller, interrupt: PIRQ7 */
221 pci_write_config_byte(dev, 0x74, 0x06);
222
223 /* Audio controller, interrupt: PIRQE */
224 pci_write_config_byte(dev, 0x8a, 0x0c);
225
226 /* Modem controller, interrupt: PIRQF */
227 pci_write_config_byte(dev, 0x8b, 0x0d);
228
229 /* HD audio controller, interrupt: PIRQG */
230 pci_write_config_byte(dev, 0x8c, 0x0e);
231
232 /* Serial ATA interrupt: PIRQD */
233 pci_write_config_byte(dev, 0x8d, 0x0b);
234
235 /* SMB interrupt: PIRQH */
236 pci_write_config_byte(dev, 0x8e, 0x0f);
237
238 /* PMU ACPI SCI interrupt: PIRQH */
239 pci_write_config_byte(dev, 0x8f, 0x0f);
240
241 /* Primary PATA IDE IRQ: 14
242 * Secondary PATA IDE IRQ: 15
243 */
244 pci_write_config_byte(dev, 0x44, 0x3d);
245 pci_write_config_byte(dev, 0x75, 0x0f);
246
247 /* Set IRQ14 and IRQ15 to legacy IRQs */
248 pci_read_config_word(dev, 0x46, &temp);
249 temp |= 0xc000;
250 pci_write_config_word(dev, 0x46, temp);
251
252 /* Set i8259 interrupt trigger
253 * IRQ 3: Level
254 * IRQ 4: Level
255 * IRQ 5: Level
256 * IRQ 6: Level
257 * IRQ 7: Level
258 * IRQ 9: Level
259 * IRQ 10: Level
260 * IRQ 11: Level
261 * IRQ 12: Level
262 * IRQ 14: Edge
263 * IRQ 15: Edge
264 */
265 outb(0xfa, 0x4d0);
266 outb(0x1e, 0x4d1);
267}
189 268
190int 269static void __devinit quirk_uli5288(struct pci_dev *dev)
191mpc86xx_exclude_device(u_char bus, u_char devfn)
192{ 270{
193#if !defined(CONFIG_PCI) 271 unsigned char c;
194 if (bus == 0 && PCI_SLOT(devfn) == 0) 272
195 return PCIBIOS_DEVICE_NOT_FOUND; 273 pci_read_config_byte(dev,0x83,&c);
196#endif 274 c |= 0x80;
275 pci_write_config_byte(dev, 0x83, c);
276
277 pci_write_config_byte(dev, 0x09, 0x01);
278 pci_write_config_byte(dev, 0x0a, 0x06);
279
280 pci_read_config_byte(dev,0x83,&c);
281 c &= 0x7f;
282 pci_write_config_byte(dev, 0x83, c);
197 283
198 return PCIBIOS_SUCCESSFUL; 284 pci_read_config_byte(dev,0x84,&c);
285 c |= 0x01;
286 pci_write_config_byte(dev, 0x84, c);
199} 287}
288
289static void __devinit quirk_uli5229(struct pci_dev *dev)
290{
291 unsigned short temp;
292 pci_write_config_word(dev, 0x04, 0x0405);
293 pci_read_config_word(dev, 0x4a, &temp);
294 temp |= 0x1000;
295 pci_write_config_word(dev, 0x4a, temp);
296}
297
298static void __devinit early_uli5249(struct pci_dev *dev)
299{
300 unsigned char temp;
301 pci_write_config_word(dev, 0x04, 0x0007);
302 pci_read_config_byte(dev, 0x7c, &temp);
303 pci_write_config_byte(dev, 0x7c, 0x80);
304 pci_write_config_byte(dev, 0x09, 0x01);
305 pci_write_config_byte(dev, 0x7c, temp);
306 dev->class |= 0x1;
307}
308
309DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_ali1575);
310DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288);
311DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229);
312DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, 0x5249, early_uli5249);
200#endif /* CONFIG_PCI */ 313#endif /* CONFIG_PCI */
201 314
202 315
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_smp.c b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
index 944ec4b71416..bb7fb41933ad 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_smp.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
@@ -10,7 +10,6 @@
10 * option) any later version. 10 * option) any later version.
11 */ 11 */
12 12
13#include <linux/config.h>
14#include <linux/stddef.h> 13#include <linux/stddef.h>
15#include <linux/kernel.h> 14#include <linux/kernel.h>
16#include <linux/init.h> 15#include <linux/init.h>
@@ -34,8 +33,8 @@ extern unsigned long __secondary_hold_acknowledge;
34static void __init 33static void __init
35smp_86xx_release_core(int nr) 34smp_86xx_release_core(int nr)
36{ 35{
37 void *mcm_vaddr; 36 __be32 __iomem *mcm_vaddr;
38 unsigned long vaddr, pcr; 37 unsigned long pcr;
39 38
40 if (nr < 0 || nr >= NR_CPUS) 39 if (nr < 0 || nr >= NR_CPUS)
41 return; 40 return;
@@ -45,10 +44,9 @@ smp_86xx_release_core(int nr)
45 */ 44 */
46 mcm_vaddr = ioremap(get_immrbase() + MPC86xx_MCM_OFFSET, 45 mcm_vaddr = ioremap(get_immrbase() + MPC86xx_MCM_OFFSET,
47 MPC86xx_MCM_SIZE); 46 MPC86xx_MCM_SIZE);
48 vaddr = (unsigned long)mcm_vaddr + MCM_PORT_CONFIG_OFFSET; 47 pcr = in_be32(mcm_vaddr + (MCM_PORT_CONFIG_OFFSET >> 2));
49 pcr = in_be32((volatile unsigned *)vaddr);
50 pcr |= 1 << (nr + 24); 48 pcr |= 1 << (nr + 24);
51 out_be32((volatile unsigned *)vaddr, pcr); 49 out_be32(mcm_vaddr + (MCM_PORT_CONFIG_OFFSET >> 2), pcr);
52} 50}
53 51
54 52
diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c
index 5180df7c75bc..bc5139043112 100644
--- a/arch/powerpc/platforms/86xx/pci.c
+++ b/arch/powerpc/platforms/86xx/pci.c
@@ -12,7 +12,6 @@
12 * option) any later version. 12 * option) any later version.
13 */ 13 */
14 14
15#include <linux/config.h>
16#include <linux/types.h> 15#include <linux/types.h>
17#include <linux/module.h> 16#include <linux/module.h>
18#include <linux/init.h> 17#include <linux/init.h>
@@ -122,15 +121,12 @@ static void __init setup_pcie_atmu(struct pci_controller *hose, struct resource
122static void __init 121static void __init
123mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size) 122mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size)
124{ 123{
125 volatile struct ccsr_pex *pcie;
126 u16 cmd; 124 u16 cmd;
127 unsigned int temps; 125 unsigned int temps;
128 126
129 DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n", 127 DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n",
130 pcie_offset, pcie_size); 128 pcie_offset, pcie_size);
131 129
132 pcie = ioremap(pcie_offset, pcie_size);
133
134 early_read_config_word(hose, 0, 0, PCI_COMMAND, &cmd); 130 early_read_config_word(hose, 0, 0, PCI_COMMAND, &cmd);
135 cmd |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY 131 cmd |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY
136 | PCI_COMMAND_IO; 132 | PCI_COMMAND_IO;
@@ -144,6 +140,14 @@ mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size)
144 early_write_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, temps); 140 early_write_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, temps);
145} 141}
146 142
143int mpc86xx_exclude_device(u_char bus, u_char devfn)
144{
145 if (bus == 0 && PCI_SLOT(devfn) == 0)
146 return PCIBIOS_DEVICE_NOT_FOUND;
147
148 return PCIBIOS_SUCCESSFUL;
149}
150
147int __init add_bridge(struct device_node *dev) 151int __init add_bridge(struct device_node *dev)
148{ 152{
149 int len; 153 int len;
@@ -198,128 +202,3 @@ int __init add_bridge(struct device_node *dev)
198 202
199 return 0; 203 return 0;
200} 204}
201
202static void __devinit quirk_ali1575(struct pci_dev *dev)
203{
204 unsigned short temp;
205
206 /*
207 * ALI1575 interrupts route table setup:
208 *
209 * IRQ pin IRQ#
210 * PIRQA ---- 3
211 * PIRQB ---- 4
212 * PIRQC ---- 5
213 * PIRQD ---- 6
214 * PIRQE ---- 9
215 * PIRQF ---- 10
216 * PIRQG ---- 11
217 * PIRQH ---- 12
218 *
219 * interrupts for PCI slot0 -- PIRQA / PIRQB / PIRQC / PIRQD
220 * PCI slot1 -- PIRQB / PIRQC / PIRQD / PIRQA
221 */
222 pci_write_config_dword(dev, 0x48, 0xb9317542);
223
224 /* USB 1.1 OHCI controller 1, interrupt: PIRQE */
225 pci_write_config_byte(dev, 0x86, 0x0c);
226
227 /* USB 1.1 OHCI controller 2, interrupt: PIRQF */
228 pci_write_config_byte(dev, 0x87, 0x0d);
229
230 /* USB 1.1 OHCI controller 3, interrupt: PIRQH */
231 pci_write_config_byte(dev, 0x88, 0x0f);
232
233 /* USB 2.0 controller, interrupt: PIRQ7 */
234 pci_write_config_byte(dev, 0x74, 0x06);
235
236 /* Audio controller, interrupt: PIRQE */
237 pci_write_config_byte(dev, 0x8a, 0x0c);
238
239 /* Modem controller, interrupt: PIRQF */
240 pci_write_config_byte(dev, 0x8b, 0x0d);
241
242 /* HD audio controller, interrupt: PIRQG */
243 pci_write_config_byte(dev, 0x8c, 0x0e);
244
245 /* Serial ATA interrupt: PIRQD */
246 pci_write_config_byte(dev, 0x8d, 0x0b);
247
248 /* SMB interrupt: PIRQH */
249 pci_write_config_byte(dev, 0x8e, 0x0f);
250
251 /* PMU ACPI SCI interrupt: PIRQH */
252 pci_write_config_byte(dev, 0x8f, 0x0f);
253
254 /* Primary PATA IDE IRQ: 14
255 * Secondary PATA IDE IRQ: 15
256 */
257 pci_write_config_byte(dev, 0x44, 0x3d);
258 pci_write_config_byte(dev, 0x75, 0x0f);
259
260 /* Set IRQ14 and IRQ15 to legacy IRQs */
261 pci_read_config_word(dev, 0x46, &temp);
262 temp |= 0xc000;
263 pci_write_config_word(dev, 0x46, temp);
264
265 /* Set i8259 interrupt trigger
266 * IRQ 3: Level
267 * IRQ 4: Level
268 * IRQ 5: Level
269 * IRQ 6: Level
270 * IRQ 7: Level
271 * IRQ 9: Level
272 * IRQ 10: Level
273 * IRQ 11: Level
274 * IRQ 12: Level
275 * IRQ 14: Edge
276 * IRQ 15: Edge
277 */
278 outb(0xfa, 0x4d0);
279 outb(0x1e, 0x4d1);
280}
281
282static void __devinit quirk_uli5288(struct pci_dev *dev)
283{
284 unsigned char c;
285
286 pci_read_config_byte(dev,0x83,&c);
287 c |= 0x80;
288 pci_write_config_byte(dev, 0x83, c);
289
290 pci_write_config_byte(dev, 0x09, 0x01);
291 pci_write_config_byte(dev, 0x0a, 0x06);
292
293 pci_read_config_byte(dev,0x83,&c);
294 c &= 0x7f;
295 pci_write_config_byte(dev, 0x83, c);
296
297 pci_read_config_byte(dev,0x84,&c);
298 c |= 0x01;
299 pci_write_config_byte(dev, 0x84, c);
300}
301
302static void __devinit quirk_uli5229(struct pci_dev *dev)
303{
304 unsigned short temp;
305 pci_write_config_word(dev, 0x04, 0x0405);
306 pci_read_config_word(dev, 0x4a, &temp);
307 temp |= 0x1000;
308 pci_write_config_word(dev, 0x4a, temp);
309}
310
311static void __devinit early_uli5249(struct pci_dev *dev)
312{
313 unsigned char temp;
314 pci_write_config_word(dev, 0x04, 0x0007);
315 pci_read_config_byte(dev, 0x7c, &temp);
316 pci_write_config_byte(dev, 0x7c, 0x80);
317 pci_write_config_byte(dev, 0x09, 0x01);
318 pci_write_config_byte(dev, 0x7c, temp);
319 dev->class |= 0x1;
320}
321
322DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_ali1575);
323DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288);
324DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229);
325DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, 0x5249, early_uli5249);
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index 292863694562..5cf46dc57895 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -14,3 +14,4 @@ obj-$(CONFIG_PPC_PSERIES) += pseries/
14obj-$(CONFIG_PPC_ISERIES) += iseries/ 14obj-$(CONFIG_PPC_ISERIES) += iseries/
15obj-$(CONFIG_PPC_MAPLE) += maple/ 15obj-$(CONFIG_PPC_MAPLE) += maple/
16obj-$(CONFIG_PPC_CELL) += cell/ 16obj-$(CONFIG_PPC_CELL) += cell/
17obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 352bbbacde9a..0c8c7b6ab897 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -6,6 +6,7 @@ config SPU_FS
6 default m 6 default m
7 depends on PPC_CELL 7 depends on PPC_CELL
8 select SPU_BASE 8 select SPU_BASE
9 select MEMORY_HOTPLUG
9 help 10 help
10 The SPU file system is used to access Synergistic Processing 11 The SPU file system is used to access Synergistic Processing
11 Units on machines implementing the Broadband Processor 12 Units on machines implementing the Broadband Processor
@@ -18,7 +19,6 @@ config SPU_BASE
18config SPUFS_MMAP 19config SPUFS_MMAP
19 bool 20 bool
20 depends on SPU_FS && SPARSEMEM 21 depends on SPU_FS && SPARSEMEM
21 select MEMORY_HOTPLUG
22 default y 22 default y
23 23
24config CBE_RAS 24config CBE_RAS
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index 1bbf822b4efc..9d5da7896892 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -1,6 +1,9 @@
1/* 1/*
2 * Cell Internal Interrupt Controller 2 * Cell Internal Interrupt Controller
3 * 3 *
4 * Copyright (C) 2006 Benjamin Herrenschmidt (benh@kernel.crashing.org)
5 * IBM, Corp.
6 *
4 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 7 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
5 * 8 *
6 * Author: Arnd Bergmann <arndb@de.ibm.com> 9 * Author: Arnd Bergmann <arndb@de.ibm.com>
@@ -20,17 +23,18 @@
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */ 24 */
22 25
23#include <linux/config.h>
24#include <linux/interrupt.h> 26#include <linux/interrupt.h>
25#include <linux/irq.h> 27#include <linux/irq.h>
26#include <linux/module.h> 28#include <linux/module.h>
27#include <linux/percpu.h> 29#include <linux/percpu.h>
28#include <linux/types.h> 30#include <linux/types.h>
31#include <linux/ioport.h>
29 32
30#include <asm/io.h> 33#include <asm/io.h>
31#include <asm/pgtable.h> 34#include <asm/pgtable.h>
32#include <asm/prom.h> 35#include <asm/prom.h>
33#include <asm/ptrace.h> 36#include <asm/ptrace.h>
37#include <asm/machdep.h>
34 38
35#include "interrupt.h" 39#include "interrupt.h"
36#include "cbe_regs.h" 40#include "cbe_regs.h"
@@ -38,231 +42,65 @@
38struct iic { 42struct iic {
39 struct cbe_iic_thread_regs __iomem *regs; 43 struct cbe_iic_thread_regs __iomem *regs;
40 u8 target_id; 44 u8 target_id;
45 u8 eoi_stack[16];
46 int eoi_ptr;
47 struct irq_host *host;
41}; 48};
42 49
43static DEFINE_PER_CPU(struct iic, iic); 50static DEFINE_PER_CPU(struct iic, iic);
51#define IIC_NODE_COUNT 2
52static struct irq_host *iic_hosts[IIC_NODE_COUNT];
44 53
45void iic_local_enable(void) 54/* Convert between "pending" bits and hw irq number */
55static irq_hw_number_t iic_pending_to_hwnum(struct cbe_iic_pending_bits bits)
46{ 56{
47 struct iic *iic = &__get_cpu_var(iic); 57 unsigned char unit = bits.source & 0xf;
48 u64 tmp;
49
50 /*
51 * There seems to be a bug that is present in DD2.x CPUs
52 * and still only partially fixed in DD3.1.
53 * This bug causes a value written to the priority register
54 * not to make it there, resulting in a system hang unless we
55 * write it again.
56 * Masking with 0xf0 is done because the Cell BE does not
57 * implement the lower four bits of the interrupt priority,
58 * they always read back as zeroes, although future CPUs
59 * might implement different bits.
60 */
61 do {
62 out_be64(&iic->regs->prio, 0xff);
63 tmp = in_be64(&iic->regs->prio);
64 } while ((tmp & 0xf0) != 0xf0);
65}
66
67void iic_local_disable(void)
68{
69 out_be64(&__get_cpu_var(iic).regs->prio, 0x0);
70}
71 58
72static unsigned int iic_startup(unsigned int irq) 59 if (bits.flags & CBE_IIC_IRQ_IPI)
73{ 60 return IIC_IRQ_IPI0 | (bits.prio >> 4);
74 return 0; 61 else if (bits.class <= 3)
62 return (bits.class << 4) | unit;
63 else
64 return IIC_IRQ_INVALID;
75} 65}
76 66
77static void iic_enable(unsigned int irq) 67static void iic_mask(unsigned int irq)
78{ 68{
79 iic_local_enable();
80} 69}
81 70
82static void iic_disable(unsigned int irq) 71static void iic_unmask(unsigned int irq)
83{ 72{
84} 73}
85 74
86static void iic_end(unsigned int irq) 75static void iic_eoi(unsigned int irq)
87{ 76{
88 iic_local_enable(); 77 struct iic *iic = &__get_cpu_var(iic);
78 out_be64(&iic->regs->prio, iic->eoi_stack[--iic->eoi_ptr]);
79 BUG_ON(iic->eoi_ptr < 0);
89} 80}
90 81
91static struct hw_interrupt_type iic_pic = { 82static struct irq_chip iic_chip = {
92 .typename = " CELL-IIC ", 83 .typename = " CELL-IIC ",
93 .startup = iic_startup, 84 .mask = iic_mask,
94 .enable = iic_enable, 85 .unmask = iic_unmask,
95 .disable = iic_disable, 86 .eoi = iic_eoi,
96 .end = iic_end,
97}; 87};
98 88
99static int iic_external_get_irq(struct cbe_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.class != 2)
121 break;
122 irq = IIC_EXT_OFFSET
123 + spider_get_irq(node)
124 + node * IIC_NODE_STRIDE;
125 break;
126 case 0x01 ... 0x04:
127 case 0x07 ... 0x0a:
128 /*
129 * These units are connected to the SPEs
130 */
131 if (pending.class > 2)
132 break;
133 irq = IIC_SPE_OFFSET
134 + pending.class * IIC_CLASS_STRIDE
135 + node * IIC_NODE_STRIDE
136 + unit;
137 break;
138 }
139 if (irq == -1)
140 printk(KERN_WARNING "Unexpected interrupt class %02x, "
141 "source %02x, prio %02x, cpu %02x\n", pending.class,
142 pending.source, pending.prio, smp_processor_id());
143 return irq;
144}
145
146/* Get an IRQ number from the pending state register of the IIC */ 89/* Get an IRQ number from the pending state register of the IIC */
147int iic_get_irq(struct pt_regs *regs) 90static unsigned int iic_get_irq(struct pt_regs *regs)
148{ 91{
149 struct iic *iic; 92 struct cbe_iic_pending_bits pending;
150 int irq; 93 struct iic *iic;
151 struct cbe_iic_pending_bits pending; 94
152 95 iic = &__get_cpu_var(iic);
153 iic = &__get_cpu_var(iic); 96 *(unsigned long *) &pending =
154 *(unsigned long *) &pending = 97 in_be64((unsigned long __iomem *) &iic->regs->pending_destr);
155 in_be64((unsigned long __iomem *) &iic->regs->pending_destr); 98 iic->eoi_stack[++iic->eoi_ptr] = pending.prio;
156 99 BUG_ON(iic->eoi_ptr > 15);
157 irq = -1; 100 if (pending.flags & CBE_IIC_IRQ_VALID)
158 if (pending.flags & CBE_IIC_IRQ_VALID) { 101 return irq_linear_revmap(iic->host,
159 if (pending.flags & CBE_IIC_IRQ_IPI) { 102 iic_pending_to_hwnum(pending));
160 irq = IIC_IPI_OFFSET + (pending.prio >> 4); 103 return NO_IRQ;
161/*
162 if (irq > 0x80)
163 printk(KERN_WARNING "Unexpected IPI prio %02x"
164 "on CPU %02x\n", pending.prio,
165 smp_processor_id());
166*/
167 } else {
168 irq = iic_external_get_irq(pending);
169 }
170 }
171 return irq;
172}
173
174/* hardcoded part to be compatible with older firmware */
175
176static int setup_iic_hardcoded(void)
177{
178 struct device_node *np;
179 int nodeid, cpu;
180 unsigned long regs;
181 struct iic *iic;
182
183 for_each_possible_cpu(cpu) {
184 iic = &per_cpu(iic, cpu);
185 nodeid = cpu/2;
186
187 for (np = of_find_node_by_type(NULL, "cpu");
188 np;
189 np = of_find_node_by_type(np, "cpu")) {
190 if (nodeid == *(int *)get_property(np, "node-id", NULL))
191 break;
192 }
193
194 if (!np) {
195 printk(KERN_WARNING "IIC: CPU %d not found\n", cpu);
196 iic->regs = NULL;
197 iic->target_id = 0xff;
198 return -ENODEV;
199 }
200
201 regs = *(long *)get_property(np, "iic", NULL);
202
203 /* hack until we have decided on the devtree info */
204 regs += 0x400;
205 if (cpu & 1)
206 regs += 0x20;
207
208 printk(KERN_INFO "IIC for CPU %d at %lx\n", cpu, regs);
209 iic->regs = ioremap(regs, sizeof(struct cbe_iic_thread_regs));
210 iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe);
211 }
212
213 return 0;
214}
215
216static int setup_iic(void)
217{
218 struct device_node *dn;
219 unsigned long *regs;
220 char *compatible;
221 unsigned *np, found = 0;
222 struct iic *iic = NULL;
223
224 for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) {
225 compatible = (char *)get_property(dn, "compatible", NULL);
226
227 if (!compatible) {
228 printk(KERN_WARNING "no compatible property found !\n");
229 continue;
230 }
231
232 if (strstr(compatible, "IBM,CBEA-Internal-Interrupt-Controller"))
233 regs = (unsigned long *)get_property(dn,"reg", NULL);
234 else
235 continue;
236
237 if (!regs)
238 printk(KERN_WARNING "IIC: no reg property\n");
239
240 np = (unsigned int *)get_property(dn, "ibm,interrupt-server-ranges", NULL);
241
242 if (!np) {
243 printk(KERN_WARNING "IIC: CPU association not found\n");
244 iic->regs = NULL;
245 iic->target_id = 0xff;
246 return -ENODEV;
247 }
248
249 iic = &per_cpu(iic, np[0]);
250 iic->regs = ioremap(regs[0], sizeof(struct cbe_iic_thread_regs));
251 iic->target_id = ((np[0] & 2) << 3) + ((np[0] & 1) ? 0xf : 0xe);
252 printk("IIC for CPU %d at %lx mapped to %p\n", np[0], regs[0], iic->regs);
253
254 iic = &per_cpu(iic, np[1]);
255 iic->regs = ioremap(regs[2], sizeof(struct cbe_iic_thread_regs));
256 iic->target_id = ((np[1] & 2) << 3) + ((np[1] & 1) ? 0xf : 0xe);
257 printk("IIC for CPU %d at %lx mapped to %p\n", np[1], regs[2], iic->regs);
258
259 found++;
260 }
261
262 if (found)
263 return 0;
264 else
265 return -ENODEV;
266} 104}
267 105
268#ifdef CONFIG_SMP 106#ifdef CONFIG_SMP
@@ -270,12 +108,12 @@ static int setup_iic(void)
270/* Use the highest interrupt priorities for IPI */ 108/* Use the highest interrupt priorities for IPI */
271static inline int iic_ipi_to_irq(int ipi) 109static inline int iic_ipi_to_irq(int ipi)
272{ 110{
273 return IIC_IPI_OFFSET + IIC_NUM_IPIS - 1 - ipi; 111 return IIC_IRQ_IPI0 + IIC_NUM_IPIS - 1 - ipi;
274} 112}
275 113
276static inline int iic_irq_to_ipi(int irq) 114static inline int iic_irq_to_ipi(int irq)
277{ 115{
278 return IIC_NUM_IPIS - 1 - (irq - IIC_IPI_OFFSET); 116 return IIC_NUM_IPIS - 1 - (irq - IIC_IRQ_IPI0);
279} 117}
280 118
281void iic_setup_cpu(void) 119void iic_setup_cpu(void)
@@ -294,22 +132,51 @@ u8 iic_get_target_id(int cpu)
294} 132}
295EXPORT_SYMBOL_GPL(iic_get_target_id); 133EXPORT_SYMBOL_GPL(iic_get_target_id);
296 134
135struct irq_host *iic_get_irq_host(int node)
136{
137 if (node < 0 || node >= IIC_NODE_COUNT)
138 return NULL;
139 return iic_hosts[node];
140}
141EXPORT_SYMBOL_GPL(iic_get_irq_host);
142
143
297static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs) 144static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
298{ 145{
299 smp_message_recv(iic_irq_to_ipi(irq), regs); 146 int ipi = (int)(long)dev_id;
147
148 smp_message_recv(ipi, regs);
149
300 return IRQ_HANDLED; 150 return IRQ_HANDLED;
301} 151}
302 152
303static void iic_request_ipi(int ipi, const char *name) 153static void iic_request_ipi(int ipi, const char *name)
304{ 154{
305 int irq; 155 int node, virq;
306 156
307 irq = iic_ipi_to_irq(ipi); 157 for (node = 0; node < IIC_NODE_COUNT; node++) {
308 /* IPIs are marked SA_INTERRUPT as they must run with irqs 158 char *rname;
309 * disabled */ 159 if (iic_hosts[node] == NULL)
310 get_irq_desc(irq)->handler = &iic_pic; 160 continue;
311 get_irq_desc(irq)->status |= IRQ_PER_CPU; 161 virq = irq_create_mapping(iic_hosts[node],
312 request_irq(irq, iic_ipi_action, SA_INTERRUPT, name, NULL); 162 iic_ipi_to_irq(ipi), 0);
163 if (virq == NO_IRQ) {
164 printk(KERN_ERR
165 "iic: failed to map IPI %s on node %d\n",
166 name, node);
167 continue;
168 }
169 rname = kzalloc(strlen(name) + 16, GFP_KERNEL);
170 if (rname)
171 sprintf(rname, "%s node %d", name, node);
172 else
173 rname = (char *)name;
174 if (request_irq(virq, iic_ipi_action, IRQF_DISABLED,
175 rname, (void *)(long)ipi))
176 printk(KERN_ERR
177 "iic: failed to request IPI %s on node %d\n",
178 name, node);
179 }
313} 180}
314 181
315void iic_request_IPIs(void) 182void iic_request_IPIs(void)
@@ -320,34 +187,119 @@ void iic_request_IPIs(void)
320 iic_request_ipi(PPC_MSG_DEBUGGER_BREAK, "IPI-debug"); 187 iic_request_ipi(PPC_MSG_DEBUGGER_BREAK, "IPI-debug");
321#endif /* CONFIG_DEBUGGER */ 188#endif /* CONFIG_DEBUGGER */
322} 189}
190
323#endif /* CONFIG_SMP */ 191#endif /* CONFIG_SMP */
324 192
325static void iic_setup_spe_handlers(void) 193
194static int iic_host_match(struct irq_host *h, struct device_node *node)
195{
196 return h->host_data != NULL && node == h->host_data;
197}
198
199static int iic_host_map(struct irq_host *h, unsigned int virq,
200 irq_hw_number_t hw, unsigned int flags)
201{
202 if (hw < IIC_IRQ_IPI0)
203 set_irq_chip_and_handler(virq, &iic_chip, handle_fasteoi_irq);
204 else
205 set_irq_chip_and_handler(virq, &iic_chip, handle_percpu_irq);
206 return 0;
207}
208
209static int iic_host_xlate(struct irq_host *h, struct device_node *ct,
210 u32 *intspec, unsigned int intsize,
211 irq_hw_number_t *out_hwirq, unsigned int *out_flags)
212
213{
214 /* Currently, we don't translate anything. That needs to be fixed as
215 * we get better defined device-trees. iic interrupts have to be
216 * explicitely mapped by whoever needs them
217 */
218 return -ENODEV;
219}
220
221static struct irq_host_ops iic_host_ops = {
222 .match = iic_host_match,
223 .map = iic_host_map,
224 .xlate = iic_host_xlate,
225};
226
227static void __init init_one_iic(unsigned int hw_cpu, unsigned long addr,
228 struct irq_host *host)
326{ 229{
327 int be, isrc; 230 /* XXX FIXME: should locate the linux CPU number from the HW cpu
231 * number properly. We are lucky for now
232 */
233 struct iic *iic = &per_cpu(iic, hw_cpu);
234
235 iic->regs = ioremap(addr, sizeof(struct cbe_iic_thread_regs));
236 BUG_ON(iic->regs == NULL);
328 237
329 /* Assume two threads per BE are present */ 238 iic->target_id = ((hw_cpu & 2) << 3) | ((hw_cpu & 1) ? 0xf : 0xe);
330 for (be=0; be < num_present_cpus() / 2; be++) { 239 iic->eoi_stack[0] = 0xff;
331 for (isrc = 0; isrc < IIC_CLASS_STRIDE * 3; isrc++) { 240 iic->host = host;
332 int irq = IIC_NODE_STRIDE * be + IIC_SPE_OFFSET + isrc; 241 out_be64(&iic->regs->prio, 0);
333 get_irq_desc(irq)->handler = &iic_pic; 242
243 printk(KERN_INFO "IIC for CPU %d at %lx mapped to %p, target id 0x%x\n",
244 hw_cpu, addr, iic->regs, iic->target_id);
245}
246
247static int __init setup_iic(void)
248{
249 struct device_node *dn;
250 struct resource r0, r1;
251 struct irq_host *host;
252 int found = 0;
253 u32 *np;
254
255 for (dn = NULL;
256 (dn = of_find_node_by_name(dn,"interrupt-controller")) != NULL;) {
257 if (!device_is_compatible(dn,
258 "IBM,CBEA-Internal-Interrupt-Controller"))
259 continue;
260 np = (u32 *)get_property(dn, "ibm,interrupt-server-ranges",
261 NULL);
262 if (np == NULL) {
263 printk(KERN_WARNING "IIC: CPU association not found\n");
264 of_node_put(dn);
265 return -ENODEV;
266 }
267 if (of_address_to_resource(dn, 0, &r0) ||
268 of_address_to_resource(dn, 1, &r1)) {
269 printk(KERN_WARNING "IIC: Can't resolve addresses\n");
270 of_node_put(dn);
271 return -ENODEV;
334 } 272 }
273 host = NULL;
274 if (found < IIC_NODE_COUNT) {
275 host = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
276 IIC_SOURCE_COUNT,
277 &iic_host_ops,
278 IIC_IRQ_INVALID);
279 iic_hosts[found] = host;
280 BUG_ON(iic_hosts[found] == NULL);
281 iic_hosts[found]->host_data = of_node_get(dn);
282 found++;
283 }
284 init_one_iic(np[0], r0.start, host);
285 init_one_iic(np[1], r1.start, host);
335 } 286 }
287
288 if (found)
289 return 0;
290 else
291 return -ENODEV;
336} 292}
337 293
338void iic_init_IRQ(void) 294void __init iic_init_IRQ(void)
339{ 295{
340 int cpu, irq_offset; 296 /* Discover and initialize iics */
341 struct iic *iic;
342
343 if (setup_iic() < 0) 297 if (setup_iic() < 0)
344 setup_iic_hardcoded(); 298 panic("IIC: Failed to initialize !\n");
345 299
346 irq_offset = 0; 300 /* Set master interrupt handling function */
347 for_each_possible_cpu(cpu) { 301 ppc_md.get_irq = iic_get_irq;
348 iic = &per_cpu(iic, cpu); 302
349 if (iic->regs) 303 /* Enable on current CPU */
350 out_be64(&iic->regs->prio, 0xff); 304 iic_setup_cpu();
351 }
352 iic_setup_spe_handlers();
353} 305}
diff --git a/arch/powerpc/platforms/cell/interrupt.h b/arch/powerpc/platforms/cell/interrupt.h
index 799f77d98f96..5560a92ec3ab 100644
--- a/arch/powerpc/platforms/cell/interrupt.h
+++ b/arch/powerpc/platforms/cell/interrupt.h
@@ -37,27 +37,24 @@
37 */ 37 */
38 38
39enum { 39enum {
40 IIC_EXT_OFFSET = 0x00, /* Start of south bridge IRQs */ 40 IIC_IRQ_INVALID = 0xff,
41 IIC_NUM_EXT = 0x40, /* Number of south bridge IRQs */ 41 IIC_IRQ_MAX = 0x3f,
42 IIC_SPE_OFFSET = 0x40, /* Start of SPE interrupts */ 42 IIC_IRQ_EXT_IOIF0 = 0x20,
43 IIC_CLASS_STRIDE = 0x10, /* SPE IRQs per class */ 43 IIC_IRQ_EXT_IOIF1 = 0x2b,
44 IIC_IPI_OFFSET = 0x70, /* Start of IPI IRQs */ 44 IIC_IRQ_IPI0 = 0x40,
45 IIC_NUM_IPIS = 0x10, /* IRQs reserved for IPI */ 45 IIC_NUM_IPIS = 0x10, /* IRQs reserved for IPI */
46 IIC_NODE_STRIDE = 0x80, /* Total IRQs per node */ 46 IIC_SOURCE_COUNT = 0x50,
47}; 47};
48 48
49extern void iic_init_IRQ(void); 49extern void iic_init_IRQ(void);
50extern int iic_get_irq(struct pt_regs *regs);
51extern void iic_cause_IPI(int cpu, int mesg); 50extern void iic_cause_IPI(int cpu, int mesg);
52extern void iic_request_IPIs(void); 51extern void iic_request_IPIs(void);
53extern void iic_setup_cpu(void); 52extern void iic_setup_cpu(void);
54extern void iic_local_enable(void);
55extern void iic_local_disable(void);
56 53
57extern u8 iic_get_target_id(int cpu); 54extern u8 iic_get_target_id(int cpu);
55extern struct irq_host *iic_get_irq_host(int node);
58 56
59extern void spider_init_IRQ(void); 57extern void spider_init_IRQ(void);
60extern int spider_get_irq(int node);
61 58
62#endif 59#endif
63#endif /* ASM_CELL_PIC_H */ 60#endif /* ASM_CELL_PIC_H */
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
index 695ac4e1617e..9f2e4ed20a57 100644
--- a/arch/powerpc/platforms/cell/pervasive.c
+++ b/arch/powerpc/platforms/cell/pervasive.c
@@ -23,7 +23,6 @@
23 23
24#undef DEBUG 24#undef DEBUG
25 25
26#include <linux/config.h>
27#include <linux/interrupt.h> 26#include <linux/interrupt.h>
28#include <linux/irq.h> 27#include <linux/irq.h>
29#include <linux/percpu.h> 28#include <linux/percpu.h>
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index 3d1831d331e5..282987d6d4a2 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -14,7 +14,6 @@
14 */ 14 */
15#undef DEBUG 15#undef DEBUG
16 16
17#include <linux/config.h>
18#include <linux/sched.h> 17#include <linux/sched.h>
19#include <linux/kernel.h> 18#include <linux/kernel.h>
20#include <linux/mm.h> 19#include <linux/mm.h>
@@ -50,6 +49,7 @@
50#include <asm/irq.h> 49#include <asm/irq.h>
51#include <asm/spu.h> 50#include <asm/spu.h>
52#include <asm/spu_priv1.h> 51#include <asm/spu_priv1.h>
52#include <asm/udbg.h>
53 53
54#include "interrupt.h" 54#include "interrupt.h"
55#include "iommu.h" 55#include "iommu.h"
@@ -80,10 +80,22 @@ static void cell_progress(char *s, unsigned short hex)
80 printk("*** %04x : %s\n", hex, s ? s : ""); 80 printk("*** %04x : %s\n", hex, s ? s : "");
81} 81}
82 82
83static void __init cell_pcibios_fixup(void)
84{
85 struct pci_dev *dev = NULL;
86
87 for_each_pci_dev(dev)
88 pci_read_irq_line(dev);
89}
90
91static void __init cell_init_irq(void)
92{
93 iic_init_IRQ();
94 spider_init_IRQ();
95}
96
83static void __init cell_setup_arch(void) 97static void __init cell_setup_arch(void)
84{ 98{
85 ppc_md.init_IRQ = iic_init_IRQ;
86 ppc_md.get_irq = iic_get_irq;
87#ifdef CONFIG_SPU_BASE 99#ifdef CONFIG_SPU_BASE
88 spu_priv1_ops = &spu_priv1_mmio_ops; 100 spu_priv1_ops = &spu_priv1_mmio_ops;
89#endif 101#endif
@@ -109,7 +121,6 @@ static void __init cell_setup_arch(void)
109 /* Find and initialize PCI host bridges */ 121 /* Find and initialize PCI host bridges */
110 init_pci_config_tokens(); 122 init_pci_config_tokens();
111 find_and_init_phbs(); 123 find_and_init_phbs();
112 spider_init_IRQ();
113 cbe_pervasive_init(); 124 cbe_pervasive_init();
114#ifdef CONFIG_DUMMY_CONSOLE 125#ifdef CONFIG_DUMMY_CONSOLE
115 conswitchp = &dummy_con; 126 conswitchp = &dummy_con;
@@ -125,12 +136,8 @@ static void __init cell_init_early(void)
125{ 136{
126 DBG(" -> cell_init_early()\n"); 137 DBG(" -> cell_init_early()\n");
127 138
128 hpte_init_native();
129
130 cell_init_iommu(); 139 cell_init_iommu();
131 140
132 ppc64_interrupt_controller = IC_CELL_PIC;
133
134 DBG(" <- cell_init_early()\n"); 141 DBG(" <- cell_init_early()\n");
135} 142}
136 143
@@ -139,11 +146,17 @@ static int __init cell_probe(void)
139{ 146{
140 unsigned long root = of_get_flat_dt_root(); 147 unsigned long root = of_get_flat_dt_root();
141 148
142 if (of_flat_dt_is_compatible(root, "IBM,CBEA") || 149 if (!of_flat_dt_is_compatible(root, "IBM,CBEA") &&
143 of_flat_dt_is_compatible(root, "IBM,CPBW-1.0")) 150 !of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
144 return 1; 151 return 0;
152
153#ifdef CONFIG_UDBG_RTAS_CONSOLE
154 udbg_init_rtas_console();
155#endif
156
157 hpte_init_native();
145 158
146 return 0; 159 return 1;
147} 160}
148 161
149/* 162/*
@@ -170,6 +183,8 @@ define_machine(cell) {
170 .calibrate_decr = generic_calibrate_decr, 183 .calibrate_decr = generic_calibrate_decr,
171 .check_legacy_ioport = cell_check_legacy_ioport, 184 .check_legacy_ioport = cell_check_legacy_ioport,
172 .progress = cell_progress, 185 .progress = cell_progress,
186 .init_IRQ = cell_init_irq,
187 .pcibios_fixup = cell_pcibios_fixup,
173#ifdef CONFIG_KEXEC 188#ifdef CONFIG_KEXEC
174 .machine_kexec = default_machine_kexec, 189 .machine_kexec = default_machine_kexec,
175 .machine_kexec_prepare = default_machine_kexec_prepare, 190 .machine_kexec_prepare = default_machine_kexec_prepare,
diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c
index bdf6c5fe58c0..46aef0640742 100644
--- a/arch/powerpc/platforms/cell/smp.c
+++ b/arch/powerpc/platforms/cell/smp.c
@@ -14,7 +14,6 @@
14 14
15#undef DEBUG 15#undef DEBUG
16 16
17#include <linux/config.h>
18#include <linux/kernel.h> 17#include <linux/kernel.h>
19#include <linux/module.h> 18#include <linux/module.h>
20#include <linux/sched.h> 19#include <linux/sched.h>
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index 55cbdd77a62d..ae7ef88f1a37 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -22,6 +22,7 @@
22 22
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/irq.h> 24#include <linux/irq.h>
25#include <linux/ioport.h>
25 26
26#include <asm/pgtable.h> 27#include <asm/pgtable.h>
27#include <asm/prom.h> 28#include <asm/prom.h>
@@ -56,184 +57,313 @@ enum {
56 REISWAITEN = 0x508, /* Reissue Wait Control*/ 57 REISWAITEN = 0x508, /* Reissue Wait Control*/
57}; 58};
58 59
59static void __iomem *spider_pics[4]; 60#define SPIDER_CHIP_COUNT 4
61#define SPIDER_SRC_COUNT 64
62#define SPIDER_IRQ_INVALID 63
60 63
61static void __iomem *spider_get_pic(int irq) 64struct spider_pic {
62{ 65 struct irq_host *host;
63 int node = irq / IIC_NODE_STRIDE; 66 struct device_node *of_node;
64 irq %= IIC_NODE_STRIDE; 67 void __iomem *regs;
65 68 unsigned int node_id;
66 if (irq >= IIC_EXT_OFFSET && 69};
67 irq < IIC_EXT_OFFSET + IIC_NUM_EXT && 70static struct spider_pic spider_pics[SPIDER_CHIP_COUNT];
68 spider_pics)
69 return spider_pics[node];
70 return NULL;
71}
72 71
73static int spider_get_nr(unsigned int irq) 72static struct spider_pic *spider_virq_to_pic(unsigned int virq)
74{ 73{
75 return (irq % IIC_NODE_STRIDE) - IIC_EXT_OFFSET; 74 return irq_map[virq].host->host_data;
76} 75}
77 76
78static void __iomem *spider_get_irq_config(int irq) 77static void __iomem *spider_get_irq_config(struct spider_pic *pic,
78 unsigned int src)
79{ 79{
80 void __iomem *pic; 80 return pic->regs + TIR_CFGA + 8 * src;
81 pic = spider_get_pic(irq);
82 return pic + TIR_CFGA + 8 * spider_get_nr(irq);
83} 81}
84 82
85static void spider_enable_irq(unsigned int irq) 83static void spider_unmask_irq(unsigned int virq)
86{ 84{
87 int nodeid = (irq / IIC_NODE_STRIDE) * 0x10; 85 struct spider_pic *pic = spider_virq_to_pic(virq);
88 void __iomem *cfg = spider_get_irq_config(irq); 86 void __iomem *cfg = spider_get_irq_config(pic, irq_map[virq].hwirq);
89 irq = spider_get_nr(irq);
90 87
91 out_be32(cfg, (in_be32(cfg) & ~0xf0)| 0x3107000eu | nodeid); 88 /* We use no locking as we should be covered by the descriptor lock
92 out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq); 89 * for access to invidual source configuration registers
90 */
91 out_be32(cfg, in_be32(cfg) | 0x30000000u);
93} 92}
94 93
95static void spider_disable_irq(unsigned int irq) 94static void spider_mask_irq(unsigned int virq)
96{ 95{
97 void __iomem *cfg = spider_get_irq_config(irq); 96 struct spider_pic *pic = spider_virq_to_pic(virq);
98 irq = spider_get_nr(irq); 97 void __iomem *cfg = spider_get_irq_config(pic, irq_map[virq].hwirq);
99 98
99 /* We use no locking as we should be covered by the descriptor lock
100 * for access to invidual source configuration registers
101 */
100 out_be32(cfg, in_be32(cfg) & ~0x30000000u); 102 out_be32(cfg, in_be32(cfg) & ~0x30000000u);
101} 103}
102 104
103static unsigned int spider_startup_irq(unsigned int irq) 105static void spider_ack_irq(unsigned int virq)
104{ 106{
105 spider_enable_irq(irq); 107 struct spider_pic *pic = spider_virq_to_pic(virq);
106 return 0; 108 unsigned int src = irq_map[virq].hwirq;
107}
108 109
109static void spider_shutdown_irq(unsigned int irq) 110 /* Reset edge detection logic if necessary
110{ 111 */
111 spider_disable_irq(irq); 112 if (get_irq_desc(virq)->status & IRQ_LEVEL)
112} 113 return;
113 114
114static void spider_end_irq(unsigned int irq) 115 /* Only interrupts 47 to 50 can be set to edge */
115{ 116 if (src < 47 || src > 50)
116 spider_enable_irq(irq); 117 return;
117}
118 118
119static void spider_ack_irq(unsigned int irq) 119 /* Perform the clear of the edge logic */
120{ 120 out_be32(pic->regs + TIR_EDC, 0x100 | (src & 0xf));
121 spider_disable_irq(irq);
122 iic_local_enable();
123} 121}
124 122
125static struct hw_interrupt_type spider_pic = { 123static struct irq_chip spider_pic = {
126 .typename = " SPIDER ", 124 .typename = " SPIDER ",
127 .startup = spider_startup_irq, 125 .unmask = spider_unmask_irq,
128 .shutdown = spider_shutdown_irq, 126 .mask = spider_mask_irq,
129 .enable = spider_enable_irq,
130 .disable = spider_disable_irq,
131 .ack = spider_ack_irq, 127 .ack = spider_ack_irq,
132 .end = spider_end_irq,
133}; 128};
134 129
135int spider_get_irq(int node) 130static int spider_host_match(struct irq_host *h, struct device_node *node)
136{ 131{
137 unsigned long cs; 132 struct spider_pic *pic = h->host_data;
138 void __iomem *regs = spider_pics[node]; 133 return node == pic->of_node;
139
140 cs = in_be32(regs + TIR_CS) >> 24;
141
142 if (cs == 63)
143 return -1;
144 else
145 return cs;
146} 134}
147 135
148/* hardcoded part to be compatible with older firmware */ 136static int spider_host_map(struct irq_host *h, unsigned int virq,
149 137 irq_hw_number_t hw, unsigned int flags)
150void spider_init_IRQ_hardcoded(void)
151{ 138{
152 int node; 139 unsigned int sense = flags & IRQ_TYPE_SENSE_MASK;
153 long spiderpic; 140 struct spider_pic *pic = h->host_data;
154 long pics[] = { 0x24000008000, 0x34000008000 }; 141 void __iomem *cfg = spider_get_irq_config(pic, hw);
155 int n; 142 int level = 0;
156 143 u32 ic;
157 pr_debug("%s(%d): Using hardcoded defaults\n", __FUNCTION__, __LINE__); 144
158 145 /* Note that only level high is supported for most interrupts */
159 for (node = 0; node < num_present_cpus()/2; node++) { 146 if (sense != IRQ_TYPE_NONE && sense != IRQ_TYPE_LEVEL_HIGH &&
160 spiderpic = pics[node]; 147 (hw < 47 || hw > 50))
161 printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic); 148 return -EINVAL;
162 spider_pics[node] = ioremap(spiderpic, 0x800); 149
163 for (n = 0; n < IIC_NUM_EXT; n++) { 150 /* Decode sense type */
164 int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE; 151 switch(sense) {
165 get_irq_desc(irq)->handler = &spider_pic; 152 case IRQ_TYPE_EDGE_RISING:
166 } 153 ic = 0x3;
167 154 break;
168 /* do not mask any interrupts because of level */ 155 case IRQ_TYPE_EDGE_FALLING:
169 out_be32(spider_pics[node] + TIR_MSK, 0x0); 156 ic = 0x2;
170 157 break;
171 /* disable edge detection clear */ 158 case IRQ_TYPE_LEVEL_LOW:
172 /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */ 159 ic = 0x0;
173 160 level = 1;
174 /* enable interrupt packets to be output */ 161 break;
175 out_be32(spider_pics[node] + TIR_PIEN, 162 case IRQ_TYPE_LEVEL_HIGH:
176 in_be32(spider_pics[node] + TIR_PIEN) | 0x1); 163 case IRQ_TYPE_NONE:
177 164 ic = 0x1;
178 /* Enable the interrupt detection enable bit. Do this last! */ 165 level = 1;
179 out_be32(spider_pics[node] + TIR_DEN, 166 break;
180 in_be32(spider_pics[node] + TIR_DEN) | 0x1); 167 default:
168 return -EINVAL;
181 } 169 }
182}
183 170
184void spider_init_IRQ(void) 171 /* Configure the source. One gross hack that was there before and
185{ 172 * that I've kept around is the priority to the BE which I set to
186 long spider_reg; 173 * be the same as the interrupt source number. I don't know wether
187 struct device_node *dn; 174 * that's supposed to make any kind of sense however, we'll have to
188 char *compatible; 175 * decide that, but for now, I'm not changing the behaviour.
189 int n, node = 0; 176 */
177 out_be32(cfg, (ic << 24) | (0x7 << 16) | (pic->node_id << 4) | 0xe);
178 out_be32(cfg + 4, (0x2 << 16) | (hw & 0xff));
179
180 if (level)
181 get_irq_desc(virq)->status |= IRQ_LEVEL;
182 set_irq_chip_and_handler(virq, &spider_pic, handle_level_irq);
183 return 0;
184}
190 185
191 for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) { 186static int spider_host_xlate(struct irq_host *h, struct device_node *ct,
192 compatible = (char *)get_property(dn, "compatible", NULL); 187 u32 *intspec, unsigned int intsize,
188 irq_hw_number_t *out_hwirq, unsigned int *out_flags)
193 189
194 if (!compatible) 190{
195 continue; 191 /* Spider interrupts have 2 cells, first is the interrupt source,
192 * second, well, I don't know for sure yet ... We mask the top bits
193 * because old device-trees encode a node number in there
194 */
195 *out_hwirq = intspec[0] & 0x3f;
196 *out_flags = IRQ_TYPE_LEVEL_HIGH;
197 return 0;
198}
196 199
197 if (strstr(compatible, "CBEA,platform-spider-pic")) 200static struct irq_host_ops spider_host_ops = {
198 spider_reg = *(long *)get_property(dn,"reg", NULL); 201 .match = spider_host_match,
199 else if (strstr(compatible, "sti,platform-spider-pic")) { 202 .map = spider_host_map,
200 spider_init_IRQ_hardcoded(); 203 .xlate = spider_host_xlate,
201 return; 204};
202 } else
203 continue;
204 205
205 if (!spider_reg) 206static void spider_irq_cascade(unsigned int irq, struct irq_desc *desc,
206 printk("interrupt controller does not have reg property !\n"); 207 struct pt_regs *regs)
208{
209 struct spider_pic *pic = desc->handler_data;
210 unsigned int cs, virq;
207 211
208 n = prom_n_addr_cells(dn); 212 cs = in_be32(pic->regs + TIR_CS) >> 24;
213 if (cs == SPIDER_IRQ_INVALID)
214 virq = NO_IRQ;
215 else
216 virq = irq_linear_revmap(pic->host, cs);
217 if (virq != NO_IRQ)
218 generic_handle_irq(virq, regs);
219 desc->chip->eoi(irq);
220}
209 221
210 if ( n != 2) 222/* For hooking up the cascace we have a problem. Our device-tree is
211 printk("reg property with invalid number of elements \n"); 223 * crap and we don't know on which BE iic interrupt we are hooked on at
224 * least not the "standard" way. We can reconstitute it based on two
225 * informations though: which BE node we are connected to and wether
226 * we are connected to IOIF0 or IOIF1. Right now, we really only care
227 * about the IBM cell blade and we know that its firmware gives us an
228 * interrupt-map property which is pretty strange.
229 */
230static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic)
231{
232 unsigned int virq;
233 u32 *imap, *tmp;
234 int imaplen, intsize, unit;
235 struct device_node *iic;
236 struct irq_host *iic_host;
237
238#if 0 /* Enable that when we have a way to retreive the node as well */
239 /* First, we check wether we have a real "interrupts" in the device
240 * tree in case the device-tree is ever fixed
241 */
242 struct of_irq oirq;
243 if (of_irq_map_one(pic->of_node, 0, &oirq) == 0) {
244 virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
245 oirq.size);
246 goto bail;
247 }
248#endif
249
250 /* Now do the horrible hacks */
251 tmp = (u32 *)get_property(pic->of_node, "#interrupt-cells", NULL);
252 if (tmp == NULL)
253 return NO_IRQ;
254 intsize = *tmp;
255 imap = (u32 *)get_property(pic->of_node, "interrupt-map", &imaplen);
256 if (imap == NULL || imaplen < (intsize + 1))
257 return NO_IRQ;
258 iic = of_find_node_by_phandle(imap[intsize]);
259 if (iic == NULL)
260 return NO_IRQ;
261 imap += intsize + 1;
262 tmp = (u32 *)get_property(iic, "#interrupt-cells", NULL);
263 if (tmp == NULL)
264 return NO_IRQ;
265 intsize = *tmp;
266 /* Assume unit is last entry of interrupt specifier */
267 unit = imap[intsize - 1];
268 /* Ok, we have a unit, now let's try to get the node */
269 tmp = (u32 *)get_property(iic, "ibm,interrupt-server-ranges", NULL);
270 if (tmp == NULL) {
271 of_node_put(iic);
272 return NO_IRQ;
273 }
274 /* ugly as hell but works for now */
275 pic->node_id = (*tmp) >> 1;
276 of_node_put(iic);
277
278 /* Ok, now let's get cracking. You may ask me why I just didn't match
279 * the iic host from the iic OF node, but that way I'm still compatible
280 * with really really old old firmwares for which we don't have a node
281 */
282 iic_host = iic_get_irq_host(pic->node_id);
283 if (iic_host == NULL)
284 return NO_IRQ;
285 /* Manufacture an IIC interrupt number of class 2 */
286 virq = irq_create_mapping(iic_host, 0x20 | unit, 0);
287 if (virq == NO_IRQ)
288 printk(KERN_ERR "spider_pic: failed to map cascade !");
289 return virq;
290}
212 291
213 spider_pics[node] = ioremap(spider_reg, 0x800);
214 292
215 printk("SPIDER addr: %lx with %i addr_cells mapped to %p\n", 293static void __init spider_init_one(struct device_node *of_node, int chip,
216 spider_reg, n, spider_pics[node]); 294 unsigned long addr)
295{
296 struct spider_pic *pic = &spider_pics[chip];
297 int i, virq;
298
299 /* Map registers */
300 pic->regs = ioremap(addr, 0x1000);
301 if (pic->regs == NULL)
302 panic("spider_pic: can't map registers !");
303
304 /* Allocate a host */
305 pic->host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, SPIDER_SRC_COUNT,
306 &spider_host_ops, SPIDER_IRQ_INVALID);
307 if (pic->host == NULL)
308 panic("spider_pic: can't allocate irq host !");
309 pic->host->host_data = pic;
310
311 /* Fill out other bits */
312 pic->of_node = of_node_get(of_node);
313
314 /* Go through all sources and disable them */
315 for (i = 0; i < SPIDER_SRC_COUNT; i++) {
316 void __iomem *cfg = pic->regs + TIR_CFGA + 8 * i;
317 out_be32(cfg, in_be32(cfg) & ~0x30000000u);
318 }
217 319
218 for (n = 0; n < IIC_NUM_EXT; n++) { 320 /* do not mask any interrupts because of level */
219 int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE; 321 out_be32(pic->regs + TIR_MSK, 0x0);
220 get_irq_desc(irq)->handler = &spider_pic;
221 }
222 322
223 /* do not mask any interrupts because of level */ 323 /* enable interrupt packets to be output */
224 out_be32(spider_pics[node] + TIR_MSK, 0x0); 324 out_be32(pic->regs + TIR_PIEN, in_be32(pic->regs + TIR_PIEN) | 0x1);
225 325
226 /* disable edge detection clear */ 326 /* Hook up the cascade interrupt to the iic and nodeid */
227 /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */ 327 virq = spider_find_cascade_and_node(pic);
328 if (virq == NO_IRQ)
329 return;
330 set_irq_data(virq, pic);
331 set_irq_chained_handler(virq, spider_irq_cascade);
228 332
229 /* enable interrupt packets to be output */ 333 printk(KERN_INFO "spider_pic: node %d, addr: 0x%lx %s\n",
230 out_be32(spider_pics[node] + TIR_PIEN, 334 pic->node_id, addr, of_node->full_name);
231 in_be32(spider_pics[node] + TIR_PIEN) | 0x1);
232 335
233 /* Enable the interrupt detection enable bit. Do this last! */ 336 /* Enable the interrupt detection enable bit. Do this last! */
234 out_be32(spider_pics[node] + TIR_DEN, 337 out_be32(pic->regs + TIR_DEN, in_be32(pic->regs + TIR_DEN) | 0x1);
235 in_be32(spider_pics[node] + TIR_DEN) | 0x1); 338}
236 339
237 node++; 340void __init spider_init_IRQ(void)
341{
342 struct resource r;
343 struct device_node *dn;
344 int chip = 0;
345
346 /* XXX node numbers are totally bogus. We _hope_ we get the device
347 * nodes in the right order here but that's definitely not guaranteed,
348 * we need to get the node from the device tree instead.
349 * There is currently no proper property for it (but our whole
350 * device-tree is bogus anyway) so all we can do is pray or maybe test
351 * the address and deduce the node-id
352 */
353 for (dn = NULL;
354 (dn = of_find_node_by_name(dn, "interrupt-controller"));) {
355 if (device_is_compatible(dn, "CBEA,platform-spider-pic")) {
356 if (of_address_to_resource(dn, 0, &r)) {
357 printk(KERN_WARNING "spider-pic: Failed\n");
358 continue;
359 }
360 } else if (device_is_compatible(dn, "sti,platform-spider-pic")
361 && (chip < 2)) {
362 static long hard_coded_pics[] =
363 { 0x24000008000, 0x34000008000 };
364 r.start = hard_coded_pics[chip];
365 } else
366 continue;
367 spider_init_one(dn, chip++, r.start);
238 } 368 }
239} 369}
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index db82f503ba2c..5d2313a6c82b 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -168,12 +168,12 @@ spu_irq_class_0_bottom(struct spu *spu)
168 168
169 stat &= mask; 169 stat &= mask;
170 170
171 if (stat & 1) /* invalid MFC DMA */ 171 if (stat & 1) /* invalid DMA alignment */
172 __spu_trap_invalid_dma(spu);
173
174 if (stat & 2) /* invalid DMA alignment */
175 __spu_trap_dma_align(spu); 172 __spu_trap_dma_align(spu);
176 173
174 if (stat & 2) /* invalid MFC DMA */
175 __spu_trap_invalid_dma(spu);
176
177 if (stat & 4) /* error on SPU */ 177 if (stat & 4) /* error on SPU */
178 __spu_trap_error(spu); 178 __spu_trap_error(spu);
179 179
@@ -264,51 +264,57 @@ spu_irq_class_2(int irq, void *data, struct pt_regs *regs)
264 return stat ? IRQ_HANDLED : IRQ_NONE; 264 return stat ? IRQ_HANDLED : IRQ_NONE;
265} 265}
266 266
267static int 267static int spu_request_irqs(struct spu *spu)
268spu_request_irqs(struct spu *spu)
269{ 268{
270 int ret; 269 int ret = 0;
271 int irq_base;
272
273 irq_base = IIC_NODE_STRIDE * spu->node + IIC_SPE_OFFSET;
274
275 snprintf(spu->irq_c0, sizeof (spu->irq_c0), "spe%02d.0", spu->number);
276 ret = request_irq(irq_base + spu->isrc,
277 spu_irq_class_0, SA_INTERRUPT, spu->irq_c0, spu);
278 if (ret)
279 goto out;
280
281 snprintf(spu->irq_c1, sizeof (spu->irq_c1), "spe%02d.1", spu->number);
282 ret = request_irq(irq_base + IIC_CLASS_STRIDE + spu->isrc,
283 spu_irq_class_1, SA_INTERRUPT, spu->irq_c1, spu);
284 if (ret)
285 goto out1;
286 270
287 snprintf(spu->irq_c2, sizeof (spu->irq_c2), "spe%02d.2", spu->number); 271 if (spu->irqs[0] != NO_IRQ) {
288 ret = request_irq(irq_base + 2*IIC_CLASS_STRIDE + spu->isrc, 272 snprintf(spu->irq_c0, sizeof (spu->irq_c0), "spe%02d.0",
289 spu_irq_class_2, SA_INTERRUPT, spu->irq_c2, spu); 273 spu->number);
290 if (ret) 274 ret = request_irq(spu->irqs[0], spu_irq_class_0,
291 goto out2; 275 IRQF_DISABLED,
292 goto out; 276 spu->irq_c0, spu);
277 if (ret)
278 goto bail0;
279 }
280 if (spu->irqs[1] != NO_IRQ) {
281 snprintf(spu->irq_c1, sizeof (spu->irq_c1), "spe%02d.1",
282 spu->number);
283 ret = request_irq(spu->irqs[1], spu_irq_class_1,
284 IRQF_DISABLED,
285 spu->irq_c1, spu);
286 if (ret)
287 goto bail1;
288 }
289 if (spu->irqs[2] != NO_IRQ) {
290 snprintf(spu->irq_c2, sizeof (spu->irq_c2), "spe%02d.2",
291 spu->number);
292 ret = request_irq(spu->irqs[2], spu_irq_class_2,
293 IRQF_DISABLED,
294 spu->irq_c2, spu);
295 if (ret)
296 goto bail2;
297 }
298 return 0;
293 299
294out2: 300bail2:
295 free_irq(irq_base + IIC_CLASS_STRIDE + spu->isrc, spu); 301 if (spu->irqs[1] != NO_IRQ)
296out1: 302 free_irq(spu->irqs[1], spu);
297 free_irq(irq_base + spu->isrc, spu); 303bail1:
298out: 304 if (spu->irqs[0] != NO_IRQ)
305 free_irq(spu->irqs[0], spu);
306bail0:
299 return ret; 307 return ret;
300} 308}
301 309
302static void 310static void spu_free_irqs(struct spu *spu)
303spu_free_irqs(struct spu *spu)
304{ 311{
305 int irq_base; 312 if (spu->irqs[0] != NO_IRQ)
306 313 free_irq(spu->irqs[0], spu);
307 irq_base = IIC_NODE_STRIDE * spu->node + IIC_SPE_OFFSET; 314 if (spu->irqs[1] != NO_IRQ)
308 315 free_irq(spu->irqs[1], spu);
309 free_irq(irq_base + spu->isrc, spu); 316 if (spu->irqs[2] != NO_IRQ)
310 free_irq(irq_base + IIC_CLASS_STRIDE + spu->isrc, spu); 317 free_irq(spu->irqs[2], spu);
311 free_irq(irq_base + 2*IIC_CLASS_STRIDE + spu->isrc, spu);
312} 318}
313 319
314static LIST_HEAD(spu_list); 320static LIST_HEAD(spu_list);
@@ -559,17 +565,38 @@ static void spu_unmap(struct spu *spu)
559 iounmap((u8 __iomem *)spu->local_store); 565 iounmap((u8 __iomem *)spu->local_store);
560} 566}
561 567
568/* This function shall be abstracted for HV platforms */
569static int __init spu_map_interrupts(struct spu *spu, struct device_node *np)
570{
571 struct irq_host *host;
572 unsigned int isrc;
573 u32 *tmp;
574
575 host = iic_get_irq_host(spu->node);
576 if (host == NULL)
577 return -ENODEV;
578
579 /* Get the interrupt source from the device-tree */
580 tmp = (u32 *)get_property(np, "isrc", NULL);
581 if (!tmp)
582 return -ENODEV;
583 spu->isrc = isrc = tmp[0];
584
585 /* Now map interrupts of all 3 classes */
586 spu->irqs[0] = irq_create_mapping(host, 0x00 | isrc, 0);
587 spu->irqs[1] = irq_create_mapping(host, 0x10 | isrc, 0);
588 spu->irqs[2] = irq_create_mapping(host, 0x20 | isrc, 0);
589
590 /* Right now, we only fail if class 2 failed */
591 return spu->irqs[2] == NO_IRQ ? -EINVAL : 0;
592}
593
562static int __init spu_map_device(struct spu *spu, struct device_node *node) 594static int __init spu_map_device(struct spu *spu, struct device_node *node)
563{ 595{
564 char *prop; 596 char *prop;
565 int ret; 597 int ret;
566 598
567 ret = -ENODEV; 599 ret = -ENODEV;
568 prop = get_property(node, "isrc", NULL);
569 if (!prop)
570 goto out;
571 spu->isrc = *(unsigned int *)prop;
572
573 spu->name = get_property(node, "name", NULL); 600 spu->name = get_property(node, "name", NULL);
574 if (!spu->name) 601 if (!spu->name)
575 goto out; 602 goto out;
@@ -636,7 +663,8 @@ static int spu_create_sysdev(struct spu *spu)
636 return ret; 663 return ret;
637 } 664 }
638 665
639 sysdev_create_file(&spu->sysdev, &attr_isrc); 666 if (spu->isrc != 0)
667 sysdev_create_file(&spu->sysdev, &attr_isrc);
640 sysfs_add_device_to_node(&spu->sysdev, spu->nid); 668 sysfs_add_device_to_node(&spu->sysdev, spu->nid);
641 669
642 return 0; 670 return 0;
@@ -668,6 +696,9 @@ static int __init create_spu(struct device_node *spe)
668 spu->nid = of_node_to_nid(spe); 696 spu->nid = of_node_to_nid(spe);
669 if (spu->nid == -1) 697 if (spu->nid == -1)
670 spu->nid = 0; 698 spu->nid = 0;
699 ret = spu_map_interrupts(spu, spe);
700 if (ret)
701 goto out_unmap;
671 spin_lock_init(&spu->register_lock); 702 spin_lock_init(&spu->register_lock);
672 spu_mfc_sdr_set(spu, mfspr(SPRN_SDR1)); 703 spu_mfc_sdr_set(spu, mfspr(SPRN_SDR1));
673 spu_mfc_sr1_set(spu, 0x33); 704 spu_mfc_sr1_set(spu, 0x33);
diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c
index f1d35ddc9df3..2d22cd59d6fc 100644
--- a/arch/powerpc/platforms/cell/spufs/backing_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c
@@ -21,7 +21,6 @@
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */ 22 */
23 23
24#include <linux/config.h>
25#include <linux/module.h> 24#include <linux/module.h>
26#include <linux/errno.h> 25#include <linux/errno.h>
27#include <linux/sched.h> 26#include <linux/sched.h>
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 7854a380dce2..58e794f9da1b 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -204,7 +204,7 @@ static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma)
204 204
205 vma->vm_flags |= VM_RESERVED; 205 vma->vm_flags |= VM_RESERVED;
206 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 206 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
207 | _PAGE_NO_CACHE); 207 | _PAGE_NO_CACHE | _PAGE_GUARDED);
208 208
209 vma->vm_ops = &spufs_cntl_mmap_vmops; 209 vma->vm_ops = &spufs_cntl_mmap_vmops;
210 return 0; 210 return 0;
@@ -675,7 +675,7 @@ static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma)
675 675
676 vma->vm_flags |= VM_RESERVED; 676 vma->vm_flags |= VM_RESERVED;
677 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 677 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
678 | _PAGE_NO_CACHE); 678 | _PAGE_NO_CACHE | _PAGE_GUARDED);
679 679
680 vma->vm_ops = &spufs_signal1_mmap_vmops; 680 vma->vm_ops = &spufs_signal1_mmap_vmops;
681 return 0; 681 return 0;
@@ -762,7 +762,7 @@ static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma)
762 /* FIXME: */ 762 /* FIXME: */
763 vma->vm_flags |= VM_RESERVED; 763 vma->vm_flags |= VM_RESERVED;
764 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 764 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
765 | _PAGE_NO_CACHE); 765 | _PAGE_NO_CACHE | _PAGE_GUARDED);
766 766
767 vma->vm_ops = &spufs_signal2_mmap_vmops; 767 vma->vm_ops = &spufs_signal2_mmap_vmops;
768 return 0; 768 return 0;
@@ -850,7 +850,7 @@ static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma)
850 850
851 vma->vm_flags |= VM_RESERVED; 851 vma->vm_flags |= VM_RESERVED;
852 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 852 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
853 | _PAGE_NO_CACHE); 853 | _PAGE_NO_CACHE | _PAGE_GUARDED);
854 854
855 vma->vm_ops = &spufs_mss_mmap_vmops; 855 vma->vm_ops = &spufs_mss_mmap_vmops;
856 return 0; 856 return 0;
@@ -899,7 +899,7 @@ static int spufs_mfc_mmap(struct file *file, struct vm_area_struct *vma)
899 899
900 vma->vm_flags |= VM_RESERVED; 900 vma->vm_flags |= VM_RESERVED;
901 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 901 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
902 | _PAGE_NO_CACHE); 902 | _PAGE_NO_CACHE | _PAGE_GUARDED);
903 903
904 vma->vm_ops = &spufs_mfc_mmap_vmops; 904 vma->vm_ops = &spufs_mfc_mmap_vmops;
905 return 0; 905 return 0;
diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c
index ede2cac46b6d..c8670f519734 100644
--- a/arch/powerpc/platforms/cell/spufs/hw_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c
@@ -18,7 +18,6 @@
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */ 19 */
20 20
21#include <linux/config.h>
22#include <linux/module.h> 21#include <linux/module.h>
23#include <linux/errno.h> 22#include <linux/errno.h>
24#include <linux/sched.h> 23#include <linux/sched.h>
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 3dcc5d8d66b9..1350294484b6 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -26,7 +26,6 @@
26 26
27#undef DEBUG 27#undef DEBUG
28 28
29#include <linux/config.h>
30#include <linux/module.h> 29#include <linux/module.h>
31#include <linux/errno.h> 30#include <linux/errno.h>
32#include <linux/sched.h> 31#include <linux/sched.h>
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index b30e55dab832..9d9d82dd32ba 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -32,7 +32,6 @@
32 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 32 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33 */ 33 */
34 34
35#include <linux/config.h>
36#include <linux/module.h> 35#include <linux/module.h>
37#include <linux/errno.h> 36#include <linux/errno.h>
38#include <linux/sched.h> 37#include <linux/sched.h>
@@ -464,7 +463,8 @@ static inline void wait_purge_complete(struct spu_state *csa, struct spu *spu)
464 * Poll MFC_CNTL[Ps] until value '11' is read 463 * Poll MFC_CNTL[Ps] until value '11' is read
465 * (purge complete). 464 * (purge complete).
466 */ 465 */
467 POLL_WHILE_FALSE(in_be64(&priv2->mfc_control_RW) & 466 POLL_WHILE_FALSE((in_be64(&priv2->mfc_control_RW) &
467 MFC_CNTL_PURGE_DMA_STATUS_MASK) ==
468 MFC_CNTL_PURGE_DMA_COMPLETE); 468 MFC_CNTL_PURGE_DMA_COMPLETE);
469} 469}
470 470
@@ -1028,7 +1028,8 @@ static inline void wait_suspend_mfc_complete(struct spu_state *csa,
1028 * Restore, Step 47. 1028 * Restore, Step 47.
1029 * Poll MFC_CNTL[Ss] until 11 is returned. 1029 * Poll MFC_CNTL[Ss] until 11 is returned.
1030 */ 1030 */
1031 POLL_WHILE_FALSE(in_be64(&priv2->mfc_control_RW) & 1031 POLL_WHILE_FALSE((in_be64(&priv2->mfc_control_RW) &
1032 MFC_CNTL_SUSPEND_DMA_STATUS_MASK) ==
1032 MFC_CNTL_SUSPEND_COMPLETE); 1033 MFC_CNTL_SUSPEND_COMPLETE);
1033} 1034}
1034 1035
@@ -2100,7 +2101,7 @@ EXPORT_SYMBOL_GPL(spu_save);
2100 * @spu: pointer to SPU iomem structure. 2101 * @spu: pointer to SPU iomem structure.
2101 * 2102 *
2102 * Perform harvest + restore, as we may not be coming 2103 * Perform harvest + restore, as we may not be coming
2103 * from a previous succesful save operation, and the 2104 * from a previous successful save operation, and the
2104 * hardware state is unknown. 2105 * hardware state is unknown.
2105 */ 2106 */
2106int spu_restore(struct spu_state *new, struct spu *spu) 2107int spu_restore(struct spu_state *new, struct spu *spu)
@@ -2203,7 +2204,7 @@ void spu_init_csa(struct spu_state *csa)
2203 2204
2204 memset(lscsa, 0, sizeof(struct spu_lscsa)); 2205 memset(lscsa, 0, sizeof(struct spu_lscsa));
2205 csa->lscsa = lscsa; 2206 csa->lscsa = lscsa;
2206 csa->register_lock = SPIN_LOCK_UNLOCKED; 2207 spin_lock_init(&csa->register_lock);
2207 2208
2208 /* Set LS pages reserved to allow for user-space mapping. */ 2209 /* Set LS pages reserved to allow for user-space mapping. */
2209 for (p = lscsa->ls; p < lscsa->ls + LS_SIZE; p += PAGE_SIZE) 2210 for (p = lscsa->ls; p < lscsa->ls + LS_SIZE; p += PAGE_SIZE)
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index ac224876ce59..6802cdc3168a 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -2,7 +2,6 @@
2 * CHRP pci routines. 2 * CHRP pci routines.
3 */ 3 */
4 4
5#include <linux/config.h>
6#include <linux/kernel.h> 5#include <linux/kernel.h>
7#include <linux/pci.h> 6#include <linux/pci.h>
8#include <linux/delay.h> 7#include <linux/delay.h>
@@ -19,7 +18,6 @@
19#include <asm/machdep.h> 18#include <asm/machdep.h>
20#include <asm/sections.h> 19#include <asm/sections.h>
21#include <asm/pci-bridge.h> 20#include <asm/pci-bridge.h>
22#include <asm/open_pic.h>
23#include <asm/grackle.h> 21#include <asm/grackle.h>
24#include <asm/rtas.h> 22#include <asm/rtas.h>
25 23
@@ -143,7 +141,7 @@ hydra_init(void)
143 if (np == NULL || of_address_to_resource(np, 0, &r)) 141 if (np == NULL || of_address_to_resource(np, 0, &r))
144 return 0; 142 return 0;
145 Hydra = ioremap(r.start, r.end-r.start); 143 Hydra = ioremap(r.start, r.end-r.start);
146 printk("Hydra Mac I/O at %lx\n", r.start); 144 printk("Hydra Mac I/O at %llx\n", (unsigned long long)r.start);
147 printk("Hydra Feature_Control was %x", 145 printk("Hydra Feature_Control was %x",
148 in_le32(&Hydra->Feature_Control)); 146 in_le32(&Hydra->Feature_Control));
149 out_le32(&Hydra->Feature_Control, (HYDRA_FC_SCC_CELL_EN | 147 out_le32(&Hydra->Feature_Control, (HYDRA_FC_SCC_CELL_EN |
@@ -162,15 +160,9 @@ void __init
162chrp_pcibios_fixup(void) 160chrp_pcibios_fixup(void)
163{ 161{
164 struct pci_dev *dev = NULL; 162 struct pci_dev *dev = NULL;
165 struct device_node *np;
166 163
167 /* PCI interrupts are controlled by the OpenPIC */ 164 for_each_pci_dev(dev)
168 for_each_pci_dev(dev) { 165 pci_read_irq_line(dev);
169 np = pci_device_to_OF_node(dev);
170 if ((np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0))
171 dev->irq = np->intrs[0].line;
172 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
173 }
174} 166}
175 167
176#define PRG_CL_RESET_VALID 0x00010000 168#define PRG_CL_RESET_VALID 0x00010000
@@ -267,7 +259,7 @@ chrp_find_bridges(void)
267 bus_range[0], bus_range[1]); 259 bus_range[0], bus_range[1]);
268 printk(" controlled by %s", dev->type); 260 printk(" controlled by %s", dev->type);
269 if (!is_longtrail) 261 if (!is_longtrail)
270 printk(" at %lx", r.start); 262 printk(" at %llx", (unsigned long long)r.start);
271 printk("\n"); 263 printk("\n");
272 264
273 hose = pcibios_alloc_controller(); 265 hose = pcibios_alloc_controller();
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 18d89f38796b..bb10171132fa 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -8,7 +8,6 @@
8 * bootup setup stuff.. 8 * bootup setup stuff..
9 */ 9 */
10 10
11#include <linux/config.h>
12#include <linux/errno.h> 11#include <linux/errno.h>
13#include <linux/sched.h> 12#include <linux/sched.h>
14#include <linux/kernel.h> 13#include <linux/kernel.h>
@@ -60,7 +59,7 @@ void rtas_indicator_progress(char *, unsigned short);
60int _chrp_type; 59int _chrp_type;
61EXPORT_SYMBOL(_chrp_type); 60EXPORT_SYMBOL(_chrp_type);
62 61
63struct mpic *chrp_mpic; 62static struct mpic *chrp_mpic;
64 63
65/* Used for doing CHRP event-scans */ 64/* Used for doing CHRP event-scans */
66DEFINE_PER_CPU(struct timer_list, heartbeat_timer); 65DEFINE_PER_CPU(struct timer_list, heartbeat_timer);
@@ -316,24 +315,32 @@ chrp_event_scan(unsigned long unused)
316 jiffies + event_scan_interval); 315 jiffies + event_scan_interval);
317} 316}
318 317
318static void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc,
319 struct pt_regs *regs)
320{
321 unsigned int cascade_irq = i8259_irq(regs);
322 if (cascade_irq != NO_IRQ)
323 generic_handle_irq(cascade_irq, regs);
324 desc->chip->eoi(irq);
325}
326
319/* 327/*
320 * Finds the open-pic node and sets up the mpic driver. 328 * Finds the open-pic node and sets up the mpic driver.
321 */ 329 */
322static void __init chrp_find_openpic(void) 330static void __init chrp_find_openpic(void)
323{ 331{
324 struct device_node *np, *root; 332 struct device_node *np, *root;
325 int len, i, j, irq_count; 333 int len, i, j;
326 int isu_size, idu_size; 334 int isu_size, idu_size;
327 unsigned int *iranges, *opprop = NULL; 335 unsigned int *iranges, *opprop = NULL;
328 int oplen = 0; 336 int oplen = 0;
329 unsigned long opaddr; 337 unsigned long opaddr;
330 int na = 1; 338 int na = 1;
331 unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS];
332 339
333 np = find_type_devices("open-pic"); 340 np = of_find_node_by_type(NULL, "open-pic");
334 if (np == NULL) 341 if (np == NULL)
335 return; 342 return;
336 root = find_path_device("/"); 343 root = of_find_node_by_path("/");
337 if (root) { 344 if (root) {
338 opprop = (unsigned int *) get_property 345 opprop = (unsigned int *) get_property
339 (root, "platform-open-pic", &oplen); 346 (root, "platform-open-pic", &oplen);
@@ -344,19 +351,15 @@ static void __init chrp_find_openpic(void)
344 oplen /= na * sizeof(unsigned int); 351 oplen /= na * sizeof(unsigned int);
345 } else { 352 } else {
346 struct resource r; 353 struct resource r;
347 if (of_address_to_resource(np, 0, &r)) 354 if (of_address_to_resource(np, 0, &r)) {
348 return; 355 goto bail;
356 }
349 opaddr = r.start; 357 opaddr = r.start;
350 oplen = 0; 358 oplen = 0;
351 } 359 }
352 360
353 printk(KERN_INFO "OpenPIC at %lx\n", opaddr); 361 printk(KERN_INFO "OpenPIC at %lx\n", opaddr);
354 362
355 irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */
356 prom_get_irq_senses(init_senses, NUM_ISA_INTERRUPTS, NR_IRQS - 4);
357 /* i8259 cascade is always positive level */
358 init_senses[0] = IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE;
359
360 iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len); 363 iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len);
361 if (iranges == NULL) 364 if (iranges == NULL)
362 len = 0; /* non-distributed mpic */ 365 len = 0; /* non-distributed mpic */
@@ -383,15 +386,12 @@ static void __init chrp_find_openpic(void)
383 if (len > 1) 386 if (len > 1)
384 isu_size = iranges[3]; 387 isu_size = iranges[3];
385 388
386 chrp_mpic = mpic_alloc(opaddr, MPIC_PRIMARY, 389 chrp_mpic = mpic_alloc(np, opaddr, MPIC_PRIMARY,
387 isu_size, NUM_ISA_INTERRUPTS, irq_count, 390 isu_size, 0, " MPIC ");
388 NR_IRQS - 4, init_senses, irq_count,
389 " MPIC ");
390 if (chrp_mpic == NULL) { 391 if (chrp_mpic == NULL) {
391 printk(KERN_ERR "Failed to allocate MPIC structure\n"); 392 printk(KERN_ERR "Failed to allocate MPIC structure\n");
392 return; 393 goto bail;
393 } 394 }
394
395 j = na - 1; 395 j = na - 1;
396 for (i = 1; i < len; ++i) { 396 for (i = 1; i < len; ++i) {
397 iranges += 2; 397 iranges += 2;
@@ -403,7 +403,10 @@ static void __init chrp_find_openpic(void)
403 } 403 }
404 404
405 mpic_init(chrp_mpic); 405 mpic_init(chrp_mpic);
406 mpic_setup_cascade(NUM_ISA_INTERRUPTS, i8259_irq_cascade, NULL); 406 ppc_md.get_irq = mpic_get_irq;
407 bail:
408 of_node_put(root);
409 of_node_put(np);
407} 410}
408 411
409#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) 412#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
@@ -414,14 +417,34 @@ static struct irqaction xmon_irqaction = {
414}; 417};
415#endif 418#endif
416 419
417void __init chrp_init_IRQ(void) 420static void __init chrp_find_8259(void)
418{ 421{
419 struct device_node *np; 422 struct device_node *np, *pic = NULL;
420 unsigned long chrp_int_ack = 0; 423 unsigned long chrp_int_ack = 0;
421#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) 424 unsigned int cascade_irq;
422 struct device_node *kbd; 425
423#endif 426 /* Look for cascade */
427 for_each_node_by_type(np, "interrupt-controller")
428 if (device_is_compatible(np, "chrp,iic")) {
429 pic = np;
430 break;
431 }
432 /* Ok, 8259 wasn't found. We need to handle the case where
433 * we have a pegasos that claims to be chrp but doesn't have
434 * a proper interrupt tree
435 */
436 if (pic == NULL && chrp_mpic != NULL) {
437 printk(KERN_ERR "i8259: Not found in device-tree"
438 " assuming no legacy interrupts\n");
439 return;
440 }
424 441
442 /* Look for intack. In a perfect world, we would look for it on
443 * the ISA bus that holds the 8259 but heh... Works that way. If
444 * we ever see a problem, we can try to re-use the pSeries code here.
445 * Also, Pegasos-type platforms don't have a proper node to start
446 * from anyway
447 */
425 for (np = find_devices("pci"); np != NULL; np = np->next) { 448 for (np = find_devices("pci"); np != NULL; np = np->next) {
426 unsigned int *addrp = (unsigned int *) 449 unsigned int *addrp = (unsigned int *)
427 get_property(np, "8259-interrupt-acknowledge", NULL); 450 get_property(np, "8259-interrupt-acknowledge", NULL);
@@ -432,11 +455,29 @@ void __init chrp_init_IRQ(void)
432 break; 455 break;
433 } 456 }
434 if (np == NULL) 457 if (np == NULL)
435 printk(KERN_ERR "Cannot find PCI interrupt acknowledge address\n"); 458 printk(KERN_WARNING "Cannot find PCI interrupt acknowledge"
459 " address, polling\n");
460
461 i8259_init(pic, chrp_int_ack);
462 if (ppc_md.get_irq == NULL)
463 ppc_md.get_irq = i8259_irq;
464 if (chrp_mpic != NULL) {
465 cascade_irq = irq_of_parse_and_map(pic, 0);
466 if (cascade_irq == NO_IRQ)
467 printk(KERN_ERR "i8259: failed to map cascade irq\n");
468 else
469 set_irq_chained_handler(cascade_irq,
470 chrp_8259_cascade);
471 }
472}
436 473
474void __init chrp_init_IRQ(void)
475{
476#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
477 struct device_node *kbd;
478#endif
437 chrp_find_openpic(); 479 chrp_find_openpic();
438 480 chrp_find_8259();
439 i8259_init(chrp_int_ack, 0);
440 481
441 if (_chrp_type == _CHRP_Pegasos) 482 if (_chrp_type == _CHRP_Pegasos)
442 ppc_md.get_irq = i8259_irq; 483 ppc_md.get_irq = i8259_irq;
@@ -521,10 +562,6 @@ static int __init chrp_probe(void)
521 DMA_MODE_READ = 0x44; 562 DMA_MODE_READ = 0x44;
522 DMA_MODE_WRITE = 0x48; 563 DMA_MODE_WRITE = 0x48;
523 isa_io_base = CHRP_ISA_IO_BASE; /* default value */ 564 isa_io_base = CHRP_ISA_IO_BASE; /* default value */
524 ppc_do_canonicalize_irqs = 1;
525
526 /* Assume we have an 8259... */
527 __irq_offset_value = NUM_ISA_INTERRUPTS;
528 565
529 return 1; 566 return 1;
530} 567}
@@ -536,7 +573,6 @@ define_machine(chrp) {
536 .init = chrp_init2, 573 .init = chrp_init2,
537 .show_cpuinfo = chrp_show_cpuinfo, 574 .show_cpuinfo = chrp_show_cpuinfo,
538 .init_IRQ = chrp_init_IRQ, 575 .init_IRQ = chrp_init_IRQ,
539 .get_irq = mpic_get_irq,
540 .pcibios_fixup = chrp_pcibios_fixup, 576 .pcibios_fixup = chrp_pcibios_fixup,
541 .restart = rtas_restart, 577 .restart = rtas_restart,
542 .power_off = rtas_power_off, 578 .power_off = rtas_power_off,
diff --git a/arch/powerpc/platforms/chrp/smp.c b/arch/powerpc/platforms/chrp/smp.c
index b616053bc331..1d2307e87c30 100644
--- a/arch/powerpc/platforms/chrp/smp.c
+++ b/arch/powerpc/platforms/chrp/smp.c
@@ -8,7 +8,6 @@
8 * 8 *
9 */ 9 */
10 10
11#include <linux/config.h>
12#include <linux/kernel.h> 11#include <linux/kernel.h>
13#include <linux/sched.h> 12#include <linux/sched.h>
14#include <linux/smp.h> 13#include <linux/smp.h>
@@ -30,7 +29,6 @@
30#include <asm/smp.h> 29#include <asm/smp.h>
31#include <asm/residual.h> 30#include <asm/residual.h>
32#include <asm/time.h> 31#include <asm/time.h>
33#include <asm/open_pic.h>
34#include <asm/machdep.h> 32#include <asm/machdep.h>
35#include <asm/smp.h> 33#include <asm/smp.h>
36#include <asm/mpic.h> 34#include <asm/mpic.h>
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index 4fdbc9ae876b..ba07a9a7c039 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -74,6 +74,16 @@ config SANDPOINT
74 Select SANDPOINT if configuring for a Motorola Sandpoint X3 74 Select SANDPOINT if configuring for a Motorola Sandpoint X3
75 (any flavor). 75 (any flavor).
76 76
77config MPC7448HPC2
78 bool "Freescale MPC7448HPC2(Taiga)"
79 select TSI108_BRIDGE
80 select DEFAULT_UIMAGE
81 select PPC_UDBG_16550
82 select MPIC
83 help
84 Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga)
85 platform
86
77config RADSTONE_PPC7D 87config RADSTONE_PPC7D
78 bool "Radstone Technology PPC7D board" 88 bool "Radstone Technology PPC7D board"
79 select PPC_I8259 89 select PPC_I8259
@@ -221,6 +231,11 @@ config MV64X60
221 select PPC_INDIRECT_PCI 231 select PPC_INDIRECT_PCI
222 default y 232 default y
223 233
234config TSI108_BRIDGE
235 bool
236 depends on MPC7448HPC2
237 default y
238
224menu "Set bridge options" 239menu "Set bridge options"
225 depends on MV64X60 240 depends on MV64X60
226 241
diff --git a/arch/powerpc/platforms/embedded6xx/Makefile b/arch/powerpc/platforms/embedded6xx/Makefile
new file mode 100644
index 000000000000..fa499fe59291
--- /dev/null
+++ b/arch/powerpc/platforms/embedded6xx/Makefile
@@ -0,0 +1,4 @@
1#
2# Makefile for the 6xx/7xx/7xxxx linux kernel.
3#
4obj-$(CONFIG_MPC7448HPC2) += mpc7448_hpc2.o
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
new file mode 100644
index 000000000000..d7a4fc7ca238
--- /dev/null
+++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
@@ -0,0 +1,335 @@
1/*
2 * mpc7448_hpc2.c
3 *
4 * Board setup routines for the Freescale Taiga platform
5 *
6 * Author: Jacob Pan
7 * jacob.pan@freescale.com
8 * Author: Xianghua Xiao
9 * x.xiao@freescale.com
10 * Maintainer: Roy Zang <tie-fei.zang@freescale.com>
11 * Add Flat Device Tree support fot mpc7448hpc2 board
12 *
13 * Copyright 2004-2006 Freescale Semiconductor, Inc.
14 *
15 * This file is licensed under
16 * the terms of the GNU General Public License version 2. This program
17 * is licensed "as is" without any warranty of any kind, whether express
18 * or implied.
19 */
20
21#include <linux/config.h>
22#include <linux/stddef.h>
23#include <linux/kernel.h>
24#include <linux/pci.h>
25#include <linux/kdev_t.h>
26#include <linux/console.h>
27#include <linux/delay.h>
28#include <linux/irq.h>
29#include <linux/ide.h>
30#include <linux/seq_file.h>
31#include <linux/root_dev.h>
32#include <linux/serial.h>
33#include <linux/tty.h>
34#include <linux/serial_core.h>
35
36#include <asm/system.h>
37#include <asm/time.h>
38#include <asm/machdep.h>
39#include <asm/prom.h>
40#include <asm/udbg.h>
41#include <asm/tsi108.h>
42#include <asm/pci-bridge.h>
43#include <asm/reg.h>
44#include <mm/mmu_decl.h>
45#include "mpc7448_hpc2.h"
46#include <asm/tsi108_irq.h>
47#include <asm/mpic.h>
48
49#undef DEBUG
50#ifdef DEBUG
51#define DBG(fmt...) do { printk(fmt); } while(0)
52#else
53#define DBG(fmt...) do { } while(0)
54#endif
55
56#ifndef CONFIG_PCI
57isa_io_base = MPC7448_HPC2_ISA_IO_BASE;
58isa_mem_base = MPC7448_HPC2_ISA_MEM_BASE;
59pci_dram_offset = MPC7448_HPC2_PCI_MEM_OFFSET;
60#endif
61
62extern int tsi108_setup_pci(struct device_node *dev);
63extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
64extern void tsi108_pci_int_init(void);
65extern int tsi108_irq_cascade(struct pt_regs *regs, void *unused);
66
67/*
68 * Define all of the IRQ senses and polarities. Taken from the
69 * mpc7448hpc manual.
70 * Note: Likely, this table and the following function should be
71 * obtained and derived from the OF Device Tree.
72 */
73
74static u_char mpc7448_hpc2_pic_initsenses[] __initdata = {
75 /* External on-board sources */
76 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* INT[0] XINT0 from FPGA */
77 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* INT[1] XINT1 from FPGA */
78 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* INT[2] PHY_INT from both GIGE */
79 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* INT[3] RESERVED */
80 /* Internal Tsi108/109 interrupt sources */
81 (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */
82 (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */
83 (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */
84 (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */
85 (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* DMA0 */
86 (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* DMA1 */
87 (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* DMA2 */
88 (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* DMA3 */
89 (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* UART0 */
90 (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* UART1 */
91 (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* I2C */
92 (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* GPIO */
93 (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* GIGE0 */
94 (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* GIGE1 */
95 (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */
96 (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* HLP */
97 (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* SDC */
98 (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Processor IF */
99 (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */
100 (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* PCI/X block */
101};
102
103int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn)
104{
105 if (bus == 0 && PCI_SLOT(devfn) == 0)
106 return PCIBIOS_DEVICE_NOT_FOUND;
107 else
108 return PCIBIOS_SUCCESSFUL;
109}
110
111/*
112 * find pci slot by devfn in interrupt map of OF tree
113 */
114u8 find_slot_by_devfn(unsigned int *interrupt_map, unsigned int devfn)
115{
116 int i;
117 unsigned int tmp;
118 for (i = 0; i < 4; i++){
119 tmp = interrupt_map[i*4*7];
120 if ((tmp >> 11) == (devfn >> 3))
121 return i;
122 }
123 return i;
124}
125
126/*
127 * Scans the interrupt map for pci device
128 */
129void mpc7448_hpc2_fixup_irq(struct pci_dev *dev)
130{
131 struct pci_controller *hose;
132 struct device_node *node;
133 unsigned int *interrupt;
134 int busnr;
135 int len;
136 u8 slot;
137 u8 pin;
138
139 /* Lookup the hose */
140 busnr = dev->bus->number;
141 hose = pci_bus_to_hose(busnr);
142 if (!hose)
143 printk(KERN_ERR "No pci hose found\n");
144
145 /* Check it has an OF node associated */
146 node = (struct device_node *) hose->arch_data;
147 if (!node)
148 printk(KERN_ERR "No pci node found\n");
149
150 interrupt = (unsigned int *) get_property(node, "interrupt-map", &len);
151 slot = find_slot_by_devfn(interrupt, dev->devfn);
152 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
153 if (pin == 0 || pin > 4)
154 pin = 1;
155 pin--;
156 dev->irq = interrupt[slot*4*7 + pin*7 + 5];
157 DBG("TSI_PCI: dev->irq = 0x%x\n", dev->irq);
158}
159/* temporary pci irq map fixup*/
160
161void __init mpc7448_hpc2_pcibios_fixup(void)
162{
163 struct pci_dev *dev = NULL;
164 for_each_pci_dev(dev) {
165 mpc7448_hpc2_fixup_irq(dev);
166 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
167 }
168}
169
170static void __init mpc7448_hpc2_setup_arch(void)
171{
172 struct device_node *cpu;
173 struct device_node *np;
174 if (ppc_md.progress)
175 ppc_md.progress("mpc7448_hpc2_setup_arch():set_bridge", 0);
176
177 cpu = of_find_node_by_type(NULL, "cpu");
178 if (cpu != 0) {
179 unsigned int *fp;
180
181 fp = (int *)get_property(cpu, "clock-frequency", NULL);
182 if (fp != 0)
183 loops_per_jiffy = *fp / HZ;
184 else
185 loops_per_jiffy = 50000000 / HZ;
186 of_node_put(cpu);
187 }
188 tsi108_csr_vir_base = get_vir_csrbase();
189
190#ifdef CONFIG_ROOT_NFS
191 ROOT_DEV = Root_NFS;
192#else
193 ROOT_DEV = Root_HDA1;
194#endif
195
196#ifdef CONFIG_BLK_DEV_INITRD
197 ROOT_DEV = Root_RAM0;
198#endif
199
200 /* setup PCI host bridge */
201#ifdef CONFIG_PCI
202 for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
203 tsi108_setup_pci(np);
204
205 ppc_md.pci_exclude_device = mpc7448_hpc2_exclude_device;
206 if (ppc_md.progress)
207 ppc_md.progress("tsi108: resources set", 0x100);
208#endif
209
210 printk(KERN_INFO "MPC7448HPC2 (TAIGA) Platform\n");
211 printk(KERN_INFO
212 "Jointly ported by Freescale and Tundra Semiconductor\n");
213 printk(KERN_INFO
214 "Enabling L2 cache then enabling the HID0 prefetch engine.\n");
215}
216
217/*
218 * Interrupt setup and service. Interrrupts on the mpc7448_hpc2 come
219 * from the four external INT pins, PCI interrupts are routed via
220 * PCI interrupt control registers, it generates internal IRQ23
221 *
222 * Interrupt routing on the Taiga Board:
223 * TSI108:PB_INT[0] -> CPU0:INT#
224 * TSI108:PB_INT[1] -> CPU0:MCP#
225 * TSI108:PB_INT[2] -> N/C
226 * TSI108:PB_INT[3] -> N/C
227 */
228static void __init mpc7448_hpc2_init_IRQ(void)
229{
230 struct mpic *mpic;
231 phys_addr_t mpic_paddr = 0;
232 struct device_node *tsi_pic;
233
234 tsi_pic = of_find_node_by_type(NULL, "open-pic");
235 if (tsi_pic) {
236 unsigned int size;
237 void *prop = get_property(tsi_pic, "reg", &size);
238 mpic_paddr = of_translate_address(tsi_pic, prop);
239 }
240
241 if (mpic_paddr == 0) {
242 printk("%s: No tsi108 PIC found !\n", __FUNCTION__);
243 return;
244 }
245
246 DBG("%s: tsi108pic phys_addr = 0x%x\n", __FUNCTION__,
247 (u32) mpic_paddr);
248
249 mpic = mpic_alloc(mpic_paddr,
250 MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET |
251 MPIC_SPV_EOI | MPIC_MOD_ID(MPIC_ID_TSI108),
252 0, /* num_sources used */
253 TSI108_IRQ_BASE,
254 0, /* num_sources used */
255 NR_IRQS - 4 /* XXXX */,
256 mpc7448_hpc2_pic_initsenses,
257 sizeof(mpc7448_hpc2_pic_initsenses), "Tsi108_PIC");
258
259 BUG_ON(mpic == NULL); /* XXXX */
260
261 mpic_init(mpic);
262 mpic_setup_cascade(IRQ_TSI108_PCI, tsi108_irq_cascade, mpic);
263 tsi108_pci_int_init();
264
265 /* Configure MPIC outputs to CPU0 */
266 tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0);
267}
268
269void mpc7448_hpc2_show_cpuinfo(struct seq_file *m)
270{
271 seq_printf(m, "vendor\t\t: Freescale Semiconductor\n");
272 seq_printf(m, "machine\t\t: MPC7448hpc2\n");
273}
274
275void mpc7448_hpc2_restart(char *cmd)
276{
277 local_irq_disable();
278
279 /* Set exception prefix high - to the firmware */
280 _nmask_and_or_msr(0, MSR_IP);
281
282 for (;;) ; /* Spin until reset happens */
283}
284
285void mpc7448_hpc2_power_off(void)
286{
287 local_irq_disable();
288 for (;;) ; /* No way to shut power off with software */
289}
290
291void mpc7448_hpc2_halt(void)
292{
293 mpc7448_hpc2_power_off();
294}
295
296/*
297 * Called very early, device-tree isn't unflattened
298 */
299static int __init mpc7448_hpc2_probe(void)
300{
301 unsigned long root = of_get_flat_dt_root();
302
303 if (!of_flat_dt_is_compatible(root, "mpc74xx"))
304 return 0;
305 return 1;
306}
307
308static int mpc7448_machine_check_exception(struct pt_regs *regs)
309{
310 extern void tsi108_clear_pci_cfg_error(void);
311 const struct exception_table_entry *entry;
312
313 /* Are we prepared to handle this fault */
314 if ((entry = search_exception_tables(regs->nip)) != NULL) {
315 tsi108_clear_pci_cfg_error();
316 regs->msr |= MSR_RI;
317 regs->nip = entry->fixup;
318 return 1;
319 }
320 return 0;
321
322}
323define_machine(mpc7448_hpc2){
324 .name = "MPC7448 HPC2",
325 .probe = mpc7448_hpc2_probe,
326 .setup_arch = mpc7448_hpc2_setup_arch,
327 .init_IRQ = mpc7448_hpc2_init_IRQ,
328 .show_cpuinfo = mpc7448_hpc2_show_cpuinfo,
329 .get_irq = mpic_get_irq,
330 .pcibios_fixup = mpc7448_hpc2_pcibios_fixup,
331 .restart = mpc7448_hpc2_restart,
332 .calibrate_decr = generic_calibrate_decr,
333 .machine_check_exception= mpc7448_machine_check_exception,
334 .progress = udbg_progress,
335};
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h
new file mode 100644
index 000000000000..a543a5242e34
--- /dev/null
+++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h
@@ -0,0 +1,26 @@
1/*
2 * mpc7448_hpc2.h
3 *
4 * Definitions for Freescale MPC7448_HPC2 platform
5 *
6 * Author: Jacob Pan
7 * jacob.pan@freescale.com
8 * Maintainer: Roy Zang <roy.zang@freescale.com>
9 *
10 * 2006 (c) Freescale Semiconductor, Inc. This file is licensed under
11 * the terms of the GNU General Public License version 2. This program
12 * is licensed "as is" without any warranty of any kind, whether express
13 * or implied.
14 */
15
16#ifndef __PPC_PLATFORMS_MPC7448_HPC2_H
17#define __PPC_PLATFORMS_MPC7448_HPC2_H
18
19#include <asm/ppcboot.h>
20
21/* Base Addresses for the PCI bus
22 */
23#define MPC7448_HPC2_PCI_MEM_OFFSET (0x00000000)
24#define MPC7448_HPC2_ISA_IO_BASE (0x00000000)
25#define MPC7448_HPC2_ISA_MEM_BASE (0x00000000)
26#endif /* __PPC_PLATFORMS_MPC7448_HPC2_H */
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index d3444aabe76e..d194140c1ebf 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -252,6 +252,7 @@ static void __init dt_model(struct iseries_flat_dt *dt)
252{ 252{
253 char buf[16] = "IBM,"; 253 char buf[16] = "IBM,";
254 254
255 /* N.B. lparcfg.c knows about the "IBM," prefixes ... */
255 /* "IBM," + mfgId[2:3] + systemSerial[1:5] */ 256 /* "IBM," + mfgId[2:3] + systemSerial[1:5] */
256 strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2); 257 strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2);
257 strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5); 258 strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5);
@@ -264,6 +265,7 @@ static void __init dt_model(struct iseries_flat_dt *dt)
264 dt_prop_str(dt, "model", buf); 265 dt_prop_str(dt, "model", buf);
265 266
266 dt_prop_str(dt, "compatible", "IBM,iSeries"); 267 dt_prop_str(dt, "compatible", "IBM,iSeries");
268 dt_prop_u32(dt, "ibm,partition-no", HvLpConfig_getLpIndex());
267} 269}
268 270
269static void __init dt_do_vdevice(struct iseries_flat_dt *dt, 271static void __init dt_do_vdevice(struct iseries_flat_dt *dt,
diff --git a/arch/powerpc/platforms/iseries/htab.c b/arch/powerpc/platforms/iseries/htab.c
index 30bdcf3925d9..ed44dfceaa45 100644
--- a/arch/powerpc/platforms/iseries/htab.c
+++ b/arch/powerpc/platforms/iseries/htab.c
@@ -242,13 +242,11 @@ static void iSeries_hpte_invalidate(unsigned long slot, unsigned long va,
242 local_irq_restore(flags); 242 local_irq_restore(flags);
243} 243}
244 244
245void hpte_init_iSeries(void) 245void __init hpte_init_iSeries(void)
246{ 246{
247 ppc_md.hpte_invalidate = iSeries_hpte_invalidate; 247 ppc_md.hpte_invalidate = iSeries_hpte_invalidate;
248 ppc_md.hpte_updatepp = iSeries_hpte_updatepp; 248 ppc_md.hpte_updatepp = iSeries_hpte_updatepp;
249 ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp; 249 ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp;
250 ppc_md.hpte_insert = iSeries_hpte_insert; 250 ppc_md.hpte_insert = iSeries_hpte_insert;
251 ppc_md.hpte_remove = iSeries_hpte_remove; 251 ppc_md.hpte_remove = iSeries_hpte_remove;
252
253 htab_finish_init();
254} 252}
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index 62bbbcf5ded3..2275e64f3152 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -23,7 +23,6 @@
23 * Created, December 13, 2000 by Wayne Holm 23 * Created, December 13, 2000 by Wayne Holm
24 * End Change Activity 24 * End Change Activity
25 */ 25 */
26#include <linux/config.h>
27#include <linux/pci.h> 26#include <linux/pci.h>
28#include <linux/init.h> 27#include <linux/init.h>
29#include <linux/threads.h> 28#include <linux/threads.h>
@@ -163,27 +162,6 @@ static void pci_event_handler(struct HvLpEvent *event, struct pt_regs *regs)
163 printk(KERN_ERR "pci_event_handler: NULL event received\n"); 162 printk(KERN_ERR "pci_event_handler: NULL event received\n");
164} 163}
165 164
166/*
167 * This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c
168 * It must be called before the bus walk.
169 */
170void __init iSeries_init_IRQ(void)
171{
172 /* Register PCI event handler and open an event path */
173 int ret;
174
175 ret = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
176 &pci_event_handler);
177 if (ret == 0) {
178 ret = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
179 if (ret != 0)
180 printk(KERN_ERR "iseries_init_IRQ: open event path "
181 "failed with rc 0x%x\n", ret);
182 } else
183 printk(KERN_ERR "iseries_init_IRQ: register handler "
184 "failed with rc 0x%x\n", ret);
185}
186
187#define REAL_IRQ_TO_SUBBUS(irq) (((irq) >> 14) & 0xff) 165#define REAL_IRQ_TO_SUBBUS(irq) (((irq) >> 14) & 0xff)
188#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1) 166#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1)
189#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1) 167#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1)
@@ -197,7 +175,7 @@ static void iseries_enable_IRQ(unsigned int irq)
197{ 175{
198 u32 bus, dev_id, function, mask; 176 u32 bus, dev_id, function, mask;
199 const u32 sub_bus = 0; 177 const u32 sub_bus = 0;
200 unsigned int rirq = virt_irq_to_real_map[irq]; 178 unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
201 179
202 /* The IRQ has already been locked by the caller */ 180 /* The IRQ has already been locked by the caller */
203 bus = REAL_IRQ_TO_BUS(rirq); 181 bus = REAL_IRQ_TO_BUS(rirq);
@@ -214,7 +192,7 @@ static unsigned int iseries_startup_IRQ(unsigned int irq)
214{ 192{
215 u32 bus, dev_id, function, mask; 193 u32 bus, dev_id, function, mask;
216 const u32 sub_bus = 0; 194 const u32 sub_bus = 0;
217 unsigned int rirq = virt_irq_to_real_map[irq]; 195 unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
218 196
219 bus = REAL_IRQ_TO_BUS(rirq); 197 bus = REAL_IRQ_TO_BUS(rirq);
220 function = REAL_IRQ_TO_FUNC(rirq); 198 function = REAL_IRQ_TO_FUNC(rirq);
@@ -242,9 +220,9 @@ void __init iSeries_activate_IRQs()
242 for_each_irq (irq) { 220 for_each_irq (irq) {
243 irq_desc_t *desc = get_irq_desc(irq); 221 irq_desc_t *desc = get_irq_desc(irq);
244 222
245 if (desc && desc->handler && desc->handler->startup) { 223 if (desc && desc->chip && desc->chip->startup) {
246 spin_lock_irqsave(&desc->lock, flags); 224 spin_lock_irqsave(&desc->lock, flags);
247 desc->handler->startup(irq); 225 desc->chip->startup(irq);
248 spin_unlock_irqrestore(&desc->lock, flags); 226 spin_unlock_irqrestore(&desc->lock, flags);
249 } 227 }
250 } 228 }
@@ -255,7 +233,7 @@ static void iseries_shutdown_IRQ(unsigned int irq)
255{ 233{
256 u32 bus, dev_id, function, mask; 234 u32 bus, dev_id, function, mask;
257 const u32 sub_bus = 0; 235 const u32 sub_bus = 0;
258 unsigned int rirq = virt_irq_to_real_map[irq]; 236 unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
259 237
260 /* irq should be locked by the caller */ 238 /* irq should be locked by the caller */
261 bus = REAL_IRQ_TO_BUS(rirq); 239 bus = REAL_IRQ_TO_BUS(rirq);
@@ -278,7 +256,7 @@ static void iseries_disable_IRQ(unsigned int irq)
278{ 256{
279 u32 bus, dev_id, function, mask; 257 u32 bus, dev_id, function, mask;
280 const u32 sub_bus = 0; 258 const u32 sub_bus = 0;
281 unsigned int rirq = virt_irq_to_real_map[irq]; 259 unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
282 260
283 /* The IRQ has already been locked by the caller */ 261 /* The IRQ has already been locked by the caller */
284 bus = REAL_IRQ_TO_BUS(rirq); 262 bus = REAL_IRQ_TO_BUS(rirq);
@@ -292,19 +270,19 @@ static void iseries_disable_IRQ(unsigned int irq)
292 270
293static void iseries_end_IRQ(unsigned int irq) 271static void iseries_end_IRQ(unsigned int irq)
294{ 272{
295 unsigned int rirq = virt_irq_to_real_map[irq]; 273 unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
296 274
297 HvCallPci_eoi(REAL_IRQ_TO_BUS(rirq), REAL_IRQ_TO_SUBBUS(rirq), 275 HvCallPci_eoi(REAL_IRQ_TO_BUS(rirq), REAL_IRQ_TO_SUBBUS(rirq),
298 (REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq)); 276 (REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq));
299} 277}
300 278
301static hw_irq_controller iSeries_IRQ_handler = { 279static struct irq_chip iseries_pic = {
302 .typename = "iSeries irq controller", 280 .typename = "iSeries irq controller",
303 .startup = iseries_startup_IRQ, 281 .startup = iseries_startup_IRQ,
304 .shutdown = iseries_shutdown_IRQ, 282 .shutdown = iseries_shutdown_IRQ,
305 .enable = iseries_enable_IRQ, 283 .unmask = iseries_enable_IRQ,
306 .disable = iseries_disable_IRQ, 284 .mask = iseries_disable_IRQ,
307 .end = iseries_end_IRQ 285 .eoi = iseries_end_IRQ
308}; 286};
309 287
310/* 288/*
@@ -315,17 +293,14 @@ static hw_irq_controller iSeries_IRQ_handler = {
315int __init iSeries_allocate_IRQ(HvBusNumber bus, 293int __init iSeries_allocate_IRQ(HvBusNumber bus,
316 HvSubBusNumber sub_bus, u32 bsubbus) 294 HvSubBusNumber sub_bus, u32 bsubbus)
317{ 295{
318 int virtirq;
319 unsigned int realirq; 296 unsigned int realirq;
320 u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus); 297 u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus);
321 u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus); 298 u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus);
322 299
323 realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3) 300 realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3)
324 + function; 301 + function;
325 virtirq = virt_irq_create_mapping(realirq);
326 302
327 irq_desc[virtirq].handler = &iSeries_IRQ_handler; 303 return irq_create_mapping(NULL, realirq, IRQ_TYPE_NONE);
328 return virtirq;
329} 304}
330 305
331#endif /* CONFIG_PCI */ 306#endif /* CONFIG_PCI */
@@ -333,10 +308,9 @@ int __init iSeries_allocate_IRQ(HvBusNumber bus,
333/* 308/*
334 * Get the next pending IRQ. 309 * Get the next pending IRQ.
335 */ 310 */
336int iSeries_get_irq(struct pt_regs *regs) 311unsigned int iSeries_get_irq(struct pt_regs *regs)
337{ 312{
338 /* -2 means ignore this interrupt */ 313 int irq = NO_IRQ_IGNORE;
339 int irq = -2;
340 314
341#ifdef CONFIG_SMP 315#ifdef CONFIG_SMP
342 if (get_lppaca()->int_dword.fields.ipi_cnt) { 316 if (get_lppaca()->int_dword.fields.ipi_cnt) {
@@ -359,9 +333,57 @@ int iSeries_get_irq(struct pt_regs *regs)
359 } 333 }
360 spin_unlock(&pending_irqs_lock); 334 spin_unlock(&pending_irqs_lock);
361 if (irq >= NR_IRQS) 335 if (irq >= NR_IRQS)
362 irq = -2; 336 irq = NO_IRQ_IGNORE;
363 } 337 }
364#endif 338#endif
365 339
366 return irq; 340 return irq;
367} 341}
342
343static int iseries_irq_host_map(struct irq_host *h, unsigned int virq,
344 irq_hw_number_t hw, unsigned int flags)
345{
346 set_irq_chip_and_handler(virq, &iseries_pic, handle_fasteoi_irq);
347
348 return 0;
349}
350
351static struct irq_host_ops iseries_irq_host_ops = {
352 .map = iseries_irq_host_map,
353};
354
355/*
356 * This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c
357 * It must be called before the bus walk.
358 */
359void __init iSeries_init_IRQ(void)
360{
361 /* Register PCI event handler and open an event path */
362 struct irq_host *host;
363 int ret;
364
365 /*
366 * The Hypervisor only allows us up to 256 interrupt
367 * sources (the irq number is passed in a u8).
368 */
369 irq_set_virq_count(256);
370
371 /* Create irq host. No need for a revmap since HV will give us
372 * back our virtual irq number
373 */
374 host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, &iseries_irq_host_ops, 0);
375 BUG_ON(host == NULL);
376 irq_set_default_host(host);
377
378 ret = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
379 &pci_event_handler);
380 if (ret == 0) {
381 ret = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
382 if (ret != 0)
383 printk(KERN_ERR "iseries_init_IRQ: open event path "
384 "failed with rc 0x%x\n", ret);
385 } else
386 printk(KERN_ERR "iseries_init_IRQ: register handler "
387 "failed with rc 0x%x\n", ret);
388}
389
diff --git a/arch/powerpc/platforms/iseries/irq.h b/arch/powerpc/platforms/iseries/irq.h
index 188aa808abd7..1ee8985140e5 100644
--- a/arch/powerpc/platforms/iseries/irq.h
+++ b/arch/powerpc/platforms/iseries/irq.h
@@ -4,6 +4,6 @@
4extern void iSeries_init_IRQ(void); 4extern void iSeries_init_IRQ(void);
5extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, u32); 5extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, u32);
6extern void iSeries_activate_IRQs(void); 6extern void iSeries_activate_IRQs(void);
7extern int iSeries_get_irq(struct pt_regs *); 7extern unsigned int iSeries_get_irq(struct pt_regs *);
8 8
9#endif /* _ISERIES_IRQ_H */ 9#endif /* _ISERIES_IRQ_H */
diff --git a/arch/powerpc/platforms/iseries/lpardata.c b/arch/powerpc/platforms/iseries/lpardata.c
index 438e2dba63b5..a7769445d6c7 100644
--- a/arch/powerpc/platforms/iseries/lpardata.c
+++ b/arch/powerpc/platforms/iseries/lpardata.c
@@ -6,7 +6,6 @@
6 * as published by the Free Software Foundation; either version 6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version. 7 * 2 of the License, or (at your option) any later version.
8 */ 8 */
9#include <linux/config.h>
10#include <linux/types.h> 9#include <linux/types.h>
11#include <linux/threads.h> 10#include <linux/threads.h>
12#include <linux/module.h> 11#include <linux/module.h>
diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c
index 8ca7b9396355..2a9f81ea27d6 100644
--- a/arch/powerpc/platforms/iseries/lpevents.c
+++ b/arch/powerpc/platforms/iseries/lpevents.c
@@ -51,20 +51,21 @@ static unsigned lpEventHandlerPaths[HvLpEvent_Type_NumTypes];
51static struct HvLpEvent * get_next_hvlpevent(void) 51static struct HvLpEvent * get_next_hvlpevent(void)
52{ 52{
53 struct HvLpEvent * event; 53 struct HvLpEvent * event;
54 event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr; 54 event = (struct HvLpEvent *)hvlpevent_queue.hq_current_event;
55 55
56 if (hvlpevent_is_valid(event)) { 56 if (hvlpevent_is_valid(event)) {
57 /* rmb() needed only for weakly consistent machines (regatta) */ 57 /* rmb() needed only for weakly consistent machines (regatta) */
58 rmb(); 58 rmb();
59 /* Set pointer to next potential event */ 59 /* Set pointer to next potential event */
60 hvlpevent_queue.xSlicCurEventPtr += ((event->xSizeMinus1 + 60 hvlpevent_queue.hq_current_event += ((event->xSizeMinus1 +
61 LpEventAlign) / LpEventAlign) * LpEventAlign; 61 IT_LP_EVENT_ALIGN) / IT_LP_EVENT_ALIGN) *
62 IT_LP_EVENT_ALIGN;
62 63
63 /* Wrap to beginning if no room at end */ 64 /* Wrap to beginning if no room at end */
64 if (hvlpevent_queue.xSlicCurEventPtr > 65 if (hvlpevent_queue.hq_current_event >
65 hvlpevent_queue.xSlicLastValidEventPtr) { 66 hvlpevent_queue.hq_last_event) {
66 hvlpevent_queue.xSlicCurEventPtr = 67 hvlpevent_queue.hq_current_event =
67 hvlpevent_queue.xSlicEventStackPtr; 68 hvlpevent_queue.hq_event_stack;
68 } 69 }
69 } else { 70 } else {
70 event = NULL; 71 event = NULL;
@@ -82,10 +83,10 @@ int hvlpevent_is_pending(void)
82 if (smp_processor_id() >= spread_lpevents) 83 if (smp_processor_id() >= spread_lpevents)
83 return 0; 84 return 0;
84 85
85 next_event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr; 86 next_event = (struct HvLpEvent *)hvlpevent_queue.hq_current_event;
86 87
87 return hvlpevent_is_valid(next_event) || 88 return hvlpevent_is_valid(next_event) ||
88 hvlpevent_queue.xPlicOverflowIntPending; 89 hvlpevent_queue.hq_overflow_pending;
89} 90}
90 91
91static void hvlpevent_clear_valid(struct HvLpEvent * event) 92static void hvlpevent_clear_valid(struct HvLpEvent * event)
@@ -95,18 +96,18 @@ static void hvlpevent_clear_valid(struct HvLpEvent * event)
95 * ie. on 64-byte boundaries. 96 * ie. on 64-byte boundaries.
96 */ 97 */
97 struct HvLpEvent *tmp; 98 struct HvLpEvent *tmp;
98 unsigned extra = ((event->xSizeMinus1 + LpEventAlign) / 99 unsigned extra = ((event->xSizeMinus1 + IT_LP_EVENT_ALIGN) /
99 LpEventAlign) - 1; 100 IT_LP_EVENT_ALIGN) - 1;
100 101
101 switch (extra) { 102 switch (extra) {
102 case 3: 103 case 3:
103 tmp = (struct HvLpEvent*)((char*)event + 3 * LpEventAlign); 104 tmp = (struct HvLpEvent*)((char*)event + 3 * IT_LP_EVENT_ALIGN);
104 hvlpevent_invalidate(tmp); 105 hvlpevent_invalidate(tmp);
105 case 2: 106 case 2:
106 tmp = (struct HvLpEvent*)((char*)event + 2 * LpEventAlign); 107 tmp = (struct HvLpEvent*)((char*)event + 2 * IT_LP_EVENT_ALIGN);
107 hvlpevent_invalidate(tmp); 108 hvlpevent_invalidate(tmp);
108 case 1: 109 case 1:
109 tmp = (struct HvLpEvent*)((char*)event + 1 * LpEventAlign); 110 tmp = (struct HvLpEvent*)((char*)event + 1 * IT_LP_EVENT_ALIGN);
110 hvlpevent_invalidate(tmp); 111 hvlpevent_invalidate(tmp);
111 } 112 }
112 113
@@ -120,7 +121,7 @@ void process_hvlpevents(struct pt_regs *regs)
120 struct HvLpEvent * event; 121 struct HvLpEvent * event;
121 122
122 /* If we have recursed, just return */ 123 /* If we have recursed, just return */
123 if (!spin_trylock(&hvlpevent_queue.lock)) 124 if (!spin_trylock(&hvlpevent_queue.hq_lock))
124 return; 125 return;
125 126
126 for (;;) { 127 for (;;) {
@@ -148,17 +149,17 @@ void process_hvlpevents(struct pt_regs *regs)
148 printk(KERN_INFO "Unexpected Lp Event type=%d\n", event->xType ); 149 printk(KERN_INFO "Unexpected Lp Event type=%d\n", event->xType );
149 150
150 hvlpevent_clear_valid(event); 151 hvlpevent_clear_valid(event);
151 } else if (hvlpevent_queue.xPlicOverflowIntPending) 152 } else if (hvlpevent_queue.hq_overflow_pending)
152 /* 153 /*
153 * No more valid events. If overflow events are 154 * No more valid events. If overflow events are
154 * pending process them 155 * pending process them
155 */ 156 */
156 HvCallEvent_getOverflowLpEvents(hvlpevent_queue.xIndex); 157 HvCallEvent_getOverflowLpEvents(hvlpevent_queue.hq_index);
157 else 158 else
158 break; 159 break;
159 } 160 }
160 161
161 spin_unlock(&hvlpevent_queue.lock); 162 spin_unlock(&hvlpevent_queue.hq_lock);
162} 163}
163 164
164static int set_spread_lpevents(char *str) 165static int set_spread_lpevents(char *str)
@@ -184,20 +185,20 @@ void setup_hvlpevent_queue(void)
184{ 185{
185 void *eventStack; 186 void *eventStack;
186 187
187 spin_lock_init(&hvlpevent_queue.lock); 188 spin_lock_init(&hvlpevent_queue.hq_lock);
188 189
189 /* Allocate a page for the Event Stack. */ 190 /* Allocate a page for the Event Stack. */
190 eventStack = alloc_bootmem_pages(LpEventStackSize); 191 eventStack = alloc_bootmem_pages(IT_LP_EVENT_STACK_SIZE);
191 memset(eventStack, 0, LpEventStackSize); 192 memset(eventStack, 0, IT_LP_EVENT_STACK_SIZE);
192 193
193 /* Invoke the hypervisor to initialize the event stack */ 194 /* Invoke the hypervisor to initialize the event stack */
194 HvCallEvent_setLpEventStack(0, eventStack, LpEventStackSize); 195 HvCallEvent_setLpEventStack(0, eventStack, IT_LP_EVENT_STACK_SIZE);
195 196
196 hvlpevent_queue.xSlicEventStackPtr = (char *)eventStack; 197 hvlpevent_queue.hq_event_stack = eventStack;
197 hvlpevent_queue.xSlicCurEventPtr = (char *)eventStack; 198 hvlpevent_queue.hq_current_event = eventStack;
198 hvlpevent_queue.xSlicLastValidEventPtr = (char *)eventStack + 199 hvlpevent_queue.hq_last_event = (char *)eventStack +
199 (LpEventStackSize - LpEventMaxSize); 200 (IT_LP_EVENT_STACK_SIZE - IT_LP_EVENT_MAX_SIZE);
200 hvlpevent_queue.xIndex = 0; 201 hvlpevent_queue.hq_index = 0;
201} 202}
202 203
203/* Register a handler for an LpEvent type */ 204/* Register a handler for an LpEvent type */
diff --git a/arch/powerpc/platforms/iseries/proc.c b/arch/powerpc/platforms/iseries/proc.c
index e68b6b5fa89f..c241413629ac 100644
--- a/arch/powerpc/platforms/iseries/proc.c
+++ b/arch/powerpc/platforms/iseries/proc.c
@@ -24,7 +24,6 @@
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/it_lp_queue.h>
28#include <asm/iseries/hv_call_xm.h> 27#include <asm/iseries/hv_call_xm.h>
29 28
30#include "processor_vpd.h" 29#include "processor_vpd.h"
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 617c724c4590..c9605d773a77 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -16,7 +16,6 @@
16 16
17#undef DEBUG 17#undef DEBUG
18 18
19#include <linux/config.h>
20#include <linux/init.h> 19#include <linux/init.h>
21#include <linux/threads.h> 20#include <linux/threads.h>
22#include <linux/smp.h> 21#include <linux/smp.h>
@@ -81,8 +80,6 @@ static void iSeries_pci_final_fixup(void) { }
81#endif 80#endif
82 81
83extern int rd_size; /* Defined in drivers/block/rd.c */ 82extern int rd_size; /* Defined in drivers/block/rd.c */
84extern unsigned long embedded_sysmap_start;
85extern unsigned long embedded_sysmap_end;
86 83
87extern unsigned long iSeries_recal_tb; 84extern unsigned long iSeries_recal_tb;
88extern unsigned long iSeries_recal_titan; 85extern unsigned long iSeries_recal_titan;
@@ -297,8 +294,6 @@ static void __init iSeries_init_early(void)
297{ 294{
298 DBG(" -> iSeries_init_early()\n"); 295 DBG(" -> iSeries_init_early()\n");
299 296
300 ppc64_interrupt_controller = IC_ISERIES;
301
302#if defined(CONFIG_BLK_DEV_INITRD) 297#if defined(CONFIG_BLK_DEV_INITRD)
303 /* 298 /*
304 * If the init RAM disk has been configured and there is 299 * If the init RAM disk has been configured and there is
@@ -321,11 +316,6 @@ static void __init iSeries_init_early(void)
321 iSeries_recal_titan = HvCallXm_loadTod(); 316 iSeries_recal_titan = HvCallXm_loadTod();
322 317
323 /* 318 /*
324 * Initialize the hash table management pointers
325 */
326 hpte_init_iSeries();
327
328 /*
329 * Initialize the DMA/TCE management 319 * Initialize the DMA/TCE management
330 */ 320 */
331 iommu_init_early_iSeries(); 321 iommu_init_early_iSeries();
@@ -563,16 +553,6 @@ static void __init iSeries_fixup_klimit(void)
563 if (naca.xRamDisk) 553 if (naca.xRamDisk)
564 klimit = KERNELBASE + (u64)naca.xRamDisk + 554 klimit = KERNELBASE + (u64)naca.xRamDisk +
565 (naca.xRamDiskSize * HW_PAGE_SIZE); 555 (naca.xRamDiskSize * HW_PAGE_SIZE);
566 else {
567 /*
568 * No ram disk was included - check and see if there
569 * was an embedded system map. Change klimit to take
570 * into account any embedded system map
571 */
572 if (embedded_sysmap_end)
573 klimit = KERNELBASE + ((embedded_sysmap_end + 4095) &
574 0xfffffffffffff000);
575 }
576} 556}
577 557
578static int __init iSeries_src_init(void) 558static int __init iSeries_src_init(void)
@@ -677,11 +657,7 @@ static int __init iseries_probe(void)
677 powerpc_firmware_features |= FW_FEATURE_ISERIES; 657 powerpc_firmware_features |= FW_FEATURE_ISERIES;
678 powerpc_firmware_features |= FW_FEATURE_LPAR; 658 powerpc_firmware_features |= FW_FEATURE_LPAR;
679 659
680 /* 660 hpte_init_iSeries();
681 * The Hypervisor only allows us up to 256 interrupt
682 * sources (the irq number is passed in a u8).
683 */
684 virt_irq_max = 255;
685 661
686 return 1; 662 return 1;
687} 663}
diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c
index 6f9d407a709f..2eb095edb472 100644
--- a/arch/powerpc/platforms/iseries/smp.c
+++ b/arch/powerpc/platforms/iseries/smp.c
@@ -14,7 +14,6 @@
14 14
15#undef DEBUG 15#undef DEBUG
16 16
17#include <linux/config.h>
18#include <linux/kernel.h> 17#include <linux/kernel.h>
19#include <linux/module.h> 18#include <linux/module.h>
20#include <linux/sched.h> 19#include <linux/sched.h>
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index 9a4efc0c3b29..63a1670d3bfd 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -376,9 +376,10 @@ static void __init maple_fixup_phb_resources(void)
376 unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base; 376 unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
377 hose->io_resource.start += offset; 377 hose->io_resource.start += offset;
378 hose->io_resource.end += offset; 378 hose->io_resource.end += offset;
379 printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n", 379 printk(KERN_INFO "PCI Host %d, io start: %llx; io end: %llx\n",
380 hose->global_number, 380 hose->global_number,
381 hose->io_resource.start, hose->io_resource.end); 381 (unsigned long long)hose->io_resource.start,
382 (unsigned long long)hose->io_resource.end);
382 } 383 }
383} 384}
384 385
@@ -442,18 +443,23 @@ void __init maple_pci_init(void)
442int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel) 443int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel)
443{ 444{
444 struct device_node *np; 445 struct device_node *np;
445 int irq = channel ? 15 : 14; 446 unsigned int defirq = channel ? 15 : 14;
447 unsigned int irq;
446 448
447 if (pdev->vendor != PCI_VENDOR_ID_AMD || 449 if (pdev->vendor != PCI_VENDOR_ID_AMD ||
448 pdev->device != PCI_DEVICE_ID_AMD_8111_IDE) 450 pdev->device != PCI_DEVICE_ID_AMD_8111_IDE)
449 return irq; 451 return defirq;
450 452
451 np = pci_device_to_OF_node(pdev); 453 np = pci_device_to_OF_node(pdev);
452 if (np == NULL) 454 if (np == NULL)
453 return irq; 455 return defirq;
454 if (np->n_intrs < 2) 456 irq = irq_of_parse_and_map(np, channel & 0x1);
455 return irq; 457 if (irq == NO_IRQ) {
456 return np->intrs[channel & 0x1].line; 458 printk("Failed to map onboard IDE interrupt for channel %d\n",
459 channel);
460 return defirq;
461 }
462 return irq;
457} 463}
458 464
459/* XXX: To remove once all firmwares are ok */ 465/* XXX: To remove once all firmwares are ok */
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index a0505ea48a86..cb528c9de4c3 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -11,9 +11,8 @@
11 * 11 *
12 */ 12 */
13 13
14#define DEBUG 14#undef DEBUG
15 15
16#include <linux/config.h>
17#include <linux/init.h> 16#include <linux/init.h>
18#include <linux/errno.h> 17#include <linux/errno.h>
19#include <linux/sched.h> 18#include <linux/sched.h>
@@ -199,55 +198,81 @@ static void __init maple_init_early(void)
199{ 198{
200 DBG(" -> maple_init_early\n"); 199 DBG(" -> maple_init_early\n");
201 200
202 /* Initialize hash table, from now on, we can take hash faults
203 * and call ioremap
204 */
205 hpte_init_native();
206
207 /* Setup interrupt mapping options */
208 ppc64_interrupt_controller = IC_OPEN_PIC;
209
210 iommu_init_early_dart(); 201 iommu_init_early_dart();
211 202
212 DBG(" <- maple_init_early\n"); 203 DBG(" <- maple_init_early\n");
213} 204}
214 205
215 206/*
216static __init void maple_init_IRQ(void) 207 * This is almost identical to pSeries and CHRP. We need to make that
208 * code generic at one point, with appropriate bits in the device-tree to
209 * identify the presence of an HT APIC
210 */
211static void __init maple_init_IRQ(void)
217{ 212{
218 struct device_node *root; 213 struct device_node *root, *np, *mpic_node = NULL;
219 unsigned int *opprop; 214 unsigned int *opprop;
220 unsigned long opic_addr; 215 unsigned long openpic_addr = 0;
216 int naddr, n, i, opplen, has_isus = 0;
221 struct mpic *mpic; 217 struct mpic *mpic;
222 unsigned char senses[128]; 218 unsigned int flags = MPIC_PRIMARY;
223 int n;
224 219
225 DBG(" -> maple_init_IRQ\n"); 220 /* Locate MPIC in the device-tree. Note that there is a bug
221 * in Maple device-tree where the type of the controller is
222 * open-pic and not interrupt-controller
223 */
224 for_each_node_by_type(np, "open-pic") {
225 mpic_node = np;
226 break;
227 }
228 if (mpic_node == NULL) {
229 printk(KERN_ERR
230 "Failed to locate the MPIC interrupt controller\n");
231 return;
232 }
226 233
227 /* XXX: Non standard, replace that with a proper openpic/mpic node 234 /* Find address list in /platform-open-pic */
228 * in the device-tree. Find the Open PIC if present */
229 root = of_find_node_by_path("/"); 235 root = of_find_node_by_path("/");
230 opprop = (unsigned int *) get_property(root, 236 naddr = prom_n_addr_cells(root);
231 "platform-open-pic", NULL); 237 opprop = (unsigned int *) get_property(root, "platform-open-pic",
232 if (opprop == 0) 238 &opplen);
233 panic("OpenPIC not found !\n"); 239 if (opprop != 0) {
234 240 openpic_addr = of_read_number(opprop, naddr);
235 n = prom_n_addr_cells(root); 241 has_isus = (opplen > naddr);
236 for (opic_addr = 0; n > 0; --n) 242 printk(KERN_DEBUG "OpenPIC addr: %lx, has ISUs: %d\n",
237 opic_addr = (opic_addr << 32) + *opprop++; 243 openpic_addr, has_isus);
244 }
238 of_node_put(root); 245 of_node_put(root);
239 246
240 /* Obtain sense values from device-tree */ 247 BUG_ON(openpic_addr == 0);
241 prom_get_irq_senses(senses, 0, 128);
242 248
243 mpic = mpic_alloc(opic_addr, 249 /* Check for a big endian MPIC */
244 MPIC_PRIMARY | MPIC_BIG_ENDIAN | 250 if (get_property(np, "big-endian", NULL) != NULL)
245 MPIC_BROKEN_U3 | MPIC_WANTS_RESET, 251 flags |= MPIC_BIG_ENDIAN;
246 0, 0, 128, 128, senses, 128, "U3-MPIC"); 252
253 /* XXX Maple specific bits */
254 flags |= MPIC_BROKEN_U3 | MPIC_WANTS_RESET;
255
256 /* Setup the openpic driver. More device-tree junks, we hard code no
257 * ISUs for now. I'll have to revisit some stuffs with the folks doing
258 * the firmware for those
259 */
260 mpic = mpic_alloc(mpic_node, openpic_addr, flags,
261 /*has_isus ? 16 :*/ 0, 0, " MPIC ");
247 BUG_ON(mpic == NULL); 262 BUG_ON(mpic == NULL);
248 mpic_init(mpic);
249 263
250 DBG(" <- maple_init_IRQ\n"); 264 /* Add ISUs */
265 opplen /= sizeof(u32);
266 for (n = 0, i = naddr; i < opplen; i += naddr, n++) {
267 unsigned long isuaddr = of_read_number(opprop + i, naddr);
268 mpic_assign_isu(mpic, n, isuaddr);
269 }
270
271 /* All ISUs are setup, complete initialization */
272 mpic_init(mpic);
273 ppc_md.get_irq = mpic_get_irq;
274 of_node_put(mpic_node);
275 of_node_put(root);
251} 276}
252 277
253static void __init maple_progress(char *s, unsigned short hex) 278static void __init maple_progress(char *s, unsigned short hex)
@@ -262,7 +287,9 @@ static void __init maple_progress(char *s, unsigned short hex)
262static int __init maple_probe(void) 287static int __init maple_probe(void)
263{ 288{
264 unsigned long root = of_get_flat_dt_root(); 289 unsigned long root = of_get_flat_dt_root();
265 if (!of_flat_dt_is_compatible(root, "Momentum,Maple")) 290
291 if (!of_flat_dt_is_compatible(root, "Momentum,Maple") &&
292 !of_flat_dt_is_compatible(root, "Momentum,Apache"))
266 return 0; 293 return 0;
267 /* 294 /*
268 * On U3, the DART (iommu) must be allocated now since it 295 * On U3, the DART (iommu) must be allocated now since it
@@ -272,6 +299,8 @@ static int __init maple_probe(void)
272 */ 299 */
273 alloc_dart_table(); 300 alloc_dart_table();
274 301
302 hpte_init_native();
303
275 return 1; 304 return 1;
276} 305}
277 306
@@ -281,7 +310,6 @@ define_machine(maple_md) {
281 .setup_arch = maple_setup_arch, 310 .setup_arch = maple_setup_arch,
282 .init_early = maple_init_early, 311 .init_early = maple_init_early,
283 .init_IRQ = maple_init_IRQ, 312 .init_IRQ = maple_init_IRQ,
284 .get_irq = mpic_get_irq,
285 .pcibios_fixup = maple_pcibios_fixup, 313 .pcibios_fixup = maple_pcibios_fixup,
286 .pci_get_legacy_ide_irq = maple_pci_get_legacy_ide_irq, 314 .pci_get_legacy_ide_irq = maple_pci_get_legacy_ide_irq,
287 .restart = maple_restart, 315 .restart = maple_restart,
diff --git a/arch/powerpc/platforms/maple/time.c b/arch/powerpc/platforms/maple/time.c
index b9a2b3d4bf33..9f7579b38c72 100644
--- a/arch/powerpc/platforms/maple/time.c
+++ b/arch/powerpc/platforms/maple/time.c
@@ -11,7 +11,6 @@
11 11
12#undef DEBUG 12#undef DEBUG
13 13
14#include <linux/config.h>
15#include <linux/errno.h> 14#include <linux/errno.h>
16#include <linux/sched.h> 15#include <linux/sched.h>
17#include <linux/kernel.h> 16#include <linux/kernel.h>
diff --git a/arch/powerpc/platforms/powermac/backlight.c b/arch/powerpc/platforms/powermac/backlight.c
index 498b042e1837..69f65e215a5c 100644
--- a/arch/powerpc/platforms/powermac/backlight.c
+++ b/arch/powerpc/platforms/powermac/backlight.c
@@ -7,7 +7,6 @@
7 * 7 *
8 */ 8 */
9 9
10#include <linux/config.h>
11#include <linux/kernel.h> 10#include <linux/kernel.h>
12#include <linux/fb.h> 11#include <linux/fb.h>
13#include <linux/backlight.h> 12#include <linux/backlight.h>
@@ -119,7 +118,14 @@ int pmac_backlight_set_legacy_brightness(int brightness)
119 down(&pmac_backlight->sem); 118 down(&pmac_backlight->sem);
120 props = pmac_backlight->props; 119 props = pmac_backlight->props;
121 props->brightness = brightness * 120 props->brightness = brightness *
122 props->max_brightness / OLD_BACKLIGHT_MAX; 121 (props->max_brightness + 1) /
122 (OLD_BACKLIGHT_MAX + 1);
123
124 if (props->brightness > props->max_brightness)
125 props->brightness = props->max_brightness;
126 else if (props->brightness < 0)
127 props->brightness = 0;
128
123 props->update_status(pmac_backlight); 129 props->update_status(pmac_backlight);
124 up(&pmac_backlight->sem); 130 up(&pmac_backlight->sem);
125 131
@@ -140,8 +146,11 @@ int pmac_backlight_get_legacy_brightness()
140 146
141 down(&pmac_backlight->sem); 147 down(&pmac_backlight->sem);
142 props = pmac_backlight->props; 148 props = pmac_backlight->props;
149
143 result = props->brightness * 150 result = props->brightness *
144 OLD_BACKLIGHT_MAX / props->max_brightness; 151 (OLD_BACKLIGHT_MAX + 1) /
152 (props->max_brightness + 1);
153
145 up(&pmac_backlight->sem); 154 up(&pmac_backlight->sem);
146 } 155 }
147 mutex_unlock(&pmac_backlight_mutex); 156 mutex_unlock(&pmac_backlight_mutex);
diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c
index eacbfd9beabc..e63d52f227ee 100644
--- a/arch/powerpc/platforms/powermac/bootx_init.c
+++ b/arch/powerpc/platforms/powermac/bootx_init.c
@@ -9,7 +9,6 @@
9 * 2 of the License, or (at your option) any later version. 9 * 2 of the License, or (at your option) any later version.
10 */ 10 */
11 11
12#include <linux/config.h>
13#include <linux/kernel.h> 12#include <linux/kernel.h>
14#include <linux/string.h> 13#include <linux/string.h>
15#include <linux/init.h> 14#include <linux/init.h>
@@ -163,6 +162,8 @@ static void __init bootx_add_chosen_props(unsigned long base,
163{ 162{
164 u32 val; 163 u32 val;
165 164
165 bootx_dt_add_prop("linux,bootx", NULL, 0, mem_end);
166
166 if (bootx_info->kernelParamsOffset) { 167 if (bootx_info->kernelParamsOffset) {
167 char *args = (char *)((unsigned long)bootx_info) + 168 char *args = (char *)((unsigned long)bootx_info) +
168 bootx_info->kernelParamsOffset; 169 bootx_info->kernelParamsOffset;
@@ -182,8 +183,25 @@ static void __init bootx_add_chosen_props(unsigned long base,
182static void __init bootx_add_display_props(unsigned long base, 183static void __init bootx_add_display_props(unsigned long base,
183 unsigned long *mem_end) 184 unsigned long *mem_end)
184{ 185{
186 boot_infos_t *bi = bootx_info;
187 u32 tmp;
188
185 bootx_dt_add_prop("linux,boot-display", NULL, 0, mem_end); 189 bootx_dt_add_prop("linux,boot-display", NULL, 0, mem_end);
186 bootx_dt_add_prop("linux,opened", NULL, 0, mem_end); 190 bootx_dt_add_prop("linux,opened", NULL, 0, mem_end);
191 tmp = bi->dispDeviceDepth;
192 bootx_dt_add_prop("linux,bootx-depth", &tmp, 4, mem_end);
193 tmp = bi->dispDeviceRect[2] - bi->dispDeviceRect[0];
194 bootx_dt_add_prop("linux,bootx-width", &tmp, 4, mem_end);
195 tmp = bi->dispDeviceRect[3] - bi->dispDeviceRect[1];
196 bootx_dt_add_prop("linux,bootx-height", &tmp, 4, mem_end);
197 tmp = bi->dispDeviceRowBytes;
198 bootx_dt_add_prop("linux,bootx-linebytes", &tmp, 4, mem_end);
199 tmp = (u32)bi->dispDeviceBase;
200 if (tmp == 0)
201 tmp = (u32)bi->logicalDisplayBase;
202 tmp += bi->dispDeviceRect[1] * bi->dispDeviceRowBytes;
203 tmp += bi->dispDeviceRect[0] * ((bi->dispDeviceDepth + 7) / 8);
204 bootx_dt_add_prop("linux,bootx-addr", &tmp, 4, mem_end);
187} 205}
188 206
189static void __init bootx_dt_add_string(char *s, unsigned long *mem_end) 207static void __init bootx_dt_add_string(char *s, unsigned long *mem_end)
@@ -212,7 +230,7 @@ static void __init bootx_scan_dt_build_strings(unsigned long base,
212 230
213 if (!strcmp(namep, "/chosen")) { 231 if (!strcmp(namep, "/chosen")) {
214 DBG(" detected /chosen ! adding properties names !\n"); 232 DBG(" detected /chosen ! adding properties names !\n");
215 bootx_dt_add_string("linux,platform", mem_end); 233 bootx_dt_add_string("linux,bootx", mem_end);
216 bootx_dt_add_string("linux,stdout-path", mem_end); 234 bootx_dt_add_string("linux,stdout-path", mem_end);
217 bootx_dt_add_string("linux,initrd-start", mem_end); 235 bootx_dt_add_string("linux,initrd-start", mem_end);
218 bootx_dt_add_string("linux,initrd-end", mem_end); 236 bootx_dt_add_string("linux,initrd-end", mem_end);
@@ -223,6 +241,11 @@ static void __init bootx_scan_dt_build_strings(unsigned long base,
223 DBG(" detected display ! adding properties names !\n"); 241 DBG(" detected display ! adding properties names !\n");
224 bootx_dt_add_string("linux,boot-display", mem_end); 242 bootx_dt_add_string("linux,boot-display", mem_end);
225 bootx_dt_add_string("linux,opened", mem_end); 243 bootx_dt_add_string("linux,opened", mem_end);
244 bootx_dt_add_string("linux,bootx-depth", mem_end);
245 bootx_dt_add_string("linux,bootx-width", mem_end);
246 bootx_dt_add_string("linux,bootx-height", mem_end);
247 bootx_dt_add_string("linux,bootx-linebytes", mem_end);
248 bootx_dt_add_string("linux,bootx-addr", mem_end);
226 strncpy(bootx_disp_path, namep, 255); 249 strncpy(bootx_disp_path, namep, 255);
227 } 250 }
228 251
@@ -444,7 +467,14 @@ void __init bootx_init(unsigned long r3, unsigned long r4)
444 if (!BOOT_INFO_IS_V2_COMPATIBLE(bi)) 467 if (!BOOT_INFO_IS_V2_COMPATIBLE(bi))
445 bi->logicalDisplayBase = bi->dispDeviceBase; 468 bi->logicalDisplayBase = bi->dispDeviceBase;
446 469
470 /* Fixup depth 16 -> 15 as that's what MacOS calls 16bpp */
471 if (bi->dispDeviceDepth == 16)
472 bi->dispDeviceDepth = 15;
473
447#ifdef CONFIG_BOOTX_TEXT 474#ifdef CONFIG_BOOTX_TEXT
475 ptr = (unsigned long)bi->logicalDisplayBase;
476 ptr += bi->dispDeviceRect[1] * bi->dispDeviceRowBytes;
477 ptr += bi->dispDeviceRect[0] * ((bi->dispDeviceDepth + 7) / 8);
448 btext_setup_display(bi->dispDeviceRect[2] - bi->dispDeviceRect[0], 478 btext_setup_display(bi->dispDeviceRect[2] - bi->dispDeviceRect[0],
449 bi->dispDeviceRect[3] - bi->dispDeviceRect[1], 479 bi->dispDeviceRect[3] - bi->dispDeviceRect[1],
450 bi->dispDeviceDepth, bi->dispDeviceRowBytes, 480 bi->dispDeviceDepth, bi->dispDeviceRowBytes,
diff --git a/arch/powerpc/platforms/powermac/cache.S b/arch/powerpc/platforms/powermac/cache.S
index fb977de6b704..6be1a4af3359 100644
--- a/arch/powerpc/platforms/powermac/cache.S
+++ b/arch/powerpc/platforms/powermac/cache.S
@@ -14,7 +14,6 @@
14 * 14 *
15 */ 15 */
16 16
17#include <linux/config.h>
18#include <asm/processor.h> 17#include <asm/processor.h>
19#include <asm/ppc_asm.h> 18#include <asm/ppc_asm.h>
20#include <asm/cputable.h> 19#include <asm/cputable.h>
diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c
index af2a8f9f1222..62926248bdb8 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_32.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_32.c
@@ -13,7 +13,6 @@
13 * 13 *
14 */ 14 */
15 15
16#include <linux/config.h>
17#include <linux/module.h> 16#include <linux/module.h>
18#include <linux/types.h> 17#include <linux/types.h>
19#include <linux/errno.h> 18#include <linux/errno.h>
@@ -68,7 +67,7 @@ static unsigned int cur_freq;
68static unsigned int sleep_freq; 67static unsigned int sleep_freq;
69 68
70/* 69/*
71 * Different models uses different mecanisms to switch the frequency 70 * Different models uses different mechanisms to switch the frequency
72 */ 71 */
73static int (*set_speed_proc)(int low_speed); 72static int (*set_speed_proc)(int low_speed);
74static unsigned int (*get_speed_proc)(void); 73static unsigned int (*get_speed_proc)(void);
@@ -268,7 +267,7 @@ static int pmu_set_cpu_speed(int low_speed)
268 267
269 /* Make sure the decrementer won't interrupt us */ 268 /* Make sure the decrementer won't interrupt us */
270 asm volatile("mtdec %0" : : "r" (0x7fffffff)); 269 asm volatile("mtdec %0" : : "r" (0x7fffffff));
271 /* Make sure any pending DEC interrupt occuring while we did 270 /* Make sure any pending DEC interrupt occurring while we did
272 * the above didn't re-enable the DEC */ 271 * the above didn't re-enable the DEC */
273 mb(); 272 mb();
274 asm volatile("mtdec %0" : : "r" (0x7fffffff)); 273 asm volatile("mtdec %0" : : "r" (0x7fffffff));
diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c
index b57e465a1b71..f08a14516139 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_64.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_64.c
@@ -10,7 +10,6 @@
10 * that is iMac G5 and latest single CPU desktop. 10 * that is iMac G5 and latest single CPU desktop.
11 */ 11 */
12 12
13#include <linux/config.h>
14#include <linux/module.h> 13#include <linux/module.h>
15#include <linux/types.h> 14#include <linux/types.h>
16#include <linux/errno.h> 15#include <linux/errno.h>
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index 85e00cb0006e..f8313bf9a9f7 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -16,7 +16,6 @@
16 * - Split split split... 16 * - Split split split...
17 * 17 *
18 */ 18 */
19#include <linux/config.h>
20#include <linux/types.h> 19#include <linux/types.h>
21#include <linux/init.h> 20#include <linux/init.h>
22#include <linux/delay.h> 21#include <linux/delay.h>
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index c896ce83d412..8677f50c2586 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -30,7 +30,6 @@
30#undef DEBUG 30#undef DEBUG
31#undef DEBUG_LOW 31#undef DEBUG_LOW
32 32
33#include <linux/config.h>
34#include <linux/types.h> 33#include <linux/types.h>
35#include <linux/sched.h> 34#include <linux/sched.h>
36#include <linux/init.h> 35#include <linux/init.h>
@@ -523,10 +522,11 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np)
523 host->speed = KW_I2C_MODE_25KHZ; 522 host->speed = KW_I2C_MODE_25KHZ;
524 break; 523 break;
525 } 524 }
526 if (np->n_intrs > 0) 525 host->irq = irq_of_parse_and_map(np, 0);
527 host->irq = np->intrs[0].line; 526 if (host->irq == NO_IRQ)
528 else 527 printk(KERN_WARNING
529 host->irq = NO_IRQ; 528 "low_i2c: Failed to map interrupt for %s\n",
529 np->full_name);
530 530
531 host->base = ioremap((*addrp), 0x1000); 531 host->base = ioremap((*addrp), 0x1000);
532 if (host->base == NULL) { 532 if (host->base == NULL) {
diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c
index 262f967b880a..6a36ea9bf673 100644
--- a/arch/powerpc/platforms/powermac/nvram.c
+++ b/arch/powerpc/platforms/powermac/nvram.c
@@ -8,7 +8,6 @@
8 * 8 *
9 * Todo: - add support for the OF persistent properties 9 * Todo: - add support for the OF persistent properties
10 */ 10 */
11#include <linux/config.h>
12#include <linux/module.h> 11#include <linux/module.h>
13#include <linux/kernel.h> 12#include <linux/kernel.h>
14#include <linux/stddef.h> 13#include <linux/stddef.h>
@@ -30,6 +29,8 @@
30#include <asm/machdep.h> 29#include <asm/machdep.h>
31#include <asm/nvram.h> 30#include <asm/nvram.h>
32 31
32#include "pmac.h"
33
33#define DEBUG 34#define DEBUG
34 35
35#ifdef DEBUG 36#ifdef DEBUG
@@ -81,9 +82,6 @@ static int nvram_partitions[3];
81// XXX Turn that into a sem 82// XXX Turn that into a sem
82static DEFINE_SPINLOCK(nv_lock); 83static DEFINE_SPINLOCK(nv_lock);
83 84
84extern int pmac_newworld;
85extern int system_running;
86
87static int (*core99_write_bank)(int bank, u8* datas); 85static int (*core99_write_bank)(int bank, u8* datas);
88static int (*core99_erase_bank)(int bank); 86static int (*core99_erase_bank)(int bank);
89 87
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index 80035853467b..556b349797e8 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -46,6 +46,9 @@ static int has_uninorth;
46static struct pci_controller *u3_agp; 46static struct pci_controller *u3_agp;
47static struct pci_controller *u4_pcie; 47static struct pci_controller *u4_pcie;
48static struct pci_controller *u3_ht; 48static struct pci_controller *u3_ht;
49#define has_second_ohare 0
50#else
51static int has_second_ohare;
49#endif /* CONFIG_PPC64 */ 52#endif /* CONFIG_PPC64 */
50 53
51extern u8 pci_cache_line_size; 54extern u8 pci_cache_line_size;
@@ -647,6 +650,33 @@ static void __init init_p2pbridge(void)
647 early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val); 650 early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val);
648} 651}
649 652
653static void __init init_second_ohare(void)
654{
655 struct device_node *np = of_find_node_by_name(NULL, "pci106b,7");
656 unsigned char bus, devfn;
657 unsigned short cmd;
658
659 if (np == NULL)
660 return;
661
662 /* This must run before we initialize the PICs since the second
663 * ohare hosts a PIC that will be accessed there.
664 */
665 if (pci_device_from_OF_node(np, &bus, &devfn) == 0) {
666 struct pci_controller* hose =
667 pci_find_hose_for_OF_device(np);
668 if (!hose) {
669 printk(KERN_ERR "Can't find PCI hose for OHare2 !\n");
670 return;
671 }
672 early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd);
673 cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
674 cmd &= ~PCI_COMMAND_IO;
675 early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd);
676 }
677 has_second_ohare = 1;
678}
679
650/* 680/*
651 * Some Apple desktop machines have a NEC PD720100A USB2 controller 681 * Some Apple desktop machines have a NEC PD720100A USB2 controller
652 * on the motherboard. Open Firmware, on these, will disable the 682 * on the motherboard. Open Firmware, on these, will disable the
@@ -688,9 +718,6 @@ static void __init fixup_nec_usb2(void)
688 " EHCI, fixing up...\n"); 718 " EHCI, fixing up...\n");
689 data &= ~1UL; 719 data &= ~1UL;
690 early_write_config_dword(hose, bus, devfn, 0xe4, data); 720 early_write_config_dword(hose, bus, devfn, 0xe4, data);
691 early_write_config_byte(hose, bus,
692 devfn | 2, PCI_INTERRUPT_LINE,
693 nec->intrs[0].line);
694 } 721 }
695 } 722 }
696} 723}
@@ -939,9 +966,10 @@ static int __init add_bridge(struct device_node *dev)
939 disp_name = "Chaos"; 966 disp_name = "Chaos";
940 primary = 0; 967 primary = 0;
941 } 968 }
942 printk(KERN_INFO "Found %s PCI host bridge at 0x%08lx. " 969 printk(KERN_INFO "Found %s PCI host bridge at 0x%016llx. "
943 "Firmware bus number: %d->%d\n", 970 "Firmware bus number: %d->%d\n",
944 disp_name, rsrc.start, hose->first_busno, hose->last_busno); 971 disp_name, (unsigned long long)rsrc.start, hose->first_busno,
972 hose->last_busno);
945#endif /* CONFIG_PPC32 */ 973#endif /* CONFIG_PPC32 */
946 974
947 DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", 975 DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
@@ -957,32 +985,28 @@ static int __init add_bridge(struct device_node *dev)
957 return 0; 985 return 0;
958} 986}
959 987
960static void __init pcibios_fixup_OF_interrupts(void) 988void __init pmac_pcibios_fixup(void)
961{ 989{
962 struct pci_dev* dev = NULL; 990 struct pci_dev* dev = NULL;
963 991
964 /*
965 * Open Firmware often doesn't initialize the
966 * PCI_INTERRUPT_LINE config register properly, so we
967 * should find the device node and apply the interrupt
968 * obtained from the OF device-tree
969 */
970 for_each_pci_dev(dev) { 992 for_each_pci_dev(dev) {
971 struct device_node *node; 993 /* Read interrupt from the device-tree */
972 node = pci_device_to_OF_node(dev); 994 pci_read_irq_line(dev);
973 /* this is the node, see if it has interrupts */ 995
974 if (node && node->n_intrs > 0) 996 /* Fixup interrupt for the modem/ethernet combo controller.
975 dev->irq = node->intrs[0].line; 997 * on machines with a second ohare chip.
976 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); 998 * The number in the device tree (27) is bogus (correct for
999 * the ethernet-only board but not the combo ethernet/modem
1000 * board). The real interrupt is 28 on the second controller
1001 * -> 28+32 = 60.
1002 */
1003 if (has_second_ohare &&
1004 dev->vendor == PCI_VENDOR_ID_DEC &&
1005 dev->device == PCI_DEVICE_ID_DEC_TULIP_PLUS)
1006 dev->irq = irq_create_mapping(NULL, 60, 0);
977 } 1007 }
978} 1008}
979 1009
980void __init pmac_pcibios_fixup(void)
981{
982 /* Fixup interrupts according to OF tree */
983 pcibios_fixup_OF_interrupts();
984}
985
986#ifdef CONFIG_PPC64 1010#ifdef CONFIG_PPC64
987static void __init pmac_fixup_phb_resources(void) 1011static void __init pmac_fixup_phb_resources(void)
988{ 1012{
@@ -1070,6 +1094,7 @@ void __init pmac_pci_init(void)
1070 1094
1071#else /* CONFIG_PPC64 */ 1095#else /* CONFIG_PPC64 */
1072 init_p2pbridge(); 1096 init_p2pbridge();
1097 init_second_ohare();
1073 fixup_nec_usb2(); 1098 fixup_nec_usb2();
1074 1099
1075 /* We are still having some issues with the Xserve G4, enabling 1100 /* We are still having some issues with the Xserve G4, enabling
diff --git a/arch/powerpc/platforms/powermac/pfunc_base.c b/arch/powerpc/platforms/powermac/pfunc_base.c
index a3bd3e728fa3..6d66359ec8c8 100644
--- a/arch/powerpc/platforms/powermac/pfunc_base.c
+++ b/arch/powerpc/platforms/powermac/pfunc_base.c
@@ -1,4 +1,3 @@
1#include <linux/config.h>
2#include <linux/types.h> 1#include <linux/types.h>
3#include <linux/init.h> 2#include <linux/init.h>
4#include <linux/delay.h> 3#include <linux/delay.h>
@@ -25,19 +24,18 @@ static irqreturn_t macio_gpio_irq(int irq, void *data, struct pt_regs *regs)
25 24
26static int macio_do_gpio_irq_enable(struct pmf_function *func) 25static int macio_do_gpio_irq_enable(struct pmf_function *func)
27{ 26{
28 if (func->node->n_intrs < 1) 27 unsigned int irq = irq_of_parse_and_map(func->node, 0);
28 if (irq == NO_IRQ)
29 return -EINVAL; 29 return -EINVAL;
30 30 return request_irq(irq, macio_gpio_irq, 0, func->node->name, func);
31 return request_irq(func->node->intrs[0].line, macio_gpio_irq, 0,
32 func->node->name, func);
33} 31}
34 32
35static int macio_do_gpio_irq_disable(struct pmf_function *func) 33static int macio_do_gpio_irq_disable(struct pmf_function *func)
36{ 34{
37 if (func->node->n_intrs < 1) 35 unsigned int irq = irq_of_parse_and_map(func->node, 0);
36 if (irq == NO_IRQ)
38 return -EINVAL; 37 return -EINVAL;
39 38 free_irq(irq, func);
40 free_irq(func->node->intrs[0].line, func);
41 return 0; 39 return 0;
42} 40}
43 41
diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c
index 047f954a89eb..b117adbf9571 100644
--- a/arch/powerpc/platforms/powermac/pfunc_core.c
+++ b/arch/powerpc/platforms/powermac/pfunc_core.c
@@ -5,7 +5,6 @@
5 * FIXME: LOCKING !!! 5 * FIXME: LOCKING !!!
6 */ 6 */
7 7
8#include <linux/config.h>
9#include <linux/init.h> 8#include <linux/init.h>
10#include <linux/delay.h> 9#include <linux/delay.h>
11#include <linux/kernel.h> 10#include <linux/kernel.h>
@@ -546,7 +545,7 @@ struct pmf_device {
546}; 545};
547 546
548static LIST_HEAD(pmf_devices); 547static LIST_HEAD(pmf_devices);
549static spinlock_t pmf_lock = SPIN_LOCK_UNLOCKED; 548static DEFINE_SPINLOCK(pmf_lock);
550static DEFINE_MUTEX(pmf_irq_mutex); 549static DEFINE_MUTEX(pmf_irq_mutex);
551 550
552static void pmf_release_device(struct kref *kref) 551static void pmf_release_device(struct kref *kref)
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 18bf3011d1e3..3d328bc1f7e0 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -15,7 +15,6 @@
15 * 15 *
16 */ 16 */
17 17
18#include <linux/config.h>
19#include <linux/stddef.h> 18#include <linux/stddef.h>
20#include <linux/init.h> 19#include <linux/init.h>
21#include <linux/sched.h> 20#include <linux/sched.h>
@@ -66,39 +65,36 @@ static u32 level_mask[4];
66 65
67static DEFINE_SPINLOCK(pmac_pic_lock); 66static DEFINE_SPINLOCK(pmac_pic_lock);
68 67
69#define GATWICK_IRQ_POOL_SIZE 10
70static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE];
71
72#define NR_MASK_WORDS ((NR_IRQS + 31) / 32) 68#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
73static unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; 69static unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
70static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
71static int pmac_irq_cascade = -1;
72static struct irq_host *pmac_pic_host;
74 73
75/* 74static void __pmac_retrigger(unsigned int irq_nr)
76 * Mark an irq as "lost". This is only used on the pmac
77 * since it can lose interrupts (see pmac_set_irq_mask).
78 * -- Cort
79 */
80void __set_lost(unsigned long irq_nr, int nokick)
81{ 75{
82 if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) { 76 if (irq_nr >= max_real_irqs && pmac_irq_cascade > 0) {
77 __set_bit(irq_nr, ppc_lost_interrupts);
78 irq_nr = pmac_irq_cascade;
79 mb();
80 }
81 if (!__test_and_set_bit(irq_nr, ppc_lost_interrupts)) {
83 atomic_inc(&ppc_n_lost_interrupts); 82 atomic_inc(&ppc_n_lost_interrupts);
84 if (!nokick) 83 set_dec(1);
85 set_dec(1);
86 } 84 }
87} 85}
88 86
89static void pmac_mask_and_ack_irq(unsigned int irq_nr) 87static void pmac_mask_and_ack_irq(unsigned int virq)
90{ 88{
91 unsigned long bit = 1UL << (irq_nr & 0x1f); 89 unsigned int src = irq_map[virq].hwirq;
92 int i = irq_nr >> 5; 90 unsigned long bit = 1UL << (virq & 0x1f);
91 int i = virq >> 5;
93 unsigned long flags; 92 unsigned long flags;
94 93
95 if ((unsigned)irq_nr >= max_irqs)
96 return;
97
98 clear_bit(irq_nr, ppc_cached_irq_mask);
99 if (test_and_clear_bit(irq_nr, ppc_lost_interrupts))
100 atomic_dec(&ppc_n_lost_interrupts);
101 spin_lock_irqsave(&pmac_pic_lock, flags); 94 spin_lock_irqsave(&pmac_pic_lock, flags);
95 __clear_bit(src, ppc_cached_irq_mask);
96 if (__test_and_clear_bit(src, ppc_lost_interrupts))
97 atomic_dec(&ppc_n_lost_interrupts);
102 out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); 98 out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
103 out_le32(&pmac_irq_hw[i]->ack, bit); 99 out_le32(&pmac_irq_hw[i]->ack, bit);
104 do { 100 do {
@@ -110,16 +106,29 @@ static void pmac_mask_and_ack_irq(unsigned int irq_nr)
110 spin_unlock_irqrestore(&pmac_pic_lock, flags); 106 spin_unlock_irqrestore(&pmac_pic_lock, flags);
111} 107}
112 108
113static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost) 109static void pmac_ack_irq(unsigned int virq)
110{
111 unsigned int src = irq_map[virq].hwirq;
112 unsigned long bit = 1UL << (src & 0x1f);
113 int i = src >> 5;
114 unsigned long flags;
115
116 spin_lock_irqsave(&pmac_pic_lock, flags);
117 if (__test_and_clear_bit(src, ppc_lost_interrupts))
118 atomic_dec(&ppc_n_lost_interrupts);
119 out_le32(&pmac_irq_hw[i]->ack, bit);
120 (void)in_le32(&pmac_irq_hw[i]->ack);
121 spin_unlock_irqrestore(&pmac_pic_lock, flags);
122}
123
124static void __pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
114{ 125{
115 unsigned long bit = 1UL << (irq_nr & 0x1f); 126 unsigned long bit = 1UL << (irq_nr & 0x1f);
116 int i = irq_nr >> 5; 127 int i = irq_nr >> 5;
117 unsigned long flags;
118 128
119 if ((unsigned)irq_nr >= max_irqs) 129 if ((unsigned)irq_nr >= max_irqs)
120 return; 130 return;
121 131
122 spin_lock_irqsave(&pmac_pic_lock, flags);
123 /* enable unmasked interrupts */ 132 /* enable unmasked interrupts */
124 out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); 133 out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
125 134
@@ -136,71 +145,78 @@ static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
136 * the bit in the flag register or request another interrupt. 145 * the bit in the flag register or request another interrupt.
137 */ 146 */
138 if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level)) 147 if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level))
139 __set_lost((ulong)irq_nr, nokicklost); 148 __pmac_retrigger(irq_nr);
140 spin_unlock_irqrestore(&pmac_pic_lock, flags);
141} 149}
142 150
143/* When an irq gets requested for the first client, if it's an 151/* When an irq gets requested for the first client, if it's an
144 * edge interrupt, we clear any previous one on the controller 152 * edge interrupt, we clear any previous one on the controller
145 */ 153 */
146static unsigned int pmac_startup_irq(unsigned int irq_nr) 154static unsigned int pmac_startup_irq(unsigned int virq)
147{ 155{
148 unsigned long bit = 1UL << (irq_nr & 0x1f); 156 unsigned long flags;
149 int i = irq_nr >> 5; 157 unsigned int src = irq_map[virq].hwirq;
158 unsigned long bit = 1UL << (src & 0x1f);
159 int i = src >> 5;
150 160
151 if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0) 161 spin_lock_irqsave(&pmac_pic_lock, flags);
162 if ((irq_desc[virq].status & IRQ_LEVEL) == 0)
152 out_le32(&pmac_irq_hw[i]->ack, bit); 163 out_le32(&pmac_irq_hw[i]->ack, bit);
153 set_bit(irq_nr, ppc_cached_irq_mask); 164 __set_bit(src, ppc_cached_irq_mask);
154 pmac_set_irq_mask(irq_nr, 0); 165 __pmac_set_irq_mask(src, 0);
166 spin_unlock_irqrestore(&pmac_pic_lock, flags);
155 167
156 return 0; 168 return 0;
157} 169}
158 170
159static void pmac_mask_irq(unsigned int irq_nr) 171static void pmac_mask_irq(unsigned int virq)
160{ 172{
161 clear_bit(irq_nr, ppc_cached_irq_mask); 173 unsigned long flags;
162 pmac_set_irq_mask(irq_nr, 0); 174 unsigned int src = irq_map[virq].hwirq;
163 mb(); 175
176 spin_lock_irqsave(&pmac_pic_lock, flags);
177 __clear_bit(src, ppc_cached_irq_mask);
178 __pmac_set_irq_mask(src, 0);
179 spin_unlock_irqrestore(&pmac_pic_lock, flags);
164} 180}
165 181
166static void pmac_unmask_irq(unsigned int irq_nr) 182static void pmac_unmask_irq(unsigned int virq)
167{ 183{
168 set_bit(irq_nr, ppc_cached_irq_mask); 184 unsigned long flags;
169 pmac_set_irq_mask(irq_nr, 0); 185 unsigned int src = irq_map[virq].hwirq;
186
187 spin_lock_irqsave(&pmac_pic_lock, flags);
188 __set_bit(src, ppc_cached_irq_mask);
189 __pmac_set_irq_mask(src, 0);
190 spin_unlock_irqrestore(&pmac_pic_lock, flags);
170} 191}
171 192
172static void pmac_end_irq(unsigned int irq_nr) 193static int pmac_retrigger(unsigned int virq)
173{ 194{
174 if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS)) 195 unsigned long flags;
175 && irq_desc[irq_nr].action) {
176 set_bit(irq_nr, ppc_cached_irq_mask);
177 pmac_set_irq_mask(irq_nr, 1);
178 }
179}
180 196
197 spin_lock_irqsave(&pmac_pic_lock, flags);
198 __pmac_retrigger(irq_map[virq].hwirq);
199 spin_unlock_irqrestore(&pmac_pic_lock, flags);
200 return 1;
201}
181 202
182struct hw_interrupt_type pmac_pic = { 203static struct irq_chip pmac_pic = {
183 .typename = " PMAC-PIC ", 204 .typename = " PMAC-PIC ",
184 .startup = pmac_startup_irq, 205 .startup = pmac_startup_irq,
185 .enable = pmac_unmask_irq, 206 .mask = pmac_mask_irq,
186 .disable = pmac_mask_irq, 207 .ack = pmac_ack_irq,
187 .ack = pmac_mask_and_ack_irq, 208 .mask_ack = pmac_mask_and_ack_irq,
188 .end = pmac_end_irq, 209 .unmask = pmac_unmask_irq,
189}; 210 .retrigger = pmac_retrigger,
190
191struct hw_interrupt_type gatwick_pic = {
192 .typename = " GATWICK ",
193 .startup = pmac_startup_irq,
194 .enable = pmac_unmask_irq,
195 .disable = pmac_mask_irq,
196 .ack = pmac_mask_and_ack_irq,
197 .end = pmac_end_irq,
198}; 211};
199 212
200static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs) 213static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
201{ 214{
215 unsigned long flags;
202 int irq, bits; 216 int irq, bits;
217 int rc = IRQ_NONE;
203 218
219 spin_lock_irqsave(&pmac_pic_lock, flags);
204 for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) { 220 for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) {
205 int i = irq >> 5; 221 int i = irq >> 5;
206 bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i]; 222 bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
@@ -210,17 +226,20 @@ static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
210 if (bits == 0) 226 if (bits == 0)
211 continue; 227 continue;
212 irq += __ilog2(bits); 228 irq += __ilog2(bits);
229 spin_unlock_irqrestore(&pmac_pic_lock, flags);
213 __do_IRQ(irq, regs); 230 __do_IRQ(irq, regs);
214 return IRQ_HANDLED; 231 spin_lock_irqsave(&pmac_pic_lock, flags);
232 rc = IRQ_HANDLED;
215 } 233 }
216 printk("gatwick irq not from gatwick pic\n"); 234 spin_unlock_irqrestore(&pmac_pic_lock, flags);
217 return IRQ_NONE; 235 return rc;
218} 236}
219 237
220static int pmac_get_irq(struct pt_regs *regs) 238static unsigned int pmac_pic_get_irq(struct pt_regs *regs)
221{ 239{
222 int irq; 240 int irq;
223 unsigned long bits = 0; 241 unsigned long bits = 0;
242 unsigned long flags;
224 243
225#ifdef CONFIG_SMP 244#ifdef CONFIG_SMP
226 void psurge_smp_message_recv(struct pt_regs *); 245 void psurge_smp_message_recv(struct pt_regs *);
@@ -228,9 +247,10 @@ static int pmac_get_irq(struct pt_regs *regs)
228 /* IPI's are a hack on the powersurge -- Cort */ 247 /* IPI's are a hack on the powersurge -- Cort */
229 if ( smp_processor_id() != 0 ) { 248 if ( smp_processor_id() != 0 ) {
230 psurge_smp_message_recv(regs); 249 psurge_smp_message_recv(regs);
231 return -2; /* ignore, already handled */ 250 return NO_IRQ_IGNORE; /* ignore, already handled */
232 } 251 }
233#endif /* CONFIG_SMP */ 252#endif /* CONFIG_SMP */
253 spin_lock_irqsave(&pmac_pic_lock, flags);
234 for (irq = max_real_irqs; (irq -= 32) >= 0; ) { 254 for (irq = max_real_irqs; (irq -= 32) >= 0; ) {
235 int i = irq >> 5; 255 int i = irq >> 5;
236 bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i]; 256 bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
@@ -242,133 +262,10 @@ static int pmac_get_irq(struct pt_regs *regs)
242 irq += __ilog2(bits); 262 irq += __ilog2(bits);
243 break; 263 break;
244 } 264 }
245 265 spin_unlock_irqrestore(&pmac_pic_lock, flags);
246 return irq; 266 if (unlikely(irq < 0))
247} 267 return NO_IRQ;
248 268 return irq_linear_revmap(pmac_pic_host, irq);
249/* This routine will fix some missing interrupt values in the device tree
250 * on the gatwick mac-io controller used by some PowerBooks
251 *
252 * Walking of OF nodes could use a bit more fixing up here, but it's not
253 * very important as this is all boot time code on static portions of the
254 * device-tree.
255 *
256 * However, the modifications done to "intrs" will have to be removed and
257 * replaced with proper updates of the "interrupts" properties or
258 * AAPL,interrupts, yet to be decided, once the dynamic parsing is there.
259 */
260static void __init pmac_fix_gatwick_interrupts(struct device_node *gw,
261 int irq_base)
262{
263 struct device_node *node;
264 int count;
265
266 memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool));
267 count = 0;
268 for (node = NULL; (node = of_get_next_child(gw, node)) != NULL;) {
269 /* Fix SCC */
270 if ((strcasecmp(node->name, "escc") == 0) && node->child) {
271 if (node->child->n_intrs < 3) {
272 node->child->intrs = &gatwick_int_pool[count];
273 count += 3;
274 }
275 node->child->n_intrs = 3;
276 node->child->intrs[0].line = 15+irq_base;
277 node->child->intrs[1].line = 4+irq_base;
278 node->child->intrs[2].line = 5+irq_base;
279 printk(KERN_INFO "irq: fixed SCC on gatwick"
280 " (%d,%d,%d)\n",
281 node->child->intrs[0].line,
282 node->child->intrs[1].line,
283 node->child->intrs[2].line);
284 }
285 /* Fix media-bay & left SWIM */
286 if (strcasecmp(node->name, "media-bay") == 0) {
287 struct device_node* ya_node;
288
289 if (node->n_intrs == 0)
290 node->intrs = &gatwick_int_pool[count++];
291 node->n_intrs = 1;
292 node->intrs[0].line = 29+irq_base;
293 printk(KERN_INFO "irq: fixed media-bay on gatwick"
294 " (%d)\n", node->intrs[0].line);
295
296 ya_node = node->child;
297 while(ya_node) {
298 if (strcasecmp(ya_node->name, "floppy") == 0) {
299 if (ya_node->n_intrs < 2) {
300 ya_node->intrs = &gatwick_int_pool[count];
301 count += 2;
302 }
303 ya_node->n_intrs = 2;
304 ya_node->intrs[0].line = 19+irq_base;
305 ya_node->intrs[1].line = 1+irq_base;
306 printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n",
307 ya_node->intrs[0].line, ya_node->intrs[1].line);
308 }
309 if (strcasecmp(ya_node->name, "ata4") == 0) {
310 if (ya_node->n_intrs < 2) {
311 ya_node->intrs = &gatwick_int_pool[count];
312 count += 2;
313 }
314 ya_node->n_intrs = 2;
315 ya_node->intrs[0].line = 14+irq_base;
316 ya_node->intrs[1].line = 3+irq_base;
317 printk(KERN_INFO "irq: fixed ide on second controller (%d,%d)\n",
318 ya_node->intrs[0].line, ya_node->intrs[1].line);
319 }
320 ya_node = ya_node->sibling;
321 }
322 }
323 }
324 if (count > 10) {
325 printk("WARNING !! Gatwick interrupt pool overflow\n");
326 printk(" GATWICK_IRQ_POOL_SIZE = %d\n", GATWICK_IRQ_POOL_SIZE);
327 printk(" requested = %d\n", count);
328 }
329}
330
331/*
332 * The PowerBook 3400/2400/3500 can have a combo ethernet/modem
333 * card which includes an ohare chip that acts as a second interrupt
334 * controller. If we find this second ohare, set it up and fix the
335 * interrupt value in the device tree for the ethernet chip.
336 */
337static void __init enable_second_ohare(struct device_node *np)
338{
339 unsigned char bus, devfn;
340 unsigned short cmd;
341 struct device_node *ether;
342
343 /* This code doesn't strictly belong here, it could be part of
344 * either the PCI initialisation or the feature code. It's kept
345 * here for historical reasons.
346 */
347 if (pci_device_from_OF_node(np, &bus, &devfn) == 0) {
348 struct pci_controller* hose =
349 pci_find_hose_for_OF_device(np);
350 if (!hose) {
351 printk(KERN_ERR "Can't find PCI hose for OHare2 !\n");
352 return;
353 }
354 early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd);
355 cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
356 cmd &= ~PCI_COMMAND_IO;
357 early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd);
358 }
359
360 /* Fix interrupt for the modem/ethernet combo controller. The number
361 * in the device tree (27) is bogus (correct for the ethernet-only
362 * board but not the combo ethernet/modem board).
363 * The real interrupt is 28 on the second controller -> 28+32 = 60.
364 */
365 ether = of_find_node_by_name(NULL, "pci1011,14");
366 if (ether && ether->n_intrs > 0) {
367 ether->intrs[0].line = 60;
368 printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n",
369 ether->intrs[0].line);
370 }
371 of_node_put(ether);
372} 269}
373 270
374#ifdef CONFIG_XMON 271#ifdef CONFIG_XMON
@@ -382,22 +279,65 @@ static struct irqaction xmon_action = {
382 279
383static struct irqaction gatwick_cascade_action = { 280static struct irqaction gatwick_cascade_action = {
384 .handler = gatwick_action, 281 .handler = gatwick_action,
385 .flags = SA_INTERRUPT, 282 .flags = IRQF_DISABLED,
386 .mask = CPU_MASK_NONE, 283 .mask = CPU_MASK_NONE,
387 .name = "cascade", 284 .name = "cascade",
388}; 285};
389 286
287static int pmac_pic_host_match(struct irq_host *h, struct device_node *node)
288{
289 /* We match all, we don't always have a node anyway */
290 return 1;
291}
292
293static int pmac_pic_host_map(struct irq_host *h, unsigned int virq,
294 irq_hw_number_t hw, unsigned int flags)
295{
296 struct irq_desc *desc = get_irq_desc(virq);
297 int level;
298
299 if (hw >= max_irqs)
300 return -EINVAL;
301
302 /* Mark level interrupts, set delayed disable for edge ones and set
303 * handlers
304 */
305 level = !!(level_mask[hw >> 5] & (1UL << (hw & 0x1f)));
306 if (level)
307 desc->status |= IRQ_LEVEL;
308 else
309 desc->status |= IRQ_DELAYED_DISABLE;
310 set_irq_chip_and_handler(virq, &pmac_pic, level ?
311 handle_level_irq : handle_edge_irq);
312 return 0;
313}
314
315static int pmac_pic_host_xlate(struct irq_host *h, struct device_node *ct,
316 u32 *intspec, unsigned int intsize,
317 irq_hw_number_t *out_hwirq,
318 unsigned int *out_flags)
319
320{
321 *out_hwirq = *intspec;
322 return 0;
323}
324
325static struct irq_host_ops pmac_pic_host_ops = {
326 .match = pmac_pic_host_match,
327 .map = pmac_pic_host_map,
328 .xlate = pmac_pic_host_xlate,
329};
330
390static void __init pmac_pic_probe_oldstyle(void) 331static void __init pmac_pic_probe_oldstyle(void)
391{ 332{
392 int i; 333 int i;
393 int irq_cascade = -1;
394 struct device_node *master = NULL; 334 struct device_node *master = NULL;
395 struct device_node *slave = NULL; 335 struct device_node *slave = NULL;
396 u8 __iomem *addr; 336 u8 __iomem *addr;
397 struct resource r; 337 struct resource r;
398 338
399 /* Set our get_irq function */ 339 /* Set our get_irq function */
400 ppc_md.get_irq = pmac_get_irq; 340 ppc_md.get_irq = pmac_pic_get_irq;
401 341
402 /* 342 /*
403 * Find the interrupt controller type & node 343 * Find the interrupt controller type & node
@@ -415,7 +355,6 @@ static void __init pmac_pic_probe_oldstyle(void)
415 if (slave) { 355 if (slave) {
416 max_irqs = 64; 356 max_irqs = 64;
417 level_mask[1] = OHARE_LEVEL_MASK; 357 level_mask[1] = OHARE_LEVEL_MASK;
418 enable_second_ohare(slave);
419 } 358 }
420 } else if ((master = of_find_node_by_name(NULL, "mac-io")) != NULL) { 359 } else if ((master = of_find_node_by_name(NULL, "mac-io")) != NULL) {
421 max_irqs = max_real_irqs = 64; 360 max_irqs = max_real_irqs = 64;
@@ -439,14 +378,18 @@ static void __init pmac_pic_probe_oldstyle(void)
439 max_irqs = 128; 378 max_irqs = 128;
440 level_mask[2] = HEATHROW_LEVEL_MASK; 379 level_mask[2] = HEATHROW_LEVEL_MASK;
441 level_mask[3] = 0; 380 level_mask[3] = 0;
442 pmac_fix_gatwick_interrupts(slave, max_real_irqs);
443 } 381 }
444 } 382 }
445 BUG_ON(master == NULL); 383 BUG_ON(master == NULL);
446 384
447 /* Set the handler for the main PIC */ 385 /*
448 for ( i = 0; i < max_real_irqs ; i++ ) 386 * Allocate an irq host
449 irq_desc[i].handler = &pmac_pic; 387 */
388 pmac_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, max_irqs,
389 &pmac_pic_host_ops,
390 max_irqs);
391 BUG_ON(pmac_pic_host == NULL);
392 irq_set_default_host(pmac_pic_host);
450 393
451 /* Get addresses of first controller if we have a node for it */ 394 /* Get addresses of first controller if we have a node for it */
452 BUG_ON(of_address_to_resource(master, 0, &r)); 395 BUG_ON(of_address_to_resource(master, 0, &r));
@@ -473,39 +416,38 @@ static void __init pmac_pic_probe_oldstyle(void)
473 pmac_irq_hw[i++] = 416 pmac_irq_hw[i++] =
474 (volatile struct pmac_irq_hw __iomem *) 417 (volatile struct pmac_irq_hw __iomem *)
475 (addr + 0x10); 418 (addr + 0x10);
476 irq_cascade = slave->intrs[0].line; 419 pmac_irq_cascade = irq_of_parse_and_map(slave, 0);
477 420
478 printk(KERN_INFO "irq: Found slave Apple PIC %s for %d irqs" 421 printk(KERN_INFO "irq: Found slave Apple PIC %s for %d irqs"
479 " cascade: %d\n", slave->full_name, 422 " cascade: %d\n", slave->full_name,
480 max_irqs - max_real_irqs, irq_cascade); 423 max_irqs - max_real_irqs, pmac_irq_cascade);
481 } 424 }
482 of_node_put(slave); 425 of_node_put(slave);
483 426
484 /* disable all interrupts in all controllers */ 427 /* Disable all interrupts in all controllers */
485 for (i = 0; i * 32 < max_irqs; ++i) 428 for (i = 0; i * 32 < max_irqs; ++i)
486 out_le32(&pmac_irq_hw[i]->enable, 0); 429 out_le32(&pmac_irq_hw[i]->enable, 0);
487 430
488 /* mark level interrupts */ 431 /* Hookup cascade irq */
489 for (i = 0; i < max_irqs; i++) 432 if (slave && pmac_irq_cascade != NO_IRQ)
490 if (level_mask[i >> 5] & (1UL << (i & 0x1f))) 433 setup_irq(pmac_irq_cascade, &gatwick_cascade_action);
491 irq_desc[i].status = IRQ_LEVEL;
492 434
493 /* Setup handlers for secondary controller and hook cascade irq*/
494 if (slave) {
495 for ( i = max_real_irqs ; i < max_irqs ; i++ )
496 irq_desc[i].handler = &gatwick_pic;
497 setup_irq(irq_cascade, &gatwick_cascade_action);
498 }
499 printk(KERN_INFO "irq: System has %d possible interrupts\n", max_irqs); 435 printk(KERN_INFO "irq: System has %d possible interrupts\n", max_irqs);
500#ifdef CONFIG_XMON 436#ifdef CONFIG_XMON
501 setup_irq(20, &xmon_action); 437 setup_irq(irq_create_mapping(NULL, 20, 0), &xmon_action);
502#endif 438#endif
503} 439}
504#endif /* CONFIG_PPC32 */ 440#endif /* CONFIG_PPC32 */
505 441
506static int pmac_u3_cascade(struct pt_regs *regs, void *data) 442static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc,
443 struct pt_regs *regs)
507{ 444{
508 return mpic_get_one_irq((struct mpic *)data, regs); 445 struct mpic *mpic = desc->handler_data;
446
447 unsigned int cascade_irq = mpic_get_one_irq(mpic, regs);
448 if (cascade_irq != NO_IRQ)
449 generic_handle_irq(cascade_irq, regs);
450 desc->chip->eoi(irq);
509} 451}
510 452
511static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic) 453static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic)
@@ -515,21 +457,20 @@ static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic)
515 int nmi_irq; 457 int nmi_irq;
516 458
517 pswitch = of_find_node_by_name(NULL, "programmer-switch"); 459 pswitch = of_find_node_by_name(NULL, "programmer-switch");
518 if (pswitch && pswitch->n_intrs) { 460 if (pswitch) {
519 nmi_irq = pswitch->intrs[0].line; 461 nmi_irq = irq_of_parse_and_map(pswitch, 0);
520 mpic_irq_set_priority(nmi_irq, 9); 462 if (nmi_irq != NO_IRQ) {
521 setup_irq(nmi_irq, &xmon_action); 463 mpic_irq_set_priority(nmi_irq, 9);
464 setup_irq(nmi_irq, &xmon_action);
465 }
466 of_node_put(pswitch);
522 } 467 }
523 of_node_put(pswitch);
524#endif /* defined(CONFIG_XMON) && defined(CONFIG_PPC32) */ 468#endif /* defined(CONFIG_XMON) && defined(CONFIG_PPC32) */
525} 469}
526 470
527static struct mpic * __init pmac_setup_one_mpic(struct device_node *np, 471static struct mpic * __init pmac_setup_one_mpic(struct device_node *np,
528 int master) 472 int master)
529{ 473{
530 unsigned char senses[128];
531 int offset = master ? 0 : 128;
532 int count = master ? 128 : 124;
533 const char *name = master ? " MPIC 1 " : " MPIC 2 "; 474 const char *name = master ? " MPIC 1 " : " MPIC 2 ";
534 struct resource r; 475 struct resource r;
535 struct mpic *mpic; 476 struct mpic *mpic;
@@ -542,8 +483,6 @@ static struct mpic * __init pmac_setup_one_mpic(struct device_node *np,
542 483
543 pmac_call_feature(PMAC_FTR_ENABLE_MPIC, np, 0, 0); 484 pmac_call_feature(PMAC_FTR_ENABLE_MPIC, np, 0, 0);
544 485
545 prom_get_irq_senses(senses, offset, offset + count);
546
547 flags |= MPIC_WANTS_RESET; 486 flags |= MPIC_WANTS_RESET;
548 if (get_property(np, "big-endian", NULL)) 487 if (get_property(np, "big-endian", NULL))
549 flags |= MPIC_BIG_ENDIAN; 488 flags |= MPIC_BIG_ENDIAN;
@@ -554,8 +493,7 @@ static struct mpic * __init pmac_setup_one_mpic(struct device_node *np,
554 if (master && (flags & MPIC_BIG_ENDIAN)) 493 if (master && (flags & MPIC_BIG_ENDIAN))
555 flags |= MPIC_BROKEN_U3; 494 flags |= MPIC_BROKEN_U3;
556 495
557 mpic = mpic_alloc(r.start, flags, 0, offset, count, master ? 252 : 0, 496 mpic = mpic_alloc(np, r.start, flags, 0, 0, name);
558 senses, count, name);
559 if (mpic == NULL) 497 if (mpic == NULL)
560 return NULL; 498 return NULL;
561 499
@@ -568,6 +506,7 @@ static int __init pmac_pic_probe_mpic(void)
568{ 506{
569 struct mpic *mpic1, *mpic2; 507 struct mpic *mpic1, *mpic2;
570 struct device_node *np, *master = NULL, *slave = NULL; 508 struct device_node *np, *master = NULL, *slave = NULL;
509 unsigned int cascade;
571 510
572 /* We can have up to 2 MPICs cascaded */ 511 /* We can have up to 2 MPICs cascaded */
573 for (np = NULL; (np = of_find_node_by_type(np, "open-pic")) 512 for (np = NULL; (np = of_find_node_by_type(np, "open-pic"))
@@ -604,8 +543,15 @@ static int __init pmac_pic_probe_mpic(void)
604 of_node_put(master); 543 of_node_put(master);
605 544
606 /* No slave, let's go out */ 545 /* No slave, let's go out */
607 if (slave == NULL || slave->n_intrs < 1) 546 if (slave == NULL)
547 return 0;
548
549 /* Get/Map slave interrupt */
550 cascade = irq_of_parse_and_map(slave, 0);
551 if (cascade == NO_IRQ) {
552 printk(KERN_ERR "Failed to map cascade IRQ\n");
608 return 0; 553 return 0;
554 }
609 555
610 mpic2 = pmac_setup_one_mpic(slave, 0); 556 mpic2 = pmac_setup_one_mpic(slave, 0);
611 if (mpic2 == NULL) { 557 if (mpic2 == NULL) {
@@ -613,7 +559,8 @@ static int __init pmac_pic_probe_mpic(void)
613 of_node_put(slave); 559 of_node_put(slave);
614 return 0; 560 return 0;
615 } 561 }
616 mpic_setup_cascade(slave->intrs[0].line, pmac_u3_cascade, mpic2); 562 set_irq_data(cascade, mpic2);
563 set_irq_chained_handler(cascade, pmac_u3_cascade);
617 564
618 of_node_put(slave); 565 of_node_put(slave);
619 return 0; 566 return 0;
@@ -622,6 +569,19 @@ static int __init pmac_pic_probe_mpic(void)
622 569
623void __init pmac_pic_init(void) 570void __init pmac_pic_init(void)
624{ 571{
572 unsigned int flags = 0;
573
574 /* We configure the OF parsing based on our oldworld vs. newworld
575 * platform type and wether we were booted by BootX.
576 */
577#ifdef CONFIG_PPC32
578 if (!pmac_newworld)
579 flags |= OF_IMAP_OLDWORLD_MAC;
580 if (get_property(of_chosen, "linux,bootx", NULL) != NULL)
581 flags |= OF_IMAP_NO_PHANDLE;
582 of_irq_map_init(flags);
583#endif /* CONFIG_PPC_32 */
584
625 /* We first try to detect Apple's new Core99 chipset, since mac-io 585 /* We first try to detect Apple's new Core99 chipset, since mac-io
626 * is quite different on those machines and contains an IBM MPIC2. 586 * is quite different on those machines and contains an IBM MPIC2.
627 */ 587 */
@@ -644,6 +604,7 @@ unsigned long sleep_save_mask[2];
644 604
645/* This used to be passed by the PMU driver but that link got 605/* This used to be passed by the PMU driver but that link got
646 * broken with the new driver model. We use this tweak for now... 606 * broken with the new driver model. We use this tweak for now...
607 * We really want to do things differently though...
647 */ 608 */
648static int pmacpic_find_viaint(void) 609static int pmacpic_find_viaint(void)
649{ 610{
@@ -657,7 +618,7 @@ static int pmacpic_find_viaint(void)
657 np = of_find_node_by_name(NULL, "via-pmu"); 618 np = of_find_node_by_name(NULL, "via-pmu");
658 if (np == NULL) 619 if (np == NULL)
659 goto not_found; 620 goto not_found;
660 viaint = np->intrs[0].line; 621 viaint = irq_of_parse_and_map(np, 0);;
661#endif /* CONFIG_ADB_PMU */ 622#endif /* CONFIG_ADB_PMU */
662 623
663not_found: 624not_found:
diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h
index 21c7b0f8f329..94e7b24b840b 100644
--- a/arch/powerpc/platforms/powermac/pmac.h
+++ b/arch/powerpc/platforms/powermac/pmac.h
@@ -12,6 +12,8 @@
12 12
13struct rtc_time; 13struct rtc_time;
14 14
15extern int pmac_newworld;
16
15extern long pmac_time_init(void); 17extern long pmac_time_init(void);
16extern unsigned long pmac_get_boot_time(void); 18extern unsigned long pmac_get_boot_time(void);
17extern void pmac_get_rtc_time(struct rtc_time *); 19extern void pmac_get_rtc_time(struct rtc_time *);
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 9cc7db7a8bdc..31a9da769fa2 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -23,7 +23,6 @@
23 * bootup setup stuff.. 23 * bootup setup stuff..
24 */ 24 */
25 25
26#include <linux/config.h>
27#include <linux/init.h> 26#include <linux/init.h>
28#include <linux/errno.h> 27#include <linux/errno.h>
29#include <linux/sched.h> 28#include <linux/sched.h>
@@ -600,13 +599,6 @@ pmac_halt(void)
600 */ 599 */
601static void __init pmac_init_early(void) 600static void __init pmac_init_early(void)
602{ 601{
603#ifdef CONFIG_PPC64
604 /* Initialize hash table, from now on, we can take hash faults
605 * and call ioremap
606 */
607 hpte_init_native();
608#endif
609
610 /* Enable early btext debug if requested */ 602 /* Enable early btext debug if requested */
611 if (strstr(cmd_line, "btextdbg")) { 603 if (strstr(cmd_line, "btextdbg")) {
612 udbg_adb_init_early(); 604 udbg_adb_init_early();
@@ -621,9 +613,6 @@ static void __init pmac_init_early(void)
621 udbg_adb_init(!!strstr(cmd_line, "btextdbg")); 613 udbg_adb_init(!!strstr(cmd_line, "btextdbg"));
622 614
623#ifdef CONFIG_PPC64 615#ifdef CONFIG_PPC64
624 /* Setup interrupt mapping options */
625 ppc64_interrupt_controller = IC_OPEN_PIC;
626
627 iommu_init_early_dart(); 616 iommu_init_early_dart();
628#endif 617#endif
629} 618}
@@ -683,6 +672,8 @@ static int __init pmac_probe(void)
683 * part of the cacheable linar mapping 672 * part of the cacheable linar mapping
684 */ 673 */
685 alloc_dart_table(); 674 alloc_dart_table();
675
676 hpte_init_native();
686#endif 677#endif
687 678
688#ifdef CONFIG_PPC32 679#ifdef CONFIG_PPC32
diff --git a/arch/powerpc/platforms/powermac/sleep.S b/arch/powerpc/platforms/powermac/sleep.S
index 22b113d19b24..1174ca128efa 100644
--- a/arch/powerpc/platforms/powermac/sleep.S
+++ b/arch/powerpc/platforms/powermac/sleep.S
@@ -10,7 +10,6 @@
10 * 10 *
11 */ 11 */
12 12
13#include <linux/config.h>
14#include <asm/processor.h> 13#include <asm/processor.h>
15#include <asm/page.h> 14#include <asm/page.h>
16#include <asm/ppc_asm.h> 15#include <asm/ppc_asm.h>
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 1065d87fc279..827b7121ffb8 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -21,7 +21,6 @@
21 * as published by the Free Software Foundation; either version 21 * as published by the Free Software Foundation; either version
22 * 2 of the License, or (at your option) any later version. 22 * 2 of the License, or (at your option) any later version.
23 */ 23 */
24#include <linux/config.h>
25#include <linux/kernel.h> 24#include <linux/kernel.h>
26#include <linux/sched.h> 25#include <linux/sched.h>
27#include <linux/smp.h> 26#include <linux/smp.h>
@@ -378,7 +377,7 @@ static void __init psurge_dual_sync_tb(int cpu_nr)
378 377
379static struct irqaction psurge_irqaction = { 378static struct irqaction psurge_irqaction = {
380 .handler = psurge_primary_intr, 379 .handler = psurge_primary_intr,
381 .flags = SA_INTERRUPT, 380 .flags = IRQF_DISABLED,
382 .mask = CPU_MASK_NONE, 381 .mask = CPU_MASK_NONE,
383 .name = "primary IPI", 382 .name = "primary IPI",
384}; 383};
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c
index 890758aa9667..a4173906e945 100644
--- a/arch/powerpc/platforms/powermac/time.c
+++ b/arch/powerpc/platforms/powermac/time.c
@@ -9,7 +9,6 @@
9 * Copyright (C) 2003-2005 Benjamin Herrenschmidt. 9 * Copyright (C) 2003-2005 Benjamin Herrenschmidt.
10 * 10 *
11 */ 11 */
12#include <linux/config.h>
13#include <linux/errno.h> 12#include <linux/errno.h>
14#include <linux/sched.h> 13#include <linux/sched.h>
15#include <linux/kernel.h> 14#include <linux/kernel.h>
diff --git a/arch/powerpc/platforms/powermac/udbg_adb.c b/arch/powerpc/platforms/powermac/udbg_adb.c
index 06c8265c2baf..6124e59e1038 100644
--- a/arch/powerpc/platforms/powermac/udbg_adb.c
+++ b/arch/powerpc/platforms/powermac/udbg_adb.c
@@ -1,4 +1,3 @@
1#include <linux/config.h>
2#include <linux/string.h> 1#include <linux/string.h>
3#include <linux/kernel.h> 2#include <linux/kernel.h>
4#include <linux/errno.h> 3#include <linux/errno.h>
diff --git a/arch/powerpc/platforms/powermac/udbg_scc.c b/arch/powerpc/platforms/powermac/udbg_scc.c
index b4fa9f03b461..37e5b1eff911 100644
--- a/arch/powerpc/platforms/powermac/udbg_scc.c
+++ b/arch/powerpc/platforms/powermac/udbg_scc.c
@@ -8,7 +8,6 @@
8 * as published by the Free Software Foundation; either version 8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version. 9 * 2 of the License, or (at your option) any later version.
10 */ 10 */
11#include <linux/config.h>
12#include <linux/types.h> 11#include <linux/types.h>
13#include <asm/udbg.h> 12#include <asm/udbg.h>
14#include <asm/processor.h> 13#include <asm/processor.h>
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c
index 98c23aec85be..c37a8497c60f 100644
--- a/arch/powerpc/platforms/pseries/eeh_cache.c
+++ b/arch/powerpc/platforms/pseries/eeh_cache.c
@@ -287,7 +287,7 @@ void pci_addr_cache_remove_device(struct pci_dev *dev)
287 * find the pci device that corresponds to a given address. 287 * find the pci device that corresponds to a given address.
288 * This routine scans all pci busses to build the cache. 288 * This routine scans all pci busses to build the cache.
289 * Must be run late in boot process, after the pci controllers 289 * Must be run late in boot process, after the pci controllers
290 * have been scaned for devices (after all device resources are known). 290 * have been scanned for devices (after all device resources are known).
291 */ 291 */
292void __init pci_addr_cache_build(void) 292void __init pci_addr_cache_build(void)
293{ 293{
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index 0ec9a5445b95..aaad2c0afcbf 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -175,7 +175,7 @@ static void eeh_report_failure(struct pci_dev *dev, void *userdata)
175 * 175 *
176 * pSeries systems will isolate a PCI slot if the PCI-Host 176 * pSeries systems will isolate a PCI slot if the PCI-Host
177 * bridge detects address or data parity errors, DMA's 177 * bridge detects address or data parity errors, DMA's
178 * occuring to wild addresses (which usually happen due to 178 * occurring to wild addresses (which usually happen due to
179 * bugs in device drivers or in PCI adapter firmware). 179 * bugs in device drivers or in PCI adapter firmware).
180 * Slot isolations also occur if #SERR, #PERR or other misc 180 * Slot isolations also occur if #SERR, #PERR or other misc
181 * PCI-related errors are detected. 181 * PCI-related errors are detected.
diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c
index 8f2d12935b99..45ccc687e57c 100644
--- a/arch/powerpc/platforms/pseries/eeh_event.c
+++ b/arch/powerpc/platforms/pseries/eeh_event.c
@@ -35,7 +35,7 @@
35 */ 35 */
36 36
37/* EEH event workqueue setup. */ 37/* EEH event workqueue setup. */
38static spinlock_t eeh_eventlist_lock = SPIN_LOCK_UNLOCKED; 38static DEFINE_SPINLOCK(eeh_eventlist_lock);
39LIST_HEAD(eeh_eventlist); 39LIST_HEAD(eeh_eventlist);
40static void eeh_thread_launcher(void *); 40static void eeh_thread_launcher(void *);
41DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL); 41DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL);
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index d03a8b078f9d..d67af2c65754 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -24,7 +24,6 @@
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */ 25 */
26 26
27#include <linux/config.h>
28#include <linux/init.h> 27#include <linux/init.h>
29#include <linux/types.h> 28#include <linux/types.h>
30#include <linux/slab.h> 29#include <linux/slab.h>
@@ -92,6 +91,15 @@ static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages)
92 *(tcep++) = 0; 91 *(tcep++) = 0;
93} 92}
94 93
94static unsigned long tce_get_pseries(struct iommu_table *tbl, long index)
95{
96 u64 *tcep;
97
98 index <<= TCE_PAGE_FACTOR;
99 tcep = ((u64 *)tbl->it_base) + index;
100
101 return *tcep;
102}
95 103
96static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, 104static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
97 long npages, unsigned long uaddr, 105 long npages, unsigned long uaddr,
@@ -235,6 +243,25 @@ static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long n
235 } 243 }
236} 244}
237 245
246static unsigned long tce_get_pSeriesLP(struct iommu_table *tbl, long tcenum)
247{
248 u64 rc;
249 unsigned long tce_ret;
250
251 tcenum <<= TCE_PAGE_FACTOR;
252 rc = plpar_tce_get((u64)tbl->it_index, (u64)tcenum << 12, &tce_ret);
253
254 if (rc && printk_ratelimit()) {
255 printk("tce_get_pSeriesLP: plpar_tce_get failed. rc=%ld\n",
256 rc);
257 printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
258 printk("\ttcenum = 0x%lx\n", (u64)tcenum);
259 show_stack(current, (unsigned long *)__get_SP());
260 }
261
262 return tce_ret;
263}
264
238static void iommu_table_setparms(struct pci_controller *phb, 265static void iommu_table_setparms(struct pci_controller *phb,
239 struct device_node *dn, 266 struct device_node *dn,
240 struct iommu_table *tbl) 267 struct iommu_table *tbl)
@@ -254,7 +281,10 @@ static void iommu_table_setparms(struct pci_controller *phb,
254 } 281 }
255 282
256 tbl->it_base = (unsigned long)__va(*basep); 283 tbl->it_base = (unsigned long)__va(*basep);
284
285#ifndef CONFIG_CRASH_DUMP
257 memset((void *)tbl->it_base, 0, *sizep); 286 memset((void *)tbl->it_base, 0, *sizep);
287#endif
258 288
259 tbl->it_busno = phb->bus->number; 289 tbl->it_busno = phb->bus->number;
260 290
@@ -560,11 +590,13 @@ void iommu_init_early_pSeries(void)
560 ppc_md.tce_build = tce_build_pSeriesLP; 590 ppc_md.tce_build = tce_build_pSeriesLP;
561 ppc_md.tce_free = tce_free_pSeriesLP; 591 ppc_md.tce_free = tce_free_pSeriesLP;
562 } 592 }
593 ppc_md.tce_get = tce_get_pSeriesLP;
563 ppc_md.iommu_bus_setup = iommu_bus_setup_pSeriesLP; 594 ppc_md.iommu_bus_setup = iommu_bus_setup_pSeriesLP;
564 ppc_md.iommu_dev_setup = iommu_dev_setup_pSeriesLP; 595 ppc_md.iommu_dev_setup = iommu_dev_setup_pSeriesLP;
565 } else { 596 } else {
566 ppc_md.tce_build = tce_build_pSeries; 597 ppc_md.tce_build = tce_build_pSeries;
567 ppc_md.tce_free = tce_free_pSeries; 598 ppc_md.tce_free = tce_free_pSeries;
599 ppc_md.tce_get = tce_get_pseries;
568 ppc_md.iommu_bus_setup = iommu_bus_setup_pSeries; 600 ppc_md.iommu_bus_setup = iommu_bus_setup_pSeries;
569 ppc_md.iommu_dev_setup = iommu_dev_setup_pSeries; 601 ppc_md.iommu_dev_setup = iommu_dev_setup_pSeries;
570 } 602 }
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 634b7d06d3cc..3aeb40699042 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -21,7 +21,6 @@
21 21
22#undef DEBUG_LOW 22#undef DEBUG_LOW
23 23
24#include <linux/config.h>
25#include <linux/kernel.h> 24#include <linux/kernel.h>
26#include <linux/dma-mapping.h> 25#include <linux/dma-mapping.h>
27#include <linux/console.h> 26#include <linux/console.h>
@@ -513,7 +512,7 @@ void pSeries_lpar_flush_hash_range(unsigned long number, int local)
513 spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); 512 spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags);
514} 513}
515 514
516void hpte_init_lpar(void) 515void __init hpte_init_lpar(void)
517{ 516{
518 ppc_md.hpte_invalidate = pSeries_lpar_hpte_invalidate; 517 ppc_md.hpte_invalidate = pSeries_lpar_hpte_invalidate;
519 ppc_md.hpte_updatepp = pSeries_lpar_hpte_updatepp; 518 ppc_md.hpte_updatepp = pSeries_lpar_hpte_updatepp;
@@ -522,6 +521,4 @@ void hpte_init_lpar(void)
522 ppc_md.hpte_remove = pSeries_lpar_hpte_remove; 521 ppc_md.hpte_remove = pSeries_lpar_hpte_remove;
523 ppc_md.flush_hash_range = pSeries_lpar_flush_hash_range; 522 ppc_md.flush_hash_range = pSeries_lpar_flush_hash_range;
524 ppc_md.hpte_clear_all = pSeries_lpar_hptab_clear; 523 ppc_md.hpte_clear_all = pSeries_lpar_hptab_clear;
525
526 htab_finish_init();
527} 524}
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index 9639c66b453d..9df783088b61 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -72,32 +72,62 @@ static irqreturn_t ras_error_interrupt(int irq, void *dev_id,
72 72
73/* #define DEBUG */ 73/* #define DEBUG */
74 74
75static void request_ras_irqs(struct device_node *np, char *propname, 75
76static void request_ras_irqs(struct device_node *np,
76 irqreturn_t (*handler)(int, void *, struct pt_regs *), 77 irqreturn_t (*handler)(int, void *, struct pt_regs *),
77 const char *name) 78 const char *name)
78{ 79{
79 unsigned int *ireg, len, i; 80 int i, index, count = 0;
80 int virq, n_intr; 81 struct of_irq oirq;
81 82 u32 *opicprop;
82 ireg = (unsigned int *)get_property(np, propname, &len); 83 unsigned int opicplen;
83 if (ireg == NULL) 84 unsigned int virqs[16];
84 return; 85
85 n_intr = prom_n_intr_cells(np); 86 /* Check for obsolete "open-pic-interrupt" property. If present, then
86 len /= n_intr * sizeof(*ireg); 87 * map those interrupts using the default interrupt host and default
87 88 * trigger
88 for (i = 0; i < len; i++) { 89 */
89 virq = virt_irq_create_mapping(*ireg); 90 opicprop = (u32 *)get_property(np, "open-pic-interrupt", &opicplen);
90 if (virq == NO_IRQ) { 91 if (opicprop) {
91 printk(KERN_ERR "Unable to allocate interrupt " 92 opicplen /= sizeof(u32);
92 "number for %s\n", np->full_name); 93 for (i = 0; i < opicplen; i++) {
93 return; 94 if (count > 15)
95 break;
96 virqs[count] = irq_create_mapping(NULL, *(opicprop++),
97 IRQ_TYPE_NONE);
98 if (virqs[count] == NO_IRQ)
99 printk(KERN_ERR "Unable to allocate interrupt "
100 "number for %s\n", np->full_name);
101 else
102 count++;
103
94 } 104 }
95 if (request_irq(irq_offset_up(virq), handler, 0, name, NULL)) { 105 }
106 /* Else use normal interrupt tree parsing */
107 else {
108 /* First try to do a proper OF tree parsing */
109 for (index = 0; of_irq_map_one(np, index, &oirq) == 0;
110 index++) {
111 if (count > 15)
112 break;
113 virqs[count] = irq_create_of_mapping(oirq.controller,
114 oirq.specifier,
115 oirq.size);
116 if (virqs[count] == NO_IRQ)
117 printk(KERN_ERR "Unable to allocate interrupt "
118 "number for %s\n", np->full_name);
119 else
120 count++;
121 }
122 }
123
124 /* Now request them */
125 for (i = 0; i < count; i++) {
126 if (request_irq(virqs[i], handler, 0, name, NULL)) {
96 printk(KERN_ERR "Unable to request interrupt %d for " 127 printk(KERN_ERR "Unable to request interrupt %d for "
97 "%s\n", irq_offset_up(virq), np->full_name); 128 "%s\n", virqs[i], np->full_name);
98 return; 129 return;
99 } 130 }
100 ireg += n_intr;
101 } 131 }
102} 132}
103 133
@@ -115,20 +145,14 @@ static int __init init_ras_IRQ(void)
115 /* Internal Errors */ 145 /* Internal Errors */
116 np = of_find_node_by_path("/event-sources/internal-errors"); 146 np = of_find_node_by_path("/event-sources/internal-errors");
117 if (np != NULL) { 147 if (np != NULL) {
118 request_ras_irqs(np, "open-pic-interrupt", ras_error_interrupt, 148 request_ras_irqs(np, ras_error_interrupt, "RAS_ERROR");
119 "RAS_ERROR");
120 request_ras_irqs(np, "interrupts", ras_error_interrupt,
121 "RAS_ERROR");
122 of_node_put(np); 149 of_node_put(np);
123 } 150 }
124 151
125 /* EPOW Events */ 152 /* EPOW Events */
126 np = of_find_node_by_path("/event-sources/epow-events"); 153 np = of_find_node_by_path("/event-sources/epow-events");
127 if (np != NULL) { 154 if (np != NULL) {
128 request_ras_irqs(np, "open-pic-interrupt", ras_epow_interrupt, 155 request_ras_irqs(np, ras_epow_interrupt, "RAS_EPOW");
129 "RAS_EPOW");
130 request_ras_irqs(np, "interrupts", ras_epow_interrupt,
131 "RAS_EPOW");
132 of_node_put(np); 156 of_node_put(np);
133 } 157 }
134 158
@@ -162,7 +186,7 @@ ras_epow_interrupt(int irq, void *dev_id, struct pt_regs * regs)
162 186
163 status = rtas_call(ras_check_exception_token, 6, 1, NULL, 187 status = rtas_call(ras_check_exception_token, 6, 1, NULL,
164 RAS_VECTOR_OFFSET, 188 RAS_VECTOR_OFFSET,
165 virt_irq_to_real(irq_offset_down(irq)), 189 irq_map[irq].hwirq,
166 RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS, 190 RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS,
167 critical, __pa(&ras_log_buf), 191 critical, __pa(&ras_log_buf),
168 rtas_get_error_log_max()); 192 rtas_get_error_log_max());
@@ -198,7 +222,7 @@ ras_error_interrupt(int irq, void *dev_id, struct pt_regs * regs)
198 222
199 status = rtas_call(ras_check_exception_token, 6, 1, NULL, 223 status = rtas_call(ras_check_exception_token, 6, 1, NULL,
200 RAS_VECTOR_OFFSET, 224 RAS_VECTOR_OFFSET,
201 virt_irq_to_real(irq_offset_down(irq)), 225 irq_map[irq].hwirq,
202 RTAS_INTERNAL_ERROR, 1 /*Time Critical */, 226 RTAS_INTERNAL_ERROR, 1 /*Time Critical */,
203 __pa(&ras_log_buf), 227 __pa(&ras_log_buf),
204 rtas_get_error_log_max()); 228 rtas_get_error_log_max());
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 1e28518c6121..54a52437265c 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -18,7 +18,6 @@
18 18
19#undef DEBUG 19#undef DEBUG
20 20
21#include <linux/config.h>
22#include <linux/cpu.h> 21#include <linux/cpu.h>
23#include <linux/errno.h> 22#include <linux/errno.h>
24#include <linux/sched.h> 23#include <linux/sched.h>
@@ -77,6 +76,9 @@
77#define DBG(fmt...) 76#define DBG(fmt...)
78#endif 77#endif
79 78
79/* move those away to a .h */
80extern void smp_init_pseries_mpic(void);
81extern void smp_init_pseries_xics(void);
80extern void find_udbg_vterm(void); 82extern void find_udbg_vterm(void);
81 83
82int fwnmi_active; /* TRUE if an FWNMI handler is present */ 84int fwnmi_active; /* TRUE if an FWNMI handler is present */
@@ -84,7 +86,7 @@ int fwnmi_active; /* TRUE if an FWNMI handler is present */
84static void pseries_shared_idle_sleep(void); 86static void pseries_shared_idle_sleep(void);
85static void pseries_dedicated_idle_sleep(void); 87static void pseries_dedicated_idle_sleep(void);
86 88
87struct mpic *pSeries_mpic; 89static struct device_node *pSeries_mpic_node;
88 90
89static void pSeries_show_cpuinfo(struct seq_file *m) 91static void pSeries_show_cpuinfo(struct seq_file *m)
90{ 92{
@@ -119,63 +121,92 @@ static void __init fwnmi_init(void)
119 fwnmi_active = 1; 121 fwnmi_active = 1;
120} 122}
121 123
122static void __init pSeries_init_mpic(void) 124void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc,
125 struct pt_regs *regs)
123{ 126{
124 unsigned int *addrp; 127 unsigned int cascade_irq = i8259_irq(regs);
125 struct device_node *np; 128 if (cascade_irq != NO_IRQ)
126 unsigned long intack = 0; 129 generic_handle_irq(cascade_irq, regs);
127 130 desc->chip->eoi(irq);
128 /* All ISUs are setup, complete initialization */
129 mpic_init(pSeries_mpic);
130
131 /* Check what kind of cascade ACK we have */
132 if (!(np = of_find_node_by_name(NULL, "pci"))
133 || !(addrp = (unsigned int *)
134 get_property(np, "8259-interrupt-acknowledge", NULL)))
135 printk(KERN_ERR "Cannot find pci to get ack address\n");
136 else
137 intack = addrp[prom_n_addr_cells(np)-1];
138 of_node_put(np);
139
140 /* Setup the legacy interrupts & controller */
141 i8259_init(intack, 0);
142
143 /* Hook cascade to mpic */
144 mpic_setup_cascade(NUM_ISA_INTERRUPTS, i8259_irq_cascade, NULL);
145} 131}
146 132
147static void __init pSeries_setup_mpic(void) 133static void __init pseries_mpic_init_IRQ(void)
148{ 134{
135 struct device_node *np, *old, *cascade = NULL;
136 unsigned int *addrp;
137 unsigned long intack = 0;
149 unsigned int *opprop; 138 unsigned int *opprop;
150 unsigned long openpic_addr = 0; 139 unsigned long openpic_addr = 0;
151 unsigned char senses[NR_IRQS - NUM_ISA_INTERRUPTS]; 140 unsigned int cascade_irq;
152 struct device_node *root; 141 int naddr, n, i, opplen;
153 int irq_count; 142 struct mpic *mpic;
154 143
155 /* Find the Open PIC if present */ 144 np = of_find_node_by_path("/");
156 root = of_find_node_by_path("/"); 145 naddr = prom_n_addr_cells(np);
157 opprop = (unsigned int *) get_property(root, "platform-open-pic", NULL); 146 opprop = (unsigned int *) get_property(np, "platform-open-pic", &opplen);
158 if (opprop != 0) { 147 if (opprop != 0) {
159 int n = prom_n_addr_cells(root); 148 openpic_addr = of_read_number(opprop, naddr);
160
161 for (openpic_addr = 0; n > 0; --n)
162 openpic_addr = (openpic_addr << 32) + *opprop++;
163 printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr); 149 printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
164 } 150 }
165 of_node_put(root); 151 of_node_put(np);
166 152
167 BUG_ON(openpic_addr == 0); 153 BUG_ON(openpic_addr == 0);
168 154
169 /* Get the sense values from OF */
170 prom_get_irq_senses(senses, NUM_ISA_INTERRUPTS, NR_IRQS);
171
172 /* Setup the openpic driver */ 155 /* Setup the openpic driver */
173 irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */ 156 mpic = mpic_alloc(pSeries_mpic_node, openpic_addr,
174 pSeries_mpic = mpic_alloc(openpic_addr, MPIC_PRIMARY, 157 MPIC_PRIMARY,
175 16, 16, irq_count, /* isu size, irq offset, irq count */ 158 16, 250, /* isu size, irq count */
176 NR_IRQS - 4, /* ipi offset */ 159 " MPIC ");
177 senses, irq_count, /* sense & sense size */ 160 BUG_ON(mpic == NULL);
178 " MPIC "); 161
162 /* Add ISUs */
163 opplen /= sizeof(u32);
164 for (n = 0, i = naddr; i < opplen; i += naddr, n++) {
165 unsigned long isuaddr = of_read_number(opprop + i, naddr);
166 mpic_assign_isu(mpic, n, isuaddr);
167 }
168
169 /* All ISUs are setup, complete initialization */
170 mpic_init(mpic);
171
172 /* Look for cascade */
173 for_each_node_by_type(np, "interrupt-controller")
174 if (device_is_compatible(np, "chrp,iic")) {
175 cascade = np;
176 break;
177 }
178 if (cascade == NULL)
179 return;
180
181 cascade_irq = irq_of_parse_and_map(cascade, 0);
182 if (cascade == NO_IRQ) {
183 printk(KERN_ERR "xics: failed to map cascade interrupt");
184 return;
185 }
186
187 /* Check ACK type */
188 for (old = of_node_get(cascade); old != NULL ; old = np) {
189 np = of_get_parent(old);
190 of_node_put(old);
191 if (np == NULL)
192 break;
193 if (strcmp(np->name, "pci") != 0)
194 continue;
195 addrp = (u32 *)get_property(np, "8259-interrupt-acknowledge",
196 NULL);
197 if (addrp == NULL)
198 continue;
199 naddr = prom_n_addr_cells(np);
200 intack = addrp[naddr-1];
201 if (naddr > 1)
202 intack |= ((unsigned long)addrp[naddr-2]) << 32;
203 }
204 if (intack)
205 printk(KERN_DEBUG "mpic: PCI 8259 intack at 0x%016lx\n",
206 intack);
207 i8259_init(cascade, intack);
208 of_node_put(cascade);
209 set_irq_chained_handler(cascade_irq, pseries_8259_cascade);
179} 210}
180 211
181static void pseries_lpar_enable_pmcs(void) 212static void pseries_lpar_enable_pmcs(void)
@@ -193,23 +224,67 @@ static void pseries_lpar_enable_pmcs(void)
193 get_lppaca()->pmcregs_in_use = 1; 224 get_lppaca()->pmcregs_in_use = 1;
194} 225}
195 226
196static void __init pSeries_setup_arch(void) 227#ifdef CONFIG_KEXEC
228static void pseries_kexec_cpu_down_mpic(int crash_shutdown, int secondary)
197{ 229{
198 /* Fixup ppc_md depending on the type of interrupt controller */ 230 mpic_teardown_this_cpu(secondary);
199 if (ppc64_interrupt_controller == IC_OPEN_PIC) { 231}
200 ppc_md.init_IRQ = pSeries_init_mpic; 232
201 ppc_md.get_irq = mpic_get_irq; 233static void pseries_kexec_cpu_down_xics(int crash_shutdown, int secondary)
202 /* Allocate the mpic now, so that find_and_init_phbs() can 234{
203 * fill the ISUs */ 235 /* Don't risk a hypervisor call if we're crashing */
204 pSeries_setup_mpic(); 236 if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) {
205 } else { 237 unsigned long vpa = __pa(get_lppaca());
206 ppc_md.init_IRQ = xics_init_IRQ; 238
207 ppc_md.get_irq = xics_get_irq; 239 if (unregister_vpa(hard_smp_processor_id(), vpa)) {
240 printk("VPA deregistration of cpu %u (hw_cpu_id %d) "
241 "failed\n", smp_processor_id(),
242 hard_smp_processor_id());
243 }
208 } 244 }
245 xics_teardown_cpu(secondary);
246}
247#endif /* CONFIG_KEXEC */
248
249static void __init pseries_discover_pic(void)
250{
251 struct device_node *np;
252 char *typep;
209 253
254 for (np = NULL; (np = of_find_node_by_name(np,
255 "interrupt-controller"));) {
256 typep = (char *)get_property(np, "compatible", NULL);
257 if (strstr(typep, "open-pic")) {
258 pSeries_mpic_node = of_node_get(np);
259 ppc_md.init_IRQ = pseries_mpic_init_IRQ;
260 ppc_md.get_irq = mpic_get_irq;
261#ifdef CONFIG_KEXEC
262 ppc_md.kexec_cpu_down = pseries_kexec_cpu_down_mpic;
263#endif
264#ifdef CONFIG_SMP
265 smp_init_pseries_mpic();
266#endif
267 return;
268 } else if (strstr(typep, "ppc-xicp")) {
269 ppc_md.init_IRQ = xics_init_IRQ;
270#ifdef CONFIG_KEXEC
271 ppc_md.kexec_cpu_down = pseries_kexec_cpu_down_xics;
272#endif
210#ifdef CONFIG_SMP 273#ifdef CONFIG_SMP
211 smp_init_pSeries(); 274 smp_init_pseries_xics();
212#endif 275#endif
276 return;
277 }
278 }
279 printk(KERN_ERR "pSeries_discover_pic: failed to recognize"
280 " interrupt-controller\n");
281}
282
283static void __init pSeries_setup_arch(void)
284{
285 /* Discover PIC type and setup ppc_md accordingly */
286 pseries_discover_pic();
287
213 /* openpic global configuration register (64-bit format). */ 288 /* openpic global configuration register (64-bit format). */
214 /* openpic Interrupt Source Unit pointer (64-bit format). */ 289 /* openpic Interrupt Source Unit pointer (64-bit format). */
215 /* python0 facility area (mmio) (64-bit format) REAL address. */ 290 /* python0 facility area (mmio) (64-bit format) REAL address. */
@@ -261,41 +336,11 @@ static int __init pSeries_init_panel(void)
261} 336}
262arch_initcall(pSeries_init_panel); 337arch_initcall(pSeries_init_panel);
263 338
264static void __init pSeries_discover_pic(void)
265{
266 struct device_node *np;
267 char *typep;
268
269 /*
270 * Setup interrupt mapping options that are needed for finish_device_tree
271 * to properly parse the OF interrupt tree & do the virtual irq mapping
272 */
273 __irq_offset_value = NUM_ISA_INTERRUPTS;
274 ppc64_interrupt_controller = IC_INVALID;
275 for (np = NULL; (np = of_find_node_by_name(np, "interrupt-controller"));) {
276 typep = (char *)get_property(np, "compatible", NULL);
277 if (strstr(typep, "open-pic")) {
278 ppc64_interrupt_controller = IC_OPEN_PIC;
279 break;
280 } else if (strstr(typep, "ppc-xicp")) {
281 ppc64_interrupt_controller = IC_PPC_XIC;
282 break;
283 }
284 }
285 if (ppc64_interrupt_controller == IC_INVALID)
286 printk("pSeries_discover_pic: failed to recognize"
287 " interrupt-controller\n");
288
289}
290
291static void pSeries_mach_cpu_die(void) 339static void pSeries_mach_cpu_die(void)
292{ 340{
293 local_irq_disable(); 341 local_irq_disable();
294 idle_task_exit(); 342 idle_task_exit();
295 /* Some hardware requires clearing the CPPR, while other hardware does not 343 xics_teardown_cpu(0);
296 * it is safe either way
297 */
298 pSeriesLP_cppr_info(0, 0);
299 rtas_stop_self(); 344 rtas_stop_self();
300 /* Should never get here... */ 345 /* Should never get here... */
301 BUG(); 346 BUG();
@@ -322,11 +367,6 @@ static void __init pSeries_init_early(void)
322 DBG(" -> pSeries_init_early()\n"); 367 DBG(" -> pSeries_init_early()\n");
323 368
324 fw_feature_init(); 369 fw_feature_init();
325
326 if (firmware_has_feature(FW_FEATURE_LPAR))
327 hpte_init_lpar();
328 else
329 hpte_init_native();
330 370
331 if (firmware_has_feature(FW_FEATURE_LPAR)) 371 if (firmware_has_feature(FW_FEATURE_LPAR))
332 find_udbg_vterm(); 372 find_udbg_vterm();
@@ -338,8 +378,6 @@ static void __init pSeries_init_early(void)
338 378
339 iommu_init_early_pSeries(); 379 iommu_init_early_pSeries();
340 380
341 pSeries_discover_pic();
342
343 DBG(" <- pSeries_init_early()\n"); 381 DBG(" <- pSeries_init_early()\n");
344} 382}
345 383
@@ -384,6 +422,11 @@ static int __init pSeries_probe_hypertas(unsigned long node,
384 if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL) != NULL) 422 if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL) != NULL)
385 powerpc_firmware_features |= FW_FEATURE_LPAR; 423 powerpc_firmware_features |= FW_FEATURE_LPAR;
386 424
425 if (firmware_has_feature(FW_FEATURE_LPAR))
426 hpte_init_lpar();
427 else
428 hpte_init_native();
429
387 return 1; 430 return 1;
388} 431}
389 432
@@ -506,27 +549,6 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus)
506 return PCI_PROBE_NORMAL; 549 return PCI_PROBE_NORMAL;
507} 550}
508 551
509#ifdef CONFIG_KEXEC
510static void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
511{
512 /* Don't risk a hypervisor call if we're crashing */
513 if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) {
514 unsigned long vpa = __pa(get_lppaca());
515
516 if (unregister_vpa(hard_smp_processor_id(), vpa)) {
517 printk("VPA deregistration of cpu %u (hw_cpu_id %d) "
518 "failed\n", smp_processor_id(),
519 hard_smp_processor_id());
520 }
521 }
522
523 if (ppc64_interrupt_controller == IC_OPEN_PIC)
524 mpic_teardown_this_cpu(secondary);
525 else
526 xics_teardown_cpu(secondary);
527}
528#endif
529
530define_machine(pseries) { 552define_machine(pseries) {
531 .name = "pSeries", 553 .name = "pSeries",
532 .probe = pSeries_probe, 554 .probe = pSeries_probe,
@@ -551,7 +573,6 @@ define_machine(pseries) {
551 .system_reset_exception = pSeries_system_reset_exception, 573 .system_reset_exception = pSeries_system_reset_exception,
552 .machine_check_exception = pSeries_machine_check_exception, 574 .machine_check_exception = pSeries_machine_check_exception,
553#ifdef CONFIG_KEXEC 575#ifdef CONFIG_KEXEC
554 .kexec_cpu_down = pseries_kexec_cpu_down,
555 .machine_kexec = default_machine_kexec, 576 .machine_kexec = default_machine_kexec,
556 .machine_kexec_prepare = default_machine_kexec_prepare, 577 .machine_kexec_prepare = default_machine_kexec_prepare,
557 .machine_crash_shutdown = default_machine_crash_shutdown, 578 .machine_crash_shutdown = default_machine_crash_shutdown,
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index 3cf78a6cd27c..ac61098ff401 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -14,7 +14,6 @@
14 14
15#undef DEBUG 15#undef DEBUG
16 16
17#include <linux/config.h>
18#include <linux/kernel.h> 17#include <linux/kernel.h>
19#include <linux/module.h> 18#include <linux/module.h>
20#include <linux/sched.h> 19#include <linux/sched.h>
@@ -417,27 +416,12 @@ static struct smp_ops_t pSeries_xics_smp_ops = {
417#endif 416#endif
418 417
419/* This is called very early */ 418/* This is called very early */
420void __init smp_init_pSeries(void) 419static void __init smp_init_pseries(void)
421{ 420{
422 int i; 421 int i;
423 422
424 DBG(" -> smp_init_pSeries()\n"); 423 DBG(" -> smp_init_pSeries()\n");
425 424
426 switch (ppc64_interrupt_controller) {
427#ifdef CONFIG_MPIC
428 case IC_OPEN_PIC:
429 smp_ops = &pSeries_mpic_smp_ops;
430 break;
431#endif
432#ifdef CONFIG_XICS
433 case IC_PPC_XIC:
434 smp_ops = &pSeries_xics_smp_ops;
435 break;
436#endif
437 default:
438 panic("Invalid interrupt controller");
439 }
440
441#ifdef CONFIG_HOTPLUG_CPU 425#ifdef CONFIG_HOTPLUG_CPU
442 smp_ops->cpu_disable = pSeries_cpu_disable; 426 smp_ops->cpu_disable = pSeries_cpu_disable;
443 smp_ops->cpu_die = pSeries_cpu_die; 427 smp_ops->cpu_die = pSeries_cpu_die;
@@ -472,3 +456,18 @@ void __init smp_init_pSeries(void)
472 DBG(" <- smp_init_pSeries()\n"); 456 DBG(" <- smp_init_pSeries()\n");
473} 457}
474 458
459#ifdef CONFIG_MPIC
460void __init smp_init_pseries_mpic(void)
461{
462 smp_ops = &pSeries_mpic_smp_ops;
463
464 smp_init_pseries();
465}
466#endif
467
468void __init smp_init_pseries_xics(void)
469{
470 smp_ops = &pSeries_xics_smp_ops;
471
472 smp_init_pseries();
473}
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index b14f9b5c114e..716972aa9777 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -8,7 +8,9 @@
8 * as published by the Free Software Foundation; either version 8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version. 9 * 2 of the License, or (at your option) any later version.
10 */ 10 */
11#include <linux/config.h> 11
12#undef DEBUG
13
12#include <linux/types.h> 14#include <linux/types.h>
13#include <linux/threads.h> 15#include <linux/threads.h>
14#include <linux/kernel.h> 16#include <linux/kernel.h>
@@ -20,6 +22,7 @@
20#include <linux/gfp.h> 22#include <linux/gfp.h>
21#include <linux/radix-tree.h> 23#include <linux/radix-tree.h>
22#include <linux/cpu.h> 24#include <linux/cpu.h>
25
23#include <asm/firmware.h> 26#include <asm/firmware.h>
24#include <asm/prom.h> 27#include <asm/prom.h>
25#include <asm/io.h> 28#include <asm/io.h>
@@ -32,26 +35,6 @@
32 35
33#include "xics.h" 36#include "xics.h"
34 37
35static unsigned int xics_startup(unsigned int irq);
36static void xics_enable_irq(unsigned int irq);
37static void xics_disable_irq(unsigned int irq);
38static void xics_mask_and_ack_irq(unsigned int irq);
39static void xics_end_irq(unsigned int irq);
40static void xics_set_affinity(unsigned int irq_nr, cpumask_t cpumask);
41
42static struct hw_interrupt_type xics_pic = {
43 .typename = " XICS ",
44 .startup = xics_startup,
45 .enable = xics_enable_irq,
46 .disable = xics_disable_irq,
47 .ack = xics_mask_and_ack_irq,
48 .end = xics_end_irq,
49 .set_affinity = xics_set_affinity
50};
51
52/* This is used to map real irq numbers to virtual */
53static struct radix_tree_root irq_map = RADIX_TREE_INIT(GFP_ATOMIC);
54
55#define XICS_IPI 2 38#define XICS_IPI 2
56#define XICS_IRQ_SPURIOUS 0 39#define XICS_IRQ_SPURIOUS 0
57 40
@@ -60,7 +43,7 @@ static struct radix_tree_root irq_map = RADIX_TREE_INIT(GFP_ATOMIC);
60 43
61/* 44/*
62 * Mark IPIs as higher priority so we can take them inside interrupts that 45 * Mark IPIs as higher priority so we can take them inside interrupts that
63 * arent marked SA_INTERRUPT 46 * arent marked IRQF_DISABLED
64 */ 47 */
65#define IPI_PRIORITY 4 48#define IPI_PRIORITY 4
66 49
@@ -82,12 +65,12 @@ struct xics_ipl {
82 65
83static struct xics_ipl __iomem *xics_per_cpu[NR_CPUS]; 66static struct xics_ipl __iomem *xics_per_cpu[NR_CPUS];
84 67
85static int xics_irq_8259_cascade = 0;
86static int xics_irq_8259_cascade_real = 0;
87static unsigned int default_server = 0xFF; 68static unsigned int default_server = 0xFF;
88static unsigned int default_distrib_server = 0; 69static unsigned int default_distrib_server = 0;
89static unsigned int interrupt_server_size = 8; 70static unsigned int interrupt_server_size = 8;
90 71
72static struct irq_host *xics_host;
73
91/* 74/*
92 * XICS only has a single IPI, so encode the messages per CPU 75 * XICS only has a single IPI, so encode the messages per CPU
93 */ 76 */
@@ -99,48 +82,34 @@ static int ibm_set_xive;
99static int ibm_int_on; 82static int ibm_int_on;
100static int ibm_int_off; 83static int ibm_int_off;
101 84
102typedef struct {
103 int (*xirr_info_get)(int cpu);
104 void (*xirr_info_set)(int cpu, int val);
105 void (*cppr_info)(int cpu, u8 val);
106 void (*qirr_info)(int cpu, u8 val);
107} xics_ops;
108 85
86/* Direct HW low level accessors */
109 87
110/* SMP */
111 88
112static int pSeries_xirr_info_get(int n_cpu) 89static inline unsigned int direct_xirr_info_get(int n_cpu)
113{ 90{
114 return in_be32(&xics_per_cpu[n_cpu]->xirr.word); 91 return in_be32(&xics_per_cpu[n_cpu]->xirr.word);
115} 92}
116 93
117static void pSeries_xirr_info_set(int n_cpu, int value) 94static inline void direct_xirr_info_set(int n_cpu, int value)
118{ 95{
119 out_be32(&xics_per_cpu[n_cpu]->xirr.word, value); 96 out_be32(&xics_per_cpu[n_cpu]->xirr.word, value);
120} 97}
121 98
122static void pSeries_cppr_info(int n_cpu, u8 value) 99static inline void direct_cppr_info(int n_cpu, u8 value)
123{ 100{
124 out_8(&xics_per_cpu[n_cpu]->xirr.bytes[0], value); 101 out_8(&xics_per_cpu[n_cpu]->xirr.bytes[0], value);
125} 102}
126 103
127static void pSeries_qirr_info(int n_cpu, u8 value) 104static inline void direct_qirr_info(int n_cpu, u8 value)
128{ 105{
129 out_8(&xics_per_cpu[n_cpu]->qirr.bytes[0], value); 106 out_8(&xics_per_cpu[n_cpu]->qirr.bytes[0], value);
130} 107}
131 108
132static xics_ops pSeries_ops = {
133 pSeries_xirr_info_get,
134 pSeries_xirr_info_set,
135 pSeries_cppr_info,
136 pSeries_qirr_info
137};
138 109
139static xics_ops *ops = &pSeries_ops; 110/* LPAR low level accessors */
140 111
141 112
142/* LPAR */
143
144static inline long plpar_eoi(unsigned long xirr) 113static inline long plpar_eoi(unsigned long xirr)
145{ 114{
146 return plpar_hcall_norets(H_EOI, xirr); 115 return plpar_hcall_norets(H_EOI, xirr);
@@ -162,7 +131,7 @@ static inline long plpar_xirr(unsigned long *xirr_ret)
162 return plpar_hcall(H_XIRR, 0, 0, 0, 0, xirr_ret, &dummy, &dummy); 131 return plpar_hcall(H_XIRR, 0, 0, 0, 0, xirr_ret, &dummy, &dummy);
163} 132}
164 133
165static int pSeriesLP_xirr_info_get(int n_cpu) 134static inline unsigned int lpar_xirr_info_get(int n_cpu)
166{ 135{
167 unsigned long lpar_rc; 136 unsigned long lpar_rc;
168 unsigned long return_value; 137 unsigned long return_value;
@@ -170,10 +139,10 @@ static int pSeriesLP_xirr_info_get(int n_cpu)
170 lpar_rc = plpar_xirr(&return_value); 139 lpar_rc = plpar_xirr(&return_value);
171 if (lpar_rc != H_SUCCESS) 140 if (lpar_rc != H_SUCCESS)
172 panic(" bad return code xirr - rc = %lx \n", lpar_rc); 141 panic(" bad return code xirr - rc = %lx \n", lpar_rc);
173 return (int)return_value; 142 return (unsigned int)return_value;
174} 143}
175 144
176static void pSeriesLP_xirr_info_set(int n_cpu, int value) 145static inline void lpar_xirr_info_set(int n_cpu, int value)
177{ 146{
178 unsigned long lpar_rc; 147 unsigned long lpar_rc;
179 unsigned long val64 = value & 0xffffffff; 148 unsigned long val64 = value & 0xffffffff;
@@ -184,7 +153,7 @@ static void pSeriesLP_xirr_info_set(int n_cpu, int value)
184 val64); 153 val64);
185} 154}
186 155
187void pSeriesLP_cppr_info(int n_cpu, u8 value) 156static inline void lpar_cppr_info(int n_cpu, u8 value)
188{ 157{
189 unsigned long lpar_rc; 158 unsigned long lpar_rc;
190 159
@@ -193,7 +162,7 @@ void pSeriesLP_cppr_info(int n_cpu, u8 value)
193 panic("bad return code cppr - rc = %lx\n", lpar_rc); 162 panic("bad return code cppr - rc = %lx\n", lpar_rc);
194} 163}
195 164
196static void pSeriesLP_qirr_info(int n_cpu , u8 value) 165static inline void lpar_qirr_info(int n_cpu , u8 value)
197{ 166{
198 unsigned long lpar_rc; 167 unsigned long lpar_rc;
199 168
@@ -202,43 +171,16 @@ static void pSeriesLP_qirr_info(int n_cpu , u8 value)
202 panic("bad return code qirr - rc = %lx\n", lpar_rc); 171 panic("bad return code qirr - rc = %lx\n", lpar_rc);
203} 172}
204 173
205xics_ops pSeriesLP_ops = {
206 pSeriesLP_xirr_info_get,
207 pSeriesLP_xirr_info_set,
208 pSeriesLP_cppr_info,
209 pSeriesLP_qirr_info
210};
211
212static unsigned int xics_startup(unsigned int virq)
213{
214 unsigned int irq;
215
216 irq = irq_offset_down(virq);
217 if (radix_tree_insert(&irq_map, virt_irq_to_real(irq),
218 &virt_irq_to_real_map[irq]) == -ENOMEM)
219 printk(KERN_CRIT "Out of memory creating real -> virtual"
220 " IRQ mapping for irq %u (real 0x%x)\n",
221 virq, virt_irq_to_real(irq));
222 xics_enable_irq(virq);
223 return 0; /* return value is ignored */
224}
225 174
226static unsigned int real_irq_to_virt(unsigned int real_irq) 175/* High level handlers and init code */
227{
228 unsigned int *ptr;
229 176
230 ptr = radix_tree_lookup(&irq_map, real_irq);
231 if (ptr == NULL)
232 return NO_IRQ;
233 return ptr - virt_irq_to_real_map;
234}
235 177
236#ifdef CONFIG_SMP 178#ifdef CONFIG_SMP
237static int get_irq_server(unsigned int irq) 179static int get_irq_server(unsigned int virq)
238{ 180{
239 unsigned int server; 181 unsigned int server;
240 /* For the moment only implement delivery to all cpus or one cpu */ 182 /* For the moment only implement delivery to all cpus or one cpu */
241 cpumask_t cpumask = irq_affinity[irq]; 183 cpumask_t cpumask = irq_desc[virq].affinity;
242 cpumask_t tmp = CPU_MASK_NONE; 184 cpumask_t tmp = CPU_MASK_NONE;
243 185
244 if (!distribute_irqs) 186 if (!distribute_irqs)
@@ -259,23 +201,28 @@ static int get_irq_server(unsigned int irq)
259 201
260} 202}
261#else 203#else
262static int get_irq_server(unsigned int irq) 204static int get_irq_server(unsigned int virq)
263{ 205{
264 return default_server; 206 return default_server;
265} 207}
266#endif 208#endif
267 209
268static void xics_enable_irq(unsigned int virq) 210
211static void xics_unmask_irq(unsigned int virq)
269{ 212{
270 unsigned int irq; 213 unsigned int irq;
271 int call_status; 214 int call_status;
272 unsigned int server; 215 unsigned int server;
273 216
274 irq = virt_irq_to_real(irq_offset_down(virq)); 217 pr_debug("xics: unmask virq %d\n", virq);
275 if (irq == XICS_IPI) 218
219 irq = (unsigned int)irq_map[virq].hwirq;
220 pr_debug(" -> map to hwirq 0x%x\n", irq);
221 if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
276 return; 222 return;
277 223
278 server = get_irq_server(virq); 224 server = get_irq_server(virq);
225
279 call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, 226 call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
280 DEFAULT_PRIORITY); 227 DEFAULT_PRIORITY);
281 if (call_status != 0) { 228 if (call_status != 0) {
@@ -294,7 +241,7 @@ static void xics_enable_irq(unsigned int virq)
294 } 241 }
295} 242}
296 243
297static void xics_disable_real_irq(unsigned int irq) 244static void xics_mask_real_irq(unsigned int irq)
298{ 245{
299 int call_status; 246 int call_status;
300 unsigned int server; 247 unsigned int server;
@@ -319,75 +266,86 @@ static void xics_disable_real_irq(unsigned int irq)
319 } 266 }
320} 267}
321 268
322static void xics_disable_irq(unsigned int virq) 269static void xics_mask_irq(unsigned int virq)
323{ 270{
324 unsigned int irq; 271 unsigned int irq;
325 272
326 irq = virt_irq_to_real(irq_offset_down(virq)); 273 pr_debug("xics: mask virq %d\n", virq);
327 xics_disable_real_irq(irq); 274
275 irq = (unsigned int)irq_map[virq].hwirq;
276 if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
277 return;
278 xics_mask_real_irq(irq);
279}
280
281static unsigned int xics_startup(unsigned int virq)
282{
283 unsigned int irq;
284
285 /* force a reverse mapping of the interrupt so it gets in the cache */
286 irq = (unsigned int)irq_map[virq].hwirq;
287 irq_radix_revmap(xics_host, irq);
288
289 /* unmask it */
290 xics_unmask_irq(virq);
291 return 0;
328} 292}
329 293
330static void xics_end_irq(unsigned int irq) 294static void xics_eoi_direct(unsigned int virq)
331{ 295{
332 int cpu = smp_processor_id(); 296 int cpu = smp_processor_id();
297 unsigned int irq = (unsigned int)irq_map[virq].hwirq;
333 298
334 iosync(); 299 iosync();
335 ops->xirr_info_set(cpu, ((0xff << 24) | 300 direct_xirr_info_set(cpu, (0xff << 24) | irq);
336 (virt_irq_to_real(irq_offset_down(irq)))));
337
338} 301}
339 302
340static void xics_mask_and_ack_irq(unsigned int irq) 303
304static void xics_eoi_lpar(unsigned int virq)
341{ 305{
342 int cpu = smp_processor_id(); 306 int cpu = smp_processor_id();
307 unsigned int irq = (unsigned int)irq_map[virq].hwirq;
343 308
344 if (irq < irq_offset_value()) { 309 iosync();
345 i8259_pic.ack(irq); 310 lpar_xirr_info_set(cpu, (0xff << 24) | irq);
346 iosync();
347 ops->xirr_info_set(cpu, ((0xff<<24) |
348 xics_irq_8259_cascade_real));
349 iosync();
350 }
351} 311}
352 312
353int xics_get_irq(struct pt_regs *regs) 313static inline unsigned int xics_remap_irq(unsigned int vec)
354{ 314{
355 unsigned int cpu = smp_processor_id(); 315 unsigned int irq;
356 unsigned int vec;
357 int irq;
358 316
359 vec = ops->xirr_info_get(cpu);
360 /* (vec >> 24) == old priority */
361 vec &= 0x00ffffff; 317 vec &= 0x00ffffff;
362 318
363 /* for sanity, this had better be < NR_IRQS - 16 */ 319 if (vec == XICS_IRQ_SPURIOUS)
364 if (vec == xics_irq_8259_cascade_real) { 320 return NO_IRQ;
365 irq = i8259_irq(regs); 321 irq = irq_radix_revmap(xics_host, vec);
366 xics_end_irq(irq_offset_up(xics_irq_8259_cascade)); 322 if (likely(irq != NO_IRQ))
367 } else if (vec == XICS_IRQ_SPURIOUS) { 323 return irq;
368 irq = -1; 324
369 } else { 325 printk(KERN_ERR "Interrupt %u (real) is invalid,"
370 irq = real_irq_to_virt(vec); 326 " disabling it.\n", vec);
371 if (irq == NO_IRQ) 327 xics_mask_real_irq(vec);
372 irq = real_irq_to_virt_slowpath(vec); 328 return NO_IRQ;
373 if (irq == NO_IRQ) {
374 printk(KERN_ERR "Interrupt %u (real) is invalid,"
375 " disabling it.\n", vec);
376 xics_disable_real_irq(vec);
377 } else
378 irq = irq_offset_up(irq);
379 }
380 return irq;
381} 329}
382 330
383#ifdef CONFIG_SMP 331static unsigned int xics_get_irq_direct(struct pt_regs *regs)
332{
333 unsigned int cpu = smp_processor_id();
384 334
385static irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs) 335 return xics_remap_irq(direct_xirr_info_get(cpu));
336}
337
338static unsigned int xics_get_irq_lpar(struct pt_regs *regs)
386{ 339{
387 int cpu = smp_processor_id(); 340 unsigned int cpu = smp_processor_id();
341
342 return xics_remap_irq(lpar_xirr_info_get(cpu));
343}
388 344
389 ops->qirr_info(cpu, 0xff); 345#ifdef CONFIG_SMP
390 346
347static irqreturn_t xics_ipi_dispatch(int cpu, struct pt_regs *regs)
348{
391 WARN_ON(cpu_is_offline(cpu)); 349 WARN_ON(cpu_is_offline(cpu));
392 350
393 while (xics_ipi_message[cpu].value) { 351 while (xics_ipi_message[cpu].value) {
@@ -419,18 +377,88 @@ static irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
419 return IRQ_HANDLED; 377 return IRQ_HANDLED;
420} 378}
421 379
380static irqreturn_t xics_ipi_action_direct(int irq, void *dev_id, struct pt_regs *regs)
381{
382 int cpu = smp_processor_id();
383
384 direct_qirr_info(cpu, 0xff);
385
386 return xics_ipi_dispatch(cpu, regs);
387}
388
389static irqreturn_t xics_ipi_action_lpar(int irq, void *dev_id, struct pt_regs *regs)
390{
391 int cpu = smp_processor_id();
392
393 lpar_qirr_info(cpu, 0xff);
394
395 return xics_ipi_dispatch(cpu, regs);
396}
397
422void xics_cause_IPI(int cpu) 398void xics_cause_IPI(int cpu)
423{ 399{
424 ops->qirr_info(cpu, IPI_PRIORITY); 400 if (firmware_has_feature(FW_FEATURE_LPAR))
401 lpar_qirr_info(cpu, IPI_PRIORITY);
402 else
403 direct_qirr_info(cpu, IPI_PRIORITY);
425} 404}
405
426#endif /* CONFIG_SMP */ 406#endif /* CONFIG_SMP */
427 407
408static void xics_set_cpu_priority(int cpu, unsigned char cppr)
409{
410 if (firmware_has_feature(FW_FEATURE_LPAR))
411 lpar_cppr_info(cpu, cppr);
412 else
413 direct_cppr_info(cpu, cppr);
414 iosync();
415}
416
417static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
418{
419 unsigned int irq;
420 int status;
421 int xics_status[2];
422 unsigned long newmask;
423 cpumask_t tmp = CPU_MASK_NONE;
424
425 irq = (unsigned int)irq_map[virq].hwirq;
426 if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
427 return;
428
429 status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
430
431 if (status) {
432 printk(KERN_ERR "xics_set_affinity: irq=%u ibm,get-xive "
433 "returns %d\n", irq, status);
434 return;
435 }
436
437 /* For the moment only implement delivery to all cpus or one cpu */
438 if (cpus_equal(cpumask, CPU_MASK_ALL)) {
439 newmask = default_distrib_server;
440 } else {
441 cpus_and(tmp, cpu_online_map, cpumask);
442 if (cpus_empty(tmp))
443 return;
444 newmask = get_hard_smp_processor_id(first_cpu(tmp));
445 }
446
447 status = rtas_call(ibm_set_xive, 3, 1, NULL,
448 irq, newmask, xics_status[1]);
449
450 if (status) {
451 printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive "
452 "returns %d\n", irq, status);
453 return;
454 }
455}
456
428void xics_setup_cpu(void) 457void xics_setup_cpu(void)
429{ 458{
430 int cpu = smp_processor_id(); 459 int cpu = smp_processor_id();
431 460
432 ops->cppr_info(cpu, 0xff); 461 xics_set_cpu_priority(cpu, 0xff);
433 iosync();
434 462
435 /* 463 /*
436 * Put the calling processor into the GIQ. This is really only 464 * Put the calling processor into the GIQ. This is really only
@@ -443,72 +471,266 @@ void xics_setup_cpu(void)
443 (1UL << interrupt_server_size) - 1 - default_distrib_server, 1); 471 (1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
444} 472}
445 473
446void xics_init_IRQ(void) 474
475static struct irq_chip xics_pic_direct = {
476 .typename = " XICS ",
477 .startup = xics_startup,
478 .mask = xics_mask_irq,
479 .unmask = xics_unmask_irq,
480 .eoi = xics_eoi_direct,
481 .set_affinity = xics_set_affinity
482};
483
484
485static struct irq_chip xics_pic_lpar = {
486 .typename = " XICS ",
487 .startup = xics_startup,
488 .mask = xics_mask_irq,
489 .unmask = xics_unmask_irq,
490 .eoi = xics_eoi_lpar,
491 .set_affinity = xics_set_affinity
492};
493
494
495static int xics_host_match(struct irq_host *h, struct device_node *node)
496{
497 /* IBM machines have interrupt parents of various funky types for things
498 * like vdevices, events, etc... The trick we use here is to match
499 * everything here except the legacy 8259 which is compatible "chrp,iic"
500 */
501 return !device_is_compatible(node, "chrp,iic");
502}
503
504static int xics_host_map_direct(struct irq_host *h, unsigned int virq,
505 irq_hw_number_t hw, unsigned int flags)
506{
507 unsigned int sense = flags & IRQ_TYPE_SENSE_MASK;
508
509 pr_debug("xics: map_direct virq %d, hwirq 0x%lx, flags: 0x%x\n",
510 virq, hw, flags);
511
512 if (sense && sense != IRQ_TYPE_LEVEL_LOW)
513 printk(KERN_WARNING "xics: using unsupported sense 0x%x"
514 " for irq %d (h: 0x%lx)\n", flags, virq, hw);
515
516 get_irq_desc(virq)->status |= IRQ_LEVEL;
517 set_irq_chip_and_handler(virq, &xics_pic_direct, handle_fasteoi_irq);
518 return 0;
519}
520
521static int xics_host_map_lpar(struct irq_host *h, unsigned int virq,
522 irq_hw_number_t hw, unsigned int flags)
523{
524 unsigned int sense = flags & IRQ_TYPE_SENSE_MASK;
525
526 pr_debug("xics: map_lpar virq %d, hwirq 0x%lx, flags: 0x%x\n",
527 virq, hw, flags);
528
529 if (sense && sense != IRQ_TYPE_LEVEL_LOW)
530 printk(KERN_WARNING "xics: using unsupported sense 0x%x"
531 " for irq %d (h: 0x%lx)\n", flags, virq, hw);
532
533 get_irq_desc(virq)->status |= IRQ_LEVEL;
534 set_irq_chip_and_handler(virq, &xics_pic_lpar, handle_fasteoi_irq);
535 return 0;
536}
537
538static int xics_host_xlate(struct irq_host *h, struct device_node *ct,
539 u32 *intspec, unsigned int intsize,
540 irq_hw_number_t *out_hwirq, unsigned int *out_flags)
541
542{
543 /* Current xics implementation translates everything
544 * to level. It is not technically right for MSIs but this
545 * is irrelevant at this point. We might get smarter in the future
546 */
547 *out_hwirq = intspec[0];
548 *out_flags = IRQ_TYPE_LEVEL_LOW;
549
550 return 0;
551}
552
553static struct irq_host_ops xics_host_direct_ops = {
554 .match = xics_host_match,
555 .map = xics_host_map_direct,
556 .xlate = xics_host_xlate,
557};
558
559static struct irq_host_ops xics_host_lpar_ops = {
560 .match = xics_host_match,
561 .map = xics_host_map_lpar,
562 .xlate = xics_host_xlate,
563};
564
565static void __init xics_init_host(void)
566{
567 struct irq_host_ops *ops;
568
569 if (firmware_has_feature(FW_FEATURE_LPAR))
570 ops = &xics_host_lpar_ops;
571 else
572 ops = &xics_host_direct_ops;
573 xics_host = irq_alloc_host(IRQ_HOST_MAP_TREE, 0, ops,
574 XICS_IRQ_SPURIOUS);
575 BUG_ON(xics_host == NULL);
576 irq_set_default_host(xics_host);
577}
578
579static void __init xics_map_one_cpu(int hw_id, unsigned long addr,
580 unsigned long size)
447{ 581{
582#ifdef CONFIG_SMP
448 int i; 583 int i;
449 unsigned long intr_size = 0;
450 struct device_node *np;
451 uint *ireg, ilen, indx = 0;
452 unsigned long intr_base = 0;
453 struct xics_interrupt_node {
454 unsigned long addr;
455 unsigned long size;
456 } intnodes[NR_CPUS];
457 584
458 ppc64_boot_msg(0x20, "XICS Init"); 585 /* This may look gross but it's good enough for now, we don't quite
586 * have a hard -> linux processor id matching.
587 */
588 for_each_possible_cpu(i) {
589 if (!cpu_present(i))
590 continue;
591 if (hw_id == get_hard_smp_processor_id(i)) {
592 xics_per_cpu[i] = ioremap(addr, size);
593 return;
594 }
595 }
596#else
597 if (hw_id != 0)
598 return;
599 xics_per_cpu[0] = ioremap(addr, size);
600#endif /* CONFIG_SMP */
601}
459 602
460 ibm_get_xive = rtas_token("ibm,get-xive"); 603static void __init xics_init_one_node(struct device_node *np,
461 ibm_set_xive = rtas_token("ibm,set-xive"); 604 unsigned int *indx)
462 ibm_int_on = rtas_token("ibm,int-on"); 605{
463 ibm_int_off = rtas_token("ibm,int-off"); 606 unsigned int ilen;
607 u32 *ireg;
464 608
465 np = of_find_node_by_type(NULL, "PowerPC-External-Interrupt-Presentation"); 609 /* This code does the theorically broken assumption that the interrupt
466 if (!np) 610 * server numbers are the same as the hard CPU numbers.
467 panic("xics_init_IRQ: can't find interrupt presentation"); 611 * This happens to be the case so far but we are playing with fire...
612 * should be fixed one of these days. -BenH.
613 */
614 ireg = (u32 *)get_property(np, "ibm,interrupt-server-ranges", NULL);
468 615
469nextnode: 616 /* Do that ever happen ? we'll know soon enough... but even good'old
470 ireg = (uint *)get_property(np, "ibm,interrupt-server-ranges", NULL); 617 * f80 does have that property ..
618 */
619 WARN_ON(ireg == NULL);
471 if (ireg) { 620 if (ireg) {
472 /* 621 /*
473 * set node starting index for this node 622 * set node starting index for this node
474 */ 623 */
475 indx = *ireg; 624 *indx = *ireg;
476 } 625 }
477 626 ireg = (u32 *)get_property(np, "reg", &ilen);
478 ireg = (uint *)get_property(np, "reg", &ilen);
479 if (!ireg) 627 if (!ireg)
480 panic("xics_init_IRQ: can't find interrupt reg property"); 628 panic("xics_init_IRQ: can't find interrupt reg property");
481 629
482 while (ilen) { 630 while (ilen >= (4 * sizeof(u32))) {
483 intnodes[indx].addr = (unsigned long)*ireg++ << 32; 631 unsigned long addr, size;
484 ilen -= sizeof(uint); 632
485 intnodes[indx].addr |= *ireg++; 633 /* XXX Use proper OF parsing code here !!! */
486 ilen -= sizeof(uint); 634 addr = (unsigned long)*ireg++ << 32;
487 intnodes[indx].size = (unsigned long)*ireg++ << 32; 635 ilen -= sizeof(u32);
488 ilen -= sizeof(uint); 636 addr |= *ireg++;
489 intnodes[indx].size |= *ireg++; 637 ilen -= sizeof(u32);
490 ilen -= sizeof(uint); 638 size = (unsigned long)*ireg++ << 32;
491 indx++; 639 ilen -= sizeof(u32);
492 if (indx >= NR_CPUS) break; 640 size |= *ireg++;
641 ilen -= sizeof(u32);
642 xics_map_one_cpu(*indx, addr, size);
643 (*indx)++;
644 }
645}
646
647
648static void __init xics_setup_8259_cascade(void)
649{
650 struct device_node *np, *old, *found = NULL;
651 int cascade, naddr;
652 u32 *addrp;
653 unsigned long intack = 0;
654
655 for_each_node_by_type(np, "interrupt-controller")
656 if (device_is_compatible(np, "chrp,iic")) {
657 found = np;
658 break;
659 }
660 if (found == NULL) {
661 printk(KERN_DEBUG "xics: no ISA interrupt controller\n");
662 return;
663 }
664 cascade = irq_of_parse_and_map(found, 0);
665 if (cascade == NO_IRQ) {
666 printk(KERN_ERR "xics: failed to map cascade interrupt");
667 return;
668 }
669 pr_debug("xics: cascade mapped to irq %d\n", cascade);
670
671 for (old = of_node_get(found); old != NULL ; old = np) {
672 np = of_get_parent(old);
673 of_node_put(old);
674 if (np == NULL)
675 break;
676 if (strcmp(np->name, "pci") != 0)
677 continue;
678 addrp = (u32 *)get_property(np, "8259-interrupt-acknowledge", NULL);
679 if (addrp == NULL)
680 continue;
681 naddr = prom_n_addr_cells(np);
682 intack = addrp[naddr-1];
683 if (naddr > 1)
684 intack |= ((unsigned long)addrp[naddr-2]) << 32;
685 }
686 if (intack)
687 printk(KERN_DEBUG "xics: PCI 8259 intack at 0x%016lx\n", intack);
688 i8259_init(found, intack);
689 of_node_put(found);
690 set_irq_chained_handler(cascade, pseries_8259_cascade);
691}
692
693void __init xics_init_IRQ(void)
694{
695 int i;
696 struct device_node *np;
697 u32 *ireg, ilen, indx = 0;
698 int found = 0;
699
700 ppc64_boot_msg(0x20, "XICS Init");
701
702 ibm_get_xive = rtas_token("ibm,get-xive");
703 ibm_set_xive = rtas_token("ibm,set-xive");
704 ibm_int_on = rtas_token("ibm,int-on");
705 ibm_int_off = rtas_token("ibm,int-off");
706
707 for_each_node_by_type(np, "PowerPC-External-Interrupt-Presentation") {
708 found = 1;
709 if (firmware_has_feature(FW_FEATURE_LPAR))
710 break;
711 xics_init_one_node(np, &indx);
493 } 712 }
713 if (found == 0)
714 return;
494 715
495 np = of_find_node_by_type(np, "PowerPC-External-Interrupt-Presentation"); 716 xics_init_host();
496 if ((indx < NR_CPUS) && np) goto nextnode;
497 717
498 /* Find the server numbers for the boot cpu. */ 718 /* Find the server numbers for the boot cpu. */
499 for (np = of_find_node_by_type(NULL, "cpu"); 719 for (np = of_find_node_by_type(NULL, "cpu");
500 np; 720 np;
501 np = of_find_node_by_type(np, "cpu")) { 721 np = of_find_node_by_type(np, "cpu")) {
502 ireg = (uint *)get_property(np, "reg", &ilen); 722 ireg = (u32 *)get_property(np, "reg", &ilen);
503 if (ireg && ireg[0] == get_hard_smp_processor_id(boot_cpuid)) { 723 if (ireg && ireg[0] == get_hard_smp_processor_id(boot_cpuid)) {
504 ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s", 724 ireg = (u32 *)get_property(np,
505 &ilen); 725 "ibm,ppc-interrupt-gserver#s",
726 &ilen);
506 i = ilen / sizeof(int); 727 i = ilen / sizeof(int);
507 if (ireg && i > 0) { 728 if (ireg && i > 0) {
508 default_server = ireg[0]; 729 default_server = ireg[0];
509 default_distrib_server = ireg[i-1]; /* take last element */ 730 /* take last element */
731 default_distrib_server = ireg[i-1];
510 } 732 }
511 ireg = (uint *)get_property(np, 733 ireg = (u32 *)get_property(np,
512 "ibm,interrupt-server#-size", NULL); 734 "ibm,interrupt-server#-size", NULL);
513 if (ireg) 735 if (ireg)
514 interrupt_server_size = *ireg; 736 interrupt_server_size = *ireg;
@@ -517,132 +739,48 @@ nextnode:
517 } 739 }
518 of_node_put(np); 740 of_node_put(np);
519 741
520 intr_base = intnodes[0].addr;
521 intr_size = intnodes[0].size;
522
523 np = of_find_node_by_type(NULL, "interrupt-controller");
524 if (!np) {
525 printk(KERN_DEBUG "xics: no ISA interrupt controller\n");
526 xics_irq_8259_cascade_real = -1;
527 xics_irq_8259_cascade = -1;
528 } else {
529 ireg = (uint *) get_property(np, "interrupts", NULL);
530 if (!ireg)
531 panic("xics_init_IRQ: can't find ISA interrupts property");
532
533 xics_irq_8259_cascade_real = *ireg;
534 xics_irq_8259_cascade
535 = virt_irq_create_mapping(xics_irq_8259_cascade_real);
536 i8259_init(0, 0);
537 of_node_put(np);
538 }
539
540 if (firmware_has_feature(FW_FEATURE_LPAR)) 742 if (firmware_has_feature(FW_FEATURE_LPAR))
541 ops = &pSeriesLP_ops; 743 ppc_md.get_irq = xics_get_irq_lpar;
542 else { 744 else
543#ifdef CONFIG_SMP 745 ppc_md.get_irq = xics_get_irq_direct;
544 for_each_possible_cpu(i) {
545 int hard_id;
546
547 /* FIXME: Do this dynamically! --RR */
548 if (!cpu_present(i))
549 continue;
550
551 hard_id = get_hard_smp_processor_id(i);
552 xics_per_cpu[i] = ioremap(intnodes[hard_id].addr,
553 intnodes[hard_id].size);
554 }
555#else
556 xics_per_cpu[0] = ioremap(intr_base, intr_size);
557#endif /* CONFIG_SMP */
558 }
559
560 for (i = irq_offset_value(); i < NR_IRQS; ++i)
561 get_irq_desc(i)->handler = &xics_pic;
562 746
563 xics_setup_cpu(); 747 xics_setup_cpu();
564 748
749 xics_setup_8259_cascade();
750
565 ppc64_boot_msg(0x21, "XICS Done"); 751 ppc64_boot_msg(0x21, "XICS Done");
566} 752}
567 753
568/*
569 * We cant do this in init_IRQ because we need the memory subsystem up for
570 * request_irq()
571 */
572static int __init xics_setup_i8259(void)
573{
574 if (ppc64_interrupt_controller == IC_PPC_XIC &&
575 xics_irq_8259_cascade != -1) {
576 if (request_irq(irq_offset_up(xics_irq_8259_cascade),
577 no_action, 0, "8259 cascade", NULL))
578 printk(KERN_ERR "xics_setup_i8259: couldn't get 8259 "
579 "cascade\n");
580 }
581 return 0;
582}
583arch_initcall(xics_setup_i8259);
584 754
585#ifdef CONFIG_SMP 755#ifdef CONFIG_SMP
586void xics_request_IPIs(void) 756void xics_request_IPIs(void)
587{ 757{
588 virt_irq_to_real_map[XICS_IPI] = XICS_IPI; 758 unsigned int ipi;
589 759
590 /* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */ 760 ipi = irq_create_mapping(xics_host, XICS_IPI, 0);
591 request_irq(irq_offset_up(XICS_IPI), xics_ipi_action, SA_INTERRUPT, 761 BUG_ON(ipi == NO_IRQ);
592 "IPI", NULL);
593 get_irq_desc(irq_offset_up(XICS_IPI))->status |= IRQ_PER_CPU;
594}
595#endif
596
597static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
598{
599 unsigned int irq;
600 int status;
601 int xics_status[2];
602 unsigned long newmask;
603 cpumask_t tmp = CPU_MASK_NONE;
604
605 irq = virt_irq_to_real(irq_offset_down(virq));
606 if (irq == XICS_IPI || irq == NO_IRQ)
607 return;
608
609 status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
610 762
611 if (status) { 763 /*
612 printk(KERN_ERR "xics_set_affinity: irq=%u ibm,get-xive " 764 * IPIs are marked IRQF_DISABLED as they must run with irqs
613 "returns %d\n", irq, status); 765 * disabled
614 return; 766 */
615 } 767 set_irq_handler(ipi, handle_percpu_irq);
616 768 if (firmware_has_feature(FW_FEATURE_LPAR))
617 /* For the moment only implement delivery to all cpus or one cpu */ 769 request_irq(ipi, xics_ipi_action_lpar, IRQF_DISABLED,
618 if (cpus_equal(cpumask, CPU_MASK_ALL)) { 770 "IPI", NULL);
619 newmask = default_distrib_server; 771 else
620 } else { 772 request_irq(ipi, xics_ipi_action_direct, IRQF_DISABLED,
621 cpus_and(tmp, cpu_online_map, cpumask); 773 "IPI", NULL);
622 if (cpus_empty(tmp))
623 return;
624 newmask = get_hard_smp_processor_id(first_cpu(tmp));
625 }
626
627 status = rtas_call(ibm_set_xive, 3, 1, NULL,
628 irq, newmask, xics_status[1]);
629
630 if (status) {
631 printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive "
632 "returns %d\n", irq, status);
633 return;
634 }
635} 774}
775#endif /* CONFIG_SMP */
636 776
637void xics_teardown_cpu(int secondary) 777void xics_teardown_cpu(int secondary)
638{ 778{
639 int cpu = smp_processor_id(); 779 int cpu = smp_processor_id();
780 unsigned int ipi;
781 struct irq_desc *desc;
640 782
641 ops->cppr_info(cpu, 0x00); 783 xics_set_cpu_priority(cpu, 0);
642 iosync();
643
644 /* Clear IPI */
645 ops->qirr_info(cpu, 0xff);
646 784
647 /* 785 /*
648 * we need to EOI the IPI if we got here from kexec down IPI 786 * we need to EOI the IPI if we got here from kexec down IPI
@@ -651,7 +789,13 @@ void xics_teardown_cpu(int secondary)
651 * should we be flagging idle loop instead? 789 * should we be flagging idle loop instead?
652 * or creating some task to be scheduled? 790 * or creating some task to be scheduled?
653 */ 791 */
654 ops->xirr_info_set(cpu, XICS_IPI); 792
793 ipi = irq_find_mapping(xics_host, XICS_IPI);
794 if (ipi == XICS_IRQ_SPURIOUS)
795 return;
796 desc = get_irq_desc(ipi);
797 if (desc->chip && desc->chip->eoi)
798 desc->chip->eoi(XICS_IPI);
655 799
656 /* 800 /*
657 * Some machines need to have at least one cpu in the GIQ, 801 * Some machines need to have at least one cpu in the GIQ,
@@ -659,8 +803,8 @@ void xics_teardown_cpu(int secondary)
659 */ 803 */
660 if (secondary) 804 if (secondary)
661 rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, 805 rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
662 (1UL << interrupt_server_size) - 1 - 806 (1UL << interrupt_server_size) - 1 -
663 default_distrib_server, 0); 807 default_distrib_server, 0);
664} 808}
665 809
666#ifdef CONFIG_HOTPLUG_CPU 810#ifdef CONFIG_HOTPLUG_CPU
@@ -672,8 +816,7 @@ void xics_migrate_irqs_away(void)
672 unsigned int irq, virq, cpu = smp_processor_id(); 816 unsigned int irq, virq, cpu = smp_processor_id();
673 817
674 /* Reject any interrupt that was queued to us... */ 818 /* Reject any interrupt that was queued to us... */
675 ops->cppr_info(cpu, 0); 819 xics_set_cpu_priority(cpu, 0);
676 iosync();
677 820
678 /* remove ourselves from the global interrupt queue */ 821 /* remove ourselves from the global interrupt queue */
679 status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, 822 status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
@@ -681,29 +824,28 @@ void xics_migrate_irqs_away(void)
681 WARN_ON(status < 0); 824 WARN_ON(status < 0);
682 825
683 /* Allow IPIs again... */ 826 /* Allow IPIs again... */
684 ops->cppr_info(cpu, DEFAULT_PRIORITY); 827 xics_set_cpu_priority(cpu, DEFAULT_PRIORITY);
685 iosync();
686 828
687 for_each_irq(virq) { 829 for_each_irq(virq) {
688 irq_desc_t *desc; 830 struct irq_desc *desc;
689 int xics_status[2]; 831 int xics_status[2];
690 unsigned long flags; 832 unsigned long flags;
691 833
692 /* We cant set affinity on ISA interrupts */ 834 /* We cant set affinity on ISA interrupts */
693 if (virq < irq_offset_value()) 835 if (virq < NUM_ISA_INTERRUPTS)
694 continue; 836 continue;
695 837 if (irq_map[virq].host != xics_host)
696 desc = get_irq_desc(virq); 838 continue;
697 irq = virt_irq_to_real(irq_offset_down(virq)); 839 irq = (unsigned int)irq_map[virq].hwirq;
698
699 /* We need to get IPIs still. */ 840 /* We need to get IPIs still. */
700 if (irq == XICS_IPI || irq == NO_IRQ) 841 if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
701 continue; 842 continue;
843 desc = get_irq_desc(virq);
702 844
703 /* We only need to migrate enabled IRQS */ 845 /* We only need to migrate enabled IRQS */
704 if (desc == NULL || desc->handler == NULL 846 if (desc == NULL || desc->chip == NULL
705 || desc->action == NULL 847 || desc->action == NULL
706 || desc->handler->set_affinity == NULL) 848 || desc->chip->set_affinity == NULL)
707 continue; 849 continue;
708 850
709 spin_lock_irqsave(&desc->lock, flags); 851 spin_lock_irqsave(&desc->lock, flags);
@@ -728,8 +870,8 @@ void xics_migrate_irqs_away(void)
728 virq, cpu); 870 virq, cpu);
729 871
730 /* Reset affinity to all cpus */ 872 /* Reset affinity to all cpus */
731 desc->handler->set_affinity(virq, CPU_MASK_ALL); 873 desc->chip->set_affinity(virq, CPU_MASK_ALL);
732 irq_affinity[virq] = CPU_MASK_ALL; 874 irq_desc[irq].affinity = CPU_MASK_ALL;
733unlock: 875unlock:
734 spin_unlock_irqrestore(&desc->lock, flags); 876 spin_unlock_irqrestore(&desc->lock, flags);
735 } 877 }
diff --git a/arch/powerpc/platforms/pseries/xics.h b/arch/powerpc/platforms/pseries/xics.h
index e14c70868f1d..6ee1055b0ffb 100644
--- a/arch/powerpc/platforms/pseries/xics.h
+++ b/arch/powerpc/platforms/pseries/xics.h
@@ -14,13 +14,12 @@
14 14
15#include <linux/cache.h> 15#include <linux/cache.h>
16 16
17void xics_init_IRQ(void); 17extern void xics_init_IRQ(void);
18int xics_get_irq(struct pt_regs *); 18extern void xics_setup_cpu(void);
19void xics_setup_cpu(void); 19extern void xics_teardown_cpu(int secondary);
20void xics_teardown_cpu(int secondary); 20extern void xics_cause_IPI(int cpu);
21void xics_cause_IPI(int cpu); 21extern void xics_request_IPIs(void);
22void xics_request_IPIs(void); 22extern void xics_migrate_irqs_away(void);
23void xics_migrate_irqs_away(void);
24 23
25/* first argument is ignored for now*/ 24/* first argument is ignored for now*/
26void pSeriesLP_cppr_info(int n_cpu, u8 value); 25void pSeriesLP_cppr_info(int n_cpu, u8 value);
@@ -31,4 +30,8 @@ struct xics_ipi_struct {
31 30
32extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; 31extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
33 32
33struct irq_desc;
34extern void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc,
35 struct pt_regs *regs);
36
34#endif /* _POWERPC_KERNEL_XICS_H */ 37#endif /* _POWERPC_KERNEL_XICS_H */