aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-08 14:50:19 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-08 14:50:19 -0400
commitdf6d3916f3b7b7e2067567a256dd4f0c1ea854a2 (patch)
tree0fdeab1ab5d566605fc99aeb5ea3f621f11e7608 /arch/powerpc/platforms
parent74add80cbd7fe246c893b93ee75ac59acdd01dd4 (diff)
parent197686dfe0038fd190326d118b743ff65ad20c0e (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (77 commits) [POWERPC] Abolish powerpc_flash_init() [POWERPC] Early serial debug support for PPC44x [POWERPC] Support for the Ebony 440GP reference board in arch/powerpc [POWERPC] Add device tree for Ebony [POWERPC] Add powerpc/platforms/44x, disable platforms/4xx for now [POWERPC] MPIC U3/U4 MSI backend [POWERPC] MPIC MSI allocator [POWERPC] Enable MSI mappings for MPIC [POWERPC] Tell Phyp we support MSI [POWERPC] RTAS MSI implementation [POWERPC] PowerPC MSI infrastructure [POWERPC] Rip out the existing powerpc msi stubs [POWERPC] Remove use of 4level-fixup.h for ppc32 [POWERPC] Add powerpc PCI-E reset API implementation [POWERPC] Holly bootwrapper [POWERPC] Holly DTS [POWERPC] Holly defconfig [POWERPC] Add support for 750CL Holly board [POWERPC] Generalize tsi108 PCI setup [POWERPC] Generalize tsi108 PHY types ... Fixed conflict in include/asm-powerpc/kdebug.h manually Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/44x/44x.h8
-rw-r--r--arch/powerpc/platforms/44x/Kconfig56
-rw-r--r--arch/powerpc/platforms/44x/Makefile2
-rw-r--r--arch/powerpc/platforms/44x/ebony.c73
-rw-r--r--arch/powerpc/platforms/44x/misc_44x.S57
-rw-r--r--arch/powerpc/platforms/52xx/Kconfig1
-rw-r--r--arch/powerpc/platforms/52xx/Makefile2
-rw-r--r--arch/powerpc/platforms/52xx/efika.c15
-rw-r--r--arch/powerpc/platforms/52xx/lite5200.c28
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_pm.c191
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_sleep.S154
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_mds.c1
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_rdb.c1
-rw-r--r--arch/powerpc/platforms/83xx/mpc836x_mds.c1
-rw-r--r--arch/powerpc/platforms/85xx/mpc8544_ds.c2
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_cds.c2
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_mds.c1
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_hpcn.c2
-rw-r--r--arch/powerpc/platforms/Kconfig1
-rw-r--r--arch/powerpc/platforms/Makefile3
-rw-r--r--arch/powerpc/platforms/cell/interrupt.c6
-rw-r--r--arch/powerpc/platforms/cell/setup.c2
-rw-r--r--arch/powerpc/platforms/cell/spider-pic.c4
-rw-r--r--arch/powerpc/platforms/chrp/pci.c2
-rw-r--r--arch/powerpc/platforms/chrp/setup.c2
-rw-r--r--arch/powerpc/platforms/embedded6xx/Kconfig14
-rw-r--r--arch/powerpc/platforms/embedded6xx/Makefile1
-rw-r--r--arch/powerpc/platforms/embedded6xx/holly.c317
-rw-r--r--arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c21
-rw-r--r--arch/powerpc/platforms/maple/pci.c12
-rw-r--r--arch/powerpc/platforms/maple/setup.c2
-rw-r--r--arch/powerpc/platforms/pasemi/cpufreq.c4
-rw-r--r--arch/powerpc/platforms/pasemi/setup.c7
-rw-r--r--arch/powerpc/platforms/powermac/cpufreq_64.c8
-rw-r--r--arch/powerpc/platforms/powermac/feature.c26
-rw-r--r--arch/powerpc/platforms/powermac/low_i2c.c2
-rw-r--r--arch/powerpc/platforms/powermac/nvram.c4
-rw-r--r--arch/powerpc/platforms/powermac/pci.c30
-rw-r--r--arch/powerpc/platforms/powermac/pic.c2
-rw-r--r--arch/powerpc/platforms/powermac/setup.c121
-rw-r--r--arch/powerpc/platforms/powermac/smp.c18
-rw-r--r--arch/powerpc/platforms/ps3/htab.c3
-rw-r--r--arch/powerpc/platforms/ps3/interrupt.c234
-rw-r--r--arch/powerpc/platforms/ps3/mm.c1
-rw-r--r--arch/powerpc/platforms/ps3/setup.c7
-rw-r--r--arch/powerpc/platforms/ps3/smp.c6
-rw-r--r--arch/powerpc/platforms/ps3/spu.c18
-rw-r--r--arch/powerpc/platforms/pseries/Makefile1
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c30
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c6
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c4
-rw-r--r--arch/powerpc/platforms/pseries/msi.c270
-rw-r--r--arch/powerpc/platforms/pseries/pci_dlpar.c1
-rw-r--r--arch/powerpc/platforms/pseries/setup.c2
-rw-r--r--arch/powerpc/platforms/pseries/xics.c4
55 files changed, 1556 insertions, 237 deletions
diff --git a/arch/powerpc/platforms/44x/44x.h b/arch/powerpc/platforms/44x/44x.h
new file mode 100644
index 000000000000..42eabf87fea3
--- /dev/null
+++ b/arch/powerpc/platforms/44x/44x.h
@@ -0,0 +1,8 @@
1#ifndef __POWERPC_PLATFORMS_44X_44X_H
2#define __POWERPC_PLATFORMS_44X_44X_H
3
4extern u8 as1_readb(volatile u8 __iomem *addr);
5extern void as1_writeb(u8 data, volatile u8 __iomem *addr);
6extern void ppc44x_reset_system(char *cmd);
7
8#endif /* __POWERPC_PLATFORMS_44X_44X_H */
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
new file mode 100644
index 000000000000..8e66949e7c67
--- /dev/null
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -0,0 +1,56 @@
1#config BAMBOO
2# bool "Bamboo"
3# depends on 44x
4# default n
5# select 440EP
6# help
7# This option enables support for the IBM PPC440EP evaluation board.
8
9config EBONY
10 bool "Ebony"
11 depends on 44x
12 default y
13 select 440GP
14 help
15 This option enables support for the IBM PPC440GP evaluation board.
16
17#config LUAN
18# bool "Luan"
19# depends on 44x
20# default n
21# select 440SP
22# help
23# This option enables support for the IBM PPC440SP evaluation board.
24
25#config OCOTEA
26# bool "Ocotea"
27# depends on 44x
28# default n
29# select 440GX
30# help
31# This option enables support for the IBM PPC440GX evaluation board.
32
33# 44x specific CPU modules, selected based on the board above.
34config 440EP
35 bool
36 select PPC_FPU
37 select IBM440EP_ERR42
38
39config 440GP
40 bool
41 select IBM_NEW_EMAC_ZMII
42
43config 440GX
44 bool
45
46config 440SP
47 bool
48
49config 440A
50 bool
51 depends on 440GX
52 default y
53
54# 44x errata/workaround config symbols, selected by the CPU models above
55config IBM440EP_ERR42
56 bool
diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile
new file mode 100644
index 000000000000..41d0a18a0e44
--- /dev/null
+++ b/arch/powerpc/platforms/44x/Makefile
@@ -0,0 +1,2 @@
1obj-$(CONFIG_44x) := misc_44x.o
2obj-$(CONFIG_EBONY) += ebony.o
diff --git a/arch/powerpc/platforms/44x/ebony.c b/arch/powerpc/platforms/44x/ebony.c
new file mode 100644
index 000000000000..ad526eafc90b
--- /dev/null
+++ b/arch/powerpc/platforms/44x/ebony.c
@@ -0,0 +1,73 @@
1/*
2 * Ebony board specific routines
3 *
4 * Matt Porter <mporter@kernel.crashing.org>
5 * Copyright 2002-2005 MontaVista Software Inc.
6 *
7 * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
8 * Copyright (c) 2003-2005 Zultys Technologies
9 *
10 * Rewritten and ported to the merged powerpc tree:
11 * Copyright 2007 David Gibson <dwg@au1.ibm.com>, IBM Corporation.
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 */
18
19#include <linux/init.h>
20#include <asm/machdep.h>
21#include <asm/prom.h>
22#include <asm/udbg.h>
23#include <asm/time.h>
24#include <asm/uic.h>
25#include <asm/of_platform.h>
26
27#include "44x.h"
28
29static struct of_device_id ebony_of_bus[] = {
30 { .type = "ibm,plb", },
31 { .type = "ibm,opb", },
32 { .type = "ibm,ebc", },
33 {},
34};
35
36static int __init ebony_device_probe(void)
37{
38 if (!machine_is(ebony))
39 return 0;
40
41 of_platform_bus_probe(NULL, ebony_of_bus, NULL);
42
43 return 0;
44}
45device_initcall(ebony_device_probe);
46
47/*
48 * Called very early, MMU is off, device-tree isn't unflattened
49 */
50static int __init ebony_probe(void)
51{
52 unsigned long root = of_get_flat_dt_root();
53
54 if (!of_flat_dt_is_compatible(root, "ibm,ebony"))
55 return 0;
56
57 return 1;
58}
59
60static void __init ebony_setup_arch(void)
61{
62}
63
64define_machine(ebony) {
65 .name = "Ebony",
66 .probe = ebony_probe,
67 .setup_arch = ebony_setup_arch,
68 .progress = udbg_progress,
69 .init_IRQ = uic_init_tree,
70 .get_irq = uic_get_irq,
71 .restart = ppc44x_reset_system,
72 .calibrate_decr = generic_calibrate_decr,
73};
diff --git a/arch/powerpc/platforms/44x/misc_44x.S b/arch/powerpc/platforms/44x/misc_44x.S
new file mode 100644
index 000000000000..3bce71d5d756
--- /dev/null
+++ b/arch/powerpc/platforms/44x/misc_44x.S
@@ -0,0 +1,57 @@
1/*
2 * This file contains miscellaneous low-level functions for PPC 44x.
3 * Copyright 2007 David Gibson <dwg@au1.ibm.com>, IBM Corporation.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
10 */
11
12#include <asm/reg.h>
13#include <asm/ppc_asm.h>
14
15 .text
16
17/*
18 * Do an IO access in AS1
19 */
20_GLOBAL(as1_readb)
21 mfmsr r7
22 ori r0,r7,MSR_DS
23 sync
24 mtmsr r0
25 sync
26 isync
27 lbz r3,0(r3)
28 sync
29 mtmsr r7
30 sync
31 isync
32 blr
33
34_GLOBAL(as1_writeb)
35 mfmsr r7
36 ori r0,r7,MSR_DS
37 sync
38 mtmsr r0
39 sync
40 isync
41 stb r3,0(r4)
42 sync
43 mtmsr r7
44 sync
45 isync
46 blr
47
48/*
49 * void ppc44x_reset_system(char *cmd)
50 *
51 * At present, this routine just applies a system reset.
52 */
53_GLOBAL(ppc44x_reset_system)
54 mfspr r13,SPRN_DBCR0
55 oris r13,r13,DBCR0_RST_SYSTEM@h
56 mtspr SPRN_DBCR0,r13
57 b . /* Just in case the reset doesn't work */
diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig
index bc4aa4a80a12..3ffaa066c2c8 100644
--- a/arch/powerpc/platforms/52xx/Kconfig
+++ b/arch/powerpc/platforms/52xx/Kconfig
@@ -1,5 +1,6 @@
1config PPC_MPC52xx 1config PPC_MPC52xx
2 bool 2 bool
3 select FSL_SOC
3 default n 4 default n
4 5
5config PPC_MPC5200 6config PPC_MPC5200
diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile
index 07cdbcacf156..b91e39c84d46 100644
--- a/arch/powerpc/platforms/52xx/Makefile
+++ b/arch/powerpc/platforms/52xx/Makefile
@@ -8,3 +8,5 @@ endif
8 8
9obj-$(CONFIG_PPC_EFIKA) += efika.o 9obj-$(CONFIG_PPC_EFIKA) += efika.o
10obj-$(CONFIG_PPC_LITE5200) += lite5200.o 10obj-$(CONFIG_PPC_LITE5200) += lite5200.o
11
12obj-$(CONFIG_PM) += mpc52xx_sleep.o mpc52xx_pm.o
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c
index a6bba97314eb..f591a9fc19b9 100644
--- a/arch/powerpc/platforms/52xx/efika.c
+++ b/arch/powerpc/platforms/52xx/efika.c
@@ -184,6 +184,16 @@ static void efika_show_cpuinfo(struct seq_file *m)
184 of_node_put(root); 184 of_node_put(root);
185} 185}
186 186
187#ifdef CONFIG_PM
188static void efika_suspend_prepare(void __iomem *mbar)
189{
190 u8 pin = 4; /* GPIO_WKUP_4 (GPIO_PSC6_0 - IRDA_RX) */
191 u8 level = 1; /* wakeup on high level */
192 /* IOW. to wake it up, short pins 1 and 3 on IRDA connector */
193 mpc52xx_set_wakeup_gpio(pin, level);
194}
195#endif
196
187static void __init efika_setup_arch(void) 197static void __init efika_setup_arch(void)
188{ 198{
189 rtas_initialize(); 199 rtas_initialize();
@@ -199,6 +209,11 @@ static void __init efika_setup_arch(void)
199 209
200 efika_pcisetup(); 210 efika_pcisetup();
201 211
212#ifdef CONFIG_PM
213 mpc52xx_suspend.board_suspend_prepare = efika_suspend_prepare;
214 mpc52xx_pm_init();
215#endif
216
202 if (ppc_md.progress) 217 if (ppc_md.progress)
203 ppc_md.progress("Linux/PPC " UTS_RELEASE " running on Efika ;-)\n", 0x0); 218 ppc_md.progress("Linux/PPC " UTS_RELEASE " running on Efika ;-)\n", 0x0);
204} 219}
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
index 8e2646ac417b..1cfc00dfb99a 100644
--- a/arch/powerpc/platforms/52xx/lite5200.c
+++ b/arch/powerpc/platforms/52xx/lite5200.c
@@ -85,6 +85,28 @@ error:
85 iounmap(gpio); 85 iounmap(gpio);
86} 86}
87 87
88#ifdef CONFIG_PM
89static u32 descr_a;
90static void lite5200_suspend_prepare(void __iomem *mbar)
91{
92 u8 pin = 1; /* GPIO_WKUP_1 (GPIO_PSC2_4) */
93 u8 level = 0; /* wakeup on low level */
94 mpc52xx_set_wakeup_gpio(pin, level);
95
96 /*
97 * power down usb port
98 * this needs to be called before of-ohci suspend code
99 */
100 descr_a = in_be32(mbar + 0x1048);
101 out_be32(mbar + 0x1048, (descr_a & ~0x200) | 0x100);
102}
103
104static void lite5200_resume_finish(void __iomem *mbar)
105{
106 out_be32(mbar + 0x1048, descr_a);
107}
108#endif
109
88static void __init lite5200_setup_arch(void) 110static void __init lite5200_setup_arch(void)
89{ 111{
90 struct device_node *np; 112 struct device_node *np;
@@ -107,6 +129,12 @@ static void __init lite5200_setup_arch(void)
107 mpc52xx_setup_cpu(); /* Generic */ 129 mpc52xx_setup_cpu(); /* Generic */
108 lite5200_setup_cpu(); /* Platorm specific */ 130 lite5200_setup_cpu(); /* Platorm specific */
109 131
132#ifdef CONFIG_PM
133 mpc52xx_suspend.board_suspend_prepare = lite5200_suspend_prepare;
134 mpc52xx_suspend.board_resume_finish = lite5200_resume_finish;
135 mpc52xx_pm_init();
136#endif
137
110#ifdef CONFIG_PCI 138#ifdef CONFIG_PCI
111 np = of_find_node_by_type(NULL, "pci"); 139 np = of_find_node_by_type(NULL, "pci");
112 if (np) { 140 if (np) {
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pm.c b/arch/powerpc/platforms/52xx/mpc52xx_pm.c
new file mode 100644
index 000000000000..fd40044d16cd
--- /dev/null
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pm.c
@@ -0,0 +1,191 @@
1#include <linux/init.h>
2#include <linux/pm.h>
3#include <linux/io.h>
4#include <asm/time.h>
5#include <asm/cacheflush.h>
6#include <asm/mpc52xx.h>
7
8#include "mpc52xx_pic.h"
9
10
11/* these are defined in mpc52xx_sleep.S, and only used here */
12extern void mpc52xx_deep_sleep(void *sram, void *sdram_regs,
13 struct mpc52xx_cdm *, struct mpc52xx_intr *);
14extern void mpc52xx_ds_sram(void);
15extern const long mpc52xx_ds_sram_size;
16extern void mpc52xx_ds_cached(void);
17extern const long mpc52xx_ds_cached_size;
18
19static void __iomem *mbar;
20static void __iomem *sdram;
21static struct mpc52xx_cdm __iomem *cdm;
22static struct mpc52xx_intr __iomem *intr;
23static struct mpc52xx_gpio_wkup __iomem *gpiow;
24static void *sram;
25static int sram_size;
26
27struct mpc52xx_suspend mpc52xx_suspend;
28
29static int mpc52xx_pm_valid(suspend_state_t state)
30{
31 switch (state) {
32 case PM_SUSPEND_STANDBY:
33 return 1;
34 default:
35 return 0;
36 }
37}
38
39int mpc52xx_set_wakeup_gpio(u8 pin, u8 level)
40{
41 u16 tmp;
42
43 /* enable gpio */
44 out_8(&gpiow->wkup_gpioe, in_8(&gpiow->wkup_gpioe) | (1 << pin));
45 /* set as input */
46 out_8(&gpiow->wkup_ddr, in_8(&gpiow->wkup_ddr) & ~(1 << pin));
47 /* enable deep sleep interrupt */
48 out_8(&gpiow->wkup_inten, in_8(&gpiow->wkup_inten) | (1 << pin));
49 /* low/high level creates wakeup interrupt */
50 tmp = in_be16(&gpiow->wkup_itype);
51 tmp &= ~(0x3 << (pin * 2));
52 tmp |= (!level + 1) << (pin * 2);
53 out_be16(&gpiow->wkup_itype, tmp);
54 /* master enable */
55 out_8(&gpiow->wkup_maste, 1);
56
57 return 0;
58}
59
60int mpc52xx_pm_prepare(suspend_state_t state)
61{
62 if (state != PM_SUSPEND_STANDBY)
63 return -EINVAL;
64
65 /* map the whole register space */
66 mbar = mpc52xx_find_and_map("mpc5200");
67 if (!mbar) {
68 printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__);
69 return -ENOSYS;
70 }
71 /* these offsets are from mpc5200 users manual */
72 sdram = mbar + 0x100;
73 cdm = mbar + 0x200;
74 intr = mbar + 0x500;
75 gpiow = mbar + 0xc00;
76 sram = mbar + 0x8000; /* Those will be handled by the */
77 sram_size = 0x4000; /* bestcomm driver soon */
78
79 /* call board suspend code, if applicable */
80 if (mpc52xx_suspend.board_suspend_prepare)
81 mpc52xx_suspend.board_suspend_prepare(mbar);
82 else {
83 printk(KERN_ALERT "%s: %i don't know how to wake up the board\n",
84 __func__, __LINE__);
85 goto out_unmap;
86 }
87
88 return 0;
89
90 out_unmap:
91 iounmap(mbar);
92 return -ENOSYS;
93}
94
95
96char saved_sram[0x4000];
97
98int mpc52xx_pm_enter(suspend_state_t state)
99{
100 u32 clk_enables;
101 u32 msr, hid0;
102 u32 intr_main_mask;
103 void __iomem * irq_0x500 = (void *)CONFIG_KERNEL_START + 0x500;
104 unsigned long irq_0x500_stop = (unsigned long)irq_0x500 + mpc52xx_ds_cached_size;
105 char saved_0x500[mpc52xx_ds_cached_size];
106
107 /* disable all interrupts in PIC */
108 intr_main_mask = in_be32(&intr->main_mask);
109 out_be32(&intr->main_mask, intr_main_mask | 0x1ffff);
110
111 /* don't let DEC expire any time soon */
112 mtspr(SPRN_DEC, 0x7fffffff);
113
114 /* save SRAM */
115 memcpy(saved_sram, sram, sram_size);
116
117 /* copy low level suspend code to sram */
118 memcpy(sram, mpc52xx_ds_sram, mpc52xx_ds_sram_size);
119
120 out_8(&cdm->ccs_sleep_enable, 1);
121 out_8(&cdm->osc_sleep_enable, 1);
122 out_8(&cdm->ccs_qreq_test, 1);
123
124 /* disable all but SDRAM and bestcomm (SRAM) clocks */
125 clk_enables = in_be32(&cdm->clk_enables);
126 out_be32(&cdm->clk_enables, clk_enables & 0x00088000);
127
128 /* disable power management */
129 msr = mfmsr();
130 mtmsr(msr & ~MSR_POW);
131
132 /* enable sleep mode, disable others */
133 hid0 = mfspr(SPRN_HID0);
134 mtspr(SPRN_HID0, (hid0 & ~(HID0_DOZE | HID0_NAP | HID0_DPM)) | HID0_SLEEP);
135
136 /* save original, copy our irq handler, flush from dcache and invalidate icache */
137 memcpy(saved_0x500, irq_0x500, mpc52xx_ds_cached_size);
138 memcpy(irq_0x500, mpc52xx_ds_cached, mpc52xx_ds_cached_size);
139 flush_icache_range((unsigned long)irq_0x500, irq_0x500_stop);
140
141 /* call low-level sleep code */
142 mpc52xx_deep_sleep(sram, sdram, cdm, intr);
143
144 /* restore original irq handler */
145 memcpy(irq_0x500, saved_0x500, mpc52xx_ds_cached_size);
146 flush_icache_range((unsigned long)irq_0x500, irq_0x500_stop);
147
148 /* restore old power mode */
149 mtmsr(msr & ~MSR_POW);
150 mtspr(SPRN_HID0, hid0);
151 mtmsr(msr);
152
153 out_be32(&cdm->clk_enables, clk_enables);
154 out_8(&cdm->ccs_sleep_enable, 0);
155 out_8(&cdm->osc_sleep_enable, 0);
156
157 /* restore SRAM */
158 memcpy(sram, saved_sram, sram_size);
159
160 /* restart jiffies */
161 wakeup_decrementer();
162
163 /* reenable interrupts in PIC */
164 out_be32(&intr->main_mask, intr_main_mask);
165
166 return 0;
167}
168
169int mpc52xx_pm_finish(suspend_state_t state)
170{
171 /* call board resume code */
172 if (mpc52xx_suspend.board_resume_finish)
173 mpc52xx_suspend.board_resume_finish(mbar);
174
175 iounmap(mbar);
176
177 return 0;
178}
179
180static struct pm_ops mpc52xx_pm_ops = {
181 .valid = mpc52xx_pm_valid,
182 .prepare = mpc52xx_pm_prepare,
183 .enter = mpc52xx_pm_enter,
184 .finish = mpc52xx_pm_finish,
185};
186
187int __init mpc52xx_pm_init(void)
188{
189 pm_set_ops(&mpc52xx_pm_ops);
190 return 0;
191}
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_sleep.S b/arch/powerpc/platforms/52xx/mpc52xx_sleep.S
new file mode 100644
index 000000000000..4dc170b0ae18
--- /dev/null
+++ b/arch/powerpc/platforms/52xx/mpc52xx_sleep.S
@@ -0,0 +1,154 @@
1#include <asm/reg.h>
2#include <asm/ppc_asm.h>
3#include <asm/processor.h>
4
5
6.text
7
8_GLOBAL(mpc52xx_deep_sleep)
9mpc52xx_deep_sleep: /* args r3-r6: SRAM, SDRAM regs, CDM regs, INTR regs */
10
11 /* enable interrupts */
12 mfmsr r7
13 ori r7, r7, 0x8000 /* EE */
14 mtmsr r7
15 sync; isync;
16
17 li r10, 0 /* flag that irq handler sets */
18
19 /* enable tmr7 (or any other) interrupt */
20 lwz r8, 0x14(r6) /* intr->main_mask */
21 ori r8, r8, 0x1
22 xori r8, r8, 0x1
23 stw r8, 0x14(r6)
24 sync
25
26 /* emulate tmr7 interrupt */
27 li r8, 0x1
28 stw r8, 0x40(r6) /* intr->main_emulate */
29 sync
30
31 /* wait for it to happen */
321:
33 cmpi cr0, r10, 1
34 bne cr0, 1b
35
36 /* lock icache */
37 mfspr r10, SPRN_HID0
38 ori r10, r10, 0x2000
39 sync; isync;
40 mtspr SPRN_HID0, r10
41 sync; isync;
42
43
44 mflr r9 /* save LR */
45
46 /* jump to sram */
47 mtlr r3
48 blrl
49
50 mtlr r9 /* restore LR */
51
52 /* unlock icache */
53 mfspr r10, SPRN_HID0
54 ori r10, r10, 0x2000
55 xori r10, r10, 0x2000
56 sync; isync;
57 mtspr SPRN_HID0, r10
58 sync; isync;
59
60
61 /* return to C code */
62 blr
63
64
65_GLOBAL(mpc52xx_ds_sram)
66mpc52xx_ds_sram:
67 /* put SDRAM into self-refresh */
68 lwz r8, 0x4(r4) /* sdram->ctrl */
69
70 oris r8, r8, 0x8000 /* mode_en */
71 stw r8, 0x4(r4)
72 sync
73
74 ori r8, r8, 0x0002 /* soft_pre */
75 stw r8, 0x4(r4)
76 sync
77 xori r8, r8, 0x0002
78
79 xoris r8, r8, 0x8000 /* !mode_en */
80 stw r8, 0x4(r4)
81 sync
82
83 oris r8, r8, 0x5000
84 xoris r8, r8, 0x4000 /* ref_en !cke */
85 stw r8, 0x4(r4)
86 sync
87
88 /* disable SDRAM clock */
89 lwz r8, 0x14(r5) /* cdm->clkenable */
90 ori r8, r8, 0x0008
91 xori r8, r8, 0x0008
92 stw r8, 0x14(r5)
93 sync
94
95
96 /* put mpc5200 to sleep */
97 mfmsr r10
98 oris r10, r10, 0x0004 /* POW = 1 */
99 sync; isync;
100 mtmsr r10
101 sync; isync;
102
103
104 /* enable clock */
105 lwz r8, 0x14(r5)
106 ori r8, r8, 0x0008
107 stw r8, 0x14(r5)
108 sync
109
110 /* get ram out of self-refresh */
111 lwz r8, 0x4(r4)
112 oris r8, r8, 0x5000 /* cke ref_en */
113 stw r8, 0x4(r4)
114 sync
115
116 blr
117_GLOBAL(mpc52xx_ds_sram_size)
118mpc52xx_ds_sram_size:
119 .long $-mpc52xx_ds_sram
120
121
122/* ### interrupt handler for wakeup from deep-sleep ### */
123_GLOBAL(mpc52xx_ds_cached)
124mpc52xx_ds_cached:
125 mtspr SPRN_SPRG0, r7
126 mtspr SPRN_SPRG1, r8
127
128 /* disable emulated interrupt */
129 mfspr r7, 311 /* MBAR */
130 addi r7, r7, 0x540 /* intr->main_emul */
131 li r8, 0
132 stw r8, 0(r7)
133 sync
134 dcbf 0, r7
135
136 /* acknowledge wakeup, so CCS releases power pown */
137 mfspr r7, 311 /* MBAR */
138 addi r7, r7, 0x524 /* intr->enc_status */
139 lwz r8, 0(r7)
140 ori r8, r8, 0x0400
141 stw r8, 0(r7)
142 sync
143 dcbf 0, r7
144
145 /* flag - we handled the interrupt */
146 li r10, 1
147
148 mfspr r8, SPRN_SPRG1
149 mfspr r7, SPRN_SPRG0
150
151 rfi
152_GLOBAL(mpc52xx_ds_cached_size)
153mpc52xx_ds_cached_size:
154 .long $-mpc52xx_ds_cached
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index fff09f5d6edf..94843ed52a93 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -111,6 +111,7 @@ static struct of_device_id mpc832x_ids[] = {
111 { .type = "soc", }, 111 { .type = "soc", },
112 { .compatible = "soc", }, 112 { .compatible = "soc", },
113 { .type = "qe", }, 113 { .type = "qe", },
114 { .type = "mdio", },
114 {}, 115 {},
115}; 116};
116 117
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
index 6b71e9ffb11a..b0b22bb29de7 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
@@ -73,6 +73,7 @@ static struct of_device_id mpc832x_ids[] = {
73 { .type = "soc", }, 73 { .type = "soc", },
74 { .compatible = "soc", }, 74 { .compatible = "soc", },
75 { .type = "qe", }, 75 { .type = "qe", },
76 { .type = "mdio", },
76 {}, 77 {},
77}; 78};
78 79
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c
index 526ed090a446..bceeff8bbfd2 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c
@@ -118,6 +118,7 @@ static struct of_device_id mpc836x_ids[] = {
118 { .type = "soc", }, 118 { .type = "soc", },
119 { .compatible = "soc", }, 119 { .compatible = "soc", },
120 { .type = "qe", }, 120 { .type = "qe", },
121 { .type = "mdio", },
121 {}, 122 {},
122}; 123};
123 124
diff --git a/arch/powerpc/platforms/85xx/mpc8544_ds.c b/arch/powerpc/platforms/85xx/mpc8544_ds.c
index 2867f85e6325..bec84ffe708e 100644
--- a/arch/powerpc/platforms/85xx/mpc8544_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc8544_ds.c
@@ -84,7 +84,7 @@ void __init mpc8544_ds_pic_init(void)
84#ifdef CONFIG_PPC_I8259 84#ifdef CONFIG_PPC_I8259
85 /* Initialize the i8259 controller */ 85 /* Initialize the i8259 controller */
86 for_each_node_by_type(np, "interrupt-controller") 86 for_each_node_by_type(np, "interrupt-controller")
87 if (device_is_compatible(np, "chrp,iic")) { 87 if (of_device_is_compatible(np, "chrp,iic")) {
88 cascade_node = np; 88 cascade_node = np;
89 break; 89 break;
90 } 90 }
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index 7e71636f9098..1490eb3ce0d3 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -197,7 +197,7 @@ static void __init mpc85xx_cds_pic_init(void)
197#ifdef CONFIG_PPC_I8259 197#ifdef CONFIG_PPC_I8259
198 /* Initialize the i8259 controller */ 198 /* Initialize the i8259 controller */
199 for_each_node_by_type(np, "interrupt-controller") 199 for_each_node_by_type(np, "interrupt-controller")
200 if (device_is_compatible(np, "chrp,iic")) { 200 if (of_device_is_compatible(np, "chrp,iic")) {
201 cascade_node = np; 201 cascade_node = np;
202 break; 202 break;
203 } 203 }
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 54db41689954..e3dddbfe66ff 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -147,6 +147,7 @@ static struct of_device_id mpc85xx_ids[] = {
147 { .type = "soc", }, 147 { .type = "soc", },
148 { .compatible = "soc", }, 148 { .compatible = "soc", },
149 { .type = "qe", }, 149 { .type = "qe", },
150 { .type = "mdio", },
150 {}, 151 {},
151}; 152};
152 153
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 3d3d98f5bd4a..90877565caa3 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -102,7 +102,7 @@ mpc86xx_hpcn_init_irq(void)
102#ifdef CONFIG_PCI 102#ifdef CONFIG_PCI
103 /* Initialize i8259 controller */ 103 /* Initialize i8259 controller */
104 for_each_node_by_type(np, "interrupt-controller") 104 for_each_node_by_type(np, "interrupt-controller")
105 if (device_is_compatible(np, "chrp,iic")) { 105 if (of_device_is_compatible(np, "chrp,iic")) {
106 cascade_node = np; 106 cascade_node = np;
107 break; 107 break;
108 } 108 }
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 51e33347c147..361acfa2894c 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -42,6 +42,7 @@ source "arch/powerpc/platforms/83xx/Kconfig"
42source "arch/powerpc/platforms/85xx/Kconfig" 42source "arch/powerpc/platforms/85xx/Kconfig"
43source "arch/powerpc/platforms/86xx/Kconfig" 43source "arch/powerpc/platforms/86xx/Kconfig"
44source "arch/powerpc/platforms/embedded6xx/Kconfig" 44source "arch/powerpc/platforms/embedded6xx/Kconfig"
45source "arch/powerpc/platforms/44x/Kconfig"
45#source "arch/powerpc/platforms/4xx/Kconfig 46#source "arch/powerpc/platforms/4xx/Kconfig
46 47
47config PPC_NATIVE 48config PPC_NATIVE
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index 452004283f17..d6e041a46d25 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -6,7 +6,8 @@ obj-$(CONFIG_PPC_PMAC) += powermac/
6endif 6endif
7endif 7endif
8obj-$(CONFIG_PPC_CHRP) += chrp/ 8obj-$(CONFIG_PPC_CHRP) += chrp/
9obj-$(CONFIG_4xx) += 4xx/ 9#obj-$(CONFIG_4xx) += 4xx/
10obj-$(CONFIG_44x) += 44x/
10obj-$(CONFIG_PPC_MPC52xx) += 52xx/ 11obj-$(CONFIG_PPC_MPC52xx) += 52xx/
11obj-$(CONFIG_PPC_8xx) += 8xx/ 12obj-$(CONFIG_PPC_8xx) += 8xx/
12obj-$(CONFIG_PPC_82xx) += 82xx/ 13obj-$(CONFIG_PPC_82xx) += 82xx/
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index 4fc4e92775d0..47264e722029 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -227,7 +227,7 @@ void iic_request_IPIs(void)
227 227
228static int iic_host_match(struct irq_host *h, struct device_node *node) 228static int iic_host_match(struct irq_host *h, struct device_node *node)
229{ 229{
230 return device_is_compatible(node, 230 return of_device_is_compatible(node,
231 "IBM,CBEA-Internal-Interrupt-Controller"); 231 "IBM,CBEA-Internal-Interrupt-Controller");
232} 232}
233 233
@@ -256,7 +256,7 @@ static int iic_host_xlate(struct irq_host *h, struct device_node *ct,
256 unsigned int node, ext, unit, class; 256 unsigned int node, ext, unit, class;
257 const u32 *val; 257 const u32 *val;
258 258
259 if (!device_is_compatible(ct, 259 if (!of_device_is_compatible(ct,
260 "IBM,CBEA-Internal-Interrupt-Controller")) 260 "IBM,CBEA-Internal-Interrupt-Controller"))
261 return -ENODEV; 261 return -ENODEV;
262 if (intsize != 1) 262 if (intsize != 1)
@@ -324,7 +324,7 @@ static int __init setup_iic(void)
324 324
325 for (dn = NULL; 325 for (dn = NULL;
326 (dn = of_find_node_by_name(dn,"interrupt-controller")) != NULL;) { 326 (dn = of_find_node_by_name(dn,"interrupt-controller")) != NULL;) {
327 if (!device_is_compatible(dn, 327 if (!of_device_is_compatible(dn,
328 "IBM,CBEA-Internal-Interrupt-Controller")) 328 "IBM,CBEA-Internal-Interrupt-Controller"))
329 continue; 329 continue;
330 np = of_get_property(dn, "ibm,interrupt-server-ranges", NULL); 330 np = of_get_property(dn, "ibm,interrupt-server-ranges", NULL);
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index 54b96183cb64..db6654272e13 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -112,7 +112,7 @@ static void __init mpic_init_IRQ(void)
112 112
113 for (dn = NULL; 113 for (dn = NULL;
114 (dn = of_find_node_by_name(dn, "interrupt-controller"));) { 114 (dn = of_find_node_by_name(dn, "interrupt-controller"));) {
115 if (!device_is_compatible(dn, "CBEA,platform-open-pic")) 115 if (!of_device_is_compatible(dn, "CBEA,platform-open-pic"))
116 continue; 116 continue;
117 117
118 /* The MPIC driver will get everything it needs from the 118 /* The MPIC driver will get everything it needs from the
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index fb1f15797bbb..05f4b3d3d756 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -358,12 +358,12 @@ void __init spider_init_IRQ(void)
358 */ 358 */
359 for (dn = NULL; 359 for (dn = NULL;
360 (dn = of_find_node_by_name(dn, "interrupt-controller"));) { 360 (dn = of_find_node_by_name(dn, "interrupt-controller"));) {
361 if (device_is_compatible(dn, "CBEA,platform-spider-pic")) { 361 if (of_device_is_compatible(dn, "CBEA,platform-spider-pic")) {
362 if (of_address_to_resource(dn, 0, &r)) { 362 if (of_address_to_resource(dn, 0, &r)) {
363 printk(KERN_WARNING "spider-pic: Failed\n"); 363 printk(KERN_WARNING "spider-pic: Failed\n");
364 continue; 364 continue;
365 } 365 }
366 } else if (device_is_compatible(dn, "sti,platform-spider-pic") 366 } else if (of_device_is_compatible(dn, "sti,platform-spider-pic")
367 && (chip < 2)) { 367 && (chip < 2)) {
368 static long hard_coded_pics[] = 368 static long hard_coded_pics[] =
369 { 0x24000008000ul, 0x34000008000ul}; 369 { 0x24000008000ul, 0x34000008000ul};
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index 1469d6478f67..d32fedc991d3 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -267,7 +267,7 @@ chrp_find_bridges(void)
267 model = of_get_property(dev, "model", NULL); 267 model = of_get_property(dev, "model", NULL);
268 if (model == NULL) 268 if (model == NULL)
269 model = "<none>"; 269 model = "<none>";
270 if (device_is_compatible(dev, "IBM,python")) { 270 if (of_device_is_compatible(dev, "IBM,python")) {
271 setup_python(hose, dev); 271 setup_python(hose, dev);
272 } else if (is_mot 272 } else if (is_mot
273 || strncmp(model, "Motorola, Grackle", 17) == 0) { 273 || strncmp(model, "Motorola, Grackle", 17) == 0) {
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 1870038a8e0a..373de4c063db 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -448,7 +448,7 @@ static void __init chrp_find_8259(void)
448 448
449 /* Look for cascade */ 449 /* Look for cascade */
450 for_each_node_by_type(np, "interrupt-controller") 450 for_each_node_by_type(np, "interrupt-controller")
451 if (device_is_compatible(np, "chrp,iic")) { 451 if (of_device_is_compatible(np, "chrp,iic")) {
452 pic = np; 452 pic = np;
453 break; 453 break;
454 } 454 }
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index 9557908ef545..8f3c2a73e165 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -20,16 +20,24 @@ config MPC7448HPC2
20 select TSI108_BRIDGE 20 select TSI108_BRIDGE
21 select DEFAULT_UIMAGE 21 select DEFAULT_UIMAGE
22 select PPC_UDBG_16550 22 select PPC_UDBG_16550
23 select MPIC
24 select MPIC_WEIRD
25 help 23 help
26 Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga) 24 Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga)
27 platform 25 platform
26
27config PPC_HOLLY
28 bool "PPC750GX/CL with TSI10x bridge (Hickory/Holly)"
29 select TSI108_BRIDGE
30 select PPC_UDBG_16550
31 help
32 Select PPC_HOLLY if configuring for an IBM 750GX/CL Eval
33 Board with TSI108/9 bridge (Hickory/Holly)
28endchoice 34endchoice
29 35
30config TSI108_BRIDGE 36config TSI108_BRIDGE
31 bool 37 bool
32 depends on MPC7448HPC2 38 depends on MPC7448HPC2 || PPC_HOLLY
39 select MPIC
40 select MPIC_WEIRD
33 default y 41 default y
34 42
35config MPC10X_BRIDGE 43config MPC10X_BRIDGE
diff --git a/arch/powerpc/platforms/embedded6xx/Makefile b/arch/powerpc/platforms/embedded6xx/Makefile
index d3d11a3cd656..b39fe4f470d5 100644
--- a/arch/powerpc/platforms/embedded6xx/Makefile
+++ b/arch/powerpc/platforms/embedded6xx/Makefile
@@ -3,3 +3,4 @@
3# 3#
4obj-$(CONFIG_MPC7448HPC2) += mpc7448_hpc2.o 4obj-$(CONFIG_MPC7448HPC2) += mpc7448_hpc2.o
5obj-$(CONFIG_LINKSTATION) += linkstation.o ls_uart.o 5obj-$(CONFIG_LINKSTATION) += linkstation.o ls_uart.o
6obj-$(CONFIG_PPC_HOLLY) += holly.o
diff --git a/arch/powerpc/platforms/embedded6xx/holly.c b/arch/powerpc/platforms/embedded6xx/holly.c
new file mode 100644
index 000000000000..3a0b4a01401c
--- /dev/null
+++ b/arch/powerpc/platforms/embedded6xx/holly.c
@@ -0,0 +1,317 @@
1/*
2 * Board setup routines for the IBM 750GX/CL platform w/ TSI10x bridge
3 *
4 * Copyright 2007 IBM Corporation
5 *
6 * Stephen Winiecki <stevewin@us.ibm.com>
7 * Josh Boyer <jwboyer@linux.vnet.ibm.com>
8 *
9 * Based on code from mpc7448_hpc2.c
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * version 2 as published by the Free Software Foundation.
14 */
15
16#include <linux/stddef.h>
17#include <linux/kernel.h>
18#include <linux/pci.h>
19#include <linux/kdev_t.h>
20#include <linux/console.h>
21#include <linux/delay.h>
22#include <linux/irq.h>
23#include <linux/ide.h>
24#include <linux/seq_file.h>
25#include <linux/root_dev.h>
26#include <linux/serial.h>
27#include <linux/tty.h>
28#include <linux/serial_core.h>
29
30#include <asm/system.h>
31#include <asm/time.h>
32#include <asm/machdep.h>
33#include <asm/prom.h>
34#include <asm/udbg.h>
35#include <asm/tsi108.h>
36#include <asm/pci-bridge.h>
37#include <asm/reg.h>
38#include <mm/mmu_decl.h>
39#include <asm/tsi108_irq.h>
40#include <asm/tsi108_pci.h>
41#include <asm/mpic.h>
42#include <asm/of_platform.h>
43
44#undef DEBUG
45
46#define HOLLY_PCI_CFG_PHYS 0x7c000000
47
48int holly_exclude_device(u_char bus, u_char devfn)
49{
50 if (bus == 0 && PCI_SLOT(devfn) == 0)
51 return PCIBIOS_DEVICE_NOT_FOUND;
52 else
53 return PCIBIOS_SUCCESSFUL;
54}
55
56static void holly_remap_bridge(void)
57{
58 u32 lut_val, lut_addr;
59 int i;
60
61 printk(KERN_INFO "Remapping PCI bridge\n");
62
63 /* Re-init the PCI bridge and LUT registers to have mappings that don't
64 * rely on PIBS
65 */
66 lut_addr = 0x900;
67 for (i = 0; i < 31; i++) {
68 tsi108_write_reg(TSI108_PB_OFFSET + lut_addr, 0x00000201);
69 lut_addr += 4;
70 tsi108_write_reg(TSI108_PB_OFFSET + lut_addr, 0x0);
71 lut_addr += 4;
72 }
73
74 /* Reserve the last LUT entry for PCI I/O space */
75 tsi108_write_reg(TSI108_PB_OFFSET + lut_addr, 0x00000241);
76 lut_addr += 4;
77 tsi108_write_reg(TSI108_PB_OFFSET + lut_addr, 0x0);
78
79 /* Map PCI I/O space */
80 tsi108_write_reg(TSI108_PCI_PFAB_IO_UPPER, 0x0);
81 tsi108_write_reg(TSI108_PCI_PFAB_IO, 0x1);
82
83 /* Map PCI CFG space */
84 tsi108_write_reg(TSI108_PCI_PFAB_BAR0_UPPER, 0x0);
85 tsi108_write_reg(TSI108_PCI_PFAB_BAR0, 0x7c000000 | 0x01);
86
87 /* We don't need MEM32 and PRM remapping so disable them */
88 tsi108_write_reg(TSI108_PCI_PFAB_MEM32, 0x0);
89 tsi108_write_reg(TSI108_PCI_PFAB_PFM3, 0x0);
90 tsi108_write_reg(TSI108_PCI_PFAB_PFM4, 0x0);
91
92 /* Set P2O_BAR0 */
93 tsi108_write_reg(TSI108_PCI_P2O_BAR0_UPPER, 0x0);
94 tsi108_write_reg(TSI108_PCI_P2O_BAR0, 0xc0000000);
95
96 /* Init the PCI LUTs to do no remapping */
97 lut_addr = 0x500;
98 lut_val = 0x00000002;
99
100 for (i = 0; i < 32; i++) {
101 tsi108_write_reg(TSI108_PCI_OFFSET + lut_addr, lut_val);
102 lut_addr += 4;
103 tsi108_write_reg(TSI108_PCI_OFFSET + lut_addr, 0x40000000);
104 lut_addr += 4;
105 lut_val += 0x02000000;
106 }
107 tsi108_write_reg(TSI108_PCI_P2O_PAGE_SIZES, 0x00007900);
108
109 /* Set 64-bit PCI bus address for system memory */
110 tsi108_write_reg(TSI108_PCI_P2O_BAR2_UPPER, 0x0);
111 tsi108_write_reg(TSI108_PCI_P2O_BAR2, 0x0);
112}
113
114static void __init holly_setup_arch(void)
115{
116 struct device_node *cpu;
117 struct device_node *np;
118
119 if (ppc_md.progress)
120 ppc_md.progress("holly_setup_arch():set_bridge", 0);
121
122 cpu = of_find_node_by_type(NULL, "cpu");
123 if (cpu) {
124 const unsigned int *fp;
125
126 fp = of_get_property(cpu, "clock-frequency", NULL);
127 if (fp)
128 loops_per_jiffy = *fp / HZ;
129 else
130 loops_per_jiffy = 50000000 / HZ;
131 of_node_put(cpu);
132 }
133 tsi108_csr_vir_base = get_vir_csrbase();
134
135 /* setup PCI host bridge */
136 holly_remap_bridge();
137
138 np = of_find_node_by_type(NULL, "pci");
139 if (np)
140 tsi108_setup_pci(np, HOLLY_PCI_CFG_PHYS, 1);
141
142 ppc_md.pci_exclude_device = holly_exclude_device;
143 if (ppc_md.progress)
144 ppc_md.progress("tsi108: resources set", 0x100);
145
146 printk(KERN_INFO "PPC750GX/CL Platform\n");
147}
148
149/*
150 * Interrupt setup and service. Interrrupts on the holly come
151 * from the four external INT pins, PCI interrupts are routed via
152 * PCI interrupt control registers, it generates internal IRQ23
153 *
154 * Interrupt routing on the Holly Board:
155 * TSI108:PB_INT[0] -> CPU0:INT#
156 * TSI108:PB_INT[1] -> CPU0:MCP#
157 * TSI108:PB_INT[2] -> N/C
158 * TSI108:PB_INT[3] -> N/C
159 */
160static void __init holly_init_IRQ(void)
161{
162 struct mpic *mpic;
163 phys_addr_t mpic_paddr = 0;
164 struct device_node *tsi_pic;
165#ifdef CONFIG_PCI
166 unsigned int cascade_pci_irq;
167 struct device_node *tsi_pci;
168 struct device_node *cascade_node = NULL;
169#endif
170
171 tsi_pic = of_find_node_by_type(NULL, "open-pic");
172 if (tsi_pic) {
173 unsigned int size;
174 const void *prop = of_get_property(tsi_pic, "reg", &size);
175 mpic_paddr = of_translate_address(tsi_pic, prop);
176 }
177
178 if (mpic_paddr == 0) {
179 printk(KERN_ERR "%s: No tsi108 PIC found !\n", __func__);
180 return;
181 }
182
183 pr_debug("%s: tsi108 pic phys_addr = 0x%x\n", __func__, (u32) mpic_paddr);
184
185 mpic = mpic_alloc(tsi_pic, mpic_paddr,
186 MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET |
187 MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108,
188 24,
189 NR_IRQS-4, /* num_sources used */
190 "Tsi108_PIC");
191
192 BUG_ON(mpic == NULL);
193
194 mpic_assign_isu(mpic, 0, mpic_paddr + 0x100);
195
196 mpic_init(mpic);
197
198#ifdef CONFIG_PCI
199 tsi_pci = of_find_node_by_type(NULL, "pci");
200 if (tsi_pci == NULL) {
201 printk(KERN_ERR "%s: No tsi108 pci node found !\n", __func__);
202 return;
203 }
204
205 cascade_node = of_find_node_by_type(NULL, "pic-router");
206 if (cascade_node == NULL) {
207 printk(KERN_ERR "%s: No tsi108 pci cascade node found !\n", __func__);
208 return;
209 }
210
211 cascade_pci_irq = irq_of_parse_and_map(tsi_pci, 0);
212 pr_debug("%s: tsi108 cascade_pci_irq = 0x%x\n", __func__, (u32) cascade_pci_irq);
213 tsi108_pci_int_init(cascade_node);
214 set_irq_data(cascade_pci_irq, mpic);
215 set_irq_chained_handler(cascade_pci_irq, tsi108_irq_cascade);
216#endif
217 /* Configure MPIC outputs to CPU0 */
218 tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0);
219 of_node_put(tsi_pic);
220}
221
222void holly_show_cpuinfo(struct seq_file *m)
223{
224 seq_printf(m, "vendor\t\t: IBM\n");
225 seq_printf(m, "machine\t\t: PPC750 GX/CL\n");
226}
227
228void holly_restart(char *cmd)
229{
230 __be32 __iomem *ocn_bar1 = NULL;
231 unsigned long bar;
232 struct device_node *bridge = NULL;
233 const void *prop;
234 int size;
235 phys_addr_t addr = 0xc0000000;
236
237 local_irq_disable();
238
239 bridge = of_find_node_by_type(NULL, "tsi-bridge");
240 if (bridge) {
241 prop = of_get_property(bridge, "reg", &size);
242 addr = of_translate_address(bridge, prop);
243 }
244 addr += (TSI108_PB_OFFSET + 0x414);
245
246 ocn_bar1 = ioremap(addr, 0x4);
247
248 /* Turn on the BOOT bit so the addresses are correctly
249 * routed to the HLP interface */
250 bar = ioread32be(ocn_bar1);
251 bar |= 2;
252 iowrite32be(bar, ocn_bar1);
253 iosync();
254
255 /* Set SRR0 to the reset vector and turn on MSR_IP */
256 mtspr(SPRN_SRR0, 0xfff00100);
257 mtspr(SPRN_SRR1, MSR_IP);
258
259 /* Do an rfi to jump back to firmware. Somewhat evil,
260 * but it works
261 */
262 __asm__ __volatile__("rfi" : : : "memory");
263
264 /* Spin until reset happens. Shouldn't really get here */
265 for (;;) ;
266}
267
268void holly_power_off(void)
269{
270 local_irq_disable();
271 /* No way to shut power off with software */
272 for (;;) ;
273}
274
275void holly_halt(void)
276{
277 holly_power_off();
278}
279
280/*
281 * Called very early, device-tree isn't unflattened
282 */
283static int __init holly_probe(void)
284{
285 unsigned long root = of_get_flat_dt_root();
286
287 if (!of_flat_dt_is_compatible(root, "ibm,holly"))
288 return 0;
289 return 1;
290}
291
292static int ppc750_machine_check_exception(struct pt_regs *regs)
293{
294 const struct exception_table_entry *entry;
295
296 /* Are we prepared to handle this fault */
297 if ((entry = search_exception_tables(regs->nip)) != NULL) {
298 tsi108_clear_pci_cfg_error();
299 regs->msr |= MSR_RI;
300 regs->nip = entry->fixup;
301 return 1;
302 }
303 return 0;
304}
305
306define_machine(holly){
307 .name = "PPC750 GX/CL TSI",
308 .probe = holly_probe,
309 .setup_arch = holly_setup_arch,
310 .init_IRQ = holly_init_IRQ,
311 .show_cpuinfo = holly_show_cpuinfo,
312 .get_irq = mpic_get_irq,
313 .restart = holly_restart,
314 .calibrate_decr = generic_calibrate_decr,
315 .machine_check_exception = ppc750_machine_check_exception,
316 .progress = udbg_progress,
317};
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
index c3f64ddb0be6..4542e0c837c0 100644
--- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
+++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
@@ -41,6 +41,7 @@
41#include <asm/reg.h> 41#include <asm/reg.h>
42#include <mm/mmu_decl.h> 42#include <mm/mmu_decl.h>
43#include "mpc7448_hpc2.h" 43#include "mpc7448_hpc2.h"
44#include <asm/tsi108_pci.h>
44#include <asm/tsi108_irq.h> 45#include <asm/tsi108_irq.h>
45#include <asm/mpic.h> 46#include <asm/mpic.h>
46 47
@@ -51,16 +52,15 @@
51#define DBG(fmt...) do { } while(0) 52#define DBG(fmt...) do { } while(0)
52#endif 53#endif
53 54
55#define MPC7448HPC2_PCI_CFG_PHYS 0xfb000000
56
54#ifndef CONFIG_PCI 57#ifndef CONFIG_PCI
55isa_io_base = MPC7448_HPC2_ISA_IO_BASE; 58isa_io_base = MPC7448_HPC2_ISA_IO_BASE;
56isa_mem_base = MPC7448_HPC2_ISA_MEM_BASE; 59isa_mem_base = MPC7448_HPC2_ISA_MEM_BASE;
57pci_dram_offset = MPC7448_HPC2_PCI_MEM_OFFSET; 60pci_dram_offset = MPC7448_HPC2_PCI_MEM_OFFSET;
58#endif 61#endif
59 62
60extern int tsi108_setup_pci(struct device_node *dev);
61extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val); 63extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
62extern void tsi108_pci_int_init(struct device_node *node);
63extern void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc);
64 64
65int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn) 65int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn)
66{ 66{
@@ -72,28 +72,16 @@ int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn)
72 72
73static void __init mpc7448_hpc2_setup_arch(void) 73static void __init mpc7448_hpc2_setup_arch(void)
74{ 74{
75 struct device_node *cpu;
76 struct device_node *np; 75 struct device_node *np;
77 if (ppc_md.progress) 76 if (ppc_md.progress)
78 ppc_md.progress("mpc7448_hpc2_setup_arch():set_bridge", 0); 77 ppc_md.progress("mpc7448_hpc2_setup_arch():set_bridge", 0);
79 78
80 cpu = of_find_node_by_type(NULL, "cpu");
81 if (cpu != 0) {
82 const unsigned int *fp;
83
84 fp = of_get_property(cpu, "clock-frequency", NULL);
85 if (fp != 0)
86 loops_per_jiffy = *fp / HZ;
87 else
88 loops_per_jiffy = 50000000 / HZ;
89 of_node_put(cpu);
90 }
91 tsi108_csr_vir_base = get_vir_csrbase(); 79 tsi108_csr_vir_base = get_vir_csrbase();
92 80
93 /* setup PCI host bridge */ 81 /* setup PCI host bridge */
94#ifdef CONFIG_PCI 82#ifdef CONFIG_PCI
95 for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) 83 for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
96 tsi108_setup_pci(np); 84 tsi108_setup_pci(np, MPC7448HPC2_PCI_CFG_PHYS, 0);
97 85
98 ppc_md.pci_exclude_device = mpc7448_hpc2_exclude_device; 86 ppc_md.pci_exclude_device = mpc7448_hpc2_exclude_device;
99 if (ppc_md.progress) 87 if (ppc_md.progress)
@@ -222,7 +210,6 @@ static int __init mpc7448_hpc2_probe(void)
222 210
223static int mpc7448_machine_check_exception(struct pt_regs *regs) 211static int mpc7448_machine_check_exception(struct pt_regs *regs)
224{ 212{
225 extern void tsi108_clear_pci_cfg_error(void);
226 const struct exception_table_entry *entry; 213 const struct exception_table_entry *entry;
227 214
228 /* Are we prepared to handle this fault */ 215 /* Are we prepared to handle this fault */
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index b1d3b99c3f9d..7aaa5bbc9363 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -467,15 +467,15 @@ static int __init add_bridge(struct device_node *dev)
467 hose->last_busno = bus_range ? bus_range[1] : 0xff; 467 hose->last_busno = bus_range ? bus_range[1] : 0xff;
468 468
469 disp_name = NULL; 469 disp_name = NULL;
470 if (device_is_compatible(dev, "u3-agp")) { 470 if (of_device_is_compatible(dev, "u3-agp")) {
471 setup_u3_agp(hose); 471 setup_u3_agp(hose);
472 disp_name = "U3-AGP"; 472 disp_name = "U3-AGP";
473 primary = 0; 473 primary = 0;
474 } else if (device_is_compatible(dev, "u3-ht")) { 474 } else if (of_device_is_compatible(dev, "u3-ht")) {
475 setup_u3_ht(hose); 475 setup_u3_ht(hose);
476 disp_name = "U3-HT"; 476 disp_name = "U3-HT";
477 primary = 1; 477 primary = 1;
478 } else if (device_is_compatible(dev, "u4-pcie")) { 478 } else if (of_device_is_compatible(dev, "u4-pcie")) {
479 setup_u4_pcie(hose); 479 setup_u4_pcie(hose);
480 disp_name = "U4-PCIE"; 480 disp_name = "U4-PCIE";
481 primary = 0; 481 primary = 0;
@@ -556,12 +556,12 @@ void __init maple_pci_init(void)
556 continue; 556 continue;
557 if (strcmp(np->type, "pci") && strcmp(np->type, "ht")) 557 if (strcmp(np->type, "pci") && strcmp(np->type, "ht"))
558 continue; 558 continue;
559 if ((device_is_compatible(np, "u4-pcie") || 559 if ((of_device_is_compatible(np, "u4-pcie") ||
560 device_is_compatible(np, "u3-agp")) && 560 of_device_is_compatible(np, "u3-agp")) &&
561 add_bridge(np) == 0) 561 add_bridge(np) == 0)
562 of_node_get(np); 562 of_node_get(np);
563 563
564 if (device_is_compatible(np, "u3-ht")) { 564 if (of_device_is_compatible(np, "u3-ht")) {
565 of_node_get(np); 565 of_node_get(np);
566 ht = np; 566 ht = np;
567 } 567 }
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index 2a30c5b2532e..354c05861629 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -231,7 +231,7 @@ static void __init maple_init_IRQ(void)
231 */ 231 */
232 232
233 for_each_node_by_type(np, "interrupt-controller") 233 for_each_node_by_type(np, "interrupt-controller")
234 if (device_is_compatible(np, "open-pic")) { 234 if (of_device_is_compatible(np, "open-pic")) {
235 mpic_node = np; 235 mpic_node = np;
236 break; 236 break;
237 } 237 }
diff --git a/arch/powerpc/platforms/pasemi/cpufreq.c b/arch/powerpc/platforms/pasemi/cpufreq.c
index 2a57d6023685..3ae083851b01 100644
--- a/arch/powerpc/platforms/pasemi/cpufreq.c
+++ b/arch/powerpc/platforms/pasemi/cpufreq.c
@@ -31,6 +31,7 @@
31#include <asm/hw_irq.h> 31#include <asm/hw_irq.h>
32#include <asm/io.h> 32#include <asm/io.h>
33#include <asm/prom.h> 33#include <asm/prom.h>
34#include <asm/time.h>
34 35
35#define SDCASR_REG 0x0100 36#define SDCASR_REG 0x0100
36#define SDCASR_REG_STRIDE 0x1000 37#define SDCASR_REG_STRIDE 0x1000
@@ -204,6 +205,8 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
204 policy->cur = pas_freqs[cur_astate].frequency; 205 policy->cur = pas_freqs[cur_astate].frequency;
205 policy->cpus = cpu_online_map; 206 policy->cpus = cpu_online_map;
206 207
208 ppc_proc_freq = policy->cur * 1000ul;
209
207 cpufreq_frequency_table_get_attr(pas_freqs, policy->cpu); 210 cpufreq_frequency_table_get_attr(pas_freqs, policy->cpu);
208 211
209 /* this ensures that policy->cpuinfo_min and policy->cpuinfo_max 212 /* this ensures that policy->cpuinfo_min and policy->cpuinfo_max
@@ -270,6 +273,7 @@ static int pas_cpufreq_target(struct cpufreq_policy *policy,
270 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); 273 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
271 mutex_unlock(&pas_switch_mutex); 274 mutex_unlock(&pas_switch_mutex);
272 275
276 ppc_proc_freq = freqs.new * 1000ul;
273 return 0; 277 return 0;
274} 278}
275 279
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
index f88f0ec4c8cb..38f107b3c521 100644
--- a/arch/powerpc/platforms/pasemi/setup.c
+++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -114,7 +114,7 @@ static __init void pas_init_IRQ(void)
114 mpic_node = NULL; 114 mpic_node = NULL;
115 115
116 for_each_node_by_type(np, "interrupt-controller") 116 for_each_node_by_type(np, "interrupt-controller")
117 if (device_is_compatible(np, "open-pic")) { 117 if (of_device_is_compatible(np, "open-pic")) {
118 mpic_node = np; 118 mpic_node = np;
119 break; 119 break;
120 } 120 }
@@ -211,7 +211,10 @@ static struct of_device_id pasemi_bus_ids[] = {
211 211
212static int __init pasemi_publish_devices(void) 212static int __init pasemi_publish_devices(void)
213{ 213{
214 /* Publish OF platform devices for southbridge IOs */ 214 if (!machine_is(pasemi))
215 return 0;
216
217 /* Publish OF platform devices for SDC and other non-PCI devices */
215 of_platform_bus_probe(NULL, pasemi_bus_ids, NULL); 218 of_platform_bus_probe(NULL, pasemi_bus_ids, NULL);
216 219
217 return 0; 220 return 0;
diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c
index 567d5523b690..00f50298c342 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_64.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_64.c
@@ -357,13 +357,13 @@ static unsigned int g5_cpufreq_get_speed(unsigned int cpu)
357 357
358static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy) 358static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy)
359{ 359{
360 if (policy->cpu != 0)
361 return -ENODEV;
362
363 policy->governor = CPUFREQ_DEFAULT_GOVERNOR; 360 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
364 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; 361 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
365 policy->cur = g5_cpu_freqs[g5_query_freq()].frequency; 362 policy->cur = g5_cpu_freqs[g5_query_freq()].frequency;
366 policy->cpus = cpu_possible_map; 363 /* secondary CPUs are tied to the primary one by the
364 * cpufreq core if in the secondary policy we tell it that
365 * it actually must be one policy together with all others. */
366 policy->cpus = cpu_online_map;
367 cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu); 367 cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu);
368 368
369 return cpufreq_frequency_table_cpuinfo(policy, 369 return cpufreq_frequency_table_cpuinfo(policy,
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index 52cfdd86c928..f29705f8047d 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -1418,7 +1418,7 @@ static long g5_eth_phy_reset(struct device_node *node, long param, long value)
1418 phy = of_get_next_child(node, NULL); 1418 phy = of_get_next_child(node, NULL);
1419 if (!phy) 1419 if (!phy)
1420 return -ENODEV; 1420 return -ENODEV;
1421 need_reset = device_is_compatible(phy, "B5221"); 1421 need_reset = of_device_is_compatible(phy, "B5221");
1422 of_node_put(phy); 1422 of_node_put(phy);
1423 if (!need_reset) 1423 if (!need_reset)
1424 return 0; 1424 return 0;
@@ -2624,7 +2624,7 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ
2624 for (node = NULL; (node = of_find_node_by_name(node, name)) != NULL;) { 2624 for (node = NULL; (node = of_find_node_by_name(node, name)) != NULL;) {
2625 if (!compat) 2625 if (!compat)
2626 break; 2626 break;
2627 if (device_is_compatible(node, compat)) 2627 if (of_device_is_compatible(node, compat))
2628 break; 2628 break;
2629 } 2629 }
2630 if (!node) 2630 if (!node)
@@ -2728,7 +2728,7 @@ initial_serial_shutdown(struct device_node *np)
2728 conn = of_get_property(np, "AAPL,connector", &len); 2728 conn = of_get_property(np, "AAPL,connector", &len);
2729 if (conn && (strcmp(conn, "infrared") == 0)) 2729 if (conn && (strcmp(conn, "infrared") == 0))
2730 port_type = PMAC_SCC_IRDA; 2730 port_type = PMAC_SCC_IRDA;
2731 else if (device_is_compatible(np, "cobalt")) 2731 else if (of_device_is_compatible(np, "cobalt"))
2732 modem = 1; 2732 modem = 1;
2733 else if (slots && slots->count > 0) { 2733 else if (slots && slots->count > 0) {
2734 if (strcmp(slots->name, "IrDA") == 0) 2734 if (strcmp(slots->name, "IrDA") == 0)
@@ -2787,7 +2787,7 @@ set_initial_features(void)
2787 */ 2787 */
2788 np = of_find_node_by_name(NULL, "ethernet"); 2788 np = of_find_node_by_name(NULL, "ethernet");
2789 while(np) { 2789 while(np) {
2790 if (device_is_compatible(np, "K2-GMAC")) 2790 if (of_device_is_compatible(np, "K2-GMAC"))
2791 g5_gmac_enable(np, 0, 1); 2791 g5_gmac_enable(np, 0, 1);
2792 np = of_find_node_by_name(np, "ethernet"); 2792 np = of_find_node_by_name(np, "ethernet");
2793 } 2793 }
@@ -2799,7 +2799,7 @@ set_initial_features(void)
2799 */ 2799 */
2800 np = of_find_node_by_name(NULL, "firewire"); 2800 np = of_find_node_by_name(NULL, "firewire");
2801 while(np) { 2801 while(np) {
2802 if (device_is_compatible(np, "pci106b,5811")) { 2802 if (of_device_is_compatible(np, "pci106b,5811")) {
2803 macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; 2803 macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
2804 g5_fw_enable(np, 0, 1); 2804 g5_fw_enable(np, 0, 1);
2805 } 2805 }
@@ -2817,8 +2817,8 @@ set_initial_features(void)
2817 np = of_find_node_by_name(NULL, "ethernet"); 2817 np = of_find_node_by_name(NULL, "ethernet");
2818 while(np) { 2818 while(np) {
2819 if (np->parent 2819 if (np->parent
2820 && device_is_compatible(np->parent, "uni-north") 2820 && of_device_is_compatible(np->parent, "uni-north")
2821 && device_is_compatible(np, "gmac")) 2821 && of_device_is_compatible(np, "gmac"))
2822 core99_gmac_enable(np, 0, 1); 2822 core99_gmac_enable(np, 0, 1);
2823 np = of_find_node_by_name(np, "ethernet"); 2823 np = of_find_node_by_name(np, "ethernet");
2824 } 2824 }
@@ -2831,10 +2831,10 @@ set_initial_features(void)
2831 np = of_find_node_by_name(NULL, "firewire"); 2831 np = of_find_node_by_name(NULL, "firewire");
2832 while(np) { 2832 while(np) {
2833 if (np->parent 2833 if (np->parent
2834 && device_is_compatible(np->parent, "uni-north") 2834 && of_device_is_compatible(np->parent, "uni-north")
2835 && (device_is_compatible(np, "pci106b,18") || 2835 && (of_device_is_compatible(np, "pci106b,18") ||
2836 device_is_compatible(np, "pci106b,30") || 2836 of_device_is_compatible(np, "pci106b,30") ||
2837 device_is_compatible(np, "pci11c1,5811"))) { 2837 of_device_is_compatible(np, "pci11c1,5811"))) {
2838 macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; 2838 macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
2839 core99_firewire_enable(np, 0, 1); 2839 core99_firewire_enable(np, 0, 1);
2840 } 2840 }
@@ -2845,8 +2845,8 @@ set_initial_features(void)
2845 np = of_find_node_by_name(NULL, "ata-6"); 2845 np = of_find_node_by_name(NULL, "ata-6");
2846 while(np) { 2846 while(np) {
2847 if (np->parent 2847 if (np->parent
2848 && device_is_compatible(np->parent, "uni-north") 2848 && of_device_is_compatible(np->parent, "uni-north")
2849 && device_is_compatible(np, "kauai-ata")) { 2849 && of_device_is_compatible(np, "kauai-ata")) {
2850 core99_ata100_enable(np, 1); 2850 core99_ata100_enable(np, 1);
2851 } 2851 }
2852 np = of_find_node_by_name(np, "ata-6"); 2852 np = of_find_node_by_name(np, "ata-6");
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index 5430e146b3e9..3f507ab9c5e5 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -1207,7 +1207,7 @@ static void pmac_i2c_devscan(void (*callback)(struct device_node *dev,
1207 if (strcmp(np->name, p->name)) 1207 if (strcmp(np->name, p->name))
1208 continue; 1208 continue;
1209 if (p->compatible && 1209 if (p->compatible &&
1210 !device_is_compatible(np, p->compatible)) 1210 !of_device_is_compatible(np, p->compatible))
1211 continue; 1211 continue;
1212 if (p->quirks & pmac_i2c_quirk_skip) 1212 if (p->quirks & pmac_i2c_quirk_skip)
1213 break; 1213 break;
diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c
index 692945c14919..c6f0f9e738e5 100644
--- a/arch/powerpc/platforms/powermac/nvram.c
+++ b/arch/powerpc/platforms/powermac/nvram.c
@@ -553,7 +553,7 @@ static int __init core99_nvram_setup(struct device_node *dp, unsigned long addr)
553 * identify the chip using flash id commands and base ourselves on 553 * identify the chip using flash id commands and base ourselves on
554 * a list of known chips IDs 554 * a list of known chips IDs
555 */ 555 */
556 if (device_is_compatible(dp, "amd-0137")) { 556 if (of_device_is_compatible(dp, "amd-0137")) {
557 core99_erase_bank = amd_erase_bank; 557 core99_erase_bank = amd_erase_bank;
558 core99_write_bank = amd_write_bank; 558 core99_write_bank = amd_write_bank;
559 } else { 559 } else {
@@ -588,7 +588,7 @@ int __init pmac_nvram_init(void)
588 } 588 }
589 } 589 }
590 590
591 is_core_99 = device_is_compatible(dp, "nvram,flash"); 591 is_core_99 = of_device_is_compatible(dp, "nvram,flash");
592 if (is_core_99) { 592 if (is_core_99) {
593 err = core99_nvram_setup(dp, r1.start); 593 err = core99_nvram_setup(dp, r1.start);
594 goto bail; 594 goto bail;
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index 22c4ae4c6934..c4af9e21ac93 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -934,15 +934,15 @@ static int __init add_bridge(struct device_node *dev)
934 934
935 /* 64 bits only bridges */ 935 /* 64 bits only bridges */
936#ifdef CONFIG_PPC64 936#ifdef CONFIG_PPC64
937 if (device_is_compatible(dev, "u3-agp")) { 937 if (of_device_is_compatible(dev, "u3-agp")) {
938 setup_u3_agp(hose); 938 setup_u3_agp(hose);
939 disp_name = "U3-AGP"; 939 disp_name = "U3-AGP";
940 primary = 0; 940 primary = 0;
941 } else if (device_is_compatible(dev, "u3-ht")) { 941 } else if (of_device_is_compatible(dev, "u3-ht")) {
942 setup_u3_ht(hose); 942 setup_u3_ht(hose);
943 disp_name = "U3-HT"; 943 disp_name = "U3-HT";
944 primary = 1; 944 primary = 1;
945 } else if (device_is_compatible(dev, "u4-pcie")) { 945 } else if (of_device_is_compatible(dev, "u4-pcie")) {
946 setup_u4_pcie(hose); 946 setup_u4_pcie(hose);
947 disp_name = "U4-PCIE"; 947 disp_name = "U4-PCIE";
948 primary = 0; 948 primary = 0;
@@ -953,7 +953,7 @@ static int __init add_bridge(struct device_node *dev)
953 953
954 /* 32 bits only bridges */ 954 /* 32 bits only bridges */
955#ifdef CONFIG_PPC32 955#ifdef CONFIG_PPC32
956 if (device_is_compatible(dev, "uni-north")) { 956 if (of_device_is_compatible(dev, "uni-north")) {
957 primary = setup_uninorth(hose, &rsrc); 957 primary = setup_uninorth(hose, &rsrc);
958 disp_name = "UniNorth"; 958 disp_name = "UniNorth";
959 } else if (strcmp(dev->name, "pci") == 0) { 959 } else if (strcmp(dev->name, "pci") == 0) {
@@ -1129,21 +1129,21 @@ pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
1129 return 0; 1129 return 0;
1130 1130
1131 uninorth_child = node->parent && 1131 uninorth_child = node->parent &&
1132 device_is_compatible(node->parent, "uni-north"); 1132 of_device_is_compatible(node->parent, "uni-north");
1133 1133
1134 /* Firewire & GMAC were disabled after PCI probe, the driver is 1134 /* Firewire & GMAC were disabled after PCI probe, the driver is
1135 * claiming them, we must re-enable them now. 1135 * claiming them, we must re-enable them now.
1136 */ 1136 */
1137 if (uninorth_child && !strcmp(node->name, "firewire") && 1137 if (uninorth_child && !strcmp(node->name, "firewire") &&
1138 (device_is_compatible(node, "pci106b,18") || 1138 (of_device_is_compatible(node, "pci106b,18") ||
1139 device_is_compatible(node, "pci106b,30") || 1139 of_device_is_compatible(node, "pci106b,30") ||
1140 device_is_compatible(node, "pci11c1,5811"))) { 1140 of_device_is_compatible(node, "pci11c1,5811"))) {
1141 pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, node, 0, 1); 1141 pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, node, 0, 1);
1142 pmac_call_feature(PMAC_FTR_1394_ENABLE, node, 0, 1); 1142 pmac_call_feature(PMAC_FTR_1394_ENABLE, node, 0, 1);
1143 updatecfg = 1; 1143 updatecfg = 1;
1144 } 1144 }
1145 if (uninorth_child && !strcmp(node->name, "ethernet") && 1145 if (uninorth_child && !strcmp(node->name, "ethernet") &&
1146 device_is_compatible(node, "gmac")) { 1146 of_device_is_compatible(node, "gmac")) {
1147 pmac_call_feature(PMAC_FTR_GMAC_ENABLE, node, 0, 1); 1147 pmac_call_feature(PMAC_FTR_GMAC_ENABLE, node, 0, 1);
1148 updatecfg = 1; 1148 updatecfg = 1;
1149 } 1149 }
@@ -1203,18 +1203,18 @@ void __init pmac_pcibios_after_init(void)
1203#endif /* CONFIG_BLK_DEV_IDE */ 1203#endif /* CONFIG_BLK_DEV_IDE */
1204 1204
1205 for_each_node_by_name(nd, "firewire") { 1205 for_each_node_by_name(nd, "firewire") {
1206 if (nd->parent && (device_is_compatible(nd, "pci106b,18") || 1206 if (nd->parent && (of_device_is_compatible(nd, "pci106b,18") ||
1207 device_is_compatible(nd, "pci106b,30") || 1207 of_device_is_compatible(nd, "pci106b,30") ||
1208 device_is_compatible(nd, "pci11c1,5811")) 1208 of_device_is_compatible(nd, "pci11c1,5811"))
1209 && device_is_compatible(nd->parent, "uni-north")) { 1209 && of_device_is_compatible(nd->parent, "uni-north")) {
1210 pmac_call_feature(PMAC_FTR_1394_ENABLE, nd, 0, 0); 1210 pmac_call_feature(PMAC_FTR_1394_ENABLE, nd, 0, 0);
1211 pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0); 1211 pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0);
1212 } 1212 }
1213 } 1213 }
1214 of_node_put(nd); 1214 of_node_put(nd);
1215 for_each_node_by_name(nd, "ethernet") { 1215 for_each_node_by_name(nd, "ethernet") {
1216 if (nd->parent && device_is_compatible(nd, "gmac") 1216 if (nd->parent && of_device_is_compatible(nd, "gmac")
1217 && device_is_compatible(nd->parent, "uni-north")) 1217 && of_device_is_compatible(nd->parent, "uni-north"))
1218 pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0); 1218 pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0);
1219 } 1219 }
1220 of_node_put(nd); 1220 of_node_put(nd);
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index ae5097ac0378..87cd6805171a 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -364,7 +364,7 @@ static void __init pmac_pic_probe_oldstyle(void)
364 slave = of_find_node_by_name(master, "mac-io"); 364 slave = of_find_node_by_name(master, "mac-io");
365 365
366 /* Check ordering of master & slave */ 366 /* Check ordering of master & slave */
367 if (device_is_compatible(master, "gatwick")) { 367 if (of_device_is_compatible(master, "gatwick")) {
368 struct device_node *tmp; 368 struct device_node *tmp;
369 BUG_ON(slave == NULL); 369 BUG_ON(slave == NULL);
370 tmp = master; 370 tmp = master;
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index b820cabac697..a410bc76a8a8 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -439,76 +439,14 @@ static void __init find_boot_device(void)
439#endif 439#endif
440} 440}
441 441
442/* TODO: Merge the suspend-to-ram with the common code !!!
443 * currently, this is a stub implementation for suspend-to-disk
444 * only
445 */
446
447#ifdef CONFIG_SOFTWARE_SUSPEND
448
449static int pmac_pm_prepare(suspend_state_t state)
450{
451 printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
452
453 return 0;
454}
455
456static int pmac_pm_enter(suspend_state_t state)
457{
458 printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
459
460 /* Giveup the lazy FPU & vec so we don't have to back them
461 * up from the low level code
462 */
463 enable_kernel_fp();
464
465#ifdef CONFIG_ALTIVEC
466 if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
467 enable_kernel_altivec();
468#endif /* CONFIG_ALTIVEC */
469
470 return 0;
471}
472
473static int pmac_pm_finish(suspend_state_t state)
474{
475 printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
476
477 /* Restore userland MMU context */
478 set_context(current->active_mm->context.id, current->active_mm->pgd);
479
480 return 0;
481}
482
483static int pmac_pm_valid(suspend_state_t state)
484{
485 switch (state) {
486 case PM_SUSPEND_DISK:
487 return 1;
488 /* can't do any other states via generic mechanism yet */
489 default:
490 return 0;
491 }
492}
493
494static struct pm_ops pmac_pm_ops = {
495 .pm_disk_mode = PM_DISK_SHUTDOWN,
496 .prepare = pmac_pm_prepare,
497 .enter = pmac_pm_enter,
498 .finish = pmac_pm_finish,
499 .valid = pmac_pm_valid,
500};
501
502#endif /* CONFIG_SOFTWARE_SUSPEND */
503
504static int initializing = 1; 442static int initializing = 1;
505 443
506static int pmac_late_init(void) 444static int pmac_late_init(void)
507{ 445{
508 initializing = 0; 446 initializing = 0;
509#ifdef CONFIG_SOFTWARE_SUSPEND 447 /* this is udbg (which is __init) and we can later use it during
510 pm_set_ops(&pmac_pm_ops); 448 * cpu hotplug (in smp_core99_kick_cpu) */
511#endif /* CONFIG_SOFTWARE_SUSPEND */ 449 ppc_md.progress = NULL;
512 return 0; 450 return 0;
513} 451}
514 452
@@ -721,12 +659,57 @@ static int pmac_pci_probe_mode(struct pci_bus *bus)
721 /* We need to use normal PCI probing for the AGP bus, 659 /* We need to use normal PCI probing for the AGP bus,
722 * since the device for the AGP bridge isn't in the tree. 660 * since the device for the AGP bridge isn't in the tree.
723 */ 661 */
724 if (bus->self == NULL && (device_is_compatible(node, "u3-agp") || 662 if (bus->self == NULL && (of_device_is_compatible(node, "u3-agp") ||
725 device_is_compatible(node, "u4-pcie"))) 663 of_device_is_compatible(node, "u4-pcie")))
726 return PCI_PROBE_NORMAL; 664 return PCI_PROBE_NORMAL;
727 return PCI_PROBE_DEVTREE; 665 return PCI_PROBE_DEVTREE;
728} 666}
729#endif 667
668#ifdef CONFIG_HOTPLUG_CPU
669/* access per cpu vars from generic smp.c */
670DECLARE_PER_CPU(int, cpu_state);
671
672static void pmac_cpu_die(void)
673{
674 /*
675 * turn off as much as possible, we'll be
676 * kicked out as this will only be invoked
677 * on core99 platforms for now ...
678 */
679
680 printk(KERN_INFO "CPU#%d offline\n", smp_processor_id());
681 __get_cpu_var(cpu_state) = CPU_DEAD;
682 smp_wmb();
683
684 /*
685 * during the path that leads here preemption is disabled,
686 * reenable it now so that when coming up preempt count is
687 * zero correctly
688 */
689 preempt_enable();
690
691 /*
692 * hard-disable interrupts for the non-NAP case, the NAP code
693 * needs to re-enable interrupts (but soft-disables them)
694 */
695 hard_irq_disable();
696
697 while (1) {
698 /* let's not take timer interrupts too often ... */
699 set_dec(0x7fffffff);
700
701 /* should always be true at this point */
702 if (cpu_has_feature(CPU_FTR_CAN_NAP))
703 power4_cpu_offline_powersave();
704 else {
705 HMT_low();
706 HMT_very_low();
707 }
708 }
709}
710#endif /* CONFIG_HOTPLUG_CPU */
711
712#endif /* CONFIG_PPC64 */
730 713
731define_machine(powermac) { 714define_machine(powermac) {
732 .name = "PowerMac", 715 .name = "PowerMac",
@@ -763,6 +746,6 @@ define_machine(powermac) {
763 .phys_mem_access_prot = pci_phys_mem_access_prot, 746 .phys_mem_access_prot = pci_phys_mem_access_prot,
764#endif 747#endif
765#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64) 748#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64)
766 .cpu_die = generic_mach_cpu_die, 749 .cpu_die = pmac_cpu_die,
767#endif 750#endif
768}; 751};
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index d2cf6136b32c..686ed82bde79 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -561,7 +561,7 @@ static void __init smp_core99_setup_i2c_hwsync(int ncpus)
561 /* Look for the clock chip */ 561 /* Look for the clock chip */
562 while ((cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL) { 562 while ((cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL) {
563 p = of_get_parent(cc); 563 p = of_get_parent(cc);
564 ok = p && device_is_compatible(p, "uni-n-i2c"); 564 ok = p && of_device_is_compatible(p, "uni-n-i2c");
565 of_node_put(p); 565 of_node_put(p);
566 if (!ok) 566 if (!ok)
567 continue; 567 continue;
@@ -574,11 +574,11 @@ static void __init smp_core99_setup_i2c_hwsync(int ncpus)
574 continue; 574 continue;
575 switch (*reg) { 575 switch (*reg) {
576 case 0xd2: 576 case 0xd2:
577 if (device_is_compatible(cc,"pulsar-legacy-slewing")) { 577 if (of_device_is_compatible(cc,"pulsar-legacy-slewing")) {
578 pmac_tb_freeze = smp_core99_pulsar_tb_freeze; 578 pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
579 pmac_tb_pulsar_addr = 0xd2; 579 pmac_tb_pulsar_addr = 0xd2;
580 name = "Pulsar"; 580 name = "Pulsar";
581 } else if (device_is_compatible(cc, "cy28508")) { 581 } else if (of_device_is_compatible(cc, "cy28508")) {
582 pmac_tb_freeze = smp_core99_cypress_tb_freeze; 582 pmac_tb_freeze = smp_core99_cypress_tb_freeze;
583 name = "Cypress"; 583 name = "Cypress";
584 } 584 }
@@ -899,7 +899,7 @@ void smp_core99_cpu_die(unsigned int cpu)
899 cpu_dead[cpu] = 0; 899 cpu_dead[cpu] = 0;
900} 900}
901 901
902#endif 902#endif /* CONFIG_HOTPLUG_CPU && CONFIG_PP32 */
903 903
904/* Core99 Macs (dual G4s and G5s) */ 904/* Core99 Macs (dual G4s and G5s) */
905struct smp_ops_t core99_smp_ops = { 905struct smp_ops_t core99_smp_ops = {
@@ -909,8 +909,16 @@ struct smp_ops_t core99_smp_ops = {
909 .setup_cpu = smp_core99_setup_cpu, 909 .setup_cpu = smp_core99_setup_cpu,
910 .give_timebase = smp_core99_give_timebase, 910 .give_timebase = smp_core99_give_timebase,
911 .take_timebase = smp_core99_take_timebase, 911 .take_timebase = smp_core99_take_timebase,
912#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32) 912#if defined(CONFIG_HOTPLUG_CPU)
913# if defined(CONFIG_PPC32)
913 .cpu_disable = smp_core99_cpu_disable, 914 .cpu_disable = smp_core99_cpu_disable,
914 .cpu_die = smp_core99_cpu_die, 915 .cpu_die = smp_core99_cpu_die,
916# endif
917# if defined(CONFIG_PPC64)
918 .cpu_disable = generic_cpu_disable,
919 .cpu_die = generic_cpu_die,
920 /* intentionally do *NOT* assign cpu_enable,
921 * the generic code will use kick_cpu then! */
922# endif
915#endif 923#endif
916}; 924};
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
index ea60c451cf87..a1409e450c70 100644
--- a/arch/powerpc/platforms/ps3/htab.c
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -273,7 +273,8 @@ void __init ps3_map_htab(void)
273 273
274 result = lv1_map_htab(0, &htab_addr); 274 result = lv1_map_htab(0, &htab_addr);
275 275
276 htab = (hpte_t *)__ioremap(htab_addr, htab_size, PAGE_READONLY_X); 276 htab = (hpte_t *)__ioremap(htab_addr, htab_size,
277 pgprot_val(PAGE_READONLY_X));
277 278
278 DBG("%s:%d: lpar %016lxh, virt %016lxh\n", __func__, __LINE__, 279 DBG("%s:%d: lpar %016lxh, virt %016lxh\n", __func__, __LINE__,
279 htab_addr, (unsigned long)htab); 280 htab_addr, (unsigned long)htab);
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
index 631c30095617..9da82c266ba9 100644
--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -89,7 +89,18 @@ struct ps3_private {
89 89
90static DEFINE_PER_CPU(struct ps3_private, ps3_private); 90static DEFINE_PER_CPU(struct ps3_private, ps3_private);
91 91
92int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet, 92/**
93 * ps3_virq_setup - virq related setup.
94 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
95 * serviced on.
96 * @outlet: The HV outlet from the various create outlet routines.
97 * @virq: The assigned Linux virq.
98 *
99 * Calls irq_create_mapping() to get a virq and sets the chip data to
100 * ps3_private data.
101 */
102
103int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
93 unsigned int *virq) 104 unsigned int *virq)
94{ 105{
95 int result; 106 int result;
@@ -111,17 +122,6 @@ int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet,
111 goto fail_create; 122 goto fail_create;
112 } 123 }
113 124
114 /* Binds outlet to cpu + virq. */
115
116 result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0);
117
118 if (result) {
119 pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n",
120 __func__, __LINE__, ps3_result(result));
121 result = -EPERM;
122 goto fail_connect;
123 }
124
125 pr_debug("%s:%d: outlet %lu => cpu %u, virq %u\n", __func__, __LINE__, 125 pr_debug("%s:%d: outlet %lu => cpu %u, virq %u\n", __func__, __LINE__,
126 outlet, cpu, *virq); 126 outlet, cpu, *virq);
127 127
@@ -136,94 +136,118 @@ int ps3_alloc_irq(enum ps3_cpu_binding cpu, unsigned long outlet,
136 return result; 136 return result;
137 137
138fail_set: 138fail_set:
139 lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, *virq);
140fail_connect:
141 irq_dispose_mapping(*virq); 139 irq_dispose_mapping(*virq);
142fail_create: 140fail_create:
143 return result; 141 return result;
144} 142}
145EXPORT_SYMBOL_GPL(ps3_alloc_irq);
146 143
147int ps3_free_irq(unsigned int virq) 144/**
145 * ps3_virq_destroy - virq related teardown.
146 * @virq: The assigned Linux virq.
147 *
148 * Clears chip data and calls irq_dispose_mapping() for the virq.
149 */
150
151int ps3_virq_destroy(unsigned int virq)
148{ 152{
149 int result;
150 const struct ps3_private *pd = get_irq_chip_data(virq); 153 const struct ps3_private *pd = get_irq_chip_data(virq);
151 154
152 pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__, 155 pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__,
153 pd->node, pd->cpu, virq); 156 pd->node, pd->cpu, virq);
154 157
155 result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq);
156
157 if (result)
158 pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n",
159 __func__, __LINE__, ps3_result(result));
160
161 set_irq_chip_data(virq, NULL); 158 set_irq_chip_data(virq, NULL);
162 irq_dispose_mapping(virq); 159 irq_dispose_mapping(virq);
163 return result; 160
161 pr_debug("%s:%d <-\n", __func__, __LINE__);
162 return 0;
164} 163}
165EXPORT_SYMBOL_GPL(ps3_free_irq);
166 164
167/** 165/**
168 * ps3_alloc_io_irq - Assign a virq to a system bus device. 166 * ps3_irq_plug_setup - Generic outlet and virq related setup.
169 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be 167 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
170 * serviced on. 168 * serviced on.
171 * @interrupt_id: The device interrupt id read from the system repository. 169 * @outlet: The HV outlet from the various create outlet routines.
172 * @virq: The assigned Linux virq. 170 * @virq: The assigned Linux virq.
173 * 171 *
174 * An io irq represents a non-virtualized device interrupt. interrupt_id 172 * Sets up virq and connects the irq plug.
175 * coresponds to the interrupt number of the interrupt controller.
176 */ 173 */
177 174
178int ps3_alloc_io_irq(enum ps3_cpu_binding cpu, unsigned int interrupt_id, 175int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
179 unsigned int *virq) 176 unsigned int *virq)
180{ 177{
181 int result; 178 int result;
182 unsigned long outlet; 179 struct ps3_private *pd;
183 180
184 result = lv1_construct_io_irq_outlet(interrupt_id, &outlet); 181 result = ps3_virq_setup(cpu, outlet, virq);
185 182
186 if (result) { 183 if (result) {
187 pr_debug("%s:%d: lv1_construct_io_irq_outlet failed: %s\n", 184 pr_debug("%s:%d: ps3_virq_setup failed\n", __func__, __LINE__);
188 __func__, __LINE__, ps3_result(result)); 185 goto fail_setup;
189 return result;
190 } 186 }
191 187
192 result = ps3_alloc_irq(cpu, outlet, virq); 188 pd = get_irq_chip_data(*virq);
193 BUG_ON(result); 189
190 /* Binds outlet to cpu + virq. */
191
192 result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0);
194 193
194 if (result) {
195 pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n",
196 __func__, __LINE__, ps3_result(result));
197 result = -EPERM;
198 goto fail_connect;
199 }
200
201 return result;
202
203fail_connect:
204 ps3_virq_destroy(*virq);
205fail_setup:
195 return result; 206 return result;
196} 207}
197EXPORT_SYMBOL_GPL(ps3_alloc_io_irq); 208EXPORT_SYMBOL_GPL(ps3_irq_plug_setup);
209
210/**
211 * ps3_irq_plug_destroy - Generic outlet and virq related teardown.
212 * @virq: The assigned Linux virq.
213 *
214 * Disconnects the irq plug and tears down virq.
215 * Do not call for system bus event interrupts setup with
216 * ps3_sb_event_receive_port_setup().
217 */
198 218
199int ps3_free_io_irq(unsigned int virq) 219int ps3_irq_plug_destroy(unsigned int virq)
200{ 220{
201 int result; 221 int result;
222 const struct ps3_private *pd = get_irq_chip_data(virq);
202 223
203 result = lv1_destruct_io_irq_outlet(virq_to_hw(virq)); 224 pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__,
225 pd->node, pd->cpu, virq);
226
227 result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq);
204 228
205 if (result) 229 if (result)
206 pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n", 230 pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n",
207 __func__, __LINE__, ps3_result(result)); 231 __func__, __LINE__, ps3_result(result));
208 232
209 ps3_free_irq(virq); 233 ps3_virq_destroy(virq);
210 234
211 return result; 235 return result;
212} 236}
213EXPORT_SYMBOL_GPL(ps3_free_io_irq); 237EXPORT_SYMBOL_GPL(ps3_irq_plug_destroy);
214 238
215/** 239/**
216 * ps3_alloc_event_irq - Allocate a virq for use with a system event. 240 * ps3_event_receive_port_setup - Setup an event receive port.
217 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be 241 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
218 * serviced on. 242 * serviced on.
219 * @virq: The assigned Linux virq. 243 * @virq: The assigned Linux virq.
220 * 244 *
221 * The virq can be used with lv1_connect_interrupt_event_receive_port() to 245 * The virq can be used with lv1_connect_interrupt_event_receive_port() to
222 * arrange to receive events, or with ps3_send_event_locally() to signal 246 * arrange to receive interrupts from system-bus devices, or with
223 * events. 247 * ps3_send_event_locally() to signal events.
224 */ 248 */
225 249
226int ps3_alloc_event_irq(enum ps3_cpu_binding cpu, unsigned int *virq) 250int ps3_event_receive_port_setup(enum ps3_cpu_binding cpu, unsigned int *virq)
227{ 251{
228 int result; 252 int result;
229 unsigned long outlet; 253 unsigned long outlet;
@@ -237,17 +261,27 @@ int ps3_alloc_event_irq(enum ps3_cpu_binding cpu, unsigned int *virq)
237 return result; 261 return result;
238 } 262 }
239 263
240 result = ps3_alloc_irq(cpu, outlet, virq); 264 result = ps3_irq_plug_setup(cpu, outlet, virq);
241 BUG_ON(result); 265 BUG_ON(result);
242 266
243 return result; 267 return result;
244} 268}
269EXPORT_SYMBOL_GPL(ps3_event_receive_port_setup);
270
271/**
272 * ps3_event_receive_port_destroy - Destroy an event receive port.
273 * @virq: The assigned Linux virq.
274 *
275 * Since ps3_event_receive_port_destroy destroys the receive port outlet,
276 * SB devices need to call disconnect_interrupt_event_receive_port() before
277 * this.
278 */
245 279
246int ps3_free_event_irq(unsigned int virq) 280int ps3_event_receive_port_destroy(unsigned int virq)
247{ 281{
248 int result; 282 int result;
249 283
250 pr_debug(" -> %s:%d\n", __func__, __LINE__); 284 pr_debug(" -> %s:%d virq: %u\n", __func__, __LINE__, virq);
251 285
252 result = lv1_destruct_event_receive_port(virq_to_hw(virq)); 286 result = lv1_destruct_event_receive_port(virq_to_hw(virq));
253 287
@@ -255,11 +289,17 @@ int ps3_free_event_irq(unsigned int virq)
255 pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n", 289 pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n",
256 __func__, __LINE__, ps3_result(result)); 290 __func__, __LINE__, ps3_result(result));
257 291
258 ps3_free_irq(virq); 292 /* lv1_destruct_event_receive_port() destroys the IRQ plug,
293 * so don't call ps3_irq_plug_destroy() here.
294 */
295
296 result = ps3_virq_destroy(virq);
297 BUG_ON(result);
259 298
260 pr_debug(" <- %s:%d\n", __func__, __LINE__); 299 pr_debug(" <- %s:%d\n", __func__, __LINE__);
261 return result; 300 return result;
262} 301}
302EXPORT_SYMBOL_GPL(ps3_event_receive_port_destroy);
263 303
264int ps3_send_event_locally(unsigned int virq) 304int ps3_send_event_locally(unsigned int virq)
265{ 305{
@@ -267,7 +307,7 @@ int ps3_send_event_locally(unsigned int virq)
267} 307}
268 308
269/** 309/**
270 * ps3_connect_event_irq - Assign a virq to a system bus device. 310 * ps3_sb_event_receive_port_setup - Setup a system bus event receive port.
271 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be 311 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
272 * serviced on. 312 * serviced on.
273 * @did: The HV device identifier read from the system repository. 313 * @did: The HV device identifier read from the system repository.
@@ -278,13 +318,15 @@ int ps3_send_event_locally(unsigned int virq)
278 * coresponds to the software interrupt number. 318 * coresponds to the software interrupt number.
279 */ 319 */
280 320
281int ps3_connect_event_irq(enum ps3_cpu_binding cpu, 321int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu,
282 const struct ps3_device_id *did, unsigned int interrupt_id, 322 const struct ps3_device_id *did, unsigned int interrupt_id,
283 unsigned int *virq) 323 unsigned int *virq)
284{ 324{
325 /* this should go in system-bus.c */
326
285 int result; 327 int result;
286 328
287 result = ps3_alloc_event_irq(cpu, virq); 329 result = ps3_event_receive_port_setup(cpu, virq);
288 330
289 if (result) 331 if (result)
290 return result; 332 return result;
@@ -296,7 +338,7 @@ int ps3_connect_event_irq(enum ps3_cpu_binding cpu,
296 pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port" 338 pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port"
297 " failed: %s\n", __func__, __LINE__, 339 " failed: %s\n", __func__, __LINE__,
298 ps3_result(result)); 340 ps3_result(result));
299 ps3_free_event_irq(*virq); 341 ps3_event_receive_port_destroy(*virq);
300 *virq = NO_IRQ; 342 *virq = NO_IRQ;
301 return result; 343 return result;
302 } 344 }
@@ -306,10 +348,13 @@ int ps3_connect_event_irq(enum ps3_cpu_binding cpu,
306 348
307 return 0; 349 return 0;
308} 350}
351EXPORT_SYMBOL(ps3_sb_event_receive_port_setup);
309 352
310int ps3_disconnect_event_irq(const struct ps3_device_id *did, 353int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did,
311 unsigned int interrupt_id, unsigned int virq) 354 unsigned int interrupt_id, unsigned int virq)
312{ 355{
356 /* this should go in system-bus.c */
357
313 int result; 358 int result;
314 359
315 pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, 360 pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
@@ -323,14 +368,65 @@ int ps3_disconnect_event_irq(const struct ps3_device_id *did,
323 " failed: %s\n", __func__, __LINE__, 368 " failed: %s\n", __func__, __LINE__,
324 ps3_result(result)); 369 ps3_result(result));
325 370
326 ps3_free_event_irq(virq); 371 result = ps3_event_receive_port_destroy(virq);
372 BUG_ON(result);
327 373
328 pr_debug(" <- %s:%d\n", __func__, __LINE__); 374 pr_debug(" <- %s:%d\n", __func__, __LINE__);
329 return result; 375 return result;
330} 376}
377EXPORT_SYMBOL(ps3_sb_event_receive_port_destroy);
331 378
332/** 379/**
333 * ps3_alloc_vuart_irq - Configure the system virtual uart virq. 380 * ps3_io_irq_setup - Setup a system bus io irq.
381 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
382 * serviced on.
383 * @interrupt_id: The device interrupt id read from the system repository.
384 * @virq: The assigned Linux virq.
385 *
386 * An io irq represents a non-virtualized device interrupt. interrupt_id
387 * coresponds to the interrupt number of the interrupt controller.
388 */
389
390int ps3_io_irq_setup(enum ps3_cpu_binding cpu, unsigned int interrupt_id,
391 unsigned int *virq)
392{
393 int result;
394 unsigned long outlet;
395
396 result = lv1_construct_io_irq_outlet(interrupt_id, &outlet);
397
398 if (result) {
399 pr_debug("%s:%d: lv1_construct_io_irq_outlet failed: %s\n",
400 __func__, __LINE__, ps3_result(result));
401 return result;
402 }
403
404 result = ps3_irq_plug_setup(cpu, outlet, virq);
405 BUG_ON(result);
406
407 return result;
408}
409EXPORT_SYMBOL_GPL(ps3_io_irq_setup);
410
411int ps3_io_irq_destroy(unsigned int virq)
412{
413 int result;
414
415 result = lv1_destruct_io_irq_outlet(virq_to_hw(virq));
416
417 if (result)
418 pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
419 __func__, __LINE__, ps3_result(result));
420
421 result = ps3_irq_plug_destroy(virq);
422 BUG_ON(result);
423
424 return result;
425}
426EXPORT_SYMBOL_GPL(ps3_io_irq_destroy);
427
428/**
429 * ps3_vuart_irq_setup - Setup the system virtual uart virq.
334 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be 430 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
335 * serviced on. 431 * serviced on.
336 * @virt_addr_bmp: The caller supplied virtual uart interrupt bitmap. 432 * @virt_addr_bmp: The caller supplied virtual uart interrupt bitmap.
@@ -340,7 +436,7 @@ int ps3_disconnect_event_irq(const struct ps3_device_id *did,
340 * freeing the interrupt will return a wrong state error. 436 * freeing the interrupt will return a wrong state error.
341 */ 437 */
342 438
343int ps3_alloc_vuart_irq(enum ps3_cpu_binding cpu, void* virt_addr_bmp, 439int ps3_vuart_irq_setup(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
344 unsigned int *virq) 440 unsigned int *virq)
345{ 441{
346 int result; 442 int result;
@@ -359,13 +455,13 @@ int ps3_alloc_vuart_irq(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
359 return result; 455 return result;
360 } 456 }
361 457
362 result = ps3_alloc_irq(cpu, outlet, virq); 458 result = ps3_irq_plug_setup(cpu, outlet, virq);
363 BUG_ON(result); 459 BUG_ON(result);
364 460
365 return result; 461 return result;
366} 462}
367 463
368int ps3_free_vuart_irq(unsigned int virq) 464int ps3_vuart_irq_destroy(unsigned int virq)
369{ 465{
370 int result; 466 int result;
371 467
@@ -377,13 +473,14 @@ int ps3_free_vuart_irq(unsigned int virq)
377 return result; 473 return result;
378 } 474 }
379 475
380 ps3_free_irq(virq); 476 result = ps3_irq_plug_destroy(virq);
477 BUG_ON(result);
381 478
382 return result; 479 return result;
383} 480}
384 481
385/** 482/**
386 * ps3_alloc_spe_irq - Configure an spe virq. 483 * ps3_spe_irq_setup - Setup an spe virq.
387 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be 484 * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
388 * serviced on. 485 * serviced on.
389 * @spe_id: The spe_id returned from lv1_construct_logical_spe(). 486 * @spe_id: The spe_id returned from lv1_construct_logical_spe().
@@ -392,7 +489,7 @@ int ps3_free_vuart_irq(unsigned int virq)
392 * 489 *
393 */ 490 */
394 491
395int ps3_alloc_spe_irq(enum ps3_cpu_binding cpu, unsigned long spe_id, 492int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id,
396 unsigned int class, unsigned int *virq) 493 unsigned int class, unsigned int *virq)
397{ 494{
398 int result; 495 int result;
@@ -408,15 +505,16 @@ int ps3_alloc_spe_irq(enum ps3_cpu_binding cpu, unsigned long spe_id,
408 return result; 505 return result;
409 } 506 }
410 507
411 result = ps3_alloc_irq(cpu, outlet, virq); 508 result = ps3_irq_plug_setup(cpu, outlet, virq);
412 BUG_ON(result); 509 BUG_ON(result);
413 510
414 return result; 511 return result;
415} 512}
416 513
417int ps3_free_spe_irq(unsigned int virq) 514int ps3_spe_irq_destroy(unsigned int virq)
418{ 515{
419 ps3_free_irq(virq); 516 int result = ps3_irq_plug_destroy(virq);
517 BUG_ON(result);
420 return 0; 518 return 0;
421} 519}
422 520
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c
index 2014d2b44449..f8a3e206c584 100644
--- a/arch/powerpc/platforms/ps3/mm.c
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -826,5 +826,4 @@ void __init ps3_mm_init(void)
826void ps3_mm_shutdown(void) 826void ps3_mm_shutdown(void)
827{ 827{
828 ps3_mm_region_destroy(&map.r1); 828 ps3_mm_region_destroy(&map.r1);
829 map.total = map.rm.size;
830} 829}
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index ac5df9688dcb..c9894933084f 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -137,6 +137,12 @@ early_param("ps3fb", early_parse_ps3fb);
137#define prealloc_ps3fb_videomemory() do { } while (0) 137#define prealloc_ps3fb_videomemory() do { } while (0)
138#endif 138#endif
139 139
140static int ps3_set_dabr(u64 dabr)
141{
142 enum {DABR_USER = 1, DABR_KERNEL = 2,};
143
144 return lv1_set_dabr(dabr, DABR_KERNEL | DABR_USER) ? -1 : 0;
145}
140 146
141static void __init ps3_setup_arch(void) 147static void __init ps3_setup_arch(void)
142{ 148{
@@ -234,6 +240,7 @@ define_machine(ps3) {
234 .get_boot_time = ps3_get_boot_time, 240 .get_boot_time = ps3_get_boot_time,
235 .set_rtc_time = ps3_set_rtc_time, 241 .set_rtc_time = ps3_set_rtc_time,
236 .get_rtc_time = ps3_get_rtc_time, 242 .get_rtc_time = ps3_get_rtc_time,
243 .set_dabr = ps3_set_dabr,
237 .calibrate_decr = ps3_calibrate_decr, 244 .calibrate_decr = ps3_calibrate_decr,
238 .progress = ps3_progress, 245 .progress = ps3_progress,
239 .restart = ps3_restart, 246 .restart = ps3_restart,
diff --git a/arch/powerpc/platforms/ps3/smp.c b/arch/powerpc/platforms/ps3/smp.c
index 6fb887961a6d..8729348c0608 100644
--- a/arch/powerpc/platforms/ps3/smp.c
+++ b/arch/powerpc/platforms/ps3/smp.c
@@ -110,7 +110,7 @@ static void __init ps3_smp_setup_cpu(int cpu)
110 BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3); 110 BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3);
111 111
112 for (i = 0; i < MSG_COUNT; i++) { 112 for (i = 0; i < MSG_COUNT; i++) {
113 result = ps3_alloc_event_irq(cpu, &virqs[i]); 113 result = ps3_event_receive_port_setup(cpu, &virqs[i]);
114 114
115 if (result) 115 if (result)
116 continue; 116 continue;
@@ -134,11 +134,13 @@ void ps3_smp_cleanup_cpu(int cpu)
134 int i; 134 int i;
135 135
136 DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); 136 DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
137
137 for (i = 0; i < MSG_COUNT; i++) { 138 for (i = 0; i < MSG_COUNT; i++) {
138 ps3_free_event_irq(virqs[i]);
139 free_irq(virqs[i], (void*)(long)i); 139 free_irq(virqs[i], (void*)(long)i);
140 ps3_event_receive_port_destroy(virqs[i]);
140 virqs[i] = NO_IRQ; 141 virqs[i] = NO_IRQ;
141 } 142 }
143
142 DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu); 144 DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu);
143} 145}
144 146
diff --git a/arch/powerpc/platforms/ps3/spu.c b/arch/powerpc/platforms/ps3/spu.c
index a397e4e17c13..651437cb2c18 100644
--- a/arch/powerpc/platforms/ps3/spu.c
+++ b/arch/powerpc/platforms/ps3/spu.c
@@ -184,7 +184,7 @@ static int __init setup_areas(struct spu *spu)
184 184
185 spu_pdata(spu)->shadow = __ioremap( 185 spu_pdata(spu)->shadow = __ioremap(
186 spu_pdata(spu)->shadow_addr, sizeof(struct spe_shadow), 186 spu_pdata(spu)->shadow_addr, sizeof(struct spe_shadow),
187 PAGE_READONLY | _PAGE_NO_CACHE | _PAGE_GUARDED); 187 pgprot_val(PAGE_READONLY) | _PAGE_NO_CACHE | _PAGE_GUARDED);
188 if (!spu_pdata(spu)->shadow) { 188 if (!spu_pdata(spu)->shadow) {
189 pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__); 189 pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__);
190 goto fail_ioremap; 190 goto fail_ioremap;
@@ -230,19 +230,19 @@ static int __init setup_interrupts(struct spu *spu)
230{ 230{
231 int result; 231 int result;
232 232
233 result = ps3_alloc_spe_irq(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, 233 result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
234 0, &spu->irqs[0]); 234 0, &spu->irqs[0]);
235 235
236 if (result) 236 if (result)
237 goto fail_alloc_0; 237 goto fail_alloc_0;
238 238
239 result = ps3_alloc_spe_irq(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, 239 result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
240 1, &spu->irqs[1]); 240 1, &spu->irqs[1]);
241 241
242 if (result) 242 if (result)
243 goto fail_alloc_1; 243 goto fail_alloc_1;
244 244
245 result = ps3_alloc_spe_irq(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id, 245 result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
246 2, &spu->irqs[2]); 246 2, &spu->irqs[2]);
247 247
248 if (result) 248 if (result)
@@ -251,9 +251,9 @@ static int __init setup_interrupts(struct spu *spu)
251 return result; 251 return result;
252 252
253fail_alloc_2: 253fail_alloc_2:
254 ps3_free_spe_irq(spu->irqs[1]); 254 ps3_spe_irq_destroy(spu->irqs[1]);
255fail_alloc_1: 255fail_alloc_1:
256 ps3_free_spe_irq(spu->irqs[0]); 256 ps3_spe_irq_destroy(spu->irqs[0]);
257fail_alloc_0: 257fail_alloc_0:
258 spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ; 258 spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ;
259 return result; 259 return result;
@@ -301,9 +301,9 @@ static int ps3_destroy_spu(struct spu *spu)
301 result = lv1_disable_logical_spe(spu_pdata(spu)->spe_id, 0); 301 result = lv1_disable_logical_spe(spu_pdata(spu)->spe_id, 0);
302 BUG_ON(result); 302 BUG_ON(result);
303 303
304 ps3_free_spe_irq(spu->irqs[2]); 304 ps3_spe_irq_destroy(spu->irqs[2]);
305 ps3_free_spe_irq(spu->irqs[1]); 305 ps3_spe_irq_destroy(spu->irqs[1]);
306 ps3_free_spe_irq(spu->irqs[0]); 306 ps3_spe_irq_destroy(spu->irqs[0]);
307 307
308 spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ; 308 spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ;
309 309
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 90235d598751..ae1fc92dc1c9 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_SCANLOG) += scanlog.o
11obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o 11obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o
12obj-$(CONFIG_KEXEC) += kexec.o 12obj-$(CONFIG_KEXEC) += kexec.o
13obj-$(CONFIG_PCI) += pci.o pci_dlpar.o 13obj-$(CONFIG_PCI) += pci.o pci_dlpar.o
14obj-$(CONFIG_PCI_MSI) += msi.o
14 15
15obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o 16obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o
16 17
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 48fbd442e9df..63e23062e982 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -580,6 +580,36 @@ rtas_pci_slot_reset(struct pci_dn *pdn, int state)
580} 580}
581 581
582/** 582/**
583 * pcibios_set_pcie_slot_reset - Set PCI-E reset state
584 * @dev: pci device struct
585 * @state: reset state to enter
586 *
587 * Return value:
588 * 0 if success
589 **/
590int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state)
591{
592 struct device_node *dn = pci_device_to_OF_node(dev);
593 struct pci_dn *pdn = PCI_DN(dn);
594
595 switch (state) {
596 case pcie_deassert_reset:
597 rtas_pci_slot_reset(pdn, 0);
598 break;
599 case pcie_hot_reset:
600 rtas_pci_slot_reset(pdn, 1);
601 break;
602 case pcie_warm_reset:
603 rtas_pci_slot_reset(pdn, 3);
604 break;
605 default:
606 return -EINVAL;
607 };
608
609 return 0;
610}
611
612/**
583 * rtas_set_slot_reset -- assert the pci #RST line for 1/4 second 613 * rtas_set_slot_reset -- assert the pci #RST line for 1/4 second
584 * @pdn: pci device node to be reset. 614 * @pdn: pci device node to be reset.
585 * 615 *
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 66665c82415c..eec684a8e44e 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -504,6 +504,12 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
504 break; 504 break;
505 } 505 }
506 506
507 if (!pdn || !PCI_DN(pdn)) {
508 printk(KERN_WARNING "pci_dma_dev_setup_pSeriesLP: "
509 "no DMA window found for pci dev=%s dn=%s\n",
510 pci_name(dev), dn? dn->full_name : "<null>");
511 return;
512 }
507 DBG(" parent is %s\n", pdn->full_name); 513 DBG(" parent is %s\n", pdn->full_name);
508 514
509 /* Check for parent == NULL so we don't try to setup the empty EADS 515 /* Check for parent == NULL so we don't try to setup the empty EADS
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 3a70e8ad7bc8..362dfbc260a6 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -231,13 +231,13 @@ void __init find_udbg_vterm(void)
231 goto out; 231 goto out;
232 vtermno = termno[0]; 232 vtermno = termno[0];
233 233
234 if (device_is_compatible(stdout_node, "hvterm1")) { 234 if (of_device_is_compatible(stdout_node, "hvterm1")) {
235 udbg_putc = udbg_putcLP; 235 udbg_putc = udbg_putcLP;
236 udbg_getc = udbg_getcLP; 236 udbg_getc = udbg_getcLP;
237 udbg_getc_poll = udbg_getc_pollLP; 237 udbg_getc_poll = udbg_getc_pollLP;
238 if (add_console) 238 if (add_console)
239 add_preferred_console("hvc", termno[0] & 0xff, NULL); 239 add_preferred_console("hvc", termno[0] & 0xff, NULL);
240 } else if (device_is_compatible(stdout_node, "hvterm-protocol")) { 240 } else if (of_device_is_compatible(stdout_node, "hvterm-protocol")) {
241 vtermno = termno[0]; 241 vtermno = termno[0];
242 udbg_putc = udbg_hvsi_putc; 242 udbg_putc = udbg_hvsi_putc;
243 udbg_getc = udbg_hvsi_getc; 243 udbg_getc = udbg_hvsi_getc;
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
new file mode 100644
index 000000000000..6063ea2f67ad
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -0,0 +1,270 @@
1/*
2 * Copyright 2006 Jake Moilanen <moilanen@austin.ibm.com>, IBM Corp.
3 * Copyright 2006-2007 Michael Ellerman, IBM Corp.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; version 2 of the
8 * License.
9 *
10 */
11
12#include <linux/device.h>
13#include <linux/irq.h>
14#include <linux/msi.h>
15
16#include <asm/rtas.h>
17#include <asm/hw_irq.h>
18#include <asm/ppc-pci.h>
19
20static int query_token, change_token;
21
22#define RTAS_QUERY_FN 0
23#define RTAS_CHANGE_FN 1
24#define RTAS_RESET_FN 2
25#define RTAS_CHANGE_MSI_FN 3
26#define RTAS_CHANGE_MSIX_FN 4
27
28static struct pci_dn *get_pdn(struct pci_dev *pdev)
29{
30 struct device_node *dn;
31 struct pci_dn *pdn;
32
33 dn = pci_device_to_OF_node(pdev);
34 if (!dn) {
35 dev_dbg(&pdev->dev, "rtas_msi: No OF device node\n");
36 return NULL;
37 }
38
39 pdn = PCI_DN(dn);
40 if (!pdn) {
41 dev_dbg(&pdev->dev, "rtas_msi: No PCI DN\n");
42 return NULL;
43 }
44
45 return pdn;
46}
47
48/* RTAS Helpers */
49
50static int rtas_change_msi(struct pci_dn *pdn, u32 func, u32 num_irqs)
51{
52 u32 addr, seq_num, rtas_ret[3];
53 unsigned long buid;
54 int rc;
55
56 addr = rtas_config_addr(pdn->busno, pdn->devfn, 0);
57 buid = pdn->phb->buid;
58
59 seq_num = 1;
60 do {
61 if (func == RTAS_CHANGE_MSI_FN || func == RTAS_CHANGE_MSIX_FN)
62 rc = rtas_call(change_token, 6, 4, rtas_ret, addr,
63 BUID_HI(buid), BUID_LO(buid),
64 func, num_irqs, seq_num);
65 else
66 rc = rtas_call(change_token, 6, 3, rtas_ret, addr,
67 BUID_HI(buid), BUID_LO(buid),
68 func, num_irqs, seq_num);
69
70 seq_num = rtas_ret[1];
71 } while (rtas_busy_delay(rc));
72
73 if (rc == 0) /* Success */
74 rc = rtas_ret[0];
75
76 pr_debug("rtas_msi: ibm,change_msi(func=%d,num=%d) = (%d)\n",
77 func, num_irqs, rc);
78
79 return rc;
80}
81
82static void rtas_disable_msi(struct pci_dev *pdev)
83{
84 struct pci_dn *pdn;
85
86 pdn = get_pdn(pdev);
87 if (!pdn)
88 return;
89
90 if (rtas_change_msi(pdn, RTAS_CHANGE_FN, 0) != 0)
91 pr_debug("rtas_msi: Setting MSIs to 0 failed!\n");
92}
93
94static int rtas_query_irq_number(struct pci_dn *pdn, int offset)
95{
96 u32 addr, rtas_ret[2];
97 unsigned long buid;
98 int rc;
99
100 addr = rtas_config_addr(pdn->busno, pdn->devfn, 0);
101 buid = pdn->phb->buid;
102
103 do {
104 rc = rtas_call(query_token, 4, 3, rtas_ret, addr,
105 BUID_HI(buid), BUID_LO(buid), offset);
106 } while (rtas_busy_delay(rc));
107
108 if (rc) {
109 pr_debug("rtas_msi: error (%d) querying source number\n", rc);
110 return rc;
111 }
112
113 return rtas_ret[0];
114}
115
116static void rtas_teardown_msi_irqs(struct pci_dev *pdev)
117{
118 struct msi_desc *entry;
119
120 list_for_each_entry(entry, &pdev->msi_list, list) {
121 if (entry->irq == NO_IRQ)
122 continue;
123
124 set_irq_msi(entry->irq, NULL);
125 irq_dispose_mapping(entry->irq);
126 }
127
128 rtas_disable_msi(pdev);
129}
130
131static int check_req_msi(struct pci_dev *pdev, int nvec)
132{
133 struct device_node *dn;
134 struct pci_dn *pdn;
135 const u32 *req_msi;
136
137 pdn = get_pdn(pdev);
138 if (!pdn)
139 return -ENODEV;
140
141 dn = pdn->node;
142
143 req_msi = of_get_property(dn, "ibm,req#msi", NULL);
144 if (!req_msi) {
145 pr_debug("rtas_msi: No ibm,req#msi on %s\n", dn->full_name);
146 return -ENOENT;
147 }
148
149 if (*req_msi < nvec) {
150 pr_debug("rtas_msi: ibm,req#msi requests < %d MSIs\n", nvec);
151 return -ENOSPC;
152 }
153
154 return 0;
155}
156
157static int rtas_msi_check_device(struct pci_dev *pdev, int nvec, int type)
158{
159 if (type == PCI_CAP_ID_MSIX)
160 pr_debug("rtas_msi: MSI-X untested, trying anyway.\n");
161
162 return check_req_msi(pdev, nvec);
163}
164
165static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
166{
167 struct pci_dn *pdn;
168 int hwirq, virq, i, rc;
169 struct msi_desc *entry;
170
171 pdn = get_pdn(pdev);
172 if (!pdn)
173 return -ENODEV;
174
175 /*
176 * Try the new more explicit firmware interface, if that fails fall
177 * back to the old interface. The old interface is known to never
178 * return MSI-Xs.
179 */
180 if (type == PCI_CAP_ID_MSI) {
181 rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec);
182
183 if (rc != nvec) {
184 pr_debug("rtas_msi: trying the old firmware call.\n");
185 rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec);
186 }
187 } else
188 rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec);
189
190 if (rc != nvec) {
191 pr_debug("rtas_msi: rtas_change_msi() failed\n");
192
193 /*
194 * In case of an error it's not clear whether the device is
195 * left with MSI enabled or not, so we explicitly disable.
196 */
197 goto out_free;
198 }
199
200 i = 0;
201 list_for_each_entry(entry, &pdev->msi_list, list) {
202 hwirq = rtas_query_irq_number(pdn, i);
203 if (hwirq < 0) {
204 rc = hwirq;
205 pr_debug("rtas_msi: error (%d) getting hwirq\n", rc);
206 goto out_free;
207 }
208
209 virq = irq_create_mapping(NULL, hwirq);
210
211 if (virq == NO_IRQ) {
212 pr_debug("rtas_msi: Failed mapping hwirq %d\n", hwirq);
213 rc = -ENOSPC;
214 goto out_free;
215 }
216
217 dev_dbg(&pdev->dev, "rtas_msi: allocated virq %d\n", virq);
218 set_irq_msi(virq, entry);
219 unmask_msi_irq(virq);
220 }
221
222 return 0;
223
224 out_free:
225 rtas_teardown_msi_irqs(pdev);
226 return rc;
227}
228
229static void rtas_msi_pci_irq_fixup(struct pci_dev *pdev)
230{
231 /* No LSI -> leave MSIs (if any) configured */
232 if (pdev->irq == NO_IRQ) {
233 dev_dbg(&pdev->dev, "rtas_msi: no LSI, nothing to do.\n");
234 return;
235 }
236
237 /* No MSI -> MSIs can't have been assigned by fw, leave LSI */
238 if (check_req_msi(pdev, 1)) {
239 dev_dbg(&pdev->dev, "rtas_msi: no req#msi, nothing to do.\n");
240 return;
241 }
242
243 dev_dbg(&pdev->dev, "rtas_msi: disabling existing MSI.\n");
244 rtas_disable_msi(pdev);
245}
246
247static int rtas_msi_init(void)
248{
249 query_token = rtas_token("ibm,query-interrupt-source-number");
250 change_token = rtas_token("ibm,change-msi");
251
252 if ((query_token == RTAS_UNKNOWN_SERVICE) ||
253 (change_token == RTAS_UNKNOWN_SERVICE)) {
254 pr_debug("rtas_msi: no RTAS tokens, no MSI support.\n");
255 return -1;
256 }
257
258 pr_debug("rtas_msi: Registering RTAS MSI callbacks.\n");
259
260 WARN_ON(ppc_md.setup_msi_irqs);
261 ppc_md.setup_msi_irqs = rtas_setup_msi_irqs;
262 ppc_md.teardown_msi_irqs = rtas_teardown_msi_irqs;
263 ppc_md.msi_check_device = rtas_msi_check_device;
264
265 WARN_ON(ppc_md.pci_irq_fixup);
266 ppc_md.pci_irq_fixup = rtas_msi_pci_irq_fixup;
267
268 return 0;
269}
270arch_initcall(rtas_msi_init);
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index fdc1a369f767..ffaf6c5c517b 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -79,6 +79,7 @@ pcibios_remove_pci_devices(struct pci_bus *bus)
79 pci_remove_bus_device(dev); 79 pci_remove_bus_device(dev);
80 } 80 }
81} 81}
82EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices);
82 83
83/* Must be called before pci_bus_add_devices */ 84/* Must be called before pci_bus_add_devices */
84void 85void
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 33eec2822c66..470db6efaeb6 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -168,7 +168,7 @@ static void __init pseries_mpic_init_IRQ(void)
168 168
169 /* Look for cascade */ 169 /* Look for cascade */
170 for_each_node_by_type(np, "interrupt-controller") 170 for_each_node_by_type(np, "interrupt-controller")
171 if (device_is_compatible(np, "chrp,iic")) { 171 if (of_device_is_compatible(np, "chrp,iic")) {
172 cascade = np; 172 cascade = np;
173 break; 173 break;
174 } 174 }
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 896cbf340c42..b854e7f1001c 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -477,7 +477,7 @@ static int xics_host_match(struct irq_host *h, struct device_node *node)
477 * like vdevices, events, etc... The trick we use here is to match 477 * like vdevices, events, etc... The trick we use here is to match
478 * everything here except the legacy 8259 which is compatible "chrp,iic" 478 * everything here except the legacy 8259 which is compatible "chrp,iic"
479 */ 479 */
480 return !device_is_compatible(node, "chrp,iic"); 480 return !of_device_is_compatible(node, "chrp,iic");
481} 481}
482 482
483static int xics_host_map_direct(struct irq_host *h, unsigned int virq, 483static int xics_host_map_direct(struct irq_host *h, unsigned int virq,
@@ -618,7 +618,7 @@ static void __init xics_setup_8259_cascade(void)
618 unsigned long intack = 0; 618 unsigned long intack = 0;
619 619
620 for_each_node_by_type(np, "interrupt-controller") 620 for_each_node_by_type(np, "interrupt-controller")
621 if (device_is_compatible(np, "chrp,iic")) { 621 if (of_device_is_compatible(np, "chrp,iic")) {
622 found = np; 622 found = np;
623 break; 623 break;
624 } 624 }