aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-01-30 21:37:27 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2008-01-30 21:37:27 -0500
commit8af03e782cae1e0a0f530ddd22301cdd12cf9dc0 (patch)
treec4af13a38bd3cc1a811a37f2358491f171052070 /arch/powerpc/platforms
parent6232665040f9a23fafd9d94d4ae8d5a2dc850f65 (diff)
parent99e139126ab2e84be67969650f92eb37c12ab5cd (diff)
Merge branch 'for-2.6.25' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'for-2.6.25' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (454 commits) [POWERPC] Cell IOMMU fixed mapping support [POWERPC] Split out the ioid fetching/checking logic [POWERPC] Add support to cell_iommu_setup_page_tables() for multiple windows [POWERPC] Split out the IOMMU logic from cell_dma_dev_setup() [POWERPC] Split cell_iommu_setup_hardware() into two parts [POWERPC] Split out the logic that allocates struct iommus [POWERPC] Allocate the hash table under 1G on cell [POWERPC] Add set_dma_ops() to match get_dma_ops() [POWERPC] 83xx: Clean up / convert mpc83xx board DTS files to v1 format. [POWERPC] 85xx: Only invalidate TLB0 and TLB1 [POWERPC] 83xx: Fix typo in mpc837x compatible entries [POWERPC] 85xx: convert sbc85* boards to use machine_device_initcall [POWERPC] 83xx: rework platform Kconfig [POWERPC] 85xx: rework platform Kconfig [POWERPC] 86xx: Remove unused IRQ defines [POWERPC] QE: Explicitly set address-cells and size cells for muram [POWERPC] Convert StorCenter DTS file to /dts-v1/ format. [POWERPC] 86xx: Convert all 86xx DTS files to /dts-v1/ format. [PPC] Remove 85xx from arch/ppc [PPC] Remove 83xx from arch/ppc ...
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/40x/Kconfig40
-rw-r--r--arch/powerpc/platforms/40x/Makefile2
-rw-r--r--arch/powerpc/platforms/40x/ep405.c123
-rw-r--r--arch/powerpc/platforms/40x/kilauea.c10
-rw-r--r--arch/powerpc/platforms/40x/makalu.c58
-rw-r--r--arch/powerpc/platforms/40x/virtex.c17
-rw-r--r--arch/powerpc/platforms/40x/walnut.c12
-rw-r--r--arch/powerpc/platforms/44x/Kconfig61
-rw-r--r--arch/powerpc/platforms/44x/Makefile7
-rw-r--r--arch/powerpc/platforms/44x/bamboo.c11
-rw-r--r--arch/powerpc/platforms/44x/ebony.c12
-rw-r--r--arch/powerpc/platforms/44x/katmai.c63
-rw-r--r--arch/powerpc/platforms/44x/rainier.c62
-rw-r--r--arch/powerpc/platforms/44x/sequoia.c11
-rw-r--r--arch/powerpc/platforms/44x/taishan.c73
-rw-r--r--arch/powerpc/platforms/44x/warp-nand.c105
-rw-r--r--arch/powerpc/platforms/44x/warp.c153
-rw-r--r--arch/powerpc/platforms/52xx/Kconfig50
-rw-r--r--arch/powerpc/platforms/52xx/Makefile1
-rw-r--r--arch/powerpc/platforms/52xx/efika.c3
-rw-r--r--arch/powerpc/platforms/52xx/lite5200.c46
-rw-r--r--arch/powerpc/platforms/52xx/lite5200_pm.c13
-rw-r--r--arch/powerpc/platforms/52xx/mpc5200_simple.c85
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_common.c154
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_pci.c20
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_pic.c22
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_pm.c15
-rw-r--r--arch/powerpc/platforms/82xx/Kconfig13
-rw-r--r--arch/powerpc/platforms/82xx/Makefile1
-rw-r--r--arch/powerpc/platforms/82xx/ep8248e.c324
-rw-r--r--arch/powerpc/platforms/82xx/mpc8272_ads.c5
-rw-r--r--arch/powerpc/platforms/82xx/pq2.c4
-rw-r--r--arch/powerpc/platforms/82xx/pq2fads.c7
-rw-r--r--arch/powerpc/platforms/83xx/Kconfig63
-rw-r--r--arch/powerpc/platforms/83xx/Makefile5
-rw-r--r--arch/powerpc/platforms/83xx/mpc831x_rdb.c (renamed from arch/powerpc/platforms/83xx/mpc8313_rdb.c)51
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_mds.c20
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_rdb.c23
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_itx.c12
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_mds.c18
-rw-r--r--arch/powerpc/platforms/83xx/mpc836x_mds.c20
-rw-r--r--arch/powerpc/platforms/83xx/mpc837x_mds.c147
-rw-r--r--arch/powerpc/platforms/83xx/mpc837x_rdb.c99
-rw-r--r--arch/powerpc/platforms/83xx/mpc83xx.h3
-rw-r--r--arch/powerpc/platforms/83xx/pci.c2
-rw-r--r--arch/powerpc/platforms/83xx/sbc834x.c115
-rw-r--r--arch/powerpc/platforms/83xx/usb.c50
-rw-r--r--arch/powerpc/platforms/85xx/Kconfig87
-rw-r--r--arch/powerpc/platforms/85xx/Makefile4
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ads.c18
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_cds.c6
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ds.c2
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_mds.c43
-rw-r--r--arch/powerpc/platforms/85xx/sbc8548.c167
-rw-r--r--arch/powerpc/platforms/85xx/sbc8560.c283
-rw-r--r--arch/powerpc/platforms/85xx/stx_gp3.c183
-rw-r--r--arch/powerpc/platforms/85xx/tqm85xx.c187
-rw-r--r--arch/powerpc/platforms/86xx/mpc8610_hpcd.c17
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_hpcn.c16
-rw-r--r--arch/powerpc/platforms/8xx/Kconfig10
-rw-r--r--arch/powerpc/platforms/8xx/Makefile1
-rw-r--r--arch/powerpc/platforms/8xx/adder875.c118
-rw-r--r--arch/powerpc/platforms/8xx/ep88xc.c10
-rw-r--r--arch/powerpc/platforms/8xx/m8xx_setup.c13
-rw-r--r--arch/powerpc/platforms/8xx/mpc86xads.h44
-rw-r--r--arch/powerpc/platforms/8xx/mpc86xads_setup.c294
-rw-r--r--arch/powerpc/platforms/8xx/mpc885ads_setup.c12
-rw-r--r--arch/powerpc/platforms/8xx/mpc8xx.h21
-rw-r--r--arch/powerpc/platforms/Kconfig18
-rw-r--r--arch/powerpc/platforms/Kconfig.cputype11
-rw-r--r--arch/powerpc/platforms/cell/Makefile2
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq.c3
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c3
-rw-r--r--arch/powerpc/platforms/cell/cbe_regs.c5
-rw-r--r--arch/powerpc/platforms/cell/io-workarounds.c9
-rw-r--r--arch/powerpc/platforms/cell/iommu.c398
-rw-r--r--arch/powerpc/platforms/cell/pmu.c7
-rw-r--r--arch/powerpc/platforms/cell/setup.c7
-rw-r--r--arch/powerpc/platforms/cell/smp.c3
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c224
-rw-r--r--arch/powerpc/platforms/cell/spu_fault.c98
-rw-r--r--arch/powerpc/platforms/cell/spu_manage.c28
-rw-r--r--arch/powerpc/platforms/cell/spufs/Makefile2
-rw-r--r--arch/powerpc/platforms/cell/spufs/backing_ops.c31
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c53
-rw-r--r--arch/powerpc/platforms/cell/spufs/coredump.c8
-rw-r--r--arch/powerpc/platforms/cell/spufs/fault.c187
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c429
-rw-r--r--arch/powerpc/platforms/cell/spufs/hw_ops.c33
-rw-r--r--arch/powerpc/platforms/cell/spufs/lscsa_alloc.c4
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c190
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c361
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h64
-rw-r--r--arch/powerpc/platforms/cell/spufs/switch.c73
-rw-r--r--arch/powerpc/platforms/celleb/Kconfig2
-rw-r--r--arch/powerpc/platforms/celleb/io-workarounds.c7
-rw-r--r--arch/powerpc/platforms/celleb/iommu.c26
-rw-r--r--arch/powerpc/platforms/celleb/pci.c14
-rw-r--r--arch/powerpc/platforms/celleb/scc_epci.c2
-rw-r--r--arch/powerpc/platforms/celleb/scc_uhc.c3
-rw-r--r--arch/powerpc/platforms/celleb/setup.c147
-rw-r--r--arch/powerpc/platforms/chrp/pci.c6
-rw-r--r--arch/powerpc/platforms/chrp/setup.c65
-rw-r--r--arch/powerpc/platforms/embedded6xx/Kconfig23
-rw-r--r--arch/powerpc/platforms/embedded6xx/Makefile1
-rw-r--r--arch/powerpc/platforms/embedded6xx/holly.c3
-rw-r--r--arch/powerpc/platforms/embedded6xx/ls_uart.c5
-rw-r--r--arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c2
-rw-r--r--arch/powerpc/platforms/embedded6xx/storcenter.c192
-rw-r--r--arch/powerpc/platforms/iseries/Makefile2
-rw-r--r--arch/powerpc/platforms/iseries/iommu.c4
-rw-r--r--arch/powerpc/platforms/iseries/lpevents.c2
-rw-r--r--arch/powerpc/platforms/iseries/pci.c670
-rw-r--r--arch/powerpc/platforms/iseries/pci.h27
-rw-r--r--arch/powerpc/platforms/iseries/setup.c61
-rw-r--r--arch/powerpc/platforms/iseries/setup.h1
-rw-r--r--arch/powerpc/platforms/iseries/vpdinfo.c275
-rw-r--r--arch/powerpc/platforms/maple/Kconfig1
-rw-r--r--arch/powerpc/platforms/maple/pci.c2
-rw-r--r--arch/powerpc/platforms/maple/setup.c2
-rw-r--r--arch/powerpc/platforms/pasemi/Kconfig12
-rw-r--r--arch/powerpc/platforms/pasemi/Makefile1
-rw-r--r--arch/powerpc/platforms/pasemi/cpufreq.c19
-rw-r--r--arch/powerpc/platforms/pasemi/electra_ide.c96
-rw-r--r--arch/powerpc/platforms/pasemi/gpio_mdio.c96
-rw-r--r--arch/powerpc/platforms/pasemi/idle.c5
-rw-r--r--arch/powerpc/platforms/pasemi/pasemi.h6
-rw-r--r--arch/powerpc/platforms/pasemi/powersave.S11
-rw-r--r--arch/powerpc/platforms/pasemi/setup.c61
-rw-r--r--arch/powerpc/platforms/powermac/low_i2c.c10
-rw-r--r--arch/powerpc/platforms/powermac/pci.c248
-rw-r--r--arch/powerpc/platforms/powermac/pfunc_base.c3
-rw-r--r--arch/powerpc/platforms/powermac/pic.c3
-rw-r--r--arch/powerpc/platforms/powermac/pmac.h2
-rw-r--r--arch/powerpc/platforms/powermac/setup.c21
-rw-r--r--arch/powerpc/platforms/powermac/time.c2
-rw-r--r--arch/powerpc/platforms/ps3/Kconfig24
-rw-r--r--arch/powerpc/platforms/ps3/device-init.c531
-rw-r--r--arch/powerpc/platforms/ps3/mm.c24
-rw-r--r--arch/powerpc/platforms/ps3/platform.h34
-rw-r--r--arch/powerpc/platforms/ps3/repository.c320
-rw-r--r--arch/powerpc/platforms/ps3/spu.c27
-rw-r--r--arch/powerpc/platforms/ps3/system-bus.c19
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c46
-rw-r--r--arch/powerpc/platforms/pseries/eeh_driver.c19
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c28
-rw-r--r--arch/powerpc/platforms/pseries/pci_dlpar.c14
-rw-r--r--arch/powerpc/platforms/pseries/plpar_wrappers.h5
-rw-r--r--arch/powerpc/platforms/pseries/smp.c3
-rw-r--r--arch/powerpc/platforms/pseries/xics.c59
-rw-r--r--arch/powerpc/platforms/pseries/xics.h3
151 files changed, 6576 insertions, 2719 deletions
diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig
index 8f6699fcc145..74f31177e47a 100644
--- a/arch/powerpc/platforms/40x/Kconfig
+++ b/arch/powerpc/platforms/40x/Kconfig
@@ -14,28 +14,34 @@
14# help 14# help
15# This option enables support for the CPCI405 board. 15# This option enables support for the CPCI405 board.
16 16
17#config EP405 17config EP405
18# bool "EP405/EP405PC" 18 bool "EP405/EP405PC"
19# depends on 40x 19 depends on 40x
20# default n 20 default n
21# select 405GP 21 select 405GP
22# help 22 select PCI
23# This option enables support for the EP405/EP405PC boards. 23 help
24 24 This option enables support for the EP405/EP405PC boards.
25#config EP405PC
26# bool "EP405PC Support"
27# depends on EP405
28# default y
29# help
30# This option enables support for the extra features of the EP405PC board.
31 25
32config KILAUEA 26config KILAUEA
33 bool "Kilauea" 27 bool "Kilauea"
34 depends on 40x 28 depends on 40x
35 default n 29 default n
30 select 405EX
31 select PPC4xx_PCI_EXPRESS
36 help 32 help
37 This option enables support for the AMCC PPC405EX evaluation board. 33 This option enables support for the AMCC PPC405EX evaluation board.
38 34
35config MAKALU
36 bool "Makalu"
37 depends on 40x
38 default n
39 select 405EX
40 select PCI
41 select PPC4xx_PCI_EXPRESS
42 help
43 This option enables support for the AMCC PPC405EX board.
44
39#config REDWOOD_5 45#config REDWOOD_5
40# bool "Redwood-5" 46# bool "Redwood-5"
41# depends on 40x 47# depends on 40x
@@ -65,6 +71,7 @@ config WALNUT
65 depends on 40x 71 depends on 40x
66 default y 72 default y
67 select 405GP 73 select 405GP
74 select PCI
68 help 75 help
69 This option enables support for the IBM PPC405GP evaluation board. 76 This option enables support for the IBM PPC405GP evaluation board.
70 77
@@ -105,6 +112,11 @@ config 405GP
105config 405EP 112config 405EP
106 bool 113 bool
107 114
115config 405EX
116 bool
117 select IBM_NEW_EMAC_EMAC4
118 select IBM_NEW_EMAC_RGMII
119
108config 405GPR 120config 405GPR
109 bool 121 bool
110 122
diff --git a/arch/powerpc/platforms/40x/Makefile b/arch/powerpc/platforms/40x/Makefile
index 51dadeee6fc6..5533a5c8ce4e 100644
--- a/arch/powerpc/platforms/40x/Makefile
+++ b/arch/powerpc/platforms/40x/Makefile
@@ -1,3 +1,5 @@
1obj-$(CONFIG_KILAUEA) += kilauea.o 1obj-$(CONFIG_KILAUEA) += kilauea.o
2obj-$(CONFIG_MAKALU) += makalu.o
2obj-$(CONFIG_WALNUT) += walnut.o 3obj-$(CONFIG_WALNUT) += walnut.o
3obj-$(CONFIG_XILINX_VIRTEX_GENERIC_BOARD) += virtex.o 4obj-$(CONFIG_XILINX_VIRTEX_GENERIC_BOARD) += virtex.o
5obj-$(CONFIG_EP405) += ep405.o
diff --git a/arch/powerpc/platforms/40x/ep405.c b/arch/powerpc/platforms/40x/ep405.c
new file mode 100644
index 000000000000..13d1345026da
--- /dev/null
+++ b/arch/powerpc/platforms/40x/ep405.c
@@ -0,0 +1,123 @@
1/*
2 * Architecture- / platform-specific boot-time initialization code for
3 * IBM PowerPC 4xx based boards. Adapted from original
4 * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
5 * <dan@net4x.com>.
6 *
7 * Copyright(c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
8 *
9 * Rewritten and ported to the merged powerpc tree:
10 * Copyright 2007 IBM Corporation
11 * Josh Boyer <jwboyer@linux.vnet.ibm.com>
12 *
13 * Adapted to EP405 by Ben. Herrenschmidt <benh@kernel.crashing.org>
14 *
15 * TODO: Wire up the PCI IRQ mux and the southbridge interrupts
16 *
17 * 2002 (c) MontaVista, Software, Inc. This file is licensed under
18 * the terms of the GNU General Public License version 2. This program
19 * is licensed "as is" without any warranty of any kind, whether express
20 * or implied.
21 */
22
23#include <linux/init.h>
24#include <linux/of_platform.h>
25
26#include <asm/machdep.h>
27#include <asm/prom.h>
28#include <asm/udbg.h>
29#include <asm/time.h>
30#include <asm/uic.h>
31#include <asm/pci-bridge.h>
32
33static struct device_node *bcsr_node;
34static void __iomem *bcsr_regs;
35
36/* BCSR registers */
37#define BCSR_ID 0
38#define BCSR_PCI_CTRL 1
39#define BCSR_FLASH_NV_POR_CTRL 2
40#define BCSR_FENET_UART_CTRL 3
41#define BCSR_PCI_IRQ 4
42#define BCSR_XIRQ_SELECT 5
43#define BCSR_XIRQ_ROUTING 6
44#define BCSR_XIRQ_STATUS 7
45#define BCSR_XIRQ_STATUS2 8
46#define BCSR_SW_STAT_LED_CTRL 9
47#define BCSR_GPIO_IRQ_PAR_CTRL 10
48/* there's more, can't be bothered typing them tho */
49
50
51static __initdata struct of_device_id ep405_of_bus[] = {
52 { .compatible = "ibm,plb3", },
53 { .compatible = "ibm,opb", },
54 { .compatible = "ibm,ebc", },
55 {},
56};
57
58static int __init ep405_device_probe(void)
59{
60 of_platform_bus_probe(NULL, ep405_of_bus, NULL);
61
62 return 0;
63}
64machine_device_initcall(ep405, ep405_device_probe);
65
66static void __init ep405_init_bcsr(void)
67{
68 const u8 *irq_routing;
69 int i;
70
71 /* Find the bloody thing & map it */
72 bcsr_node = of_find_compatible_node(NULL, NULL, "ep405-bcsr");
73 if (bcsr_node == NULL) {
74 printk(KERN_ERR "EP405 BCSR not found !\n");
75 return;
76 }
77 bcsr_regs = of_iomap(bcsr_node, 0);
78 if (bcsr_regs == NULL) {
79 printk(KERN_ERR "EP405 BCSR failed to map !\n");
80 return;
81 }
82
83 /* Get the irq-routing property and apply the routing to the CPLD */
84 irq_routing = of_get_property(bcsr_node, "irq-routing", NULL);
85 if (irq_routing == NULL)
86 return;
87 for (i = 0; i < 16; i++) {
88 u8 irq = irq_routing[i];
89 out_8(bcsr_regs + BCSR_XIRQ_SELECT, i);
90 out_8(bcsr_regs + BCSR_XIRQ_ROUTING, irq);
91 }
92 in_8(bcsr_regs + BCSR_XIRQ_SELECT);
93 mb();
94 out_8(bcsr_regs + BCSR_GPIO_IRQ_PAR_CTRL, 0xfe);
95}
96
97static void __init ep405_setup_arch(void)
98{
99 /* Find & init the BCSR CPLD */
100 ep405_init_bcsr();
101
102 ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
103}
104
105static int __init ep405_probe(void)
106{
107 unsigned long root = of_get_flat_dt_root();
108
109 if (!of_flat_dt_is_compatible(root, "ep405"))
110 return 0;
111
112 return 1;
113}
114
115define_machine(ep405) {
116 .name = "EP405",
117 .probe = ep405_probe,
118 .setup_arch = ep405_setup_arch,
119 .progress = udbg_progress,
120 .init_IRQ = uic_init_tree,
121 .get_irq = uic_get_irq,
122 .calibrate_decr = generic_calibrate_decr,
123};
diff --git a/arch/powerpc/platforms/40x/kilauea.c b/arch/powerpc/platforms/40x/kilauea.c
index 1bffdbdd21b1..f9206a7fede0 100644
--- a/arch/powerpc/platforms/40x/kilauea.c
+++ b/arch/powerpc/platforms/40x/kilauea.c
@@ -19,8 +19,9 @@
19#include <asm/udbg.h> 19#include <asm/udbg.h>
20#include <asm/time.h> 20#include <asm/time.h>
21#include <asm/uic.h> 21#include <asm/uic.h>
22#include <asm/pci-bridge.h>
22 23
23static struct of_device_id kilauea_of_bus[] = { 24static __initdata struct of_device_id kilauea_of_bus[] = {
24 { .compatible = "ibm,plb4", }, 25 { .compatible = "ibm,plb4", },
25 { .compatible = "ibm,opb", }, 26 { .compatible = "ibm,opb", },
26 { .compatible = "ibm,ebc", }, 27 { .compatible = "ibm,ebc", },
@@ -29,14 +30,11 @@ static struct of_device_id kilauea_of_bus[] = {
29 30
30static int __init kilauea_device_probe(void) 31static int __init kilauea_device_probe(void)
31{ 32{
32 if (!machine_is(kilauea))
33 return 0;
34
35 of_platform_bus_probe(NULL, kilauea_of_bus, NULL); 33 of_platform_bus_probe(NULL, kilauea_of_bus, NULL);
36 34
37 return 0; 35 return 0;
38} 36}
39device_initcall(kilauea_device_probe); 37machine_device_initcall(kilauea, kilauea_device_probe);
40 38
41static int __init kilauea_probe(void) 39static int __init kilauea_probe(void)
42{ 40{
@@ -45,6 +43,8 @@ static int __init kilauea_probe(void)
45 if (!of_flat_dt_is_compatible(root, "amcc,kilauea")) 43 if (!of_flat_dt_is_compatible(root, "amcc,kilauea"))
46 return 0; 44 return 0;
47 45
46 ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
47
48 return 1; 48 return 1;
49} 49}
50 50
diff --git a/arch/powerpc/platforms/40x/makalu.c b/arch/powerpc/platforms/40x/makalu.c
new file mode 100644
index 000000000000..4e4df72fc9cd
--- /dev/null
+++ b/arch/powerpc/platforms/40x/makalu.c
@@ -0,0 +1,58 @@
1/*
2 * Makalu board specific routines
3 *
4 * Copyright 2007 DENX Software Engineering, Stefan Roese <sr@denx.de>
5 *
6 * Based on the Walnut code by
7 * Josh Boyer <jwboyer@linux.vnet.ibm.com>
8 * Copyright 2007 IBM Corporation
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15#include <linux/init.h>
16#include <linux/of_platform.h>
17#include <asm/machdep.h>
18#include <asm/prom.h>
19#include <asm/udbg.h>
20#include <asm/time.h>
21#include <asm/uic.h>
22#include <asm/pci-bridge.h>
23
24static __initdata struct of_device_id makalu_of_bus[] = {
25 { .compatible = "ibm,plb4", },
26 { .compatible = "ibm,opb", },
27 { .compatible = "ibm,ebc", },
28 {},
29};
30
31static int __init makalu_device_probe(void)
32{
33 of_platform_bus_probe(NULL, makalu_of_bus, NULL);
34
35 return 0;
36}
37machine_device_initcall(makalu, makalu_device_probe);
38
39static int __init makalu_probe(void)
40{
41 unsigned long root = of_get_flat_dt_root();
42
43 if (!of_flat_dt_is_compatible(root, "amcc,makalu"))
44 return 0;
45
46 ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
47
48 return 1;
49}
50
51define_machine(makalu) {
52 .name = "Makalu",
53 .probe = makalu_probe,
54 .progress = udbg_progress,
55 .init_IRQ = uic_init_tree,
56 .get_irq = uic_get_irq,
57 .calibrate_decr = generic_calibrate_decr,
58};
diff --git a/arch/powerpc/platforms/40x/virtex.c b/arch/powerpc/platforms/40x/virtex.c
index 14bbc328170f..88b66444dfb2 100644
--- a/arch/powerpc/platforms/40x/virtex.c
+++ b/arch/powerpc/platforms/40x/virtex.c
@@ -15,16 +15,23 @@
15#include <asm/time.h> 15#include <asm/time.h>
16#include <asm/xilinx_intc.h> 16#include <asm/xilinx_intc.h>
17 17
18static struct of_device_id xilinx_of_bus_ids[] __initdata = {
19 { .compatible = "xlnx,plb-v46-1.00.a", },
20 { .compatible = "xlnx,plb-v34-1.01.a", },
21 { .compatible = "xlnx,plb-v34-1.02.a", },
22 { .compatible = "xlnx,opb-v20-1.10.c", },
23 { .compatible = "xlnx,dcr-v29-1.00.a", },
24 { .compatible = "xlnx,compound", },
25 {}
26};
27
18static int __init virtex_device_probe(void) 28static int __init virtex_device_probe(void)
19{ 29{
20 if (!machine_is(virtex)) 30 of_platform_bus_probe(NULL, xilinx_of_bus_ids, NULL);
21 return 0;
22
23 of_platform_bus_probe(NULL, NULL, NULL);
24 31
25 return 0; 32 return 0;
26} 33}
27device_initcall(virtex_device_probe); 34machine_device_initcall(virtex, virtex_device_probe);
28 35
29static int __init virtex_probe(void) 36static int __init virtex_probe(void)
30{ 37{
diff --git a/arch/powerpc/platforms/40x/walnut.c b/arch/powerpc/platforms/40x/walnut.c
index ff6db2431798..5d9edd917f92 100644
--- a/arch/powerpc/platforms/40x/walnut.c
+++ b/arch/powerpc/platforms/40x/walnut.c
@@ -24,8 +24,9 @@
24#include <asm/udbg.h> 24#include <asm/udbg.h>
25#include <asm/time.h> 25#include <asm/time.h>
26#include <asm/uic.h> 26#include <asm/uic.h>
27#include <asm/pci-bridge.h>
27 28
28static struct of_device_id walnut_of_bus[] = { 29static __initdata struct of_device_id walnut_of_bus[] = {
29 { .compatible = "ibm,plb3", }, 30 { .compatible = "ibm,plb3", },
30 { .compatible = "ibm,opb", }, 31 { .compatible = "ibm,opb", },
31 { .compatible = "ibm,ebc", }, 32 { .compatible = "ibm,ebc", },
@@ -34,15 +35,12 @@ static struct of_device_id walnut_of_bus[] = {
34 35
35static int __init walnut_device_probe(void) 36static int __init walnut_device_probe(void)
36{ 37{
37 if (!machine_is(walnut))
38 return 0;
39
40 /* FIXME: do bus probe here */
41 of_platform_bus_probe(NULL, walnut_of_bus, NULL); 38 of_platform_bus_probe(NULL, walnut_of_bus, NULL);
39 of_instantiate_rtc();
42 40
43 return 0; 41 return 0;
44} 42}
45device_initcall(walnut_device_probe); 43machine_device_initcall(walnut, walnut_device_probe);
46 44
47static int __init walnut_probe(void) 45static int __init walnut_probe(void)
48{ 46{
@@ -51,6 +49,8 @@ static int __init walnut_probe(void)
51 if (!of_flat_dt_is_compatible(root, "ibm,walnut")) 49 if (!of_flat_dt_is_compatible(root, "ibm,walnut"))
52 return 0; 50 return 0;
53 51
52 ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
53
54 return 1; 54 return 1;
55} 55}
56 56
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index 8390cc164135..c062c4cbbed5 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -3,6 +3,7 @@ config BAMBOO
3 depends on 44x 3 depends on 44x
4 default n 4 default n
5 select 440EP 5 select 440EP
6 select PCI
6 help 7 help
7 This option enables support for the IBM PPC440EP evaluation board. 8 This option enables support for the IBM PPC440EP evaluation board.
8 9
@@ -11,6 +12,8 @@ config EBONY
11 depends on 44x 12 depends on 44x
12 default y 13 default y
13 select 440GP 14 select 440GP
15 select PCI
16 select OF_RTC
14 help 17 help
15 This option enables support for the IBM PPC440GP evaluation board. 18 This option enables support for the IBM PPC440GP evaluation board.
16 19
@@ -22,6 +25,48 @@ config SEQUOIA
22 help 25 help
23 This option enables support for the AMCC PPC440EPX evaluation board. 26 This option enables support for the AMCC PPC440EPX evaluation board.
24 27
28config TAISHAN
29 bool "Taishan"
30 depends on 44x
31 default n
32 select 440GX
33 select PCI
34 help
35 This option enables support for the AMCC PPC440GX "Taishan"
36 evaluation board.
37
38config KATMAI
39 bool "Katmai"
40 depends on 44x
41 default n
42 select 440SPe
43 select PCI
44 select PPC4xx_PCI_EXPRESS
45 help
46 This option enables support for the AMCC PPC440SPe evaluation board.
47
48config RAINIER
49 bool "Rainier"
50 depends on 44x
51 default n
52 select 440GRX
53 select PCI
54 help
55 This option enables support for the AMCC PPC440GRX evaluation board.
56
57config WARP
58 bool "PIKA Warp"
59 depends on 44x
60 default n
61 select 440EP
62 help
63 This option enables support for the PIKA Warp(tm) Appliance. The Warp
64 is a small computer replacement with up to 9 ports of FXO/FXS plus VOIP
65 stations and trunks.
66
67 See http://www.pikatechnologies.com/ and follow the "PIKA for Computer
68 Telephony Developers" link for more information.
69
25#config LUAN 70#config LUAN
26# bool "Luan" 71# bool "Luan"
27# depends on 44x 72# depends on 44x
@@ -44,6 +89,7 @@ config 440EP
44 select PPC_FPU 89 select PPC_FPU
45 select IBM440EP_ERR42 90 select IBM440EP_ERR42
46 select IBM_NEW_EMAC_ZMII 91 select IBM_NEW_EMAC_ZMII
92 select USB_ARCH_HAS_OHCI
47 93
48config 440EPX 94config 440EPX
49 bool 95 bool
@@ -52,20 +98,29 @@ config 440EPX
52 select IBM_NEW_EMAC_RGMII 98 select IBM_NEW_EMAC_RGMII
53 select IBM_NEW_EMAC_ZMII 99 select IBM_NEW_EMAC_ZMII
54 100
101config 440GRX
102 bool
103 select IBM_NEW_EMAC_EMAC4
104 select IBM_NEW_EMAC_RGMII
105 select IBM_NEW_EMAC_ZMII
106
55config 440GP 107config 440GP
56 bool 108 bool
57 select IBM_NEW_EMAC_ZMII 109 select IBM_NEW_EMAC_ZMII
58 110
59config 440GX 111config 440GX
60 bool 112 bool
113 select IBM_NEW_EMAC_EMAC4
114 select IBM_NEW_EMAC_RGMII
115 select IBM_NEW_EMAC_ZMII #test only
116 select IBM_NEW_EMAC_TAH #test only
61 117
62config 440SP 118config 440SP
63 bool 119 bool
64 120
65config 440A 121config 440SPe
122 select IBM_NEW_EMAC_EMAC4
66 bool 123 bool
67 depends on 440GX || 440EPX
68 default y
69 124
70# 44x errata/workaround config symbols, selected by the CPU models above 125# 44x errata/workaround config symbols, selected by the CPU models above
71config IBM440EP_ERR42 126config IBM440EP_ERR42
diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile
index 10ce6740cc7d..0864d4f1cbc2 100644
--- a/arch/powerpc/platforms/44x/Makefile
+++ b/arch/powerpc/platforms/44x/Makefile
@@ -1,4 +1,9 @@
1obj-$(CONFIG_44x) := misc_44x.o 1obj-$(CONFIG_44x) := misc_44x.o
2obj-$(CONFIG_EBONY) += ebony.o 2obj-$(CONFIG_EBONY) += ebony.o
3obj-$(CONFIG_BAMBOO) += bamboo.o 3obj-$(CONFIG_TAISHAN) += taishan.o
4obj-$(CONFIG_BAMBOO) += bamboo.o
4obj-$(CONFIG_SEQUOIA) += sequoia.o 5obj-$(CONFIG_SEQUOIA) += sequoia.o
6obj-$(CONFIG_KATMAI) += katmai.o
7obj-$(CONFIG_RAINIER) += rainier.o
8obj-$(CONFIG_WARP) += warp.o
9obj-$(CONFIG_WARP) += warp-nand.o
diff --git a/arch/powerpc/platforms/44x/bamboo.c b/arch/powerpc/platforms/44x/bamboo.c
index be23f112184f..fb9a22a7e8d0 100644
--- a/arch/powerpc/platforms/44x/bamboo.c
+++ b/arch/powerpc/platforms/44x/bamboo.c
@@ -21,9 +21,11 @@
21#include <asm/udbg.h> 21#include <asm/udbg.h>
22#include <asm/time.h> 22#include <asm/time.h>
23#include <asm/uic.h> 23#include <asm/uic.h>
24#include <asm/pci-bridge.h>
25
24#include "44x.h" 26#include "44x.h"
25 27
26static struct of_device_id bamboo_of_bus[] = { 28static __initdata struct of_device_id bamboo_of_bus[] = {
27 { .compatible = "ibm,plb4", }, 29 { .compatible = "ibm,plb4", },
28 { .compatible = "ibm,opb", }, 30 { .compatible = "ibm,opb", },
29 { .compatible = "ibm,ebc", }, 31 { .compatible = "ibm,ebc", },
@@ -32,14 +34,11 @@ static struct of_device_id bamboo_of_bus[] = {
32 34
33static int __init bamboo_device_probe(void) 35static int __init bamboo_device_probe(void)
34{ 36{
35 if (!machine_is(bamboo))
36 return 0;
37
38 of_platform_bus_probe(NULL, bamboo_of_bus, NULL); 37 of_platform_bus_probe(NULL, bamboo_of_bus, NULL);
39 38
40 return 0; 39 return 0;
41} 40}
42device_initcall(bamboo_device_probe); 41machine_device_initcall(bamboo, bamboo_device_probe);
43 42
44static int __init bamboo_probe(void) 43static int __init bamboo_probe(void)
45{ 44{
@@ -48,6 +47,8 @@ static int __init bamboo_probe(void)
48 if (!of_flat_dt_is_compatible(root, "amcc,bamboo")) 47 if (!of_flat_dt_is_compatible(root, "amcc,bamboo"))
49 return 0; 48 return 0;
50 49
50 ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
51
51 return 1; 52 return 1;
52} 53}
53 54
diff --git a/arch/powerpc/platforms/44x/ebony.c b/arch/powerpc/platforms/44x/ebony.c
index 6cd3476767cc..1a8d467bff85 100644
--- a/arch/powerpc/platforms/44x/ebony.c
+++ b/arch/powerpc/platforms/44x/ebony.c
@@ -18,16 +18,18 @@
18 18
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/of_platform.h> 20#include <linux/of_platform.h>
21#include <linux/rtc.h>
21 22
22#include <asm/machdep.h> 23#include <asm/machdep.h>
23#include <asm/prom.h> 24#include <asm/prom.h>
24#include <asm/udbg.h> 25#include <asm/udbg.h>
25#include <asm/time.h> 26#include <asm/time.h>
26#include <asm/uic.h> 27#include <asm/uic.h>
28#include <asm/pci-bridge.h>
27 29
28#include "44x.h" 30#include "44x.h"
29 31
30static struct of_device_id ebony_of_bus[] = { 32static __initdata struct of_device_id ebony_of_bus[] = {
31 { .compatible = "ibm,plb4", }, 33 { .compatible = "ibm,plb4", },
32 { .compatible = "ibm,opb", }, 34 { .compatible = "ibm,opb", },
33 { .compatible = "ibm,ebc", }, 35 { .compatible = "ibm,ebc", },
@@ -36,14 +38,12 @@ static struct of_device_id ebony_of_bus[] = {
36 38
37static int __init ebony_device_probe(void) 39static int __init ebony_device_probe(void)
38{ 40{
39 if (!machine_is(ebony))
40 return 0;
41
42 of_platform_bus_probe(NULL, ebony_of_bus, NULL); 41 of_platform_bus_probe(NULL, ebony_of_bus, NULL);
42 of_instantiate_rtc();
43 43
44 return 0; 44 return 0;
45} 45}
46device_initcall(ebony_device_probe); 46machine_device_initcall(ebony, ebony_device_probe);
47 47
48/* 48/*
49 * Called very early, MMU is off, device-tree isn't unflattened 49 * Called very early, MMU is off, device-tree isn't unflattened
@@ -55,6 +55,8 @@ static int __init ebony_probe(void)
55 if (!of_flat_dt_is_compatible(root, "ibm,ebony")) 55 if (!of_flat_dt_is_compatible(root, "ibm,ebony"))
56 return 0; 56 return 0;
57 57
58 ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
59
58 return 1; 60 return 1;
59} 61}
60 62
diff --git a/arch/powerpc/platforms/44x/katmai.c b/arch/powerpc/platforms/44x/katmai.c
new file mode 100644
index 000000000000..11134121f272
--- /dev/null
+++ b/arch/powerpc/platforms/44x/katmai.c
@@ -0,0 +1,63 @@
1/*
2 * Katmai board specific routines
3 *
4 * Benjamin Herrenschmidt <benh@kernel.crashing.org>
5 * Copyright 2007 IBM Corp.
6 *
7 * Based on the Bamboo code by
8 * Josh Boyer <jwboyer@linux.vnet.ibm.com>
9 * Copyright 2007 IBM Corporation
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 */
16#include <linux/init.h>
17#include <linux/of_platform.h>
18
19#include <asm/machdep.h>
20#include <asm/prom.h>
21#include <asm/udbg.h>
22#include <asm/time.h>
23#include <asm/uic.h>
24#include <asm/pci-bridge.h>
25
26#include "44x.h"
27
28static __initdata struct of_device_id katmai_of_bus[] = {
29 { .compatible = "ibm,plb4", },
30 { .compatible = "ibm,opb", },
31 { .compatible = "ibm,ebc", },
32 {},
33};
34
35static int __init katmai_device_probe(void)
36{
37 of_platform_bus_probe(NULL, katmai_of_bus, NULL);
38
39 return 0;
40}
41machine_device_initcall(katmai, katmai_device_probe);
42
43static int __init katmai_probe(void)
44{
45 unsigned long root = of_get_flat_dt_root();
46
47 if (!of_flat_dt_is_compatible(root, "amcc,katmai"))
48 return 0;
49
50 ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
51
52 return 1;
53}
54
55define_machine(katmai) {
56 .name = "Katmai",
57 .probe = katmai_probe,
58 .progress = udbg_progress,
59 .init_IRQ = uic_init_tree,
60 .get_irq = uic_get_irq,
61 .restart = ppc44x_reset_system,
62 .calibrate_decr = generic_calibrate_decr,
63};
diff --git a/arch/powerpc/platforms/44x/rainier.c b/arch/powerpc/platforms/44x/rainier.c
new file mode 100644
index 000000000000..a7fae1cf69c1
--- /dev/null
+++ b/arch/powerpc/platforms/44x/rainier.c
@@ -0,0 +1,62 @@
1/*
2 * Rainier board specific routines
3 *
4 * Valentine Barshak <vbarshak@ru.mvista.com>
5 * Copyright 2007 MontaVista Software Inc.
6 *
7 * Based on the Bamboo code by
8 * Josh Boyer <jwboyer@linux.vnet.ibm.com>
9 * Copyright 2007 IBM Corporation
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 */
16#include <linux/init.h>
17#include <linux/of_platform.h>
18
19#include <asm/machdep.h>
20#include <asm/prom.h>
21#include <asm/udbg.h>
22#include <asm/time.h>
23#include <asm/uic.h>
24#include <asm/pci-bridge.h>
25#include "44x.h"
26
27static __initdata struct of_device_id rainier_of_bus[] = {
28 { .compatible = "ibm,plb4", },
29 { .compatible = "ibm,opb", },
30 { .compatible = "ibm,ebc", },
31 {},
32};
33
34static int __init rainier_device_probe(void)
35{
36 of_platform_bus_probe(NULL, rainier_of_bus, NULL);
37
38 return 0;
39}
40machine_device_initcall(rainier, rainier_device_probe);
41
42static int __init rainier_probe(void)
43{
44 unsigned long root = of_get_flat_dt_root();
45
46 if (!of_flat_dt_is_compatible(root, "amcc,rainier"))
47 return 0;
48
49 ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
50
51 return 1;
52}
53
54define_machine(rainier) {
55 .name = "Rainier",
56 .probe = rainier_probe,
57 .progress = udbg_progress,
58 .init_IRQ = uic_init_tree,
59 .get_irq = uic_get_irq,
60 .restart = ppc44x_reset_system,
61 .calibrate_decr = generic_calibrate_decr,
62};
diff --git a/arch/powerpc/platforms/44x/sequoia.c b/arch/powerpc/platforms/44x/sequoia.c
index 21a9dd14f297..d279db42c896 100644
--- a/arch/powerpc/platforms/44x/sequoia.c
+++ b/arch/powerpc/platforms/44x/sequoia.c
@@ -21,9 +21,11 @@
21#include <asm/udbg.h> 21#include <asm/udbg.h>
22#include <asm/time.h> 22#include <asm/time.h>
23#include <asm/uic.h> 23#include <asm/uic.h>
24#include <asm/pci-bridge.h>
25
24#include "44x.h" 26#include "44x.h"
25 27
26static struct of_device_id sequoia_of_bus[] = { 28static __initdata struct of_device_id sequoia_of_bus[] = {
27 { .compatible = "ibm,plb4", }, 29 { .compatible = "ibm,plb4", },
28 { .compatible = "ibm,opb", }, 30 { .compatible = "ibm,opb", },
29 { .compatible = "ibm,ebc", }, 31 { .compatible = "ibm,ebc", },
@@ -32,14 +34,11 @@ static struct of_device_id sequoia_of_bus[] = {
32 34
33static int __init sequoia_device_probe(void) 35static int __init sequoia_device_probe(void)
34{ 36{
35 if (!machine_is(sequoia))
36 return 0;
37
38 of_platform_bus_probe(NULL, sequoia_of_bus, NULL); 37 of_platform_bus_probe(NULL, sequoia_of_bus, NULL);
39 38
40 return 0; 39 return 0;
41} 40}
42device_initcall(sequoia_device_probe); 41machine_device_initcall(sequoia, sequoia_device_probe);
43 42
44static int __init sequoia_probe(void) 43static int __init sequoia_probe(void)
45{ 44{
@@ -48,6 +47,8 @@ static int __init sequoia_probe(void)
48 if (!of_flat_dt_is_compatible(root, "amcc,sequoia")) 47 if (!of_flat_dt_is_compatible(root, "amcc,sequoia"))
49 return 0; 48 return 0;
50 49
50 ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
51
51 return 1; 52 return 1;
52} 53}
53 54
diff --git a/arch/powerpc/platforms/44x/taishan.c b/arch/powerpc/platforms/44x/taishan.c
new file mode 100644
index 000000000000..28ab7e2e02c3
--- /dev/null
+++ b/arch/powerpc/platforms/44x/taishan.c
@@ -0,0 +1,73 @@
1/*
2 * Taishan board specific routines based off ebony.c code
3 * original copyrights below
4 *
5 * Matt Porter <mporter@kernel.crashing.org>
6 * Copyright 2002-2005 MontaVista Software Inc.
7 *
8 * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
9 * Copyright (c) 2003-2005 Zultys Technologies
10 *
11 * Rewritten and ported to the merged powerpc tree:
12 * Copyright 2007 David Gibson <dwg@au1.ibm.com>, IBM Corporation.
13 *
14 * Modified from ebony.c for taishan:
15 * Copyright 2007 Hugh Blemings <hugh@au.ibm.com>, IBM Corporation.
16 *
17 * This program is free software; you can redistribute it and/or modify it
18 * under the terms of the GNU General Public License as published by the
19 * Free Software Foundation; either version 2 of the License, or (at your
20 * option) any later version.
21 */
22
23#include <linux/init.h>
24#include <linux/of_platform.h>
25
26#include <asm/machdep.h>
27#include <asm/prom.h>
28#include <asm/udbg.h>
29#include <asm/time.h>
30#include <asm/uic.h>
31#include <asm/pci-bridge.h>
32
33#include "44x.h"
34
35static __initdata struct of_device_id taishan_of_bus[] = {
36 { .compatible = "ibm,plb4", },
37 { .compatible = "ibm,opb", },
38 { .compatible = "ibm,ebc", },
39 {},
40};
41
42static int __init taishan_device_probe(void)
43{
44 of_platform_bus_probe(NULL, taishan_of_bus, NULL);
45
46 return 0;
47}
48machine_device_initcall(taishan, taishan_device_probe);
49
50/*
51 * Called very early, MMU is off, device-tree isn't unflattened
52 */
53static int __init taishan_probe(void)
54{
55 unsigned long root = of_get_flat_dt_root();
56
57 if (!of_flat_dt_is_compatible(root, "amcc,taishan"))
58 return 0;
59
60 ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
61
62 return 1;
63}
64
65define_machine(taishan) {
66 .name = "Taishan",
67 .probe = taishan_probe,
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/warp-nand.c b/arch/powerpc/platforms/44x/warp-nand.c
new file mode 100644
index 000000000000..84ab78ff8c03
--- /dev/null
+++ b/arch/powerpc/platforms/44x/warp-nand.c
@@ -0,0 +1,105 @@
1/*
2 * PIKA Warp(tm) NAND flash specific routines
3 *
4 * Copyright (c) 2008 PIKA Technologies
5 * Sean MacLennan <smaclennan@pikatech.com>
6 */
7
8#include <linux/platform_device.h>
9#include <linux/mtd/mtd.h>
10#include <linux/mtd/map.h>
11#include <linux/mtd/partitions.h>
12#include <linux/mtd/nand.h>
13#include <linux/mtd/ndfc.h>
14
15#ifdef CONFIG_MTD_NAND_NDFC
16
17#define CS_NAND_0 1 /* use chip select 1 for NAND device 0 */
18
19#define WARP_NAND_FLASH_REG_ADDR 0xD0000000UL
20#define WARP_NAND_FLASH_REG_SIZE 0x2000
21
22static struct resource warp_ndfc = {
23 .start = WARP_NAND_FLASH_REG_ADDR,
24 .end = WARP_NAND_FLASH_REG_ADDR + WARP_NAND_FLASH_REG_SIZE,
25 .flags = IORESOURCE_MEM,
26};
27
28static struct mtd_partition nand_parts[] = {
29 {
30 .name = "kernel",
31 .offset = 0,
32 .size = 0x0200000
33 },
34 {
35 .name = "root",
36 .offset = 0x0200000,
37 .size = 0x3400000
38 },
39 {
40 .name = "user",
41 .offset = 0x3600000,
42 .size = 0x0A00000
43 },
44};
45
46struct ndfc_controller_settings warp_ndfc_settings = {
47 .ccr_settings = (NDFC_CCR_BS(CS_NAND_0) | NDFC_CCR_ARAC1),
48 .ndfc_erpn = 0,
49};
50
51static struct ndfc_chip_settings warp_chip0_settings = {
52 .bank_settings = 0x80002222,
53};
54
55struct platform_nand_ctrl warp_nand_ctrl = {
56 .priv = &warp_ndfc_settings,
57};
58
59static struct platform_device warp_ndfc_device = {
60 .name = "ndfc-nand",
61 .id = 0,
62 .dev = {
63 .platform_data = &warp_nand_ctrl,
64 },
65 .num_resources = 1,
66 .resource = &warp_ndfc,
67};
68
69static struct nand_ecclayout nand_oob_16 = {
70 .eccbytes = 3,
71 .eccpos = { 0, 1, 2, 3, 6, 7 },
72 .oobfree = { {.offset = 8, .length = 16} }
73};
74
75static struct platform_nand_chip warp_nand_chip0 = {
76 .nr_chips = 1,
77 .chip_offset = CS_NAND_0,
78 .nr_partitions = ARRAY_SIZE(nand_parts),
79 .partitions = nand_parts,
80 .chip_delay = 50,
81 .ecclayout = &nand_oob_16,
82 .priv = &warp_chip0_settings,
83};
84
85static struct platform_device warp_nand_device = {
86 .name = "ndfc-chip",
87 .id = 0,
88 .num_resources = 1,
89 .resource = &warp_ndfc,
90 .dev = {
91 .platform_data = &warp_nand_chip0,
92 .parent = &warp_ndfc_device.dev,
93 }
94};
95
96static int warp_setup_nand_flash(void)
97{
98 platform_device_register(&warp_ndfc_device);
99 platform_device_register(&warp_nand_device);
100
101 return 0;
102}
103device_initcall(warp_setup_nand_flash);
104
105#endif
diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c
new file mode 100644
index 000000000000..8f01563dbd2a
--- /dev/null
+++ b/arch/powerpc/platforms/44x/warp.c
@@ -0,0 +1,153 @@
1/*
2 * PIKA Warp(tm) board specific routines
3 *
4 * Copyright (c) 2008 PIKA Technologies
5 * Sean MacLennan <smaclennan@pikatech.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12#include <linux/init.h>
13#include <linux/of_platform.h>
14#include <linux/kthread.h>
15
16#include <asm/machdep.h>
17#include <asm/prom.h>
18#include <asm/udbg.h>
19#include <asm/time.h>
20#include <asm/uic.h>
21
22#include "44x.h"
23
24
25static __initdata struct of_device_id warp_of_bus[] = {
26 { .compatible = "ibm,plb4", },
27 { .compatible = "ibm,opb", },
28 { .compatible = "ibm,ebc", },
29 {},
30};
31
32static int __init warp_device_probe(void)
33{
34 of_platform_bus_probe(NULL, warp_of_bus, NULL);
35 return 0;
36}
37machine_device_initcall(warp, warp_device_probe);
38
39static int __init warp_probe(void)
40{
41 unsigned long root = of_get_flat_dt_root();
42
43 return of_flat_dt_is_compatible(root, "pika,warp");
44}
45
46define_machine(warp) {
47 .name = "Warp",
48 .probe = warp_probe,
49 .progress = udbg_progress,
50 .init_IRQ = uic_init_tree,
51 .get_irq = uic_get_irq,
52 .restart = ppc44x_reset_system,
53 .calibrate_decr = generic_calibrate_decr,
54};
55
56
57#define LED_GREEN (0x80000000 >> 0)
58#define LED_RED (0x80000000 >> 1)
59
60
61/* This is for the power LEDs 1 = on, 0 = off, -1 = leave alone */
62void warp_set_power_leds(int green, int red)
63{
64 static void __iomem *gpio_base = NULL;
65 unsigned leds;
66
67 if (gpio_base == NULL) {
68 struct device_node *np;
69
70 /* Power LEDS are on the second GPIO controller */
71 np = of_find_compatible_node(NULL, NULL, "ibm,gpio-440EP");
72 if (np)
73 np = of_find_compatible_node(np, NULL, "ibm,gpio-440EP");
74 if (np == NULL) {
75 printk(KERN_ERR __FILE__ ": Unable to find gpio\n");
76 return;
77 }
78
79 gpio_base = of_iomap(np, 0);
80 of_node_put(np);
81 if (gpio_base == NULL) {
82 printk(KERN_ERR __FILE__ ": Unable to map gpio");
83 return;
84 }
85 }
86
87 leds = in_be32(gpio_base);
88
89 switch (green) {
90 case 0: leds &= ~LED_GREEN; break;
91 case 1: leds |= LED_GREEN; break;
92 }
93 switch (red) {
94 case 0: leds &= ~LED_RED; break;
95 case 1: leds |= LED_RED; break;
96 }
97
98 out_be32(gpio_base, leds);
99}
100EXPORT_SYMBOL(warp_set_power_leds);
101
102
103#ifdef CONFIG_SENSORS_AD7414
104static int pika_dtm_thread(void __iomem *fpga)
105{
106 extern int ad7414_get_temp(int index);
107
108 while (!kthread_should_stop()) {
109 int temp = ad7414_get_temp(0);
110
111 out_be32(fpga, temp);
112
113 set_current_state(TASK_INTERRUPTIBLE);
114 schedule_timeout(HZ);
115 }
116
117 return 0;
118}
119
120static int __init pika_dtm_start(void)
121{
122 struct task_struct *dtm_thread;
123 struct device_node *np;
124 struct resource res;
125 void __iomem *fpga;
126
127 np = of_find_compatible_node(NULL, NULL, "pika,fpga");
128 if (np == NULL)
129 return -ENOENT;
130
131 /* We do not call of_iomap here since it would map in the entire
132 * fpga space, which is over 8k.
133 */
134 if (of_address_to_resource(np, 0, &res)) {
135 of_node_put(np);
136 return -ENOENT;
137 }
138 of_node_put(np);
139
140 fpga = ioremap(res.start + 0x20, 4);
141 if (fpga == NULL)
142 return -ENOENT;
143
144 dtm_thread = kthread_run(pika_dtm_thread, fpga + 0x20, "pika-dtm");
145 if (IS_ERR(dtm_thread)) {
146 iounmap(fpga);
147 return PTR_ERR(dtm_thread);
148 }
149
150 return 0;
151}
152device_initcall(pika_dtm_start);
153#endif
diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig
index 2938d4927b83..515f244c90bb 100644
--- a/arch/powerpc/platforms/52xx/Kconfig
+++ b/arch/powerpc/platforms/52xx/Kconfig
@@ -1,38 +1,48 @@
1config PPC_MPC52xx 1config PPC_MPC52xx
2 bool 2 bool "52xx-based boards"
3 depends on PPC_MULTIPLATFORM && PPC32
3 select FSL_SOC 4 select FSL_SOC
4 select PPC_CLOCK 5 select PPC_CLOCK
5 default n
6
7config PPC_MPC5200
8 bool
9 select PPC_MPC52xx
10 default n
11 6
12config PPC_MPC5200_BUGFIX 7config PPC_MPC5200_SIMPLE
13 bool "MPC5200 (L25R) bugfix support" 8 bool "Generic support for simple MPC5200 based boards"
14 depends on PPC_MPC5200 9 depends on PPC_MPC52xx
15 default n 10 select DEFAULT_UIMAGE
11 select WANT_DEVICE_TREE
16 help 12 help
17 Enable workarounds for original MPC5200 errata. This is not required 13 This option enables support for a simple MPC52xx based boards which
18 for MPC5200B based boards. 14 do not need a custom platform specific setup. Such boards are
15 supported assuming the following:
19 16
20 It is safe to say 'Y' here 17 - GPIO pins are configured by the firmware,
18 - CDM configuration (clocking) is setup correctly by firmware,
19 - if the 'fsl,has-wdt' property is present in one of the
20 gpt nodes, then it is safe to use such gpt to reset the board,
21 - PCI is supported if enabled in the kernel configuration
22 and if there is a PCI bus node defined in the device tree.
23
24 Boards that are compatible with this generic platform support
25 are: 'tqc,tqm5200', 'promess,motionpro', 'schindler,cm5200'.
21 26
22config PPC_EFIKA 27config PPC_EFIKA
23 bool "bPlan Efika 5k2. MPC5200B based computer" 28 bool "bPlan Efika 5k2. MPC5200B based computer"
24 depends on PPC_MULTIPLATFORM && PPC32 29 depends on PPC_MPC52xx
25 select PPC_RTAS 30 select PPC_RTAS
26 select RTAS_PROC 31 select RTAS_PROC
27 select PPC_MPC52xx
28 select PPC_NATIVE 32 select PPC_NATIVE
29 default n
30 33
31config PPC_LITE5200 34config PPC_LITE5200
32 bool "Freescale Lite5200 Eval Board" 35 bool "Freescale Lite5200 Eval Board"
33 depends on PPC_MULTIPLATFORM && PPC32 36 depends on PPC_MPC52xx
37 select DEFAULT_UIMAGE
34 select WANT_DEVICE_TREE 38 select WANT_DEVICE_TREE
35 select PPC_MPC5200
36 default n
37 39
40config PPC_MPC5200_BUGFIX
41 bool "MPC5200 (L25R) bugfix support"
42 depends on PPC_MPC52xx
43 help
44 Enable workarounds for original MPC5200 errata. This is not required
45 for MPC5200B based boards.
46
47 It is safe to say 'Y' here
38 48
diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile
index 307dbc178091..fe1b81bb5224 100644
--- a/arch/powerpc/platforms/52xx/Makefile
+++ b/arch/powerpc/platforms/52xx/Makefile
@@ -6,6 +6,7 @@ obj-y += mpc52xx_pic.o mpc52xx_common.o
6obj-$(CONFIG_PCI) += mpc52xx_pci.o 6obj-$(CONFIG_PCI) += mpc52xx_pci.o
7endif 7endif
8 8
9obj-$(CONFIG_PPC_MPC5200_SIMPLE) += mpc5200_simple.o
9obj-$(CONFIG_PPC_EFIKA) += efika.o 10obj-$(CONFIG_PPC_EFIKA) += efika.o
10obj-$(CONFIG_PPC_LITE5200) += lite5200.o 11obj-$(CONFIG_PPC_LITE5200) += lite5200.o
11 12
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c
index a0da70c8b502..a2068faef6ea 100644
--- a/arch/powerpc/platforms/52xx/efika.c
+++ b/arch/powerpc/platforms/52xx/efika.c
@@ -180,6 +180,9 @@ static void __init efika_setup_arch(void)
180{ 180{
181 rtas_initialize(); 181 rtas_initialize();
182 182
183 /* Map important registers from the internal memory map */
184 mpc52xx_map_common_devices();
185
183 efika_pcisetup(); 186 efika_pcisetup();
184 187
185#ifdef CONFIG_PM 188#ifdef CONFIG_PM
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
index 25d2bfa3d9dc..956f459e175c 100644
--- a/arch/powerpc/platforms/52xx/lite5200.c
+++ b/arch/powerpc/platforms/52xx/lite5200.c
@@ -32,6 +32,19 @@
32 * 32 *
33 */ 33 */
34 34
35/* mpc5200 device tree match tables */
36static struct of_device_id mpc5200_cdm_ids[] __initdata = {
37 { .compatible = "fsl,mpc5200-cdm", },
38 { .compatible = "mpc5200-cdm", },
39 {}
40};
41
42static struct of_device_id mpc5200_gpio_ids[] __initdata = {
43 { .compatible = "fsl,mpc5200-gpio", },
44 { .compatible = "mpc5200-gpio", },
45 {}
46};
47
35/* 48/*
36 * Fix clock configuration. 49 * Fix clock configuration.
37 * 50 *
@@ -42,10 +55,12 @@
42static void __init 55static void __init
43lite5200_fix_clock_config(void) 56lite5200_fix_clock_config(void)
44{ 57{
58 struct device_node *np;
45 struct mpc52xx_cdm __iomem *cdm; 59 struct mpc52xx_cdm __iomem *cdm;
46
47 /* Map zones */ 60 /* Map zones */
48 cdm = mpc52xx_find_and_map("mpc5200-cdm"); 61 np = of_find_matching_node(NULL, mpc5200_cdm_ids);
62 cdm = of_iomap(np, 0);
63 of_node_put(np);
49 if (!cdm) { 64 if (!cdm) {
50 printk(KERN_ERR "%s() failed; expect abnormal behaviour\n", 65 printk(KERN_ERR "%s() failed; expect abnormal behaviour\n",
51 __FUNCTION__); 66 __FUNCTION__);
@@ -74,10 +89,13 @@ lite5200_fix_clock_config(void)
74static void __init 89static void __init
75lite5200_fix_port_config(void) 90lite5200_fix_port_config(void)
76{ 91{
92 struct device_node *np;
77 struct mpc52xx_gpio __iomem *gpio; 93 struct mpc52xx_gpio __iomem *gpio;
78 u32 port_config; 94 u32 port_config;
79 95
80 gpio = mpc52xx_find_and_map("mpc5200-gpio"); 96 np = of_find_matching_node(NULL, mpc5200_gpio_ids);
97 gpio = of_iomap(np, 0);
98 of_node_put(np);
81 if (!gpio) { 99 if (!gpio) {
82 printk(KERN_ERR "%s() failed. expect abnormal behavior\n", 100 printk(KERN_ERR "%s() failed. expect abnormal behavior\n",
83 __FUNCTION__); 101 __FUNCTION__);
@@ -131,22 +149,18 @@ static void lite5200_resume_finish(void __iomem *mbar)
131 149
132static void __init lite5200_setup_arch(void) 150static void __init lite5200_setup_arch(void)
133{ 151{
134#ifdef CONFIG_PCI
135 struct device_node *np;
136#endif
137
138 if (ppc_md.progress) 152 if (ppc_md.progress)
139 ppc_md.progress("lite5200_setup_arch()", 0); 153 ppc_md.progress("lite5200_setup_arch()", 0);
140 154
141 /* Fix things that firmware should have done. */ 155 /* Map important registers from the internal memory map */
142 lite5200_fix_clock_config(); 156 mpc52xx_map_common_devices();
143 lite5200_fix_port_config();
144 157
145 /* Some mpc5200 & mpc5200b related configuration */ 158 /* Some mpc5200 & mpc5200b related configuration */
146 mpc5200_setup_xlb_arbiter(); 159 mpc5200_setup_xlb_arbiter();
147 160
148 /* Map wdt for mpc52xx_restart() */ 161 /* Fix things that firmware should have done. */
149 mpc52xx_map_wdt(); 162 lite5200_fix_clock_config();
163 lite5200_fix_port_config();
150 164
151#ifdef CONFIG_PM 165#ifdef CONFIG_PM
152 mpc52xx_suspend.board_suspend_prepare = lite5200_suspend_prepare; 166 mpc52xx_suspend.board_suspend_prepare = lite5200_suspend_prepare;
@@ -154,13 +168,7 @@ static void __init lite5200_setup_arch(void)
154 lite5200_pm_init(); 168 lite5200_pm_init();
155#endif 169#endif
156 170
157#ifdef CONFIG_PCI 171 mpc52xx_setup_pci();
158 np = of_find_node_by_type(NULL, "pci");
159 if (np) {
160 mpc52xx_add_bridge(np);
161 of_node_put(np);
162 }
163#endif
164} 172}
165 173
166/* 174/*
diff --git a/arch/powerpc/platforms/52xx/lite5200_pm.c b/arch/powerpc/platforms/52xx/lite5200_pm.c
index ffa14aff5248..c0f13e8deb0b 100644
--- a/arch/powerpc/platforms/52xx/lite5200_pm.c
+++ b/arch/powerpc/platforms/52xx/lite5200_pm.c
@@ -42,6 +42,15 @@ static int lite5200_pm_set_target(suspend_state_t state)
42 42
43static int lite5200_pm_prepare(void) 43static int lite5200_pm_prepare(void)
44{ 44{
45 struct device_node *np;
46 const struct of_device_id immr_ids[] = {
47 { .compatible = "fsl,mpc5200-immr", },
48 { .compatible = "fsl,mpc5200b-immr", },
49 { .type = "soc", .compatible = "mpc5200", }, /* lite5200 */
50 { .type = "builtin", .compatible = "mpc5200", }, /* efika */
51 {}
52 };
53
45 /* deep sleep? let mpc52xx code handle that */ 54 /* deep sleep? let mpc52xx code handle that */
46 if (lite5200_pm_target_state == PM_SUSPEND_STANDBY) 55 if (lite5200_pm_target_state == PM_SUSPEND_STANDBY)
47 return mpc52xx_pm_prepare(); 56 return mpc52xx_pm_prepare();
@@ -50,7 +59,9 @@ static int lite5200_pm_prepare(void)
50 return -EINVAL; 59 return -EINVAL;
51 60
52 /* map registers */ 61 /* map registers */
53 mbar = mpc52xx_find_and_map("mpc5200"); 62 np = of_find_matching_node(NULL, immr_ids);
63 mbar = of_iomap(np, 0);
64 of_node_put(np);
54 if (!mbar) { 65 if (!mbar) {
55 printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__); 66 printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__);
56 return -ENOSYS; 67 return -ENOSYS;
diff --git a/arch/powerpc/platforms/52xx/mpc5200_simple.c b/arch/powerpc/platforms/52xx/mpc5200_simple.c
new file mode 100644
index 000000000000..c48b82bc2aad
--- /dev/null
+++ b/arch/powerpc/platforms/52xx/mpc5200_simple.c
@@ -0,0 +1,85 @@
1/*
2 * Support for 'mpc5200-simple-platform' compatible boards.
3 *
4 * Written by Marian Balakowicz <m8@semihalf.com>
5 * Copyright (C) 2007 Semihalf
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 * Description:
13 * This code implements support for a simple MPC52xx based boards which
14 * do not need a custom platform specific setup. Such boards are
15 * supported assuming the following:
16 *
17 * - GPIO pins are configured by the firmware,
18 * - CDM configuration (clocking) is setup correctly by firmware,
19 * - if the 'fsl,has-wdt' property is present in one of the
20 * gpt nodes, then it is safe to use such gpt to reset the board,
21 * - PCI is supported if enabled in the kernel configuration
22 * and if there is a PCI bus node defined in the device tree.
23 *
24 * Boards that are compatible with this generic platform support
25 * are listed in a 'board' table.
26 */
27
28#undef DEBUG
29#include <asm/time.h>
30#include <asm/prom.h>
31#include <asm/machdep.h>
32#include <asm/mpc52xx.h>
33
34/*
35 * Setup the architecture
36 */
37static void __init mpc5200_simple_setup_arch(void)
38{
39 if (ppc_md.progress)
40 ppc_md.progress("mpc5200_simple_setup_arch()", 0);
41
42 /* Map important registers from the internal memory map */
43 mpc52xx_map_common_devices();
44
45 /* Some mpc5200 & mpc5200b related configuration */
46 mpc5200_setup_xlb_arbiter();
47
48 mpc52xx_setup_pci();
49}
50
51/* list of the supported boards */
52static char *board[] __initdata = {
53 "promess,motionpro",
54 "schindler,cm5200",
55 "tqc,tqm5200",
56 NULL
57};
58
59/*
60 * Called very early, MMU is off, device-tree isn't unflattened
61 */
62static int __init mpc5200_simple_probe(void)
63{
64 unsigned long node = of_get_flat_dt_root();
65 int i = 0;
66
67 while (board[i]) {
68 if (of_flat_dt_is_compatible(node, board[i]))
69 break;
70 i++;
71 }
72
73 return (board[i] != NULL);
74}
75
76define_machine(mpc5200_simple_platform) {
77 .name = "mpc5200-simple-platform",
78 .probe = mpc5200_simple_probe,
79 .setup_arch = mpc5200_simple_setup_arch,
80 .init = mpc52xx_declare_of_platform_devices,
81 .init_IRQ = mpc52xx_init_irq,
82 .get_irq = mpc52xx_get_irq,
83 .restart = mpc52xx_restart,
84 .calibrate_decr = generic_calibrate_decr,
85};
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c
index 9850685c5429..9aa4425d80b2 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_common.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c
@@ -13,57 +13,38 @@
13#undef DEBUG 13#undef DEBUG
14 14
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <linux/spinlock.h>
16#include <linux/of_platform.h> 17#include <linux/of_platform.h>
17#include <asm/io.h> 18#include <asm/io.h>
18#include <asm/prom.h> 19#include <asm/prom.h>
19#include <asm/mpc52xx.h> 20#include <asm/mpc52xx.h>
20 21
22/* MPC5200 device tree match tables */
23static struct of_device_id mpc52xx_xlb_ids[] __initdata = {
24 { .compatible = "fsl,mpc5200-xlb", },
25 { .compatible = "mpc5200-xlb", },
26 {}
27};
28static struct of_device_id mpc52xx_bus_ids[] __initdata = {
29 { .compatible = "fsl,mpc5200-immr", },
30 { .compatible = "fsl,mpc5200b-immr", },
31 { .compatible = "fsl,lpb", },
32
33 /* depreciated matches; shouldn't be used in new device trees */
34 { .type = "builtin", .compatible = "mpc5200", }, /* efika */
35 { .type = "soc", .compatible = "mpc5200", }, /* lite5200 */
36 {}
37};
38
21/* 39/*
22 * This variable is mapped in mpc52xx_map_wdt() and used in mpc52xx_restart(). 40 * This variable is mapped in mpc52xx_map_wdt() and used in mpc52xx_restart().
23 * Permanent mapping is required because mpc52xx_restart() can be called 41 * Permanent mapping is required because mpc52xx_restart() can be called
24 * from interrupt context while node mapping (which calls ioremap()) 42 * from interrupt context while node mapping (which calls ioremap())
25 * cannot be used at such point. 43 * cannot be used at such point.
26 */ 44 */
27static volatile struct mpc52xx_gpt *mpc52xx_wdt = NULL; 45static spinlock_t mpc52xx_lock = SPIN_LOCK_UNLOCKED;
28 46static struct mpc52xx_gpt __iomem *mpc52xx_wdt;
29static void __iomem * 47static struct mpc52xx_cdm __iomem *mpc52xx_cdm;
30mpc52xx_map_node(struct device_node *ofn)
31{
32 const u32 *regaddr_p;
33 u64 regaddr64, size64;
34
35 if (!ofn)
36 return NULL;
37
38 regaddr_p = of_get_address(ofn, 0, &size64, NULL);
39 if (!regaddr_p) {
40 of_node_put(ofn);
41 return NULL;
42 }
43
44 regaddr64 = of_translate_address(ofn, regaddr_p);
45
46 of_node_put(ofn);
47
48 return ioremap((u32)regaddr64, (u32)size64);
49}
50
51void __iomem *
52mpc52xx_find_and_map(const char *compatible)
53{
54 return mpc52xx_map_node(
55 of_find_compatible_node(NULL, NULL, compatible));
56}
57
58EXPORT_SYMBOL(mpc52xx_find_and_map);
59
60void __iomem *
61mpc52xx_find_and_map_path(const char *path)
62{
63 return mpc52xx_map_node(of_find_node_by_path(path));
64}
65
66EXPORT_SYMBOL(mpc52xx_find_and_map_path);
67 48
68/** 49/**
69 * mpc52xx_find_ipb_freq - Find the IPB bus frequency for a device 50 * mpc52xx_find_ipb_freq - Find the IPB bus frequency for a device
@@ -101,9 +82,12 @@ EXPORT_SYMBOL(mpc52xx_find_ipb_freq);
101void __init 82void __init
102mpc5200_setup_xlb_arbiter(void) 83mpc5200_setup_xlb_arbiter(void)
103{ 84{
85 struct device_node *np;
104 struct mpc52xx_xlb __iomem *xlb; 86 struct mpc52xx_xlb __iomem *xlb;
105 87
106 xlb = mpc52xx_find_and_map("mpc5200-xlb"); 88 np = of_find_matching_node(NULL, mpc52xx_xlb_ids);
89 xlb = of_iomap(np, 0);
90 of_node_put(np);
107 if (!xlb) { 91 if (!xlb) {
108 printk(KERN_ERR __FILE__ ": " 92 printk(KERN_ERR __FILE__ ": "
109 "Error mapping XLB in mpc52xx_setup_cpu(). " 93 "Error mapping XLB in mpc52xx_setup_cpu(). "
@@ -124,41 +108,101 @@ mpc5200_setup_xlb_arbiter(void)
124 iounmap(xlb); 108 iounmap(xlb);
125} 109}
126 110
111/**
112 * mpc52xx_declare_of_platform_devices: register internal devices and children
113 * of the localplus bus to the of_platform
114 * bus.
115 */
127void __init 116void __init
128mpc52xx_declare_of_platform_devices(void) 117mpc52xx_declare_of_platform_devices(void)
129{ 118{
130 /* Find every child of the SOC node and add it to of_platform */ 119 /* Find every child of the SOC node and add it to of_platform */
131 if (of_platform_bus_probe(NULL, NULL, NULL)) 120 if (of_platform_bus_probe(NULL, mpc52xx_bus_ids, NULL))
132 printk(KERN_ERR __FILE__ ": " 121 printk(KERN_ERR __FILE__ ": "
133 "Error while probing of_platform bus\n"); 122 "Error while probing of_platform bus\n");
134} 123}
135 124
125/*
126 * match tables used by mpc52xx_map_common_devices()
127 */
128static struct of_device_id mpc52xx_gpt_ids[] __initdata = {
129 { .compatible = "fsl,mpc5200-gpt", },
130 { .compatible = "mpc5200-gpt", }, /* old */
131 {}
132};
133static struct of_device_id mpc52xx_cdm_ids[] __initdata = {
134 { .compatible = "fsl,mpc5200-cdm", },
135 { .compatible = "mpc5200-cdm", }, /* old */
136 {}
137};
138
139/**
140 * mpc52xx_map_common_devices: iomap devices required by common code
141 */
136void __init 142void __init
137mpc52xx_map_wdt(void) 143mpc52xx_map_common_devices(void)
138{ 144{
139 const void *has_wdt;
140 struct device_node *np; 145 struct device_node *np;
141 146
142 /* mpc52xx_wdt is mapped here and used in mpc52xx_restart, 147 /* mpc52xx_wdt is mapped here and used in mpc52xx_restart,
143 * possibly from a interrupt context. wdt is only implement 148 * possibly from a interrupt context. wdt is only implement
144 * on a gpt0, so check has-wdt property before mapping. 149 * on a gpt0, so check has-wdt property before mapping.
145 */ 150 */
146 for_each_compatible_node(np, NULL, "fsl,mpc5200-gpt") { 151 for_each_matching_node(np, mpc52xx_gpt_ids) {
147 has_wdt = of_get_property(np, "fsl,has-wdt", NULL); 152 if (of_get_property(np, "fsl,has-wdt", NULL) ||
148 if (has_wdt) { 153 of_get_property(np, "has-wdt", NULL)) {
149 mpc52xx_wdt = mpc52xx_map_node(np); 154 mpc52xx_wdt = of_iomap(np, 0);
150 return; 155 of_node_put(np);
156 break;
151 } 157 }
152 } 158 }
153 for_each_compatible_node(np, NULL, "mpc5200-gpt") { 159
154 has_wdt = of_get_property(np, "has-wdt", NULL); 160 /* Clock Distribution Module, used by PSC clock setting function */
155 if (has_wdt) { 161 np = of_find_matching_node(NULL, mpc52xx_cdm_ids);
156 mpc52xx_wdt = mpc52xx_map_node(np); 162 mpc52xx_cdm = of_iomap(np, 0);
157 return; 163 of_node_put(np);
158 } 164}
165
166/**
167 * mpc52xx_set_psc_clkdiv: Set clock divider in the CDM for PSC ports
168 *
169 * @psc_id: id of psc port; must be 1,2,3 or 6
170 * @clkdiv: clock divider value to put into CDM PSC register.
171 */
172int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv)
173{
174 unsigned long flags;
175 u16 __iomem *reg;
176 u32 val;
177 u32 mask;
178 u32 mclken_div;
179
180 if (!mpc52xx_cdm)
181 return -ENODEV;
182
183 mclken_div = 0x8000 | (clkdiv & 0x1FF);
184 switch (psc_id) {
185 case 1: reg = &mpc52xx_cdm->mclken_div_psc1; mask = 0x20; break;
186 case 2: reg = &mpc52xx_cdm->mclken_div_psc2; mask = 0x40; break;
187 case 3: reg = &mpc52xx_cdm->mclken_div_psc3; mask = 0x80; break;
188 case 6: reg = &mpc52xx_cdm->mclken_div_psc6; mask = 0x10; break;
189 default:
190 return -ENODEV;
159 } 191 }
192
193 /* Set the rate and enable the clock */
194 spin_lock_irqsave(&mpc52xx_lock, flags);
195 out_be16(reg, mclken_div);
196 val = in_be32(&mpc52xx_cdm->clk_enables);
197 out_be32(&mpc52xx_cdm->clk_enables, val | mask);
198 spin_unlock_irqrestore(&mpc52xx_lock, flags);
199
200 return 0;
160} 201}
161 202
203/**
204 * mpc52xx_restart: ppc_md->restart hook for mpc5200 using the watchdog timer
205 */
162void 206void
163mpc52xx_restart(char *cmd) 207mpc52xx_restart(char *cmd)
164{ 208{
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
index 4c6c82a684b1..e3428ddd9040 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
@@ -99,6 +99,12 @@ struct mpc52xx_pci {
99 u8 reserved6[4]; /* PCI + 0xFC */ 99 u8 reserved6[4]; /* PCI + 0xFC */
100}; 100};
101 101
102/* MPC5200 device tree match tables */
103const struct of_device_id mpc52xx_pci_ids[] __initdata = {
104 { .type = "pci", .compatible = "fsl,mpc5200-pci", },
105 { .type = "pci", .compatible = "mpc5200-pci", },
106 {}
107};
102 108
103/* ======================================================================== */ 109/* ======================================================================== */
104/* PCI configuration acess */ 110/* PCI configuration acess */
@@ -363,7 +369,7 @@ mpc52xx_add_bridge(struct device_node *node)
363 369
364 pr_debug("Adding MPC52xx PCI host bridge %s\n", node->full_name); 370 pr_debug("Adding MPC52xx PCI host bridge %s\n", node->full_name);
365 371
366 pci_assign_all_buses = 1; 372 ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
367 373
368 if (of_address_to_resource(node, 0, &rsrc) != 0) { 374 if (of_address_to_resource(node, 0, &rsrc) != 0) {
369 printk(KERN_ERR "Can't get %s resources\n", node->full_name); 375 printk(KERN_ERR "Can't get %s resources\n", node->full_name);
@@ -406,3 +412,15 @@ mpc52xx_add_bridge(struct device_node *node)
406 412
407 return 0; 413 return 0;
408} 414}
415
416void __init mpc52xx_setup_pci(void)
417{
418 struct device_node *pci;
419
420 pci = of_find_matching_node(NULL, mpc52xx_pci_ids);
421 if (!pci)
422 return;
423
424 mpc52xx_add_bridge(pci);
425 of_node_put(pci);
426}
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
index 61100f270c68..d0dead8b9a95 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
@@ -29,6 +29,18 @@
29 * 29 *
30*/ 30*/
31 31
32/* MPC5200 device tree match tables */
33static struct of_device_id mpc52xx_pic_ids[] __initdata = {
34 { .compatible = "fsl,mpc5200-pic", },
35 { .compatible = "mpc5200-pic", },
36 {}
37};
38static struct of_device_id mpc52xx_sdma_ids[] __initdata = {
39 { .compatible = "fsl,mpc5200-bestcomm", },
40 { .compatible = "mpc5200-bestcomm", },
41 {}
42};
43
32static struct mpc52xx_intr __iomem *intr; 44static struct mpc52xx_intr __iomem *intr;
33static struct mpc52xx_sdma __iomem *sdma; 45static struct mpc52xx_sdma __iomem *sdma;
34static struct irq_host *mpc52xx_irqhost = NULL; 46static struct irq_host *mpc52xx_irqhost = NULL;
@@ -364,16 +376,18 @@ void __init mpc52xx_init_irq(void)
364{ 376{
365 u32 intr_ctrl; 377 u32 intr_ctrl;
366 struct device_node *picnode; 378 struct device_node *picnode;
379 struct device_node *np;
367 380
368 /* Remap the necessary zones */ 381 /* Remap the necessary zones */
369 picnode = of_find_compatible_node(NULL, NULL, "mpc5200-pic"); 382 picnode = of_find_matching_node(NULL, mpc52xx_pic_ids);
370 383 intr = of_iomap(picnode, 0);
371 intr = mpc52xx_find_and_map("mpc5200-pic");
372 if (!intr) 384 if (!intr)
373 panic(__FILE__ ": find_and_map failed on 'mpc5200-pic'. " 385 panic(__FILE__ ": find_and_map failed on 'mpc5200-pic'. "
374 "Check node !"); 386 "Check node !");
375 387
376 sdma = mpc52xx_find_and_map("mpc5200-bestcomm"); 388 np = of_find_matching_node(NULL, mpc52xx_sdma_ids);
389 sdma = of_iomap(np, 0);
390 of_node_put(np);
377 if (!sdma) 391 if (!sdma)
378 panic(__FILE__ ": find_and_map failed on 'mpc5200-bestcomm'. " 392 panic(__FILE__ ": find_and_map failed on 'mpc5200-bestcomm'. "
379 "Check node !"); 393 "Check node !");
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pm.c b/arch/powerpc/platforms/52xx/mpc52xx_pm.c
index 7ffa7babf254..c72d3304387f 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pm.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pm.c
@@ -59,10 +59,21 @@ int mpc52xx_set_wakeup_gpio(u8 pin, u8 level)
59 59
60int mpc52xx_pm_prepare(void) 60int mpc52xx_pm_prepare(void)
61{ 61{
62 struct device_node *np;
63 const struct of_device_id immr_ids[] = {
64 { .compatible = "fsl,mpc5200-immr", },
65 { .compatible = "fsl,mpc5200b-immr", },
66 { .type = "soc", .compatible = "mpc5200", }, /* lite5200 */
67 { .type = "builtin", .compatible = "mpc5200", }, /* efika */
68 {}
69 };
70
62 /* map the whole register space */ 71 /* map the whole register space */
63 mbar = mpc52xx_find_and_map("mpc5200"); 72 np = of_find_matching_node(NULL, immr_ids);
73 mbar = of_iomap(np, 0);
74 of_node_put(np);
64 if (!mbar) { 75 if (!mbar) {
65 printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__); 76 pr_err("mpc52xx_pm_prepare(): could not map registers\n");
66 return -ENOSYS; 77 return -ENOSYS;
67 } 78 }
68 /* these offsets are from mpc5200 users manual */ 79 /* these offsets are from mpc5200 users manual */
diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig
index 541fbb815631..4fad6c7bf9f1 100644
--- a/arch/powerpc/platforms/82xx/Kconfig
+++ b/arch/powerpc/platforms/82xx/Kconfig
@@ -26,6 +26,19 @@ config PQ2FADS
26 help 26 help
27 This option enables support for the PQ2FADS board 27 This option enables support for the PQ2FADS board
28 28
29config EP8248E
30 bool "Embedded Planet EP8248E (a.k.a. CWH-PPC-8248N-VE)"
31 select 8272
32 select 8260
33 select FSL_SOC
34 select PPC_CPM_NEW_BINDING
35 select MDIO_BITBANG
36 help
37 This enables support for the Embedded Planet EP8248E board.
38
39 This board is also resold by Freescale as the QUICCStart
40 MPC8248 Evaluation System and/or the CWH-PPC-8248N-VE.
41
29endchoice 42endchoice
30 43
31config PQ2ADS 44config PQ2ADS
diff --git a/arch/powerpc/platforms/82xx/Makefile b/arch/powerpc/platforms/82xx/Makefile
index 68c8b0c9772b..6cd5cd59bf2a 100644
--- a/arch/powerpc/platforms/82xx/Makefile
+++ b/arch/powerpc/platforms/82xx/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_MPC8272_ADS) += mpc8272_ads.o
5obj-$(CONFIG_CPM2) += pq2.o 5obj-$(CONFIG_CPM2) += pq2.o
6obj-$(CONFIG_PQ2_ADS_PCI_PIC) += pq2ads-pci-pic.o 6obj-$(CONFIG_PQ2_ADS_PCI_PIC) += pq2ads-pci-pic.o
7obj-$(CONFIG_PQ2FADS) += pq2fads.o 7obj-$(CONFIG_PQ2FADS) += pq2fads.o
8obj-$(CONFIG_EP8248E) += ep8248e.o
diff --git a/arch/powerpc/platforms/82xx/ep8248e.c b/arch/powerpc/platforms/82xx/ep8248e.c
new file mode 100644
index 000000000000..ba93d8ae9b0c
--- /dev/null
+++ b/arch/powerpc/platforms/82xx/ep8248e.c
@@ -0,0 +1,324 @@
1/*
2 * Embedded Planet EP8248E support
3 *
4 * Copyright 2007 Freescale Semiconductor, Inc.
5 * Author: Scott Wood <scottwood@freescale.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/init.h>
14#include <linux/interrupt.h>
15#include <linux/fsl_devices.h>
16#include <linux/mdio-bitbang.h>
17#include <linux/of_platform.h>
18
19#include <asm/io.h>
20#include <asm/cpm2.h>
21#include <asm/udbg.h>
22#include <asm/machdep.h>
23#include <asm/time.h>
24#include <asm/mpc8260.h>
25#include <asm/prom.h>
26
27#include <sysdev/fsl_soc.h>
28#include <sysdev/cpm2_pic.h>
29
30#include "pq2.h"
31
32static u8 __iomem *ep8248e_bcsr;
33static struct device_node *ep8248e_bcsr_node;
34
35#define BCSR7_SCC2_ENABLE 0x10
36
37#define BCSR8_PHY1_ENABLE 0x80
38#define BCSR8_PHY1_POWER 0x40
39#define BCSR8_PHY2_ENABLE 0x20
40#define BCSR8_PHY2_POWER 0x10
41#define BCSR8_MDIO_READ 0x04
42#define BCSR8_MDIO_CLOCK 0x02
43#define BCSR8_MDIO_DATA 0x01
44
45#define BCSR9_USB_ENABLE 0x80
46#define BCSR9_USB_POWER 0x40
47#define BCSR9_USB_HOST 0x20
48#define BCSR9_USB_FULL_SPEED_TARGET 0x10
49
50static void __init ep8248e_pic_init(void)
51{
52 struct device_node *np = of_find_compatible_node(NULL, NULL, "fsl,pq2-pic");
53 if (!np) {
54 printk(KERN_ERR "PIC init: can not find cpm-pic node\n");
55 return;
56 }
57
58 cpm2_pic_init(np);
59 of_node_put(np);
60}
61
62static void ep8248e_set_mdc(struct mdiobb_ctrl *ctrl, int level)
63{
64 if (level)
65 setbits8(&ep8248e_bcsr[8], BCSR8_MDIO_CLOCK);
66 else
67 clrbits8(&ep8248e_bcsr[8], BCSR8_MDIO_CLOCK);
68
69 /* Read back to flush the write. */
70 in_8(&ep8248e_bcsr[8]);
71}
72
73static void ep8248e_set_mdio_dir(struct mdiobb_ctrl *ctrl, int output)
74{
75 if (output)
76 clrbits8(&ep8248e_bcsr[8], BCSR8_MDIO_READ);
77 else
78 setbits8(&ep8248e_bcsr[8], BCSR8_MDIO_READ);
79
80 /* Read back to flush the write. */
81 in_8(&ep8248e_bcsr[8]);
82}
83
84static void ep8248e_set_mdio_data(struct mdiobb_ctrl *ctrl, int data)
85{
86 if (data)
87 setbits8(&ep8248e_bcsr[8], BCSR8_MDIO_DATA);
88 else
89 clrbits8(&ep8248e_bcsr[8], BCSR8_MDIO_DATA);
90
91 /* Read back to flush the write. */
92 in_8(&ep8248e_bcsr[8]);
93}
94
95static int ep8248e_get_mdio_data(struct mdiobb_ctrl *ctrl)
96{
97 return in_8(&ep8248e_bcsr[8]) & BCSR8_MDIO_DATA;
98}
99
100static const struct mdiobb_ops ep8248e_mdio_ops = {
101 .set_mdc = ep8248e_set_mdc,
102 .set_mdio_dir = ep8248e_set_mdio_dir,
103 .set_mdio_data = ep8248e_set_mdio_data,
104 .get_mdio_data = ep8248e_get_mdio_data,
105 .owner = THIS_MODULE,
106};
107
108static struct mdiobb_ctrl ep8248e_mdio_ctrl = {
109 .ops = &ep8248e_mdio_ops,
110};
111
112static int __devinit ep8248e_mdio_probe(struct of_device *ofdev,
113 const struct of_device_id *match)
114{
115 struct mii_bus *bus;
116 struct resource res;
117 struct device_node *node;
118 int ret, i;
119
120 node = of_get_parent(ofdev->node);
121 of_node_put(node);
122 if (node != ep8248e_bcsr_node)
123 return -ENODEV;
124
125 ret = of_address_to_resource(ofdev->node, 0, &res);
126 if (ret)
127 return ret;
128
129 bus = alloc_mdio_bitbang(&ep8248e_mdio_ctrl);
130 if (!bus)
131 return -ENOMEM;
132
133 bus->phy_mask = 0;
134 bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
135
136 for (i = 0; i < PHY_MAX_ADDR; i++)
137 bus->irq[i] = -1;
138
139 bus->name = "ep8248e-mdio-bitbang";
140 bus->dev = &ofdev->dev;
141 bus->id = res.start;
142
143 return mdiobus_register(bus);
144}
145
146static int ep8248e_mdio_remove(struct of_device *ofdev)
147{
148 BUG();
149 return 0;
150}
151
152static const struct of_device_id ep8248e_mdio_match[] = {
153 {
154 .compatible = "fsl,ep8248e-mdio-bitbang",
155 },
156 {},
157};
158
159static struct of_platform_driver ep8248e_mdio_driver = {
160 .driver = {
161 .name = "ep8248e-mdio-bitbang",
162 },
163 .match_table = ep8248e_mdio_match,
164 .probe = ep8248e_mdio_probe,
165 .remove = ep8248e_mdio_remove,
166};
167
168struct cpm_pin {
169 int port, pin, flags;
170};
171
172static __initdata struct cpm_pin ep8248e_pins[] = {
173 /* SMC1 */
174 {2, 4, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
175 {2, 5, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
176
177 /* SCC1 */
178 {2, 14, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
179 {2, 15, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
180 {3, 29, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
181 {3, 30, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
182 {3, 31, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
183
184 /* FCC1 */
185 {0, 14, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
186 {0, 15, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
187 {0, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
188 {0, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
189 {0, 18, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
190 {0, 19, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
191 {0, 20, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
192 {0, 21, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
193 {0, 26, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
194 {0, 27, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
195 {0, 28, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
196 {0, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
197 {0, 30, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
198 {0, 31, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
199 {2, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
200 {2, 22, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
201
202 /* FCC2 */
203 {1, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
204 {1, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
205 {1, 20, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
206 {1, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
207 {1, 22, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
208 {1, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
209 {1, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
210 {1, 25, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
211 {1, 26, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
212 {1, 27, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
213 {1, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
214 {1, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
215 {1, 30, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
216 {1, 31, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
217 {2, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
218 {2, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
219
220 /* I2C */
221 {4, 14, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
222 {4, 15, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
223
224 /* USB */
225 {2, 10, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
226 {2, 11, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
227 {2, 20, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
228 {2, 24, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
229 {3, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
230 {3, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
231 {3, 25, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
232};
233
234static void __init init_ioports(void)
235{
236 int i;
237
238 for (i = 0; i < ARRAY_SIZE(ep8248e_pins); i++) {
239 const struct cpm_pin *pin = &ep8248e_pins[i];
240 cpm2_set_pin(pin->port, pin->pin, pin->flags);
241 }
242
243 cpm2_smc_clk_setup(CPM_CLK_SMC1, CPM_BRG7);
244 cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_RX);
245 cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_TX);
246 cpm2_clk_setup(CPM_CLK_SCC3, CPM_CLK8, CPM_CLK_TX); /* USB */
247 cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK11, CPM_CLK_RX);
248 cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK10, CPM_CLK_TX);
249 cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK13, CPM_CLK_RX);
250 cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK14, CPM_CLK_TX);
251}
252
253static void __init ep8248e_setup_arch(void)
254{
255 if (ppc_md.progress)
256 ppc_md.progress("ep8248e_setup_arch()", 0);
257
258 cpm2_reset();
259
260 /* When this is set, snooping CPM DMA from RAM causes
261 * machine checks. See erratum SIU18.
262 */
263 clrbits32(&cpm2_immr->im_siu_conf.siu_82xx.sc_bcr, MPC82XX_BCR_PLDP);
264
265 ep8248e_bcsr_node =
266 of_find_compatible_node(NULL, NULL, "fsl,ep8248e-bcsr");
267 if (!ep8248e_bcsr_node) {
268 printk(KERN_ERR "No bcsr in device tree\n");
269 return;
270 }
271
272 ep8248e_bcsr = of_iomap(ep8248e_bcsr_node, 0);
273 if (!ep8248e_bcsr) {
274 printk(KERN_ERR "Cannot map BCSR registers\n");
275 of_node_put(ep8248e_bcsr_node);
276 ep8248e_bcsr_node = NULL;
277 return;
278 }
279
280 setbits8(&ep8248e_bcsr[7], BCSR7_SCC2_ENABLE);
281 setbits8(&ep8248e_bcsr[8], BCSR8_PHY1_ENABLE | BCSR8_PHY1_POWER |
282 BCSR8_PHY2_ENABLE | BCSR8_PHY2_POWER);
283
284 init_ioports();
285
286 if (ppc_md.progress)
287 ppc_md.progress("ep8248e_setup_arch(), finish", 0);
288}
289
290static __initdata struct of_device_id of_bus_ids[] = {
291 { .compatible = "simple-bus", },
292 { .compatible = "fsl,ep8248e-bcsr", },
293 {},
294};
295
296static int __init declare_of_platform_devices(void)
297{
298 of_platform_bus_probe(NULL, of_bus_ids, NULL);
299 of_register_platform_driver(&ep8248e_mdio_driver);
300
301 return 0;
302}
303machine_device_initcall(ep8248e, declare_of_platform_devices);
304
305/*
306 * Called very early, device-tree isn't unflattened
307 */
308static int __init ep8248e_probe(void)
309{
310 unsigned long root = of_get_flat_dt_root();
311 return of_flat_dt_is_compatible(root, "fsl,ep8248e");
312}
313
314define_machine(ep8248e)
315{
316 .name = "Embedded Planet EP8248E",
317 .probe = ep8248e_probe,
318 .setup_arch = ep8248e_setup_arch,
319 .init_IRQ = ep8248e_pic_init,
320 .get_irq = cpm2_get_irq,
321 .calibrate_decr = generic_calibrate_decr,
322 .restart = pq2_restart,
323 .progress = udbg_progress,
324};
diff --git a/arch/powerpc/platforms/82xx/mpc8272_ads.c b/arch/powerpc/platforms/82xx/mpc8272_ads.c
index fd83440eb287..3fce6b375dbc 100644
--- a/arch/powerpc/platforms/82xx/mpc8272_ads.c
+++ b/arch/powerpc/platforms/82xx/mpc8272_ads.c
@@ -165,14 +165,11 @@ static struct of_device_id __initdata of_bus_ids[] = {
165 165
166static int __init declare_of_platform_devices(void) 166static int __init declare_of_platform_devices(void)
167{ 167{
168 if (!machine_is(mpc8272_ads))
169 return 0;
170
171 /* Publish the QE devices */ 168 /* Publish the QE devices */
172 of_platform_bus_probe(NULL, of_bus_ids, NULL); 169 of_platform_bus_probe(NULL, of_bus_ids, NULL);
173 return 0; 170 return 0;
174} 171}
175device_initcall(declare_of_platform_devices); 172machine_device_initcall(mpc8272_ads, declare_of_platform_devices);
176 173
177/* 174/*
178 * Called very early, device-tree isn't unflattened 175 * Called very early, device-tree isn't unflattened
diff --git a/arch/powerpc/platforms/82xx/pq2.c b/arch/powerpc/platforms/82xx/pq2.c
index a497cbaa1ac5..1b75902fad64 100644
--- a/arch/powerpc/platforms/82xx/pq2.c
+++ b/arch/powerpc/platforms/82xx/pq2.c
@@ -53,13 +53,13 @@ static void __init pq2_pci_add_bridge(struct device_node *np)
53 if (of_address_to_resource(np, 0, &r) || r.end - r.start < 0x10b) 53 if (of_address_to_resource(np, 0, &r) || r.end - r.start < 0x10b)
54 goto err; 54 goto err;
55 55
56 pci_assign_all_buses = 1; 56 ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
57 57
58 hose = pcibios_alloc_controller(np); 58 hose = pcibios_alloc_controller(np);
59 if (!hose) 59 if (!hose)
60 return; 60 return;
61 61
62 hose->arch_data = np; 62 hose->dn = np;
63 63
64 setup_indirect_pci(hose, r.start + 0x100, r.start + 0x104, 0); 64 setup_indirect_pci(hose, r.start + 0x100, r.start + 0x104, 0);
65 pci_process_bridge_OF_ranges(hose, np, 1); 65 pci_process_bridge_OF_ranges(hose, np, 1);
diff --git a/arch/powerpc/platforms/82xx/pq2fads.c b/arch/powerpc/platforms/82xx/pq2fads.c
index 4f457a9c79ae..68196e349994 100644
--- a/arch/powerpc/platforms/82xx/pq2fads.c
+++ b/arch/powerpc/platforms/82xx/pq2fads.c
@@ -15,12 +15,12 @@
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17#include <linux/fsl_devices.h> 17#include <linux/fsl_devices.h>
18#include <linux/of_platform.h>
18 19
19#include <asm/io.h> 20#include <asm/io.h>
20#include <asm/cpm2.h> 21#include <asm/cpm2.h>
21#include <asm/udbg.h> 22#include <asm/udbg.h>
22#include <asm/machdep.h> 23#include <asm/machdep.h>
23#include <asm/of_platform.h>
24#include <asm/time.h> 24#include <asm/time.h>
25 25
26#include <sysdev/fsl_soc.h> 26#include <sysdev/fsl_soc.h>
@@ -176,14 +176,11 @@ static struct of_device_id __initdata of_bus_ids[] = {
176 176
177static int __init declare_of_platform_devices(void) 177static int __init declare_of_platform_devices(void)
178{ 178{
179 if (!machine_is(pq2fads))
180 return 0;
181
182 /* Publish the QE devices */ 179 /* Publish the QE devices */
183 of_platform_bus_probe(NULL, of_bus_ids, NULL); 180 of_platform_bus_probe(NULL, of_bus_ids, NULL);
184 return 0; 181 return 0;
185} 182}
186device_initcall(declare_of_platform_devices); 183machine_device_initcall(pq2fads, declare_of_platform_devices);
187 184
188define_machine(pq2fads) 185define_machine(pq2fads)
189{ 186{
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index ec305f18abd8..13587e2e8680 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -1,18 +1,23 @@
1choice 1menuconfig MPC83xx
2 prompt "83xx Board Type" 2 bool "83xx Board Type"
3 depends on PPC_83xx 3 depends on PPC_83xx
4 default MPC834x_MDS 4 select PPC_UDBG_16550
5 select PPC_INDIRECT_PCI
6
7if MPC83xx
5 8
6config MPC8313_RDB 9config MPC831x_RDB
7 bool "Freescale MPC8313 RDB" 10 bool "Freescale MPC831x RDB"
8 select DEFAULT_UIMAGE 11 select DEFAULT_UIMAGE
12 select PPC_MPC831x
9 help 13 help
10 This option enables support for the MPC8313 RDB board. 14 This option enables support for the MPC8313 RDB and MPC8315 RDB boards.
11 15
12config MPC832x_MDS 16config MPC832x_MDS
13 bool "Freescale MPC832x MDS" 17 bool "Freescale MPC832x MDS"
14 select DEFAULT_UIMAGE 18 select DEFAULT_UIMAGE
15 select QUICC_ENGINE 19 select QUICC_ENGINE
20 select PPC_MPC832x
16 help 21 help
17 This option enables support for the MPC832x MDS evaluation board. 22 This option enables support for the MPC832x MDS evaluation board.
18 23
@@ -20,12 +25,14 @@ config MPC832x_RDB
20 bool "Freescale MPC832x RDB" 25 bool "Freescale MPC832x RDB"
21 select DEFAULT_UIMAGE 26 select DEFAULT_UIMAGE
22 select QUICC_ENGINE 27 select QUICC_ENGINE
28 select PPC_MPC832x
23 help 29 help
24 This option enables support for the MPC8323 RDB board. 30 This option enables support for the MPC8323 RDB board.
25 31
26config MPC834x_MDS 32config MPC834x_MDS
27 bool "Freescale MPC834x MDS" 33 bool "Freescale MPC834x MDS"
28 select DEFAULT_UIMAGE 34 select DEFAULT_UIMAGE
35 select PPC_MPC834x
29 help 36 help
30 This option enables support for the MPC 834x MDS evaluation board. 37 This option enables support for the MPC 834x MDS evaluation board.
31 38
@@ -37,6 +44,7 @@ config MPC834x_MDS
37config MPC834x_ITX 44config MPC834x_ITX
38 bool "Freescale MPC834x ITX" 45 bool "Freescale MPC834x ITX"
39 select DEFAULT_UIMAGE 46 select DEFAULT_UIMAGE
47 select PPC_MPC834x
40 help 48 help
41 This option enables support for the MPC 834x ITX evaluation board. 49 This option enables support for the MPC 834x ITX evaluation board.
42 50
@@ -50,28 +58,41 @@ config MPC836x_MDS
50 help 58 help
51 This option enables support for the MPC836x MDS Processor Board. 59 This option enables support for the MPC836x MDS Processor Board.
52 60
53endchoice 61config MPC837x_MDS
62 bool "Freescale MPC837x MDS"
63 select DEFAULT_UIMAGE
64 select PPC_MPC837x
65 help
66 This option enables support for the MPC837x MDS Processor Board.
67
68config MPC837x_RDB
69 bool "Freescale MPC837x RDB"
70 select DEFAULT_UIMAGE
71 select PPC_MPC837x
72 help
73 This option enables support for the MPC837x RDB Board.
74
75config SBC834x
76 bool "Wind River SBC834x"
77 select DEFAULT_UIMAGE
78 select PPC_MPC834x
79 help
80 This option enables support for the Wind River SBC834x board.
81
82endif
54 83
84# used for usb
55config PPC_MPC831x 85config PPC_MPC831x
56 bool 86 bool
57 select PPC_UDBG_16550
58 select PPC_INDIRECT_PCI
59 default y if MPC8313_RDB
60 87
88# used for math-emu
61config PPC_MPC832x 89config PPC_MPC832x
62 bool 90 bool
63 select PPC_UDBG_16550
64 select PPC_INDIRECT_PCI
65 default y if MPC832x_MDS || MPC832x_RDB
66 91
67config MPC834x 92# used for usb
93config PPC_MPC834x
68 bool 94 bool
69 select PPC_UDBG_16550
70 select PPC_INDIRECT_PCI
71 default y if MPC834x_MDS || MPC834x_ITX
72 95
73config PPC_MPC836x 96# used for usb
97config PPC_MPC837x
74 bool 98 bool
75 select PPC_UDBG_16550
76 select PPC_INDIRECT_PCI
77 default y if MPC836x_MDS
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile
index 5a98f885779f..7e6dd3e259d8 100644
--- a/arch/powerpc/platforms/83xx/Makefile
+++ b/arch/powerpc/platforms/83xx/Makefile
@@ -3,9 +3,12 @@
3# 3#
4obj-y := misc.o usb.o 4obj-y := misc.o usb.o
5obj-$(CONFIG_PCI) += pci.o 5obj-$(CONFIG_PCI) += pci.o
6obj-$(CONFIG_MPC8313_RDB) += mpc8313_rdb.o 6obj-$(CONFIG_MPC831x_RDB) += mpc831x_rdb.o
7obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o 7obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o
8obj-$(CONFIG_MPC834x_MDS) += mpc834x_mds.o 8obj-$(CONFIG_MPC834x_MDS) += mpc834x_mds.o
9obj-$(CONFIG_MPC834x_ITX) += mpc834x_itx.o 9obj-$(CONFIG_MPC834x_ITX) += mpc834x_itx.o
10obj-$(CONFIG_MPC836x_MDS) += mpc836x_mds.o 10obj-$(CONFIG_MPC836x_MDS) += mpc836x_mds.o
11obj-$(CONFIG_MPC832x_MDS) += mpc832x_mds.o 11obj-$(CONFIG_MPC832x_MDS) += mpc832x_mds.o
12obj-$(CONFIG_MPC837x_MDS) += mpc837x_mds.o
13obj-$(CONFIG_SBC834x) += sbc834x.o
14obj-$(CONFIG_MPC837x_RDB) += mpc837x_rdb.o
diff --git a/arch/powerpc/platforms/83xx/mpc8313_rdb.c b/arch/powerpc/platforms/83xx/mpc831x_rdb.c
index 33766b8f2594..c4db5172b27a 100644
--- a/arch/powerpc/platforms/83xx/mpc8313_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc831x_rdb.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * arch/powerpc/platforms/83xx/mpc8313_rdb.c 2 * arch/powerpc/platforms/83xx/mpc831x_rdb.c
3 * 3 *
4 * Description: MPC8313x RDB board specific routines. 4 * Description: MPC831x RDB board specific routines.
5 * This file is based on mpc834x_sys.c 5 * This file is based on mpc834x_sys.c
6 * Author: Lo Wlison <r43300@freescale.com> 6 * Author: Lo Wlison <r43300@freescale.com>
7 * 7 *
@@ -14,6 +14,7 @@
14 */ 14 */
15 15
16#include <linux/pci.h> 16#include <linux/pci.h>
17#include <linux/of_platform.h>
17 18
18#include <asm/time.h> 19#include <asm/time.h>
19#include <asm/ipic.h> 20#include <asm/ipic.h>
@@ -21,26 +22,17 @@
21 22
22#include "mpc83xx.h" 23#include "mpc83xx.h"
23 24
24#undef DEBUG 25/*
25#ifdef DEBUG
26#define DBG(fmt...) udbg_printf(fmt)
27#else
28#define DBG(fmt...)
29#endif
30
31/* ************************************************************************
32 *
33 * Setup the architecture 26 * Setup the architecture
34 *
35 */ 27 */
36static void __init mpc8313_rdb_setup_arch(void) 28static void __init mpc831x_rdb_setup_arch(void)
37{ 29{
38#ifdef CONFIG_PCI 30#ifdef CONFIG_PCI
39 struct device_node *np; 31 struct device_node *np;
40#endif 32#endif
41 33
42 if (ppc_md.progress) 34 if (ppc_md.progress)
43 ppc_md.progress("mpc8313_rdb_setup_arch()", 0); 35 ppc_md.progress("mpc831x_rdb_setup_arch()", 0);
44 36
45#ifdef CONFIG_PCI 37#ifdef CONFIG_PCI
46 for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") 38 for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
@@ -49,7 +41,7 @@ static void __init mpc8313_rdb_setup_arch(void)
49 mpc831x_usb_cfg(); 41 mpc831x_usb_cfg();
50} 42}
51 43
52void __init mpc8313_rdb_init_IRQ(void) 44void __init mpc831x_rdb_init_IRQ(void)
53{ 45{
54 struct device_node *np; 46 struct device_node *np;
55 47
@@ -68,18 +60,31 @@ void __init mpc8313_rdb_init_IRQ(void)
68/* 60/*
69 * Called very early, MMU is off, device-tree isn't unflattened 61 * Called very early, MMU is off, device-tree isn't unflattened
70 */ 62 */
71static int __init mpc8313_rdb_probe(void) 63static int __init mpc831x_rdb_probe(void)
72{ 64{
73 unsigned long root = of_get_flat_dt_root(); 65 unsigned long root = of_get_flat_dt_root();
74 66
75 return of_flat_dt_is_compatible(root, "MPC8313ERDB"); 67 return of_flat_dt_is_compatible(root, "MPC8313ERDB") ||
68 of_flat_dt_is_compatible(root, "fsl,mpc8315erdb");
69}
70
71static struct of_device_id __initdata of_bus_ids[] = {
72 { .compatible = "simple-bus" },
73 {},
74};
75
76static int __init declare_of_platform_devices(void)
77{
78 of_platform_bus_probe(NULL, of_bus_ids, NULL);
79 return 0;
76} 80}
81machine_device_initcall(mpc831x_rdb, declare_of_platform_devices);
77 82
78define_machine(mpc8313_rdb) { 83define_machine(mpc831x_rdb) {
79 .name = "MPC8313 RDB", 84 .name = "MPC831x RDB",
80 .probe = mpc8313_rdb_probe, 85 .probe = mpc831x_rdb_probe,
81 .setup_arch = mpc8313_rdb_setup_arch, 86 .setup_arch = mpc831x_rdb_setup_arch,
82 .init_IRQ = mpc8313_rdb_init_IRQ, 87 .init_IRQ = mpc831x_rdb_init_IRQ,
83 .get_irq = ipic_get_irq, 88 .get_irq = ipic_get_irq,
84 .restart = mpc83xx_restart, 89 .restart = mpc83xx_restart,
85 .time_init = mpc83xx_time_init, 90 .time_init = mpc83xx_time_init,
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index 39ee7a13b25a..6dbc6eabcb02 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -23,9 +23,9 @@
23#include <linux/seq_file.h> 23#include <linux/seq_file.h>
24#include <linux/root_dev.h> 24#include <linux/root_dev.h>
25#include <linux/initrd.h> 25#include <linux/initrd.h>
26#include <linux/of_platform.h>
27#include <linux/of_device.h>
26 28
27#include <asm/of_device.h>
28#include <asm/of_platform.h>
29#include <asm/system.h> 29#include <asm/system.h>
30#include <asm/atomic.h> 30#include <asm/atomic.h>
31#include <asm/time.h> 31#include <asm/time.h>
@@ -105,20 +105,18 @@ static struct of_device_id mpc832x_ids[] = {
105 { .type = "soc", }, 105 { .type = "soc", },
106 { .compatible = "soc", }, 106 { .compatible = "soc", },
107 { .type = "qe", }, 107 { .type = "qe", },
108 { .compatible = "fsl,qe", },
108 {}, 109 {},
109}; 110};
110 111
111static int __init mpc832x_declare_of_platform_devices(void) 112static int __init mpc832x_declare_of_platform_devices(void)
112{ 113{
113 if (!machine_is(mpc832x_mds))
114 return 0;
115
116 /* Publish the QE devices */ 114 /* Publish the QE devices */
117 of_platform_bus_probe(NULL, mpc832x_ids, NULL); 115 of_platform_bus_probe(NULL, mpc832x_ids, NULL);
118 116
119 return 0; 117 return 0;
120} 118}
121device_initcall(mpc832x_declare_of_platform_devices); 119machine_device_initcall(mpc832x_mds, mpc832x_declare_of_platform_devices);
122 120
123static void __init mpc832x_sys_init_IRQ(void) 121static void __init mpc832x_sys_init_IRQ(void)
124{ 122{
@@ -137,10 +135,12 @@ static void __init mpc832x_sys_init_IRQ(void)
137 of_node_put(np); 135 of_node_put(np);
138 136
139#ifdef CONFIG_QUICC_ENGINE 137#ifdef CONFIG_QUICC_ENGINE
140 np = of_find_node_by_type(NULL, "qeic"); 138 np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
141 if (!np) 139 if (!np) {
142 return; 140 np = of_find_node_by_type(NULL, "qeic");
143 141 if (!np)
142 return;
143 }
144 qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic); 144 qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic);
145 of_node_put(np); 145 of_node_put(np);
146#endif /* CONFIG_QUICC_ENGINE */ 146#endif /* CONFIG_QUICC_ENGINE */
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
index d4bd04001b99..9f0fd88b2b1f 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
@@ -19,8 +19,8 @@
19#include <linux/spi/spi.h> 19#include <linux/spi/spi.h>
20#include <linux/spi/mmc_spi.h> 20#include <linux/spi/mmc_spi.h>
21#include <linux/mmc/host.h> 21#include <linux/mmc/host.h>
22#include <linux/of_platform.h>
22 23
23#include <asm/of_platform.h>
24#include <asm/time.h> 24#include <asm/time.h>
25#include <asm/ipic.h> 25#include <asm/ipic.h>
26#include <asm/udbg.h> 26#include <asm/udbg.h>
@@ -63,9 +63,6 @@ static struct spi_board_info mpc832x_spi_boardinfo = {
63 63
64static int __init mpc832x_spi_init(void) 64static int __init mpc832x_spi_init(void)
65{ 65{
66 if (!machine_is(mpc832x_rdb))
67 return 0;
68
69 par_io_config_pin(3, 0, 3, 0, 1, 0); /* SPI1 MOSI, I/O */ 66 par_io_config_pin(3, 0, 3, 0, 1, 0); /* SPI1 MOSI, I/O */
70 par_io_config_pin(3, 1, 3, 0, 1, 0); /* SPI1 MISO, I/O */ 67 par_io_config_pin(3, 1, 3, 0, 1, 0); /* SPI1 MISO, I/O */
71 par_io_config_pin(3, 2, 3, 0, 1, 0); /* SPI1 CLK, I/O */ 68 par_io_config_pin(3, 2, 3, 0, 1, 0); /* SPI1 CLK, I/O */
@@ -80,7 +77,7 @@ static int __init mpc832x_spi_init(void)
80 mpc83xx_spi_deactivate_cs); 77 mpc83xx_spi_deactivate_cs);
81} 78}
82 79
83device_initcall(mpc832x_spi_init); 80machine_device_initcall(mpc832x_rdb, mpc832x_spi_init);
84 81
85/* ************************************************************************ 82/* ************************************************************************
86 * 83 *
@@ -118,20 +115,18 @@ static struct of_device_id mpc832x_ids[] = {
118 { .type = "soc", }, 115 { .type = "soc", },
119 { .compatible = "soc", }, 116 { .compatible = "soc", },
120 { .type = "qe", }, 117 { .type = "qe", },
118 { .compatible = "fsl,qe", },
121 {}, 119 {},
122}; 120};
123 121
124static int __init mpc832x_declare_of_platform_devices(void) 122static int __init mpc832x_declare_of_platform_devices(void)
125{ 123{
126 if (!machine_is(mpc832x_rdb))
127 return 0;
128
129 /* Publish the QE devices */ 124 /* Publish the QE devices */
130 of_platform_bus_probe(NULL, mpc832x_ids, NULL); 125 of_platform_bus_probe(NULL, mpc832x_ids, NULL);
131 126
132 return 0; 127 return 0;
133} 128}
134device_initcall(mpc832x_declare_of_platform_devices); 129machine_device_initcall(mpc832x_rdb, mpc832x_declare_of_platform_devices);
135 130
136void __init mpc832x_rdb_init_IRQ(void) 131void __init mpc832x_rdb_init_IRQ(void)
137{ 132{
@@ -151,10 +146,12 @@ void __init mpc832x_rdb_init_IRQ(void)
151 of_node_put(np); 146 of_node_put(np);
152 147
153#ifdef CONFIG_QUICC_ENGINE 148#ifdef CONFIG_QUICC_ENGINE
154 np = of_find_node_by_type(NULL, "qeic"); 149 np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
155 if (!np) 150 if (!np) {
156 return; 151 np = of_find_node_by_type(NULL, "qeic");
157 152 if (!np)
153 return;
154 }
158 qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic); 155 qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic);
159 of_node_put(np); 156 of_node_put(np);
160#endif /* CONFIG_QUICC_ENGINE */ 157#endif /* CONFIG_QUICC_ENGINE */
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index aa768199432d..50e8f632061c 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -23,6 +23,7 @@
23#include <linux/delay.h> 23#include <linux/delay.h>
24#include <linux/seq_file.h> 24#include <linux/seq_file.h>
25#include <linux/root_dev.h> 25#include <linux/root_dev.h>
26#include <linux/of_platform.h>
26 27
27#include <asm/system.h> 28#include <asm/system.h>
28#include <asm/atomic.h> 29#include <asm/atomic.h>
@@ -37,6 +38,17 @@
37 38
38#include "mpc83xx.h" 39#include "mpc83xx.h"
39 40
41static struct of_device_id __initdata mpc834x_itx_ids[] = {
42 { .compatible = "fsl,pq2pro-localbus", },
43 {},
44};
45
46static int __init mpc834x_itx_declare_of_platform_devices(void)
47{
48 return of_platform_bus_probe(NULL, mpc834x_itx_ids, NULL);
49}
50machine_device_initcall(mpc834x_itx, mpc834x_itx_declare_of_platform_devices);
51
40/* ************************************************************************ 52/* ************************************************************************
41 * 53 *
42 * Setup the architecture 54 * Setup the architecture
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c
index a81bb3ce6b94..2b8a0a3f8557 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c
@@ -23,6 +23,7 @@
23#include <linux/delay.h> 23#include <linux/delay.h>
24#include <linux/seq_file.h> 24#include <linux/seq_file.h>
25#include <linux/root_dev.h> 25#include <linux/root_dev.h>
26#include <linux/of_platform.h>
26 27
27#include <asm/system.h> 28#include <asm/system.h>
28#include <asm/atomic.h> 29#include <asm/atomic.h>
@@ -106,14 +107,27 @@ static void __init mpc834x_mds_init_IRQ(void)
106 ipic_set_default_priority(); 107 ipic_set_default_priority();
107} 108}
108 109
110static struct of_device_id mpc834x_ids[] = {
111 { .type = "soc", },
112 { .compatible = "soc", },
113 {},
114};
115
116static int __init mpc834x_declare_of_platform_devices(void)
117{
118 of_platform_bus_probe(NULL, mpc834x_ids, NULL);
119 return 0;
120}
121machine_device_initcall(mpc834x_mds, mpc834x_declare_of_platform_devices);
122
109/* 123/*
110 * Called very early, MMU is off, device-tree isn't unflattened 124 * Called very early, MMU is off, device-tree isn't unflattened
111 */ 125 */
112static int __init mpc834x_mds_probe(void) 126static int __init mpc834x_mds_probe(void)
113{ 127{
114 unsigned long root = of_get_flat_dt_root(); 128 unsigned long root = of_get_flat_dt_root();
115 129
116 return of_flat_dt_is_compatible(root, "MPC834xMDS"); 130 return of_flat_dt_is_compatible(root, "MPC834xMDS");
117} 131}
118 132
119define_machine(mpc834x_mds) { 133define_machine(mpc834x_mds) {
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c
index e40012f8f488..c2e5de60c055 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c
@@ -29,9 +29,9 @@
29#include <linux/seq_file.h> 29#include <linux/seq_file.h>
30#include <linux/root_dev.h> 30#include <linux/root_dev.h>
31#include <linux/initrd.h> 31#include <linux/initrd.h>
32#include <linux/of_platform.h>
33#include <linux/of_device.h>
32 34
33#include <asm/of_device.h>
34#include <asm/of_platform.h>
35#include <asm/system.h> 35#include <asm/system.h>
36#include <asm/atomic.h> 36#include <asm/atomic.h>
37#include <asm/time.h> 37#include <asm/time.h>
@@ -136,20 +136,18 @@ static struct of_device_id mpc836x_ids[] = {
136 { .type = "soc", }, 136 { .type = "soc", },
137 { .compatible = "soc", }, 137 { .compatible = "soc", },
138 { .type = "qe", }, 138 { .type = "qe", },
139 { .compatible = "fsl,qe", },
139 {}, 140 {},
140}; 141};
141 142
142static int __init mpc836x_declare_of_platform_devices(void) 143static int __init mpc836x_declare_of_platform_devices(void)
143{ 144{
144 if (!machine_is(mpc836x_mds))
145 return 0;
146
147 /* Publish the QE devices */ 145 /* Publish the QE devices */
148 of_platform_bus_probe(NULL, mpc836x_ids, NULL); 146 of_platform_bus_probe(NULL, mpc836x_ids, NULL);
149 147
150 return 0; 148 return 0;
151} 149}
152device_initcall(mpc836x_declare_of_platform_devices); 150machine_device_initcall(mpc836x_mds, mpc836x_declare_of_platform_devices);
153 151
154static void __init mpc836x_mds_init_IRQ(void) 152static void __init mpc836x_mds_init_IRQ(void)
155{ 153{
@@ -168,10 +166,12 @@ static void __init mpc836x_mds_init_IRQ(void)
168 of_node_put(np); 166 of_node_put(np);
169 167
170#ifdef CONFIG_QUICC_ENGINE 168#ifdef CONFIG_QUICC_ENGINE
171 np = of_find_node_by_type(NULL, "qeic"); 169 np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
172 if (!np) 170 if (!np) {
173 return; 171 np = of_find_node_by_type(NULL, "qeic");
174 172 if (!np)
173 return;
174 }
175 qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic); 175 qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic);
176 of_node_put(np); 176 of_node_put(np);
177#endif /* CONFIG_QUICC_ENGINE */ 177#endif /* CONFIG_QUICC_ENGINE */
diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c
new file mode 100644
index 000000000000..8a9c26973605
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c
@@ -0,0 +1,147 @@
1/*
2 * arch/powerpc/platforms/83xx/mpc837x_mds.c
3 *
4 * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
5 *
6 * MPC837x MDS board specific routines
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/pci.h>
15#include <linux/of.h>
16#include <linux/of_platform.h>
17
18#include <asm/time.h>
19#include <asm/ipic.h>
20#include <asm/udbg.h>
21#include <asm/prom.h>
22
23#include "mpc83xx.h"
24
25#define BCSR12_USB_SER_MASK 0x8a
26#define BCSR12_USB_SER_PIN 0x80
27#define BCSR12_USB_SER_DEVICE 0x02
28extern int mpc837x_usb_cfg(void);
29
30static int mpc837xmds_usb_cfg(void)
31{
32 struct device_node *np;
33 const void *phy_type, *mode;
34 void __iomem *bcsr_regs = NULL;
35 u8 bcsr12;
36 int ret;
37
38 ret = mpc837x_usb_cfg();
39 if (ret)
40 return ret;
41 /* Map BCSR area */
42 np = of_find_node_by_name(NULL, "bcsr");
43 if (np) {
44 struct resource res;
45
46 of_address_to_resource(np, 0, &res);
47 bcsr_regs = ioremap(res.start, res.end - res.start + 1);
48 of_node_put(np);
49 }
50 if (!bcsr_regs)
51 return -1;
52
53 np = of_find_node_by_name(NULL, "usb");
54 if (!np)
55 return -ENODEV;
56 phy_type = of_get_property(np, "phy_type", NULL);
57 if (phy_type && !strcmp(phy_type, "ulpi")) {
58 clrbits8(bcsr_regs + 12, BCSR12_USB_SER_PIN);
59 } else if (phy_type && !strcmp(phy_type, "serial")) {
60 mode = of_get_property(np, "dr_mode", NULL);
61 bcsr12 = in_8(bcsr_regs + 12) & ~BCSR12_USB_SER_MASK;
62 bcsr12 |= BCSR12_USB_SER_PIN;
63 if (mode && !strcmp(mode, "peripheral"))
64 bcsr12 |= BCSR12_USB_SER_DEVICE;
65 out_8(bcsr_regs + 12, bcsr12);
66 } else {
67 printk(KERN_ERR "USB DR: unsupported PHY\n");
68 }
69
70 of_node_put(np);
71 iounmap(bcsr_regs);
72 return 0;
73}
74
75/* ************************************************************************
76 *
77 * Setup the architecture
78 *
79 */
80static void __init mpc837x_mds_setup_arch(void)
81{
82#ifdef CONFIG_PCI
83 struct device_node *np;
84#endif
85
86 if (ppc_md.progress)
87 ppc_md.progress("mpc837x_mds_setup_arch()", 0);
88
89#ifdef CONFIG_PCI
90 for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
91 mpc83xx_add_bridge(np);
92#endif
93 mpc837xmds_usb_cfg();
94}
95
96static struct of_device_id mpc837x_ids[] = {
97 { .type = "soc", },
98 { .compatible = "soc", },
99 {},
100};
101
102static int __init mpc837x_declare_of_platform_devices(void)
103{
104 /* Publish of_device */
105 of_platform_bus_probe(NULL, mpc837x_ids, NULL);
106
107 return 0;
108}
109machine_device_initcall(mpc837x_mds, mpc837x_declare_of_platform_devices);
110
111static void __init mpc837x_mds_init_IRQ(void)
112{
113 struct device_node *np;
114
115 np = of_find_compatible_node(NULL, NULL, "fsl,ipic");
116 if (!np)
117 return;
118
119 ipic_init(np, 0);
120
121 /* Initialize the default interrupt mapping priorities,
122 * in case the boot rom changed something on us.
123 */
124 ipic_set_default_priority();
125}
126
127/*
128 * Called very early, MMU is off, device-tree isn't unflattened
129 */
130static int __init mpc837x_mds_probe(void)
131{
132 unsigned long root = of_get_flat_dt_root();
133
134 return of_flat_dt_is_compatible(root, "fsl,mpc837xmds");
135}
136
137define_machine(mpc837x_mds) {
138 .name = "MPC837x MDS",
139 .probe = mpc837x_mds_probe,
140 .setup_arch = mpc837x_mds_setup_arch,
141 .init_IRQ = mpc837x_mds_init_IRQ,
142 .get_irq = ipic_get_irq,
143 .restart = mpc83xx_restart,
144 .time_init = mpc83xx_time_init,
145 .calibrate_decr = generic_calibrate_decr,
146 .progress = udbg_progress,
147};
diff --git a/arch/powerpc/platforms/83xx/mpc837x_rdb.c b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
new file mode 100644
index 000000000000..2293ae51383d
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
@@ -0,0 +1,99 @@
1/*
2 * arch/powerpc/platforms/83xx/mpc837x_rdb.c
3 *
4 * Copyright (C) 2007 Freescale Semicondutor, Inc. All rights reserved.
5 *
6 * MPC837x RDB board specific routines
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/pci.h>
15#include <linux/of_platform.h>
16
17#include <asm/time.h>
18#include <asm/ipic.h>
19#include <asm/udbg.h>
20
21#include "mpc83xx.h"
22
23extern int mpc837x_usb_cfg(void);
24
25/* ************************************************************************
26 *
27 * Setup the architecture
28 *
29 */
30static void __init mpc837x_rdb_setup_arch(void)
31{
32#ifdef CONFIG_PCI
33 struct device_node *np;
34#endif
35
36 if (ppc_md.progress)
37 ppc_md.progress("mpc837x_rdb_setup_arch()", 0);
38
39#ifdef CONFIG_PCI
40 for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
41 mpc83xx_add_bridge(np);
42#endif
43 mpc837x_usb_cfg();
44}
45
46static struct of_device_id mpc837x_ids[] = {
47 { .type = "soc", },
48 { .compatible = "soc", },
49 {},
50};
51
52static int __init mpc837x_declare_of_platform_devices(void)
53{
54 /* Publish of_device */
55 of_platform_bus_probe(NULL, mpc837x_ids, NULL);
56
57 return 0;
58}
59machine_device_initcall(mpc837x_rdb, mpc837x_declare_of_platform_devices);
60
61static void __init mpc837x_rdb_init_IRQ(void)
62{
63 struct device_node *np;
64
65 np = of_find_compatible_node(NULL, NULL, "fsl,ipic");
66 if (!np)
67 return;
68
69 ipic_init(np, 0);
70
71 /* Initialize the default interrupt mapping priorities,
72 * in case the boot rom changed something on us.
73 */
74 ipic_set_default_priority();
75}
76
77/*
78 * Called very early, MMU is off, device-tree isn't unflattened
79 */
80static int __init mpc837x_rdb_probe(void)
81{
82 unsigned long root = of_get_flat_dt_root();
83
84 return of_flat_dt_is_compatible(root, "fsl,mpc8377rdb") ||
85 of_flat_dt_is_compatible(root, "fsl,mpc8378rdb") ||
86 of_flat_dt_is_compatible(root, "fsl,mpc8379rdb");
87}
88
89define_machine(mpc837x_rdb) {
90 .name = "MPC837x RDB",
91 .probe = mpc837x_rdb_probe,
92 .setup_arch = mpc837x_rdb_setup_arch,
93 .init_IRQ = mpc837x_rdb_init_IRQ,
94 .get_irq = ipic_get_irq,
95 .restart = mpc83xx_restart,
96 .time_init = mpc83xx_time_init,
97 .calibrate_decr = generic_calibrate_decr,
98 .progress = udbg_progress,
99};
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h
index b778cb4f3fb5..88bb748aff0d 100644
--- a/arch/powerpc/platforms/83xx/mpc83xx.h
+++ b/arch/powerpc/platforms/83xx/mpc83xx.h
@@ -14,6 +14,7 @@
14#define MPC83XX_SCCR_USB_DRCM_11 0x00300000 14#define MPC83XX_SCCR_USB_DRCM_11 0x00300000
15#define MPC83XX_SCCR_USB_DRCM_01 0x00100000 15#define MPC83XX_SCCR_USB_DRCM_01 0x00100000
16#define MPC83XX_SCCR_USB_DRCM_10 0x00200000 16#define MPC83XX_SCCR_USB_DRCM_10 0x00200000
17#define MPC837X_SCCR_USB_DRCM_11 0x00c00000
17 18
18/* system i/o configuration register low */ 19/* system i/o configuration register low */
19#define MPC83XX_SICRL_OFFS 0x114 20#define MPC83XX_SICRL_OFFS 0x114
@@ -22,6 +23,8 @@
22#define MPC834X_SICRL_USB1 0x20000000 23#define MPC834X_SICRL_USB1 0x20000000
23#define MPC831X_SICRL_USB_MASK 0x00000c00 24#define MPC831X_SICRL_USB_MASK 0x00000c00
24#define MPC831X_SICRL_USB_ULPI 0x00000800 25#define MPC831X_SICRL_USB_ULPI 0x00000800
26#define MPC837X_SICRL_USB_MASK 0xf0000000
27#define MPC837X_SICRL_USB_ULPI 0x50000000
25 28
26/* system i/o configuration register high */ 29/* system i/o configuration register high */
27#define MPC83XX_SICRH_OFFS 0x118 30#define MPC83XX_SICRH_OFFS 0x118
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c
index 80425d7b14f8..14f1080c6c9d 100644
--- a/arch/powerpc/platforms/83xx/pci.c
+++ b/arch/powerpc/platforms/83xx/pci.c
@@ -54,7 +54,7 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
54 " bus 0\n", dev->full_name); 54 " bus 0\n", dev->full_name);
55 } 55 }
56 56
57 pci_assign_all_buses = 1; 57 ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
58 hose = pcibios_alloc_controller(dev); 58 hose = pcibios_alloc_controller(dev);
59 if (!hose) 59 if (!hose)
60 return -ENOMEM; 60 return -ENOMEM;
diff --git a/arch/powerpc/platforms/83xx/sbc834x.c b/arch/powerpc/platforms/83xx/sbc834x.c
new file mode 100644
index 000000000000..cf382474a83d
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/sbc834x.c
@@ -0,0 +1,115 @@
1/*
2 * arch/powerpc/platforms/83xx/sbc834x.c
3 *
4 * Wind River SBC834x board specific routines
5 *
6 * By Paul Gortmaker (see MAINTAINERS for contact information)
7 *
8 * Based largely on the mpc834x_mds.c support by Kumar Gala.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15
16#include <linux/stddef.h>
17#include <linux/kernel.h>
18#include <linux/init.h>
19#include <linux/errno.h>
20#include <linux/reboot.h>
21#include <linux/pci.h>
22#include <linux/kdev_t.h>
23#include <linux/major.h>
24#include <linux/console.h>
25#include <linux/delay.h>
26#include <linux/seq_file.h>
27#include <linux/root_dev.h>
28#include <linux/of_platform.h>
29
30#include <asm/system.h>
31#include <asm/atomic.h>
32#include <asm/time.h>
33#include <asm/io.h>
34#include <asm/machdep.h>
35#include <asm/ipic.h>
36#include <asm/irq.h>
37#include <asm/prom.h>
38#include <asm/udbg.h>
39#include <sysdev/fsl_soc.h>
40
41#include "mpc83xx.h"
42
43/* ************************************************************************
44 *
45 * Setup the architecture
46 *
47 */
48static void __init sbc834x_setup_arch(void)
49{
50#ifdef CONFIG_PCI
51 struct device_node *np;
52#endif
53
54 if (ppc_md.progress)
55 ppc_md.progress("sbc834x_setup_arch()", 0);
56
57#ifdef CONFIG_PCI
58 for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
59 mpc83xx_add_bridge(np);
60#endif
61
62}
63
64static void __init sbc834x_init_IRQ(void)
65{
66 struct device_node *np;
67
68 np = of_find_node_by_type(NULL, "ipic");
69 if (!np)
70 return;
71
72 ipic_init(np, 0);
73
74 /* Initialize the default interrupt mapping priorities,
75 * in case the boot rom changed something on us.
76 */
77 ipic_set_default_priority();
78
79 of_node_put(np);
80}
81
82static struct __initdata of_device_id sbc834x_ids[] = {
83 { .type = "soc", },
84 { .compatible = "soc", },
85 {},
86};
87
88static int __init sbc834x_declare_of_platform_devices(void)
89{
90 of_platform_bus_probe(NULL, sbc834x_ids, NULL);
91 return 0;
92}
93machine_device_initcall(sbc834x, sbc834x_declare_of_platform_devices);
94
95/*
96 * Called very early, MMU is off, device-tree isn't unflattened
97 */
98static int __init sbc834x_probe(void)
99{
100 unsigned long root = of_get_flat_dt_root();
101
102 return of_flat_dt_is_compatible(root, "SBC834x");
103}
104
105define_machine(sbc834x) {
106 .name = "SBC834x",
107 .probe = sbc834x_probe,
108 .setup_arch = sbc834x_setup_arch,
109 .init_IRQ = sbc834x_init_IRQ,
110 .get_irq = ipic_get_irq,
111 .restart = mpc83xx_restart,
112 .time_init = mpc83xx_time_init,
113 .calibrate_decr = generic_calibrate_decr,
114 .progress = udbg_progress,
115};
diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c
index b45160f8d084..681230a30acd 100644
--- a/arch/powerpc/platforms/83xx/usb.c
+++ b/arch/powerpc/platforms/83xx/usb.c
@@ -22,7 +22,7 @@
22#include "mpc83xx.h" 22#include "mpc83xx.h"
23 23
24 24
25#ifdef CONFIG_MPC834x 25#ifdef CONFIG_PPC_MPC834x
26int mpc834x_usb_cfg(void) 26int mpc834x_usb_cfg(void)
27{ 27{
28 unsigned long sccr, sicrl, sicrh; 28 unsigned long sccr, sicrl, sicrh;
@@ -41,7 +41,7 @@ int mpc834x_usb_cfg(void)
41 sicrl = in_be32(immap + MPC83XX_SICRL_OFFS) & ~MPC834X_SICRL_USB_MASK; 41 sicrl = in_be32(immap + MPC83XX_SICRL_OFFS) & ~MPC834X_SICRL_USB_MASK;
42 sicrh = in_be32(immap + MPC83XX_SICRH_OFFS) & ~MPC834X_SICRH_USB_UTMI; 42 sicrh = in_be32(immap + MPC83XX_SICRH_OFFS) & ~MPC834X_SICRH_USB_UTMI;
43 43
44 np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr"); 44 np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr");
45 if (np) { 45 if (np) {
46 sccr |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */ 46 sccr |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */
47 47
@@ -67,7 +67,7 @@ int mpc834x_usb_cfg(void)
67 port0_is_dr = 1; 67 port0_is_dr = 1;
68 of_node_put(np); 68 of_node_put(np);
69 } 69 }
70 np = of_find_compatible_node(NULL, "usb", "fsl-usb2-mph"); 70 np = of_find_compatible_node(NULL, NULL, "fsl-usb2-mph");
71 if (np) { 71 if (np) {
72 sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */ 72 sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */
73 73
@@ -96,7 +96,7 @@ int mpc834x_usb_cfg(void)
96 iounmap(immap); 96 iounmap(immap);
97 return 0; 97 return 0;
98} 98}
99#endif /* CONFIG_MPC834x */ 99#endif /* CONFIG_PPC_MPC834x */
100 100
101#ifdef CONFIG_PPC_MPC831x 101#ifdef CONFIG_PPC_MPC831x
102int mpc831x_usb_cfg(void) 102int mpc831x_usb_cfg(void)
@@ -111,7 +111,7 @@ int mpc831x_usb_cfg(void)
111 const void *dr_mode; 111 const void *dr_mode;
112#endif 112#endif
113 113
114 np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr"); 114 np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr");
115 if (!np) 115 if (!np)
116 return -ENODEV; 116 return -ENODEV;
117 prop = of_get_property(np, "phy_type", NULL); 117 prop = of_get_property(np, "phy_type", NULL);
@@ -179,3 +179,43 @@ int mpc831x_usb_cfg(void)
179 return ret; 179 return ret;
180} 180}
181#endif /* CONFIG_PPC_MPC831x */ 181#endif /* CONFIG_PPC_MPC831x */
182
183#ifdef CONFIG_PPC_MPC837x
184int mpc837x_usb_cfg(void)
185{
186 void __iomem *immap;
187 struct device_node *np = NULL;
188 const void *prop;
189 int ret = 0;
190
191 np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr");
192 if (!np)
193 return -ENODEV;
194 prop = of_get_property(np, "phy_type", NULL);
195
196 if (!prop || (strcmp(prop, "ulpi") && strcmp(prop, "serial"))) {
197 printk(KERN_WARNING "837x USB PHY type not supported\n");
198 of_node_put(np);
199 return -EINVAL;
200 }
201
202 /* Map IMMR space for pin and clock settings */
203 immap = ioremap(get_immrbase(), 0x1000);
204 if (!immap) {
205 of_node_put(np);
206 return -ENOMEM;
207 }
208
209 /* Configure clock */
210 clrsetbits_be32(immap + MPC83XX_SCCR_OFFS, MPC837X_SCCR_USB_DRCM_11,
211 MPC837X_SCCR_USB_DRCM_11);
212
213 /* Configure pin mux for ULPI/serial */
214 clrsetbits_be32(immap + MPC83XX_SICRL_OFFS, MPC837X_SICRL_USB_MASK,
215 MPC837X_SICRL_USB_ULPI);
216
217 iounmap(immap);
218 of_node_put(np);
219 return ret;
220}
221#endif /* CONFIG_PPC_MPC837x */
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index 7748a3a426db..7e76ddbd5821 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -1,7 +1,14 @@
1choice 1menuconfig MPC85xx
2 prompt "Machine Type" 2 bool "Machine Type"
3 depends on PPC_85xx 3 depends on PPC_85xx
4 default MPC8540_ADS 4 select PPC_UDBG_16550
5 select PPC_INDIRECT_PCI if PCI
6 select MPIC
7 select FSL_PCI if PCI
8 select SERIAL_8250_SHARE_IRQ if SERIAL_8250
9 default y
10
11if MPC85xx
5 12
6config MPC8540_ADS 13config MPC8540_ADS
7 bool "Freescale MPC8540 ADS" 14 bool "Freescale MPC8540 ADS"
@@ -13,6 +20,7 @@ config MPC8560_ADS
13 bool "Freescale MPC8560 ADS" 20 bool "Freescale MPC8560 ADS"
14 select DEFAULT_UIMAGE 21 select DEFAULT_UIMAGE
15 select PPC_CPM_NEW_BINDING 22 select PPC_CPM_NEW_BINDING
23 select CPM2
16 help 24 help
17 This option enables support for the MPC 8560 ADS board 25 This option enables support for the MPC 8560 ADS board
18 26
@@ -38,25 +46,64 @@ config MPC85xx_DS
38 help 46 help
39 This option enables support for the MPC85xx DS (MPC8544 DS) board 47 This option enables support for the MPC85xx DS (MPC8544 DS) board
40 48
41endchoice 49config STX_GP3
50 bool "Silicon Turnkey Express GP3"
51 help
52 This option enables support for the Silicon Turnkey Express GP3
53 board.
54 select CPM2
55 select DEFAULT_UIMAGE
56 select PPC_CPM_NEW_BINDING
42 57
43config MPC8540 58config TQM8540
44 bool 59 bool "TQ Components TQM8540"
45 select PPC_UDBG_16550 60 help
46 select PPC_INDIRECT_PCI 61 This option enables support for the TQ Components TQM8540 board.
47 default y if MPC8540_ADS || MPC85xx_CDS 62 select DEFAULT_UIMAGE
63 select PPC_CPM_NEW_BINDING
64 select TQM85xx
48 65
49config MPC8560 66config TQM8541
50 bool 67 bool "TQ Components TQM8541"
68 help
69 This option enables support for the TQ Components TQM8541 board.
70 select DEFAULT_UIMAGE
71 select PPC_CPM_NEW_BINDING
72 select TQM85xx
73 select CPM2
74
75config TQM8555
76 bool "TQ Components TQM8555"
77 help
78 This option enables support for the TQ Components TQM8555 board.
79 select DEFAULT_UIMAGE
80 select PPC_CPM_NEW_BINDING
81 select TQM85xx
51 select CPM2 82 select CPM2
52 default y if MPC8560_ADS
53 83
54config MPC85xx 84config TQM8560
85 bool "TQ Components TQM8560"
86 help
87 This option enables support for the TQ Components TQM8560 board.
88 select DEFAULT_UIMAGE
89 select PPC_CPM_NEW_BINDING
90 select TQM85xx
91 select CPM2
92
93config SBC8548
94 bool "Wind River SBC8548"
95 select DEFAULT_UIMAGE
96 help
97 This option enables support for the Wind River SBC8548 board
98
99config SBC8560
100 bool "Wind River SBC8560"
101 select DEFAULT_UIMAGE
102 select PPC_CPM_NEW_BINDING if CPM2
103 help
104 This option enables support for the Wind River SBC8560 board
105
106endif # MPC85xx
107
108config TQM85xx
55 bool 109 bool
56 select PPC_UDBG_16550
57 select PPC_INDIRECT_PCI if PCI
58 select MPIC
59 select FSL_PCI if PCI
60 select SERIAL_8250_SHARE_IRQ if SERIAL_8250
61 default y if MPC8540_ADS || MPC85xx_CDS || MPC8560_ADS \
62 || MPC85xx_MDS || MPC85xx_DS
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index 5eca92023ec8..cb7af4ebd75f 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -6,3 +6,7 @@ obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o
6obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o 6obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o
7obj-$(CONFIG_MPC85xx_DS) += mpc85xx_ds.o 7obj-$(CONFIG_MPC85xx_DS) += mpc85xx_ds.o
8obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o 8obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o
9obj-$(CONFIG_STX_GP3) += stx_gp3.o
10obj-$(CONFIG_TQM85xx) += tqm85xx.o
11obj-$(CONFIG_SBC8560) += sbc8560.o
12obj-$(CONFIG_SBC8548) += sbc8548.o
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index bccdc25f83a2..4e0305096114 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -52,9 +52,9 @@ static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
52{ 52{
53 int cascade_irq; 53 int cascade_irq;
54 54
55 while ((cascade_irq = cpm2_get_irq()) >= 0) { 55 while ((cascade_irq = cpm2_get_irq()) >= 0)
56 generic_handle_irq(cascade_irq); 56 generic_handle_irq(cascade_irq);
57 } 57
58 desc->chip->eoi(irq); 58 desc->chip->eoi(irq);
59} 59}
60 60
@@ -70,13 +70,12 @@ static void __init mpc85xx_ads_pic_init(void)
70#endif 70#endif
71 71
72 np = of_find_node_by_type(np, "open-pic"); 72 np = of_find_node_by_type(np, "open-pic");
73 73 if (!np) {
74 if (np == NULL) {
75 printk(KERN_ERR "Could not find open-pic node\n"); 74 printk(KERN_ERR "Could not find open-pic node\n");
76 return; 75 return;
77 } 76 }
78 77
79 if(of_address_to_resource(np, 0, &r)) { 78 if (of_address_to_resource(np, 0, &r)) {
80 printk(KERN_ERR "Could not map mpic register space\n"); 79 printk(KERN_ERR "Could not map mpic register space\n");
81 of_node_put(np); 80 of_node_put(np);
82 return; 81 return;
@@ -100,6 +99,7 @@ static void __init mpc85xx_ads_pic_init(void)
100 irq = irq_of_parse_and_map(np, 0); 99 irq = irq_of_parse_and_map(np, 0);
101 100
102 cpm2_pic_init(np); 101 cpm2_pic_init(np);
102 of_node_put(np);
103 set_irq_chained_handler(irq, cpm2_cascade); 103 set_irq_chained_handler(irq, cpm2_cascade);
104#endif 104#endif
105} 105}
@@ -112,7 +112,7 @@ struct cpm_pin {
112 int port, pin, flags; 112 int port, pin, flags;
113}; 113};
114 114
115static struct cpm_pin mpc8560_ads_pins[] = { 115static const struct cpm_pin mpc8560_ads_pins[] = {
116 /* SCC1 */ 116 /* SCC1 */
117 {3, 29, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, 117 {3, 29, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
118 {3, 30, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, 118 {3, 30, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
@@ -233,13 +233,11 @@ static struct of_device_id __initdata of_bus_ids[] = {
233 233
234static int __init declare_of_platform_devices(void) 234static int __init declare_of_platform_devices(void)
235{ 235{
236 if (!machine_is(mpc85xx_ads))
237 return 0;
238
239 of_platform_bus_probe(NULL, of_bus_ids, NULL); 236 of_platform_bus_probe(NULL, of_bus_ids, NULL);
237
240 return 0; 238 return 0;
241} 239}
242device_initcall(declare_of_platform_devices); 240machine_device_initcall(mpc85xx_ads, declare_of_platform_devices);
243 241
244/* 242/*
245 * Called very early, device-tree isn't unflattened 243 * Called very early, device-tree isn't unflattened
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index 4d063eec6210..8b1de7884be6 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -222,9 +222,6 @@ static int mpc85xx_cds_8259_attach(void)
222 struct device_node *cascade_node = NULL; 222 struct device_node *cascade_node = NULL;
223 int cascade_irq; 223 int cascade_irq;
224 224
225 if (!machine_is(mpc85xx_cds))
226 return 0;
227
228 /* Initialize the i8259 controller */ 225 /* Initialize the i8259 controller */
229 for_each_node_by_type(np, "interrupt-controller") 226 for_each_node_by_type(np, "interrupt-controller")
230 if (of_device_is_compatible(np, "chrp,iic")) { 227 if (of_device_is_compatible(np, "chrp,iic")) {
@@ -262,8 +259,7 @@ static int mpc85xx_cds_8259_attach(void)
262 259
263 return 0; 260 return 0;
264} 261}
265 262machine_device_initcall(mpc85xx_cds, mpc85xx_cds_8259_attach);
266device_initcall(mpc85xx_cds_8259_attach);
267 263
268#endif /* CONFIG_PPC_I8259 */ 264#endif /* CONFIG_PPC_I8259 */
269 265
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index 59c121a97ac7..bdb3d0b38cd2 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -123,7 +123,7 @@ static int mpc85xx_exclude_device(struct pci_controller *hose,
123 struct device_node* node; 123 struct device_node* node;
124 struct resource rsrc; 124 struct resource rsrc;
125 125
126 node = (struct device_node *)hose->arch_data; 126 node = hose->dn;
127 of_address_to_resource(node, 0, &rsrc); 127 of_address_to_resource(node, 0, &rsrc);
128 128
129 if ((rsrc.start & 0xfffff) == primary_phb_addr) { 129 if ((rsrc.start & 0xfffff) == primary_phb_addr) {
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 61b3eedf41b9..25f8bc75e838 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -30,9 +30,9 @@
30#include <linux/initrd.h> 30#include <linux/initrd.h>
31#include <linux/module.h> 31#include <linux/module.h>
32#include <linux/fsl_devices.h> 32#include <linux/fsl_devices.h>
33#include <linux/of_platform.h>
34#include <linux/of_device.h>
33 35
34#include <asm/of_device.h>
35#include <asm/of_platform.h>
36#include <asm/system.h> 36#include <asm/system.h>
37#include <asm/atomic.h> 37#include <asm/atomic.h>
38#include <asm/time.h> 38#include <asm/time.h>
@@ -94,21 +94,25 @@ static void __init mpc85xx_mds_setup_arch(void)
94#endif 94#endif
95 95
96#ifdef CONFIG_QUICC_ENGINE 96#ifdef CONFIG_QUICC_ENGINE
97 if ((np = of_find_node_by_name(NULL, "qe")) != NULL) { 97 np = of_find_compatible_node(NULL, NULL, "fsl,qe");
98 qe_reset(); 98 if (!np) {
99 of_node_put(np); 99 np = of_find_node_by_name(NULL, "qe");
100 if (!np)
101 return;
100 } 102 }
101 103
102 if ((np = of_find_node_by_name(NULL, "par_io")) != NULL) { 104 qe_reset();
103 struct device_node *ucc = NULL; 105 of_node_put(np);
106
107 np = of_find_node_by_name(NULL, "par_io");
108 if (np) {
109 struct device_node *ucc;
104 110
105 par_io_init(np); 111 par_io_init(np);
106 of_node_put(np); 112 of_node_put(np);
107 113
108 for ( ;(ucc = of_find_node_by_name(ucc, "ucc")) != NULL;) 114 for_each_node_by_name(ucc, "ucc")
109 par_io_of_config(ucc); 115 par_io_of_config(ucc);
110
111 of_node_put(ucc);
112 } 116 }
113 117
114 if (bcsr_regs) { 118 if (bcsr_regs) {
@@ -131,7 +135,6 @@ static void __init mpc85xx_mds_setup_arch(void)
131 135
132 iounmap(bcsr_regs); 136 iounmap(bcsr_regs);
133 } 137 }
134
135#endif /* CONFIG_QUICC_ENGINE */ 138#endif /* CONFIG_QUICC_ENGINE */
136} 139}
137 140
@@ -139,20 +142,18 @@ static struct of_device_id mpc85xx_ids[] = {
139 { .type = "soc", }, 142 { .type = "soc", },
140 { .compatible = "soc", }, 143 { .compatible = "soc", },
141 { .type = "qe", }, 144 { .type = "qe", },
145 { .compatible = "fsl,qe", },
142 {}, 146 {},
143}; 147};
144 148
145static int __init mpc85xx_publish_devices(void) 149static int __init mpc85xx_publish_devices(void)
146{ 150{
147 if (!machine_is(mpc85xx_mds))
148 return 0;
149
150 /* Publish the QE devices */ 151 /* Publish the QE devices */
151 of_platform_bus_probe(NULL,mpc85xx_ids,NULL); 152 of_platform_bus_probe(NULL, mpc85xx_ids, NULL);
152 153
153 return 0; 154 return 0;
154} 155}
155device_initcall(mpc85xx_publish_devices); 156machine_device_initcall(mpc85xx_mds, mpc85xx_publish_devices);
156 157
157static void __init mpc85xx_mds_pic_init(void) 158static void __init mpc85xx_mds_pic_init(void)
158{ 159{
@@ -179,10 +180,12 @@ static void __init mpc85xx_mds_pic_init(void)
179 mpic_init(mpic); 180 mpic_init(mpic);
180 181
181#ifdef CONFIG_QUICC_ENGINE 182#ifdef CONFIG_QUICC_ENGINE
182 np = of_find_node_by_type(NULL, "qeic"); 183 np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
183 if (!np) 184 if (!np) {
184 return; 185 np = of_find_node_by_type(NULL, "qeic");
185 186 if (!np)
187 return;
188 }
186 qe_ic_init(np, 0, qe_ic_cascade_muxed_mpic, NULL); 189 qe_ic_init(np, 0, qe_ic_cascade_muxed_mpic, NULL);
187 of_node_put(np); 190 of_node_put(np);
188#endif /* CONFIG_QUICC_ENGINE */ 191#endif /* CONFIG_QUICC_ENGINE */
diff --git a/arch/powerpc/platforms/85xx/sbc8548.c b/arch/powerpc/platforms/85xx/sbc8548.c
new file mode 100644
index 000000000000..488facb99fe8
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/sbc8548.c
@@ -0,0 +1,167 @@
1/*
2 * Wind River SBC8548 setup and early boot code.
3 *
4 * Copyright 2007 Wind River Systems Inc.
5 *
6 * By Paul Gortmaker (see MAINTAINERS for contact information)
7 *
8 * Based largely on the MPC8548CDS support - Copyright 2005 Freescale Inc.
9 *
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 */
16
17#include <linux/stddef.h>
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/errno.h>
21#include <linux/reboot.h>
22#include <linux/pci.h>
23#include <linux/kdev_t.h>
24#include <linux/major.h>
25#include <linux/console.h>
26#include <linux/delay.h>
27#include <linux/seq_file.h>
28#include <linux/initrd.h>
29#include <linux/module.h>
30#include <linux/interrupt.h>
31#include <linux/fsl_devices.h>
32#include <linux/of_platform.h>
33
34#include <asm/system.h>
35#include <asm/pgtable.h>
36#include <asm/page.h>
37#include <asm/atomic.h>
38#include <asm/time.h>
39#include <asm/io.h>
40#include <asm/machdep.h>
41#include <asm/ipic.h>
42#include <asm/pci-bridge.h>
43#include <asm/irq.h>
44#include <mm/mmu_decl.h>
45#include <asm/prom.h>
46#include <asm/udbg.h>
47#include <asm/mpic.h>
48
49#include <sysdev/fsl_soc.h>
50#include <sysdev/fsl_pci.h>
51
52static void __init sbc8548_pic_init(void)
53{
54 struct mpic *mpic;
55 struct resource r;
56 struct device_node *np = NULL;
57
58 np = of_find_node_by_type(np, "open-pic");
59
60 if (np == NULL) {
61 printk(KERN_ERR "Could not find open-pic node\n");
62 return;
63 }
64
65 if (of_address_to_resource(np, 0, &r)) {
66 printk(KERN_ERR "Failed to map mpic register space\n");
67 of_node_put(np);
68 return;
69 }
70
71 mpic = mpic_alloc(np, r.start,
72 MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
73 0, 256, " OpenPIC ");
74 BUG_ON(mpic == NULL);
75
76 /* Return the mpic node */
77 of_node_put(np);
78
79 mpic_init(mpic);
80}
81
82/*
83 * Setup the architecture
84 */
85static void __init sbc8548_setup_arch(void)
86{
87#ifdef CONFIG_PCI
88 struct device_node *np;
89#endif
90
91 if (ppc_md.progress)
92 ppc_md.progress("sbc8548_setup_arch()", 0);
93
94#ifdef CONFIG_PCI
95 for_each_node_by_type(np, "pci") {
96 if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
97 of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
98 struct resource rsrc;
99 of_address_to_resource(np, 0, &rsrc);
100 if ((rsrc.start & 0xfffff) == 0x8000)
101 fsl_add_bridge(np, 1);
102 else
103 fsl_add_bridge(np, 0);
104 }
105 }
106#endif
107}
108
109static void sbc8548_show_cpuinfo(struct seq_file *m)
110{
111 uint pvid, svid, phid1;
112 uint memsize = total_memory;
113
114 pvid = mfspr(SPRN_PVR);
115 svid = mfspr(SPRN_SVR);
116
117 seq_printf(m, "Vendor\t\t: Wind River\n");
118 seq_printf(m, "Machine\t\t: SBC8548\n");
119 seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
120 seq_printf(m, "SVR\t\t: 0x%x\n", svid);
121
122 /* Display cpu Pll setting */
123 phid1 = mfspr(SPRN_HID1);
124 seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
125
126 /* Display the amount of memory */
127 seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
128}
129
130static struct of_device_id __initdata of_bus_ids[] = {
131 { .name = "soc", },
132 { .type = "soc", },
133 {},
134};
135
136static int __init declare_of_platform_devices(void)
137{
138 of_platform_bus_probe(NULL, of_bus_ids, NULL);
139
140 return 0;
141}
142machine_device_initcall(sbc8548, declare_of_platform_devices);
143
144/*
145 * Called very early, device-tree isn't unflattened
146 */
147static int __init sbc8548_probe(void)
148{
149 unsigned long root = of_get_flat_dt_root();
150
151 return of_flat_dt_is_compatible(root, "SBC8548");
152}
153
154define_machine(sbc8548) {
155 .name = "SBC8548",
156 .probe = sbc8548_probe,
157 .setup_arch = sbc8548_setup_arch,
158 .init_IRQ = sbc8548_pic_init,
159 .show_cpuinfo = sbc8548_show_cpuinfo,
160 .get_irq = mpic_get_irq,
161 .restart = fsl_rstcr_restart,
162#ifdef CONFIG_PCI
163 .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
164#endif
165 .calibrate_decr = generic_calibrate_decr,
166 .progress = udbg_progress,
167};
diff --git a/arch/powerpc/platforms/85xx/sbc8560.c b/arch/powerpc/platforms/85xx/sbc8560.c
new file mode 100644
index 000000000000..2c580cd24e4f
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/sbc8560.c
@@ -0,0 +1,283 @@
1/*
2 * Wind River SBC8560 setup and early boot code.
3 *
4 * Copyright 2007 Wind River Systems Inc.
5 *
6 * By Paul Gortmaker (see MAINTAINERS for contact information)
7 *
8 * Based largely on the MPC8560ADS support - Copyright 2005 Freescale Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
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/delay.h>
21#include <linux/seq_file.h>
22#include <linux/of_platform.h>
23
24#include <asm/system.h>
25#include <asm/time.h>
26#include <asm/machdep.h>
27#include <asm/pci-bridge.h>
28#include <asm/mpic.h>
29#include <mm/mmu_decl.h>
30#include <asm/udbg.h>
31
32#include <sysdev/fsl_soc.h>
33#include <sysdev/fsl_pci.h>
34
35#ifdef CONFIG_CPM2
36#include <asm/cpm2.h>
37#include <sysdev/cpm2_pic.h>
38#endif
39
40#ifdef CONFIG_CPM2
41
42static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
43{
44 int cascade_irq;
45
46 while ((cascade_irq = cpm2_get_irq()) >= 0)
47 generic_handle_irq(cascade_irq);
48
49 desc->chip->eoi(irq);
50}
51
52#endif /* CONFIG_CPM2 */
53
54static void __init sbc8560_pic_init(void)
55{
56 struct mpic *mpic;
57 struct resource r;
58 struct device_node *np = NULL;
59#ifdef CONFIG_CPM2
60 int irq;
61#endif
62
63 np = of_find_node_by_type(np, "open-pic");
64 if (!np) {
65 printk(KERN_ERR "Could not find open-pic node\n");
66 return;
67 }
68
69 if (of_address_to_resource(np, 0, &r)) {
70 printk(KERN_ERR "Could not map mpic register space\n");
71 of_node_put(np);
72 return;
73 }
74
75 mpic = mpic_alloc(np, r.start,
76 MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
77 0, 256, " OpenPIC ");
78 BUG_ON(mpic == NULL);
79 of_node_put(np);
80
81 mpic_init(mpic);
82
83#ifdef CONFIG_CPM2
84 /* Setup CPM2 PIC */
85 np = of_find_compatible_node(NULL, NULL, "fsl,cpm2-pic");
86 if (np == NULL) {
87 printk(KERN_ERR "PIC init: can not find fsl,cpm2-pic node\n");
88 return;
89 }
90 irq = irq_of_parse_and_map(np, 0);
91
92 cpm2_pic_init(np);
93 of_node_put(np);
94 set_irq_chained_handler(irq, cpm2_cascade);
95#endif
96}
97
98/*
99 * Setup the architecture
100 */
101#ifdef CONFIG_CPM2
102struct cpm_pin {
103 int port, pin, flags;
104};
105
106static const struct cpm_pin sbc8560_pins[] = {
107 /* SCC1 */
108 {3, 29, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
109 {3, 30, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
110 {3, 31, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
111
112 /* SCC2 */
113 {3, 26, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
114 {3, 27, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
115 {3, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
116
117 /* FCC2 */
118 {1, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
119 {1, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
120 {1, 20, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
121 {1, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
122 {1, 22, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
123 {1, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
124 {1, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
125 {1, 25, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
126 {1, 26, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
127 {1, 27, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
128 {1, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
129 {1, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
130 {1, 30, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
131 {1, 31, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
132 {2, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* CLK14 */
133 {2, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* CLK13 */
134
135 /* FCC3 */
136 {1, 4, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
137 {1, 5, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
138 {1, 6, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
139 {1, 7, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
140 {1, 8, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
141 {1, 9, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
142 {1, 10, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
143 {1, 11, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
144 {1, 12, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
145 {1, 13, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
146 {1, 14, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
147 {1, 15, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
148 {1, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
149 {1, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
150 {2, 16, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* CLK16 */
151 {2, 17, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* CLK15 */
152};
153
154static void __init init_ioports(void)
155{
156 int i;
157
158 for (i = 0; i < ARRAY_SIZE(sbc8560_pins); i++) {
159 struct cpm_pin *pin = &sbc8560_pins[i];
160 cpm2_set_pin(pin->port, pin->pin, pin->flags);
161 }
162
163 cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_RX);
164 cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_TX);
165 cpm2_clk_setup(CPM_CLK_SCC2, CPM_BRG2, CPM_CLK_RX);
166 cpm2_clk_setup(CPM_CLK_SCC2, CPM_BRG2, CPM_CLK_TX);
167 cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK13, CPM_CLK_RX);
168 cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK14, CPM_CLK_TX);
169 cpm2_clk_setup(CPM_CLK_FCC3, CPM_CLK15, CPM_CLK_RX);
170 cpm2_clk_setup(CPM_CLK_FCC3, CPM_CLK16, CPM_CLK_TX);
171}
172#endif
173
174static void __init sbc8560_setup_arch(void)
175{
176#ifdef CONFIG_PCI
177 struct device_node *np;
178#endif
179
180 if (ppc_md.progress)
181 ppc_md.progress("sbc8560_setup_arch()", 0);
182
183#ifdef CONFIG_CPM2
184 cpm2_reset();
185 init_ioports();
186#endif
187
188#ifdef CONFIG_PCI
189 for_each_compatible_node(np, "pci", "fsl,mpc8540-pci")
190 fsl_add_bridge(np, 1);
191#endif
192}
193
194static void sbc8560_show_cpuinfo(struct seq_file *m)
195{
196 uint pvid, svid, phid1;
197 uint memsize = total_memory;
198
199 pvid = mfspr(SPRN_PVR);
200 svid = mfspr(SPRN_SVR);
201
202 seq_printf(m, "Vendor\t\t: Wind River\n");
203 seq_printf(m, "Machine\t\t: SBC8560\n");
204 seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
205 seq_printf(m, "SVR\t\t: 0x%x\n", svid);
206
207 /* Display cpu Pll setting */
208 phid1 = mfspr(SPRN_HID1);
209 seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
210
211 /* Display the amount of memory */
212 seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
213}
214
215static struct of_device_id __initdata of_bus_ids[] = {
216 { .name = "soc", },
217 { .type = "soc", },
218 { .name = "cpm", },
219 { .name = "localbus", },
220 {},
221};
222
223static int __init declare_of_platform_devices(void)
224{
225 of_platform_bus_probe(NULL, of_bus_ids, NULL);
226
227 return 0;
228}
229machine_device_initcall(sbc8560, declare_of_platform_devices);
230
231/*
232 * Called very early, device-tree isn't unflattened
233 */
234static int __init sbc8560_probe(void)
235{
236 unsigned long root = of_get_flat_dt_root();
237
238 return of_flat_dt_is_compatible(root, "SBC8560");
239}
240
241#ifdef CONFIG_RTC_DRV_M48T59
242static int __init sbc8560_rtc_init(void)
243{
244 struct device_node *np;
245 struct resource res;
246 struct platform_device *rtc_dev;
247
248 np = of_find_compatible_node(NULL, NULL, "m48t59");
249 if (np == NULL) {
250 printk("No RTC in DTB. Has it been eaten by wild dogs?\n");
251 return -ENODEV;
252 }
253
254 of_address_to_resource(np, 0, &res);
255 of_node_put(np);
256
257 printk("Found RTC (m48t59) at i/o 0x%x\n", res.start);
258
259 rtc_dev = platform_device_register_simple("rtc-m48t59", 0, &res, 1);
260
261 if (IS_ERR(rtc_dev)) {
262 printk("Registering sbc8560 RTC device failed\n");
263 return PTR_ERR(rtc_dev);
264 }
265
266 return 0;
267}
268
269arch_initcall(sbc8560_rtc_init);
270
271#endif /* M48T59 */
272
273define_machine(sbc8560) {
274 .name = "SBC8560",
275 .probe = sbc8560_probe,
276 .setup_arch = sbc8560_setup_arch,
277 .init_IRQ = sbc8560_pic_init,
278 .show_cpuinfo = sbc8560_show_cpuinfo,
279 .get_irq = mpic_get_irq,
280 .restart = fsl_rstcr_restart,
281 .calibrate_decr = generic_calibrate_decr,
282 .progress = udbg_progress,
283};
diff --git a/arch/powerpc/platforms/85xx/stx_gp3.c b/arch/powerpc/platforms/85xx/stx_gp3.c
new file mode 100644
index 000000000000..18499d7c9d9e
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/stx_gp3.c
@@ -0,0 +1,183 @@
1/*
2 * Based on MPC8560 ADS and arch/ppc stx_gp3 ports
3 *
4 * Maintained by Kumar Gala (see MAINTAINERS for contact information)
5 *
6 * Copyright 2008 Freescale Semiconductor Inc.
7 *
8 * Dan Malek <dan@embeddededge.com>
9 * Copyright 2004 Embedded Edge, LLC
10 *
11 * Copied from mpc8560_ads.c
12 * Copyright 2002, 2003 Motorola Inc.
13 *
14 * Ported to 2.6, Matt Porter <mporter@kernel.crashing.org>
15 * Copyright 2004-2005 MontaVista Software, Inc.
16 *
17 * This program is free software; you can redistribute it and/or modify it
18 * under the terms of the GNU General Public License as published by the
19 * Free Software Foundation; either version 2 of the License, or (at your
20 * option) any later version.
21 */
22
23#include <linux/stddef.h>
24#include <linux/kernel.h>
25#include <linux/pci.h>
26#include <linux/kdev_t.h>
27#include <linux/delay.h>
28#include <linux/seq_file.h>
29#include <linux/of_platform.h>
30
31#include <asm/system.h>
32#include <asm/time.h>
33#include <asm/machdep.h>
34#include <asm/pci-bridge.h>
35#include <asm/mpic.h>
36#include <asm/prom.h>
37#include <mm/mmu_decl.h>
38#include <asm/udbg.h>
39
40#include <sysdev/fsl_soc.h>
41#include <sysdev/fsl_pci.h>
42
43#ifdef CONFIG_CPM2
44#include <asm/cpm2.h>
45#include <sysdev/cpm2_pic.h>
46
47static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
48{
49 int cascade_irq;
50
51 while ((cascade_irq = cpm2_get_irq()) >= 0)
52 generic_handle_irq(cascade_irq);
53
54 desc->chip->eoi(irq);
55}
56#endif /* CONFIG_CPM2 */
57
58static void __init stx_gp3_pic_init(void)
59{
60 struct mpic *mpic;
61 struct resource r;
62 struct device_node *np;
63#ifdef CONFIG_CPM2
64 int irq;
65#endif
66
67 np = of_find_node_by_type(NULL, "open-pic");
68 if (!np) {
69 printk(KERN_ERR "Could not find open-pic node\n");
70 return;
71 }
72
73 if (of_address_to_resource(np, 0, &r)) {
74 printk(KERN_ERR "Could not map mpic register space\n");
75 of_node_put(np);
76 return;
77 }
78
79 mpic = mpic_alloc(np, r.start,
80 MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
81 0, 256, " OpenPIC ");
82 BUG_ON(mpic == NULL);
83 of_node_put(np);
84
85 mpic_init(mpic);
86
87#ifdef CONFIG_CPM2
88 /* Setup CPM2 PIC */
89 np = of_find_compatible_node(NULL, NULL, "fsl,cpm2-pic");
90 if (np == NULL) {
91 printk(KERN_ERR "PIC init: can not find fsl,cpm2-pic node\n");
92 return;
93 }
94 irq = irq_of_parse_and_map(np, 0);
95
96 if (irq == NO_IRQ) {
97 of_node_put(np);
98 printk(KERN_ERR "PIC init: got no IRQ for cpm cascade\n");
99 return;
100 }
101
102 cpm2_pic_init(np);
103 of_node_put(np);
104 set_irq_chained_handler(irq, cpm2_cascade);
105#endif
106}
107
108/*
109 * Setup the architecture
110 */
111static void __init stx_gp3_setup_arch(void)
112{
113#ifdef CONFIG_PCI
114 struct device_node *np;
115#endif
116
117 if (ppc_md.progress)
118 ppc_md.progress("stx_gp3_setup_arch()", 0);
119
120#ifdef CONFIG_CPM2
121 cpm2_reset();
122#endif
123
124#ifdef CONFIG_PCI
125 for_each_compatible_node(np, "pci", "fsl,mpc8540-pci")
126 fsl_add_bridge(np, 1);
127#endif
128}
129
130static void stx_gp3_show_cpuinfo(struct seq_file *m)
131{
132 uint pvid, svid, phid1;
133 uint memsize = total_memory;
134
135 pvid = mfspr(SPRN_PVR);
136 svid = mfspr(SPRN_SVR);
137
138 seq_printf(m, "Vendor\t\t: RPC Electronics STx \n");
139 seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
140 seq_printf(m, "SVR\t\t: 0x%x\n", svid);
141
142 /* Display cpu Pll setting */
143 phid1 = mfspr(SPRN_HID1);
144 seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
145
146 /* Display the amount of memory */
147 seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
148}
149
150static struct of_device_id __initdata of_bus_ids[] = {
151 { .compatible = "simple-bus", },
152 {},
153};
154
155static int __init declare_of_platform_devices(void)
156{
157 of_platform_bus_probe(NULL, of_bus_ids, NULL);
158
159 return 0;
160}
161machine_device_initcall(stx_gp3, declare_of_platform_devices);
162
163/*
164 * Called very early, device-tree isn't unflattened
165 */
166static int __init stx_gp3_probe(void)
167{
168 unsigned long root = of_get_flat_dt_root();
169
170 return of_flat_dt_is_compatible(root, "stx,gp3-8560");
171}
172
173define_machine(stx_gp3) {
174 .name = "STX GP3",
175 .probe = stx_gp3_probe,
176 .setup_arch = stx_gp3_setup_arch,
177 .init_IRQ = stx_gp3_pic_init,
178 .show_cpuinfo = stx_gp3_show_cpuinfo,
179 .get_irq = mpic_get_irq,
180 .restart = fsl_rstcr_restart,
181 .calibrate_decr = generic_calibrate_decr,
182 .progress = udbg_progress,
183};
diff --git a/arch/powerpc/platforms/85xx/tqm85xx.c b/arch/powerpc/platforms/85xx/tqm85xx.c
new file mode 100644
index 000000000000..77681acf1bae
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/tqm85xx.c
@@ -0,0 +1,187 @@
1/*
2 * Based on MPC8560 ADS and arch/ppc tqm85xx ports
3 *
4 * Maintained by Kumar Gala (see MAINTAINERS for contact information)
5 *
6 * Copyright 2008 Freescale Semiconductor Inc.
7 *
8 * Copyright (c) 2005-2006 DENX Software Engineering
9 * Stefan Roese <sr@denx.de>
10 *
11 * Based on original work by
12 * Kumar Gala <kumar.gala@freescale.com>
13 * Copyright 2004 Freescale Semiconductor Inc.
14 *
15 * This program is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License as published by the
17 * Free Software Foundation; either version 2 of the License, or (at your
18 * option) any later version.
19 */
20
21#include <linux/stddef.h>
22#include <linux/kernel.h>
23#include <linux/pci.h>
24#include <linux/kdev_t.h>
25#include <linux/delay.h>
26#include <linux/seq_file.h>
27#include <linux/of_platform.h>
28
29#include <asm/system.h>
30#include <asm/time.h>
31#include <asm/machdep.h>
32#include <asm/pci-bridge.h>
33#include <asm/mpic.h>
34#include <asm/prom.h>
35#include <mm/mmu_decl.h>
36#include <asm/udbg.h>
37
38#include <sysdev/fsl_soc.h>
39#include <sysdev/fsl_pci.h>
40
41#ifdef CONFIG_CPM2
42#include <asm/cpm2.h>
43#include <sysdev/cpm2_pic.h>
44
45static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
46{
47 int cascade_irq;
48
49 while ((cascade_irq = cpm2_get_irq()) >= 0)
50 generic_handle_irq(cascade_irq);
51
52 desc->chip->eoi(irq);
53}
54#endif /* CONFIG_CPM2 */
55
56static void __init tqm85xx_pic_init(void)
57{
58 struct mpic *mpic;
59 struct resource r;
60 struct device_node *np;
61#ifdef CONFIG_CPM2
62 int irq;
63#endif
64
65 np = of_find_node_by_type(NULL, "open-pic");
66 if (!np) {
67 printk(KERN_ERR "Could not find open-pic node\n");
68 return;
69 }
70
71 if (of_address_to_resource(np, 0, &r)) {
72 printk(KERN_ERR "Could not map mpic register space\n");
73 of_node_put(np);
74 return;
75 }
76
77 mpic = mpic_alloc(np, r.start,
78 MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
79 0, 256, " OpenPIC ");
80 BUG_ON(mpic == NULL);
81 of_node_put(np);
82
83 mpic_init(mpic);
84
85#ifdef CONFIG_CPM2
86 /* Setup CPM2 PIC */
87 np = of_find_compatible_node(NULL, NULL, "fsl,cpm2-pic");
88 if (np == NULL) {
89 printk(KERN_ERR "PIC init: can not find fsl,cpm2-pic node\n");
90 return;
91 }
92 irq = irq_of_parse_and_map(np, 0);
93
94 if (irq == NO_IRQ) {
95 of_node_put(np);
96 printk(KERN_ERR "PIC init: got no IRQ for cpm cascade\n");
97 return;
98 }
99
100 cpm2_pic_init(np);
101 of_node_put(np);
102 set_irq_chained_handler(irq, cpm2_cascade);
103#endif
104}
105
106/*
107 * Setup the architecture
108 */
109static void __init tqm85xx_setup_arch(void)
110{
111#ifdef CONFIG_PCI
112 struct device_node *np;
113#endif
114
115 if (ppc_md.progress)
116 ppc_md.progress("tqm85xx_setup_arch()", 0);
117
118#ifdef CONFIG_CPM2
119 cpm2_reset();
120#endif
121
122#ifdef CONFIG_PCI
123 for_each_compatible_node(np, "pci", "fsl,mpc8540-pci")
124 fsl_add_bridge(np, 1);
125#endif
126}
127
128static void tqm85xx_show_cpuinfo(struct seq_file *m)
129{
130 uint pvid, svid, phid1;
131 uint memsize = total_memory;
132
133 pvid = mfspr(SPRN_PVR);
134 svid = mfspr(SPRN_SVR);
135
136 seq_printf(m, "Vendor\t\t: TQ Components\n");
137 seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
138 seq_printf(m, "SVR\t\t: 0x%x\n", svid);
139
140 /* Display cpu Pll setting */
141 phid1 = mfspr(SPRN_HID1);
142 seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
143
144 /* Display the amount of memory */
145 seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
146}
147
148static struct of_device_id __initdata of_bus_ids[] = {
149 { .compatible = "simple-bus", },
150 {},
151};
152
153static int __init declare_of_platform_devices(void)
154{
155 of_platform_bus_probe(NULL, of_bus_ids, NULL);
156
157 return 0;
158}
159machine_device_initcall(tqm85xx, declare_of_platform_devices);
160
161/*
162 * Called very early, device-tree isn't unflattened
163 */
164static int __init tqm85xx_probe(void)
165{
166 unsigned long root = of_get_flat_dt_root();
167
168 if ((of_flat_dt_is_compatible(root, "tqm,8540")) ||
169 (of_flat_dt_is_compatible(root, "tqm,8541")) ||
170 (of_flat_dt_is_compatible(root, "tqm,8555")) ||
171 (of_flat_dt_is_compatible(root, "tqm,8560")))
172 return 1;
173
174 return 0;
175}
176
177define_machine(tqm85xx) {
178 .name = "TQM85xx",
179 .probe = tqm85xx_probe,
180 .setup_arch = tqm85xx_setup_arch,
181 .init_IRQ = tqm85xx_pic_init,
182 .show_cpuinfo = tqm85xx_show_cpuinfo,
183 .get_irq = mpic_get_irq,
184 .restart = fsl_rstcr_restart,
185 .calibrate_decr = generic_calibrate_decr,
186 .progress = udbg_progress,
187};
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index 6390895e5e92..0b07485641fe 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -34,9 +34,24 @@
34 34
35#include <asm/mpic.h> 35#include <asm/mpic.h>
36 36
37#include <linux/of_platform.h>
37#include <sysdev/fsl_pci.h> 38#include <sysdev/fsl_pci.h>
38#include <sysdev/fsl_soc.h> 39#include <sysdev/fsl_soc.h>
39 40
41static struct of_device_id __initdata mpc8610_ids[] = {
42 { .compatible = "fsl,mpc8610-immr", },
43 {}
44};
45
46static int __init mpc8610_declare_of_platform_devices(void)
47{
48 /* Without this call, the SSI device driver won't get probed. */
49 of_platform_bus_probe(NULL, mpc8610_ids, NULL);
50
51 return 0;
52}
53machine_device_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices);
54
40void __init 55void __init
41mpc86xx_hpcd_init_irq(void) 56mpc86xx_hpcd_init_irq(void)
42{ 57{
@@ -124,7 +139,7 @@ static void __devinit quirk_uli5229(struct pci_dev *dev)
124static void __devinit final_uli5288(struct pci_dev *dev) 139static void __devinit final_uli5288(struct pci_dev *dev)
125{ 140{
126 struct pci_controller *hose = pci_bus_to_host(dev->bus); 141 struct pci_controller *hose = pci_bus_to_host(dev->bus);
127 struct device_node *hosenode = hose ? hose->arch_data : NULL; 142 struct device_node *hosenode = hose ? hose->dn : NULL;
128 struct of_irq oirq; 143 struct of_irq oirq;
129 int virq, pin = 2; 144 int virq, pin = 2;
130 u32 laddr[3]; 145 u32 laddr[3];
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 32a531aebcb7..cfbe8c52e263 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -18,6 +18,7 @@
18#include <linux/kdev_t.h> 18#include <linux/kdev_t.h>
19#include <linux/delay.h> 19#include <linux/delay.h>
20#include <linux/seq_file.h> 20#include <linux/seq_file.h>
21#include <linux/of_platform.h>
21 22
22#include <asm/system.h> 23#include <asm/system.h>
23#include <asm/time.h> 24#include <asm/time.h>
@@ -116,7 +117,7 @@ static int mpc86xx_exclude_device(struct pci_controller *hose,
116 struct device_node* node; 117 struct device_node* node;
117 struct resource rsrc; 118 struct resource rsrc;
118 119
119 node = (struct device_node *)hose->arch_data; 120 node = hose->dn;
120 of_address_to_resource(node, 0, &rsrc); 121 of_address_to_resource(node, 0, &rsrc);
121 122
122 if ((rsrc.start & 0xfffff) == 0x8000) { 123 if ((rsrc.start & 0xfffff) == 0x8000) {
@@ -212,6 +213,19 @@ mpc86xx_time_init(void)
212 return 0; 213 return 0;
213} 214}
214 215
216static __initdata struct of_device_id of_bus_ids[] = {
217 { .compatible = "simple-bus", },
218 {},
219};
220
221static int __init declare_of_platform_devices(void)
222{
223 of_platform_bus_probe(NULL, of_bus_ids, NULL);
224
225 return 0;
226}
227machine_device_initcall(mpc86xx_hpcn, declare_of_platform_devices);
228
215define_machine(mpc86xx_hpcn) { 229define_machine(mpc86xx_hpcn) {
216 .name = "MPC86xx HPCN", 230 .name = "MPC86xx HPCN",
217 .probe = mpc86xx_hpcn_probe, 231 .probe = mpc86xx_hpcn_probe,
diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig
index bd28655043a0..7fd224ca233d 100644
--- a/arch/powerpc/platforms/8xx/Kconfig
+++ b/arch/powerpc/platforms/8xx/Kconfig
@@ -18,6 +18,7 @@ config MPC8XXFADS
18config MPC86XADS 18config MPC86XADS
19 bool "MPC86XADS" 19 bool "MPC86XADS"
20 select CPM1 20 select CPM1
21 select PPC_CPM_NEW_BINDING
21 help 22 help
22 MPC86x Application Development System by Freescale Semiconductor. 23 MPC86x Application Development System by Freescale Semiconductor.
23 The MPC86xADS is meant to serve as a platform for s/w and h/w 24 The MPC86xADS is meant to serve as a platform for s/w and h/w
@@ -43,6 +44,15 @@ config PPC_EP88XC
43 This board is also resold by Freescale as the QUICCStart 44 This board is also resold by Freescale as the QUICCStart
44 MPC885 Evaluation System and/or the CWH-PPC-885XN-VE. 45 MPC885 Evaluation System and/or the CWH-PPC-885XN-VE.
45 46
47config PPC_ADDER875
48 bool "Analogue & Micro Adder 875"
49 select CPM1
50 select PPC_CPM_NEW_BINDING
51 select REDBOOT
52 help
53 This enables support for the Analogue & Micro Adder 875
54 board.
55
46endchoice 56endchoice
47 57
48menu "Freescale Ethernet driver platform-specific options" 58menu "Freescale Ethernet driver platform-specific options"
diff --git a/arch/powerpc/platforms/8xx/Makefile b/arch/powerpc/platforms/8xx/Makefile
index 8b7098018b59..7b71d9c8fb45 100644
--- a/arch/powerpc/platforms/8xx/Makefile
+++ b/arch/powerpc/platforms/8xx/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_PPC_8xx) += m8xx_setup.o
5obj-$(CONFIG_MPC885ADS) += mpc885ads_setup.o 5obj-$(CONFIG_MPC885ADS) += mpc885ads_setup.o
6obj-$(CONFIG_MPC86XADS) += mpc86xads_setup.o 6obj-$(CONFIG_MPC86XADS) += mpc86xads_setup.o
7obj-$(CONFIG_PPC_EP88XC) += ep88xc.o 7obj-$(CONFIG_PPC_EP88XC) += ep88xc.o
8obj-$(CONFIG_PPC_ADDER875) += adder875.o
diff --git a/arch/powerpc/platforms/8xx/adder875.c b/arch/powerpc/platforms/8xx/adder875.c
new file mode 100644
index 000000000000..c6bc0783c3b0
--- /dev/null
+++ b/arch/powerpc/platforms/8xx/adder875.c
@@ -0,0 +1,118 @@
1/* Analogue & Micro Adder MPC875 board support
2 *
3 * Author: Scott Wood <scottwood@freescale.com>
4 *
5 * Copyright (c) 2007 Freescale Semiconductor, Inc.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License, version 2, as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/init.h>
13#include <linux/fs_enet_pd.h>
14#include <linux/of_platform.h>
15
16#include <asm/time.h>
17#include <asm/machdep.h>
18#include <asm/commproc.h>
19#include <asm/fs_pd.h>
20#include <asm/udbg.h>
21#include <asm/prom.h>
22
23#include <sysdev/commproc.h>
24
25struct cpm_pin {
26 int port, pin, flags;
27};
28
29static __initdata struct cpm_pin adder875_pins[] = {
30 /* SMC1 */
31 {CPM_PORTB, 24, CPM_PIN_INPUT}, /* RX */
32 {CPM_PORTB, 25, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TX */
33
34 /* MII1 */
35 {CPM_PORTA, 0, CPM_PIN_INPUT},
36 {CPM_PORTA, 1, CPM_PIN_INPUT},
37 {CPM_PORTA, 2, CPM_PIN_INPUT},
38 {CPM_PORTA, 3, CPM_PIN_INPUT},
39 {CPM_PORTA, 4, CPM_PIN_OUTPUT},
40 {CPM_PORTA, 10, CPM_PIN_OUTPUT},
41 {CPM_PORTA, 11, CPM_PIN_OUTPUT},
42 {CPM_PORTB, 19, CPM_PIN_INPUT},
43 {CPM_PORTB, 31, CPM_PIN_INPUT},
44 {CPM_PORTC, 12, CPM_PIN_INPUT},
45 {CPM_PORTC, 13, CPM_PIN_INPUT},
46 {CPM_PORTE, 30, CPM_PIN_OUTPUT},
47 {CPM_PORTE, 31, CPM_PIN_OUTPUT},
48
49 /* MII2 */
50 {CPM_PORTE, 14, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
51 {CPM_PORTE, 15, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
52 {CPM_PORTE, 16, CPM_PIN_OUTPUT},
53 {CPM_PORTE, 17, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
54 {CPM_PORTE, 18, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
55 {CPM_PORTE, 19, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
56 {CPM_PORTE, 20, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
57 {CPM_PORTE, 21, CPM_PIN_OUTPUT},
58 {CPM_PORTE, 22, CPM_PIN_OUTPUT},
59 {CPM_PORTE, 23, CPM_PIN_OUTPUT},
60 {CPM_PORTE, 24, CPM_PIN_OUTPUT},
61 {CPM_PORTE, 25, CPM_PIN_OUTPUT},
62 {CPM_PORTE, 26, CPM_PIN_OUTPUT},
63 {CPM_PORTE, 27, CPM_PIN_OUTPUT},
64 {CPM_PORTE, 28, CPM_PIN_OUTPUT},
65 {CPM_PORTE, 29, CPM_PIN_OUTPUT},
66};
67
68static void __init init_ioports(void)
69{
70 int i;
71
72 for (i = 0; i < ARRAY_SIZE(adder875_pins); i++) {
73 const struct cpm_pin *pin = &adder875_pins[i];
74 cpm1_set_pin(pin->port, pin->pin, pin->flags);
75 }
76
77 cpm1_clk_setup(CPM_CLK_SMC1, CPM_BRG1, CPM_CLK_RTX);
78
79 /* Set FEC1 and FEC2 to MII mode */
80 clrbits32(&mpc8xx_immr->im_cpm.cp_cptr, 0x00000180);
81}
82
83static void __init adder875_setup(void)
84{
85 cpm_reset();
86 init_ioports();
87}
88
89static int __init adder875_probe(void)
90{
91 unsigned long root = of_get_flat_dt_root();
92 return of_flat_dt_is_compatible(root, "analogue-and-micro,adder875");
93}
94
95static __initdata struct of_device_id of_bus_ids[] = {
96 { .compatible = "simple-bus", },
97 {},
98};
99
100static int __init declare_of_platform_devices(void)
101{
102 of_platform_bus_probe(NULL, of_bus_ids, NULL);
103 return 0;
104}
105machine_device_initcall(adder875, declare_of_platform_devices);
106
107define_machine(adder875) {
108 .name = "Adder MPC875",
109 .probe = adder875_probe,
110 .setup_arch = adder875_setup,
111 .init_IRQ = m8xx_pic_init,
112 .get_irq = mpc8xx_get_irq,
113 .restart = mpc8xx_restart,
114 .calibrate_decr = generic_calibrate_decr,
115 .set_rtc_time = mpc8xx_set_rtc_time,
116 .get_rtc_time = mpc8xx_get_rtc_time,
117 .progress = udbg_progress,
118};
diff --git a/arch/powerpc/platforms/8xx/ep88xc.c b/arch/powerpc/platforms/8xx/ep88xc.c
index c518b6cc5fab..a8dffa005775 100644
--- a/arch/powerpc/platforms/8xx/ep88xc.c
+++ b/arch/powerpc/platforms/8xx/ep88xc.c
@@ -16,8 +16,9 @@
16#include <asm/io.h> 16#include <asm/io.h>
17#include <asm/udbg.h> 17#include <asm/udbg.h>
18#include <asm/commproc.h> 18#include <asm/commproc.h>
19#include <asm/cpm1.h>
19 20
20#include <sysdev/commproc.h> 21#include "mpc8xx.h"
21 22
22struct cpm_pin { 23struct cpm_pin {
23 int port, pin, flags; 24 int port, pin, flags;
@@ -155,18 +156,17 @@ static struct of_device_id __initdata of_bus_ids[] = {
155static int __init declare_of_platform_devices(void) 156static int __init declare_of_platform_devices(void)
156{ 157{
157 /* Publish the QE devices */ 158 /* Publish the QE devices */
158 if (machine_is(ep88xc)) 159 of_platform_bus_probe(NULL, of_bus_ids, NULL);
159 of_platform_bus_probe(NULL, of_bus_ids, NULL);
160 160
161 return 0; 161 return 0;
162} 162}
163device_initcall(declare_of_platform_devices); 163machine_device_initcall(ep88xc, declare_of_platform_devices);
164 164
165define_machine(ep88xc) { 165define_machine(ep88xc) {
166 .name = "Embedded Planet EP88xC", 166 .name = "Embedded Planet EP88xC",
167 .probe = ep88xc_probe, 167 .probe = ep88xc_probe,
168 .setup_arch = ep88xc_setup_arch, 168 .setup_arch = ep88xc_setup_arch,
169 .init_IRQ = m8xx_pic_init, 169 .init_IRQ = mpc8xx_pics_init,
170 .get_irq = mpc8xx_get_irq, 170 .get_irq = mpc8xx_get_irq,
171 .restart = mpc8xx_restart, 171 .restart = mpc8xx_restart,
172 .calibrate_decr = mpc8xx_calibrate_decr, 172 .calibrate_decr = mpc8xx_calibrate_decr,
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c
index d35eda80e9e6..184f998d1be2 100644
--- a/arch/powerpc/platforms/8xx/m8xx_setup.c
+++ b/arch/powerpc/platforms/8xx/m8xx_setup.c
@@ -16,6 +16,7 @@
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/time.h> 17#include <linux/time.h>
18#include <linux/rtc.h> 18#include <linux/rtc.h>
19#include <linux/fsl_devices.h>
19 20
20#include <asm/io.h> 21#include <asm/io.h>
21#include <asm/mpc8xx.h> 22#include <asm/mpc8xx.h>
@@ -25,13 +26,11 @@
25#include <mm/mmu_decl.h> 26#include <mm/mmu_decl.h>
26 27
27#include <sysdev/mpc8xx_pic.h> 28#include <sysdev/mpc8xx_pic.h>
28#include <sysdev/commproc.h>
29 29
30#ifdef CONFIG_PCMCIA_M8XX 30#include "mpc8xx.h"
31
31struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops; 32struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops;
32#endif
33 33
34void m8xx_calibrate_decr(void);
35extern int cpm_pic_init(void); 34extern int cpm_pic_init(void);
36extern int cpm_get_irq(void); 35extern int cpm_get_irq(void);
37 36
@@ -120,7 +119,7 @@ void __init mpc8xx_calibrate_decr(void)
120 ppc_tb_freq /= 16; 119 ppc_tb_freq /= 16;
121 ppc_proc_freq = 50000000; 120 ppc_proc_freq = 50000000;
122 if (!get_freq("clock-frequency", &ppc_proc_freq)) 121 if (!get_freq("clock-frequency", &ppc_proc_freq))
123 printk(KERN_ERR "WARNING: Estimating processor frequency" 122 printk(KERN_ERR "WARNING: Estimating processor frequency "
124 "(not found)\n"); 123 "(not found)\n");
125 124
126 printk("Decrementer Frequency = 0x%lx\n", ppc_tb_freq); 125 printk("Decrementer Frequency = 0x%lx\n", ppc_tb_freq);
@@ -237,13 +236,13 @@ static void cpm_cascade(unsigned int irq, struct irq_desc *desc)
237 desc->chip->eoi(irq); 236 desc->chip->eoi(irq);
238} 237}
239 238
240/* Initialize the internal interrupt controller. The number of 239/* Initialize the internal interrupt controllers. The number of
241 * interrupts supported can vary with the processor type, and the 240 * interrupts supported can vary with the processor type, and the
242 * 82xx family can have up to 64. 241 * 82xx family can have up to 64.
243 * External interrupts can be either edge or level triggered, and 242 * External interrupts can be either edge or level triggered, and
244 * need to be initialized by the appropriate driver. 243 * need to be initialized by the appropriate driver.
245 */ 244 */
246void __init m8xx_pic_init(void) 245void __init mpc8xx_pics_init(void)
247{ 246{
248 int irq; 247 int irq;
249 248
diff --git a/arch/powerpc/platforms/8xx/mpc86xads.h b/arch/powerpc/platforms/8xx/mpc86xads.h
index cffa194ccf1f..17b1fe75e0b2 100644
--- a/arch/powerpc/platforms/8xx/mpc86xads.h
+++ b/arch/powerpc/platforms/8xx/mpc86xads.h
@@ -15,27 +15,6 @@
15#ifndef __ASM_MPC86XADS_H__ 15#ifndef __ASM_MPC86XADS_H__
16#define __ASM_MPC86XADS_H__ 16#define __ASM_MPC86XADS_H__
17 17
18#include <sysdev/fsl_soc.h>
19
20/* U-Boot maps BCSR to 0xff080000 */
21#define BCSR_ADDR ((uint)0xff080000)
22#define BCSR_SIZE ((uint)32)
23#define BCSR0 ((uint)(BCSR_ADDR + 0x00))
24#define BCSR1 ((uint)(BCSR_ADDR + 0x04))
25#define BCSR2 ((uint)(BCSR_ADDR + 0x08))
26#define BCSR3 ((uint)(BCSR_ADDR + 0x0c))
27#define BCSR4 ((uint)(BCSR_ADDR + 0x10))
28
29#define CFG_PHYDEV_ADDR ((uint)0xff0a0000)
30#define BCSR5 ((uint)(CFG_PHYDEV_ADDR + 0x300))
31
32#define MPC8xx_CPM_OFFSET (0x9c0)
33#define CPM_MAP_ADDR (get_immrbase() + MPC8xx_CPM_OFFSET)
34#define CPM_IRQ_OFFSET 16 // for compability with cpm_uart driver
35
36#define PCMCIA_MEM_ADDR ((uint)0xff020000)
37#define PCMCIA_MEM_SIZE ((uint)(64 * 1024))
38
39/* Bits of interest in the BCSRs. 18/* Bits of interest in the BCSRs.
40 */ 19 */
41#define BCSR1_ETHEN ((uint)0x20000000) 20#define BCSR1_ETHEN ((uint)0x20000000)
@@ -64,28 +43,5 @@
64#define BCSR5_MII1_EN 0x02 43#define BCSR5_MII1_EN 0x02
65#define BCSR5_MII1_RST 0x01 44#define BCSR5_MII1_RST 0x01
66 45
67/* Interrupt level assignments */
68#define PHY_INTERRUPT SIU_IRQ7 /* PHY link change interrupt */
69#define SIU_INT_FEC1 SIU_LEVEL1 /* FEC1 interrupt */
70#define FEC_INTERRUPT SIU_INT_FEC1 /* FEC interrupt */
71
72/* We don't use the 8259 */
73#define NR_8259_INTS 0
74
75/* CPM Ethernet through SCC1 */
76#define PA_ENET_RXD ((ushort)0x0001)
77#define PA_ENET_TXD ((ushort)0x0002)
78#define PA_ENET_TCLK ((ushort)0x0100)
79#define PA_ENET_RCLK ((ushort)0x0200)
80#define PB_ENET_TENA ((uint)0x00001000)
81#define PC_ENET_CLSN ((ushort)0x0010)
82#define PC_ENET_RENA ((ushort)0x0020)
83
84/* Control bits in the SICR to route TCLK (CLK1) and RCLK (CLK2) to
85 * SCC1. Also, make sure GR1 (bit 24) and SC1 (bit 25) are zero.
86 */
87#define SICR_ENET_MASK ((uint)0x000000ff)
88#define SICR_ENET_CLKRT ((uint)0x0000002c)
89
90#endif /* __ASM_MPC86XADS_H__ */ 46#endif /* __ASM_MPC86XADS_H__ */
91#endif /* __KERNEL__ */ 47#endif /* __KERNEL__ */
diff --git a/arch/powerpc/platforms/8xx/mpc86xads_setup.c b/arch/powerpc/platforms/8xx/mpc86xads_setup.c
index 49012835f453..c028a5b71bbb 100644
--- a/arch/powerpc/platforms/8xx/mpc86xads_setup.c
+++ b/arch/powerpc/platforms/8xx/mpc86xads_setup.c
@@ -6,273 +6,141 @@
6 * 6 *
7 * Copyright 2005 MontaVista Software Inc. 7 * Copyright 2005 MontaVista Software Inc.
8 * 8 *
9 * Heavily modified by Scott Wood <scottwood@freescale.com>
10 * Copyright 2007 Freescale Semiconductor, Inc.
11 *
9 * This file is licensed under the terms of the GNU General Public License 12 * This file is licensed under the terms of the GNU General Public License
10 * version 2. This program is licensed "as is" without any warranty of any 13 * version 2. This program is licensed "as is" without any warranty of any
11 * kind, whether express or implied. 14 * kind, whether express or implied.
12 */ 15 */
13 16
14#include <linux/init.h> 17#include <linux/init.h>
15#include <linux/module.h> 18#include <linux/of_platform.h>
16#include <linux/param.h>
17#include <linux/string.h>
18#include <linux/ioport.h>
19#include <linux/device.h>
20#include <linux/delay.h>
21#include <linux/root_dev.h>
22
23#include <linux/fs_enet_pd.h>
24#include <linux/fs_uart_pd.h>
25#include <linux/mii.h>
26 19
27#include <asm/delay.h>
28#include <asm/io.h> 20#include <asm/io.h>
29#include <asm/machdep.h> 21#include <asm/machdep.h>
30#include <asm/page.h>
31#include <asm/processor.h>
32#include <asm/system.h> 22#include <asm/system.h>
33#include <asm/time.h> 23#include <asm/time.h>
34#include <asm/mpc8xx.h>
35#include <asm/8xx_immap.h> 24#include <asm/8xx_immap.h>
36#include <asm/commproc.h> 25#include <asm/cpm1.h>
37#include <asm/fs_pd.h> 26#include <asm/fs_pd.h>
38#include <asm/prom.h> 27#include <asm/udbg.h>
39 28
40#include <sysdev/commproc.h> 29#include "mpc86xads.h"
30#include "mpc8xx.h"
41 31
42static void init_smc1_uart_ioports(struct fs_uart_platform_info* fpi); 32struct cpm_pin {
43static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi); 33 int port, pin, flags;
44static void init_scc1_ioports(struct fs_platform_info* ptr); 34};
45 35
46void __init mpc86xads_board_setup(void) 36static struct cpm_pin mpc866ads_pins[] = {
47{ 37 /* SMC1 */
48 cpm8xx_t *cp; 38 {CPM_PORTB, 24, CPM_PIN_INPUT}, /* RX */
49 unsigned int *bcsr_io; 39 {CPM_PORTB, 25, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TX */
50 u8 tmpval8; 40
41 /* SMC2 */
42 {CPM_PORTB, 21, CPM_PIN_INPUT}, /* RX */
43 {CPM_PORTB, 20, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TX */
44
45 /* SCC1 */
46 {CPM_PORTA, 6, CPM_PIN_INPUT}, /* CLK1 */
47 {CPM_PORTA, 7, CPM_PIN_INPUT}, /* CLK2 */
48 {CPM_PORTA, 14, CPM_PIN_INPUT}, /* TX */
49 {CPM_PORTA, 15, CPM_PIN_INPUT}, /* RX */
50 {CPM_PORTB, 19, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TENA */
51 {CPM_PORTC, 10, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_GPIO}, /* RENA */
52 {CPM_PORTC, 11, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_GPIO}, /* CLSN */
53
54 /* MII */
55 {CPM_PORTD, 3, CPM_PIN_OUTPUT},
56 {CPM_PORTD, 4, CPM_PIN_OUTPUT},
57 {CPM_PORTD, 5, CPM_PIN_OUTPUT},
58 {CPM_PORTD, 6, CPM_PIN_OUTPUT},
59 {CPM_PORTD, 7, CPM_PIN_OUTPUT},
60 {CPM_PORTD, 8, CPM_PIN_OUTPUT},
61 {CPM_PORTD, 9, CPM_PIN_OUTPUT},
62 {CPM_PORTD, 10, CPM_PIN_OUTPUT},
63 {CPM_PORTD, 11, CPM_PIN_OUTPUT},
64 {CPM_PORTD, 12, CPM_PIN_OUTPUT},
65 {CPM_PORTD, 13, CPM_PIN_OUTPUT},
66 {CPM_PORTD, 14, CPM_PIN_OUTPUT},
67 {CPM_PORTD, 15, CPM_PIN_OUTPUT},
68};
51 69
52 bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); 70static void __init init_ioports(void)
53 cp = (cpm8xx_t *)immr_map(im_cpm); 71{
72 int i;
54 73
55 if (bcsr_io == NULL) { 74 for (i = 0; i < ARRAY_SIZE(mpc866ads_pins); i++) {
56 printk(KERN_CRIT "Could not remap BCSR\n"); 75 struct cpm_pin *pin = &mpc866ads_pins[i];
57 return; 76 cpm1_set_pin(pin->port, pin->pin, pin->flags);
58 } 77 }
59#ifdef CONFIG_SERIAL_CPM_SMC1
60 clrbits32(bcsr_io, BCSR1_RS232EN_1);
61 clrbits32(&cp->cp_simode, 0xe0000000 >> 17); /* brg1 */
62 tmpval8 = in_8(&(cp->cp_smc[0].smc_smcm)) | (SMCM_RX | SMCM_TX);
63 out_8(&(cp->cp_smc[0].smc_smcm), tmpval8);
64 clrbits16(&cp->cp_smc[0].smc_smcmr, SMCMR_REN | SMCMR_TEN);
65#else
66 setbits32(bcsr_io,BCSR1_RS232EN_1);
67 out_be16(&cp->cp_smc[0].smc_smcmr, 0);
68 out_8(&cp->cp_smc[0].smc_smce, 0);
69#endif
70 78
71#ifdef CONFIG_SERIAL_CPM_SMC2 79 cpm1_clk_setup(CPM_CLK_SMC1, CPM_BRG1, CPM_CLK_RTX);
72 clrbits32(bcsr_io,BCSR1_RS232EN_2); 80 cpm1_clk_setup(CPM_CLK_SMC2, CPM_BRG2, CPM_CLK_RTX);
73 clrbits32(&cp->cp_simode, 0xe0000000 >> 1); 81 cpm1_clk_setup(CPM_CLK_SCC1, CPM_CLK1, CPM_CLK_TX);
74 setbits32(&cp->cp_simode, 0x20000000 >> 1); /* brg2 */ 82 cpm1_clk_setup(CPM_CLK_SCC1, CPM_CLK2, CPM_CLK_RX);
75 tmpval8 = in_8(&(cp->cp_smc[1].smc_smcm)) | (SMCM_RX | SMCM_TX);
76 out_8(&(cp->cp_smc[1].smc_smcm), tmpval8);
77 clrbits16(&cp->cp_smc[1].smc_smcmr, SMCMR_REN | SMCMR_TEN);
78 83
79 init_smc2_uart_ioports(0); 84 /* Set FEC1 and FEC2 to MII mode */
80#else 85 clrbits32(&mpc8xx_immr->im_cpm.cp_cptr, 0x00000180);
81 setbits32(bcsr_io,BCSR1_RS232EN_2);
82 out_be16(&cp->cp_smc[1].smc_smcmr, 0);
83 out_8(&cp->cp_smc[1].smc_smce, 0);
84#endif
85 immr_unmap(cp);
86 iounmap(bcsr_io);
87} 86}
88 87
89 88static void __init mpc86xads_setup_arch(void)
90static void init_fec1_ioports(struct fs_platform_info* ptr)
91{ 89{
92 iop8xx_t *io_port = (iop8xx_t *)immr_map(im_ioport); 90 struct device_node *np;
93 91 u32 __iomem *bcsr_io;
94 /* configure FEC1 pins */
95
96 setbits16(&io_port->iop_pdpar, 0x1fff);
97 setbits16(&io_port->iop_pddir, 0x1fff);
98
99 immr_unmap(io_port);
100}
101 92
102void init_fec_ioports(struct fs_platform_info *fpi) 93 cpm_reset();
103{ 94 init_ioports();
104 int fec_no = fs_get_fec_index(fpi->fs_no);
105 95
106 switch (fec_no) { 96 np = of_find_compatible_node(NULL, NULL, "fsl,mpc866ads-bcsr");
107 case 0: 97 if (!np) {
108 init_fec1_ioports(fpi); 98 printk(KERN_CRIT "Could not find fsl,mpc866ads-bcsr node\n");
109 break;
110 default:
111 printk(KERN_ERR "init_fec_ioports: invalid FEC number\n");
112 return; 99 return;
113 } 100 }
114}
115
116static void init_scc1_ioports(struct fs_platform_info* fpi)
117{
118 unsigned *bcsr_io;
119 iop8xx_t *io_port;
120 cpm8xx_t *cp;
121 101
122 bcsr_io = ioremap(BCSR_ADDR, BCSR_SIZE); 102 bcsr_io = of_iomap(np, 0);
123 io_port = (iop8xx_t *)immr_map(im_ioport); 103 of_node_put(np);
124 cp = (cpm8xx_t *)immr_map(im_cpm);
125 104
126 if (bcsr_io == NULL) { 105 if (bcsr_io == NULL) {
127 printk(KERN_CRIT "Could not remap BCSR\n"); 106 printk(KERN_CRIT "Could not remap BCSR\n");
128 return; 107 return;
129 } 108 }
130 109
131 /* Configure port A pins for Txd and Rxd. 110 clrbits32(bcsr_io, BCSR1_RS232EN_1 | BCSR1_RS232EN_2 | BCSR1_ETHEN);
132 */
133 setbits16(&io_port->iop_papar, PA_ENET_RXD | PA_ENET_TXD);
134 clrbits16(&io_port->iop_padir, PA_ENET_RXD | PA_ENET_TXD);
135 clrbits16(&io_port->iop_paodr, PA_ENET_TXD);
136
137 /* Configure port C pins to enable CLSN and RENA.
138 */
139 clrbits16(&io_port->iop_pcpar, PC_ENET_CLSN | PC_ENET_RENA);
140 clrbits16(&io_port->iop_pcdir, PC_ENET_CLSN | PC_ENET_RENA);
141 setbits16(&io_port->iop_pcso, PC_ENET_CLSN | PC_ENET_RENA);
142
143 /* Configure port A for TCLK and RCLK.
144 */
145 setbits16(&io_port->iop_papar, PA_ENET_TCLK | PA_ENET_RCLK);
146 clrbits16(&io_port->iop_padir, PA_ENET_TCLK | PA_ENET_RCLK);
147 clrbits32(&cp->cp_pbpar, PB_ENET_TENA);
148 clrbits32(&cp->cp_pbdir, PB_ENET_TENA);
149
150 /* Configure Serial Interface clock routing.
151 * First, clear all SCC bits to zero, then set the ones we want.
152 */
153 clrbits32(&cp->cp_sicr, SICR_ENET_MASK);
154 setbits32(&cp->cp_sicr, SICR_ENET_CLKRT);
155
156 /* In the original SCC enet driver the following code is placed at
157 the end of the initialization */
158 setbits32(&cp->cp_pbpar, PB_ENET_TENA);
159 setbits32(&cp->cp_pbdir, PB_ENET_TENA);
160
161 clrbits32(bcsr_io+1, BCSR1_ETHEN);
162 iounmap(bcsr_io); 111 iounmap(bcsr_io);
163 immr_unmap(cp);
164 immr_unmap(io_port);
165} 112}
166 113
167void init_scc_ioports(struct fs_platform_info *fpi) 114static int __init mpc86xads_probe(void)
168{
169 int scc_no = fs_get_scc_index(fpi->fs_no);
170
171 switch (scc_no) {
172 case 0:
173 init_scc1_ioports(fpi);
174 break;
175 default:
176 printk(KERN_ERR "init_scc_ioports: invalid SCC number\n");
177 return;
178 }
179}
180
181
182
183static void init_smc1_uart_ioports(struct fs_uart_platform_info* ptr)
184{ 115{
185 unsigned *bcsr_io; 116 unsigned long root = of_get_flat_dt_root();
186 cpm8xx_t *cp = (cpm8xx_t *)immr_map(im_cpm); 117 return of_flat_dt_is_compatible(root, "fsl,mpc866ads");
187
188 setbits32(&cp->cp_pbpar, 0x000000c0);
189 clrbits32(&cp->cp_pbdir, 0x000000c0);
190 clrbits16(&cp->cp_pbodr, 0x00c0);
191 immr_unmap(cp);
192
193 bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
194
195 if (bcsr_io == NULL) {
196 printk(KERN_CRIT "Could not remap BCSR1\n");
197 return;
198 }
199 clrbits32(bcsr_io,BCSR1_RS232EN_1);
200 iounmap(bcsr_io);
201} 118}
202 119
203static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi) 120static struct of_device_id __initdata of_bus_ids[] = {
204{ 121 { .name = "soc", },
205 unsigned *bcsr_io; 122 { .name = "cpm", },
206 cpm8xx_t *cp = (cpm8xx_t *)immr_map(im_cpm); 123 { .name = "localbus", },
207 124 {},
208 setbits32(&cp->cp_pbpar, 0x00000c00); 125};
209 clrbits32(&cp->cp_pbdir, 0x00000c00);
210 clrbits16(&cp->cp_pbodr, 0x0c00);
211 immr_unmap(cp);
212
213 bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
214
215 if (bcsr_io == NULL) {
216 printk(KERN_CRIT "Could not remap BCSR1\n");
217 return;
218 }
219 clrbits32(bcsr_io,BCSR1_RS232EN_2);
220 iounmap(bcsr_io);
221}
222 126
223void init_smc_ioports(struct fs_uart_platform_info *data) 127static int __init declare_of_platform_devices(void)
224{ 128{
225 int smc_no = fs_uart_id_fsid2smc(data->fs_no); 129 of_platform_bus_probe(NULL, of_bus_ids, NULL);
226
227 switch (smc_no) {
228 case 0:
229 init_smc1_uart_ioports(data);
230 data->brg = data->clk_rx;
231 break;
232 case 1:
233 init_smc2_uart_ioports(data);
234 data->brg = data->clk_rx;
235 break;
236 default:
237 printk(KERN_ERR "init_scc_ioports: invalid SCC number\n");
238 return;
239 }
240}
241 130
242int platform_device_skip(const char *model, int id)
243{
244 return 0; 131 return 0;
245} 132}
246 133machine_device_initcall(mpc86x_ads, declare_of_platform_devices);
247static void __init mpc86xads_setup_arch(void)
248{
249 cpm_reset();
250
251 mpc86xads_board_setup();
252
253 ROOT_DEV = Root_NFS;
254}
255
256static int __init mpc86xads_probe(void)
257{
258 char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
259 "model", NULL);
260 if (model == NULL)
261 return 0;
262 if (strcmp(model, "MPC866ADS"))
263 return 0;
264
265 return 1;
266}
267 134
268define_machine(mpc86x_ads) { 135define_machine(mpc86x_ads) {
269 .name = "MPC86x ADS", 136 .name = "MPC86x ADS",
270 .probe = mpc86xads_probe, 137 .probe = mpc86xads_probe,
271 .setup_arch = mpc86xads_setup_arch, 138 .setup_arch = mpc86xads_setup_arch,
272 .init_IRQ = m8xx_pic_init, 139 .init_IRQ = mpc8xx_pics_init,
273 .get_irq = mpc8xx_get_irq, 140 .get_irq = mpc8xx_get_irq,
274 .restart = mpc8xx_restart, 141 .restart = mpc8xx_restart,
275 .calibrate_decr = mpc8xx_calibrate_decr, 142 .calibrate_decr = mpc8xx_calibrate_decr,
276 .set_rtc_time = mpc8xx_set_rtc_time, 143 .set_rtc_time = mpc8xx_set_rtc_time,
277 .get_rtc_time = mpc8xx_get_rtc_time, 144 .get_rtc_time = mpc8xx_get_rtc_time,
145 .progress = udbg_progress,
278}; 146};
diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
index 2cf1b6a75173..6e7ded0233f6 100644
--- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c
+++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
@@ -36,11 +36,12 @@
36#include <asm/time.h> 36#include <asm/time.h>
37#include <asm/mpc8xx.h> 37#include <asm/mpc8xx.h>
38#include <asm/8xx_immap.h> 38#include <asm/8xx_immap.h>
39#include <asm/commproc.h> 39#include <asm/cpm1.h>
40#include <asm/fs_pd.h> 40#include <asm/fs_pd.h>
41#include <asm/udbg.h> 41#include <asm/udbg.h>
42 42
43#include <sysdev/commproc.h> 43#include "mpc885ads.h"
44#include "mpc8xx.h"
44 45
45static u32 __iomem *bcsr, *bcsr5; 46static u32 __iomem *bcsr, *bcsr5;
46 47
@@ -264,18 +265,17 @@ static struct of_device_id __initdata of_bus_ids[] = {
264static int __init declare_of_platform_devices(void) 265static int __init declare_of_platform_devices(void)
265{ 266{
266 /* Publish the QE devices */ 267 /* Publish the QE devices */
267 if (machine_is(mpc885_ads)) 268 of_platform_bus_probe(NULL, of_bus_ids, NULL);
268 of_platform_bus_probe(NULL, of_bus_ids, NULL);
269 269
270 return 0; 270 return 0;
271} 271}
272device_initcall(declare_of_platform_devices); 272machine_device_initcall(mpc885_ads, declare_of_platform_devices);
273 273
274define_machine(mpc885_ads) { 274define_machine(mpc885_ads) {
275 .name = "Freescale MPC885 ADS", 275 .name = "Freescale MPC885 ADS",
276 .probe = mpc885ads_probe, 276 .probe = mpc885ads_probe,
277 .setup_arch = mpc885ads_setup_arch, 277 .setup_arch = mpc885ads_setup_arch,
278 .init_IRQ = m8xx_pic_init, 278 .init_IRQ = mpc8xx_pics_init,
279 .get_irq = mpc8xx_get_irq, 279 .get_irq = mpc8xx_get_irq,
280 .restart = mpc8xx_restart, 280 .restart = mpc8xx_restart,
281 .calibrate_decr = mpc8xx_calibrate_decr, 281 .calibrate_decr = mpc8xx_calibrate_decr,
diff --git a/arch/powerpc/platforms/8xx/mpc8xx.h b/arch/powerpc/platforms/8xx/mpc8xx.h
new file mode 100644
index 000000000000..239a243a6161
--- /dev/null
+++ b/arch/powerpc/platforms/8xx/mpc8xx.h
@@ -0,0 +1,21 @@
1/*
2 * Prototypes, etc. for the Freescale MPC8xx embedded cpu chips
3 * May need to be cleaned as the port goes on ...
4 *
5 * Copyright (C) 2008 Jochen Friedrich <jochen@scram.de>
6 *
7 * This file is licensed under the terms of the GNU General Public License
8 * version 2. This program is licensed "as is" without any warranty of any
9 * kind, whether express or implied.
10 */
11#ifndef __MPC8xx_H
12#define __MPC8xx_H
13
14extern void mpc8xx_restart(char *cmd);
15extern void mpc8xx_calibrate_decr(void);
16extern int mpc8xx_set_rtc_time(struct rtc_time *tm);
17extern void mpc8xx_get_rtc_time(struct rtc_time *tm);
18extern void mpc8xx_pics_init(void);
19extern unsigned int mpc8xx_get_irq(void);
20
21#endif /* __MPC8xx_H */
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index ea22cad2cd0a..fdce10c4f074 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -21,7 +21,8 @@ config PPC_83xx
21 bool "Freescale 83xx" 21 bool "Freescale 83xx"
22 depends on 6xx 22 depends on 6xx
23 select FSL_SOC 23 select FSL_SOC
24 select 83xx 24 select MPC83xx
25 select IPIC
25 select WANT_DEVICE_TREE 26 select WANT_DEVICE_TREE
26 27
27config PPC_86xx 28config PPC_86xx
@@ -80,6 +81,10 @@ config XICS
80 bool 81 bool
81 default y 82 default y
82 83
84config IPIC
85 bool
86 default n
87
83config MPIC 88config MPIC
84 bool 89 bool
85 default n 90 default n
@@ -265,6 +270,7 @@ config TAU_AVERAGE
265config QUICC_ENGINE 270config QUICC_ENGINE
266 bool 271 bool
267 select PPC_LIB_RHEAP 272 select PPC_LIB_RHEAP
273 select CRC32
268 help 274 help
269 The QUICC Engine (QE) is a new generation of communications 275 The QUICC Engine (QE) is a new generation of communications
270 coprocessors on Freescale embedded CPUs (akin to CPM in older chips). 276 coprocessors on Freescale embedded CPUs (akin to CPM in older chips).
@@ -272,8 +278,8 @@ config QUICC_ENGINE
272 for a machine with a QE coprocessor. 278 for a machine with a QE coprocessor.
273 279
274config CPM2 280config CPM2
275 bool 281 bool "Enable support for the CPM2 (Communications Processor Module)"
276 default n 282 depends on MPC85xx || 8260
277 select CPM 283 select CPM
278 select PPC_LIB_RHEAP 284 select PPC_LIB_RHEAP
279 help 285 help
@@ -315,6 +321,12 @@ config FSL_ULI1575
315config CPM 321config CPM
316 bool 322 bool
317 323
324config OF_RTC
325 bool
326 help
327 Uses information from the OF or flattened device tree to instatiate
328 platform devices for direct mapped RTC chips like the DS1742 or DS1743.
329
318source "arch/powerpc/sysdev/bestcomm/Kconfig" 330source "arch/powerpc/sysdev/bestcomm/Kconfig"
319 331
320endmenu 332endmenu
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 99684ea606af..7fc41104d53e 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -29,8 +29,8 @@ config PPC_85xx
29 bool "Freescale 85xx" 29 bool "Freescale 85xx"
30 select E500 30 select E500
31 select FSL_SOC 31 select FSL_SOC
32 select 85xx
33 select WANT_DEVICE_TREE 32 select WANT_DEVICE_TREE
33 select MPC85xx
34 34
35config PPC_8xx 35config PPC_8xx
36 bool "Freescale 8xx" 36 bool "Freescale 8xx"
@@ -43,6 +43,7 @@ config 40x
43 bool "AMCC 40x" 43 bool "AMCC 40x"
44 select PPC_DCR_NATIVE 44 select PPC_DCR_NATIVE
45 select WANT_DEVICE_TREE 45 select WANT_DEVICE_TREE
46 select PPC_UDBG_16550
46 47
47config 44x 48config 44x
48 bool "AMCC 44x" 49 bool "AMCC 44x"
@@ -92,14 +93,6 @@ config 6xx
92config 8xx 93config 8xx
93 bool 94 bool
94 95
95# this is temp to handle compat with arch=ppc
96config 83xx
97 bool
98
99# this is temp to handle compat with arch=ppc
100config 85xx
101 bool
102
103config E500 96config E500
104 bool 97 bool
105 98
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index 39d695cb9693..c89964c6fb1f 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -20,7 +20,7 @@ spu-manage-$(CONFIG_PPC_CELL_NATIVE) += spu_manage.o
20 20
21obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \ 21obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \
22 spu_notify.o \ 22 spu_notify.o \
23 spu_syscalls.o \ 23 spu_syscalls.o spu_fault.o \
24 $(spu-priv1-y) \ 24 $(spu-priv1-y) \
25 $(spu-manage-y) \ 25 $(spu-manage-y) \
26 spufs/ 26 spufs/
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c
index 13d5a87f13b1..ec7c8f45a215 100644
--- a/arch/powerpc/platforms/cell/cbe_cpufreq.c
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c
@@ -21,8 +21,9 @@
21 */ 21 */
22 22
23#include <linux/cpufreq.h> 23#include <linux/cpufreq.h>
24#include <linux/of_platform.h>
25
24#include <asm/machdep.h> 26#include <asm/machdep.h>
25#include <asm/of_platform.h>
26#include <asm/prom.h> 27#include <asm/prom.h>
27#include <asm/cell-regs.h> 28#include <asm/cell-regs.h>
28#include "cbe_cpufreq.h" 29#include "cbe_cpufreq.h"
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c b/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c
index 6a2c1b0a9a94..69288f653144 100644
--- a/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c
@@ -23,7 +23,8 @@
23#include <linux/kernel.h> 23#include <linux/kernel.h>
24#include <linux/types.h> 24#include <linux/types.h>
25#include <linux/timer.h> 25#include <linux/timer.h>
26#include <asm/of_platform.h> 26#include <linux/of_platform.h>
27
27#include <asm/processor.h> 28#include <asm/processor.h>
28#include <asm/prom.h> 29#include <asm/prom.h>
29#include <asm/pmi.h> 30#include <asm/pmi.h>
diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c
index 16a9b07e7b0c..dbc338f187a2 100644
--- a/arch/powerpc/platforms/cell/cbe_regs.c
+++ b/arch/powerpc/platforms/cell/cbe_regs.c
@@ -9,13 +9,13 @@
9#include <linux/percpu.h> 9#include <linux/percpu.h>
10#include <linux/types.h> 10#include <linux/types.h>
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/of_device.h>
13#include <linux/of_platform.h>
12 14
13#include <asm/io.h> 15#include <asm/io.h>
14#include <asm/pgtable.h> 16#include <asm/pgtable.h>
15#include <asm/prom.h> 17#include <asm/prom.h>
16#include <asm/ptrace.h> 18#include <asm/ptrace.h>
17#include <asm/of_device.h>
18#include <asm/of_platform.h>
19#include <asm/cell-regs.h> 19#include <asm/cell-regs.h>
20 20
21/* 21/*
@@ -256,6 +256,7 @@ void __init cbe_regs_init(void)
256 printk(KERN_ERR "cbe_regs: More BE chips than supported" 256 printk(KERN_ERR "cbe_regs: More BE chips than supported"
257 "!\n"); 257 "!\n");
258 cbe_regs_map_count--; 258 cbe_regs_map_count--;
259 of_node_put(cpu);
259 return; 260 return;
260 } 261 }
261 map->cpu_node = cpu; 262 map->cpu_node = cpu;
diff --git a/arch/powerpc/platforms/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c
index 9d7c2ef940a8..979d4b67efb4 100644
--- a/arch/powerpc/platforms/cell/io-workarounds.c
+++ b/arch/powerpc/platforms/cell/io-workarounds.c
@@ -238,7 +238,7 @@ static void __init spider_pci_setup_chip(struct spider_pci_bus *bus)
238static void __init spider_pci_add_one(struct pci_controller *phb) 238static void __init spider_pci_add_one(struct pci_controller *phb)
239{ 239{
240 struct spider_pci_bus *bus = &spider_pci_busses[spider_pci_count]; 240 struct spider_pci_bus *bus = &spider_pci_busses[spider_pci_count];
241 struct device_node *np = phb->arch_data; 241 struct device_node *np = phb->dn;
242 struct resource rsrc; 242 struct resource rsrc;
243 void __iomem *regs; 243 void __iomem *regs;
244 244
@@ -309,15 +309,12 @@ static int __init spider_pci_workaround_init(void)
309{ 309{
310 struct pci_controller *phb; 310 struct pci_controller *phb;
311 311
312 if (!machine_is(cell))
313 return 0;
314
315 /* Find spider bridges. We assume they have been all probed 312 /* Find spider bridges. We assume they have been all probed
316 * in setup_arch(). If that was to change, we would need to 313 * in setup_arch(). If that was to change, we would need to
317 * update this code to cope with dynamically added busses 314 * update this code to cope with dynamically added busses
318 */ 315 */
319 list_for_each_entry(phb, &hose_list, list_node) { 316 list_for_each_entry(phb, &hose_list, list_node) {
320 struct device_node *np = phb->arch_data; 317 struct device_node *np = phb->dn;
321 const char *model = of_get_property(np, "model", NULL); 318 const char *model = of_get_property(np, "model", NULL);
322 319
323 /* If no model property or name isn't exactly "pci", skip */ 320 /* If no model property or name isn't exactly "pci", skip */
@@ -343,4 +340,4 @@ static int __init spider_pci_workaround_init(void)
343 340
344 return 0; 341 return 0;
345} 342}
346arch_initcall(spider_pci_workaround_init); 343machine_arch_initcall(cell, spider_pci_workaround_init);
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index faabc3fdc130..df330666ccc9 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * IOMMU implementation for Cell Broadband Processor Architecture 2 * IOMMU implementation for Cell Broadband Processor Architecture
3 * 3 *
4 * (C) Copyright IBM Corporation 2006 4 * (C) Copyright IBM Corporation 2006-2008
5 * 5 *
6 * Author: Jeremy Kerr <jk@ozlabs.org> 6 * Author: Jeremy Kerr <jk@ozlabs.org>
7 * 7 *
@@ -26,14 +26,15 @@
26#include <linux/init.h> 26#include <linux/init.h>
27#include <linux/interrupt.h> 27#include <linux/interrupt.h>
28#include <linux/notifier.h> 28#include <linux/notifier.h>
29#include <linux/of_platform.h>
29 30
30#include <asm/prom.h> 31#include <asm/prom.h>
31#include <asm/iommu.h> 32#include <asm/iommu.h>
32#include <asm/machdep.h> 33#include <asm/machdep.h>
33#include <asm/pci-bridge.h> 34#include <asm/pci-bridge.h>
34#include <asm/udbg.h> 35#include <asm/udbg.h>
35#include <asm/of_platform.h>
36#include <asm/lmb.h> 36#include <asm/lmb.h>
37#include <asm/firmware.h>
37#include <asm/cell-regs.h> 38#include <asm/cell-regs.h>
38 39
39#include "interrupt.h" 40#include "interrupt.h"
@@ -305,29 +306,28 @@ static int cell_iommu_find_ioc(int nid, unsigned long *base)
305 return -ENODEV; 306 return -ENODEV;
306} 307}
307 308
308static void cell_iommu_setup_hardware(struct cbe_iommu *iommu, unsigned long size) 309static void cell_iommu_setup_page_tables(struct cbe_iommu *iommu,
310 unsigned long dbase, unsigned long dsize,
311 unsigned long fbase, unsigned long fsize)
309{ 312{
310 struct page *page; 313 struct page *page;
311 int ret, i; 314 int i;
312 unsigned long reg, segments, pages_per_segment, ptab_size, n_pte_pages; 315 unsigned long reg, segments, pages_per_segment, ptab_size, stab_size,
313 unsigned long xlate_base; 316 n_pte_pages, base;
314 unsigned int virq;
315
316 if (cell_iommu_find_ioc(iommu->nid, &xlate_base))
317 panic("%s: missing IOC register mappings for node %d\n",
318 __FUNCTION__, iommu->nid);
319 317
320 iommu->xlate_regs = ioremap(xlate_base, IOC_Reg_Size); 318 base = dbase;
321 iommu->cmd_regs = iommu->xlate_regs + IOC_IOCmd_Offset; 319 if (fsize != 0)
320 base = min(fbase, dbase);
322 321
323 segments = size >> IO_SEGMENT_SHIFT; 322 segments = max(dbase + dsize, fbase + fsize) >> IO_SEGMENT_SHIFT;
324 pages_per_segment = 1ull << IO_PAGENO_BITS; 323 pages_per_segment = 1ull << IO_PAGENO_BITS;
325 324
326 pr_debug("%s: iommu[%d]: segments: %lu, pages per segment: %lu\n", 325 pr_debug("%s: iommu[%d]: segments: %lu, pages per segment: %lu\n",
327 __FUNCTION__, iommu->nid, segments, pages_per_segment); 326 __FUNCTION__, iommu->nid, segments, pages_per_segment);
328 327
329 /* set up the segment table */ 328 /* set up the segment table */
330 page = alloc_pages_node(iommu->nid, GFP_KERNEL, 0); 329 stab_size = segments * sizeof(unsigned long);
330 page = alloc_pages_node(iommu->nid, GFP_KERNEL, get_order(stab_size));
331 BUG_ON(!page); 331 BUG_ON(!page);
332 iommu->stab = page_address(page); 332 iommu->stab = page_address(page);
333 clear_page(iommu->stab); 333 clear_page(iommu->stab);
@@ -371,11 +371,25 @@ static void cell_iommu_setup_hardware(struct cbe_iommu *iommu, unsigned long siz
371 } 371 }
372 372
373 pr_debug("Setting up IOMMU stab:\n"); 373 pr_debug("Setting up IOMMU stab:\n");
374 for (i = 0; i * (1ul << IO_SEGMENT_SHIFT) < size; i++) { 374 for (i = base >> IO_SEGMENT_SHIFT; i < segments; i++) {
375 iommu->stab[i] = reg | 375 iommu->stab[i] = reg |
376 (__pa(iommu->ptab) + n_pte_pages * IOMMU_PAGE_SIZE * i); 376 (__pa(iommu->ptab) + n_pte_pages * IOMMU_PAGE_SIZE * i);
377 pr_debug("\t[%d] 0x%016lx\n", i, iommu->stab[i]); 377 pr_debug("\t[%d] 0x%016lx\n", i, iommu->stab[i]);
378 } 378 }
379}
380
381static void cell_iommu_enable_hardware(struct cbe_iommu *iommu)
382{
383 int ret;
384 unsigned long reg, xlate_base;
385 unsigned int virq;
386
387 if (cell_iommu_find_ioc(iommu->nid, &xlate_base))
388 panic("%s: missing IOC register mappings for node %d\n",
389 __FUNCTION__, iommu->nid);
390
391 iommu->xlate_regs = ioremap(xlate_base, IOC_Reg_Size);
392 iommu->cmd_regs = iommu->xlate_regs + IOC_IOCmd_Offset;
379 393
380 /* ensure that the STEs have updated */ 394 /* ensure that the STEs have updated */
381 mb(); 395 mb();
@@ -405,6 +419,13 @@ static void cell_iommu_setup_hardware(struct cbe_iommu *iommu, unsigned long siz
405 out_be64(iommu->cmd_regs + IOC_IOCmd_Cfg, reg); 419 out_be64(iommu->cmd_regs + IOC_IOCmd_Cfg, reg);
406} 420}
407 421
422static void cell_iommu_setup_hardware(struct cbe_iommu *iommu,
423 unsigned long base, unsigned long size)
424{
425 cell_iommu_setup_page_tables(iommu, base, size, 0, 0);
426 cell_iommu_enable_hardware(iommu);
427}
428
408#if 0/* Unused for now */ 429#if 0/* Unused for now */
409static struct iommu_window *find_window(struct cbe_iommu *iommu, 430static struct iommu_window *find_window(struct cbe_iommu *iommu,
410 unsigned long offset, unsigned long size) 431 unsigned long offset, unsigned long size)
@@ -422,25 +443,36 @@ static struct iommu_window *find_window(struct cbe_iommu *iommu,
422} 443}
423#endif 444#endif
424 445
446static inline u32 cell_iommu_get_ioid(struct device_node *np)
447{
448 const u32 *ioid;
449
450 ioid = of_get_property(np, "ioid", NULL);
451 if (ioid == NULL) {
452 printk(KERN_WARNING "iommu: missing ioid for %s using 0\n",
453 np->full_name);
454 return 0;
455 }
456
457 return *ioid;
458}
459
425static struct iommu_window * __init 460static struct iommu_window * __init
426cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np, 461cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np,
427 unsigned long offset, unsigned long size, 462 unsigned long offset, unsigned long size,
428 unsigned long pte_offset) 463 unsigned long pte_offset)
429{ 464{
430 struct iommu_window *window; 465 struct iommu_window *window;
431 const unsigned int *ioid; 466 u32 ioid;
432 467
433 ioid = of_get_property(np, "ioid", NULL); 468 ioid = cell_iommu_get_ioid(np);
434 if (ioid == NULL)
435 printk(KERN_WARNING "iommu: missing ioid for %s using 0\n",
436 np->full_name);
437 469
438 window = kmalloc_node(sizeof(*window), GFP_KERNEL, iommu->nid); 470 window = kmalloc_node(sizeof(*window), GFP_KERNEL, iommu->nid);
439 BUG_ON(window == NULL); 471 BUG_ON(window == NULL);
440 472
441 window->offset = offset; 473 window->offset = offset;
442 window->size = size; 474 window->size = size;
443 window->ioid = ioid ? *ioid : 0; 475 window->ioid = ioid;
444 window->iommu = iommu; 476 window->iommu = iommu;
445 window->pte_offset = pte_offset; 477 window->pte_offset = pte_offset;
446 478
@@ -489,16 +521,17 @@ static struct cbe_iommu *cell_iommu_for_node(int nid)
489 return NULL; 521 return NULL;
490} 522}
491 523
492static void cell_dma_dev_setup(struct device *dev) 524static unsigned long cell_dma_direct_offset;
525
526static unsigned long dma_iommu_fixed_base;
527struct dma_mapping_ops dma_iommu_fixed_ops;
528
529static void cell_dma_dev_setup_iommu(struct device *dev)
493{ 530{
494 struct iommu_window *window; 531 struct iommu_window *window;
495 struct cbe_iommu *iommu; 532 struct cbe_iommu *iommu;
496 struct dev_archdata *archdata = &dev->archdata; 533 struct dev_archdata *archdata = &dev->archdata;
497 534
498 /* If we run without iommu, no need to do anything */
499 if (get_pci_dma_ops() == &dma_direct_ops)
500 return;
501
502 /* Current implementation uses the first window available in that 535 /* Current implementation uses the first window available in that
503 * node's iommu. We -might- do something smarter later though it may 536 * node's iommu. We -might- do something smarter later though it may
504 * never be necessary 537 * never be necessary
@@ -515,6 +548,23 @@ static void cell_dma_dev_setup(struct device *dev)
515 archdata->dma_data = &window->table; 548 archdata->dma_data = &window->table;
516} 549}
517 550
551static void cell_dma_dev_setup_static(struct device *dev);
552
553static void cell_dma_dev_setup(struct device *dev)
554{
555 struct dev_archdata *archdata = &dev->archdata;
556
557 /* Order is important here, these are not mutually exclusive */
558 if (get_dma_ops(dev) == &dma_iommu_fixed_ops)
559 cell_dma_dev_setup_static(dev);
560 else if (get_pci_dma_ops() == &dma_iommu_ops)
561 cell_dma_dev_setup_iommu(dev);
562 else if (get_pci_dma_ops() == &dma_direct_ops)
563 archdata->dma_data = (void *)cell_dma_direct_offset;
564 else
565 BUG();
566}
567
518static void cell_pci_dma_dev_setup(struct pci_dev *dev) 568static void cell_pci_dma_dev_setup(struct pci_dev *dev)
519{ 569{
520 cell_dma_dev_setup(&dev->dev); 570 cell_dma_dev_setup(&dev->dev);
@@ -560,10 +610,9 @@ static int __init cell_iommu_get_window(struct device_node *np,
560 return 0; 610 return 0;
561} 611}
562 612
563static void __init cell_iommu_init_one(struct device_node *np, unsigned long offset) 613static struct cbe_iommu * __init cell_iommu_alloc(struct device_node *np)
564{ 614{
565 struct cbe_iommu *iommu; 615 struct cbe_iommu *iommu;
566 unsigned long base, size;
567 int nid, i; 616 int nid, i;
568 617
569 /* Get node ID */ 618 /* Get node ID */
@@ -571,7 +620,7 @@ static void __init cell_iommu_init_one(struct device_node *np, unsigned long off
571 if (nid < 0) { 620 if (nid < 0) {
572 printk(KERN_ERR "iommu: failed to get node for %s\n", 621 printk(KERN_ERR "iommu: failed to get node for %s\n",
573 np->full_name); 622 np->full_name);
574 return; 623 return NULL;
575 } 624 }
576 pr_debug("iommu: setting up iommu for node %d (%s)\n", 625 pr_debug("iommu: setting up iommu for node %d (%s)\n",
577 nid, np->full_name); 626 nid, np->full_name);
@@ -587,7 +636,7 @@ static void __init cell_iommu_init_one(struct device_node *np, unsigned long off
587 if (cbe_nr_iommus >= NR_IOMMUS) { 636 if (cbe_nr_iommus >= NR_IOMMUS) {
588 printk(KERN_ERR "iommu: too many IOMMUs detected ! (%s)\n", 637 printk(KERN_ERR "iommu: too many IOMMUs detected ! (%s)\n",
589 np->full_name); 638 np->full_name);
590 return; 639 return NULL;
591 } 640 }
592 641
593 /* Init base fields */ 642 /* Init base fields */
@@ -598,6 +647,19 @@ static void __init cell_iommu_init_one(struct device_node *np, unsigned long off
598 snprintf(iommu->name, sizeof(iommu->name), "iommu%d", i); 647 snprintf(iommu->name, sizeof(iommu->name), "iommu%d", i);
599 INIT_LIST_HEAD(&iommu->windows); 648 INIT_LIST_HEAD(&iommu->windows);
600 649
650 return iommu;
651}
652
653static void __init cell_iommu_init_one(struct device_node *np,
654 unsigned long offset)
655{
656 struct cbe_iommu *iommu;
657 unsigned long base, size;
658
659 iommu = cell_iommu_alloc(np);
660 if (!iommu)
661 return;
662
601 /* Obtain a window for it */ 663 /* Obtain a window for it */
602 cell_iommu_get_window(np, &base, &size); 664 cell_iommu_get_window(np, &base, &size);
603 665
@@ -605,7 +667,7 @@ static void __init cell_iommu_init_one(struct device_node *np, unsigned long off
605 base, base + size - 1); 667 base, base + size - 1);
606 668
607 /* Initialize the hardware */ 669 /* Initialize the hardware */
608 cell_iommu_setup_hardware(iommu, size); 670 cell_iommu_setup_hardware(iommu, base, size);
609 671
610 /* Setup the iommu_table */ 672 /* Setup the iommu_table */
611 cell_iommu_setup_window(iommu, np, base, size, 673 cell_iommu_setup_window(iommu, np, base, size,
@@ -653,7 +715,7 @@ static int __init cell_iommu_init_disabled(void)
653 715
654 /* If we have no Axon, we set up the spider DMA magic offset */ 716 /* If we have no Axon, we set up the spider DMA magic offset */
655 if (of_find_node_by_name(NULL, "axon") == NULL) 717 if (of_find_node_by_name(NULL, "axon") == NULL)
656 dma_direct_offset = SPIDER_DMA_OFFSET; 718 cell_dma_direct_offset = SPIDER_DMA_OFFSET;
657 719
658 /* Now we need to check to see where the memory is mapped 720 /* Now we need to check to see where the memory is mapped
659 * in PCI space. We assume that all busses use the same dma 721 * in PCI space. We assume that all busses use the same dma
@@ -687,20 +749,274 @@ static int __init cell_iommu_init_disabled(void)
687 return -ENODEV; 749 return -ENODEV;
688 } 750 }
689 751
690 dma_direct_offset += base; 752 cell_dma_direct_offset += base;
753
754 if (cell_dma_direct_offset != 0)
755 ppc_md.pci_dma_dev_setup = cell_pci_dma_dev_setup;
691 756
692 printk("iommu: disabled, direct DMA offset is 0x%lx\n", 757 printk("iommu: disabled, direct DMA offset is 0x%lx\n",
693 dma_direct_offset); 758 cell_dma_direct_offset);
694 759
695 return 0; 760 return 0;
696} 761}
697 762
698static int __init cell_iommu_init(void) 763/*
764 * Fixed IOMMU mapping support
765 *
766 * This code adds support for setting up a fixed IOMMU mapping on certain
767 * cell machines. For 64-bit devices this avoids the performance overhead of
768 * mapping and unmapping pages at runtime. 32-bit devices are unable to use
769 * the fixed mapping.
770 *
771 * The fixed mapping is established at boot, and maps all of physical memory
772 * 1:1 into device space at some offset. On machines with < 30 GB of memory
773 * we setup the fixed mapping immediately above the normal IOMMU window.
774 *
775 * For example a machine with 4GB of memory would end up with the normal
776 * IOMMU window from 0-2GB and the fixed mapping window from 2GB to 6GB. In
777 * this case a 64-bit device wishing to DMA to 1GB would be told to DMA to
778 * 3GB, plus any offset required by firmware. The firmware offset is encoded
779 * in the "dma-ranges" property.
780 *
781 * On machines with 30GB or more of memory, we are unable to place the fixed
782 * mapping above the normal IOMMU window as we would run out of address space.
783 * Instead we move the normal IOMMU window to coincide with the hash page
784 * table, this region does not need to be part of the fixed mapping as no
785 * device should ever be DMA'ing to it. We then setup the fixed mapping
786 * from 0 to 32GB.
787 */
788
789static u64 cell_iommu_get_fixed_address(struct device *dev)
699{ 790{
791 u64 cpu_addr, size, best_size, pci_addr = OF_BAD_ADDR;
792 struct device_node *tmp, *np;
793 const u32 *ranges = NULL;
794 int i, len, best;
795
796 np = dev->archdata.of_node;
797 of_node_get(np);
798 ranges = of_get_property(np, "dma-ranges", &len);
799 while (!ranges && np) {
800 tmp = of_get_parent(np);
801 of_node_put(np);
802 np = tmp;
803 ranges = of_get_property(np, "dma-ranges", &len);
804 }
805
806 if (!ranges) {
807 dev_dbg(dev, "iommu: no dma-ranges found\n");
808 goto out;
809 }
810
811 len /= sizeof(u32);
812
813 /* dma-ranges format:
814 * 1 cell: pci space
815 * 2 cells: pci address
816 * 2 cells: parent address
817 * 2 cells: size
818 */
819 for (i = 0, best = -1, best_size = 0; i < len; i += 7) {
820 cpu_addr = of_translate_dma_address(np, ranges +i + 3);
821 size = of_read_number(ranges + i + 5, 2);
822
823 if (cpu_addr == 0 && size > best_size) {
824 best = i;
825 best_size = size;
826 }
827 }
828
829 if (best >= 0)
830 pci_addr = of_read_number(ranges + best + 1, 2);
831 else
832 dev_dbg(dev, "iommu: no suitable range found!\n");
833
834out:
835 of_node_put(np);
836
837 return pci_addr;
838}
839
840static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask)
841{
842 if (!dev->dma_mask || !dma_supported(dev, dma_mask))
843 return -EIO;
844
845 if (dma_mask == DMA_BIT_MASK(64)) {
846 if (cell_iommu_get_fixed_address(dev) == OF_BAD_ADDR)
847 dev_dbg(dev, "iommu: 64-bit OK, but bad addr\n");
848 else {
849 dev_dbg(dev, "iommu: 64-bit OK, using fixed ops\n");
850 set_dma_ops(dev, &dma_iommu_fixed_ops);
851 cell_dma_dev_setup(dev);
852 }
853 } else {
854 dev_dbg(dev, "iommu: not 64-bit, using default ops\n");
855 set_dma_ops(dev, get_pci_dma_ops());
856 }
857
858 *dev->dma_mask = dma_mask;
859
860 return 0;
861}
862
863static void cell_dma_dev_setup_static(struct device *dev)
864{
865 struct dev_archdata *archdata = &dev->archdata;
866 u64 addr;
867
868 addr = cell_iommu_get_fixed_address(dev) + dma_iommu_fixed_base;
869 archdata->dma_data = (void *)addr;
870
871 dev_dbg(dev, "iommu: fixed addr = %lx\n", addr);
872}
873
874static void cell_iommu_setup_fixed_ptab(struct cbe_iommu *iommu,
875 struct device_node *np, unsigned long dbase, unsigned long dsize,
876 unsigned long fbase, unsigned long fsize)
877{
878 unsigned long base_pte, uaddr, *io_pte;
879 int i;
880
881 dma_iommu_fixed_base = fbase;
882
883 /* convert from bytes into page table indices */
884 dbase = dbase >> IOMMU_PAGE_SHIFT;
885 dsize = dsize >> IOMMU_PAGE_SHIFT;
886 fbase = fbase >> IOMMU_PAGE_SHIFT;
887 fsize = fsize >> IOMMU_PAGE_SHIFT;
888
889 pr_debug("iommu: mapping 0x%lx pages from 0x%lx\n", fsize, fbase);
890
891 io_pte = iommu->ptab;
892 base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW
893 | (cell_iommu_get_ioid(np) & IOPTE_IOID_Mask);
894
895 uaddr = 0;
896 for (i = fbase; i < fbase + fsize; i++, uaddr += IOMMU_PAGE_SIZE) {
897 /* Don't touch the dynamic region */
898 if (i >= dbase && i < (dbase + dsize)) {
899 pr_debug("iommu: static/dynamic overlap, skipping\n");
900 continue;
901 }
902 io_pte[i] = base_pte | (__pa(uaddr) & IOPTE_RPN_Mask);
903 }
904
905 mb();
906}
907
908static int __init cell_iommu_fixed_mapping_init(void)
909{
910 unsigned long dbase, dsize, fbase, fsize, hbase, hend;
911 struct cbe_iommu *iommu;
700 struct device_node *np; 912 struct device_node *np;
701 913
702 if (!machine_is(cell)) 914 /* The fixed mapping is only supported on axon machines */
703 return -ENODEV; 915 np = of_find_node_by_name(NULL, "axon");
916 if (!np) {
917 pr_debug("iommu: fixed mapping disabled, no axons found\n");
918 return -1;
919 }
920
921 /* The default setup is to have the fixed mapping sit after the
922 * dynamic region, so find the top of the largest IOMMU window
923 * on any axon, then add the size of RAM and that's our max value.
924 * If that is > 32GB we have to do other shennanigans.
925 */
926 fbase = 0;
927 for_each_node_by_name(np, "axon") {
928 cell_iommu_get_window(np, &dbase, &dsize);
929 fbase = max(fbase, dbase + dsize);
930 }
931
932 fbase = _ALIGN_UP(fbase, 1 << IO_SEGMENT_SHIFT);
933 fsize = lmb_phys_mem_size();
934
935 if ((fbase + fsize) <= 0x800000000)
936 hbase = 0; /* use the device tree window */
937 else {
938 /* If we're over 32 GB we need to cheat. We can't map all of
939 * RAM with the fixed mapping, and also fit the dynamic
940 * region. So try to place the dynamic region where the hash
941 * table sits, drivers never need to DMA to it, we don't
942 * need a fixed mapping for that area.
943 */
944 if (!htab_address) {
945 pr_debug("iommu: htab is NULL, on LPAR? Huh?\n");
946 return -1;
947 }
948 hbase = __pa(htab_address);
949 hend = hbase + htab_size_bytes;
950
951 /* The window must start and end on a segment boundary */
952 if ((hbase != _ALIGN_UP(hbase, 1 << IO_SEGMENT_SHIFT)) ||
953 (hend != _ALIGN_UP(hend, 1 << IO_SEGMENT_SHIFT))) {
954 pr_debug("iommu: hash window not segment aligned\n");
955 return -1;
956 }
957
958 /* Check the hash window fits inside the real DMA window */
959 for_each_node_by_name(np, "axon") {
960 cell_iommu_get_window(np, &dbase, &dsize);
961
962 if (hbase < dbase || (hend > (dbase + dsize))) {
963 pr_debug("iommu: hash window doesn't fit in"
964 "real DMA window\n");
965 return -1;
966 }
967 }
968
969 fbase = 0;
970 }
971
972 /* Setup the dynamic regions */
973 for_each_node_by_name(np, "axon") {
974 iommu = cell_iommu_alloc(np);
975 BUG_ON(!iommu);
976
977 if (hbase == 0)
978 cell_iommu_get_window(np, &dbase, &dsize);
979 else {
980 dbase = hbase;
981 dsize = htab_size_bytes;
982 }
983
984 pr_debug("iommu: setting up %d, dynamic window %lx-%lx " \
985 "fixed window %lx-%lx\n", iommu->nid, dbase,
986 dbase + dsize, fbase, fbase + fsize);
987
988 cell_iommu_setup_page_tables(iommu, dbase, dsize, fbase, fsize);
989 cell_iommu_setup_fixed_ptab(iommu, np, dbase, dsize,
990 fbase, fsize);
991 cell_iommu_enable_hardware(iommu);
992 cell_iommu_setup_window(iommu, np, dbase, dsize, 0);
993 }
994
995 dma_iommu_fixed_ops = dma_direct_ops;
996 dma_iommu_fixed_ops.set_dma_mask = dma_set_mask_and_switch;
997
998 dma_iommu_ops.set_dma_mask = dma_set_mask_and_switch;
999 set_pci_dma_ops(&dma_iommu_ops);
1000
1001 printk(KERN_DEBUG "IOMMU fixed mapping established.\n");
1002
1003 return 0;
1004}
1005
1006static int iommu_fixed_disabled;
1007
1008static int __init setup_iommu_fixed(char *str)
1009{
1010 if (strcmp(str, "off") == 0)
1011 iommu_fixed_disabled = 1;
1012
1013 return 1;
1014}
1015__setup("iommu_fixed=", setup_iommu_fixed);
1016
1017static int __init cell_iommu_init(void)
1018{
1019 struct device_node *np;
704 1020
705 /* If IOMMU is disabled or we have little enough RAM to not need 1021 /* If IOMMU is disabled or we have little enough RAM to not need
706 * to enable it, we setup a direct mapping. 1022 * to enable it, we setup a direct mapping.
@@ -717,6 +1033,9 @@ static int __init cell_iommu_init(void)
717 ppc_md.tce_build = tce_build_cell; 1033 ppc_md.tce_build = tce_build_cell;
718 ppc_md.tce_free = tce_free_cell; 1034 ppc_md.tce_free = tce_free_cell;
719 1035
1036 if (!iommu_fixed_disabled && cell_iommu_fixed_mapping_init() == 0)
1037 goto bail;
1038
720 /* Create an iommu for each /axon node. */ 1039 /* Create an iommu for each /axon node. */
721 for_each_node_by_name(np, "axon") { 1040 for_each_node_by_name(np, "axon") {
722 if (np->parent == NULL || np->parent->parent != NULL) 1041 if (np->parent == NULL || np->parent->parent != NULL)
@@ -744,5 +1063,6 @@ static int __init cell_iommu_init(void)
744 1063
745 return 0; 1064 return 0;
746} 1065}
747arch_initcall(cell_iommu_init); 1066machine_arch_initcall(cell, cell_iommu_init);
1067machine_arch_initcall(celleb_native, cell_iommu_init);
748 1068
diff --git a/arch/powerpc/platforms/cell/pmu.c b/arch/powerpc/platforms/cell/pmu.c
index 1ed303678887..69ed0d7f1646 100644
--- a/arch/powerpc/platforms/cell/pmu.c
+++ b/arch/powerpc/platforms/cell/pmu.c
@@ -213,7 +213,7 @@ u32 cbe_read_pm(u32 cpu, enum pm_reg_name reg)
213 break; 213 break;
214 214
215 case pm_interval: 215 case pm_interval:
216 READ_SHADOW_REG(val, pm_interval); 216 READ_MMIO_UPPER32(val, pm_interval);
217 break; 217 break;
218 218
219 case pm_start_stop: 219 case pm_start_stop:
@@ -381,9 +381,6 @@ static int __init cbe_init_pm_irq(void)
381 unsigned int irq; 381 unsigned int irq;
382 int rc, node; 382 int rc, node;
383 383
384 if (!machine_is(cell))
385 return 0;
386
387 for_each_node(node) { 384 for_each_node(node) {
388 irq = irq_create_mapping(NULL, IIC_IRQ_IOEX_PMI | 385 irq = irq_create_mapping(NULL, IIC_IRQ_IOEX_PMI |
389 (node << IIC_IRQ_NODE_SHIFT)); 386 (node << IIC_IRQ_NODE_SHIFT));
@@ -404,7 +401,7 @@ static int __init cbe_init_pm_irq(void)
404 401
405 return 0; 402 return 0;
406} 403}
407arch_initcall(cbe_init_pm_irq); 404machine_arch_initcall(cell, cbe_init_pm_irq);
408 405
409void cbe_sync_irq(int node) 406void cbe_sync_irq(int node)
410{ 407{
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index 98e7ef8e6fc6..e6534b519c9a 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -30,6 +30,7 @@
30#include <linux/console.h> 30#include <linux/console.h>
31#include <linux/mutex.h> 31#include <linux/mutex.h>
32#include <linux/memory_hotplug.h> 32#include <linux/memory_hotplug.h>
33#include <linux/of_platform.h>
33 34
34#include <asm/mmu.h> 35#include <asm/mmu.h>
35#include <asm/processor.h> 36#include <asm/processor.h>
@@ -51,7 +52,6 @@
51#include <asm/spu_priv1.h> 52#include <asm/spu_priv1.h>
52#include <asm/udbg.h> 53#include <asm/udbg.h>
53#include <asm/mpic.h> 54#include <asm/mpic.h>
54#include <asm/of_platform.h>
55#include <asm/cell-regs.h> 55#include <asm/cell-regs.h>
56 56
57#include "interrupt.h" 57#include "interrupt.h"
@@ -85,9 +85,6 @@ static int __init cell_publish_devices(void)
85{ 85{
86 int node; 86 int node;
87 87
88 if (!machine_is(cell))
89 return 0;
90
91 /* Publish OF platform devices for southbridge IOs */ 88 /* Publish OF platform devices for southbridge IOs */
92 of_platform_bus_probe(NULL, NULL, NULL); 89 of_platform_bus_probe(NULL, NULL, NULL);
93 90
@@ -101,7 +98,7 @@ static int __init cell_publish_devices(void)
101 } 98 }
102 return 0; 99 return 0;
103} 100}
104device_initcall(cell_publish_devices); 101machine_device_initcall(cell, cell_publish_devices);
105 102
106static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc) 103static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc)
107{ 104{
diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c
index e4438456c867..efb3964457b1 100644
--- a/arch/powerpc/platforms/cell/smp.c
+++ b/arch/powerpc/platforms/cell/smp.c
@@ -42,6 +42,7 @@
42#include <asm/firmware.h> 42#include <asm/firmware.h>
43#include <asm/system.h> 43#include <asm/system.h>
44#include <asm/rtas.h> 44#include <asm/rtas.h>
45#include <asm/cputhreads.h>
45 46
46#include "interrupt.h" 47#include "interrupt.h"
47#include <asm/udbg.h> 48#include <asm/udbg.h>
@@ -182,7 +183,7 @@ static int smp_cell_cpu_bootable(unsigned int nr)
182 */ 183 */
183 if (system_state < SYSTEM_RUNNING && 184 if (system_state < SYSTEM_RUNNING &&
184 cpu_has_feature(CPU_FTR_SMT) && 185 cpu_has_feature(CPU_FTR_SMT) &&
185 !smt_enabled_at_boot && nr % 2 != 0) 186 !smt_enabled_at_boot && cpu_thread_in_core(nr) != 0)
186 return 0; 187 return 0;
187 188
188 return 1; 189 return 1;
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index a08862203643..e45cfa84911f 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -34,6 +34,7 @@
34#include <linux/linux_logo.h> 34#include <linux/linux_logo.h>
35#include <asm/spu.h> 35#include <asm/spu.h>
36#include <asm/spu_priv1.h> 36#include <asm/spu_priv1.h>
37#include <asm/spu_csa.h>
37#include <asm/xmon.h> 38#include <asm/xmon.h>
38#include <asm/prom.h> 39#include <asm/prom.h>
39 40
@@ -47,6 +48,13 @@ struct cbe_spu_info cbe_spu_info[MAX_NUMNODES];
47EXPORT_SYMBOL_GPL(cbe_spu_info); 48EXPORT_SYMBOL_GPL(cbe_spu_info);
48 49
49/* 50/*
51 * The spufs fault-handling code needs to call force_sig_info to raise signals
52 * on DMA errors. Export it here to avoid general kernel-wide access to this
53 * function
54 */
55EXPORT_SYMBOL_GPL(force_sig_info);
56
57/*
50 * Protects cbe_spu_info and spu->number. 58 * Protects cbe_spu_info and spu->number.
51 */ 59 */
52static DEFINE_SPINLOCK(spu_lock); 60static DEFINE_SPINLOCK(spu_lock);
@@ -66,6 +74,10 @@ static LIST_HEAD(spu_full_list);
66static DEFINE_SPINLOCK(spu_full_list_lock); 74static DEFINE_SPINLOCK(spu_full_list_lock);
67static DEFINE_MUTEX(spu_full_list_mutex); 75static DEFINE_MUTEX(spu_full_list_mutex);
68 76
77struct spu_slb {
78 u64 esid, vsid;
79};
80
69void spu_invalidate_slbs(struct spu *spu) 81void spu_invalidate_slbs(struct spu *spu)
70{ 82{
71 struct spu_priv2 __iomem *priv2 = spu->priv2; 83 struct spu_priv2 __iomem *priv2 = spu->priv2;
@@ -114,40 +126,36 @@ void spu_associate_mm(struct spu *spu, struct mm_struct *mm)
114} 126}
115EXPORT_SYMBOL_GPL(spu_associate_mm); 127EXPORT_SYMBOL_GPL(spu_associate_mm);
116 128
117static int __spu_trap_invalid_dma(struct spu *spu) 129int spu_64k_pages_available(void)
118{ 130{
119 pr_debug("%s\n", __FUNCTION__); 131 return mmu_psize_defs[MMU_PAGE_64K].shift != 0;
120 spu->dma_callback(spu, SPE_EVENT_INVALID_DMA);
121 return 0;
122} 132}
133EXPORT_SYMBOL_GPL(spu_64k_pages_available);
123 134
124static int __spu_trap_dma_align(struct spu *spu) 135static void spu_restart_dma(struct spu *spu)
125{ 136{
126 pr_debug("%s\n", __FUNCTION__); 137 struct spu_priv2 __iomem *priv2 = spu->priv2;
127 spu->dma_callback(spu, SPE_EVENT_DMA_ALIGNMENT);
128 return 0;
129}
130 138
131static int __spu_trap_error(struct spu *spu) 139 if (!test_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags))
132{ 140 out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND);
133 pr_debug("%s\n", __FUNCTION__);
134 spu->dma_callback(spu, SPE_EVENT_SPE_ERROR);
135 return 0;
136} 141}
137 142
138static void spu_restart_dma(struct spu *spu) 143static inline void spu_load_slb(struct spu *spu, int slbe, struct spu_slb *slb)
139{ 144{
140 struct spu_priv2 __iomem *priv2 = spu->priv2; 145 struct spu_priv2 __iomem *priv2 = spu->priv2;
141 146
142 if (!test_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags)) 147 pr_debug("%s: adding SLB[%d] 0x%016lx 0x%016lx\n",
143 out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND); 148 __func__, slbe, slb->vsid, slb->esid);
149
150 out_be64(&priv2->slb_index_W, slbe);
151 out_be64(&priv2->slb_vsid_RW, slb->vsid);
152 out_be64(&priv2->slb_esid_RW, slb->esid);
144} 153}
145 154
146static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) 155static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
147{ 156{
148 struct spu_priv2 __iomem *priv2 = spu->priv2;
149 struct mm_struct *mm = spu->mm; 157 struct mm_struct *mm = spu->mm;
150 u64 esid, vsid, llp; 158 struct spu_slb slb;
151 int psize; 159 int psize;
152 160
153 pr_debug("%s\n", __FUNCTION__); 161 pr_debug("%s\n", __FUNCTION__);
@@ -159,7 +167,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
159 printk("%s: invalid access during switch!\n", __func__); 167 printk("%s: invalid access during switch!\n", __func__);
160 return 1; 168 return 1;
161 } 169 }
162 esid = (ea & ESID_MASK) | SLB_ESID_V; 170 slb.esid = (ea & ESID_MASK) | SLB_ESID_V;
163 171
164 switch(REGION_ID(ea)) { 172 switch(REGION_ID(ea)) {
165 case USER_REGION_ID: 173 case USER_REGION_ID:
@@ -168,21 +176,21 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
168#else 176#else
169 psize = mm->context.user_psize; 177 psize = mm->context.user_psize;
170#endif 178#endif
171 vsid = (get_vsid(mm->context.id, ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) | 179 slb.vsid = (get_vsid(mm->context.id, ea, MMU_SEGSIZE_256M)
172 SLB_VSID_USER; 180 << SLB_VSID_SHIFT) | SLB_VSID_USER;
173 break; 181 break;
174 case VMALLOC_REGION_ID: 182 case VMALLOC_REGION_ID:
175 if (ea < VMALLOC_END) 183 if (ea < VMALLOC_END)
176 psize = mmu_vmalloc_psize; 184 psize = mmu_vmalloc_psize;
177 else 185 else
178 psize = mmu_io_psize; 186 psize = mmu_io_psize;
179 vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) | 187 slb.vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M)
180 SLB_VSID_KERNEL; 188 << SLB_VSID_SHIFT) | SLB_VSID_KERNEL;
181 break; 189 break;
182 case KERNEL_REGION_ID: 190 case KERNEL_REGION_ID:
183 psize = mmu_linear_psize; 191 psize = mmu_linear_psize;
184 vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) | 192 slb.vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M)
185 SLB_VSID_KERNEL; 193 << SLB_VSID_SHIFT) | SLB_VSID_KERNEL;
186 break; 194 break;
187 default: 195 default:
188 /* Future: support kernel segments so that drivers 196 /* Future: support kernel segments so that drivers
@@ -191,11 +199,9 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
191 pr_debug("invalid region access at %016lx\n", ea); 199 pr_debug("invalid region access at %016lx\n", ea);
192 return 1; 200 return 1;
193 } 201 }
194 llp = mmu_psize_defs[psize].sllp; 202 slb.vsid |= mmu_psize_defs[psize].sllp;
195 203
196 out_be64(&priv2->slb_index_W, spu->slb_replace); 204 spu_load_slb(spu, spu->slb_replace, &slb);
197 out_be64(&priv2->slb_vsid_RW, vsid | llp);
198 out_be64(&priv2->slb_esid_RW, esid);
199 205
200 spu->slb_replace++; 206 spu->slb_replace++;
201 if (spu->slb_replace >= 8) 207 if (spu->slb_replace >= 8)
@@ -225,13 +231,83 @@ static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr)
225 return 1; 231 return 1;
226 } 232 }
227 233
234 spu->class_0_pending = 0;
228 spu->dar = ea; 235 spu->dar = ea;
229 spu->dsisr = dsisr; 236 spu->dsisr = dsisr;
230 mb(); 237
231 spu->stop_callback(spu); 238 spu->stop_callback(spu);
239
240 return 0;
241}
242
243static void __spu_kernel_slb(void *addr, struct spu_slb *slb)
244{
245 unsigned long ea = (unsigned long)addr;
246 u64 llp;
247
248 if (REGION_ID(ea) == KERNEL_REGION_ID)
249 llp = mmu_psize_defs[mmu_linear_psize].sllp;
250 else
251 llp = mmu_psize_defs[mmu_virtual_psize].sllp;
252
253 slb->vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
254 SLB_VSID_KERNEL | llp;
255 slb->esid = (ea & ESID_MASK) | SLB_ESID_V;
256}
257
258/**
259 * Given an array of @nr_slbs SLB entries, @slbs, return non-zero if the
260 * address @new_addr is present.
261 */
262static inline int __slb_present(struct spu_slb *slbs, int nr_slbs,
263 void *new_addr)
264{
265 unsigned long ea = (unsigned long)new_addr;
266 int i;
267
268 for (i = 0; i < nr_slbs; i++)
269 if (!((slbs[i].esid ^ ea) & ESID_MASK))
270 return 1;
271
232 return 0; 272 return 0;
233} 273}
234 274
275/**
276 * Setup the SPU kernel SLBs, in preparation for a context save/restore. We
277 * need to map both the context save area, and the save/restore code.
278 *
279 * Because the lscsa and code may cross segment boundaires, we check to see
280 * if mappings are required for the start and end of each range. We currently
281 * assume that the mappings are smaller that one segment - if not, something
282 * is seriously wrong.
283 */
284void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa,
285 void *code, int code_size)
286{
287 struct spu_slb slbs[4];
288 int i, nr_slbs = 0;
289 /* start and end addresses of both mappings */
290 void *addrs[] = {
291 lscsa, (void *)lscsa + sizeof(*lscsa) - 1,
292 code, code + code_size - 1
293 };
294
295 /* check the set of addresses, and create a new entry in the slbs array
296 * if there isn't already a SLB for that address */
297 for (i = 0; i < ARRAY_SIZE(addrs); i++) {
298 if (__slb_present(slbs, nr_slbs, addrs[i]))
299 continue;
300
301 __spu_kernel_slb(addrs[i], &slbs[nr_slbs]);
302 nr_slbs++;
303 }
304
305 /* Add the set of SLBs */
306 for (i = 0; i < nr_slbs; i++)
307 spu_load_slb(spu, i, &slbs[i]);
308}
309EXPORT_SYMBOL_GPL(spu_setup_kernel_slbs);
310
235static irqreturn_t 311static irqreturn_t
236spu_irq_class_0(int irq, void *data) 312spu_irq_class_0(int irq, void *data)
237{ 313{
@@ -240,12 +316,13 @@ spu_irq_class_0(int irq, void *data)
240 316
241 spu = data; 317 spu = data;
242 318
319 spin_lock(&spu->register_lock);
243 mask = spu_int_mask_get(spu, 0); 320 mask = spu_int_mask_get(spu, 0);
244 stat = spu_int_stat_get(spu, 0); 321 stat = spu_int_stat_get(spu, 0) & mask;
245 stat &= mask;
246 322
247 spin_lock(&spu->register_lock);
248 spu->class_0_pending |= stat; 323 spu->class_0_pending |= stat;
324 spu->dsisr = spu_mfc_dsisr_get(spu);
325 spu->dar = spu_mfc_dar_get(spu);
249 spin_unlock(&spu->register_lock); 326 spin_unlock(&spu->register_lock);
250 327
251 spu->stop_callback(spu); 328 spu->stop_callback(spu);
@@ -255,31 +332,6 @@ spu_irq_class_0(int irq, void *data)
255 return IRQ_HANDLED; 332 return IRQ_HANDLED;
256} 333}
257 334
258int
259spu_irq_class_0_bottom(struct spu *spu)
260{
261 unsigned long flags;
262 unsigned long stat;
263
264 spin_lock_irqsave(&spu->register_lock, flags);
265 stat = spu->class_0_pending;
266 spu->class_0_pending = 0;
267
268 if (stat & 1) /* invalid DMA alignment */
269 __spu_trap_dma_align(spu);
270
271 if (stat & 2) /* invalid MFC DMA */
272 __spu_trap_invalid_dma(spu);
273
274 if (stat & 4) /* error on SPU */
275 __spu_trap_error(spu);
276
277 spin_unlock_irqrestore(&spu->register_lock, flags);
278
279 return (stat & 0x7) ? -EIO : 0;
280}
281EXPORT_SYMBOL_GPL(spu_irq_class_0_bottom);
282
283static irqreturn_t 335static irqreturn_t
284spu_irq_class_1(int irq, void *data) 336spu_irq_class_1(int irq, void *data)
285{ 337{
@@ -294,24 +346,23 @@ spu_irq_class_1(int irq, void *data)
294 stat = spu_int_stat_get(spu, 1) & mask; 346 stat = spu_int_stat_get(spu, 1) & mask;
295 dar = spu_mfc_dar_get(spu); 347 dar = spu_mfc_dar_get(spu);
296 dsisr = spu_mfc_dsisr_get(spu); 348 dsisr = spu_mfc_dsisr_get(spu);
297 if (stat & 2) /* mapping fault */ 349 if (stat & CLASS1_STORAGE_FAULT_INTR)
298 spu_mfc_dsisr_set(spu, 0ul); 350 spu_mfc_dsisr_set(spu, 0ul);
299 spu_int_stat_clear(spu, 1, stat); 351 spu_int_stat_clear(spu, 1, stat);
300 spin_unlock(&spu->register_lock); 352 spin_unlock(&spu->register_lock);
301 pr_debug("%s: %lx %lx %lx %lx\n", __FUNCTION__, mask, stat, 353 pr_debug("%s: %lx %lx %lx %lx\n", __FUNCTION__, mask, stat,
302 dar, dsisr); 354 dar, dsisr);
303 355
304 if (stat & 1) /* segment fault */ 356 if (stat & CLASS1_SEGMENT_FAULT_INTR)
305 __spu_trap_data_seg(spu, dar); 357 __spu_trap_data_seg(spu, dar);
306 358
307 if (stat & 2) { /* mapping fault */ 359 if (stat & CLASS1_STORAGE_FAULT_INTR)
308 __spu_trap_data_map(spu, dar, dsisr); 360 __spu_trap_data_map(spu, dar, dsisr);
309 }
310 361
311 if (stat & 4) /* ls compare & suspend on get */ 362 if (stat & CLASS1_LS_COMPARE_SUSPEND_ON_GET_INTR)
312 ; 363 ;
313 364
314 if (stat & 8) /* ls compare & suspend on put */ 365 if (stat & CLASS1_LS_COMPARE_SUSPEND_ON_PUT_INTR)
315 ; 366 ;
316 367
317 return stat ? IRQ_HANDLED : IRQ_NONE; 368 return stat ? IRQ_HANDLED : IRQ_NONE;
@@ -323,6 +374,8 @@ spu_irq_class_2(int irq, void *data)
323 struct spu *spu; 374 struct spu *spu;
324 unsigned long stat; 375 unsigned long stat;
325 unsigned long mask; 376 unsigned long mask;
377 const int mailbox_intrs =
378 CLASS2_MAILBOX_THRESHOLD_INTR | CLASS2_MAILBOX_INTR;
326 379
327 spu = data; 380 spu = data;
328 spin_lock(&spu->register_lock); 381 spin_lock(&spu->register_lock);
@@ -330,31 +383,30 @@ spu_irq_class_2(int irq, void *data)
330 mask = spu_int_mask_get(spu, 2); 383 mask = spu_int_mask_get(spu, 2);
331 /* ignore interrupts we're not waiting for */ 384 /* ignore interrupts we're not waiting for */
332 stat &= mask; 385 stat &= mask;
333 /* 386
334 * mailbox interrupts (0x1 and 0x10) are level triggered. 387 /* mailbox interrupts are level triggered. mask them now before
335 * mask them now before acknowledging. 388 * acknowledging */
336 */ 389 if (stat & mailbox_intrs)
337 if (stat & 0x11) 390 spu_int_mask_and(spu, 2, ~(stat & mailbox_intrs));
338 spu_int_mask_and(spu, 2, ~(stat & 0x11));
339 /* acknowledge all interrupts before the callbacks */ 391 /* acknowledge all interrupts before the callbacks */
340 spu_int_stat_clear(spu, 2, stat); 392 spu_int_stat_clear(spu, 2, stat);
341 spin_unlock(&spu->register_lock); 393 spin_unlock(&spu->register_lock);
342 394
343 pr_debug("class 2 interrupt %d, %lx, %lx\n", irq, stat, mask); 395 pr_debug("class 2 interrupt %d, %lx, %lx\n", irq, stat, mask);
344 396
345 if (stat & 1) /* PPC core mailbox */ 397 if (stat & CLASS2_MAILBOX_INTR)
346 spu->ibox_callback(spu); 398 spu->ibox_callback(spu);
347 399
348 if (stat & 2) /* SPU stop-and-signal */ 400 if (stat & CLASS2_SPU_STOP_INTR)
349 spu->stop_callback(spu); 401 spu->stop_callback(spu);
350 402
351 if (stat & 4) /* SPU halted */ 403 if (stat & CLASS2_SPU_HALT_INTR)
352 spu->stop_callback(spu); 404 spu->stop_callback(spu);
353 405
354 if (stat & 8) /* DMA tag group complete */ 406 if (stat & CLASS2_SPU_DMA_TAG_GROUP_COMPLETE_INTR)
355 spu->mfc_callback(spu); 407 spu->mfc_callback(spu);
356 408
357 if (stat & 0x10) /* SPU mailbox threshold */ 409 if (stat & CLASS2_MAILBOX_THRESHOLD_INTR)
358 spu->wbox_callback(spu); 410 spu->wbox_callback(spu);
359 411
360 spu->stats.class2_intr++; 412 spu->stats.class2_intr++;
@@ -479,13 +531,27 @@ EXPORT_SYMBOL_GPL(spu_add_sysdev_attr);
479int spu_add_sysdev_attr_group(struct attribute_group *attrs) 531int spu_add_sysdev_attr_group(struct attribute_group *attrs)
480{ 532{
481 struct spu *spu; 533 struct spu *spu;
534 int rc = 0;
482 535
483 mutex_lock(&spu_full_list_mutex); 536 mutex_lock(&spu_full_list_mutex);
484 list_for_each_entry(spu, &spu_full_list, full_list) 537 list_for_each_entry(spu, &spu_full_list, full_list) {
485 sysfs_create_group(&spu->sysdev.kobj, attrs); 538 rc = sysfs_create_group(&spu->sysdev.kobj, attrs);
539
540 /* we're in trouble here, but try unwinding anyway */
541 if (rc) {
542 printk(KERN_ERR "%s: can't create sysfs group '%s'\n",
543 __func__, attrs->name);
544
545 list_for_each_entry_continue_reverse(spu,
546 &spu_full_list, full_list)
547 sysfs_remove_group(&spu->sysdev.kobj, attrs);
548 break;
549 }
550 }
551
486 mutex_unlock(&spu_full_list_mutex); 552 mutex_unlock(&spu_full_list_mutex);
487 553
488 return 0; 554 return rc;
489} 555}
490EXPORT_SYMBOL_GPL(spu_add_sysdev_attr_group); 556EXPORT_SYMBOL_GPL(spu_add_sysdev_attr_group);
491 557
diff --git a/arch/powerpc/platforms/cell/spu_fault.c b/arch/powerpc/platforms/cell/spu_fault.c
new file mode 100644
index 000000000000..c8b1cd42905d
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spu_fault.c
@@ -0,0 +1,98 @@
1/*
2 * SPU mm fault handler
3 *
4 * (C) Copyright IBM Deutschland Entwicklung GmbH 2007
5 *
6 * Author: Arnd Bergmann <arndb@de.ibm.com>
7 * Author: Jeremy Kerr <jk@ozlabs.org>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23#include <linux/sched.h>
24#include <linux/mm.h>
25#include <linux/module.h>
26
27#include <asm/spu.h>
28#include <asm/spu_csa.h>
29
30/*
31 * This ought to be kept in sync with the powerpc specific do_page_fault
32 * function. Currently, there are a few corner cases that we haven't had
33 * to handle fortunately.
34 */
35int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
36 unsigned long dsisr, unsigned *flt)
37{
38 struct vm_area_struct *vma;
39 unsigned long is_write;
40 int ret;
41
42#if 0
43 if (!IS_VALID_EA(ea)) {
44 return -EFAULT;
45 }
46#endif /* XXX */
47 if (mm == NULL) {
48 return -EFAULT;
49 }
50 if (mm->pgd == NULL) {
51 return -EFAULT;
52 }
53
54 down_read(&mm->mmap_sem);
55 vma = find_vma(mm, ea);
56 if (!vma)
57 goto bad_area;
58 if (vma->vm_start <= ea)
59 goto good_area;
60 if (!(vma->vm_flags & VM_GROWSDOWN))
61 goto bad_area;
62 if (expand_stack(vma, ea))
63 goto bad_area;
64good_area:
65 is_write = dsisr & MFC_DSISR_ACCESS_PUT;
66 if (is_write) {
67 if (!(vma->vm_flags & VM_WRITE))
68 goto bad_area;
69 } else {
70 if (dsisr & MFC_DSISR_ACCESS_DENIED)
71 goto bad_area;
72 if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
73 goto bad_area;
74 }
75 ret = 0;
76 *flt = handle_mm_fault(mm, vma, ea, is_write);
77 if (unlikely(*flt & VM_FAULT_ERROR)) {
78 if (*flt & VM_FAULT_OOM) {
79 ret = -ENOMEM;
80 goto bad_area;
81 } else if (*flt & VM_FAULT_SIGBUS) {
82 ret = -EFAULT;
83 goto bad_area;
84 }
85 BUG();
86 }
87 if (*flt & VM_FAULT_MAJOR)
88 current->maj_flt++;
89 else
90 current->min_flt++;
91 up_read(&mm->mmap_sem);
92 return ret;
93
94bad_area:
95 up_read(&mm->mmap_sem);
96 return -EFAULT;
97}
98EXPORT_SYMBOL_GPL(spu_handle_mm_fault);
diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c
index 1b010707488d..d351bdebf5f1 100644
--- a/arch/powerpc/platforms/cell/spu_manage.c
+++ b/arch/powerpc/platforms/cell/spu_manage.c
@@ -35,6 +35,7 @@
35#include <asm/firmware.h> 35#include <asm/firmware.h>
36#include <asm/prom.h> 36#include <asm/prom.h>
37 37
38#include "spufs/spufs.h"
38#include "interrupt.h" 39#include "interrupt.h"
39 40
40struct device_node *spu_devnode(struct spu *spu) 41struct device_node *spu_devnode(struct spu *spu)
@@ -345,7 +346,7 @@ static int __init of_create_spu(struct spu *spu, void *data)
345 } 346 }
346 ret = spu_map_interrupts_old(spu, spe); 347 ret = spu_map_interrupts_old(spu, spe);
347 if (ret) { 348 if (ret) {
348 printk(KERN_ERR "%s: could not map interrupts", 349 printk(KERN_ERR "%s: could not map interrupts\n",
349 spu->name); 350 spu->name);
350 goto out_unmap; 351 goto out_unmap;
351 } 352 }
@@ -369,6 +370,16 @@ static int of_destroy_spu(struct spu *spu)
369 return 0; 370 return 0;
370} 371}
371 372
373static void enable_spu_by_master_run(struct spu_context *ctx)
374{
375 ctx->ops->master_start(ctx);
376}
377
378static void disable_spu_by_master_run(struct spu_context *ctx)
379{
380 ctx->ops->master_stop(ctx);
381}
382
372/* Hardcoded affinity idxs for qs20 */ 383/* Hardcoded affinity idxs for qs20 */
373#define QS20_SPES_PER_BE 8 384#define QS20_SPES_PER_BE 8
374static int qs20_reg_idxs[QS20_SPES_PER_BE] = { 0, 2, 4, 6, 7, 5, 3, 1 }; 385static int qs20_reg_idxs[QS20_SPES_PER_BE] = { 0, 2, 4, 6, 7, 5, 3, 1 };
@@ -411,10 +422,15 @@ static void init_affinity_qs20_harcoded(void)
411 422
412static int of_has_vicinity(void) 423static int of_has_vicinity(void)
413{ 424{
414 struct spu* spu; 425 struct device_node *dn;
415 426
416 spu = list_first_entry(&cbe_spu_info[0].spus, struct spu, cbe_list); 427 for_each_node_by_type(dn, "spe") {
417 return of_find_property(spu_devnode(spu), "vicinity", NULL) != NULL; 428 if (of_find_property(dn, "vicinity", NULL)) {
429 of_node_put(dn);
430 return 1;
431 }
432 }
433 return 0;
418} 434}
419 435
420static struct spu *devnode_spu(int cbe, struct device_node *dn) 436static struct spu *devnode_spu(int cbe, struct device_node *dn)
@@ -525,7 +541,7 @@ static int __init init_affinity(void)
525 if (of_flat_dt_is_compatible(root, "IBM,CPBW-1.0")) 541 if (of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
526 init_affinity_qs20_harcoded(); 542 init_affinity_qs20_harcoded();
527 else 543 else
528 printk("No affinity configuration found"); 544 printk("No affinity configuration found\n");
529 } 545 }
530 546
531 return 0; 547 return 0;
@@ -535,5 +551,7 @@ const struct spu_management_ops spu_management_of_ops = {
535 .enumerate_spus = of_enumerate_spus, 551 .enumerate_spus = of_enumerate_spus,
536 .create_spu = of_create_spu, 552 .create_spu = of_create_spu,
537 .destroy_spu = of_destroy_spu, 553 .destroy_spu = of_destroy_spu,
554 .enable_spu = enable_spu_by_master_run,
555 .disable_spu = disable_spu_by_master_run,
538 .init_affinity = init_affinity, 556 .init_affinity = init_affinity,
539}; 557};
diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile
index 328afcf89503..d3a349fb42e5 100644
--- a/arch/powerpc/platforms/cell/spufs/Makefile
+++ b/arch/powerpc/platforms/cell/spufs/Makefile
@@ -1,8 +1,8 @@
1obj-y += switch.o fault.o lscsa_alloc.o
2 1
3obj-$(CONFIG_SPU_FS) += spufs.o 2obj-$(CONFIG_SPU_FS) += spufs.o
4spufs-y += inode.o file.o context.o syscalls.o coredump.o 3spufs-y += inode.o file.o context.o syscalls.o coredump.o
5spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o 4spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o
5spufs-y += switch.o fault.o lscsa_alloc.o
6 6
7# Rules to build switch.o with the help of SPU tool chain 7# Rules to build switch.o with the help of SPU tool chain
8SPU_CROSS := spu- 8SPU_CROSS := spu-
diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c
index ec01214e51ee..50d98a154aaf 100644
--- a/arch/powerpc/platforms/cell/spufs/backing_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c
@@ -106,16 +106,20 @@ static unsigned int spu_backing_mbox_stat_poll(struct spu_context *ctx,
106 if (stat & 0xff0000) 106 if (stat & 0xff0000)
107 ret |= POLLIN | POLLRDNORM; 107 ret |= POLLIN | POLLRDNORM;
108 else { 108 else {
109 ctx->csa.priv1.int_stat_class0_RW &= ~0x1; 109 ctx->csa.priv1.int_stat_class2_RW &=
110 ctx->csa.priv1.int_mask_class2_RW |= 0x1; 110 ~CLASS2_MAILBOX_INTR;
111 ctx->csa.priv1.int_mask_class2_RW |=
112 CLASS2_ENABLE_MAILBOX_INTR;
111 } 113 }
112 } 114 }
113 if (events & (POLLOUT | POLLWRNORM)) { 115 if (events & (POLLOUT | POLLWRNORM)) {
114 if (stat & 0x00ff00) 116 if (stat & 0x00ff00)
115 ret = POLLOUT | POLLWRNORM; 117 ret = POLLOUT | POLLWRNORM;
116 else { 118 else {
117 ctx->csa.priv1.int_stat_class0_RW &= ~0x10; 119 ctx->csa.priv1.int_stat_class2_RW &=
118 ctx->csa.priv1.int_mask_class2_RW |= 0x10; 120 ~CLASS2_MAILBOX_THRESHOLD_INTR;
121 ctx->csa.priv1.int_mask_class2_RW |=
122 CLASS2_ENABLE_MAILBOX_THRESHOLD_INTR;
119 } 123 }
120 } 124 }
121 spin_unlock_irq(&ctx->csa.register_lock); 125 spin_unlock_irq(&ctx->csa.register_lock);
@@ -139,7 +143,7 @@ static int spu_backing_ibox_read(struct spu_context *ctx, u32 * data)
139 ret = 4; 143 ret = 4;
140 } else { 144 } else {
141 /* make sure we get woken up by the interrupt */ 145 /* make sure we get woken up by the interrupt */
142 ctx->csa.priv1.int_mask_class2_RW |= 0x1UL; 146 ctx->csa.priv1.int_mask_class2_RW |= CLASS2_ENABLE_MAILBOX_INTR;
143 ret = 0; 147 ret = 0;
144 } 148 }
145 spin_unlock(&ctx->csa.register_lock); 149 spin_unlock(&ctx->csa.register_lock);
@@ -169,7 +173,8 @@ static int spu_backing_wbox_write(struct spu_context *ctx, u32 data)
169 } else { 173 } else {
170 /* make sure we get woken up by the interrupt when space 174 /* make sure we get woken up by the interrupt when space
171 becomes available */ 175 becomes available */
172 ctx->csa.priv1.int_mask_class2_RW |= 0x10; 176 ctx->csa.priv1.int_mask_class2_RW |=
177 CLASS2_ENABLE_MAILBOX_THRESHOLD_INTR;
173 ret = 0; 178 ret = 0;
174 } 179 }
175 spin_unlock(&ctx->csa.register_lock); 180 spin_unlock(&ctx->csa.register_lock);
@@ -268,6 +273,11 @@ static char *spu_backing_get_ls(struct spu_context *ctx)
268 return ctx->csa.lscsa->ls; 273 return ctx->csa.lscsa->ls;
269} 274}
270 275
276static void spu_backing_privcntl_write(struct spu_context *ctx, u64 val)
277{
278 ctx->csa.priv2.spu_privcntl_RW = val;
279}
280
271static u32 spu_backing_runcntl_read(struct spu_context *ctx) 281static u32 spu_backing_runcntl_read(struct spu_context *ctx)
272{ 282{
273 return ctx->csa.prob.spu_runcntl_RW; 283 return ctx->csa.prob.spu_runcntl_RW;
@@ -285,6 +295,11 @@ static void spu_backing_runcntl_write(struct spu_context *ctx, u32 val)
285 spin_unlock(&ctx->csa.register_lock); 295 spin_unlock(&ctx->csa.register_lock);
286} 296}
287 297
298static void spu_backing_runcntl_stop(struct spu_context *ctx)
299{
300 spu_backing_runcntl_write(ctx, SPU_RUNCNTL_STOP);
301}
302
288static void spu_backing_master_start(struct spu_context *ctx) 303static void spu_backing_master_start(struct spu_context *ctx)
289{ 304{
290 struct spu_state *csa = &ctx->csa; 305 struct spu_state *csa = &ctx->csa;
@@ -358,7 +373,7 @@ static int spu_backing_send_mfc_command(struct spu_context *ctx,
358 373
359static void spu_backing_restart_dma(struct spu_context *ctx) 374static void spu_backing_restart_dma(struct spu_context *ctx)
360{ 375{
361 /* nothing to do here */ 376 ctx->csa.priv2.mfc_control_RW |= MFC_CNTL_RESTART_DMA_COMMAND;
362} 377}
363 378
364struct spu_context_ops spu_backing_ops = { 379struct spu_context_ops spu_backing_ops = {
@@ -379,8 +394,10 @@ struct spu_context_ops spu_backing_ops = {
379 .npc_write = spu_backing_npc_write, 394 .npc_write = spu_backing_npc_write,
380 .status_read = spu_backing_status_read, 395 .status_read = spu_backing_status_read,
381 .get_ls = spu_backing_get_ls, 396 .get_ls = spu_backing_get_ls,
397 .privcntl_write = spu_backing_privcntl_write,
382 .runcntl_read = spu_backing_runcntl_read, 398 .runcntl_read = spu_backing_runcntl_read,
383 .runcntl_write = spu_backing_runcntl_write, 399 .runcntl_write = spu_backing_runcntl_write,
400 .runcntl_stop = spu_backing_runcntl_stop,
384 .master_start = spu_backing_master_start, 401 .master_start = spu_backing_master_start,
385 .master_stop = spu_backing_master_stop, 402 .master_stop = spu_backing_master_stop,
386 .set_mfc_query = spu_backing_set_mfc_query, 403 .set_mfc_query = spu_backing_set_mfc_query,
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index adf0a030d6fe..133995ed5cc7 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -52,6 +52,7 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
52 init_waitqueue_head(&ctx->wbox_wq); 52 init_waitqueue_head(&ctx->wbox_wq);
53 init_waitqueue_head(&ctx->stop_wq); 53 init_waitqueue_head(&ctx->stop_wq);
54 init_waitqueue_head(&ctx->mfc_wq); 54 init_waitqueue_head(&ctx->mfc_wq);
55 init_waitqueue_head(&ctx->run_wq);
55 ctx->state = SPU_STATE_SAVED; 56 ctx->state = SPU_STATE_SAVED;
56 ctx->ops = &spu_backing_ops; 57 ctx->ops = &spu_backing_ops;
57 ctx->owner = get_task_mm(current); 58 ctx->owner = get_task_mm(current);
@@ -105,7 +106,17 @@ int put_spu_context(struct spu_context *ctx)
105void spu_forget(struct spu_context *ctx) 106void spu_forget(struct spu_context *ctx)
106{ 107{
107 struct mm_struct *mm; 108 struct mm_struct *mm;
108 spu_acquire_saved(ctx); 109
110 /*
111 * This is basically an open-coded spu_acquire_saved, except that
112 * we don't acquire the state mutex interruptible.
113 */
114 mutex_lock(&ctx->state_mutex);
115 if (ctx->state != SPU_STATE_SAVED) {
116 set_bit(SPU_SCHED_WAS_ACTIVE, &ctx->sched_flags);
117 spu_deactivate(ctx);
118 }
119
109 mm = ctx->owner; 120 mm = ctx->owner;
110 ctx->owner = NULL; 121 ctx->owner = NULL;
111 mmput(mm); 122 mmput(mm);
@@ -133,47 +144,23 @@ void spu_unmap_mappings(struct spu_context *ctx)
133} 144}
134 145
135/** 146/**
136 * spu_acquire_runnable - lock spu contex and make sure it is in runnable state 147 * spu_acquire_saved - lock spu contex and make sure it is in saved state
137 * @ctx: spu contex to lock 148 * @ctx: spu contex to lock
138 *
139 * Note:
140 * Returns 0 and with the context locked on success
141 * Returns negative error and with the context _unlocked_ on failure.
142 */ 149 */
143int spu_acquire_runnable(struct spu_context *ctx, unsigned long flags) 150int spu_acquire_saved(struct spu_context *ctx)
144{ 151{
145 int ret = -EINVAL; 152 int ret;
146
147 spu_acquire(ctx);
148 if (ctx->state == SPU_STATE_SAVED) {
149 /*
150 * Context is about to be freed, so we can't acquire it anymore.
151 */
152 if (!ctx->owner)
153 goto out_unlock;
154 ret = spu_activate(ctx, flags);
155 if (ret)
156 goto out_unlock;
157 }
158 153
159 return 0; 154 ret = spu_acquire(ctx);
160 155 if (ret)
161 out_unlock: 156 return ret;
162 spu_release(ctx);
163 return ret;
164}
165 157
166/**
167 * spu_acquire_saved - lock spu contex and make sure it is in saved state
168 * @ctx: spu contex to lock
169 */
170void spu_acquire_saved(struct spu_context *ctx)
171{
172 spu_acquire(ctx);
173 if (ctx->state != SPU_STATE_SAVED) { 158 if (ctx->state != SPU_STATE_SAVED) {
174 set_bit(SPU_SCHED_WAS_ACTIVE, &ctx->sched_flags); 159 set_bit(SPU_SCHED_WAS_ACTIVE, &ctx->sched_flags);
175 spu_deactivate(ctx); 160 spu_deactivate(ctx);
176 } 161 }
162
163 return 0;
177} 164}
178 165
179/** 166/**
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 80f62363e1ce..0c6a96b82b2d 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -148,7 +148,9 @@ int spufs_coredump_extra_notes_size(void)
148 148
149 fd = 0; 149 fd = 0;
150 while ((ctx = coredump_next_context(&fd)) != NULL) { 150 while ((ctx = coredump_next_context(&fd)) != NULL) {
151 spu_acquire_saved(ctx); 151 rc = spu_acquire_saved(ctx);
152 if (rc)
153 break;
152 rc = spufs_ctx_note_size(ctx, fd); 154 rc = spufs_ctx_note_size(ctx, fd);
153 spu_release_saved(ctx); 155 spu_release_saved(ctx);
154 if (rc < 0) 156 if (rc < 0)
@@ -224,7 +226,9 @@ int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset)
224 226
225 fd = 0; 227 fd = 0;
226 while ((ctx = coredump_next_context(&fd)) != NULL) { 228 while ((ctx = coredump_next_context(&fd)) != NULL) {
227 spu_acquire_saved(ctx); 229 rc = spu_acquire_saved(ctx);
230 if (rc)
231 return rc;
228 232
229 for (j = 0; spufs_coredump_read[j].name != NULL; j++) { 233 for (j = 0; spufs_coredump_read[j].name != NULL; j++) {
230 rc = spufs_arch_write_note(ctx, j, file, fd, foffset); 234 rc = spufs_arch_write_note(ctx, j, file, fd, foffset);
diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c
index 917eab4be486..eff4d291ba85 100644
--- a/arch/powerpc/platforms/cell/spufs/fault.c
+++ b/arch/powerpc/platforms/cell/spufs/fault.c
@@ -28,117 +28,71 @@
28 28
29#include "spufs.h" 29#include "spufs.h"
30 30
31/* 31/**
32 * This ought to be kept in sync with the powerpc specific do_page_fault 32 * Handle an SPE event, depending on context SPU_CREATE_EVENTS_ENABLED flag.
33 * function. Currently, there are a few corner cases that we haven't had 33 *
34 * to handle fortunately. 34 * If the context was created with events, we just set the return event.
35 * Otherwise, send an appropriate signal to the process.
35 */ 36 */
36static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, 37static void spufs_handle_event(struct spu_context *ctx,
37 unsigned long dsisr, unsigned *flt) 38 unsigned long ea, int type)
38{ 39{
39 struct vm_area_struct *vma; 40 siginfo_t info;
40 unsigned long is_write;
41 int ret;
42 41
43#if 0 42 if (ctx->flags & SPU_CREATE_EVENTS_ENABLED) {
44 if (!IS_VALID_EA(ea)) { 43 ctx->event_return |= type;
45 return -EFAULT; 44 wake_up_all(&ctx->stop_wq);
46 } 45 return;
47#endif /* XXX */
48 if (mm == NULL) {
49 return -EFAULT;
50 }
51 if (mm->pgd == NULL) {
52 return -EFAULT;
53 } 46 }
54 47
55 down_read(&mm->mmap_sem); 48 memset(&info, 0, sizeof(info));
56 vma = find_vma(mm, ea); 49
57 if (!vma) 50 switch (type) {
58 goto bad_area; 51 case SPE_EVENT_INVALID_DMA:
59 if (vma->vm_start <= ea) 52 info.si_signo = SIGBUS;
60 goto good_area; 53 info.si_code = BUS_OBJERR;
61 if (!(vma->vm_flags & VM_GROWSDOWN)) 54 break;
62 goto bad_area; 55 case SPE_EVENT_SPE_DATA_STORAGE:
63 if (expand_stack(vma, ea)) 56 info.si_signo = SIGSEGV;
64 goto bad_area; 57 info.si_addr = (void __user *)ea;
65good_area: 58 info.si_code = SEGV_ACCERR;
66 is_write = dsisr & MFC_DSISR_ACCESS_PUT; 59 ctx->ops->restart_dma(ctx);
67 if (is_write) { 60 break;
68 if (!(vma->vm_flags & VM_WRITE)) 61 case SPE_EVENT_DMA_ALIGNMENT:
69 goto bad_area; 62 info.si_signo = SIGBUS;
70 } else { 63 /* DAR isn't set for an alignment fault :( */
71 if (dsisr & MFC_DSISR_ACCESS_DENIED) 64 info.si_code = BUS_ADRALN;
72 goto bad_area; 65 break;
73 if (!(vma->vm_flags & (VM_READ | VM_EXEC))) 66 case SPE_EVENT_SPE_ERROR:
74 goto bad_area; 67 info.si_signo = SIGILL;
68 info.si_addr = (void __user *)(unsigned long)
69 ctx->ops->npc_read(ctx) - 4;
70 info.si_code = ILL_ILLOPC;
71 break;
75 } 72 }
76 ret = 0;
77 *flt = handle_mm_fault(mm, vma, ea, is_write);
78 if (unlikely(*flt & VM_FAULT_ERROR)) {
79 if (*flt & VM_FAULT_OOM) {
80 ret = -ENOMEM;
81 goto bad_area;
82 } else if (*flt & VM_FAULT_SIGBUS) {
83 ret = -EFAULT;
84 goto bad_area;
85 }
86 BUG();
87 }
88 if (*flt & VM_FAULT_MAJOR)
89 current->maj_flt++;
90 else
91 current->min_flt++;
92 up_read(&mm->mmap_sem);
93 return ret;
94 73
95bad_area: 74 if (info.si_signo)
96 up_read(&mm->mmap_sem); 75 force_sig_info(info.si_signo, &info, current);
97 return -EFAULT;
98} 76}
99 77
100static void spufs_handle_dma_error(struct spu_context *ctx, 78int spufs_handle_class0(struct spu_context *ctx)
101 unsigned long ea, int type)
102{ 79{
103 if (ctx->flags & SPU_CREATE_EVENTS_ENABLED) { 80 unsigned long stat = ctx->csa.class_0_pending & CLASS0_INTR_MASK;
104 ctx->event_return |= type;
105 wake_up_all(&ctx->stop_wq);
106 } else {
107 siginfo_t info;
108 memset(&info, 0, sizeof(info));
109
110 switch (type) {
111 case SPE_EVENT_INVALID_DMA:
112 info.si_signo = SIGBUS;
113 info.si_code = BUS_OBJERR;
114 break;
115 case SPE_EVENT_SPE_DATA_STORAGE:
116 info.si_signo = SIGBUS;
117 info.si_addr = (void __user *)ea;
118 info.si_code = BUS_ADRERR;
119 break;
120 case SPE_EVENT_DMA_ALIGNMENT:
121 info.si_signo = SIGBUS;
122 /* DAR isn't set for an alignment fault :( */
123 info.si_code = BUS_ADRALN;
124 break;
125 case SPE_EVENT_SPE_ERROR:
126 info.si_signo = SIGILL;
127 info.si_addr = (void __user *)(unsigned long)
128 ctx->ops->npc_read(ctx) - 4;
129 info.si_code = ILL_ILLOPC;
130 break;
131 }
132 if (info.si_signo)
133 force_sig_info(info.si_signo, &info, current);
134 }
135}
136 81
137void spufs_dma_callback(struct spu *spu, int type) 82 if (likely(!stat))
138{ 83 return 0;
139 spufs_handle_dma_error(spu->ctx, spu->dar, type); 84
85 if (stat & CLASS0_DMA_ALIGNMENT_INTR)
86 spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_DMA_ALIGNMENT);
87
88 if (stat & CLASS0_INVALID_DMA_COMMAND_INTR)
89 spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_INVALID_DMA);
90
91 if (stat & CLASS0_SPU_ERROR_INTR)
92 spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_SPE_ERROR);
93
94 return -EIO;
140} 95}
141EXPORT_SYMBOL_GPL(spufs_dma_callback);
142 96
143/* 97/*
144 * bottom half handler for page faults, we can't do this from 98 * bottom half handler for page faults, we can't do this from
@@ -154,7 +108,7 @@ int spufs_handle_class1(struct spu_context *ctx)
154 u64 ea, dsisr, access; 108 u64 ea, dsisr, access;
155 unsigned long flags; 109 unsigned long flags;
156 unsigned flt = 0; 110 unsigned flt = 0;
157 int ret; 111 int ret, ret2;
158 112
159 /* 113 /*
160 * dar and dsisr get passed from the registers 114 * dar and dsisr get passed from the registers
@@ -165,16 +119,8 @@ int spufs_handle_class1(struct spu_context *ctx)
165 * in time, we can still expect to get the same fault 119 * in time, we can still expect to get the same fault
166 * the immediately after the context restore. 120 * the immediately after the context restore.
167 */ 121 */
168 if (ctx->state == SPU_STATE_RUNNABLE) { 122 ea = ctx->csa.dar;
169 ea = ctx->spu->dar; 123 dsisr = ctx->csa.dsisr;
170 dsisr = ctx->spu->dsisr;
171 ctx->spu->dar= ctx->spu->dsisr = 0;
172 } else {
173 ea = ctx->csa.priv1.mfc_dar_RW;
174 dsisr = ctx->csa.priv1.mfc_dsisr_RW;
175 ctx->csa.priv1.mfc_dar_RW = 0;
176 ctx->csa.priv1.mfc_dsisr_RW = 0;
177 }
178 124
179 if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED))) 125 if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)))
180 return 0; 126 return 0;
@@ -201,7 +147,22 @@ int spufs_handle_class1(struct spu_context *ctx)
201 if (ret) 147 if (ret)
202 ret = spu_handle_mm_fault(current->mm, ea, dsisr, &flt); 148 ret = spu_handle_mm_fault(current->mm, ea, dsisr, &flt);
203 149
204 spu_acquire(ctx); 150 /*
151 * If spu_acquire fails due to a pending signal we just want to return
152 * EINTR to userspace even if that means missing the dma restart or
153 * updating the page fault statistics.
154 */
155 ret2 = spu_acquire(ctx);
156 if (ret2)
157 goto out;
158
159 /*
160 * Clear dsisr under ctxt lock after handling the fault, so that
161 * time slicing will not preempt the context while the page fault
162 * handler is running. Context switch code removes mappings.
163 */
164 ctx->csa.dar = ctx->csa.dsisr = 0;
165
205 /* 166 /*
206 * If we handled the fault successfully and are in runnable 167 * If we handled the fault successfully and are in runnable
207 * state, restart the DMA. 168 * state, restart the DMA.
@@ -222,9 +183,9 @@ int spufs_handle_class1(struct spu_context *ctx)
222 if (ctx->spu) 183 if (ctx->spu)
223 ctx->ops->restart_dma(ctx); 184 ctx->ops->restart_dma(ctx);
224 } else 185 } else
225 spufs_handle_dma_error(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE); 186 spufs_handle_event(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE);
226 187
188 out:
227 spuctx_switch_state(ctx, SPU_UTIL_SYSTEM); 189 spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);
228 return ret; 190 return ret;
229} 191}
230EXPORT_SYMBOL_GPL(spufs_handle_class1);
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index d9e56a503795..3fcd06418b01 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -40,6 +40,120 @@
40 40
41#define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000) 41#define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000)
42 42
43/* Simple attribute files */
44struct spufs_attr {
45 int (*get)(void *, u64 *);
46 int (*set)(void *, u64);
47 char get_buf[24]; /* enough to store a u64 and "\n\0" */
48 char set_buf[24];
49 void *data;
50 const char *fmt; /* format for read operation */
51 struct mutex mutex; /* protects access to these buffers */
52};
53
54static int spufs_attr_open(struct inode *inode, struct file *file,
55 int (*get)(void *, u64 *), int (*set)(void *, u64),
56 const char *fmt)
57{
58 struct spufs_attr *attr;
59
60 attr = kmalloc(sizeof(*attr), GFP_KERNEL);
61 if (!attr)
62 return -ENOMEM;
63
64 attr->get = get;
65 attr->set = set;
66 attr->data = inode->i_private;
67 attr->fmt = fmt;
68 mutex_init(&attr->mutex);
69 file->private_data = attr;
70
71 return nonseekable_open(inode, file);
72}
73
74static int spufs_attr_release(struct inode *inode, struct file *file)
75{
76 kfree(file->private_data);
77 return 0;
78}
79
80static ssize_t spufs_attr_read(struct file *file, char __user *buf,
81 size_t len, loff_t *ppos)
82{
83 struct spufs_attr *attr;
84 size_t size;
85 ssize_t ret;
86
87 attr = file->private_data;
88 if (!attr->get)
89 return -EACCES;
90
91 ret = mutex_lock_interruptible(&attr->mutex);
92 if (ret)
93 return ret;
94
95 if (*ppos) { /* continued read */
96 size = strlen(attr->get_buf);
97 } else { /* first read */
98 u64 val;
99 ret = attr->get(attr->data, &val);
100 if (ret)
101 goto out;
102
103 size = scnprintf(attr->get_buf, sizeof(attr->get_buf),
104 attr->fmt, (unsigned long long)val);
105 }
106
107 ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size);
108out:
109 mutex_unlock(&attr->mutex);
110 return ret;
111}
112
113static ssize_t spufs_attr_write(struct file *file, const char __user *buf,
114 size_t len, loff_t *ppos)
115{
116 struct spufs_attr *attr;
117 u64 val;
118 size_t size;
119 ssize_t ret;
120
121 attr = file->private_data;
122 if (!attr->set)
123 return -EACCES;
124
125 ret = mutex_lock_interruptible(&attr->mutex);
126 if (ret)
127 return ret;
128
129 ret = -EFAULT;
130 size = min(sizeof(attr->set_buf) - 1, len);
131 if (copy_from_user(attr->set_buf, buf, size))
132 goto out;
133
134 ret = len; /* claim we got the whole input */
135 attr->set_buf[size] = '\0';
136 val = simple_strtol(attr->set_buf, NULL, 0);
137 attr->set(attr->data, val);
138out:
139 mutex_unlock(&attr->mutex);
140 return ret;
141}
142
143#define DEFINE_SPUFS_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt) \
144static int __fops ## _open(struct inode *inode, struct file *file) \
145{ \
146 __simple_attr_check_format(__fmt, 0ull); \
147 return spufs_attr_open(inode, file, __get, __set, __fmt); \
148} \
149static struct file_operations __fops = { \
150 .owner = THIS_MODULE, \
151 .open = __fops ## _open, \
152 .release = spufs_attr_release, \
153 .read = spufs_attr_read, \
154 .write = spufs_attr_write, \
155};
156
43 157
44static int 158static int
45spufs_mem_open(struct inode *inode, struct file *file) 159spufs_mem_open(struct inode *inode, struct file *file)
@@ -84,9 +198,12 @@ spufs_mem_read(struct file *file, char __user *buffer,
84 struct spu_context *ctx = file->private_data; 198 struct spu_context *ctx = file->private_data;
85 ssize_t ret; 199 ssize_t ret;
86 200
87 spu_acquire(ctx); 201 ret = spu_acquire(ctx);
202 if (ret)
203 return ret;
88 ret = __spufs_mem_read(ctx, buffer, size, pos); 204 ret = __spufs_mem_read(ctx, buffer, size, pos);
89 spu_release(ctx); 205 spu_release(ctx);
206
90 return ret; 207 return ret;
91} 208}
92 209
@@ -106,7 +223,10 @@ spufs_mem_write(struct file *file, const char __user *buffer,
106 if (size > LS_SIZE - pos) 223 if (size > LS_SIZE - pos)
107 size = LS_SIZE - pos; 224 size = LS_SIZE - pos;
108 225
109 spu_acquire(ctx); 226 ret = spu_acquire(ctx);
227 if (ret)
228 return ret;
229
110 local_store = ctx->ops->get_ls(ctx); 230 local_store = ctx->ops->get_ls(ctx);
111 ret = copy_from_user(local_store + pos, buffer, size); 231 ret = copy_from_user(local_store + pos, buffer, size);
112 spu_release(ctx); 232 spu_release(ctx);
@@ -146,7 +266,8 @@ static unsigned long spufs_mem_mmap_nopfn(struct vm_area_struct *vma,
146 pr_debug("spufs_mem_mmap_nopfn address=0x%lx -> 0x%lx, offset=0x%lx\n", 266 pr_debug("spufs_mem_mmap_nopfn address=0x%lx -> 0x%lx, offset=0x%lx\n",
147 addr0, address, offset); 267 addr0, address, offset);
148 268
149 spu_acquire(ctx); 269 if (spu_acquire(ctx))
270 return NOPFN_REFAULT;
150 271
151 if (ctx->state == SPU_STATE_SAVED) { 272 if (ctx->state == SPU_STATE_SAVED) {
152 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 273 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
@@ -236,23 +357,32 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma,
236{ 357{
237 struct spu_context *ctx = vma->vm_file->private_data; 358 struct spu_context *ctx = vma->vm_file->private_data;
238 unsigned long area, offset = address - vma->vm_start; 359 unsigned long area, offset = address - vma->vm_start;
239 int ret;
240 360
241 offset += vma->vm_pgoff << PAGE_SHIFT; 361 offset += vma->vm_pgoff << PAGE_SHIFT;
242 if (offset >= ps_size) 362 if (offset >= ps_size)
243 return NOPFN_SIGBUS; 363 return NOPFN_SIGBUS;
244 364
245 /* error here usually means a signal.. we might want to test 365 /*
246 * the error code more precisely though 366 * We have to wait for context to be loaded before we have
367 * pages to hand out to the user, but we don't want to wait
368 * with the mmap_sem held.
369 * It is possible to drop the mmap_sem here, but then we need
370 * to return NOPFN_REFAULT because the mappings may have
371 * hanged.
247 */ 372 */
248 ret = spu_acquire_runnable(ctx, 0); 373 if (spu_acquire(ctx))
249 if (ret)
250 return NOPFN_REFAULT; 374 return NOPFN_REFAULT;
251 375
252 area = ctx->spu->problem_phys + ps_offs; 376 if (ctx->state == SPU_STATE_SAVED) {
253 vm_insert_pfn(vma, address, (area + offset) >> PAGE_SHIFT); 377 up_read(&current->mm->mmap_sem);
254 spu_release(ctx); 378 spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE);
379 down_read(&current->mm->mmap_sem);
380 } else {
381 area = ctx->spu->problem_phys + ps_offs;
382 vm_insert_pfn(vma, address, (area + offset) >> PAGE_SHIFT);
383 }
255 384
385 spu_release(ctx);
256 return NOPFN_REFAULT; 386 return NOPFN_REFAULT;
257} 387}
258 388
@@ -286,25 +416,32 @@ static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma)
286#define spufs_cntl_mmap NULL 416#define spufs_cntl_mmap NULL
287#endif /* !SPUFS_MMAP_4K */ 417#endif /* !SPUFS_MMAP_4K */
288 418
289static u64 spufs_cntl_get(void *data) 419static int spufs_cntl_get(void *data, u64 *val)
290{ 420{
291 struct spu_context *ctx = data; 421 struct spu_context *ctx = data;
292 u64 val; 422 int ret;
293 423
294 spu_acquire(ctx); 424 ret = spu_acquire(ctx);
295 val = ctx->ops->status_read(ctx); 425 if (ret)
426 return ret;
427 *val = ctx->ops->status_read(ctx);
296 spu_release(ctx); 428 spu_release(ctx);
297 429
298 return val; 430 return 0;
299} 431}
300 432
301static void spufs_cntl_set(void *data, u64 val) 433static int spufs_cntl_set(void *data, u64 val)
302{ 434{
303 struct spu_context *ctx = data; 435 struct spu_context *ctx = data;
436 int ret;
304 437
305 spu_acquire(ctx); 438 ret = spu_acquire(ctx);
439 if (ret)
440 return ret;
306 ctx->ops->runcntl_write(ctx, val); 441 ctx->ops->runcntl_write(ctx, val);
307 spu_release(ctx); 442 spu_release(ctx);
443
444 return 0;
308} 445}
309 446
310static int spufs_cntl_open(struct inode *inode, struct file *file) 447static int spufs_cntl_open(struct inode *inode, struct file *file)
@@ -317,7 +454,7 @@ static int spufs_cntl_open(struct inode *inode, struct file *file)
317 if (!i->i_openers++) 454 if (!i->i_openers++)
318 ctx->cntl = inode->i_mapping; 455 ctx->cntl = inode->i_mapping;
319 mutex_unlock(&ctx->mapping_lock); 456 mutex_unlock(&ctx->mapping_lock);
320 return simple_attr_open(inode, file, spufs_cntl_get, 457 return spufs_attr_open(inode, file, spufs_cntl_get,
321 spufs_cntl_set, "0x%08lx"); 458 spufs_cntl_set, "0x%08lx");
322} 459}
323 460
@@ -327,7 +464,7 @@ spufs_cntl_release(struct inode *inode, struct file *file)
327 struct spufs_inode_info *i = SPUFS_I(inode); 464 struct spufs_inode_info *i = SPUFS_I(inode);
328 struct spu_context *ctx = i->i_ctx; 465 struct spu_context *ctx = i->i_ctx;
329 466
330 simple_attr_close(inode, file); 467 spufs_attr_release(inode, file);
331 468
332 mutex_lock(&ctx->mapping_lock); 469 mutex_lock(&ctx->mapping_lock);
333 if (!--i->i_openers) 470 if (!--i->i_openers)
@@ -339,8 +476,8 @@ spufs_cntl_release(struct inode *inode, struct file *file)
339static const struct file_operations spufs_cntl_fops = { 476static const struct file_operations spufs_cntl_fops = {
340 .open = spufs_cntl_open, 477 .open = spufs_cntl_open,
341 .release = spufs_cntl_release, 478 .release = spufs_cntl_release,
342 .read = simple_attr_read, 479 .read = spufs_attr_read,
343 .write = simple_attr_write, 480 .write = spufs_attr_write,
344 .mmap = spufs_cntl_mmap, 481 .mmap = spufs_cntl_mmap,
345}; 482};
346 483
@@ -368,7 +505,9 @@ spufs_regs_read(struct file *file, char __user *buffer,
368 int ret; 505 int ret;
369 struct spu_context *ctx = file->private_data; 506 struct spu_context *ctx = file->private_data;
370 507
371 spu_acquire_saved(ctx); 508 ret = spu_acquire_saved(ctx);
509 if (ret)
510 return ret;
372 ret = __spufs_regs_read(ctx, buffer, size, pos); 511 ret = __spufs_regs_read(ctx, buffer, size, pos);
373 spu_release_saved(ctx); 512 spu_release_saved(ctx);
374 return ret; 513 return ret;
@@ -387,7 +526,9 @@ spufs_regs_write(struct file *file, const char __user *buffer,
387 return -EFBIG; 526 return -EFBIG;
388 *pos += size; 527 *pos += size;
389 528
390 spu_acquire_saved(ctx); 529 ret = spu_acquire_saved(ctx);
530 if (ret)
531 return ret;
391 532
392 ret = copy_from_user(lscsa->gprs + *pos - size, 533 ret = copy_from_user(lscsa->gprs + *pos - size,
393 buffer, size) ? -EFAULT : size; 534 buffer, size) ? -EFAULT : size;
@@ -419,7 +560,9 @@ spufs_fpcr_read(struct file *file, char __user * buffer,
419 int ret; 560 int ret;
420 struct spu_context *ctx = file->private_data; 561 struct spu_context *ctx = file->private_data;
421 562
422 spu_acquire_saved(ctx); 563 ret = spu_acquire_saved(ctx);
564 if (ret)
565 return ret;
423 ret = __spufs_fpcr_read(ctx, buffer, size, pos); 566 ret = __spufs_fpcr_read(ctx, buffer, size, pos);
424 spu_release_saved(ctx); 567 spu_release_saved(ctx);
425 return ret; 568 return ret;
@@ -436,10 +579,12 @@ spufs_fpcr_write(struct file *file, const char __user * buffer,
436 size = min_t(ssize_t, sizeof(lscsa->fpcr) - *pos, size); 579 size = min_t(ssize_t, sizeof(lscsa->fpcr) - *pos, size);
437 if (size <= 0) 580 if (size <= 0)
438 return -EFBIG; 581 return -EFBIG;
439 *pos += size;
440 582
441 spu_acquire_saved(ctx); 583 ret = spu_acquire_saved(ctx);
584 if (ret)
585 return ret;
442 586
587 *pos += size;
443 ret = copy_from_user((char *)&lscsa->fpcr + *pos - size, 588 ret = copy_from_user((char *)&lscsa->fpcr + *pos - size,
444 buffer, size) ? -EFAULT : size; 589 buffer, size) ? -EFAULT : size;
445 590
@@ -486,7 +631,10 @@ static ssize_t spufs_mbox_read(struct file *file, char __user *buf,
486 631
487 udata = (void __user *)buf; 632 udata = (void __user *)buf;
488 633
489 spu_acquire(ctx); 634 count = spu_acquire(ctx);
635 if (count)
636 return count;
637
490 for (count = 0; (count + 4) <= len; count += 4, udata++) { 638 for (count = 0; (count + 4) <= len; count += 4, udata++) {
491 int ret; 639 int ret;
492 ret = ctx->ops->mbox_read(ctx, &mbox_data); 640 ret = ctx->ops->mbox_read(ctx, &mbox_data);
@@ -522,12 +670,15 @@ static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf,
522 size_t len, loff_t *pos) 670 size_t len, loff_t *pos)
523{ 671{
524 struct spu_context *ctx = file->private_data; 672 struct spu_context *ctx = file->private_data;
673 ssize_t ret;
525 u32 mbox_stat; 674 u32 mbox_stat;
526 675
527 if (len < 4) 676 if (len < 4)
528 return -EINVAL; 677 return -EINVAL;
529 678
530 spu_acquire(ctx); 679 ret = spu_acquire(ctx);
680 if (ret)
681 return ret;
531 682
532 mbox_stat = ctx->ops->mbox_stat_read(ctx) & 0xff; 683 mbox_stat = ctx->ops->mbox_stat_read(ctx) & 0xff;
533 684
@@ -562,6 +713,9 @@ void spufs_ibox_callback(struct spu *spu)
562{ 713{
563 struct spu_context *ctx = spu->ctx; 714 struct spu_context *ctx = spu->ctx;
564 715
716 if (!ctx)
717 return;
718
565 wake_up_all(&ctx->ibox_wq); 719 wake_up_all(&ctx->ibox_wq);
566 kill_fasync(&ctx->ibox_fasync, SIGIO, POLLIN); 720 kill_fasync(&ctx->ibox_fasync, SIGIO, POLLIN);
567} 721}
@@ -593,7 +747,9 @@ static ssize_t spufs_ibox_read(struct file *file, char __user *buf,
593 747
594 udata = (void __user *)buf; 748 udata = (void __user *)buf;
595 749
596 spu_acquire(ctx); 750 count = spu_acquire(ctx);
751 if (count)
752 return count;
597 753
598 /* wait only for the first element */ 754 /* wait only for the first element */
599 count = 0; 755 count = 0;
@@ -639,7 +795,11 @@ static unsigned int spufs_ibox_poll(struct file *file, poll_table *wait)
639 795
640 poll_wait(file, &ctx->ibox_wq, wait); 796 poll_wait(file, &ctx->ibox_wq, wait);
641 797
642 spu_acquire(ctx); 798 /*
799 * For now keep this uninterruptible and also ignore the rule
800 * that poll should not sleep. Will be fixed later.
801 */
802 mutex_lock(&ctx->state_mutex);
643 mask = ctx->ops->mbox_stat_poll(ctx, POLLIN | POLLRDNORM); 803 mask = ctx->ops->mbox_stat_poll(ctx, POLLIN | POLLRDNORM);
644 spu_release(ctx); 804 spu_release(ctx);
645 805
@@ -657,12 +817,15 @@ static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf,
657 size_t len, loff_t *pos) 817 size_t len, loff_t *pos)
658{ 818{
659 struct spu_context *ctx = file->private_data; 819 struct spu_context *ctx = file->private_data;
820 ssize_t ret;
660 u32 ibox_stat; 821 u32 ibox_stat;
661 822
662 if (len < 4) 823 if (len < 4)
663 return -EINVAL; 824 return -EINVAL;
664 825
665 spu_acquire(ctx); 826 ret = spu_acquire(ctx);
827 if (ret)
828 return ret;
666 ibox_stat = (ctx->ops->mbox_stat_read(ctx) >> 16) & 0xff; 829 ibox_stat = (ctx->ops->mbox_stat_read(ctx) >> 16) & 0xff;
667 spu_release(ctx); 830 spu_release(ctx);
668 831
@@ -698,6 +861,9 @@ void spufs_wbox_callback(struct spu *spu)
698{ 861{
699 struct spu_context *ctx = spu->ctx; 862 struct spu_context *ctx = spu->ctx;
700 863
864 if (!ctx)
865 return;
866
701 wake_up_all(&ctx->wbox_wq); 867 wake_up_all(&ctx->wbox_wq);
702 kill_fasync(&ctx->wbox_fasync, SIGIO, POLLOUT); 868 kill_fasync(&ctx->wbox_fasync, SIGIO, POLLOUT);
703} 869}
@@ -731,7 +897,9 @@ static ssize_t spufs_wbox_write(struct file *file, const char __user *buf,
731 if (__get_user(wbox_data, udata)) 897 if (__get_user(wbox_data, udata))
732 return -EFAULT; 898 return -EFAULT;
733 899
734 spu_acquire(ctx); 900 count = spu_acquire(ctx);
901 if (count)
902 return count;
735 903
736 /* 904 /*
737 * make sure we can at least write one element, by waiting 905 * make sure we can at least write one element, by waiting
@@ -772,7 +940,11 @@ static unsigned int spufs_wbox_poll(struct file *file, poll_table *wait)
772 940
773 poll_wait(file, &ctx->wbox_wq, wait); 941 poll_wait(file, &ctx->wbox_wq, wait);
774 942
775 spu_acquire(ctx); 943 /*
944 * For now keep this uninterruptible and also ignore the rule
945 * that poll should not sleep. Will be fixed later.
946 */
947 mutex_lock(&ctx->state_mutex);
776 mask = ctx->ops->mbox_stat_poll(ctx, POLLOUT | POLLWRNORM); 948 mask = ctx->ops->mbox_stat_poll(ctx, POLLOUT | POLLWRNORM);
777 spu_release(ctx); 949 spu_release(ctx);
778 950
@@ -790,12 +962,15 @@ static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf,
790 size_t len, loff_t *pos) 962 size_t len, loff_t *pos)
791{ 963{
792 struct spu_context *ctx = file->private_data; 964 struct spu_context *ctx = file->private_data;
965 ssize_t ret;
793 u32 wbox_stat; 966 u32 wbox_stat;
794 967
795 if (len < 4) 968 if (len < 4)
796 return -EINVAL; 969 return -EINVAL;
797 970
798 spu_acquire(ctx); 971 ret = spu_acquire(ctx);
972 if (ret)
973 return ret;
799 wbox_stat = (ctx->ops->mbox_stat_read(ctx) >> 8) & 0xff; 974 wbox_stat = (ctx->ops->mbox_stat_read(ctx) >> 8) & 0xff;
800 spu_release(ctx); 975 spu_release(ctx);
801 976
@@ -866,7 +1041,9 @@ static ssize_t spufs_signal1_read(struct file *file, char __user *buf,
866 int ret; 1041 int ret;
867 struct spu_context *ctx = file->private_data; 1042 struct spu_context *ctx = file->private_data;
868 1043
869 spu_acquire_saved(ctx); 1044 ret = spu_acquire_saved(ctx);
1045 if (ret)
1046 return ret;
870 ret = __spufs_signal1_read(ctx, buf, len, pos); 1047 ret = __spufs_signal1_read(ctx, buf, len, pos);
871 spu_release_saved(ctx); 1048 spu_release_saved(ctx);
872 1049
@@ -877,6 +1054,7 @@ static ssize_t spufs_signal1_write(struct file *file, const char __user *buf,
877 size_t len, loff_t *pos) 1054 size_t len, loff_t *pos)
878{ 1055{
879 struct spu_context *ctx; 1056 struct spu_context *ctx;
1057 ssize_t ret;
880 u32 data; 1058 u32 data;
881 1059
882 ctx = file->private_data; 1060 ctx = file->private_data;
@@ -887,7 +1065,9 @@ static ssize_t spufs_signal1_write(struct file *file, const char __user *buf,
887 if (copy_from_user(&data, buf, 4)) 1065 if (copy_from_user(&data, buf, 4))
888 return -EFAULT; 1066 return -EFAULT;
889 1067
890 spu_acquire(ctx); 1068 ret = spu_acquire(ctx);
1069 if (ret)
1070 return ret;
891 ctx->ops->signal1_write(ctx, data); 1071 ctx->ops->signal1_write(ctx, data);
892 spu_release(ctx); 1072 spu_release(ctx);
893 1073
@@ -997,7 +1177,9 @@ static ssize_t spufs_signal2_read(struct file *file, char __user *buf,
997 struct spu_context *ctx = file->private_data; 1177 struct spu_context *ctx = file->private_data;
998 int ret; 1178 int ret;
999 1179
1000 spu_acquire_saved(ctx); 1180 ret = spu_acquire_saved(ctx);
1181 if (ret)
1182 return ret;
1001 ret = __spufs_signal2_read(ctx, buf, len, pos); 1183 ret = __spufs_signal2_read(ctx, buf, len, pos);
1002 spu_release_saved(ctx); 1184 spu_release_saved(ctx);
1003 1185
@@ -1008,6 +1190,7 @@ static ssize_t spufs_signal2_write(struct file *file, const char __user *buf,
1008 size_t len, loff_t *pos) 1190 size_t len, loff_t *pos)
1009{ 1191{
1010 struct spu_context *ctx; 1192 struct spu_context *ctx;
1193 ssize_t ret;
1011 u32 data; 1194 u32 data;
1012 1195
1013 ctx = file->private_data; 1196 ctx = file->private_data;
@@ -1018,7 +1201,9 @@ static ssize_t spufs_signal2_write(struct file *file, const char __user *buf,
1018 if (copy_from_user(&data, buf, 4)) 1201 if (copy_from_user(&data, buf, 4))
1019 return -EFAULT; 1202 return -EFAULT;
1020 1203
1021 spu_acquire(ctx); 1204 ret = spu_acquire(ctx);
1205 if (ret)
1206 return ret;
1022 ctx->ops->signal2_write(ctx, data); 1207 ctx->ops->signal2_write(ctx, data);
1023 spu_release(ctx); 1208 spu_release(ctx);
1024 1209
@@ -1086,33 +1271,42 @@ static const struct file_operations spufs_signal2_nosched_fops = {
1086#define SPU_ATTR_ACQUIRE_SAVED 2 1271#define SPU_ATTR_ACQUIRE_SAVED 2
1087 1272
1088#define DEFINE_SPUFS_ATTRIBUTE(__name, __get, __set, __fmt, __acquire) \ 1273#define DEFINE_SPUFS_ATTRIBUTE(__name, __get, __set, __fmt, __acquire) \
1089static u64 __##__get(void *data) \ 1274static int __##__get(void *data, u64 *val) \
1090{ \ 1275{ \
1091 struct spu_context *ctx = data; \ 1276 struct spu_context *ctx = data; \
1092 u64 ret; \ 1277 int ret = 0; \
1093 \ 1278 \
1094 if (__acquire == SPU_ATTR_ACQUIRE) { \ 1279 if (__acquire == SPU_ATTR_ACQUIRE) { \
1095 spu_acquire(ctx); \ 1280 ret = spu_acquire(ctx); \
1096 ret = __get(ctx); \ 1281 if (ret) \
1282 return ret; \
1283 *val = __get(ctx); \
1097 spu_release(ctx); \ 1284 spu_release(ctx); \
1098 } else if (__acquire == SPU_ATTR_ACQUIRE_SAVED) { \ 1285 } else if (__acquire == SPU_ATTR_ACQUIRE_SAVED) { \
1099 spu_acquire_saved(ctx); \ 1286 ret = spu_acquire_saved(ctx); \
1100 ret = __get(ctx); \ 1287 if (ret) \
1288 return ret; \
1289 *val = __get(ctx); \
1101 spu_release_saved(ctx); \ 1290 spu_release_saved(ctx); \
1102 } else \ 1291 } else \
1103 ret = __get(ctx); \ 1292 *val = __get(ctx); \
1104 \ 1293 \
1105 return ret; \ 1294 return 0; \
1106} \ 1295} \
1107DEFINE_SIMPLE_ATTRIBUTE(__name, __##__get, __set, __fmt); 1296DEFINE_SPUFS_SIMPLE_ATTRIBUTE(__name, __##__get, __set, __fmt);
1108 1297
1109static void spufs_signal1_type_set(void *data, u64 val) 1298static int spufs_signal1_type_set(void *data, u64 val)
1110{ 1299{
1111 struct spu_context *ctx = data; 1300 struct spu_context *ctx = data;
1301 int ret;
1112 1302
1113 spu_acquire(ctx); 1303 ret = spu_acquire(ctx);
1304 if (ret)
1305 return ret;
1114 ctx->ops->signal1_type_set(ctx, val); 1306 ctx->ops->signal1_type_set(ctx, val);
1115 spu_release(ctx); 1307 spu_release(ctx);
1308
1309 return 0;
1116} 1310}
1117 1311
1118static u64 spufs_signal1_type_get(struct spu_context *ctx) 1312static u64 spufs_signal1_type_get(struct spu_context *ctx)
@@ -1123,13 +1317,18 @@ DEFINE_SPUFS_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get,
1123 spufs_signal1_type_set, "%llu", SPU_ATTR_ACQUIRE); 1317 spufs_signal1_type_set, "%llu", SPU_ATTR_ACQUIRE);
1124 1318
1125 1319
1126static void spufs_signal2_type_set(void *data, u64 val) 1320static int spufs_signal2_type_set(void *data, u64 val)
1127{ 1321{
1128 struct spu_context *ctx = data; 1322 struct spu_context *ctx = data;
1323 int ret;
1129 1324
1130 spu_acquire(ctx); 1325 ret = spu_acquire(ctx);
1326 if (ret)
1327 return ret;
1131 ctx->ops->signal2_type_set(ctx, val); 1328 ctx->ops->signal2_type_set(ctx, val);
1132 spu_release(ctx); 1329 spu_release(ctx);
1330
1331 return 0;
1133} 1332}
1134 1333
1135static u64 spufs_signal2_type_get(struct spu_context *ctx) 1334static u64 spufs_signal2_type_get(struct spu_context *ctx)
@@ -1329,6 +1528,9 @@ void spufs_mfc_callback(struct spu *spu)
1329{ 1528{
1330 struct spu_context *ctx = spu->ctx; 1529 struct spu_context *ctx = spu->ctx;
1331 1530
1531 if (!ctx)
1532 return;
1533
1332 wake_up_all(&ctx->mfc_wq); 1534 wake_up_all(&ctx->mfc_wq);
1333 1535
1334 pr_debug("%s %s\n", __FUNCTION__, spu->name); 1536 pr_debug("%s %s\n", __FUNCTION__, spu->name);
@@ -1375,12 +1577,17 @@ static ssize_t spufs_mfc_read(struct file *file, char __user *buffer,
1375 if (size != 4) 1577 if (size != 4)
1376 goto out; 1578 goto out;
1377 1579
1378 spu_acquire(ctx); 1580 ret = spu_acquire(ctx);
1581 if (ret)
1582 return ret;
1583
1584 ret = -EINVAL;
1379 if (file->f_flags & O_NONBLOCK) { 1585 if (file->f_flags & O_NONBLOCK) {
1380 status = ctx->ops->read_mfc_tagstatus(ctx); 1586 status = ctx->ops->read_mfc_tagstatus(ctx);
1381 if (!(status & ctx->tagwait)) 1587 if (!(status & ctx->tagwait))
1382 ret = -EAGAIN; 1588 ret = -EAGAIN;
1383 else 1589 else
1590 /* XXX(hch): shouldn't we clear ret here? */
1384 ctx->tagwait &= ~status; 1591 ctx->tagwait &= ~status;
1385 } else { 1592 } else {
1386 ret = spufs_wait(ctx->mfc_wq, 1593 ret = spufs_wait(ctx->mfc_wq,
@@ -1505,7 +1712,11 @@ static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer,
1505 if (ret) 1712 if (ret)
1506 goto out; 1713 goto out;
1507 1714
1508 ret = spu_acquire_runnable(ctx, 0); 1715 ret = spu_acquire(ctx);
1716 if (ret)
1717 goto out;
1718
1719 ret = spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE);
1509 if (ret) 1720 if (ret)
1510 goto out; 1721 goto out;
1511 1722
@@ -1539,7 +1750,11 @@ static unsigned int spufs_mfc_poll(struct file *file,poll_table *wait)
1539 1750
1540 poll_wait(file, &ctx->mfc_wq, wait); 1751 poll_wait(file, &ctx->mfc_wq, wait);
1541 1752
1542 spu_acquire(ctx); 1753 /*
1754 * For now keep this uninterruptible and also ignore the rule
1755 * that poll should not sleep. Will be fixed later.
1756 */
1757 mutex_lock(&ctx->state_mutex);
1543 ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2); 1758 ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2);
1544 free_elements = ctx->ops->get_mfc_free_elements(ctx); 1759 free_elements = ctx->ops->get_mfc_free_elements(ctx);
1545 tagstatus = ctx->ops->read_mfc_tagstatus(ctx); 1760 tagstatus = ctx->ops->read_mfc_tagstatus(ctx);
@@ -1562,7 +1777,9 @@ static int spufs_mfc_flush(struct file *file, fl_owner_t id)
1562 struct spu_context *ctx = file->private_data; 1777 struct spu_context *ctx = file->private_data;
1563 int ret; 1778 int ret;
1564 1779
1565 spu_acquire(ctx); 1780 ret = spu_acquire(ctx);
1781 if (ret)
1782 return ret;
1566#if 0 1783#if 0
1567/* this currently hangs */ 1784/* this currently hangs */
1568 ret = spufs_wait(ctx->mfc_wq, 1785 ret = spufs_wait(ctx->mfc_wq,
@@ -1605,12 +1822,18 @@ static const struct file_operations spufs_mfc_fops = {
1605 .mmap = spufs_mfc_mmap, 1822 .mmap = spufs_mfc_mmap,
1606}; 1823};
1607 1824
1608static void spufs_npc_set(void *data, u64 val) 1825static int spufs_npc_set(void *data, u64 val)
1609{ 1826{
1610 struct spu_context *ctx = data; 1827 struct spu_context *ctx = data;
1611 spu_acquire(ctx); 1828 int ret;
1829
1830 ret = spu_acquire(ctx);
1831 if (ret)
1832 return ret;
1612 ctx->ops->npc_write(ctx, val); 1833 ctx->ops->npc_write(ctx, val);
1613 spu_release(ctx); 1834 spu_release(ctx);
1835
1836 return 0;
1614} 1837}
1615 1838
1616static u64 spufs_npc_get(struct spu_context *ctx) 1839static u64 spufs_npc_get(struct spu_context *ctx)
@@ -1620,13 +1843,19 @@ static u64 spufs_npc_get(struct spu_context *ctx)
1620DEFINE_SPUFS_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set, 1843DEFINE_SPUFS_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set,
1621 "0x%llx\n", SPU_ATTR_ACQUIRE); 1844 "0x%llx\n", SPU_ATTR_ACQUIRE);
1622 1845
1623static void spufs_decr_set(void *data, u64 val) 1846static int spufs_decr_set(void *data, u64 val)
1624{ 1847{
1625 struct spu_context *ctx = data; 1848 struct spu_context *ctx = data;
1626 struct spu_lscsa *lscsa = ctx->csa.lscsa; 1849 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1627 spu_acquire_saved(ctx); 1850 int ret;
1851
1852 ret = spu_acquire_saved(ctx);
1853 if (ret)
1854 return ret;
1628 lscsa->decr.slot[0] = (u32) val; 1855 lscsa->decr.slot[0] = (u32) val;
1629 spu_release_saved(ctx); 1856 spu_release_saved(ctx);
1857
1858 return 0;
1630} 1859}
1631 1860
1632static u64 spufs_decr_get(struct spu_context *ctx) 1861static u64 spufs_decr_get(struct spu_context *ctx)
@@ -1637,15 +1866,21 @@ static u64 spufs_decr_get(struct spu_context *ctx)
1637DEFINE_SPUFS_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set, 1866DEFINE_SPUFS_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set,
1638 "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED); 1867 "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED);
1639 1868
1640static void spufs_decr_status_set(void *data, u64 val) 1869static int spufs_decr_status_set(void *data, u64 val)
1641{ 1870{
1642 struct spu_context *ctx = data; 1871 struct spu_context *ctx = data;
1643 spu_acquire_saved(ctx); 1872 int ret;
1873
1874 ret = spu_acquire_saved(ctx);
1875 if (ret)
1876 return ret;
1644 if (val) 1877 if (val)
1645 ctx->csa.priv2.mfc_control_RW |= MFC_CNTL_DECREMENTER_RUNNING; 1878 ctx->csa.priv2.mfc_control_RW |= MFC_CNTL_DECREMENTER_RUNNING;
1646 else 1879 else
1647 ctx->csa.priv2.mfc_control_RW &= ~MFC_CNTL_DECREMENTER_RUNNING; 1880 ctx->csa.priv2.mfc_control_RW &= ~MFC_CNTL_DECREMENTER_RUNNING;
1648 spu_release_saved(ctx); 1881 spu_release_saved(ctx);
1882
1883 return 0;
1649} 1884}
1650 1885
1651static u64 spufs_decr_status_get(struct spu_context *ctx) 1886static u64 spufs_decr_status_get(struct spu_context *ctx)
@@ -1659,13 +1894,19 @@ DEFINE_SPUFS_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get,
1659 spufs_decr_status_set, "0x%llx\n", 1894 spufs_decr_status_set, "0x%llx\n",
1660 SPU_ATTR_ACQUIRE_SAVED); 1895 SPU_ATTR_ACQUIRE_SAVED);
1661 1896
1662static void spufs_event_mask_set(void *data, u64 val) 1897static int spufs_event_mask_set(void *data, u64 val)
1663{ 1898{
1664 struct spu_context *ctx = data; 1899 struct spu_context *ctx = data;
1665 struct spu_lscsa *lscsa = ctx->csa.lscsa; 1900 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1666 spu_acquire_saved(ctx); 1901 int ret;
1902
1903 ret = spu_acquire_saved(ctx);
1904 if (ret)
1905 return ret;
1667 lscsa->event_mask.slot[0] = (u32) val; 1906 lscsa->event_mask.slot[0] = (u32) val;
1668 spu_release_saved(ctx); 1907 spu_release_saved(ctx);
1908
1909 return 0;
1669} 1910}
1670 1911
1671static u64 spufs_event_mask_get(struct spu_context *ctx) 1912static u64 spufs_event_mask_get(struct spu_context *ctx)
@@ -1690,13 +1931,19 @@ static u64 spufs_event_status_get(struct spu_context *ctx)
1690DEFINE_SPUFS_ATTRIBUTE(spufs_event_status_ops, spufs_event_status_get, 1931DEFINE_SPUFS_ATTRIBUTE(spufs_event_status_ops, spufs_event_status_get,
1691 NULL, "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED) 1932 NULL, "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED)
1692 1933
1693static void spufs_srr0_set(void *data, u64 val) 1934static int spufs_srr0_set(void *data, u64 val)
1694{ 1935{
1695 struct spu_context *ctx = data; 1936 struct spu_context *ctx = data;
1696 struct spu_lscsa *lscsa = ctx->csa.lscsa; 1937 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1697 spu_acquire_saved(ctx); 1938 int ret;
1939
1940 ret = spu_acquire_saved(ctx);
1941 if (ret)
1942 return ret;
1698 lscsa->srr0.slot[0] = (u32) val; 1943 lscsa->srr0.slot[0] = (u32) val;
1699 spu_release_saved(ctx); 1944 spu_release_saved(ctx);
1945
1946 return 0;
1700} 1947}
1701 1948
1702static u64 spufs_srr0_get(struct spu_context *ctx) 1949static u64 spufs_srr0_get(struct spu_context *ctx)
@@ -1727,10 +1974,12 @@ static u64 spufs_object_id_get(struct spu_context *ctx)
1727 return ctx->object_id; 1974 return ctx->object_id;
1728} 1975}
1729 1976
1730static void spufs_object_id_set(void *data, u64 id) 1977static int spufs_object_id_set(void *data, u64 id)
1731{ 1978{
1732 struct spu_context *ctx = data; 1979 struct spu_context *ctx = data;
1733 ctx->object_id = id; 1980 ctx->object_id = id;
1981
1982 return 0;
1734} 1983}
1735 1984
1736DEFINE_SPUFS_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get, 1985DEFINE_SPUFS_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get,
@@ -1777,13 +2026,13 @@ static const struct file_operations spufs_caps_fops = {
1777static ssize_t __spufs_mbox_info_read(struct spu_context *ctx, 2026static ssize_t __spufs_mbox_info_read(struct spu_context *ctx,
1778 char __user *buf, size_t len, loff_t *pos) 2027 char __user *buf, size_t len, loff_t *pos)
1779{ 2028{
1780 u32 mbox_stat;
1781 u32 data; 2029 u32 data;
1782 2030
1783 mbox_stat = ctx->csa.prob.mb_stat_R; 2031 /* EOF if there's no entry in the mbox */
1784 if (mbox_stat & 0x0000ff) { 2032 if (!(ctx->csa.prob.mb_stat_R & 0x0000ff))
1785 data = ctx->csa.prob.pu_mb_R; 2033 return 0;
1786 } 2034
2035 data = ctx->csa.prob.pu_mb_R;
1787 2036
1788 return simple_read_from_buffer(buf, len, pos, &data, sizeof data); 2037 return simple_read_from_buffer(buf, len, pos, &data, sizeof data);
1789} 2038}
@@ -1797,7 +2046,9 @@ static ssize_t spufs_mbox_info_read(struct file *file, char __user *buf,
1797 if (!access_ok(VERIFY_WRITE, buf, len)) 2046 if (!access_ok(VERIFY_WRITE, buf, len))
1798 return -EFAULT; 2047 return -EFAULT;
1799 2048
1800 spu_acquire_saved(ctx); 2049 ret = spu_acquire_saved(ctx);
2050 if (ret)
2051 return ret;
1801 spin_lock(&ctx->csa.register_lock); 2052 spin_lock(&ctx->csa.register_lock);
1802 ret = __spufs_mbox_info_read(ctx, buf, len, pos); 2053 ret = __spufs_mbox_info_read(ctx, buf, len, pos);
1803 spin_unlock(&ctx->csa.register_lock); 2054 spin_unlock(&ctx->csa.register_lock);
@@ -1815,13 +2066,13 @@ static const struct file_operations spufs_mbox_info_fops = {
1815static ssize_t __spufs_ibox_info_read(struct spu_context *ctx, 2066static ssize_t __spufs_ibox_info_read(struct spu_context *ctx,
1816 char __user *buf, size_t len, loff_t *pos) 2067 char __user *buf, size_t len, loff_t *pos)
1817{ 2068{
1818 u32 ibox_stat;
1819 u32 data; 2069 u32 data;
1820 2070
1821 ibox_stat = ctx->csa.prob.mb_stat_R; 2071 /* EOF if there's no entry in the ibox */
1822 if (ibox_stat & 0xff0000) { 2072 if (!(ctx->csa.prob.mb_stat_R & 0xff0000))
1823 data = ctx->csa.priv2.puint_mb_R; 2073 return 0;
1824 } 2074
2075 data = ctx->csa.priv2.puint_mb_R;
1825 2076
1826 return simple_read_from_buffer(buf, len, pos, &data, sizeof data); 2077 return simple_read_from_buffer(buf, len, pos, &data, sizeof data);
1827} 2078}
@@ -1835,7 +2086,9 @@ static ssize_t spufs_ibox_info_read(struct file *file, char __user *buf,
1835 if (!access_ok(VERIFY_WRITE, buf, len)) 2086 if (!access_ok(VERIFY_WRITE, buf, len))
1836 return -EFAULT; 2087 return -EFAULT;
1837 2088
1838 spu_acquire_saved(ctx); 2089 ret = spu_acquire_saved(ctx);
2090 if (ret)
2091 return ret;
1839 spin_lock(&ctx->csa.register_lock); 2092 spin_lock(&ctx->csa.register_lock);
1840 ret = __spufs_ibox_info_read(ctx, buf, len, pos); 2093 ret = __spufs_ibox_info_read(ctx, buf, len, pos);
1841 spin_unlock(&ctx->csa.register_lock); 2094 spin_unlock(&ctx->csa.register_lock);
@@ -1876,7 +2129,9 @@ static ssize_t spufs_wbox_info_read(struct file *file, char __user *buf,
1876 if (!access_ok(VERIFY_WRITE, buf, len)) 2129 if (!access_ok(VERIFY_WRITE, buf, len))
1877 return -EFAULT; 2130 return -EFAULT;
1878 2131
1879 spu_acquire_saved(ctx); 2132 ret = spu_acquire_saved(ctx);
2133 if (ret)
2134 return ret;
1880 spin_lock(&ctx->csa.register_lock); 2135 spin_lock(&ctx->csa.register_lock);
1881 ret = __spufs_wbox_info_read(ctx, buf, len, pos); 2136 ret = __spufs_wbox_info_read(ctx, buf, len, pos);
1882 spin_unlock(&ctx->csa.register_lock); 2137 spin_unlock(&ctx->csa.register_lock);
@@ -1926,7 +2181,9 @@ static ssize_t spufs_dma_info_read(struct file *file, char __user *buf,
1926 if (!access_ok(VERIFY_WRITE, buf, len)) 2181 if (!access_ok(VERIFY_WRITE, buf, len))
1927 return -EFAULT; 2182 return -EFAULT;
1928 2183
1929 spu_acquire_saved(ctx); 2184 ret = spu_acquire_saved(ctx);
2185 if (ret)
2186 return ret;
1930 spin_lock(&ctx->csa.register_lock); 2187 spin_lock(&ctx->csa.register_lock);
1931 ret = __spufs_dma_info_read(ctx, buf, len, pos); 2188 ret = __spufs_dma_info_read(ctx, buf, len, pos);
1932 spin_unlock(&ctx->csa.register_lock); 2189 spin_unlock(&ctx->csa.register_lock);
@@ -1977,7 +2234,9 @@ static ssize_t spufs_proxydma_info_read(struct file *file, char __user *buf,
1977 struct spu_context *ctx = file->private_data; 2234 struct spu_context *ctx = file->private_data;
1978 int ret; 2235 int ret;
1979 2236
1980 spu_acquire_saved(ctx); 2237 ret = spu_acquire_saved(ctx);
2238 if (ret)
2239 return ret;
1981 spin_lock(&ctx->csa.register_lock); 2240 spin_lock(&ctx->csa.register_lock);
1982 ret = __spufs_proxydma_info_read(ctx, buf, len, pos); 2241 ret = __spufs_proxydma_info_read(ctx, buf, len, pos);
1983 spin_unlock(&ctx->csa.register_lock); 2242 spin_unlock(&ctx->csa.register_lock);
@@ -2066,8 +2325,12 @@ static unsigned long long spufs_class2_intrs(struct spu_context *ctx)
2066static int spufs_show_stat(struct seq_file *s, void *private) 2325static int spufs_show_stat(struct seq_file *s, void *private)
2067{ 2326{
2068 struct spu_context *ctx = s->private; 2327 struct spu_context *ctx = s->private;
2328 int ret;
2329
2330 ret = spu_acquire(ctx);
2331 if (ret)
2332 return ret;
2069 2333
2070 spu_acquire(ctx);
2071 seq_printf(s, "%s %llu %llu %llu %llu " 2334 seq_printf(s, "%s %llu %llu %llu %llu "
2072 "%llu %llu %llu %llu %llu %llu %llu %llu\n", 2335 "%llu %llu %llu %llu %llu %llu %llu %llu\n",
2073 ctx_state_names[ctx->stats.util_state], 2336 ctx_state_names[ctx->stats.util_state],
diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c
index fc4ed1ffbd4f..64f8540b832c 100644
--- a/arch/powerpc/platforms/cell/spufs/hw_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c
@@ -76,16 +76,18 @@ static unsigned int spu_hw_mbox_stat_poll(struct spu_context *ctx,
76 if (stat & 0xff0000) 76 if (stat & 0xff0000)
77 ret |= POLLIN | POLLRDNORM; 77 ret |= POLLIN | POLLRDNORM;
78 else { 78 else {
79 spu_int_stat_clear(spu, 2, 0x1); 79 spu_int_stat_clear(spu, 2, CLASS2_MAILBOX_INTR);
80 spu_int_mask_or(spu, 2, 0x1); 80 spu_int_mask_or(spu, 2, CLASS2_ENABLE_MAILBOX_INTR);
81 } 81 }
82 } 82 }
83 if (events & (POLLOUT | POLLWRNORM)) { 83 if (events & (POLLOUT | POLLWRNORM)) {
84 if (stat & 0x00ff00) 84 if (stat & 0x00ff00)
85 ret = POLLOUT | POLLWRNORM; 85 ret = POLLOUT | POLLWRNORM;
86 else { 86 else {
87 spu_int_stat_clear(spu, 2, 0x10); 87 spu_int_stat_clear(spu, 2,
88 spu_int_mask_or(spu, 2, 0x10); 88 CLASS2_MAILBOX_THRESHOLD_INTR);
89 spu_int_mask_or(spu, 2,
90 CLASS2_ENABLE_MAILBOX_THRESHOLD_INTR);
89 } 91 }
90 } 92 }
91 spin_unlock_irq(&spu->register_lock); 93 spin_unlock_irq(&spu->register_lock);
@@ -106,7 +108,7 @@ static int spu_hw_ibox_read(struct spu_context *ctx, u32 * data)
106 ret = 4; 108 ret = 4;
107 } else { 109 } else {
108 /* make sure we get woken up by the interrupt */ 110 /* make sure we get woken up by the interrupt */
109 spu_int_mask_or(spu, 2, 0x1); 111 spu_int_mask_or(spu, 2, CLASS2_ENABLE_MAILBOX_INTR);
110 ret = 0; 112 ret = 0;
111 } 113 }
112 spin_unlock_irq(&spu->register_lock); 114 spin_unlock_irq(&spu->register_lock);
@@ -127,7 +129,7 @@ static int spu_hw_wbox_write(struct spu_context *ctx, u32 data)
127 } else { 129 } else {
128 /* make sure we get woken up by the interrupt when space 130 /* make sure we get woken up by the interrupt when space
129 becomes available */ 131 becomes available */
130 spu_int_mask_or(spu, 2, 0x10); 132 spu_int_mask_or(spu, 2, CLASS2_ENABLE_MAILBOX_THRESHOLD_INTR);
131 ret = 0; 133 ret = 0;
132 } 134 }
133 spin_unlock_irq(&spu->register_lock); 135 spin_unlock_irq(&spu->register_lock);
@@ -206,6 +208,11 @@ static char *spu_hw_get_ls(struct spu_context *ctx)
206 return ctx->spu->local_store; 208 return ctx->spu->local_store;
207} 209}
208 210
211static void spu_hw_privcntl_write(struct spu_context *ctx, u64 val)
212{
213 out_be64(&ctx->spu->priv2->spu_privcntl_RW, val);
214}
215
209static u32 spu_hw_runcntl_read(struct spu_context *ctx) 216static u32 spu_hw_runcntl_read(struct spu_context *ctx)
210{ 217{
211 return in_be32(&ctx->spu->problem->spu_runcntl_RW); 218 return in_be32(&ctx->spu->problem->spu_runcntl_RW);
@@ -215,11 +222,21 @@ static void spu_hw_runcntl_write(struct spu_context *ctx, u32 val)
215{ 222{
216 spin_lock_irq(&ctx->spu->register_lock); 223 spin_lock_irq(&ctx->spu->register_lock);
217 if (val & SPU_RUNCNTL_ISOLATE) 224 if (val & SPU_RUNCNTL_ISOLATE)
218 out_be64(&ctx->spu->priv2->spu_privcntl_RW, 4LL); 225 spu_hw_privcntl_write(ctx,
226 SPU_PRIVCNT_LOAD_REQUEST_ENABLE_MASK);
219 out_be32(&ctx->spu->problem->spu_runcntl_RW, val); 227 out_be32(&ctx->spu->problem->spu_runcntl_RW, val);
220 spin_unlock_irq(&ctx->spu->register_lock); 228 spin_unlock_irq(&ctx->spu->register_lock);
221} 229}
222 230
231static void spu_hw_runcntl_stop(struct spu_context *ctx)
232{
233 spin_lock_irq(&ctx->spu->register_lock);
234 out_be32(&ctx->spu->problem->spu_runcntl_RW, SPU_RUNCNTL_STOP);
235 while (in_be32(&ctx->spu->problem->spu_status_R) & SPU_STATUS_RUNNING)
236 cpu_relax();
237 spin_unlock_irq(&ctx->spu->register_lock);
238}
239
223static void spu_hw_master_start(struct spu_context *ctx) 240static void spu_hw_master_start(struct spu_context *ctx)
224{ 241{
225 struct spu *spu = ctx->spu; 242 struct spu *spu = ctx->spu;
@@ -319,8 +336,10 @@ struct spu_context_ops spu_hw_ops = {
319 .npc_write = spu_hw_npc_write, 336 .npc_write = spu_hw_npc_write,
320 .status_read = spu_hw_status_read, 337 .status_read = spu_hw_status_read,
321 .get_ls = spu_hw_get_ls, 338 .get_ls = spu_hw_get_ls,
339 .privcntl_write = spu_hw_privcntl_write,
322 .runcntl_read = spu_hw_runcntl_read, 340 .runcntl_read = spu_hw_runcntl_read,
323 .runcntl_write = spu_hw_runcntl_write, 341 .runcntl_write = spu_hw_runcntl_write,
342 .runcntl_stop = spu_hw_runcntl_stop,
324 .master_start = spu_hw_master_start, 343 .master_start = spu_hw_master_start,
325 .master_stop = spu_hw_master_stop, 344 .master_stop = spu_hw_master_stop,
326 .set_mfc_query = spu_hw_set_mfc_query, 345 .set_mfc_query = spu_hw_set_mfc_query,
diff --git a/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c b/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c
index f4b3c052dabf..0e9f325c9ff7 100644
--- a/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c
+++ b/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c
@@ -28,6 +28,8 @@
28#include <asm/spu_csa.h> 28#include <asm/spu_csa.h>
29#include <asm/mmu.h> 29#include <asm/mmu.h>
30 30
31#include "spufs.h"
32
31static int spu_alloc_lscsa_std(struct spu_state *csa) 33static int spu_alloc_lscsa_std(struct spu_state *csa)
32{ 34{
33 struct spu_lscsa *lscsa; 35 struct spu_lscsa *lscsa;
@@ -73,7 +75,7 @@ int spu_alloc_lscsa(struct spu_state *csa)
73 int i, j, n_4k; 75 int i, j, n_4k;
74 76
75 /* Check availability of 64K pages */ 77 /* Check availability of 64K pages */
76 if (mmu_psize_defs[MMU_PAGE_64K].shift == 0) 78 if (!spu_64k_pages_available())
77 goto fail; 79 goto fail;
78 80
79 csa->use_big_pages = 1; 81 csa->use_big_pages = 1;
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index 1ce5e22ea5f4..c01a09da1e56 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -15,24 +15,55 @@ void spufs_stop_callback(struct spu *spu)
15{ 15{
16 struct spu_context *ctx = spu->ctx; 16 struct spu_context *ctx = spu->ctx;
17 17
18 wake_up_all(&ctx->stop_wq); 18 /*
19 * It should be impossible to preempt a context while an exception
20 * is being processed, since the context switch code is specially
21 * coded to deal with interrupts ... But, just in case, sanity check
22 * the context pointer. It is OK to return doing nothing since
23 * the exception will be regenerated when the context is resumed.
24 */
25 if (ctx) {
26 /* Copy exception arguments into module specific structure */
27 ctx->csa.class_0_pending = spu->class_0_pending;
28 ctx->csa.dsisr = spu->dsisr;
29 ctx->csa.dar = spu->dar;
30
31 /* ensure that the exception status has hit memory before a
32 * thread waiting on the context's stop queue is woken */
33 smp_wmb();
34
35 wake_up_all(&ctx->stop_wq);
36 }
37
38 /* Clear callback arguments from spu structure */
39 spu->class_0_pending = 0;
40 spu->dsisr = 0;
41 spu->dar = 0;
19} 42}
20 43
21static inline int spu_stopped(struct spu_context *ctx, u32 *stat) 44int spu_stopped(struct spu_context *ctx, u32 *stat)
22{ 45{
23 struct spu *spu; 46 u64 dsisr;
24 u64 pte_fault; 47 u32 stopped;
25 48
26 *stat = ctx->ops->status_read(ctx); 49 *stat = ctx->ops->status_read(ctx);
27 50
28 spu = ctx->spu; 51 if (test_bit(SPU_SCHED_NOTIFY_ACTIVE, &ctx->sched_flags))
29 if (ctx->state != SPU_STATE_RUNNABLE ||
30 test_bit(SPU_SCHED_NOTIFY_ACTIVE, &ctx->sched_flags))
31 return 1; 52 return 1;
32 pte_fault = spu->dsisr & 53
33 (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED); 54 stopped = SPU_STATUS_INVALID_INSTR | SPU_STATUS_SINGLE_STEP |
34 return (!(*stat & SPU_STATUS_RUNNING) || pte_fault || spu->class_0_pending) ? 55 SPU_STATUS_STOPPED_BY_HALT | SPU_STATUS_STOPPED_BY_STOP;
35 1 : 0; 56 if (*stat & stopped)
57 return 1;
58
59 dsisr = ctx->csa.dsisr;
60 if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED))
61 return 1;
62
63 if (ctx->csa.class_0_pending)
64 return 1;
65
66 return 0;
36} 67}
37 68
38static int spu_setup_isolated(struct spu_context *ctx) 69static int spu_setup_isolated(struct spu_context *ctx)
@@ -128,34 +159,66 @@ out:
128 159
129static int spu_run_init(struct spu_context *ctx, u32 *npc) 160static int spu_run_init(struct spu_context *ctx, u32 *npc)
130{ 161{
162 unsigned long runcntl = SPU_RUNCNTL_RUNNABLE;
163 int ret;
164
131 spuctx_switch_state(ctx, SPU_UTIL_SYSTEM); 165 spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);
132 166
133 if (ctx->flags & SPU_CREATE_ISOLATE) { 167 /*
134 unsigned long runcntl; 168 * NOSCHED is synchronous scheduling with respect to the caller.
169 * The caller waits for the context to be loaded.
170 */
171 if (ctx->flags & SPU_CREATE_NOSCHED) {
172 if (ctx->state == SPU_STATE_SAVED) {
173 ret = spu_activate(ctx, 0);
174 if (ret)
175 return ret;
176 }
177 }
135 178
179 /*
180 * Apply special setup as required.
181 */
182 if (ctx->flags & SPU_CREATE_ISOLATE) {
136 if (!(ctx->ops->status_read(ctx) & SPU_STATUS_ISOLATED_STATE)) { 183 if (!(ctx->ops->status_read(ctx) & SPU_STATUS_ISOLATED_STATE)) {
137 int ret = spu_setup_isolated(ctx); 184 ret = spu_setup_isolated(ctx);
138 if (ret) 185 if (ret)
139 return ret; 186 return ret;
140 } 187 }
141 188
142 /* if userspace has set the runcntrl register (eg, to issue an 189 /*
143 * isolated exit), we need to re-set it here */ 190 * If userspace has set the runcntrl register (eg, to
191 * issue an isolated exit), we need to re-set it here
192 */
144 runcntl = ctx->ops->runcntl_read(ctx) & 193 runcntl = ctx->ops->runcntl_read(ctx) &
145 (SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE); 194 (SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE);
146 if (runcntl == 0) 195 if (runcntl == 0)
147 runcntl = SPU_RUNCNTL_RUNNABLE; 196 runcntl = SPU_RUNCNTL_RUNNABLE;
197 }
198
199 if (ctx->flags & SPU_CREATE_NOSCHED) {
200 spuctx_switch_state(ctx, SPU_UTIL_USER);
148 ctx->ops->runcntl_write(ctx, runcntl); 201 ctx->ops->runcntl_write(ctx, runcntl);
149 } else { 202 } else {
150 unsigned long mode = SPU_PRIVCNTL_MODE_NORMAL; 203 unsigned long privcntl;
151 ctx->ops->npc_write(ctx, *npc); 204
152 if (test_thread_flag(TIF_SINGLESTEP)) 205 if (test_thread_flag(TIF_SINGLESTEP))
153 mode = SPU_PRIVCNTL_MODE_SINGLE_STEP; 206 privcntl = SPU_PRIVCNTL_MODE_SINGLE_STEP;
154 out_be64(&ctx->spu->priv2->spu_privcntl_RW, mode); 207 else
155 ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); 208 privcntl = SPU_PRIVCNTL_MODE_NORMAL;
156 }
157 209
158 spuctx_switch_state(ctx, SPU_UTIL_USER); 210 ctx->ops->npc_write(ctx, *npc);
211 ctx->ops->privcntl_write(ctx, privcntl);
212 ctx->ops->runcntl_write(ctx, runcntl);
213
214 if (ctx->state == SPU_STATE_SAVED) {
215 ret = spu_activate(ctx, 0);
216 if (ret)
217 return ret;
218 } else {
219 spuctx_switch_state(ctx, SPU_UTIL_USER);
220 }
221 }
159 222
160 return 0; 223 return 0;
161} 224}
@@ -165,6 +228,8 @@ static int spu_run_fini(struct spu_context *ctx, u32 *npc,
165{ 228{
166 int ret = 0; 229 int ret = 0;
167 230
231 spu_del_from_rq(ctx);
232
168 *status = ctx->ops->status_read(ctx); 233 *status = ctx->ops->status_read(ctx);
169 *npc = ctx->ops->npc_read(ctx); 234 *npc = ctx->ops->npc_read(ctx);
170 235
@@ -177,26 +242,6 @@ static int spu_run_fini(struct spu_context *ctx, u32 *npc,
177 return ret; 242 return ret;
178} 243}
179 244
180static int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc,
181 u32 *status)
182{
183 int ret;
184
185 ret = spu_run_fini(ctx, npc, status);
186 if (ret)
187 return ret;
188
189 if (*status & (SPU_STATUS_STOPPED_BY_STOP | SPU_STATUS_STOPPED_BY_HALT))
190 return *status;
191
192 ret = spu_acquire_runnable(ctx, 0);
193 if (ret)
194 return ret;
195
196 spuctx_switch_state(ctx, SPU_UTIL_USER);
197 return 0;
198}
199
200/* 245/*
201 * SPU syscall restarting is tricky because we violate the basic 246 * SPU syscall restarting is tricky because we violate the basic
202 * assumption that the signal handler is running on the interrupted 247 * assumption that the signal handler is running on the interrupted
@@ -247,7 +292,7 @@ static int spu_process_callback(struct spu_context *ctx)
247 u32 ls_pointer, npc; 292 u32 ls_pointer, npc;
248 void __iomem *ls; 293 void __iomem *ls;
249 long spu_ret; 294 long spu_ret;
250 int ret; 295 int ret, ret2;
251 296
252 /* get syscall block from local store */ 297 /* get syscall block from local store */
253 npc = ctx->ops->npc_read(ctx) & ~3; 298 npc = ctx->ops->npc_read(ctx) & ~3;
@@ -269,9 +314,11 @@ static int spu_process_callback(struct spu_context *ctx)
269 if (spu_ret <= -ERESTARTSYS) { 314 if (spu_ret <= -ERESTARTSYS) {
270 ret = spu_handle_restartsys(ctx, &spu_ret, &npc); 315 ret = spu_handle_restartsys(ctx, &spu_ret, &npc);
271 } 316 }
272 spu_acquire(ctx); 317 ret2 = spu_acquire(ctx);
273 if (ret == -ERESTARTSYS) 318 if (ret == -ERESTARTSYS)
274 return ret; 319 return ret;
320 if (ret2)
321 return -EINTR;
275 } 322 }
276 323
277 /* write result, jump over indirect pointer */ 324 /* write result, jump over indirect pointer */
@@ -281,18 +328,6 @@ static int spu_process_callback(struct spu_context *ctx)
281 return ret; 328 return ret;
282} 329}
283 330
284static inline int spu_process_events(struct spu_context *ctx)
285{
286 struct spu *spu = ctx->spu;
287 int ret = 0;
288
289 if (spu->class_0_pending)
290 ret = spu_irq_class_0_bottom(spu);
291 if (!ret && signal_pending(current))
292 ret = -ERESTARTSYS;
293 return ret;
294}
295
296long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event) 331long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event)
297{ 332{
298 int ret; 333 int ret;
@@ -302,29 +337,14 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event)
302 if (mutex_lock_interruptible(&ctx->run_mutex)) 337 if (mutex_lock_interruptible(&ctx->run_mutex))
303 return -ERESTARTSYS; 338 return -ERESTARTSYS;
304 339
305 ctx->ops->master_start(ctx); 340 spu_enable_spu(ctx);
306 ctx->event_return = 0; 341 ctx->event_return = 0;
307 342
308 spu_acquire(ctx); 343 ret = spu_acquire(ctx);
309 if (ctx->state == SPU_STATE_SAVED) { 344 if (ret)
310 __spu_update_sched_info(ctx); 345 goto out_unlock;
311 spu_set_timeslice(ctx);
312 346
313 ret = spu_activate(ctx, 0); 347 spu_update_sched_info(ctx);
314 if (ret) {
315 spu_release(ctx);
316 goto out;
317 }
318 } else {
319 /*
320 * We have to update the scheduling priority under active_mutex
321 * to protect against find_victim().
322 *
323 * No need to update the timeslice ASAP, it will get updated
324 * once the current one has expired.
325 */
326 spu_update_sched_info(ctx);
327 }
328 348
329 ret = spu_run_init(ctx, npc); 349 ret = spu_run_init(ctx, npc);
330 if (ret) { 350 if (ret) {
@@ -358,14 +378,12 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event)
358 if (ret) 378 if (ret)
359 break; 379 break;
360 380
361 if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { 381 ret = spufs_handle_class0(ctx);
362 ret = spu_reacquire_runnable(ctx, npc, &status); 382 if (ret)
363 if (ret) 383 break;
364 goto out2;
365 continue;
366 }
367 ret = spu_process_events(ctx);
368 384
385 if (signal_pending(current))
386 ret = -ERESTARTSYS;
369 } while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP | 387 } while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP |
370 SPU_STATUS_STOPPED_BY_HALT | 388 SPU_STATUS_STOPPED_BY_HALT |
371 SPU_STATUS_SINGLE_STEP))); 389 SPU_STATUS_SINGLE_STEP)));
@@ -376,11 +394,10 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event)
376 ctx->stats.libassist++; 394 ctx->stats.libassist++;
377 395
378 396
379 ctx->ops->master_stop(ctx); 397 spu_disable_spu(ctx);
380 ret = spu_run_fini(ctx, npc, &status); 398 ret = spu_run_fini(ctx, npc, &status);
381 spu_yield(ctx); 399 spu_yield(ctx);
382 400
383out2:
384 if ((ret == 0) || 401 if ((ret == 0) ||
385 ((ret == -ERESTARTSYS) && 402 ((ret == -ERESTARTSYS) &&
386 ((status & SPU_STATUS_STOPPED_BY_HALT) || 403 ((status & SPU_STATUS_STOPPED_BY_HALT) ||
@@ -401,6 +418,7 @@ out2:
401 418
402out: 419out:
403 *event = ctx->event_return; 420 *event = ctx->event_return;
421out_unlock:
404 mutex_unlock(&ctx->run_mutex); 422 mutex_unlock(&ctx->run_mutex);
405 return ret; 423 return ret;
406} 424}
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 9ad53e637aee..00d914232af1 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -58,6 +58,7 @@ static unsigned long spu_avenrun[3];
58static struct spu_prio_array *spu_prio; 58static struct spu_prio_array *spu_prio;
59static struct task_struct *spusched_task; 59static struct task_struct *spusched_task;
60static struct timer_list spusched_timer; 60static struct timer_list spusched_timer;
61static struct timer_list spuloadavg_timer;
61 62
62/* 63/*
63 * Priority of a normal, non-rt, non-niced'd process (aka nice level 0). 64 * Priority of a normal, non-rt, non-niced'd process (aka nice level 0).
@@ -105,15 +106,21 @@ void spu_set_timeslice(struct spu_context *ctx)
105void __spu_update_sched_info(struct spu_context *ctx) 106void __spu_update_sched_info(struct spu_context *ctx)
106{ 107{
107 /* 108 /*
108 * 32-Bit assignment are atomic on powerpc, and we don't care about 109 * assert that the context is not on the runqueue, so it is safe
109 * memory ordering here because retriving the controlling thread is 110 * to change its scheduling parameters.
110 * per defintion racy. 111 */
112 BUG_ON(!list_empty(&ctx->rq));
113
114 /*
115 * 32-Bit assignments are atomic on powerpc, and we don't care about
116 * memory ordering here because retrieving the controlling thread is
117 * per definition racy.
111 */ 118 */
112 ctx->tid = current->pid; 119 ctx->tid = current->pid;
113 120
114 /* 121 /*
115 * We do our own priority calculations, so we normally want 122 * We do our own priority calculations, so we normally want
116 * ->static_prio to start with. Unfortunately thies field 123 * ->static_prio to start with. Unfortunately this field
117 * contains junk for threads with a realtime scheduling 124 * contains junk for threads with a realtime scheduling
118 * policy so we have to look at ->prio in this case. 125 * policy so we have to look at ->prio in this case.
119 */ 126 */
@@ -124,23 +131,32 @@ void __spu_update_sched_info(struct spu_context *ctx)
124 ctx->policy = current->policy; 131 ctx->policy = current->policy;
125 132
126 /* 133 /*
127 * A lot of places that don't hold list_mutex poke into 134 * TO DO: the context may be loaded, so we may need to activate
128 * cpus_allowed, including grab_runnable_context which 135 * it again on a different node. But it shouldn't hurt anything
129 * already holds the runq_lock. So abuse runq_lock 136 * to update its parameters, because we know that the scheduler
130 * to protect this field aswell. 137 * is not actively looking at this field, since it is not on the
138 * runqueue. The context will be rescheduled on the proper node
139 * if it is timesliced or preempted.
131 */ 140 */
132 spin_lock(&spu_prio->runq_lock);
133 ctx->cpus_allowed = current->cpus_allowed; 141 ctx->cpus_allowed = current->cpus_allowed;
134 spin_unlock(&spu_prio->runq_lock);
135} 142}
136 143
137void spu_update_sched_info(struct spu_context *ctx) 144void spu_update_sched_info(struct spu_context *ctx)
138{ 145{
139 int node = ctx->spu->node; 146 int node;
140 147
141 mutex_lock(&cbe_spu_info[node].list_mutex); 148 if (ctx->state == SPU_STATE_RUNNABLE) {
142 __spu_update_sched_info(ctx); 149 node = ctx->spu->node;
143 mutex_unlock(&cbe_spu_info[node].list_mutex); 150
151 /*
152 * Take list_mutex to sync with find_victim().
153 */
154 mutex_lock(&cbe_spu_info[node].list_mutex);
155 __spu_update_sched_info(ctx);
156 mutex_unlock(&cbe_spu_info[node].list_mutex);
157 } else {
158 __spu_update_sched_info(ctx);
159 }
144} 160}
145 161
146static int __node_allowed(struct spu_context *ctx, int node) 162static int __node_allowed(struct spu_context *ctx, int node)
@@ -174,7 +190,7 @@ void do_notify_spus_active(void)
174 * Wake up the active spu_contexts. 190 * Wake up the active spu_contexts.
175 * 191 *
176 * When the awakened processes see their "notify_active" flag is set, 192 * When the awakened processes see their "notify_active" flag is set,
177 * they will call spu_switch_notify(); 193 * they will call spu_switch_notify().
178 */ 194 */
179 for_each_online_node(node) { 195 for_each_online_node(node) {
180 struct spu *spu; 196 struct spu *spu;
@@ -221,7 +237,6 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx)
221 spu->wbox_callback = spufs_wbox_callback; 237 spu->wbox_callback = spufs_wbox_callback;
222 spu->stop_callback = spufs_stop_callback; 238 spu->stop_callback = spufs_stop_callback;
223 spu->mfc_callback = spufs_mfc_callback; 239 spu->mfc_callback = spufs_mfc_callback;
224 spu->dma_callback = spufs_dma_callback;
225 mb(); 240 mb();
226 spu_unmap_mappings(ctx); 241 spu_unmap_mappings(ctx);
227 spu_restore(&ctx->csa, spu); 242 spu_restore(&ctx->csa, spu);
@@ -409,7 +424,6 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
409 spu->wbox_callback = NULL; 424 spu->wbox_callback = NULL;
410 spu->stop_callback = NULL; 425 spu->stop_callback = NULL;
411 spu->mfc_callback = NULL; 426 spu->mfc_callback = NULL;
412 spu->dma_callback = NULL;
413 spu_associate_mm(spu, NULL); 427 spu_associate_mm(spu, NULL);
414 spu->pid = 0; 428 spu->pid = 0;
415 spu->tgid = 0; 429 spu->tgid = 0;
@@ -454,6 +468,13 @@ static void __spu_add_to_rq(struct spu_context *ctx)
454 } 468 }
455} 469}
456 470
471static void spu_add_to_rq(struct spu_context *ctx)
472{
473 spin_lock(&spu_prio->runq_lock);
474 __spu_add_to_rq(ctx);
475 spin_unlock(&spu_prio->runq_lock);
476}
477
457static void __spu_del_from_rq(struct spu_context *ctx) 478static void __spu_del_from_rq(struct spu_context *ctx)
458{ 479{
459 int prio = ctx->prio; 480 int prio = ctx->prio;
@@ -468,10 +489,24 @@ static void __spu_del_from_rq(struct spu_context *ctx)
468 } 489 }
469} 490}
470 491
492void spu_del_from_rq(struct spu_context *ctx)
493{
494 spin_lock(&spu_prio->runq_lock);
495 __spu_del_from_rq(ctx);
496 spin_unlock(&spu_prio->runq_lock);
497}
498
471static void spu_prio_wait(struct spu_context *ctx) 499static void spu_prio_wait(struct spu_context *ctx)
472{ 500{
473 DEFINE_WAIT(wait); 501 DEFINE_WAIT(wait);
474 502
503 /*
504 * The caller must explicitly wait for a context to be loaded
505 * if the nosched flag is set. If NOSCHED is not set, the caller
506 * queues the context and waits for an spu event or error.
507 */
508 BUG_ON(!(ctx->flags & SPU_CREATE_NOSCHED));
509
475 spin_lock(&spu_prio->runq_lock); 510 spin_lock(&spu_prio->runq_lock);
476 prepare_to_wait_exclusive(&ctx->stop_wq, &wait, TASK_INTERRUPTIBLE); 511 prepare_to_wait_exclusive(&ctx->stop_wq, &wait, TASK_INTERRUPTIBLE);
477 if (!signal_pending(current)) { 512 if (!signal_pending(current)) {
@@ -555,7 +590,7 @@ static struct spu *find_victim(struct spu_context *ctx)
555 /* 590 /*
556 * Look for a possible preemption candidate on the local node first. 591 * Look for a possible preemption candidate on the local node first.
557 * If there is no candidate look at the other nodes. This isn't 592 * If there is no candidate look at the other nodes. This isn't
558 * exactly fair, but so far the whole spu schedule tries to keep 593 * exactly fair, but so far the whole spu scheduler tries to keep
559 * a strong node affinity. We might want to fine-tune this in 594 * a strong node affinity. We might want to fine-tune this in
560 * the future. 595 * the future.
561 */ 596 */
@@ -571,6 +606,7 @@ static struct spu *find_victim(struct spu_context *ctx)
571 struct spu_context *tmp = spu->ctx; 606 struct spu_context *tmp = spu->ctx;
572 607
573 if (tmp && tmp->prio > ctx->prio && 608 if (tmp && tmp->prio > ctx->prio &&
609 !(tmp->flags & SPU_CREATE_NOSCHED) &&
574 (!victim || tmp->prio > victim->prio)) 610 (!victim || tmp->prio > victim->prio))
575 victim = spu->ctx; 611 victim = spu->ctx;
576 } 612 }
@@ -582,6 +618,10 @@ static struct spu *find_victim(struct spu_context *ctx)
582 * higher priority contexts before lower priority 618 * higher priority contexts before lower priority
583 * ones, so this is safe until we introduce 619 * ones, so this is safe until we introduce
584 * priority inheritance schemes. 620 * priority inheritance schemes.
621 *
622 * XXX if the highest priority context is locked,
623 * this can loop a long time. Might be better to
624 * look at another context or give up after X retries.
585 */ 625 */
586 if (!mutex_trylock(&victim->state_mutex)) { 626 if (!mutex_trylock(&victim->state_mutex)) {
587 victim = NULL; 627 victim = NULL;
@@ -589,10 +629,10 @@ static struct spu *find_victim(struct spu_context *ctx)
589 } 629 }
590 630
591 spu = victim->spu; 631 spu = victim->spu;
592 if (!spu) { 632 if (!spu || victim->prio <= ctx->prio) {
593 /* 633 /*
594 * This race can happen because we've dropped 634 * This race can happen because we've dropped
595 * the active list mutex. No a problem, just 635 * the active list mutex. Not a problem, just
596 * restart the search. 636 * restart the search.
597 */ 637 */
598 mutex_unlock(&victim->state_mutex); 638 mutex_unlock(&victim->state_mutex);
@@ -607,13 +647,10 @@ static struct spu *find_victim(struct spu_context *ctx)
607 647
608 victim->stats.invol_ctx_switch++; 648 victim->stats.invol_ctx_switch++;
609 spu->stats.invol_ctx_switch++; 649 spu->stats.invol_ctx_switch++;
650 spu_add_to_rq(victim);
651
610 mutex_unlock(&victim->state_mutex); 652 mutex_unlock(&victim->state_mutex);
611 /* 653
612 * We need to break out of the wait loop in spu_run
613 * manually to ensure this context gets put on the
614 * runqueue again ASAP.
615 */
616 wake_up(&victim->stop_wq);
617 return spu; 654 return spu;
618 } 655 }
619 } 656 }
@@ -621,6 +658,50 @@ static struct spu *find_victim(struct spu_context *ctx)
621 return NULL; 658 return NULL;
622} 659}
623 660
661static void __spu_schedule(struct spu *spu, struct spu_context *ctx)
662{
663 int node = spu->node;
664 int success = 0;
665
666 spu_set_timeslice(ctx);
667
668 mutex_lock(&cbe_spu_info[node].list_mutex);
669 if (spu->ctx == NULL) {
670 spu_bind_context(spu, ctx);
671 cbe_spu_info[node].nr_active++;
672 spu->alloc_state = SPU_USED;
673 success = 1;
674 }
675 mutex_unlock(&cbe_spu_info[node].list_mutex);
676
677 if (success)
678 wake_up_all(&ctx->run_wq);
679 else
680 spu_add_to_rq(ctx);
681}
682
683static void spu_schedule(struct spu *spu, struct spu_context *ctx)
684{
685 /* not a candidate for interruptible because it's called either
686 from the scheduler thread or from spu_deactivate */
687 mutex_lock(&ctx->state_mutex);
688 __spu_schedule(spu, ctx);
689 spu_release(ctx);
690}
691
692static void spu_unschedule(struct spu *spu, struct spu_context *ctx)
693{
694 int node = spu->node;
695
696 mutex_lock(&cbe_spu_info[node].list_mutex);
697 cbe_spu_info[node].nr_active--;
698 spu->alloc_state = SPU_FREE;
699 spu_unbind_context(spu, ctx);
700 ctx->stats.invol_ctx_switch++;
701 spu->stats.invol_ctx_switch++;
702 mutex_unlock(&cbe_spu_info[node].list_mutex);
703}
704
624/** 705/**
625 * spu_activate - find a free spu for a context and execute it 706 * spu_activate - find a free spu for a context and execute it
626 * @ctx: spu context to schedule 707 * @ctx: spu context to schedule
@@ -632,39 +713,47 @@ static struct spu *find_victim(struct spu_context *ctx)
632 */ 713 */
633int spu_activate(struct spu_context *ctx, unsigned long flags) 714int spu_activate(struct spu_context *ctx, unsigned long flags)
634{ 715{
635 do { 716 struct spu *spu;
636 struct spu *spu;
637 717
638 /* 718 /*
639 * If there are multiple threads waiting for a single context 719 * If there are multiple threads waiting for a single context
640 * only one actually binds the context while the others will 720 * only one actually binds the context while the others will
641 * only be able to acquire the state_mutex once the context 721 * only be able to acquire the state_mutex once the context
642 * already is in runnable state. 722 * already is in runnable state.
643 */ 723 */
644 if (ctx->spu) 724 if (ctx->spu)
645 return 0; 725 return 0;
646 726
647 spu = spu_get_idle(ctx); 727spu_activate_top:
648 /* 728 if (signal_pending(current))
649 * If this is a realtime thread we try to get it running by 729 return -ERESTARTSYS;
650 * preempting a lower priority thread.
651 */
652 if (!spu && rt_prio(ctx->prio))
653 spu = find_victim(ctx);
654 if (spu) {
655 int node = spu->node;
656 730
657 mutex_lock(&cbe_spu_info[node].list_mutex); 731 spu = spu_get_idle(ctx);
658 spu_bind_context(spu, ctx); 732 /*
659 cbe_spu_info[node].nr_active++; 733 * If this is a realtime thread we try to get it running by
660 mutex_unlock(&cbe_spu_info[node].list_mutex); 734 * preempting a lower priority thread.
661 return 0; 735 */
662 } 736 if (!spu && rt_prio(ctx->prio))
737 spu = find_victim(ctx);
738 if (spu) {
739 unsigned long runcntl;
740
741 runcntl = ctx->ops->runcntl_read(ctx);
742 __spu_schedule(spu, ctx);
743 if (runcntl & SPU_RUNCNTL_RUNNABLE)
744 spuctx_switch_state(ctx, SPU_UTIL_USER);
663 745
746 return 0;
747 }
748
749 if (ctx->flags & SPU_CREATE_NOSCHED) {
664 spu_prio_wait(ctx); 750 spu_prio_wait(ctx);
665 } while (!signal_pending(current)); 751 goto spu_activate_top;
752 }
666 753
667 return -ERESTARTSYS; 754 spu_add_to_rq(ctx);
755
756 return 0;
668} 757}
669 758
670/** 759/**
@@ -706,21 +795,19 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio)
706 if (spu) { 795 if (spu) {
707 new = grab_runnable_context(max_prio, spu->node); 796 new = grab_runnable_context(max_prio, spu->node);
708 if (new || force) { 797 if (new || force) {
709 int node = spu->node; 798 spu_unschedule(spu, ctx);
710 799 if (new) {
711 mutex_lock(&cbe_spu_info[node].list_mutex); 800 if (new->flags & SPU_CREATE_NOSCHED)
712 spu_unbind_context(spu, ctx); 801 wake_up(&new->stop_wq);
713 spu->alloc_state = SPU_FREE; 802 else {
714 cbe_spu_info[node].nr_active--; 803 spu_release(ctx);
715 mutex_unlock(&cbe_spu_info[node].list_mutex); 804 spu_schedule(spu, new);
716 805 /* this one can't easily be made
717 ctx->stats.vol_ctx_switch++; 806 interruptible */
718 spu->stats.vol_ctx_switch++; 807 mutex_lock(&ctx->state_mutex);
719 808 }
720 if (new) 809 }
721 wake_up(&new->stop_wq);
722 } 810 }
723
724 } 811 }
725 812
726 return new != NULL; 813 return new != NULL;
@@ -757,43 +844,38 @@ void spu_yield(struct spu_context *ctx)
757 844
758static noinline void spusched_tick(struct spu_context *ctx) 845static noinline void spusched_tick(struct spu_context *ctx)
759{ 846{
847 struct spu_context *new = NULL;
848 struct spu *spu = NULL;
849 u32 status;
850
851 if (spu_acquire(ctx))
852 BUG(); /* a kernel thread never has signals pending */
853
854 if (ctx->state != SPU_STATE_RUNNABLE)
855 goto out;
856 if (spu_stopped(ctx, &status))
857 goto out;
760 if (ctx->flags & SPU_CREATE_NOSCHED) 858 if (ctx->flags & SPU_CREATE_NOSCHED)
761 return; 859 goto out;
762 if (ctx->policy == SCHED_FIFO) 860 if (ctx->policy == SCHED_FIFO)
763 return; 861 goto out;
764 862
765 if (--ctx->time_slice) 863 if (--ctx->time_slice)
766 return; 864 goto out;
767 865
768 /* 866 spu = ctx->spu;
769 * Unfortunately list_mutex ranks outside of state_mutex, so 867 new = grab_runnable_context(ctx->prio + 1, spu->node);
770 * we have to trylock here. If we fail give the context another 868 if (new) {
771 * tick and try again. 869 spu_unschedule(spu, ctx);
772 */ 870 spu_add_to_rq(ctx);
773 if (mutex_trylock(&ctx->state_mutex)) {
774 struct spu *spu = ctx->spu;
775 struct spu_context *new;
776
777 new = grab_runnable_context(ctx->prio + 1, spu->node);
778 if (new) {
779 spu_unbind_context(spu, ctx);
780 ctx->stats.invol_ctx_switch++;
781 spu->stats.invol_ctx_switch++;
782 spu->alloc_state = SPU_FREE;
783 cbe_spu_info[spu->node].nr_active--;
784 wake_up(&new->stop_wq);
785 /*
786 * We need to break out of the wait loop in
787 * spu_run manually to ensure this context
788 * gets put on the runqueue again ASAP.
789 */
790 wake_up(&ctx->stop_wq);
791 }
792 spu_set_timeslice(ctx);
793 mutex_unlock(&ctx->state_mutex);
794 } else { 871 } else {
795 ctx->time_slice++; 872 ctx->time_slice++;
796 } 873 }
874out:
875 spu_release(ctx);
876
877 if (new)
878 spu_schedule(spu, new);
797} 879}
798 880
799/** 881/**
@@ -817,35 +899,31 @@ static unsigned long count_active_contexts(void)
817} 899}
818 900
819/** 901/**
820 * spu_calc_load - given tick count, update the avenrun load estimates. 902 * spu_calc_load - update the avenrun load estimates.
821 * @tick: tick count
822 * 903 *
823 * No locking against reading these values from userspace, as for 904 * No locking against reading these values from userspace, as for
824 * the CPU loadavg code. 905 * the CPU loadavg code.
825 */ 906 */
826static void spu_calc_load(unsigned long ticks) 907static void spu_calc_load(void)
827{ 908{
828 unsigned long active_tasks; /* fixed-point */ 909 unsigned long active_tasks; /* fixed-point */
829 static int count = LOAD_FREQ; 910
830 911 active_tasks = count_active_contexts() * FIXED_1;
831 count -= ticks; 912 CALC_LOAD(spu_avenrun[0], EXP_1, active_tasks);
832 913 CALC_LOAD(spu_avenrun[1], EXP_5, active_tasks);
833 if (unlikely(count < 0)) { 914 CALC_LOAD(spu_avenrun[2], EXP_15, active_tasks);
834 active_tasks = count_active_contexts() * FIXED_1;
835 do {
836 CALC_LOAD(spu_avenrun[0], EXP_1, active_tasks);
837 CALC_LOAD(spu_avenrun[1], EXP_5, active_tasks);
838 CALC_LOAD(spu_avenrun[2], EXP_15, active_tasks);
839 count += LOAD_FREQ;
840 } while (count < 0);
841 }
842} 915}
843 916
844static void spusched_wake(unsigned long data) 917static void spusched_wake(unsigned long data)
845{ 918{
846 mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK); 919 mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK);
847 wake_up_process(spusched_task); 920 wake_up_process(spusched_task);
848 spu_calc_load(SPUSCHED_TICK); 921}
922
923static void spuloadavg_wake(unsigned long data)
924{
925 mod_timer(&spuloadavg_timer, jiffies + LOAD_FREQ);
926 spu_calc_load();
849} 927}
850 928
851static int spusched_thread(void *unused) 929static int spusched_thread(void *unused)
@@ -857,17 +935,58 @@ static int spusched_thread(void *unused)
857 set_current_state(TASK_INTERRUPTIBLE); 935 set_current_state(TASK_INTERRUPTIBLE);
858 schedule(); 936 schedule();
859 for (node = 0; node < MAX_NUMNODES; node++) { 937 for (node = 0; node < MAX_NUMNODES; node++) {
860 mutex_lock(&cbe_spu_info[node].list_mutex); 938 struct mutex *mtx = &cbe_spu_info[node].list_mutex;
861 list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) 939
862 if (spu->ctx) 940 mutex_lock(mtx);
863 spusched_tick(spu->ctx); 941 list_for_each_entry(spu, &cbe_spu_info[node].spus,
864 mutex_unlock(&cbe_spu_info[node].list_mutex); 942 cbe_list) {
943 struct spu_context *ctx = spu->ctx;
944
945 if (ctx) {
946 mutex_unlock(mtx);
947 spusched_tick(ctx);
948 mutex_lock(mtx);
949 }
950 }
951 mutex_unlock(mtx);
865 } 952 }
866 } 953 }
867 954
868 return 0; 955 return 0;
869} 956}
870 957
958void spuctx_switch_state(struct spu_context *ctx,
959 enum spu_utilization_state new_state)
960{
961 unsigned long long curtime;
962 signed long long delta;
963 struct timespec ts;
964 struct spu *spu;
965 enum spu_utilization_state old_state;
966
967 ktime_get_ts(&ts);
968 curtime = timespec_to_ns(&ts);
969 delta = curtime - ctx->stats.tstamp;
970
971 WARN_ON(!mutex_is_locked(&ctx->state_mutex));
972 WARN_ON(delta < 0);
973
974 spu = ctx->spu;
975 old_state = ctx->stats.util_state;
976 ctx->stats.util_state = new_state;
977 ctx->stats.tstamp = curtime;
978
979 /*
980 * Update the physical SPU utilization statistics.
981 */
982 if (spu) {
983 ctx->stats.times[old_state] += delta;
984 spu->stats.times[old_state] += delta;
985 spu->stats.util_state = new_state;
986 spu->stats.tstamp = curtime;
987 }
988}
989
871#define LOAD_INT(x) ((x) >> FSHIFT) 990#define LOAD_INT(x) ((x) >> FSHIFT)
872#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) 991#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
873 992
@@ -881,7 +1000,7 @@ static int show_spu_loadavg(struct seq_file *s, void *private)
881 1000
882 /* 1001 /*
883 * Note that last_pid doesn't really make much sense for the 1002 * Note that last_pid doesn't really make much sense for the
884 * SPU loadavg (it even seems very odd on the CPU side..), 1003 * SPU loadavg (it even seems very odd on the CPU side...),
885 * but we include it here to have a 100% compatible interface. 1004 * but we include it here to have a 100% compatible interface.
886 */ 1005 */
887 seq_printf(s, "%d.%02d %d.%02d %d.%02d %ld/%d %d\n", 1006 seq_printf(s, "%d.%02d %d.%02d %d.%02d %ld/%d %d\n",
@@ -922,6 +1041,7 @@ int __init spu_sched_init(void)
922 spin_lock_init(&spu_prio->runq_lock); 1041 spin_lock_init(&spu_prio->runq_lock);
923 1042
924 setup_timer(&spusched_timer, spusched_wake, 0); 1043 setup_timer(&spusched_timer, spusched_wake, 0);
1044 setup_timer(&spuloadavg_timer, spuloadavg_wake, 0);
925 1045
926 spusched_task = kthread_run(spusched_thread, NULL, "spusched"); 1046 spusched_task = kthread_run(spusched_thread, NULL, "spusched");
927 if (IS_ERR(spusched_task)) { 1047 if (IS_ERR(spusched_task)) {
@@ -929,6 +1049,8 @@ int __init spu_sched_init(void)
929 goto out_free_spu_prio; 1049 goto out_free_spu_prio;
930 } 1050 }
931 1051
1052 mod_timer(&spuloadavg_timer, 0);
1053
932 entry = create_proc_entry("spu_loadavg", 0, NULL); 1054 entry = create_proc_entry("spu_loadavg", 0, NULL);
933 if (!entry) 1055 if (!entry)
934 goto out_stop_kthread; 1056 goto out_stop_kthread;
@@ -954,6 +1076,7 @@ void spu_sched_exit(void)
954 remove_proc_entry("spu_loadavg", NULL); 1076 remove_proc_entry("spu_loadavg", NULL);
955 1077
956 del_timer_sync(&spusched_timer); 1078 del_timer_sync(&spusched_timer);
1079 del_timer_sync(&spuloadavg_timer);
957 kthread_stop(spusched_task); 1080 kthread_stop(spusched_task);
958 1081
959 for (node = 0; node < MAX_NUMNODES; node++) { 1082 for (node = 0; node < MAX_NUMNODES; node++) {
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index ca47b991bda5..0e114038ea6f 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -71,6 +71,7 @@ struct spu_context {
71 wait_queue_head_t wbox_wq; 71 wait_queue_head_t wbox_wq;
72 wait_queue_head_t stop_wq; 72 wait_queue_head_t stop_wq;
73 wait_queue_head_t mfc_wq; 73 wait_queue_head_t mfc_wq;
74 wait_queue_head_t run_wq;
74 struct fasync_struct *ibox_fasync; 75 struct fasync_struct *ibox_fasync;
75 struct fasync_struct *wbox_fasync; 76 struct fasync_struct *wbox_fasync;
76 struct fasync_struct *mfc_fasync; 77 struct fasync_struct *mfc_fasync;
@@ -168,8 +169,10 @@ struct spu_context_ops {
168 void (*npc_write) (struct spu_context * ctx, u32 data); 169 void (*npc_write) (struct spu_context * ctx, u32 data);
169 u32(*status_read) (struct spu_context * ctx); 170 u32(*status_read) (struct spu_context * ctx);
170 char*(*get_ls) (struct spu_context * ctx); 171 char*(*get_ls) (struct spu_context * ctx);
172 void (*privcntl_write) (struct spu_context *ctx, u64 data);
171 u32 (*runcntl_read) (struct spu_context * ctx); 173 u32 (*runcntl_read) (struct spu_context * ctx);
172 void (*runcntl_write) (struct spu_context * ctx, u32 data); 174 void (*runcntl_write) (struct spu_context * ctx, u32 data);
175 void (*runcntl_stop) (struct spu_context * ctx);
173 void (*master_start) (struct spu_context * ctx); 176 void (*master_start) (struct spu_context * ctx);
174 void (*master_stop) (struct spu_context * ctx); 177 void (*master_stop) (struct spu_context * ctx);
175 int (*set_mfc_query)(struct spu_context * ctx, u32 mask, u32 mode); 178 int (*set_mfc_query)(struct spu_context * ctx, u32 mask, u32 mode);
@@ -219,15 +222,16 @@ void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx);
219 222
220/* fault handling */ 223/* fault handling */
221int spufs_handle_class1(struct spu_context *ctx); 224int spufs_handle_class1(struct spu_context *ctx);
225int spufs_handle_class0(struct spu_context *ctx);
222 226
223/* affinity */ 227/* affinity */
224struct spu *affinity_check(struct spu_context *ctx); 228struct spu *affinity_check(struct spu_context *ctx);
225 229
226/* context management */ 230/* context management */
227extern atomic_t nr_spu_contexts; 231extern atomic_t nr_spu_contexts;
228static inline void spu_acquire(struct spu_context *ctx) 232static inline int __must_check spu_acquire(struct spu_context *ctx)
229{ 233{
230 mutex_lock(&ctx->state_mutex); 234 return mutex_lock_interruptible(&ctx->state_mutex);
231} 235}
232 236
233static inline void spu_release(struct spu_context *ctx) 237static inline void spu_release(struct spu_context *ctx)
@@ -242,10 +246,11 @@ int put_spu_context(struct spu_context *ctx);
242void spu_unmap_mappings(struct spu_context *ctx); 246void spu_unmap_mappings(struct spu_context *ctx);
243 247
244void spu_forget(struct spu_context *ctx); 248void spu_forget(struct spu_context *ctx);
245int spu_acquire_runnable(struct spu_context *ctx, unsigned long flags); 249int __must_check spu_acquire_saved(struct spu_context *ctx);
246void spu_acquire_saved(struct spu_context *ctx);
247void spu_release_saved(struct spu_context *ctx); 250void spu_release_saved(struct spu_context *ctx);
248 251
252int spu_stopped(struct spu_context *ctx, u32 * stat);
253void spu_del_from_rq(struct spu_context *ctx);
249int spu_activate(struct spu_context *ctx, unsigned long flags); 254int spu_activate(struct spu_context *ctx, unsigned long flags);
250void spu_deactivate(struct spu_context *ctx); 255void spu_deactivate(struct spu_context *ctx);
251void spu_yield(struct spu_context *ctx); 256void spu_yield(struct spu_context *ctx);
@@ -279,7 +284,9 @@ extern char *isolated_loader;
279 } \ 284 } \
280 spu_release(ctx); \ 285 spu_release(ctx); \
281 schedule(); \ 286 schedule(); \
282 spu_acquire(ctx); \ 287 __ret = spu_acquire(ctx); \
288 if (__ret) \
289 break; \
283 } \ 290 } \
284 finish_wait(&(wq), &__wait); \ 291 finish_wait(&(wq), &__wait); \
285 __ret; \ 292 __ret; \
@@ -306,41 +313,16 @@ struct spufs_coredump_reader {
306extern struct spufs_coredump_reader spufs_coredump_read[]; 313extern struct spufs_coredump_reader spufs_coredump_read[];
307extern int spufs_coredump_num_notes; 314extern int spufs_coredump_num_notes;
308 315
309/* 316extern int spu_init_csa(struct spu_state *csa);
310 * This function is a little bit too large for an inline, but 317extern void spu_fini_csa(struct spu_state *csa);
311 * as fault.c is built into the kernel we can't move it out of 318extern int spu_save(struct spu_state *prev, struct spu *spu);
312 * line. 319extern int spu_restore(struct spu_state *new, struct spu *spu);
313 */ 320extern int spu_switch(struct spu_state *prev, struct spu_state *new,
314static inline void spuctx_switch_state(struct spu_context *ctx, 321 struct spu *spu);
315 enum spu_utilization_state new_state) 322extern int spu_alloc_lscsa(struct spu_state *csa);
316{ 323extern void spu_free_lscsa(struct spu_state *csa);
317 unsigned long long curtime; 324
318 signed long long delta; 325extern void spuctx_switch_state(struct spu_context *ctx,
319 struct timespec ts; 326 enum spu_utilization_state new_state);
320 struct spu *spu;
321 enum spu_utilization_state old_state;
322
323 ktime_get_ts(&ts);
324 curtime = timespec_to_ns(&ts);
325 delta = curtime - ctx->stats.tstamp;
326
327 WARN_ON(!mutex_is_locked(&ctx->state_mutex));
328 WARN_ON(delta < 0);
329
330 spu = ctx->spu;
331 old_state = ctx->stats.util_state;
332 ctx->stats.util_state = new_state;
333 ctx->stats.tstamp = curtime;
334
335 /*
336 * Update the physical SPU utilization statistics.
337 */
338 if (spu) {
339 ctx->stats.times[old_state] += delta;
340 spu->stats.times[old_state] += delta;
341 spu->stats.util_state = new_state;
342 spu->stats.tstamp = curtime;
343 }
344}
345 327
346#endif 328#endif
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index 3d64c81cc6e2..6063c88c26d2 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -48,6 +48,8 @@
48#include <asm/spu_csa.h> 48#include <asm/spu_csa.h>
49#include <asm/mmu_context.h> 49#include <asm/mmu_context.h>
50 50
51#include "spufs.h"
52
51#include "spu_save_dump.h" 53#include "spu_save_dump.h"
52#include "spu_restore_dump.h" 54#include "spu_restore_dump.h"
53 55
@@ -691,35 +693,9 @@ static inline void resume_mfc_queue(struct spu_state *csa, struct spu *spu)
691 out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESUME_DMA_QUEUE); 693 out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESUME_DMA_QUEUE);
692} 694}
693 695
694static inline void get_kernel_slb(u64 ea, u64 slb[2]) 696static inline void setup_mfc_slbs(struct spu_state *csa, struct spu *spu,
697 unsigned int *code, int code_size)
695{ 698{
696 u64 llp;
697
698 if (REGION_ID(ea) == KERNEL_REGION_ID)
699 llp = mmu_psize_defs[mmu_linear_psize].sllp;
700 else
701 llp = mmu_psize_defs[mmu_virtual_psize].sllp;
702 slb[0] = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
703 SLB_VSID_KERNEL | llp;
704 slb[1] = (ea & ESID_MASK) | SLB_ESID_V;
705}
706
707static inline void load_mfc_slb(struct spu *spu, u64 slb[2], int slbe)
708{
709 struct spu_priv2 __iomem *priv2 = spu->priv2;
710
711 out_be64(&priv2->slb_index_W, slbe);
712 eieio();
713 out_be64(&priv2->slb_vsid_RW, slb[0]);
714 out_be64(&priv2->slb_esid_RW, slb[1]);
715 eieio();
716}
717
718static inline void setup_mfc_slbs(struct spu_state *csa, struct spu *spu)
719{
720 u64 code_slb[2];
721 u64 lscsa_slb[2];
722
723 /* Save, Step 47: 699 /* Save, Step 47:
724 * Restore, Step 30. 700 * Restore, Step 30.
725 * If MFC_SR1[R]=1, write 0 to SLB_Invalidate_All 701 * If MFC_SR1[R]=1, write 0 to SLB_Invalidate_All
@@ -735,11 +711,7 @@ static inline void setup_mfc_slbs(struct spu_state *csa, struct spu *spu)
735 * translation is desired by OS environment). 711 * translation is desired by OS environment).
736 */ 712 */
737 spu_invalidate_slbs(spu); 713 spu_invalidate_slbs(spu);
738 get_kernel_slb((unsigned long)&spu_save_code[0], code_slb); 714 spu_setup_kernel_slbs(spu, csa->lscsa, code, code_size);
739 get_kernel_slb((unsigned long)csa->lscsa, lscsa_slb);
740 load_mfc_slb(spu, code_slb, 0);
741 if ((lscsa_slb[0] != code_slb[0]) || (lscsa_slb[1] != code_slb[1]))
742 load_mfc_slb(spu, lscsa_slb, 1);
743} 715}
744 716
745static inline void set_switch_active(struct spu_state *csa, struct spu *spu) 717static inline void set_switch_active(struct spu_state *csa, struct spu *spu)
@@ -768,9 +740,9 @@ static inline void enable_interrupts(struct spu_state *csa, struct spu *spu)
768 * (translation) interrupts. 740 * (translation) interrupts.
769 */ 741 */
770 spin_lock_irq(&spu->register_lock); 742 spin_lock_irq(&spu->register_lock);
771 spu_int_stat_clear(spu, 0, ~0ul); 743 spu_int_stat_clear(spu, 0, CLASS0_INTR_MASK);
772 spu_int_stat_clear(spu, 1, ~0ul); 744 spu_int_stat_clear(spu, 1, CLASS1_INTR_MASK);
773 spu_int_stat_clear(spu, 2, ~0ul); 745 spu_int_stat_clear(spu, 2, CLASS2_INTR_MASK);
774 spu_int_mask_set(spu, 0, 0ul); 746 spu_int_mask_set(spu, 0, 0ul);
775 spu_int_mask_set(spu, 1, class1_mask); 747 spu_int_mask_set(spu, 1, class1_mask);
776 spu_int_mask_set(spu, 2, 0ul); 748 spu_int_mask_set(spu, 2, 0ul);
@@ -927,8 +899,8 @@ static inline void wait_tag_complete(struct spu_state *csa, struct spu *spu)
927 POLL_WHILE_FALSE(in_be32(&prob->dma_tagstatus_R) & mask); 899 POLL_WHILE_FALSE(in_be32(&prob->dma_tagstatus_R) & mask);
928 900
929 local_irq_save(flags); 901 local_irq_save(flags);
930 spu_int_stat_clear(spu, 0, ~(0ul)); 902 spu_int_stat_clear(spu, 0, CLASS0_INTR_MASK);
931 spu_int_stat_clear(spu, 2, ~(0ul)); 903 spu_int_stat_clear(spu, 2, CLASS2_INTR_MASK);
932 local_irq_restore(flags); 904 local_irq_restore(flags);
933} 905}
934 906
@@ -946,8 +918,8 @@ static inline void wait_spu_stopped(struct spu_state *csa, struct spu *spu)
946 POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING); 918 POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING);
947 919
948 local_irq_save(flags); 920 local_irq_save(flags);
949 spu_int_stat_clear(spu, 0, ~(0ul)); 921 spu_int_stat_clear(spu, 0, CLASS0_INTR_MASK);
950 spu_int_stat_clear(spu, 2, ~(0ul)); 922 spu_int_stat_clear(spu, 2, CLASS2_INTR_MASK);
951 local_irq_restore(flags); 923 local_irq_restore(flags);
952} 924}
953 925
@@ -1423,9 +1395,9 @@ static inline void clear_interrupts(struct spu_state *csa, struct spu *spu)
1423 spu_int_mask_set(spu, 0, 0ul); 1395 spu_int_mask_set(spu, 0, 0ul);
1424 spu_int_mask_set(spu, 1, 0ul); 1396 spu_int_mask_set(spu, 1, 0ul);
1425 spu_int_mask_set(spu, 2, 0ul); 1397 spu_int_mask_set(spu, 2, 0ul);
1426 spu_int_stat_clear(spu, 0, ~0ul); 1398 spu_int_stat_clear(spu, 0, CLASS0_INTR_MASK);
1427 spu_int_stat_clear(spu, 1, ~0ul); 1399 spu_int_stat_clear(spu, 1, CLASS1_INTR_MASK);
1428 spu_int_stat_clear(spu, 2, ~0ul); 1400 spu_int_stat_clear(spu, 2, CLASS2_INTR_MASK);
1429 spin_unlock_irq(&spu->register_lock); 1401 spin_unlock_irq(&spu->register_lock);
1430} 1402}
1431 1403
@@ -1866,7 +1838,8 @@ static void save_lscsa(struct spu_state *prev, struct spu *spu)
1866 */ 1838 */
1867 1839
1868 resume_mfc_queue(prev, spu); /* Step 46. */ 1840 resume_mfc_queue(prev, spu); /* Step 46. */
1869 setup_mfc_slbs(prev, spu); /* Step 47. */ 1841 /* Step 47. */
1842 setup_mfc_slbs(prev, spu, spu_save_code, sizeof(spu_save_code));
1870 set_switch_active(prev, spu); /* Step 48. */ 1843 set_switch_active(prev, spu); /* Step 48. */
1871 enable_interrupts(prev, spu); /* Step 49. */ 1844 enable_interrupts(prev, spu); /* Step 49. */
1872 save_ls_16kb(prev, spu); /* Step 50. */ 1845 save_ls_16kb(prev, spu); /* Step 50. */
@@ -1971,7 +1944,8 @@ static void restore_lscsa(struct spu_state *next, struct spu *spu)
1971 setup_spu_status_part1(next, spu); /* Step 27. */ 1944 setup_spu_status_part1(next, spu); /* Step 27. */
1972 setup_spu_status_part2(next, spu); /* Step 28. */ 1945 setup_spu_status_part2(next, spu); /* Step 28. */
1973 restore_mfc_rag(next, spu); /* Step 29. */ 1946 restore_mfc_rag(next, spu); /* Step 29. */
1974 setup_mfc_slbs(next, spu); /* Step 30. */ 1947 /* Step 30. */
1948 setup_mfc_slbs(next, spu, spu_restore_code, sizeof(spu_restore_code));
1975 set_spu_npc(next, spu); /* Step 31. */ 1949 set_spu_npc(next, spu); /* Step 31. */
1976 set_signot1(next, spu); /* Step 32. */ 1950 set_signot1(next, spu); /* Step 32. */
1977 set_signot2(next, spu); /* Step 33. */ 1951 set_signot2(next, spu); /* Step 33. */
@@ -2103,10 +2077,6 @@ int spu_save(struct spu_state *prev, struct spu *spu)
2103 int rc; 2077 int rc;
2104 2078
2105 acquire_spu_lock(spu); /* Step 1. */ 2079 acquire_spu_lock(spu); /* Step 1. */
2106 prev->dar = spu->dar;
2107 prev->dsisr = spu->dsisr;
2108 spu->dar = 0;
2109 spu->dsisr = 0;
2110 rc = __do_spu_save(prev, spu); /* Steps 2-53. */ 2080 rc = __do_spu_save(prev, spu); /* Steps 2-53. */
2111 release_spu_lock(spu); 2081 release_spu_lock(spu);
2112 if (rc != 0 && rc != 2 && rc != 6) { 2082 if (rc != 0 && rc != 2 && rc != 6) {
@@ -2133,9 +2103,6 @@ int spu_restore(struct spu_state *new, struct spu *spu)
2133 acquire_spu_lock(spu); 2103 acquire_spu_lock(spu);
2134 harvest(NULL, spu); 2104 harvest(NULL, spu);
2135 spu->slb_replace = 0; 2105 spu->slb_replace = 0;
2136 new->dar = 0;
2137 new->dsisr = 0;
2138 spu->class_0_pending = 0;
2139 rc = __do_spu_restore(new, spu); 2106 rc = __do_spu_restore(new, spu);
2140 release_spu_lock(spu); 2107 release_spu_lock(spu);
2141 if (rc) { 2108 if (rc) {
@@ -2215,10 +2182,8 @@ int spu_init_csa(struct spu_state *csa)
2215 2182
2216 return 0; 2183 return 0;
2217} 2184}
2218EXPORT_SYMBOL_GPL(spu_init_csa);
2219 2185
2220void spu_fini_csa(struct spu_state *csa) 2186void spu_fini_csa(struct spu_state *csa)
2221{ 2187{
2222 spu_free_lscsa(csa); 2188 spu_free_lscsa(csa);
2223} 2189}
2224EXPORT_SYMBOL_GPL(spu_fini_csa);
diff --git a/arch/powerpc/platforms/celleb/Kconfig b/arch/powerpc/platforms/celleb/Kconfig
index 04748d410fc9..372891edcdd2 100644
--- a/arch/powerpc/platforms/celleb/Kconfig
+++ b/arch/powerpc/platforms/celleb/Kconfig
@@ -2,6 +2,8 @@ config PPC_CELLEB
2 bool "Toshiba's Cell Reference Set 'Celleb' Architecture" 2 bool "Toshiba's Cell Reference Set 'Celleb' Architecture"
3 depends on PPC_MULTIPLATFORM && PPC64 3 depends on PPC_MULTIPLATFORM && PPC64
4 select PPC_CELL 4 select PPC_CELL
5 select PPC_CELL_NATIVE
6 select PPC_RTAS
5 select PPC_INDIRECT_IO 7 select PPC_INDIRECT_IO
6 select PPC_OF_PLATFORM_PCI 8 select PPC_OF_PLATFORM_PCI
7 select HAS_TXX9_SERIAL 9 select HAS_TXX9_SERIAL
diff --git a/arch/powerpc/platforms/celleb/io-workarounds.c b/arch/powerpc/platforms/celleb/io-workarounds.c
index 2b912140bcbb..423339be1bac 100644
--- a/arch/powerpc/platforms/celleb/io-workarounds.c
+++ b/arch/powerpc/platforms/celleb/io-workarounds.c
@@ -22,6 +22,7 @@
22 22
23#undef DEBUG 23#undef DEBUG
24 24
25#include <linux/of.h>
25#include <linux/of_device.h> 26#include <linux/of_device.h>
26#include <linux/irq.h> 27#include <linux/irq.h>
27 28
@@ -222,7 +223,7 @@ void __init celleb_pci_add_one(struct pci_controller *phb,
222 void (*dummy_read)(struct pci_controller *)) 223 void (*dummy_read)(struct pci_controller *))
223{ 224{
224 struct celleb_pci_bus *bus = &celleb_pci_busses[celleb_pci_count]; 225 struct celleb_pci_bus *bus = &celleb_pci_busses[celleb_pci_count];
225 struct device_node *np = phb->arch_data; 226 struct device_node *np = phb->dn;
226 227
227 if (celleb_pci_count >= MAX_CELLEB_PCI_BUS) { 228 if (celleb_pci_count >= MAX_CELLEB_PCI_BUS) {
228 printk(KERN_ERR "Too many pci bridges, workarounds" 229 printk(KERN_ERR "Too many pci bridges, workarounds"
@@ -256,13 +257,13 @@ int __init celleb_pci_workaround_init(void)
256 257
257 celleb_dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL); 258 celleb_dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL);
258 if (!celleb_dummy_page_va) { 259 if (!celleb_dummy_page_va) {
259 printk(KERN_ERR "Celleb: dummy read disabled." 260 printk(KERN_ERR "Celleb: dummy read disabled. "
260 "Alloc celleb_dummy_page_va failed\n"); 261 "Alloc celleb_dummy_page_va failed\n");
261 return 1; 262 return 1;
262 } 263 }
263 264
264 list_for_each_entry(phb, &hose_list, list_node) { 265 list_for_each_entry(phb, &hose_list, list_node) {
265 node = phb->arch_data; 266 node = phb->dn;
266 match = of_match_node(celleb_pci_workaround_match, node); 267 match = of_match_node(celleb_pci_workaround_match, node);
267 268
268 if (match) { 269 if (match) {
diff --git a/arch/powerpc/platforms/celleb/iommu.c b/arch/powerpc/platforms/celleb/iommu.c
index 755d869d8553..93b0efddd658 100644
--- a/arch/powerpc/platforms/celleb/iommu.c
+++ b/arch/powerpc/platforms/celleb/iommu.c
@@ -22,8 +22,9 @@
22#include <linux/init.h> 22#include <linux/init.h>
23#include <linux/dma-mapping.h> 23#include <linux/dma-mapping.h>
24#include <linux/pci.h> 24#include <linux/pci.h>
25#include <linux/of_platform.h>
25 26
26#include <asm/of_platform.h> 27#include <asm/machdep.h>
27 28
28#include "beat_wrapper.h" 29#include "beat_wrapper.h"
29 30
@@ -51,6 +52,8 @@ static int __init find_dma_window(u64 *io_space_id, u64 *ioid,
51 return 0; 52 return 0;
52} 53}
53 54
55static unsigned long celleb_dma_direct_offset;
56
54static void __init celleb_init_direct_mapping(void) 57static void __init celleb_init_direct_mapping(void)
55{ 58{
56 u64 lpar_addr, io_addr; 59 u64 lpar_addr, io_addr;
@@ -68,7 +71,18 @@ static void __init celleb_init_direct_mapping(void)
68 ioid, DMA_FLAGS); 71 ioid, DMA_FLAGS);
69 } 72 }
70 73
71 dma_direct_offset = dma_base; 74 celleb_dma_direct_offset = dma_base;
75}
76
77static void celleb_dma_dev_setup(struct device *dev)
78{
79 dev->archdata.dma_ops = get_pci_dma_ops();
80 dev->archdata.dma_data = (void *)celleb_dma_direct_offset;
81}
82
83static void celleb_pci_dma_dev_setup(struct pci_dev *pdev)
84{
85 celleb_dma_dev_setup(&pdev->dev);
72} 86}
73 87
74static int celleb_of_bus_notify(struct notifier_block *nb, 88static int celleb_of_bus_notify(struct notifier_block *nb,
@@ -80,7 +94,7 @@ static int celleb_of_bus_notify(struct notifier_block *nb,
80 if (action != BUS_NOTIFY_ADD_DEVICE) 94 if (action != BUS_NOTIFY_ADD_DEVICE)
81 return 0; 95 return 0;
82 96
83 dev->archdata.dma_ops = get_pci_dma_ops(); 97 celleb_dma_dev_setup(dev);
84 98
85 return 0; 99 return 0;
86} 100}
@@ -91,14 +105,12 @@ static struct notifier_block celleb_of_bus_notifier = {
91 105
92static int __init celleb_init_iommu(void) 106static int __init celleb_init_iommu(void)
93{ 107{
94 if (!machine_is(celleb))
95 return -ENODEV;
96
97 celleb_init_direct_mapping(); 108 celleb_init_direct_mapping();
98 set_pci_dma_ops(&dma_direct_ops); 109 set_pci_dma_ops(&dma_direct_ops);
110 ppc_md.pci_dma_dev_setup = celleb_pci_dma_dev_setup;
99 bus_register_notifier(&of_platform_bus_type, &celleb_of_bus_notifier); 111 bus_register_notifier(&of_platform_bus_type, &celleb_of_bus_notifier);
100 112
101 return 0; 113 return 0;
102} 114}
103 115
104arch_initcall(celleb_init_iommu); 116machine_arch_initcall(celleb_beat, celleb_init_iommu);
diff --git a/arch/powerpc/platforms/celleb/pci.c b/arch/powerpc/platforms/celleb/pci.c
index 6bc32fda7a6b..51b390d34e4d 100644
--- a/arch/powerpc/platforms/celleb/pci.c
+++ b/arch/powerpc/platforms/celleb/pci.c
@@ -31,6 +31,7 @@
31#include <linux/init.h> 31#include <linux/init.h>
32#include <linux/bootmem.h> 32#include <linux/bootmem.h>
33#include <linux/pci_regs.h> 33#include <linux/pci_regs.h>
34#include <linux/of.h>
34#include <linux/of_device.h> 35#include <linux/of_device.h>
35 36
36#include <asm/io.h> 37#include <asm/io.h>
@@ -138,8 +139,6 @@ static void celleb_config_read_fake(unsigned char *config, int where,
138 *val = celleb_fake_config_readl(p); 139 *val = celleb_fake_config_readl(p);
139 break; 140 break;
140 } 141 }
141
142 return;
143} 142}
144 143
145static void celleb_config_write_fake(unsigned char *config, int where, 144static void celleb_config_write_fake(unsigned char *config, int where,
@@ -158,7 +157,6 @@ static void celleb_config_write_fake(unsigned char *config, int where,
158 celleb_fake_config_writel(val, p); 157 celleb_fake_config_writel(val, p);
159 break; 158 break;
160 } 159 }
161 return;
162} 160}
163 161
164static int celleb_fake_pci_read_config(struct pci_bus *bus, 162static int celleb_fake_pci_read_config(struct pci_bus *bus,
@@ -351,6 +349,10 @@ static int __init celleb_setup_fake_pci_device(struct device_node *node,
351 wi1 = of_get_property(node, "vendor-id", NULL); 349 wi1 = of_get_property(node, "vendor-id", NULL);
352 wi2 = of_get_property(node, "class-code", NULL); 350 wi2 = of_get_property(node, "class-code", NULL);
353 wi3 = of_get_property(node, "revision-id", NULL); 351 wi3 = of_get_property(node, "revision-id", NULL);
352 if (!wi0 || !wi1 || !wi2 || !wi3) {
353 printk(KERN_ERR "PCI: Missing device tree properties.\n");
354 goto error;
355 }
354 356
355 celleb_config_write_fake(*config, PCI_DEVICE_ID, 2, wi0[0] & 0xffff); 357 celleb_config_write_fake(*config, PCI_DEVICE_ID, 2, wi0[0] & 0xffff);
356 celleb_config_write_fake(*config, PCI_VENDOR_ID, 2, wi1[0] & 0xffff); 358 celleb_config_write_fake(*config, PCI_VENDOR_ID, 2, wi1[0] & 0xffff);
@@ -372,6 +374,10 @@ static int __init celleb_setup_fake_pci_device(struct device_node *node,
372 celleb_setup_pci_base_addrs(hose, devno, fn, num_base_addr); 374 celleb_setup_pci_base_addrs(hose, devno, fn, num_base_addr);
373 375
374 li = of_get_property(node, "interrupts", &rlen); 376 li = of_get_property(node, "interrupts", &rlen);
377 if (!li) {
378 printk(KERN_ERR "PCI: interrupts not found.\n");
379 goto error;
380 }
375 val = li[0]; 381 val = li[0];
376 celleb_config_write_fake(*config, PCI_INTERRUPT_PIN, 1, 1); 382 celleb_config_write_fake(*config, PCI_INTERRUPT_PIN, 1, 1);
377 celleb_config_write_fake(*config, PCI_INTERRUPT_LINE, 1, val); 383 celleb_config_write_fake(*config, PCI_INTERRUPT_LINE, 1, val);
@@ -475,7 +481,7 @@ static struct of_device_id celleb_phb_match[] __initdata = {
475 481
476int __init celleb_setup_phb(struct pci_controller *phb) 482int __init celleb_setup_phb(struct pci_controller *phb)
477{ 483{
478 struct device_node *dev = phb->arch_data; 484 struct device_node *dev = phb->dn;
479 const struct of_device_id *match; 485 const struct of_device_id *match;
480 int (*setup_func)(struct device_node *, struct pci_controller *); 486 int (*setup_func)(struct device_node *, struct pci_controller *);
481 487
diff --git a/arch/powerpc/platforms/celleb/scc_epci.c b/arch/powerpc/platforms/celleb/scc_epci.c
index 9d076426676c..a3c7cfbcb323 100644
--- a/arch/powerpc/platforms/celleb/scc_epci.c
+++ b/arch/powerpc/platforms/celleb/scc_epci.c
@@ -95,7 +95,7 @@ void __init epci_workaround_init(struct pci_controller *hose)
95 private->dummy_page_da = dma_map_single(hose->parent, 95 private->dummy_page_da = dma_map_single(hose->parent,
96 celleb_dummy_page_va, PAGE_SIZE, DMA_FROM_DEVICE); 96 celleb_dummy_page_va, PAGE_SIZE, DMA_FROM_DEVICE);
97 if (private->dummy_page_da == DMA_ERROR_CODE) { 97 if (private->dummy_page_da == DMA_ERROR_CODE) {
98 printk(KERN_ERR "EPCI: dummy read disabled." 98 printk(KERN_ERR "EPCI: dummy read disabled. "
99 "Map dummy page failed.\n"); 99 "Map dummy page failed.\n");
100 return; 100 return;
101 } 101 }
diff --git a/arch/powerpc/platforms/celleb/scc_uhc.c b/arch/powerpc/platforms/celleb/scc_uhc.c
index b59c38a06e3e..cb4307994087 100644
--- a/arch/powerpc/platforms/celleb/scc_uhc.c
+++ b/arch/powerpc/platforms/celleb/scc_uhc.c
@@ -47,7 +47,8 @@ static void enable_scc_uhc(struct pci_dev *dev)
47 u32 val = 0; 47 u32 val = 0;
48 int i; 48 int i;
49 49
50 if (!machine_is(celleb)) 50 if (!machine_is(celleb_beat) &&
51 !machine_is(celleb_native))
51 return; 52 return;
52 53
53 uhc_base = ioremap(pci_resource_start(dev, 0), 54 uhc_base = ioremap(pci_resource_start(dev, 0),
diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c
index ddfb35ae741f..f27ae1e3fb58 100644
--- a/arch/powerpc/platforms/celleb/setup.c
+++ b/arch/powerpc/platforms/celleb/setup.c
@@ -40,6 +40,7 @@
40#include <linux/seq_file.h> 40#include <linux/seq_file.h>
41#include <linux/root_dev.h> 41#include <linux/root_dev.h>
42#include <linux/console.h> 42#include <linux/console.h>
43#include <linux/of_platform.h>
43 44
44#include <asm/mmu.h> 45#include <asm/mmu.h>
45#include <asm/processor.h> 46#include <asm/processor.h>
@@ -52,12 +53,16 @@
52#include <asm/time.h> 53#include <asm/time.h>
53#include <asm/spu_priv1.h> 54#include <asm/spu_priv1.h>
54#include <asm/firmware.h> 55#include <asm/firmware.h>
55#include <asm/of_platform.h> 56#include <asm/rtas.h>
57#include <asm/cell-regs.h>
56 58
57#include "interrupt.h" 59#include "interrupt.h"
58#include "beat_wrapper.h" 60#include "beat_wrapper.h"
59#include "beat.h" 61#include "beat.h"
60#include "pci.h" 62#include "pci.h"
63#include "../cell/interrupt.h"
64#include "../cell/pervasive.h"
65#include "../cell/ras.h"
61 66
62static char celleb_machine_type[128] = "Celleb"; 67static char celleb_machine_type[128] = "Celleb";
63 68
@@ -88,61 +93,122 @@ static void celleb_progress(char *s, unsigned short hex)
88 printk("*** %04x : %s\n", hex, s ? s : ""); 93 printk("*** %04x : %s\n", hex, s ? s : "");
89} 94}
90 95
91static void __init celleb_setup_arch(void) 96static void __init celleb_setup_arch_common(void)
97{
98 /* init to some ~sane value until calibrate_delay() runs */
99 loops_per_jiffy = 50000000;
100
101#ifdef CONFIG_DUMMY_CONSOLE
102 conswitchp = &dummy_con;
103#endif
104}
105
106static struct of_device_id celleb_bus_ids[] __initdata = {
107 { .type = "scc", },
108 { .type = "ioif", }, /* old style */
109 {},
110};
111
112static int __init celleb_publish_devices(void)
113{
114 /* Publish OF platform devices for southbridge IOs */
115 of_platform_bus_probe(NULL, celleb_bus_ids, NULL);
116
117 celleb_pci_workaround_init();
118
119 return 0;
120}
121machine_device_initcall(celleb_beat, celleb_publish_devices);
122machine_device_initcall(celleb_native, celleb_publish_devices);
123
124
125/*
126 * functions for Celleb-Beat
127 */
128static void __init celleb_setup_arch_beat(void)
92{ 129{
93#ifdef CONFIG_SPU_BASE 130#ifdef CONFIG_SPU_BASE
94 spu_priv1_ops = &spu_priv1_beat_ops; 131 spu_priv1_ops = &spu_priv1_beat_ops;
95 spu_management_ops = &spu_management_of_ops; 132 spu_management_ops = &spu_management_of_ops;
96#endif 133#endif
97 134
98#ifdef CONFIG_SMP 135#ifdef CONFIG_SMP
99 smp_init_celleb(); 136 smp_init_celleb();
100#endif 137#endif
101 138
102 /* init to some ~sane value until calibrate_delay() runs */ 139 celleb_setup_arch_common();
103 loops_per_jiffy = 50000000;
104
105#ifdef CONFIG_DUMMY_CONSOLE
106 conswitchp = &dummy_con;
107#endif
108} 140}
109 141
110static int __init celleb_probe(void) 142static int __init celleb_probe_beat(void)
111{ 143{
112 unsigned long root = of_get_flat_dt_root(); 144 unsigned long root = of_get_flat_dt_root();
113 145
114 if (!of_flat_dt_is_compatible(root, "Beat")) 146 if (!of_flat_dt_is_compatible(root, "Beat"))
115 return 0; 147 return 0;
116 148
117 powerpc_firmware_features |= FW_FEATURE_CELLEB_POSSIBLE; 149 powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS
150 | FW_FEATURE_BEAT | FW_FEATURE_LPAR;
118 hpte_init_beat_v3(); 151 hpte_init_beat_v3();
152
119 return 1; 153 return 1;
120} 154}
121 155
122static struct of_device_id celleb_bus_ids[] __initdata = {
123 { .type = "scc", },
124 { .type = "ioif", }, /* old style */
125 {},
126};
127 156
128static int __init celleb_publish_devices(void) 157/*
158 * functions for Celleb-native
159 */
160static void __init celleb_init_IRQ_native(void)
129{ 161{
130 if (!machine_is(celleb)) 162 iic_init_IRQ();
131 return 0; 163 spider_init_IRQ();
164}
132 165
133 /* Publish OF platform devices for southbridge IOs */ 166static void __init celleb_setup_arch_native(void)
134 of_platform_bus_probe(NULL, celleb_bus_ids, NULL); 167{
168#ifdef CONFIG_SPU_BASE
169 spu_priv1_ops = &spu_priv1_mmio_ops;
170 spu_management_ops = &spu_management_of_ops;
171#endif
135 172
136 celleb_pci_workaround_init(); 173 cbe_regs_init();
137 174
138 return 0; 175#ifdef CONFIG_CBE_RAS
176 cbe_ras_init();
177#endif
178
179#ifdef CONFIG_SMP
180 smp_init_cell();
181#endif
182
183 cbe_pervasive_init();
184
185 /* XXX: nvram initialization should be added */
186
187 celleb_setup_arch_common();
139} 188}
140device_initcall(celleb_publish_devices);
141 189
142define_machine(celleb) { 190static int __init celleb_probe_native(void)
143 .name = "Cell Reference Set", 191{
144 .probe = celleb_probe, 192 unsigned long root = of_get_flat_dt_root();
145 .setup_arch = celleb_setup_arch, 193
194 if (of_flat_dt_is_compatible(root, "Beat") ||
195 !of_flat_dt_is_compatible(root, "TOSHIBA,Celleb"))
196 return 0;
197
198 powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS;
199 hpte_init_native();
200
201 return 1;
202}
203
204
205/*
206 * machine definitions
207 */
208define_machine(celleb_beat) {
209 .name = "Cell Reference Set (Beat)",
210 .probe = celleb_probe_beat,
211 .setup_arch = celleb_setup_arch_beat,
146 .show_cpuinfo = celleb_show_cpuinfo, 212 .show_cpuinfo = celleb_show_cpuinfo,
147 .restart = beat_restart, 213 .restart = beat_restart,
148 .power_off = beat_power_off, 214 .power_off = beat_power_off,
@@ -167,3 +233,26 @@ define_machine(celleb) {
167 .machine_crash_shutdown = default_machine_crash_shutdown, 233 .machine_crash_shutdown = default_machine_crash_shutdown,
168#endif 234#endif
169}; 235};
236
237define_machine(celleb_native) {
238 .name = "Cell Reference Set (native)",
239 .probe = celleb_probe_native,
240 .setup_arch = celleb_setup_arch_native,
241 .show_cpuinfo = celleb_show_cpuinfo,
242 .restart = rtas_restart,
243 .power_off = rtas_power_off,
244 .halt = rtas_halt,
245 .get_boot_time = rtas_get_boot_time,
246 .get_rtc_time = rtas_get_rtc_time,
247 .set_rtc_time = rtas_set_rtc_time,
248 .calibrate_decr = generic_calibrate_decr,
249 .progress = celleb_progress,
250 .pci_probe_mode = celleb_pci_probe_mode,
251 .pci_setup_phb = celleb_setup_phb,
252 .init_IRQ = celleb_init_IRQ_native,
253#ifdef CONFIG_KEXEC
254 .machine_kexec = default_machine_kexec,
255 .machine_kexec_prepare = default_machine_kexec_prepare,
256 .machine_crash_shutdown = default_machine_crash_shutdown,
257#endif
258};
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index 0340a342f772..609c46db4a1b 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -198,7 +198,7 @@ static void __init setup_peg2(struct pci_controller *hose, struct device_node *d
198 printk ("RTAS supporting Pegasos OF not found, please upgrade" 198 printk ("RTAS supporting Pegasos OF not found, please upgrade"
199 " your firmware\n"); 199 " your firmware\n");
200 } 200 }
201 pci_assign_all_buses = 1; 201 ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
202 /* keep the reference to the root node */ 202 /* keep the reference to the root node */
203} 203}
204 204
@@ -354,7 +354,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105,
354 * mode as well. The same fixup must be done to the class-code property in 354 * mode as well. The same fixup must be done to the class-code property in
355 * the IDE node /pci@80000000/ide@C,1 355 * the IDE node /pci@80000000/ide@C,1
356 */ 356 */
357static void __devinit chrp_pci_fixup_vt8231_ata(struct pci_dev *viaide) 357static void chrp_pci_fixup_vt8231_ata(struct pci_dev *viaide)
358{ 358{
359 u8 progif; 359 u8 progif;
360 struct pci_dev *viaisa; 360 struct pci_dev *viaisa;
@@ -375,4 +375,4 @@ static void __devinit chrp_pci_fixup_vt8231_ata(struct pci_dev *viaide)
375 375
376 pci_dev_put(viaisa); 376 pci_dev_put(viaisa);
377} 377}
378DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, chrp_pci_fixup_vt8231_ata); 378DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, chrp_pci_fixup_vt8231_ata);
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 59306261f5b2..116babbaaf81 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -115,7 +115,7 @@ void chrp_show_cpuinfo(struct seq_file *m)
115 seq_printf(m, "machine\t\t: CHRP %s\n", model); 115 seq_printf(m, "machine\t\t: CHRP %s\n", model);
116 116
117 /* longtrail (goldengate) stuff */ 117 /* longtrail (goldengate) stuff */
118 if (!strncmp(model, "IBM,LongTrail", 13)) { 118 if (model && !strncmp(model, "IBM,LongTrail", 13)) {
119 /* VLSI VAS96011/12 `Golden Gate 2' */ 119 /* VLSI VAS96011/12 `Golden Gate 2' */
120 /* Memory banks */ 120 /* Memory banks */
121 sdramen = (in_le32(gg2_pci_config_base + GG2_PCI_DRAM_CTRL) 121 sdramen = (in_le32(gg2_pci_config_base + GG2_PCI_DRAM_CTRL)
@@ -203,15 +203,20 @@ static void __init sio_fixup_irq(const char *name, u8 device, u8 level,
203static void __init sio_init(void) 203static void __init sio_init(void)
204{ 204{
205 struct device_node *root; 205 struct device_node *root;
206 const char *model;
206 207
207 if ((root = of_find_node_by_path("/")) && 208 root = of_find_node_by_path("/");
208 !strncmp(of_get_property(root, "model", NULL), 209 if (!root)
209 "IBM,LongTrail", 13)) { 210 return;
211
212 model = of_get_property(root, "model", NULL);
213 if (model && !strncmp(model, "IBM,LongTrail", 13)) {
210 /* logical device 0 (KBC/Keyboard) */ 214 /* logical device 0 (KBC/Keyboard) */
211 sio_fixup_irq("keyboard", 0, 1, 2); 215 sio_fixup_irq("keyboard", 0, 1, 2);
212 /* select logical device 1 (KBC/Mouse) */ 216 /* select logical device 1 (KBC/Mouse) */
213 sio_fixup_irq("mouse", 1, 12, 2); 217 sio_fixup_irq("mouse", 1, 12, 2);
214 } 218 }
219
215 of_node_put(root); 220 of_node_put(root);
216} 221}
217 222
@@ -251,6 +256,57 @@ static void briq_restart(char *cmd)
251 for(;;); 256 for(;;);
252} 257}
253 258
259/*
260 * Per default, input/output-device points to the keyboard/screen
261 * If no card is installed, the built-in serial port is used as a fallback.
262 * But unfortunately, the firmware does not connect /chosen/{stdin,stdout}
263 * the the built-in serial node. Instead, a /failsafe node is created.
264 */
265static void chrp_init_early(void)
266{
267 struct device_node *node;
268 const char *property;
269
270 if (strstr(cmd_line, "console="))
271 return;
272 /* find the boot console from /chosen/stdout */
273 if (!of_chosen)
274 return;
275 node = of_find_node_by_path("/");
276 if (!node)
277 return;
278 property = of_get_property(node, "model", NULL);
279 if (!property)
280 goto out_put;
281 if (strcmp(property, "Pegasos2"))
282 goto out_put;
283 /* this is a Pegasos2 */
284 property = of_get_property(of_chosen, "linux,stdout-path", NULL);
285 if (!property)
286 goto out_put;
287 of_node_put(node);
288 node = of_find_node_by_path(property);
289 if (!node)
290 return;
291 property = of_get_property(node, "device_type", NULL);
292 if (!property)
293 goto out_put;
294 if (strcmp(property, "serial"))
295 goto out_put;
296 /*
297 * The 9pin connector is either /failsafe
298 * or /pci@80000000/isa@C/serial@i2F8
299 * The optional graphics card has also type 'serial' in VGA mode.
300 */
301 property = of_get_property(node, "name", NULL);
302 if (!property)
303 goto out_put;
304 if (!strcmp(property, "failsafe") || !strcmp(property, "serial"))
305 add_preferred_console("ttyS", 0, NULL);
306out_put:
307 of_node_put(node);
308}
309
254void __init chrp_setup_arch(void) 310void __init chrp_setup_arch(void)
255{ 311{
256 struct device_node *root = of_find_node_by_path("/"); 312 struct device_node *root = of_find_node_by_path("/");
@@ -594,6 +650,7 @@ define_machine(chrp) {
594 .probe = chrp_probe, 650 .probe = chrp_probe,
595 .setup_arch = chrp_setup_arch, 651 .setup_arch = chrp_setup_arch,
596 .init = chrp_init2, 652 .init = chrp_init2,
653 .init_early = chrp_init_early,
597 .show_cpuinfo = chrp_show_cpuinfo, 654 .show_cpuinfo = chrp_show_cpuinfo,
598 .init_IRQ = chrp_init_IRQ, 655 .init_IRQ = chrp_init_IRQ,
599 .restart = rtas_restart, 656 .restart = rtas_restart,
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index 8924095a7928..6c8083757938 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -9,6 +9,8 @@ config LINKSTATION
9 select FSL_SOC 9 select FSL_SOC
10 select PPC_UDBG_16550 if SERIAL_8250 10 select PPC_UDBG_16550 if SERIAL_8250
11 select DEFAULT_UIMAGE 11 select DEFAULT_UIMAGE
12 select MPC10X_OPENPIC
13 select MPC10X_BRIDGE
12 help 14 help
13 Select LINKSTATION if configuring for one of PPC- (MPC8241) 15 Select LINKSTATION if configuring for one of PPC- (MPC8241)
14 based NAS systems from Buffalo Technology. So far only 16 based NAS systems from Buffalo Technology. So far only
@@ -16,6 +18,19 @@ config LINKSTATION
16 Linkstation-I HD-HLAN and HD-HGLAN versions, and PPC-based 18 Linkstation-I HD-HLAN and HD-HGLAN versions, and PPC-based
17 Terastation systems should be supported too. 19 Terastation systems should be supported too.
18 20
21config STORCENTER
22 bool "IOMEGA StorCenter"
23 depends on EMBEDDED6xx
24 select MPIC
25 select FSL_SOC
26 select PPC_UDBG_16550 if SERIAL_8250
27 select WANT_DEVICE_TREE
28 select MPC10X_OPENPIC
29 select MPC10X_BRIDGE
30 help
31 Select STORCENTER if configuring for the iomega StorCenter
32 with an 8241 CPU in it.
33
19config MPC7448HPC2 34config MPC7448HPC2
20 bool "Freescale MPC7448HPC2(Taiga)" 35 bool "Freescale MPC7448HPC2(Taiga)"
21 depends on EMBEDDED6xx 36 depends on EMBEDDED6xx
@@ -23,6 +38,7 @@ config MPC7448HPC2
23 select DEFAULT_UIMAGE 38 select DEFAULT_UIMAGE
24 select PPC_UDBG_16550 39 select PPC_UDBG_16550
25 select WANT_DEVICE_TREE 40 select WANT_DEVICE_TREE
41 select TSI108_BRIDGE
26 help 42 help
27 Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga) 43 Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga)
28 platform 44 platform
@@ -33,6 +49,7 @@ config PPC_HOLLY
33 select TSI108_BRIDGE 49 select TSI108_BRIDGE
34 select PPC_UDBG_16550 50 select PPC_UDBG_16550
35 select WANT_DEVICE_TREE 51 select WANT_DEVICE_TREE
52 select TSI108_BRIDGE
36 help 53 help
37 Select PPC_HOLLY if configuring for an IBM 750GX/CL Eval 54 Select PPC_HOLLY if configuring for an IBM 750GX/CL Eval
38 Board with TSI108/9 bridge (Hickory/Holly) 55 Board with TSI108/9 bridge (Hickory/Holly)
@@ -48,17 +65,13 @@ config PPC_PRPMC2800
48 65
49config TSI108_BRIDGE 66config TSI108_BRIDGE
50 bool 67 bool
51 depends on MPC7448HPC2 || PPC_HOLLY
52 select PCI 68 select PCI
53 select MPIC 69 select MPIC
54 select MPIC_WEIRD 70 select MPIC_WEIRD
55 default y
56 71
57config MPC10X_BRIDGE 72config MPC10X_BRIDGE
58 bool 73 bool
59 depends on LINKSTATION
60 select PPC_INDIRECT_PCI 74 select PPC_INDIRECT_PCI
61 default y
62 75
63config MV64X60 76config MV64X60
64 bool 77 bool
@@ -67,8 +80,6 @@ config MV64X60
67 80
68config MPC10X_OPENPIC 81config MPC10X_OPENPIC
69 bool 82 bool
70 depends on LINKSTATION
71 default y
72 83
73config MPC10X_STORE_GATHERING 84config MPC10X_STORE_GATHERING
74 bool "Enable MPC10x store gathering" 85 bool "Enable MPC10x store gathering"
diff --git a/arch/powerpc/platforms/embedded6xx/Makefile b/arch/powerpc/platforms/embedded6xx/Makefile
index 844947cfc5db..06524d3ffd2e 100644
--- a/arch/powerpc/platforms/embedded6xx/Makefile
+++ b/arch/powerpc/platforms/embedded6xx/Makefile
@@ -3,5 +3,6 @@
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_STORCENTER) += storcenter.o
6obj-$(CONFIG_PPC_HOLLY) += holly.o 7obj-$(CONFIG_PPC_HOLLY) += holly.o
7obj-$(CONFIG_PPC_PRPMC2800) += prpmc2800.o 8obj-$(CONFIG_PPC_PRPMC2800) += prpmc2800.o
diff --git a/arch/powerpc/platforms/embedded6xx/holly.c b/arch/powerpc/platforms/embedded6xx/holly.c
index b6de2b5223dd..b21fde589ca7 100644
--- a/arch/powerpc/platforms/embedded6xx/holly.c
+++ b/arch/powerpc/platforms/embedded6xx/holly.c
@@ -20,12 +20,12 @@
20#include <linux/console.h> 20#include <linux/console.h>
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/irq.h> 22#include <linux/irq.h>
23#include <linux/ide.h>
24#include <linux/seq_file.h> 23#include <linux/seq_file.h>
25#include <linux/root_dev.h> 24#include <linux/root_dev.h>
26#include <linux/serial.h> 25#include <linux/serial.h>
27#include <linux/tty.h> 26#include <linux/tty.h>
28#include <linux/serial_core.h> 27#include <linux/serial_core.h>
28#include <linux/of_platform.h>
29 29
30#include <asm/system.h> 30#include <asm/system.h>
31#include <asm/time.h> 31#include <asm/time.h>
@@ -39,7 +39,6 @@
39#include <asm/tsi108_irq.h> 39#include <asm/tsi108_irq.h>
40#include <asm/tsi108_pci.h> 40#include <asm/tsi108_pci.h>
41#include <asm/mpic.h> 41#include <asm/mpic.h>
42#include <asm/of_platform.h>
43 42
44#undef DEBUG 43#undef DEBUG
45 44
diff --git a/arch/powerpc/platforms/embedded6xx/ls_uart.c b/arch/powerpc/platforms/embedded6xx/ls_uart.c
index c99264cedda5..9d891bd5df5a 100644
--- a/arch/powerpc/platforms/embedded6xx/ls_uart.c
+++ b/arch/powerpc/platforms/embedded6xx/ls_uart.c
@@ -117,9 +117,6 @@ static int __init ls_uarts_init(void)
117 phys_addr_t phys_addr; 117 phys_addr_t phys_addr;
118 int len; 118 int len;
119 119
120 if (!machine_is(linkstation))
121 return 0;
122
123 avr = of_find_node_by_path("/soc10x/serial@80004500"); 120 avr = of_find_node_by_path("/soc10x/serial@80004500");
124 if (!avr) 121 if (!avr)
125 return -EINVAL; 122 return -EINVAL;
@@ -142,4 +139,4 @@ static int __init ls_uarts_init(void)
142 return 0; 139 return 0;
143} 140}
144 141
145late_initcall(ls_uarts_init); 142machine_late_initcall(linkstation, ls_uarts_init);
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
index a2c04b9d42b1..d4f8bf581e3a 100644
--- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
+++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
@@ -53,8 +53,6 @@
53 53
54#define MPC7448HPC2_PCI_CFG_PHYS 0xfb000000 54#define MPC7448HPC2_PCI_CFG_PHYS 0xfb000000
55 55
56extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
57
58int mpc7448_hpc2_exclude_device(struct pci_controller *hose, 56int mpc7448_hpc2_exclude_device(struct pci_controller *hose,
59 u_char bus, u_char devfn) 57 u_char bus, u_char devfn)
60{ 58{
diff --git a/arch/powerpc/platforms/embedded6xx/storcenter.c b/arch/powerpc/platforms/embedded6xx/storcenter.c
new file mode 100644
index 000000000000..e12e9d298716
--- /dev/null
+++ b/arch/powerpc/platforms/embedded6xx/storcenter.c
@@ -0,0 +1,192 @@
1/*
2 * Board setup routines for the storcenter
3 *
4 * Copyright 2007 (C) Oyvind Repvik (nail@nslu2-linux.org)
5 * Copyright 2007 Andy Wilcox, Jon Loeliger
6 *
7 * Based on linkstation.c by G. Liakhovetski
8 *
9 * This file is licensed under the terms of the GNU General Public License
10 * version 2. This program is licensed "as is" without any warranty of
11 * any kind, whether express or implied.
12 */
13
14#include <linux/kernel.h>
15#include <linux/pci.h>
16#include <linux/initrd.h>
17#include <linux/mtd/physmap.h>
18#include <linux/of_platform.h>
19
20#include <asm/system.h>
21#include <asm/time.h>
22#include <asm/prom.h>
23#include <asm/mpic.h>
24#include <asm/pci-bridge.h>
25
26#include "mpc10x.h"
27
28
29#ifdef CONFIG_MTD_PHYSMAP
30static struct mtd_partition storcenter_physmap_partitions[] = {
31 {
32 .name = "kernel",
33 .offset = 0x000000,
34 .size = 0x170000,
35 },
36 {
37 .name = "rootfs",
38 .offset = 0x170000,
39 .size = 0x590000,
40 },
41 {
42 .name = "uboot",
43 .offset = 0x700000,
44 .size = 0x040000,
45 },
46 {
47 .name = "config",
48 .offset = 0x740000,
49 .size = 0x0c0000,
50 },
51};
52#endif
53
54
55static __initdata struct of_device_id storcenter_of_bus[] = {
56 { .name = "soc", },
57 {},
58};
59
60static int __init storcenter_device_probe(void)
61{
62 of_platform_bus_probe(NULL, storcenter_of_bus, NULL);
63 return 0;
64}
65machine_device_initcall(storcenter, storcenter_device_probe);
66
67
68static int __init storcenter_add_bridge(struct device_node *dev)
69{
70#ifdef CONFIG_PCI
71 int len;
72 struct pci_controller *hose;
73 const int *bus_range;
74
75 printk("Adding PCI host bridge %s\n", dev->full_name);
76
77 hose = pcibios_alloc_controller(dev);
78 if (hose == NULL)
79 return -ENOMEM;
80
81 bus_range = of_get_property(dev, "bus-range", &len);
82 hose->first_busno = bus_range ? bus_range[0] : 0;
83 hose->last_busno = bus_range ? bus_range[1] : 0xff;
84
85 setup_indirect_pci(hose, MPC10X_MAPB_CNFG_ADDR, MPC10X_MAPB_CNFG_DATA, 0);
86
87 /* Interpret the "ranges" property */
88 /* This also maps the I/O region and sets isa_io/mem_base */
89 pci_process_bridge_OF_ranges(hose, dev, 1);
90#endif
91
92 return 0;
93}
94
95static void __init storcenter_setup_arch(void)
96{
97 struct device_node *np;
98
99#ifdef CONFIG_MTD_PHYSMAP
100 physmap_set_partitions(storcenter_physmap_partitions,
101 ARRAY_SIZE(storcenter_physmap_partitions));
102#endif
103
104 /* Lookup PCI host bridges */
105 for_each_compatible_node(np, "pci", "mpc10x-pci")
106 storcenter_add_bridge(np);
107
108 printk(KERN_INFO "IOMEGA StorCenter\n");
109}
110
111/*
112 * Interrupt setup and service. Interrrupts on the turbostation come
113 * from the four PCI slots plus onboard 8241 devices: I2C, DUART.
114 */
115static void __init storcenter_init_IRQ(void)
116{
117 struct mpic *mpic;
118 struct device_node *dnp;
119 const void *prop;
120 int size;
121 phys_addr_t paddr;
122
123 dnp = of_find_node_by_type(NULL, "open-pic");
124 if (dnp == NULL)
125 return;
126
127 prop = of_get_property(dnp, "reg", &size);
128 if (prop == NULL) {
129 of_node_put(dnp);
130 return;
131 }
132
133 paddr = (phys_addr_t)of_translate_address(dnp, prop);
134 mpic = mpic_alloc(dnp, paddr, MPIC_PRIMARY | MPIC_WANTS_RESET,
135 4, 32, " EPIC ");
136
137 of_node_put(dnp);
138
139 BUG_ON(mpic == NULL);
140
141 /* PCI IRQs */
142 /*
143 * 2.6.12 patch:
144 * openpic_set_sources(0, 5, OpenPIC_Addr + 0x10200);
145 * openpic_set_sources(5, 2, OpenPIC_Addr + 0x11120);
146 * first_irq, num_irqs, __iomem first_ISR
147 * o_ss: i, src: 0, fdf50200
148 * o_ss: i, src: 1, fdf50220
149 * o_ss: i, src: 2, fdf50240
150 * o_ss: i, src: 3, fdf50260
151 * o_ss: i, src: 4, fdf50280
152 * o_ss: i, src: 5, fdf51120
153 * o_ss: i, src: 6, fdf51140
154 */
155 mpic_assign_isu(mpic, 0, paddr + 0x10200);
156 mpic_assign_isu(mpic, 1, paddr + 0x10220);
157 mpic_assign_isu(mpic, 2, paddr + 0x10240);
158 mpic_assign_isu(mpic, 3, paddr + 0x10260);
159 mpic_assign_isu(mpic, 4, paddr + 0x10280);
160 mpic_assign_isu(mpic, 5, paddr + 0x11120);
161 mpic_assign_isu(mpic, 6, paddr + 0x11140);
162
163 mpic_init(mpic);
164}
165
166static void storcenter_restart(char *cmd)
167{
168 local_irq_disable();
169
170 /* Set exception prefix high - to the firmware */
171 _nmask_and_or_msr(0, MSR_IP);
172
173 /* Wait for reset to happen */
174 for (;;) ;
175}
176
177static int __init storcenter_probe(void)
178{
179 unsigned long root = of_get_flat_dt_root();
180
181 return of_flat_dt_is_compatible(root, "storcenter");
182}
183
184define_machine(storcenter){
185 .name = "IOMEGA StorCenter",
186 .probe = storcenter_probe,
187 .setup_arch = storcenter_setup_arch,
188 .init_IRQ = storcenter_init_IRQ,
189 .get_irq = mpic_get_irq,
190 .restart = storcenter_restart,
191 .calibrate_decr = generic_calibrate_decr,
192};
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile
index a65f1b44abf8..cc7161ff1666 100644
--- a/arch/powerpc/platforms/iseries/Makefile
+++ b/arch/powerpc/platforms/iseries/Makefile
@@ -5,7 +5,7 @@ extra-y += dt.o
5obj-y += exception.o 5obj-y += exception.o
6obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \ 6obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \
7 hvcall.o proc.o htab.o iommu.o misc.o irq.o 7 hvcall.o proc.o htab.o iommu.o misc.o irq.o
8obj-$(CONFIG_PCI) += pci.o vpdinfo.o 8obj-$(CONFIG_PCI) += pci.o
9obj-$(CONFIG_SMP) += smp.o 9obj-$(CONFIG_SMP) += smp.o
10obj-$(CONFIG_VIOPATH) += viopath.o vio.o 10obj-$(CONFIG_VIOPATH) += viopath.o vio.o
11obj-$(CONFIG_MODULES) += ksyms.o 11obj-$(CONFIG_MODULES) += ksyms.o
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index 49e9c664ea89..6a0c6f6675cd 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -163,8 +163,10 @@ static struct iommu_table *iommu_table_find(struct iommu_table * tbl)
163 (it->it_type == TCE_PCI) && 163 (it->it_type == TCE_PCI) &&
164 (it->it_offset == tbl->it_offset) && 164 (it->it_offset == tbl->it_offset) &&
165 (it->it_index == tbl->it_index) && 165 (it->it_index == tbl->it_index) &&
166 (it->it_size == tbl->it_size)) 166 (it->it_size == tbl->it_size)) {
167 of_node_put(node);
167 return it; 168 return it;
169 }
168 } 170 }
169 return NULL; 171 return NULL;
170} 172}
diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c
index 275f49449839..e5b40e3e0082 100644
--- a/arch/powerpc/platforms/iseries/lpevents.c
+++ b/arch/powerpc/platforms/iseries/lpevents.c
@@ -239,7 +239,7 @@ int HvLpEvent_unregisterHandler(HvLpEvent_Type eventType)
239 * other CPUs, and that the deleted handler isn't 239 * other CPUs, and that the deleted handler isn't
240 * still running on another CPU when we return. 240 * still running on another CPU when we return.
241 */ 241 */
242 synchronize_rcu(); 242 synchronize_sched();
243 return 0; 243 return 0;
244 } 244 }
245 } 245 }
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index da87162000f0..cc562e4c2f32 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (C) 2001 Allan Trautman, IBM Corporation 2 * Copyright (C) 2001 Allan Trautman, IBM Corporation
3 * Copyright (C) 2005,2007 Stephen Rothwell, IBM Corp
3 * 4 *
4 * iSeries specific routines for PCI. 5 * iSeries specific routines for PCI.
5 * 6 *
@@ -19,13 +20,18 @@
19 * along with this program; if not, write to the Free Software 20 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */ 22 */
23
24#undef DEBUG
25
22#include <linux/kernel.h> 26#include <linux/kernel.h>
23#include <linux/list.h> 27#include <linux/list.h>
24#include <linux/string.h> 28#include <linux/string.h>
25#include <linux/init.h> 29#include <linux/init.h>
26#include <linux/module.h> 30#include <linux/module.h>
27#include <linux/pci.h> 31#include <linux/pci.h>
32#include <linux/of.h>
28 33
34#include <asm/types.h>
29#include <asm/io.h> 35#include <asm/io.h>
30#include <asm/irq.h> 36#include <asm/irq.h>
31#include <asm/prom.h> 37#include <asm/prom.h>
@@ -35,6 +41,7 @@
35#include <asm/abs_addr.h> 41#include <asm/abs_addr.h>
36#include <asm/firmware.h> 42#include <asm/firmware.h>
37 43
44#include <asm/iseries/hv_types.h>
38#include <asm/iseries/hv_call_xm.h> 45#include <asm/iseries/hv_call_xm.h>
39#include <asm/iseries/mf.h> 46#include <asm/iseries/mf.h>
40#include <asm/iseries/iommu.h> 47#include <asm/iseries/iommu.h>
@@ -45,15 +52,8 @@
45#include "pci.h" 52#include "pci.h"
46#include "call_pci.h" 53#include "call_pci.h"
47 54
48/* 55#define PCI_RETRY_MAX 3
49 * Forward declares of prototypes. 56static int limit_pci_retries = 1; /* Set Retry Error on. */
50 */
51static struct device_node *find_Device_Node(int bus, int devfn);
52
53static int Pci_Retry_Max = 3; /* Only retry 3 times */
54static int Pci_Error_Flag = 1; /* Set Retry Error on. */
55
56static struct pci_ops iSeries_pci_ops;
57 57
58/* 58/*
59 * Table defines 59 * Table defines
@@ -62,6 +62,7 @@ static struct pci_ops iSeries_pci_ops;
62#define IOMM_TABLE_MAX_ENTRIES 1024 62#define IOMM_TABLE_MAX_ENTRIES 1024
63#define IOMM_TABLE_ENTRY_SIZE 0x0000000000400000UL 63#define IOMM_TABLE_ENTRY_SIZE 0x0000000000400000UL
64#define BASE_IO_MEMORY 0xE000000000000000UL 64#define BASE_IO_MEMORY 0xE000000000000000UL
65#define END_IO_MEMORY 0xEFFFFFFFFFFFFFFFUL
65 66
66static unsigned long max_io_memory = BASE_IO_MEMORY; 67static unsigned long max_io_memory = BASE_IO_MEMORY;
67static long current_iomm_table_entry; 68static long current_iomm_table_entry;
@@ -70,12 +71,237 @@ static long current_iomm_table_entry;
70 * Lookup Tables. 71 * Lookup Tables.
71 */ 72 */
72static struct device_node *iomm_table[IOMM_TABLE_MAX_ENTRIES]; 73static struct device_node *iomm_table[IOMM_TABLE_MAX_ENTRIES];
73static u8 iobar_table[IOMM_TABLE_MAX_ENTRIES]; 74static u64 ds_addr_table[IOMM_TABLE_MAX_ENTRIES];
74 75
75static const char pci_io_text[] = "iSeries PCI I/O";
76static DEFINE_SPINLOCK(iomm_table_lock); 76static DEFINE_SPINLOCK(iomm_table_lock);
77 77
78/* 78/*
79 * Generate a Direct Select Address for the Hypervisor
80 */
81static inline u64 iseries_ds_addr(struct device_node *node)
82{
83 struct pci_dn *pdn = PCI_DN(node);
84 const u32 *sbp = of_get_property(node, "linux,subbus", NULL);
85
86 return ((u64)pdn->busno << 48) + ((u64)(sbp ? *sbp : 0) << 40)
87 + ((u64)0x10 << 32);
88}
89
90/*
91 * Size of Bus VPD data
92 */
93#define BUS_VPDSIZE 1024
94
95/*
96 * Bus Vpd Tags
97 */
98#define VPD_END_OF_AREA 0x79
99#define VPD_ID_STRING 0x82
100#define VPD_VENDOR_AREA 0x84
101
102/*
103 * Mfg Area Tags
104 */
105#define VPD_FRU_FRAME_ID 0x4649 /* "FI" */
106#define VPD_SLOT_MAP_FORMAT 0x4D46 /* "MF" */
107#define VPD_SLOT_MAP 0x534D /* "SM" */
108
109/*
110 * Structures of the areas
111 */
112struct mfg_vpd_area {
113 u16 tag;
114 u8 length;
115 u8 data1;
116 u8 data2;
117};
118#define MFG_ENTRY_SIZE 3
119
120struct slot_map {
121 u8 agent;
122 u8 secondary_agent;
123 u8 phb;
124 char card_location[3];
125 char parms[8];
126 char reserved[2];
127};
128#define SLOT_ENTRY_SIZE 16
129
130/*
131 * Parse the Slot Area
132 */
133static void __init iseries_parse_slot_area(struct slot_map *map, int len,
134 HvAgentId agent, u8 *phb, char card[4])
135{
136 /*
137 * Parse Slot label until we find the one requested
138 */
139 while (len > 0) {
140 if (map->agent == agent) {
141 /*
142 * If Phb wasn't found, grab the entry first one found.
143 */
144 if (*phb == 0xff)
145 *phb = map->phb;
146 /* Found it, extract the data. */
147 if (map->phb == *phb) {
148 memcpy(card, &map->card_location, 3);
149 card[3] = 0;
150 break;
151 }
152 }
153 /* Point to the next Slot */
154 map = (struct slot_map *)((char *)map + SLOT_ENTRY_SIZE);
155 len -= SLOT_ENTRY_SIZE;
156 }
157}
158
159/*
160 * Parse the Mfg Area
161 */
162static void __init iseries_parse_mfg_area(struct mfg_vpd_area *area, int len,
163 HvAgentId agent, u8 *phb, u8 *frame, char card[4])
164{
165 u16 slot_map_fmt = 0;
166
167 /* Parse Mfg Data */
168 while (len > 0) {
169 int mfg_tag_len = area->length;
170 /* Frame ID (FI 4649020310 ) */
171 if (area->tag == VPD_FRU_FRAME_ID)
172 *frame = area->data1;
173 /* Slot Map Format (MF 4D46020004 ) */
174 else if (area->tag == VPD_SLOT_MAP_FORMAT)
175 slot_map_fmt = (area->data1 * 256)
176 + area->data2;
177 /* Slot Map (SM 534D90 */
178 else if (area->tag == VPD_SLOT_MAP) {
179 struct slot_map *slot_map;
180
181 if (slot_map_fmt == 0x1004)
182 slot_map = (struct slot_map *)((char *)area
183 + MFG_ENTRY_SIZE + 1);
184 else
185 slot_map = (struct slot_map *)((char *)area
186 + MFG_ENTRY_SIZE);
187 iseries_parse_slot_area(slot_map, mfg_tag_len,
188 agent, phb, card);
189 }
190 /*
191 * Point to the next Mfg Area
192 * Use defined size, sizeof give wrong answer
193 */
194 area = (struct mfg_vpd_area *)((char *)area + mfg_tag_len
195 + MFG_ENTRY_SIZE);
196 len -= (mfg_tag_len + MFG_ENTRY_SIZE);
197 }
198}
199
200/*
201 * Look for "BUS".. Data is not Null terminated.
202 * PHBID of 0xFF indicates PHB was not found in VPD Data.
203 */
204static u8 __init iseries_parse_phbid(u8 *area, int len)
205{
206 while (len > 0) {
207 if ((*area == 'B') && (*(area + 1) == 'U')
208 && (*(area + 2) == 'S')) {
209 area += 3;
210 while (*area == ' ')
211 area++;
212 return *area & 0x0F;
213 }
214 area++;
215 len--;
216 }
217 return 0xff;
218}
219
220/*
221 * Parse out the VPD Areas
222 */
223static void __init iseries_parse_vpd(u8 *data, int data_len,
224 HvAgentId agent, u8 *frame, char card[4])
225{
226 u8 phb = 0xff;
227
228 while (data_len > 0) {
229 int len;
230 u8 tag = *data;
231
232 if (tag == VPD_END_OF_AREA)
233 break;
234 len = *(data + 1) + (*(data + 2) * 256);
235 data += 3;
236 data_len -= 3;
237 if (tag == VPD_ID_STRING)
238 phb = iseries_parse_phbid(data, len);
239 else if (tag == VPD_VENDOR_AREA)
240 iseries_parse_mfg_area((struct mfg_vpd_area *)data, len,
241 agent, &phb, frame, card);
242 /* Point to next Area. */
243 data += len;
244 data_len -= len;
245 }
246}
247
248static int __init iseries_get_location_code(u16 bus, HvAgentId agent,
249 u8 *frame, char card[4])
250{
251 int status = 0;
252 int bus_vpd_len = 0;
253 u8 *bus_vpd = kmalloc(BUS_VPDSIZE, GFP_KERNEL);
254
255 if (bus_vpd == NULL) {
256 printk("PCI: Bus VPD Buffer allocation failure.\n");
257 return 0;
258 }
259 bus_vpd_len = HvCallPci_getBusVpd(bus, iseries_hv_addr(bus_vpd),
260 BUS_VPDSIZE);
261 if (bus_vpd_len == 0) {
262 printk("PCI: Bus VPD Buffer zero length.\n");
263 goto out_free;
264 }
265 /* printk("PCI: bus_vpd: %p, %d\n",bus_vpd, bus_vpd_len); */
266 /* Make sure this is what I think it is */
267 if (*bus_vpd != VPD_ID_STRING) {
268 printk("PCI: Bus VPD Buffer missing starting tag.\n");
269 goto out_free;
270 }
271 iseries_parse_vpd(bus_vpd, bus_vpd_len, agent, frame, card);
272 status = 1;
273out_free:
274 kfree(bus_vpd);
275 return status;
276}
277
278/*
279 * Prints the device information.
280 * - Pass in pci_dev* pointer to the device.
281 * - Pass in the device count
282 *
283 * Format:
284 * PCI: Bus 0, Device 26, Vendor 0x12AE Frame 1, Card C10 Ethernet
285 * controller
286 */
287static void __init iseries_device_information(struct pci_dev *pdev,
288 u16 bus, HvSubBusNumber subbus)
289{
290 u8 frame = 0;
291 char card[4];
292 HvAgentId agent;
293
294 agent = ISERIES_PCI_AGENTID(ISERIES_GET_DEVICE_FROM_SUBBUS(subbus),
295 ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus));
296
297 if (iseries_get_location_code(bus, agent, &frame, card)) {
298 printk(KERN_INFO "PCI: %s, Vendor %04X Frame%3d, "
299 "Card %4s 0x%04X\n", pci_name(pdev), pdev->vendor,
300 frame, card, (int)(pdev->class >> 8));
301 }
302}
303
304/*
79 * iomm_table_allocate_entry 305 * iomm_table_allocate_entry
80 * 306 *
81 * Adds pci_dev entry in address translation table 307 * Adds pci_dev entry in address translation table
@@ -87,7 +313,7 @@ static DEFINE_SPINLOCK(iomm_table_lock);
87 * - CurrentIndex is incremented to keep track of the last entry. 313 * - CurrentIndex is incremented to keep track of the last entry.
88 * - Builds the resource entry for allocated BARs. 314 * - Builds the resource entry for allocated BARs.
89 */ 315 */
90static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num) 316static void __init iomm_table_allocate_entry(struct pci_dev *dev, int bar_num)
91{ 317{
92 struct resource *bar_res = &dev->resource[bar_num]; 318 struct resource *bar_res = &dev->resource[bar_num];
93 long bar_size = pci_resource_len(dev, bar_num); 319 long bar_size = pci_resource_len(dev, bar_num);
@@ -101,7 +327,6 @@ static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num)
101 * Set Resource values. 327 * Set Resource values.
102 */ 328 */
103 spin_lock(&iomm_table_lock); 329 spin_lock(&iomm_table_lock);
104 bar_res->name = pci_io_text;
105 bar_res->start = BASE_IO_MEMORY + 330 bar_res->start = BASE_IO_MEMORY +
106 IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry; 331 IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
107 bar_res->end = bar_res->start + bar_size - 1; 332 bar_res->end = bar_res->start + bar_size - 1;
@@ -110,7 +335,8 @@ static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num)
110 */ 335 */
111 while (bar_size > 0 ) { 336 while (bar_size > 0 ) {
112 iomm_table[current_iomm_table_entry] = dev->sysdata; 337 iomm_table[current_iomm_table_entry] = dev->sysdata;
113 iobar_table[current_iomm_table_entry] = bar_num; 338 ds_addr_table[current_iomm_table_entry] =
339 iseries_ds_addr(dev->sysdata) | (bar_num << 24);
114 bar_size -= IOMM_TABLE_ENTRY_SIZE; 340 bar_size -= IOMM_TABLE_ENTRY_SIZE;
115 ++current_iomm_table_entry; 341 ++current_iomm_table_entry;
116 } 342 }
@@ -130,7 +356,7 @@ static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num)
130 * - Loops through The Bar resources(0 - 5) including the ROM 356 * - Loops through The Bar resources(0 - 5) including the ROM
131 * is resource(6). 357 * is resource(6).
132 */ 358 */
133static void allocate_device_bars(struct pci_dev *dev) 359static void __init allocate_device_bars(struct pci_dev *dev)
134{ 360{
135 int bar_num; 361 int bar_num;
136 362
@@ -145,79 +371,19 @@ static void allocate_device_bars(struct pci_dev *dev)
145 * PCI: Read Vendor Failed 0x18.58.10 Rc: 0x00xx 371 * PCI: Read Vendor Failed 0x18.58.10 Rc: 0x00xx
146 * PCI: Connect Bus Unit Failed 0x18.58.10 Rc: 0x00xx 372 * PCI: Connect Bus Unit Failed 0x18.58.10 Rc: 0x00xx
147 */ 373 */
148static void pci_Log_Error(char *Error_Text, int Bus, int SubBus, 374static void pci_log_error(char *error, int bus, int subbus,
149 int AgentId, int HvRc) 375 int agent, int hv_res)
150{ 376{
151 if (HvRc == 0x0302) 377 if (hv_res == 0x0302)
152 return; 378 return;
153 printk(KERN_ERR "PCI: %s Failed: 0x%02X.%02X.%02X Rc: 0x%04X", 379 printk(KERN_ERR "PCI: %s Failed: 0x%02X.%02X.%02X Rc: 0x%04X",
154 Error_Text, Bus, SubBus, AgentId, HvRc); 380 error, bus, subbus, agent, hv_res);
155}
156
157/*
158 * iSeries_pci_final_fixup(void)
159 */
160void __init iSeries_pci_final_fixup(void)
161{
162 struct pci_dev *pdev = NULL;
163 struct device_node *node;
164 int DeviceCount = 0;
165
166 /* Fix up at the device node and pci_dev relationship */
167 mf_display_src(0xC9000100);
168
169 printk("pcibios_final_fixup\n");
170 for_each_pci_dev(pdev) {
171 node = find_Device_Node(pdev->bus->number, pdev->devfn);
172 printk("pci dev %p (%x.%x), node %p\n", pdev,
173 pdev->bus->number, pdev->devfn, node);
174
175 if (node != NULL) {
176 struct pci_dn *pdn = PCI_DN(node);
177 const u32 *agent;
178
179 agent = of_get_property(node, "linux,agent-id", NULL);
180 if ((pdn != NULL) && (agent != NULL)) {
181 u8 irq = iSeries_allocate_IRQ(pdn->busno, 0,
182 pdn->bussubno);
183 int err;
184
185 err = HvCallXm_connectBusUnit(pdn->busno, pdn->bussubno,
186 *agent, irq);
187 if (err)
188 pci_Log_Error("Connect Bus Unit",
189 pdn->busno, pdn->bussubno, *agent, err);
190 else {
191 err = HvCallPci_configStore8(pdn->busno, pdn->bussubno,
192 *agent,
193 PCI_INTERRUPT_LINE,
194 irq);
195 if (err)
196 pci_Log_Error("PciCfgStore Irq Failed!",
197 pdn->busno, pdn->bussubno, *agent, err);
198 }
199 if (!err)
200 pdev->irq = irq;
201 }
202
203 ++DeviceCount;
204 pdev->sysdata = (void *)node;
205 PCI_DN(node)->pcidev = pdev;
206 allocate_device_bars(pdev);
207 iSeries_Device_Information(pdev, DeviceCount);
208 iommu_devnode_init_iSeries(pdev, node);
209 } else
210 printk("PCI: Device Tree not found for 0x%016lX\n",
211 (unsigned long)pdev);
212 }
213 iSeries_activate_IRQs();
214 mf_display_src(0xC9000200);
215} 381}
216 382
217/* 383/*
218 * Look down the chain to find the matching Device Device 384 * Look down the chain to find the matching Device Device
219 */ 385 */
220static struct device_node *find_Device_Node(int bus, int devfn) 386static struct device_node *find_device_node(int bus, int devfn)
221{ 387{
222 struct device_node *node; 388 struct device_node *node;
223 389
@@ -230,22 +396,66 @@ static struct device_node *find_Device_Node(int bus, int devfn)
230 return NULL; 396 return NULL;
231} 397}
232 398
233#if 0
234/* 399/*
235 * Returns the device node for the passed pci_dev 400 * iSeries_pcibios_fixup_resources
236 * Sanity Check Node PciDev to passed pci_dev 401 *
237 * If none is found, returns a NULL which the client must handle. 402 * Fixes up all resources for devices
238 */ 403 */
239static struct device_node *get_Device_Node(struct pci_dev *pdev) 404void __init iSeries_pcibios_fixup_resources(struct pci_dev *pdev)
240{ 405{
406 const u32 *agent;
407 const u32 *sub_bus;
408 unsigned char bus = pdev->bus->number;
241 struct device_node *node; 409 struct device_node *node;
410 int i;
411
412 node = find_device_node(bus, pdev->devfn);
413 pr_debug("PCI: iSeries %s, pdev %p, node %p\n",
414 pci_name(pdev), pdev, node);
415 if (!node) {
416 printk("PCI: %s disabled, device tree entry not found !\n",
417 pci_name(pdev));
418 for (i = 0; i <= PCI_ROM_RESOURCE; i++)
419 pdev->resource[i].flags = 0;
420 return;
421 }
422 sub_bus = of_get_property(node, "linux,subbus", NULL);
423 agent = of_get_property(node, "linux,agent-id", NULL);
424 if (agent && sub_bus) {
425 u8 irq = iSeries_allocate_IRQ(bus, 0, *sub_bus);
426 int err;
427
428 err = HvCallXm_connectBusUnit(bus, *sub_bus, *agent, irq);
429 if (err)
430 pci_log_error("Connect Bus Unit",
431 bus, *sub_bus, *agent, err);
432 else {
433 err = HvCallPci_configStore8(bus, *sub_bus,
434 *agent, PCI_INTERRUPT_LINE, irq);
435 if (err)
436 pci_log_error("PciCfgStore Irq Failed!",
437 bus, *sub_bus, *agent, err);
438 else
439 pdev->irq = irq;
440 }
441 }
242 442
243 node = pdev->sysdata; 443 pdev->sysdata = node;
244 if (node == NULL || PCI_DN(node)->pcidev != pdev) 444 allocate_device_bars(pdev);
245 node = find_Device_Node(pdev->bus->number, pdev->devfn); 445 iseries_device_information(pdev, bus, *sub_bus);
246 return node; 446 iommu_devnode_init_iSeries(pdev, node);
447}
448
449/*
450 * iSeries_pci_final_fixup(void)
451 */
452void __init iSeries_pci_final_fixup(void)
453{
454 /* Fix up at the device node and pci_dev relationship */
455 mf_display_src(0xC9000100);
456 iSeries_activate_IRQs();
457 mf_display_src(0xC9000200);
247} 458}
248#endif
249 459
250/* 460/*
251 * Config space read and write functions. 461 * Config space read and write functions.
@@ -269,7 +479,7 @@ static u64 hv_cfg_write_func[4] = {
269static int iSeries_pci_read_config(struct pci_bus *bus, unsigned int devfn, 479static int iSeries_pci_read_config(struct pci_bus *bus, unsigned int devfn,
270 int offset, int size, u32 *val) 480 int offset, int size, u32 *val)
271{ 481{
272 struct device_node *node = find_Device_Node(bus->number, devfn); 482 struct device_node *node = find_device_node(bus->number, devfn);
273 u64 fn; 483 u64 fn;
274 struct HvCallPci_LoadReturn ret; 484 struct HvCallPci_LoadReturn ret;
275 485
@@ -299,7 +509,7 @@ static int iSeries_pci_read_config(struct pci_bus *bus, unsigned int devfn,
299static int iSeries_pci_write_config(struct pci_bus *bus, unsigned int devfn, 509static int iSeries_pci_write_config(struct pci_bus *bus, unsigned int devfn,
300 int offset, int size, u32 val) 510 int offset, int size, u32 val)
301{ 511{
302 struct device_node *node = find_Device_Node(bus->number, devfn); 512 struct device_node *node = find_device_node(bus->number, devfn);
303 u64 fn; 513 u64 fn;
304 u64 ret; 514 u64 ret;
305 515
@@ -331,22 +541,22 @@ static struct pci_ops iSeries_pci_ops = {
331 * PCI: Device 23.90 ReadL Retry( 1) 541 * PCI: Device 23.90 ReadL Retry( 1)
332 * PCI: Device 23.90 ReadL Retry Successful(1) 542 * PCI: Device 23.90 ReadL Retry Successful(1)
333 */ 543 */
334static int CheckReturnCode(char *TextHdr, struct device_node *DevNode, 544static int check_return_code(char *type, struct device_node *dn,
335 int *retry, u64 ret) 545 int *retry, u64 ret)
336{ 546{
337 if (ret != 0) { 547 if (ret != 0) {
338 struct pci_dn *pdn = PCI_DN(DevNode); 548 struct pci_dn *pdn = PCI_DN(dn);
339 549
340 (*retry)++; 550 (*retry)++;
341 printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n", 551 printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n",
342 TextHdr, pdn->busno, pdn->devfn, 552 type, pdn->busno, pdn->devfn,
343 *retry, (int)ret); 553 *retry, (int)ret);
344 /* 554 /*
345 * Bump the retry and check for retry count exceeded. 555 * Bump the retry and check for retry count exceeded.
346 * If, Exceeded, panic the system. 556 * If, Exceeded, panic the system.
347 */ 557 */
348 if (((*retry) > Pci_Retry_Max) && 558 if (((*retry) > PCI_RETRY_MAX) &&
349 (Pci_Error_Flag > 0)) { 559 (limit_pci_retries > 0)) {
350 mf_display_src(0xB6000103); 560 mf_display_src(0xB6000103);
351 panic_timeout = 0; 561 panic_timeout = 0;
352 panic("PCI: Hardware I/O Error, SRC B6000103, " 562 panic("PCI: Hardware I/O Error, SRC B6000103, "
@@ -363,28 +573,39 @@ static int CheckReturnCode(char *TextHdr, struct device_node *DevNode,
363 * the exposure of being device global. 573 * the exposure of being device global.
364 */ 574 */
365static inline struct device_node *xlate_iomm_address( 575static inline struct device_node *xlate_iomm_address(
366 const volatile void __iomem *IoAddress, 576 const volatile void __iomem *addr,
367 u64 *dsaptr, u64 *BarOffsetPtr) 577 u64 *dsaptr, u64 *bar_offset, const char *func)
368{ 578{
369 unsigned long OrigIoAddr; 579 unsigned long orig_addr;
370 unsigned long BaseIoAddr; 580 unsigned long base_addr;
371 unsigned long TableIndex; 581 unsigned long ind;
372 struct device_node *DevNode; 582 struct device_node *dn;
583
584 orig_addr = (unsigned long __force)addr;
585 if ((orig_addr < BASE_IO_MEMORY) || (orig_addr >= max_io_memory)) {
586 static unsigned long last_jiffies;
587 static int num_printed;
373 588
374 OrigIoAddr = (unsigned long __force)IoAddress; 589 if ((jiffies - last_jiffies) > 60 * HZ) {
375 if ((OrigIoAddr < BASE_IO_MEMORY) || (OrigIoAddr >= max_io_memory)) 590 last_jiffies = jiffies;
591 num_printed = 0;
592 }
593 if (num_printed++ < 10)
594 printk(KERN_ERR
595 "iSeries_%s: invalid access at IO address %p\n",
596 func, addr);
376 return NULL; 597 return NULL;
377 BaseIoAddr = OrigIoAddr - BASE_IO_MEMORY; 598 }
378 TableIndex = BaseIoAddr / IOMM_TABLE_ENTRY_SIZE; 599 base_addr = orig_addr - BASE_IO_MEMORY;
379 DevNode = iomm_table[TableIndex]; 600 ind = base_addr / IOMM_TABLE_ENTRY_SIZE;
380 601 dn = iomm_table[ind];
381 if (DevNode != NULL) { 602
382 int barnum = iobar_table[TableIndex]; 603 if (dn != NULL) {
383 *dsaptr = iseries_ds_addr(DevNode) | (barnum << 24); 604 *dsaptr = ds_addr_table[ind];
384 *BarOffsetPtr = BaseIoAddr % IOMM_TABLE_ENTRY_SIZE; 605 *bar_offset = base_addr % IOMM_TABLE_ENTRY_SIZE;
385 } else 606 } else
386 panic("PCI: Invalid PCI IoAddress detected!\n"); 607 panic("PCI: Invalid PCI IO address detected!\n");
387 return DevNode; 608 return dn;
388} 609}
389 610
390/* 611/*
@@ -392,91 +613,58 @@ static inline struct device_node *xlate_iomm_address(
392 * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal 613 * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal
393 * else, data is returned in Big Endian format. 614 * else, data is returned in Big Endian format.
394 */ 615 */
395static u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress) 616static u8 iseries_readb(const volatile void __iomem *addr)
396{ 617{
397 u64 BarOffset; 618 u64 bar_offset;
398 u64 dsa; 619 u64 dsa;
399 int retry = 0; 620 int retry = 0;
400 struct HvCallPci_LoadReturn ret; 621 struct HvCallPci_LoadReturn ret;
401 struct device_node *DevNode = 622 struct device_node *dn =
402 xlate_iomm_address(IoAddress, &dsa, &BarOffset); 623 xlate_iomm_address(addr, &dsa, &bar_offset, "read_byte");
403
404 if (DevNode == NULL) {
405 static unsigned long last_jiffies;
406 static int num_printed;
407 624
408 if ((jiffies - last_jiffies) > 60 * HZ) { 625 if (dn == NULL)
409 last_jiffies = jiffies;
410 num_printed = 0;
411 }
412 if (num_printed++ < 10)
413 printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n",
414 IoAddress);
415 return 0xff; 626 return 0xff;
416 }
417 do { 627 do {
418 HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0); 628 HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, bar_offset, 0);
419 } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0); 629 } while (check_return_code("RDB", dn, &retry, ret.rc) != 0);
420 630
421 return ret.value; 631 return ret.value;
422} 632}
423 633
424static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress) 634static u16 iseries_readw_be(const volatile void __iomem *addr)
425{ 635{
426 u64 BarOffset; 636 u64 bar_offset;
427 u64 dsa; 637 u64 dsa;
428 int retry = 0; 638 int retry = 0;
429 struct HvCallPci_LoadReturn ret; 639 struct HvCallPci_LoadReturn ret;
430 struct device_node *DevNode = 640 struct device_node *dn =
431 xlate_iomm_address(IoAddress, &dsa, &BarOffset); 641 xlate_iomm_address(addr, &dsa, &bar_offset, "read_word");
432 642
433 if (DevNode == NULL) { 643 if (dn == NULL)
434 static unsigned long last_jiffies;
435 static int num_printed;
436
437 if ((jiffies - last_jiffies) > 60 * HZ) {
438 last_jiffies = jiffies;
439 num_printed = 0;
440 }
441 if (num_printed++ < 10)
442 printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n",
443 IoAddress);
444 return 0xffff; 644 return 0xffff;
445 }
446 do { 645 do {
447 HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa, 646 HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa,
448 BarOffset, 0); 647 bar_offset, 0);
449 } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0); 648 } while (check_return_code("RDW", dn, &retry, ret.rc) != 0);
450 649
451 return ret.value; 650 return ret.value;
452} 651}
453 652
454static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress) 653static u32 iseries_readl_be(const volatile void __iomem *addr)
455{ 654{
456 u64 BarOffset; 655 u64 bar_offset;
457 u64 dsa; 656 u64 dsa;
458 int retry = 0; 657 int retry = 0;
459 struct HvCallPci_LoadReturn ret; 658 struct HvCallPci_LoadReturn ret;
460 struct device_node *DevNode = 659 struct device_node *dn =
461 xlate_iomm_address(IoAddress, &dsa, &BarOffset); 660 xlate_iomm_address(addr, &dsa, &bar_offset, "read_long");
462
463 if (DevNode == NULL) {
464 static unsigned long last_jiffies;
465 static int num_printed;
466 661
467 if ((jiffies - last_jiffies) > 60 * HZ) { 662 if (dn == NULL)
468 last_jiffies = jiffies;
469 num_printed = 0;
470 }
471 if (num_printed++ < 10)
472 printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n",
473 IoAddress);
474 return 0xffffffff; 663 return 0xffffffff;
475 }
476 do { 664 do {
477 HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa, 665 HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa,
478 BarOffset, 0); 666 bar_offset, 0);
479 } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0); 667 } while (check_return_code("RDL", dn, &retry, ret.rc) != 0);
480 668
481 return ret.value; 669 return ret.value;
482} 670}
@@ -485,134 +673,72 @@ static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
485 * Write MM I/O Instructions for the iSeries 673 * Write MM I/O Instructions for the iSeries
486 * 674 *
487 */ 675 */
488static void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress) 676static void iseries_writeb(u8 data, volatile void __iomem *addr)
489{ 677{
490 u64 BarOffset; 678 u64 bar_offset;
491 u64 dsa; 679 u64 dsa;
492 int retry = 0; 680 int retry = 0;
493 u64 rc; 681 u64 rc;
494 struct device_node *DevNode = 682 struct device_node *dn =
495 xlate_iomm_address(IoAddress, &dsa, &BarOffset); 683 xlate_iomm_address(addr, &dsa, &bar_offset, "write_byte");
496
497 if (DevNode == NULL) {
498 static unsigned long last_jiffies;
499 static int num_printed;
500 684
501 if ((jiffies - last_jiffies) > 60 * HZ) { 685 if (dn == NULL)
502 last_jiffies = jiffies;
503 num_printed = 0;
504 }
505 if (num_printed++ < 10)
506 printk(KERN_ERR "iSeries_Write_Byte: invalid access at IO address %p\n", IoAddress);
507 return; 686 return;
508 }
509 do { 687 do {
510 rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0); 688 rc = HvCall4(HvCallPciBarStore8, dsa, bar_offset, data, 0);
511 } while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0); 689 } while (check_return_code("WWB", dn, &retry, rc) != 0);
512} 690}
513 691
514static void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress) 692static void iseries_writew_be(u16 data, volatile void __iomem *addr)
515{ 693{
516 u64 BarOffset; 694 u64 bar_offset;
517 u64 dsa; 695 u64 dsa;
518 int retry = 0; 696 int retry = 0;
519 u64 rc; 697 u64 rc;
520 struct device_node *DevNode = 698 struct device_node *dn =
521 xlate_iomm_address(IoAddress, &dsa, &BarOffset); 699 xlate_iomm_address(addr, &dsa, &bar_offset, "write_word");
522 700
523 if (DevNode == NULL) { 701 if (dn == NULL)
524 static unsigned long last_jiffies;
525 static int num_printed;
526
527 if ((jiffies - last_jiffies) > 60 * HZ) {
528 last_jiffies = jiffies;
529 num_printed = 0;
530 }
531 if (num_printed++ < 10)
532 printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n",
533 IoAddress);
534 return; 702 return;
535 }
536 do { 703 do {
537 rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, data, 0); 704 rc = HvCall4(HvCallPciBarStore16, dsa, bar_offset, data, 0);
538 } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0); 705 } while (check_return_code("WWW", dn, &retry, rc) != 0);
539} 706}
540 707
541static void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress) 708static void iseries_writel_be(u32 data, volatile void __iomem *addr)
542{ 709{
543 u64 BarOffset; 710 u64 bar_offset;
544 u64 dsa; 711 u64 dsa;
545 int retry = 0; 712 int retry = 0;
546 u64 rc; 713 u64 rc;
547 struct device_node *DevNode = 714 struct device_node *dn =
548 xlate_iomm_address(IoAddress, &dsa, &BarOffset); 715 xlate_iomm_address(addr, &dsa, &bar_offset, "write_long");
549
550 if (DevNode == NULL) {
551 static unsigned long last_jiffies;
552 static int num_printed;
553 716
554 if ((jiffies - last_jiffies) > 60 * HZ) { 717 if (dn == NULL)
555 last_jiffies = jiffies;
556 num_printed = 0;
557 }
558 if (num_printed++ < 10)
559 printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n",
560 IoAddress);
561 return; 718 return;
562 }
563 do { 719 do {
564 rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, data, 0); 720 rc = HvCall4(HvCallPciBarStore32, dsa, bar_offset, data, 0);
565 } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0); 721 } while (check_return_code("WWL", dn, &retry, rc) != 0);
566}
567
568static u8 iseries_readb(const volatile void __iomem *addr)
569{
570 return iSeries_Read_Byte(addr);
571} 722}
572 723
573static u16 iseries_readw(const volatile void __iomem *addr) 724static u16 iseries_readw(const volatile void __iomem *addr)
574{ 725{
575 return le16_to_cpu(iSeries_Read_Word(addr)); 726 return le16_to_cpu(iseries_readw_be(addr));
576} 727}
577 728
578static u32 iseries_readl(const volatile void __iomem *addr) 729static u32 iseries_readl(const volatile void __iomem *addr)
579{ 730{
580 return le32_to_cpu(iSeries_Read_Long(addr)); 731 return le32_to_cpu(iseries_readl_be(addr));
581}
582
583static u16 iseries_readw_be(const volatile void __iomem *addr)
584{
585 return iSeries_Read_Word(addr);
586}
587
588static u32 iseries_readl_be(const volatile void __iomem *addr)
589{
590 return iSeries_Read_Long(addr);
591}
592
593static void iseries_writeb(u8 data, volatile void __iomem *addr)
594{
595 iSeries_Write_Byte(data, addr);
596} 732}
597 733
598static void iseries_writew(u16 data, volatile void __iomem *addr) 734static void iseries_writew(u16 data, volatile void __iomem *addr)
599{ 735{
600 iSeries_Write_Word(cpu_to_le16(data), addr); 736 iseries_writew_be(cpu_to_le16(data), addr);
601} 737}
602 738
603static void iseries_writel(u32 data, volatile void __iomem *addr) 739static void iseries_writel(u32 data, volatile void __iomem *addr)
604{ 740{
605 iSeries_Write_Long(cpu_to_le32(data), addr); 741 iseries_writel(cpu_to_le32(data), addr);
606}
607
608static void iseries_writew_be(u16 data, volatile void __iomem *addr)
609{
610 iSeries_Write_Word(data, addr);
611}
612
613static void iseries_writel_be(u32 data, volatile void __iomem *addr)
614{
615 iSeries_Write_Long(data, addr);
616} 742}
617 743
618static void iseries_readsb(const volatile void __iomem *addr, void *buf, 744static void iseries_readsb(const volatile void __iomem *addr, void *buf,
@@ -620,7 +746,7 @@ static void iseries_readsb(const volatile void __iomem *addr, void *buf,
620{ 746{
621 u8 *dst = buf; 747 u8 *dst = buf;
622 while(count-- > 0) 748 while(count-- > 0)
623 *(dst++) = iSeries_Read_Byte(addr); 749 *(dst++) = iseries_readb(addr);
624} 750}
625 751
626static void iseries_readsw(const volatile void __iomem *addr, void *buf, 752static void iseries_readsw(const volatile void __iomem *addr, void *buf,
@@ -628,7 +754,7 @@ static void iseries_readsw(const volatile void __iomem *addr, void *buf,
628{ 754{
629 u16 *dst = buf; 755 u16 *dst = buf;
630 while(count-- > 0) 756 while(count-- > 0)
631 *(dst++) = iSeries_Read_Word(addr); 757 *(dst++) = iseries_readw_be(addr);
632} 758}
633 759
634static void iseries_readsl(const volatile void __iomem *addr, void *buf, 760static void iseries_readsl(const volatile void __iomem *addr, void *buf,
@@ -636,7 +762,7 @@ static void iseries_readsl(const volatile void __iomem *addr, void *buf,
636{ 762{
637 u32 *dst = buf; 763 u32 *dst = buf;
638 while(count-- > 0) 764 while(count-- > 0)
639 *(dst++) = iSeries_Read_Long(addr); 765 *(dst++) = iseries_readl_be(addr);
640} 766}
641 767
642static void iseries_writesb(volatile void __iomem *addr, const void *buf, 768static void iseries_writesb(volatile void __iomem *addr, const void *buf,
@@ -644,7 +770,7 @@ static void iseries_writesb(volatile void __iomem *addr, const void *buf,
644{ 770{
645 const u8 *src = buf; 771 const u8 *src = buf;
646 while(count-- > 0) 772 while(count-- > 0)
647 iSeries_Write_Byte(*(src++), addr); 773 iseries_writeb(*(src++), addr);
648} 774}
649 775
650static void iseries_writesw(volatile void __iomem *addr, const void *buf, 776static void iseries_writesw(volatile void __iomem *addr, const void *buf,
@@ -652,7 +778,7 @@ static void iseries_writesw(volatile void __iomem *addr, const void *buf,
652{ 778{
653 const u16 *src = buf; 779 const u16 *src = buf;
654 while(count-- > 0) 780 while(count-- > 0)
655 iSeries_Write_Word(*(src++), addr); 781 iseries_writew_be(*(src++), addr);
656} 782}
657 783
658static void iseries_writesl(volatile void __iomem *addr, const void *buf, 784static void iseries_writesl(volatile void __iomem *addr, const void *buf,
@@ -660,7 +786,7 @@ static void iseries_writesl(volatile void __iomem *addr, const void *buf,
660{ 786{
661 const u32 *src = buf; 787 const u32 *src = buf;
662 while(count-- > 0) 788 while(count-- > 0)
663 iSeries_Write_Long(*(src++), addr); 789 iseries_writel_be(*(src++), addr);
664} 790}
665 791
666static void iseries_memset_io(volatile void __iomem *addr, int c, 792static void iseries_memset_io(volatile void __iomem *addr, int c,
@@ -669,7 +795,7 @@ static void iseries_memset_io(volatile void __iomem *addr, int c,
669 volatile char __iomem *d = addr; 795 volatile char __iomem *d = addr;
670 796
671 while (n-- > 0) 797 while (n-- > 0)
672 iSeries_Write_Byte(c, d++); 798 iseries_writeb(c, d++);
673} 799}
674 800
675static void iseries_memcpy_fromio(void *dest, const volatile void __iomem *src, 801static void iseries_memcpy_fromio(void *dest, const volatile void __iomem *src,
@@ -679,7 +805,7 @@ static void iseries_memcpy_fromio(void *dest, const volatile void __iomem *src,
679 const volatile char __iomem *s = src; 805 const volatile char __iomem *s = src;
680 806
681 while (n-- > 0) 807 while (n-- > 0)
682 *d++ = iSeries_Read_Byte(s++); 808 *d++ = iseries_readb(s++);
683} 809}
684 810
685static void iseries_memcpy_toio(volatile void __iomem *dest, const void *src, 811static void iseries_memcpy_toio(volatile void __iomem *dest, const void *src,
@@ -689,7 +815,7 @@ static void iseries_memcpy_toio(volatile void __iomem *dest, const void *src,
689 volatile char __iomem *d = dest; 815 volatile char __iomem *d = dest;
690 816
691 while (n-- > 0) 817 while (n-- > 0)
692 iSeries_Write_Byte(*s++, d++); 818 iseries_writeb(*s++, d++);
693} 819}
694 820
695/* We only set MMIO ops. The default PIO ops will be default 821/* We only set MMIO ops. The default PIO ops will be default
@@ -742,6 +868,8 @@ void __init iSeries_pcibios_init(void)
742 /* Install IO hooks */ 868 /* Install IO hooks */
743 ppc_pci_io = iseries_pci_io; 869 ppc_pci_io = iseries_pci_io;
744 870
871 pci_probe_only = 1;
872
745 /* iSeries has no IO space in the common sense, it needs to set 873 /* iSeries has no IO space in the common sense, it needs to set
746 * the IO base to 0 874 * the IO base to 0
747 */ 875 */
@@ -767,11 +895,21 @@ void __init iSeries_pcibios_init(void)
767 phb = pcibios_alloc_controller(node); 895 phb = pcibios_alloc_controller(node);
768 if (phb == NULL) 896 if (phb == NULL)
769 continue; 897 continue;
898 /* All legacy iSeries PHBs are in domain zero */
899 phb->global_number = 0;
770 900
771 phb->pci_mem_offset = bus;
772 phb->first_busno = bus; 901 phb->first_busno = bus;
773 phb->last_busno = bus; 902 phb->last_busno = bus;
774 phb->ops = &iSeries_pci_ops; 903 phb->ops = &iSeries_pci_ops;
904 phb->io_base_virt = (void __iomem *)_IO_BASE;
905 phb->io_resource.flags = IORESOURCE_IO;
906 phb->io_resource.start = BASE_IO_MEMORY;
907 phb->io_resource.end = END_IO_MEMORY;
908 phb->io_resource.name = "iSeries PCI IO";
909 phb->mem_resources[0].flags = IORESOURCE_MEM;
910 phb->mem_resources[0].start = BASE_IO_MEMORY;
911 phb->mem_resources[0].end = END_IO_MEMORY;
912 phb->mem_resources[0].name = "Series PCI MEM";
775 } 913 }
776 914
777 of_node_put(root); 915 of_node_put(root);
diff --git a/arch/powerpc/platforms/iseries/pci.h b/arch/powerpc/platforms/iseries/pci.h
index 33a8489fde54..d9cf974c2718 100644
--- a/arch/powerpc/platforms/iseries/pci.h
+++ b/arch/powerpc/platforms/iseries/pci.h
@@ -30,10 +30,6 @@
30 * End Change Activity 30 * End Change Activity
31 */ 31 */
32 32
33#include <asm/pci-bridge.h>
34
35struct pci_dev; /* For Forward Reference */
36
37/* 33/*
38 * Decodes Linux DevFn to iSeries DevFn, bridge device, or function. 34 * Decodes Linux DevFn to iSeries DevFn, bridge device, or function.
39 * For Linux, see PCI_SLOT and PCI_FUNC in include/linux/pci.h 35 * For Linux, see PCI_SLOT and PCI_FUNC in include/linux/pci.h
@@ -47,17 +43,16 @@ struct pci_dev; /* For Forward Reference */
47#define ISERIES_GET_DEVICE_FROM_SUBBUS(subbus) ((subbus >> 5) & 0x7) 43#define ISERIES_GET_DEVICE_FROM_SUBBUS(subbus) ((subbus >> 5) & 0x7)
48#define ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus) ((subbus >> 2) & 0x7) 44#define ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus) ((subbus >> 2) & 0x7)
49 45
50/* 46struct pci_dev;
51 * Generate a Direct Select Address for the Hypervisor 47
52 */ 48#ifdef CONFIG_PCI
53static inline u64 iseries_ds_addr(struct device_node *node) 49extern void iSeries_pcibios_init(void);
54{ 50extern void iSeries_pci_final_fixup(void);
55 struct pci_dn *pdn = PCI_DN(node); 51extern void iSeries_pcibios_fixup_resources(struct pci_dev *dev);
56 52#else
57 return ((u64)pdn->busno << 48) + ((u64)pdn->bussubno << 40) 53static inline void iSeries_pcibios_init(void) { }
58 + ((u64)0x10 << 32); 54static inline void iSeries_pci_final_fixup(void) { }
59} 55static inline void iSeries_pcibios_fixup_resources(struct pci_dev *dev) {}
60 56#endif
61extern void iSeries_Device_Information(struct pci_dev*, int);
62 57
63#endif /* _PLATFORMS_ISERIES_PCI_H */ 58#endif /* _PLATFORMS_ISERIES_PCI_H */
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 0877a8834110..b72120751bbe 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -63,6 +63,7 @@
63#include "main_store.h" 63#include "main_store.h"
64#include "call_sm.h" 64#include "call_sm.h"
65#include "call_hpt.h" 65#include "call_hpt.h"
66#include "pci.h"
66 67
67#ifdef DEBUG 68#ifdef DEBUG
68#define DBG(fmt...) udbg_printf(fmt) 69#define DBG(fmt...) udbg_printf(fmt)
@@ -74,11 +75,6 @@
74static unsigned long build_iSeries_Memory_Map(void); 75static unsigned long build_iSeries_Memory_Map(void);
75static void iseries_shared_idle(void); 76static void iseries_shared_idle(void);
76static void iseries_dedicated_idle(void); 77static void iseries_dedicated_idle(void);
77#ifdef CONFIG_PCI
78extern void iSeries_pci_final_fixup(void);
79#else
80static void iSeries_pci_final_fixup(void) { }
81#endif
82 78
83 79
84struct MemoryBlock { 80struct MemoryBlock {
@@ -112,13 +108,13 @@ static unsigned long iSeries_process_Condor_mainstore_vpd(
112 * correctly. 108 * correctly.
113 */ 109 */
114 mb_array[0].logicalStart = 0; 110 mb_array[0].logicalStart = 0;
115 mb_array[0].logicalEnd = 0x100000000; 111 mb_array[0].logicalEnd = 0x100000000UL;
116 mb_array[0].absStart = 0; 112 mb_array[0].absStart = 0;
117 mb_array[0].absEnd = 0x100000000; 113 mb_array[0].absEnd = 0x100000000UL;
118 114
119 if (holeSize) { 115 if (holeSize) {
120 numMemoryBlocks = 2; 116 numMemoryBlocks = 2;
121 holeStart = holeStart & 0x000fffffffffffff; 117 holeStart = holeStart & 0x000fffffffffffffUL;
122 holeStart = addr_to_chunk(holeStart); 118 holeStart = addr_to_chunk(holeStart);
123 holeFirstChunk = holeStart; 119 holeFirstChunk = holeStart;
124 holeSize = addr_to_chunk(holeSize); 120 holeSize = addr_to_chunk(holeSize);
@@ -128,9 +124,9 @@ static unsigned long iSeries_process_Condor_mainstore_vpd(
128 mb_array[0].logicalEnd = holeFirstChunk; 124 mb_array[0].logicalEnd = holeFirstChunk;
129 mb_array[0].absEnd = holeFirstChunk; 125 mb_array[0].absEnd = holeFirstChunk;
130 mb_array[1].logicalStart = holeFirstChunk; 126 mb_array[1].logicalStart = holeFirstChunk;
131 mb_array[1].logicalEnd = 0x100000000 - holeSizeChunks; 127 mb_array[1].logicalEnd = 0x100000000UL - holeSizeChunks;
132 mb_array[1].absStart = holeFirstChunk + holeSizeChunks; 128 mb_array[1].absStart = holeFirstChunk + holeSizeChunks;
133 mb_array[1].absEnd = 0x100000000; 129 mb_array[1].absEnd = 0x100000000UL;
134 } 130 }
135 return numMemoryBlocks; 131 return numMemoryBlocks;
136} 132}
@@ -234,9 +230,9 @@ static unsigned long iSeries_process_Regatta_mainstore_vpd(
234 mb_array[i].logicalEnd, 230 mb_array[i].logicalEnd,
235 mb_array[i].absStart, mb_array[i].absEnd); 231 mb_array[i].absStart, mb_array[i].absEnd);
236 mb_array[i].absStart = addr_to_chunk(mb_array[i].absStart & 232 mb_array[i].absStart = addr_to_chunk(mb_array[i].absStart &
237 0x000fffffffffffff); 233 0x000fffffffffffffUL);
238 mb_array[i].absEnd = addr_to_chunk(mb_array[i].absEnd & 234 mb_array[i].absEnd = addr_to_chunk(mb_array[i].absEnd &
239 0x000fffffffffffff); 235 0x000fffffffffffffUL);
240 mb_array[i].logicalStart = 236 mb_array[i].logicalStart =
241 addr_to_chunk(mb_array[i].logicalStart); 237 addr_to_chunk(mb_array[i].logicalStart);
242 mb_array[i].logicalEnd = addr_to_chunk(mb_array[i].logicalEnd); 238 mb_array[i].logicalEnd = addr_to_chunk(mb_array[i].logicalEnd);
@@ -320,7 +316,7 @@ struct mschunks_map mschunks_map = {
320}; 316};
321EXPORT_SYMBOL(mschunks_map); 317EXPORT_SYMBOL(mschunks_map);
322 318
323void mschunks_alloc(unsigned long num_chunks) 319static void mschunks_alloc(unsigned long num_chunks)
324{ 320{
325 klimit = _ALIGN(klimit, sizeof(u32)); 321 klimit = _ALIGN(klimit, sizeof(u32));
326 mschunks_map.mapping = (u32 *)klimit; 322 mschunks_map.mapping = (u32 *)klimit;
@@ -499,6 +495,8 @@ static void __init iSeries_setup_arch(void)
499 itVpdAreas.xSlicMaxLogicalProcs); 495 itVpdAreas.xSlicMaxLogicalProcs);
500 printk("Max physical processors = %d\n", 496 printk("Max physical processors = %d\n",
501 itVpdAreas.xSlicMaxPhysicalProcs); 497 itVpdAreas.xSlicMaxPhysicalProcs);
498
499 iSeries_pcibios_init();
502} 500}
503 501
504static void iSeries_show_cpuinfo(struct seq_file *m) 502static void iSeries_show_cpuinfo(struct seq_file *m)
@@ -641,24 +639,25 @@ static int __init iseries_probe(void)
641} 639}
642 640
643define_machine(iseries) { 641define_machine(iseries) {
644 .name = "iSeries", 642 .name = "iSeries",
645 .setup_arch = iSeries_setup_arch, 643 .setup_arch = iSeries_setup_arch,
646 .show_cpuinfo = iSeries_show_cpuinfo, 644 .show_cpuinfo = iSeries_show_cpuinfo,
647 .init_IRQ = iSeries_init_IRQ, 645 .init_IRQ = iSeries_init_IRQ,
648 .get_irq = iSeries_get_irq, 646 .get_irq = iSeries_get_irq,
649 .init_early = iSeries_init_early, 647 .init_early = iSeries_init_early,
650 .pcibios_fixup = iSeries_pci_final_fixup, 648 .pcibios_fixup = iSeries_pci_final_fixup,
651 .restart = mf_reboot, 649 .pcibios_fixup_resources= iSeries_pcibios_fixup_resources,
652 .power_off = mf_power_off, 650 .restart = mf_reboot,
653 .halt = mf_power_off, 651 .power_off = mf_power_off,
654 .get_boot_time = iSeries_get_boot_time, 652 .halt = mf_power_off,
655 .set_rtc_time = iSeries_set_rtc_time, 653 .get_boot_time = iSeries_get_boot_time,
656 .get_rtc_time = iSeries_get_rtc_time, 654 .set_rtc_time = iSeries_set_rtc_time,
657 .calibrate_decr = generic_calibrate_decr, 655 .get_rtc_time = iSeries_get_rtc_time,
658 .progress = iSeries_progress, 656 .calibrate_decr = generic_calibrate_decr,
659 .probe = iseries_probe, 657 .progress = iSeries_progress,
660 .ioremap = iseries_ioremap, 658 .probe = iseries_probe,
661 .iounmap = iseries_iounmap, 659 .ioremap = iseries_ioremap,
660 .iounmap = iseries_iounmap,
662 /* XXX Implement enable_pmcs for iSeries */ 661 /* XXX Implement enable_pmcs for iSeries */
663}; 662};
664 663
diff --git a/arch/powerpc/platforms/iseries/setup.h b/arch/powerpc/platforms/iseries/setup.h
index 0a47ac53c959..729754bbb018 100644
--- a/arch/powerpc/platforms/iseries/setup.h
+++ b/arch/powerpc/platforms/iseries/setup.h
@@ -17,6 +17,7 @@
17#ifndef __ISERIES_SETUP_H__ 17#ifndef __ISERIES_SETUP_H__
18#define __ISERIES_SETUP_H__ 18#define __ISERIES_SETUP_H__
19 19
20extern void *iSeries_early_setup(void);
20extern unsigned long iSeries_get_boot_time(void); 21extern unsigned long iSeries_get_boot_time(void);
21extern int iSeries_set_rtc_time(struct rtc_time *tm); 22extern int iSeries_set_rtc_time(struct rtc_time *tm);
22extern void iSeries_get_rtc_time(struct rtc_time *tm); 23extern void iSeries_get_rtc_time(struct rtc_time *tm);
diff --git a/arch/powerpc/platforms/iseries/vpdinfo.c b/arch/powerpc/platforms/iseries/vpdinfo.c
deleted file mode 100644
index 9f83878a0c2e..000000000000
--- a/arch/powerpc/platforms/iseries/vpdinfo.c
+++ /dev/null
@@ -1,275 +0,0 @@
1/*
2 * This code gets the card location of the hardware
3 * Copyright (C) 2001 <Allan H Trautman> <IBM Corp>
4 * Copyright (C) 2005 Stephen Rothwel, IBM Corp
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the:
18 * Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330,
20 * Boston, MA 02111-1307 USA
21 *
22 * Change Activity:
23 * Created, Feb 2, 2001
24 * Ported to ppc64, August 20, 2001
25 * End Change Activity
26 */
27#include <linux/init.h>
28#include <linux/module.h>
29#include <linux/pci.h>
30
31#include <asm/types.h>
32#include <asm/resource.h>
33#include <asm/abs_addr.h>
34#include <asm/pci-bridge.h>
35#include <asm/iseries/hv_types.h>
36
37#include "pci.h"
38#include "call_pci.h"
39
40/*
41 * Size of Bus VPD data
42 */
43#define BUS_VPDSIZE 1024
44
45/*
46 * Bus Vpd Tags
47 */
48#define VpdEndOfAreaTag 0x79
49#define VpdIdStringTag 0x82
50#define VpdVendorAreaTag 0x84
51
52/*
53 * Mfg Area Tags
54 */
55#define VpdFruFrameId 0x4649 // "FI"
56#define VpdSlotMapFormat 0x4D46 // "MF"
57#define VpdSlotMap 0x534D // "SM"
58
59/*
60 * Structures of the areas
61 */
62struct MfgVpdAreaStruct {
63 u16 Tag;
64 u8 TagLength;
65 u8 AreaData1;
66 u8 AreaData2;
67};
68typedef struct MfgVpdAreaStruct MfgArea;
69#define MFG_ENTRY_SIZE 3
70
71struct SlotMapStruct {
72 u8 AgentId;
73 u8 SecondaryAgentId;
74 u8 PhbId;
75 char CardLocation[3];
76 char Parms[8];
77 char Reserved[2];
78};
79typedef struct SlotMapStruct SlotMap;
80#define SLOT_ENTRY_SIZE 16
81
82/*
83 * Parse the Slot Area
84 */
85static void __init iSeries_Parse_SlotArea(SlotMap *MapPtr, int MapLen,
86 HvAgentId agent, u8 *PhbId, char card[4])
87{
88 int SlotMapLen = MapLen;
89 SlotMap *SlotMapPtr = MapPtr;
90
91 /*
92 * Parse Slot label until we find the one requested
93 */
94 while (SlotMapLen > 0) {
95 if (SlotMapPtr->AgentId == agent) {
96 /*
97 * If Phb wasn't found, grab the entry first one found.
98 */
99 if (*PhbId == 0xff)
100 *PhbId = SlotMapPtr->PhbId;
101 /* Found it, extract the data. */
102 if (SlotMapPtr->PhbId == *PhbId) {
103 memcpy(card, &SlotMapPtr->CardLocation, 3);
104 card[3] = 0;
105 break;
106 }
107 }
108 /* Point to the next Slot */
109 SlotMapPtr = (SlotMap *)((char *)SlotMapPtr + SLOT_ENTRY_SIZE);
110 SlotMapLen -= SLOT_ENTRY_SIZE;
111 }
112}
113
114/*
115 * Parse the Mfg Area
116 */
117static void __init iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen,
118 HvAgentId agent, u8 *PhbId,
119 u8 *frame, char card[4])
120{
121 MfgArea *MfgAreaPtr = (MfgArea *)AreaData;
122 int MfgAreaLen = AreaLen;
123 u16 SlotMapFmt = 0;
124
125 /* Parse Mfg Data */
126 while (MfgAreaLen > 0) {
127 int MfgTagLen = MfgAreaPtr->TagLength;
128 /* Frame ID (FI 4649020310 ) */
129 if (MfgAreaPtr->Tag == VpdFruFrameId) /* FI */
130 *frame = MfgAreaPtr->AreaData1;
131 /* Slot Map Format (MF 4D46020004 ) */
132 else if (MfgAreaPtr->Tag == VpdSlotMapFormat) /* MF */
133 SlotMapFmt = (MfgAreaPtr->AreaData1 * 256)
134 + MfgAreaPtr->AreaData2;
135 /* Slot Map (SM 534D90 */
136 else if (MfgAreaPtr->Tag == VpdSlotMap) { /* SM */
137 SlotMap *SlotMapPtr;
138
139 if (SlotMapFmt == 0x1004)
140 SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr
141 + MFG_ENTRY_SIZE + 1);
142 else
143 SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr
144 + MFG_ENTRY_SIZE);
145 iSeries_Parse_SlotArea(SlotMapPtr, MfgTagLen,
146 agent, PhbId, card);
147 }
148 /*
149 * Point to the next Mfg Area
150 * Use defined size, sizeof give wrong answer
151 */
152 MfgAreaPtr = (MfgArea *)((char *)MfgAreaPtr + MfgTagLen
153 + MFG_ENTRY_SIZE);
154 MfgAreaLen -= (MfgTagLen + MFG_ENTRY_SIZE);
155 }
156}
157
158/*
159 * Look for "BUS".. Data is not Null terminated.
160 * PHBID of 0xFF indicates PHB was not found in VPD Data.
161 */
162static int __init iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength)
163{
164 u8 *PhbPtr = AreaPtr;
165 int DataLen = AreaLength;
166 char PhbId = 0xFF;
167
168 while (DataLen > 0) {
169 if ((*PhbPtr == 'B') && (*(PhbPtr + 1) == 'U')
170 && (*(PhbPtr + 2) == 'S')) {
171 PhbPtr += 3;
172 while (*PhbPtr == ' ')
173 ++PhbPtr;
174 PhbId = (*PhbPtr & 0x0F);
175 break;
176 }
177 ++PhbPtr;
178 --DataLen;
179 }
180 return PhbId;
181}
182
183/*
184 * Parse out the VPD Areas
185 */
186static void __init iSeries_Parse_Vpd(u8 *VpdData, int VpdDataLen,
187 HvAgentId agent, u8 *frame, char card[4])
188{
189 u8 *TagPtr = VpdData;
190 int DataLen = VpdDataLen - 3;
191 u8 PhbId = 0xff;
192
193 while ((*TagPtr != VpdEndOfAreaTag) && (DataLen > 0)) {
194 int AreaLen = *(TagPtr + 1) + (*(TagPtr + 2) * 256);
195 u8 *AreaData = TagPtr + 3;
196
197 if (*TagPtr == VpdIdStringTag)
198 PhbId = iSeries_Parse_PhbId(AreaData, AreaLen);
199 else if (*TagPtr == VpdVendorAreaTag)
200 iSeries_Parse_MfgArea(AreaData, AreaLen,
201 agent, &PhbId, frame, card);
202 /* Point to next Area. */
203 TagPtr = AreaData + AreaLen;
204 DataLen -= AreaLen;
205 }
206}
207
208static int __init iSeries_Get_Location_Code(u16 bus, HvAgentId agent,
209 u8 *frame, char card[4])
210{
211 int status = 0;
212 int BusVpdLen = 0;
213 u8 *BusVpdPtr = kmalloc(BUS_VPDSIZE, GFP_KERNEL);
214
215 if (BusVpdPtr == NULL) {
216 printk("PCI: Bus VPD Buffer allocation failure.\n");
217 return 0;
218 }
219 BusVpdLen = HvCallPci_getBusVpd(bus, iseries_hv_addr(BusVpdPtr),
220 BUS_VPDSIZE);
221 if (BusVpdLen == 0) {
222 printk("PCI: Bus VPD Buffer zero length.\n");
223 goto out_free;
224 }
225 /* printk("PCI: BusVpdPtr: %p, %d\n",BusVpdPtr, BusVpdLen); */
226 /* Make sure this is what I think it is */
227 if (*BusVpdPtr != VpdIdStringTag) { /* 0x82 */
228 printk("PCI: Bus VPD Buffer missing starting tag.\n");
229 goto out_free;
230 }
231 iSeries_Parse_Vpd(BusVpdPtr, BusVpdLen, agent, frame, card);
232 status = 1;
233out_free:
234 kfree(BusVpdPtr);
235 return status;
236}
237
238/*
239 * Prints the device information.
240 * - Pass in pci_dev* pointer to the device.
241 * - Pass in the device count
242 *
243 * Format:
244 * PCI: Bus 0, Device 26, Vendor 0x12AE Frame 1, Card C10 Ethernet
245 * controller
246 */
247void __init iSeries_Device_Information(struct pci_dev *PciDev, int count)
248{
249 struct device_node *DevNode = PciDev->sysdata;
250 struct pci_dn *pdn;
251 u16 bus;
252 u8 frame = 0;
253 char card[4];
254 HvSubBusNumber subbus;
255 HvAgentId agent;
256
257 if (DevNode == NULL) {
258 printk("%d. PCI: iSeries_Device_Information DevNode is NULL\n",
259 count);
260 return;
261 }
262
263 pdn = PCI_DN(DevNode);
264 bus = pdn->busno;
265 subbus = pdn->bussubno;
266 agent = ISERIES_PCI_AGENTID(ISERIES_GET_DEVICE_FROM_SUBBUS(subbus),
267 ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus));
268
269 if (iSeries_Get_Location_Code(bus, agent, &frame, card)) {
270 printk("%d. PCI: Bus%3d, Device%3d, Vendor %04X Frame%3d, "
271 "Card %4s 0x%04X\n", count, bus,
272 PCI_SLOT(PciDev->devfn), PciDev->vendor, frame,
273 card, (int)(PciDev->class >> 8));
274 }
275}
diff --git a/arch/powerpc/platforms/maple/Kconfig b/arch/powerpc/platforms/maple/Kconfig
index f7c95eb5d8ba..a6467a5591fa 100644
--- a/arch/powerpc/platforms/maple/Kconfig
+++ b/arch/powerpc/platforms/maple/Kconfig
@@ -1,6 +1,7 @@
1config PPC_MAPLE 1config PPC_MAPLE
2 depends on PPC_MULTIPLATFORM && PPC64 2 depends on PPC_MULTIPLATFORM && PPC64
3 bool "Maple 970FX Evaluation Board" 3 bool "Maple 970FX Evaluation Board"
4 select PCI
4 select MPIC 5 select MPIC
5 select U3_DART 6 select U3_DART
6 select MPIC_U3_HT_IRQS 7 select MPIC_U3_HT_IRQS
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index 771ed0cf29a5..3ffa0ac170ee 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -558,7 +558,7 @@ void __init maple_pci_init(void)
558 * safe assumptions hopefully. 558 * safe assumptions hopefully.
559 */ 559 */
560 if (u3_agp) { 560 if (u3_agp) {
561 struct device_node *np = u3_agp->arch_data; 561 struct device_node *np = u3_agp->dn;
562 PCI_DN(np)->busno = 0xf0; 562 PCI_DN(np)->busno = 0xf0;
563 for (np = np->child; np; np = np->sibling) 563 for (np = np->child; np; np = np->sibling)
564 PCI_DN(np)->busno = 0xf0; 564 PCI_DN(np)->busno = 0xf0;
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index 144177d77cf1..3ce2d73b4177 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -42,6 +42,7 @@
42#include <linux/serial.h> 42#include <linux/serial.h>
43#include <linux/smp.h> 43#include <linux/smp.h>
44#include <linux/bitops.h> 44#include <linux/bitops.h>
45#include <linux/of_device.h>
45 46
46#include <asm/processor.h> 47#include <asm/processor.h>
47#include <asm/sections.h> 48#include <asm/sections.h>
@@ -56,7 +57,6 @@
56#include <asm/dma.h> 57#include <asm/dma.h>
57#include <asm/cputable.h> 58#include <asm/cputable.h>
58#include <asm/time.h> 59#include <asm/time.h>
59#include <asm/of_device.h>
60#include <asm/lmb.h> 60#include <asm/lmb.h>
61#include <asm/mpic.h> 61#include <asm/mpic.h>
62#include <asm/rtas.h> 62#include <asm/rtas.h>
diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig
index 735e1536cbfc..348e0619e3e5 100644
--- a/arch/powerpc/platforms/pasemi/Kconfig
+++ b/arch/powerpc/platforms/pasemi/Kconfig
@@ -3,6 +3,7 @@ config PPC_PASEMI
3 bool "PA Semi SoC-based platforms" 3 bool "PA Semi SoC-based platforms"
4 default n 4 default n
5 select MPIC 5 select MPIC
6 select PCI
6 select PPC_UDBG_16550 7 select PPC_UDBG_16550
7 select PPC_NATIVE 8 select PPC_NATIVE
8 select MPIC_BROKEN_REGREAD 9 select MPIC_BROKEN_REGREAD
@@ -17,7 +18,7 @@ config PPC_PASEMI_IOMMU
17 bool "PA Semi IOMMU support" 18 bool "PA Semi IOMMU support"
18 depends on PPC_PASEMI 19 depends on PPC_PASEMI
19 help 20 help
20 IOMMU support for PA6T-1682M 21 IOMMU support for PA Semi PWRficient
21 22
22config PPC_PASEMI_IOMMU_DMA_FORCE 23config PPC_PASEMI_IOMMU_DMA_FORCE
23 bool "Force DMA engine to use IOMMU" 24 bool "Force DMA engine to use IOMMU"
@@ -36,13 +37,4 @@ config PPC_PASEMI_MDIO
36 help 37 help
37 Driver for MDIO via GPIO on PWRficient platforms 38 Driver for MDIO via GPIO on PWRficient platforms
38 39
39config ELECTRA_IDE
40 tristate "Electra IDE driver"
41 default y
42 depends on PPC_PASEMI && ATA
43 select PATA_PLATFORM
44 help
45 This includes driver support for the Electra on-board IDE
46 interface.
47
48endmenu 40endmenu
diff --git a/arch/powerpc/platforms/pasemi/Makefile b/arch/powerpc/platforms/pasemi/Makefile
index e636daa7a80e..8f52d7515793 100644
--- a/arch/powerpc/platforms/pasemi/Makefile
+++ b/arch/powerpc/platforms/pasemi/Makefile
@@ -1,4 +1,3 @@
1obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o dma_lib.o 1obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o dma_lib.o
2obj-$(CONFIG_PPC_PASEMI_MDIO) += gpio_mdio.o 2obj-$(CONFIG_PPC_PASEMI_MDIO) += gpio_mdio.o
3obj-$(CONFIG_ELECTRA_IDE) += electra_ide.o
4obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o 3obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o
diff --git a/arch/powerpc/platforms/pasemi/cpufreq.c b/arch/powerpc/platforms/pasemi/cpufreq.c
index 1cfb8b0c8fec..58556b028a4c 100644
--- a/arch/powerpc/platforms/pasemi/cpufreq.c
+++ b/arch/powerpc/platforms/pasemi/cpufreq.c
@@ -32,6 +32,7 @@
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#include <asm/time.h>
35#include <asm/smp.h>
35 36
36#define SDCASR_REG 0x0100 37#define SDCASR_REG 0x0100
37#define SDCASR_REG_STRIDE 0x1000 38#define SDCASR_REG_STRIDE 0x1000
@@ -124,6 +125,11 @@ static void set_astate(int cpu, unsigned int astate)
124 local_irq_restore(flags); 125 local_irq_restore(flags);
125} 126}
126 127
128int check_astate(void)
129{
130 return get_cur_astate(hard_smp_processor_id());
131}
132
127void restore_astate(int cpu) 133void restore_astate(int cpu)
128{ 134{
129 set_astate(cpu, current_astate); 135 set_astate(cpu, current_astate);
@@ -147,7 +153,10 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
147 if (!cpu) 153 if (!cpu)
148 goto out; 154 goto out;
149 155
150 dn = of_find_compatible_node(NULL, "sdc", "1682m-sdc"); 156 dn = of_find_compatible_node(NULL, NULL, "1682m-sdc");
157 if (!dn)
158 dn = of_find_compatible_node(NULL, NULL,
159 "pasemi,pwrficient-sdc");
151 if (!dn) 160 if (!dn)
152 goto out; 161 goto out;
153 err = of_address_to_resource(dn, 0, &res); 162 err = of_address_to_resource(dn, 0, &res);
@@ -160,7 +169,10 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
160 goto out; 169 goto out;
161 } 170 }
162 171
163 dn = of_find_compatible_node(NULL, "gizmo", "1682m-gizmo"); 172 dn = of_find_compatible_node(NULL, NULL, "1682m-gizmo");
173 if (!dn)
174 dn = of_find_compatible_node(NULL, NULL,
175 "pasemi,pwrficient-gizmo");
164 if (!dn) { 176 if (!dn) {
165 err = -ENODEV; 177 err = -ENODEV;
166 goto out_unmap_sdcasr; 178 goto out_unmap_sdcasr;
@@ -292,7 +304,8 @@ static struct cpufreq_driver pas_cpufreq_driver = {
292 304
293static int __init pas_cpufreq_init(void) 305static int __init pas_cpufreq_init(void)
294{ 306{
295 if (!machine_is_compatible("PA6T-1682M")) 307 if (!machine_is_compatible("PA6T-1682M") &&
308 !machine_is_compatible("pasemi,pwrficient"))
296 return -ENODEV; 309 return -ENODEV;
297 310
298 return cpufreq_register_driver(&pas_cpufreq_driver); 311 return cpufreq_register_driver(&pas_cpufreq_driver);
diff --git a/arch/powerpc/platforms/pasemi/electra_ide.c b/arch/powerpc/platforms/pasemi/electra_ide.c
deleted file mode 100644
index 12fb0c949263..000000000000
--- a/arch/powerpc/platforms/pasemi/electra_ide.c
+++ /dev/null
@@ -1,96 +0,0 @@
1/*
2 * Copyright (C) 2007 PA Semi, Inc
3 *
4 * Maintained by: Olof Johansson <olof@lixom.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include <linux/platform_device.h>
21
22#include <asm/prom.h>
23#include <asm/system.h>
24
25/* The electra IDE interface is incredibly simple: Just a device on the localbus
26 * with interrupts hooked up to one of the GPIOs. The device tree contains the
27 * address window and interrupt mappings already, and the pata_platform driver handles
28 * the rest. We just need to hook the two up.
29 */
30
31#define MAX_IFS 4 /* really, we have only one */
32
33static struct platform_device *pdevs[MAX_IFS];
34
35static int __devinit electra_ide_init(void)
36{
37 struct device_node *np;
38 struct resource r[3];
39 int ret = 0;
40 int i;
41
42 np = of_find_compatible_node(NULL, "ide", "electra-ide");
43 i = 0;
44
45 while (np && i < MAX_IFS) {
46 memset(r, 0, sizeof(r));
47
48 /* pata_platform wants two address ranges: one for the base registers,
49 * another for the control (altstatus). It's located at offset 0x3f6 in
50 * the window, but the device tree only has one large register window
51 * that covers both ranges. So we need to split it up by hand here:
52 */
53
54 ret = of_address_to_resource(np, 0, &r[0]);
55 if (ret)
56 goto out;
57 ret = of_address_to_resource(np, 0, &r[1]);
58 if (ret)
59 goto out;
60
61 r[1].start += 0x3f6;
62 r[0].end = r[1].start-1;
63
64 r[2].start = irq_of_parse_and_map(np, 0);
65 r[2].end = irq_of_parse_and_map(np, 0);
66 r[2].flags = IORESOURCE_IRQ;
67
68 pr_debug("registering platform device at 0x%lx/0x%lx, irq is %ld\n",
69 r[0].start, r[1].start, r[2].start);
70 pdevs[i] = platform_device_register_simple("pata_platform", i, r, 3);
71 if (IS_ERR(pdevs[i])) {
72 ret = PTR_ERR(pdevs[i]);
73 pdevs[i] = NULL;
74 goto out;
75 }
76 np = of_find_compatible_node(np, "ide", "electra-ide");
77 }
78out:
79 return ret;
80}
81module_init(electra_ide_init);
82
83static void __devexit electra_ide_exit(void)
84{
85 int i;
86
87 for (i = 0; i < MAX_IFS; i++)
88 if (pdevs[i])
89 platform_device_unregister(pdevs[i]);
90}
91module_exit(electra_ide_exit);
92
93
94MODULE_LICENSE("GPL");
95MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
96MODULE_DESCRIPTION("PA Semi Electra IDE driver");
diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c
index dae9f658122e..b46542990cf8 100644
--- a/arch/powerpc/platforms/pasemi/gpio_mdio.c
+++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c
@@ -30,7 +30,7 @@
30#include <linux/interrupt.h> 30#include <linux/interrupt.h>
31#include <linux/phy.h> 31#include <linux/phy.h>
32#include <linux/platform_device.h> 32#include <linux/platform_device.h>
33#include <asm/of_platform.h> 33#include <linux/of_platform.h>
34 34
35#define DELAY 1 35#define DELAY 1
36 36
@@ -218,45 +218,27 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev,
218 const struct of_device_id *match) 218 const struct of_device_id *match)
219{ 219{
220 struct device *dev = &ofdev->dev; 220 struct device *dev = &ofdev->dev;
221 struct device_node *np = ofdev->node; 221 struct device_node *phy_dn, *np = ofdev->node;
222 struct device_node *gpio_np;
223 struct mii_bus *new_bus; 222 struct mii_bus *new_bus;
224 struct resource res;
225 struct gpio_priv *priv; 223 struct gpio_priv *priv;
226 const unsigned int *prop; 224 const unsigned int *prop;
227 int err = 0; 225 int err;
228 int i; 226 int i;
229 227
230 gpio_np = of_find_compatible_node(NULL, "gpio", "1682m-gpio"); 228 err = -ENOMEM;
231
232 if (!gpio_np)
233 return -ENODEV;
234
235 err = of_address_to_resource(gpio_np, 0, &res);
236 of_node_put(gpio_np);
237
238 if (err)
239 return -EINVAL;
240
241 if (!gpio_regs)
242 gpio_regs = ioremap(res.start, 0x100);
243
244 if (!gpio_regs)
245 return -EPERM;
246
247 priv = kzalloc(sizeof(struct gpio_priv), GFP_KERNEL); 229 priv = kzalloc(sizeof(struct gpio_priv), GFP_KERNEL);
248 if (priv == NULL) 230 if (!priv)
249 return -ENOMEM; 231 goto out;
250 232
251 new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL); 233 new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
252 234
253 if (new_bus == NULL) 235 if (!new_bus)
254 return -ENOMEM; 236 goto out_free_priv;
255 237
256 new_bus->name = "pasemi gpio mdio bus", 238 new_bus->name = "pasemi gpio mdio bus";
257 new_bus->read = &gpio_mdio_read, 239 new_bus->read = &gpio_mdio_read;
258 new_bus->write = &gpio_mdio_write, 240 new_bus->write = &gpio_mdio_write;
259 new_bus->reset = &gpio_mdio_reset, 241 new_bus->reset = &gpio_mdio_reset;
260 242
261 prop = of_get_property(np, "reg", NULL); 243 prop = of_get_property(np, "reg", NULL);
262 new_bus->id = *prop; 244 new_bus->id = *prop;
@@ -265,9 +247,24 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev,
265 new_bus->phy_mask = 0; 247 new_bus->phy_mask = 0;
266 248
267 new_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); 249 new_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
268 for(i = 0; i < PHY_MAX_ADDR; ++i)
269 new_bus->irq[i] = irq_create_mapping(NULL, 10);
270 250
251 if (!new_bus->irq)
252 goto out_free_bus;
253
254 for (i = 0; i < PHY_MAX_ADDR; i++)
255 new_bus->irq[i] = NO_IRQ;
256
257 for (phy_dn = of_get_next_child(np, NULL);
258 phy_dn != NULL;
259 phy_dn = of_get_next_child(np, phy_dn)) {
260 const unsigned int *ip, *regp;
261
262 ip = of_get_property(phy_dn, "interrupts", NULL);
263 regp = of_get_property(phy_dn, "reg", NULL);
264 if (!ip || !regp || *regp >= PHY_MAX_ADDR)
265 continue;
266 new_bus->irq[*regp] = irq_create_mapping(NULL, *ip);
267 }
271 268
272 prop = of_get_property(np, "mdc-pin", NULL); 269 prop = of_get_property(np, "mdc-pin", NULL);
273 priv->mdc_pin = *prop; 270 priv->mdc_pin = *prop;
@@ -280,17 +277,21 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev,
280 277
281 err = mdiobus_register(new_bus); 278 err = mdiobus_register(new_bus);
282 279
283 if (0 != err) { 280 if (err != 0) {
284 printk(KERN_ERR "%s: Cannot register as MDIO bus, err %d\n", 281 printk(KERN_ERR "%s: Cannot register as MDIO bus, err %d\n",
285 new_bus->name, err); 282 new_bus->name, err);
286 goto bus_register_fail; 283 goto out_free_irq;
287 } 284 }
288 285
289 return 0; 286 return 0;
290 287
291bus_register_fail: 288out_free_irq:
289 kfree(new_bus->irq);
290out_free_bus:
292 kfree(new_bus); 291 kfree(new_bus);
293 292out_free_priv:
293 kfree(priv);
294out:
294 return err; 295 return err;
295} 296}
296 297
@@ -317,6 +318,7 @@ static struct of_device_id gpio_mdio_match[] =
317 }, 318 },
318 {}, 319 {},
319}; 320};
321MODULE_DEVICE_TABLE(of, gpio_mdio_match);
320 322
321static struct of_platform_driver gpio_mdio_driver = 323static struct of_platform_driver gpio_mdio_driver =
322{ 324{
@@ -330,12 +332,32 @@ static struct of_platform_driver gpio_mdio_driver =
330 332
331int gpio_mdio_init(void) 333int gpio_mdio_init(void)
332{ 334{
335 struct device_node *np;
336
337 np = of_find_compatible_node(NULL, NULL, "1682m-gpio");
338 if (!np)
339 np = of_find_compatible_node(NULL, NULL,
340 "pasemi,pwrficient-gpio");
341 if (!np)
342 return -ENODEV;
343 gpio_regs = of_iomap(np, 0);
344 of_node_put(np);
345
346 if (!gpio_regs)
347 return -ENODEV;
348
333 return of_register_platform_driver(&gpio_mdio_driver); 349 return of_register_platform_driver(&gpio_mdio_driver);
334} 350}
351module_init(gpio_mdio_init);
335 352
336void gpio_mdio_exit(void) 353void gpio_mdio_exit(void)
337{ 354{
338 of_unregister_platform_driver(&gpio_mdio_driver); 355 of_unregister_platform_driver(&gpio_mdio_driver);
356 if (gpio_regs)
357 iounmap(gpio_regs);
339} 358}
340device_initcall(gpio_mdio_init); 359module_exit(gpio_mdio_exit);
341 360
361MODULE_LICENSE("GPL");
362MODULE_AUTHOR("Olof Johansson <olof@lixom.net>");
363MODULE_DESCRIPTION("Driver for MDIO over GPIO on PA Semi PWRficient-based boards");
diff --git a/arch/powerpc/platforms/pasemi/idle.c b/arch/powerpc/platforms/pasemi/idle.c
index d8e1fcc78513..43911d8b0206 100644
--- a/arch/powerpc/platforms/pasemi/idle.c
+++ b/arch/powerpc/platforms/pasemi/idle.c
@@ -74,9 +74,6 @@ static int pasemi_system_reset_exception(struct pt_regs *regs)
74 74
75static int __init pasemi_idle_init(void) 75static int __init pasemi_idle_init(void)
76{ 76{
77 if (!machine_is(pasemi))
78 return -ENODEV;
79
80#ifndef CONFIG_PPC_PASEMI_CPUFREQ 77#ifndef CONFIG_PPC_PASEMI_CPUFREQ
81 printk(KERN_WARNING "No cpufreq driver, powersavings modes disabled\n"); 78 printk(KERN_WARNING "No cpufreq driver, powersavings modes disabled\n");
82 current_mode = 0; 79 current_mode = 0;
@@ -88,7 +85,7 @@ static int __init pasemi_idle_init(void)
88 85
89 return 0; 86 return 0;
90} 87}
91late_initcall(pasemi_idle_init); 88machine_late_initcall(pasemi, pasemi_idle_init);
92 89
93static int __init idle_param(char *p) 90static int __init idle_param(char *p)
94{ 91{
diff --git a/arch/powerpc/platforms/pasemi/pasemi.h b/arch/powerpc/platforms/pasemi/pasemi.h
index 58b344c6fc38..b1e524f7489d 100644
--- a/arch/powerpc/platforms/pasemi/pasemi.h
+++ b/arch/powerpc/platforms/pasemi/pasemi.h
@@ -17,8 +17,14 @@ extern void idle_doze(void);
17 17
18/* Restore astate to last set */ 18/* Restore astate to last set */
19#ifdef CONFIG_PPC_PASEMI_CPUFREQ 19#ifdef CONFIG_PPC_PASEMI_CPUFREQ
20extern int check_astate(void);
20extern void restore_astate(int cpu); 21extern void restore_astate(int cpu);
21#else 22#else
23static inline int check_astate(void)
24{
25 /* Always return >0 so we never power save */
26 return 1;
27}
22static inline void restore_astate(int cpu) 28static inline void restore_astate(int cpu)
23{ 29{
24} 30}
diff --git a/arch/powerpc/platforms/pasemi/powersave.S b/arch/powerpc/platforms/pasemi/powersave.S
index 6d0fba6aab17..56f45adcd089 100644
--- a/arch/powerpc/platforms/pasemi/powersave.S
+++ b/arch/powerpc/platforms/pasemi/powersave.S
@@ -62,7 +62,16 @@ sleep_common:
62 mflr r0 62 mflr r0
63 std r0, 16(r1) 63 std r0, 16(r1)
64 stdu r1,-64(r1) 64 stdu r1,-64(r1)
65#ifdef CONFIG_PPC_PASEMI_CPUFREQ
66 std r3, 48(r1)
65 67
68 /* Only do power savings when in astate 0 */
69 bl .check_astate
70 cmpwi r3,0
71 bne 1f
72
73 ld r3, 48(r1)
74#endif
66 LOAD_REG_IMMEDIATE(r6,MSR_DR|MSR_IR|MSR_ME|MSR_EE) 75 LOAD_REG_IMMEDIATE(r6,MSR_DR|MSR_IR|MSR_ME|MSR_EE)
67 mfmsr r4 76 mfmsr r4
68 andc r5,r4,r6 77 andc r5,r4,r6
@@ -73,7 +82,7 @@ sleep_common:
73 82
74 mtmsrd r4,0 83 mtmsrd r4,0
75 84
76 addi r1,r1,64 851: addi r1,r1,64
77 ld r0,16(r1) 86 ld r0,16(r1)
78 mtlr r0 87 mtlr r0
79 blr 88 blr
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
index 3d62060498b4..c64fb5bfb37e 100644
--- a/arch/powerpc/platforms/pasemi/setup.c
+++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -27,6 +27,7 @@
27#include <linux/delay.h> 27#include <linux/delay.h>
28#include <linux/console.h> 28#include <linux/console.h>
29#include <linux/pci.h> 29#include <linux/pci.h>
30#include <linux/of_platform.h>
30 31
31#include <asm/prom.h> 32#include <asm/prom.h>
32#include <asm/system.h> 33#include <asm/system.h>
@@ -35,7 +36,7 @@
35#include <asm/mpic.h> 36#include <asm/mpic.h>
36#include <asm/smp.h> 37#include <asm/smp.h>
37#include <asm/time.h> 38#include <asm/time.h>
38#include <asm/of_platform.h> 39#include <asm/mmu.h>
39 40
40#include <pcmcia/ss.h> 41#include <pcmcia/ss.h>
41#include <pcmcia/cistpl.h> 42#include <pcmcia/cistpl.h>
@@ -43,6 +44,10 @@
43 44
44#include "pasemi.h" 45#include "pasemi.h"
45 46
47#if !defined(CONFIG_SMP)
48static void smp_send_stop(void) {}
49#endif
50
46/* SDC reset register, must be pre-mapped at reset time */ 51/* SDC reset register, must be pre-mapped at reset time */
47static void __iomem *reset_reg; 52static void __iomem *reset_reg;
48 53
@@ -56,10 +61,14 @@ struct mce_regs {
56 61
57static struct mce_regs mce_regs[MAX_MCE_REGS]; 62static struct mce_regs mce_regs[MAX_MCE_REGS];
58static int num_mce_regs; 63static int num_mce_regs;
64static int nmi_virq = NO_IRQ;
59 65
60 66
61static void pas_restart(char *cmd) 67static void pas_restart(char *cmd)
62{ 68{
69 /* Need to put others cpu in hold loop so they're not sleeping */
70 smp_send_stop();
71 udelay(10000);
63 printk("Restarting...\n"); 72 printk("Restarting...\n");
64 while (1) 73 while (1)
65 out_le32(reset_reg, 0x6000000); 74 out_le32(reset_reg, 0x6000000);
@@ -126,9 +135,6 @@ static int __init pas_setup_mce_regs(void)
126 struct pci_dev *dev; 135 struct pci_dev *dev;
127 int reg; 136 int reg;
128 137
129 if (!machine_is(pasemi))
130 return -ENODEV;
131
132 /* Remap various SoC status registers for use by the MCE handler */ 138 /* Remap various SoC status registers for use by the MCE handler */
133 139
134 reg = 0; 140 reg = 0;
@@ -172,7 +178,7 @@ static int __init pas_setup_mce_regs(void)
172 178
173 return 0; 179 return 0;
174} 180}
175device_initcall(pas_setup_mce_regs); 181machine_device_initcall(pasemi, pas_setup_mce_regs);
176 182
177static __init void pas_init_IRQ(void) 183static __init void pas_init_IRQ(void)
178{ 184{
@@ -181,6 +187,8 @@ static __init void pas_init_IRQ(void)
181 unsigned long openpic_addr; 187 unsigned long openpic_addr;
182 const unsigned int *opprop; 188 const unsigned int *opprop;
183 int naddr, opplen; 189 int naddr, opplen;
190 int mpic_flags;
191 const unsigned int *nmiprop;
184 struct mpic *mpic; 192 struct mpic *mpic;
185 193
186 mpic_node = NULL; 194 mpic_node = NULL;
@@ -213,13 +221,26 @@ static __init void pas_init_IRQ(void)
213 openpic_addr = of_read_number(opprop, naddr); 221 openpic_addr = of_read_number(opprop, naddr);
214 printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr); 222 printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
215 223
224 mpic_flags = MPIC_PRIMARY | MPIC_LARGE_VECTORS | MPIC_NO_BIAS;
225
226 nmiprop = of_get_property(mpic_node, "nmi-source", NULL);
227 if (nmiprop)
228 mpic_flags |= MPIC_ENABLE_MCK;
229
216 mpic = mpic_alloc(mpic_node, openpic_addr, 230 mpic = mpic_alloc(mpic_node, openpic_addr,
217 MPIC_PRIMARY|MPIC_LARGE_VECTORS, 231 mpic_flags, 0, 0, "PASEMI-OPIC");
218 0, 0, " PAS-OPIC ");
219 BUG_ON(!mpic); 232 BUG_ON(!mpic);
220 233
221 mpic_assign_isu(mpic, 0, openpic_addr + 0x10000); 234 mpic_assign_isu(mpic, 0, openpic_addr + 0x10000);
222 mpic_init(mpic); 235 mpic_init(mpic);
236 /* The NMI/MCK source needs to be prio 15 */
237 if (nmiprop) {
238 nmi_virq = irq_create_mapping(NULL, *nmiprop);
239 mpic_irq_set_priority(nmi_virq, 15);
240 set_irq_type(nmi_virq, IRQ_TYPE_EDGE_RISING);
241 mpic_unmask_irq(nmi_virq);
242 }
243
223 of_node_put(mpic_node); 244 of_node_put(mpic_node);
224 of_node_put(root); 245 of_node_put(root);
225} 246}
@@ -239,6 +260,14 @@ static int pas_machine_check_handler(struct pt_regs *regs)
239 260
240 srr0 = regs->nip; 261 srr0 = regs->nip;
241 srr1 = regs->msr; 262 srr1 = regs->msr;
263
264 if (nmi_virq != NO_IRQ && mpic_get_mcirq() == nmi_virq) {
265 printk(KERN_ERR "NMI delivered\n");
266 debugger(regs);
267 mpic_end_irq(nmi_virq);
268 goto out;
269 }
270
242 dsisr = mfspr(SPRN_DSISR); 271 dsisr = mfspr(SPRN_DSISR);
243 printk(KERN_ERR "Machine Check on CPU %d\n", cpu); 272 printk(KERN_ERR "Machine Check on CPU %d\n", cpu);
244 printk(KERN_ERR "SRR0 0x%016lx SRR1 0x%016lx\n", srr0, srr1); 273 printk(KERN_ERR "SRR0 0x%016lx SRR1 0x%016lx\n", srr0, srr1);
@@ -295,14 +324,14 @@ static int pas_machine_check_handler(struct pt_regs *regs)
295 int i; 324 int i;
296 325
297 printk(KERN_ERR "slb contents:\n"); 326 printk(KERN_ERR "slb contents:\n");
298 for (i = 0; i < SLB_NUM_ENTRIES; i++) { 327 for (i = 0; i < mmu_slb_size; i++) {
299 asm volatile("slbmfee %0,%1" : "=r" (e) : "r" (i)); 328 asm volatile("slbmfee %0,%1" : "=r" (e) : "r" (i));
300 asm volatile("slbmfev %0,%1" : "=r" (v) : "r" (i)); 329 asm volatile("slbmfev %0,%1" : "=r" (v) : "r" (i));
301 printk(KERN_ERR "%02d %016lx %016lx\n", i, e, v); 330 printk(KERN_ERR "%02d %016lx %016lx\n", i, e, v);
302 } 331 }
303 } 332 }
304 333
305 334out:
306 /* SRR1[62] is from MSR[62] if recoverable, so pass that back */ 335 /* SRR1[62] is from MSR[62] if recoverable, so pass that back */
307 return !!(srr1 & 0x2); 336 return !!(srr1 & 0x2);
308} 337}
@@ -362,16 +391,17 @@ static inline void pasemi_pcmcia_init(void)
362 391
363 392
364static struct of_device_id pasemi_bus_ids[] = { 393static struct of_device_id pasemi_bus_ids[] = {
394 /* Unfortunately needed for legacy firmwares */
365 { .type = "localbus", }, 395 { .type = "localbus", },
366 { .type = "sdc", }, 396 { .type = "sdc", },
397 /* These are the proper entries, which newer firmware uses */
398 { .compatible = "pasemi,localbus", },
399 { .compatible = "pasemi,sdc", },
367 {}, 400 {},
368}; 401};
369 402
370static int __init pasemi_publish_devices(void) 403static int __init pasemi_publish_devices(void)
371{ 404{
372 if (!machine_is(pasemi))
373 return 0;
374
375 pasemi_pcmcia_init(); 405 pasemi_pcmcia_init();
376 406
377 /* Publish OF platform devices for SDC and other non-PCI devices */ 407 /* Publish OF platform devices for SDC and other non-PCI devices */
@@ -379,7 +409,7 @@ static int __init pasemi_publish_devices(void)
379 409
380 return 0; 410 return 0;
381} 411}
382device_initcall(pasemi_publish_devices); 412machine_device_initcall(pasemi, pasemi_publish_devices);
383 413
384 414
385/* 415/*
@@ -389,7 +419,8 @@ static int __init pas_probe(void)
389{ 419{
390 unsigned long root = of_get_flat_dt_root(); 420 unsigned long root = of_get_flat_dt_root();
391 421
392 if (!of_flat_dt_is_compatible(root, "PA6T-1682M")) 422 if (!of_flat_dt_is_compatible(root, "PA6T-1682M") &&
423 !of_flat_dt_is_compatible(root, "pasemi,pwrficient"))
393 return 0; 424 return 0;
394 425
395 hpte_init_native(); 426 hpte_init_native();
@@ -400,7 +431,7 @@ static int __init pas_probe(void)
400} 431}
401 432
402define_machine(pasemi) { 433define_machine(pasemi) {
403 .name = "PA Semi PA6T-1682M", 434 .name = "PA Semi PWRficient",
404 .probe = pas_probe, 435 .probe = pas_probe,
405 .setup_arch = pas_setup_arch, 436 .setup_arch = pas_setup_arch,
406 .init_early = pas_init_early, 437 .init_early = pas_init_early,
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index da2007e3db0e..21226b74c9b2 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -585,8 +585,7 @@ static void __init kw_i2c_probe(void)
585 struct device_node *np, *child, *parent; 585 struct device_node *np, *child, *parent;
586 586
587 /* Probe keywest-i2c busses */ 587 /* Probe keywest-i2c busses */
588 for (np = NULL; 588 for_each_compatible_node(np, "i2c","keywest-i2c") {
589 (np = of_find_compatible_node(np, "i2c","keywest-i2c")) != NULL;){
590 struct pmac_i2c_host_kw *host; 589 struct pmac_i2c_host_kw *host;
591 int multibus, chans, i; 590 int multibus, chans, i;
592 591
@@ -1462,9 +1461,6 @@ int __init pmac_i2c_init(void)
1462 return 0; 1461 return 0;
1463 i2c_inited = 1; 1462 i2c_inited = 1;
1464 1463
1465 if (!machine_is(powermac))
1466 return 0;
1467
1468 /* Probe keywest-i2c busses */ 1464 /* Probe keywest-i2c busses */
1469 kw_i2c_probe(); 1465 kw_i2c_probe();
1470 1466
@@ -1483,7 +1479,7 @@ int __init pmac_i2c_init(void)
1483 1479
1484 return 0; 1480 return 0;
1485} 1481}
1486arch_initcall(pmac_i2c_init); 1482machine_arch_initcall(powermac, pmac_i2c_init);
1487 1483
1488/* Since pmac_i2c_init can be called too early for the platform device 1484/* Since pmac_i2c_init can be called too early for the platform device
1489 * registration, we need to do it at a later time. In our case, subsys 1485 * registration, we need to do it at a later time. In our case, subsys
@@ -1515,4 +1511,4 @@ static int __init pmac_i2c_create_platform_devices(void)
1515 1511
1516 return 0; 1512 return 0;
1517} 1513}
1518subsys_initcall(pmac_i2c_create_platform_devices); 1514machine_subsys_initcall(powermac, pmac_i2c_create_platform_devices);
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index f852ae3e0ee4..1c58db9d42cb 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -40,8 +40,6 @@
40static int has_uninorth; 40static int has_uninorth;
41#ifdef CONFIG_PPC64 41#ifdef CONFIG_PPC64
42static struct pci_controller *u3_agp; 42static struct pci_controller *u3_agp;
43static struct pci_controller *u4_pcie;
44static struct pci_controller *u3_ht;
45#else 43#else
46static int has_second_ohare; 44static int has_second_ohare;
47#endif /* CONFIG_PPC64 */ 45#endif /* CONFIG_PPC64 */
@@ -314,12 +312,15 @@ static int u3_ht_skip_device(struct pci_controller *hose,
314 312
315 /* We only allow config cycles to devices that are in OF device-tree 313 /* We only allow config cycles to devices that are in OF device-tree
316 * as we are apparently having some weird things going on with some 314 * as we are apparently having some weird things going on with some
317 * revs of K2 on recent G5s 315 * revs of K2 on recent G5s, except for the host bridge itself, which
316 * is missing from the tree but we know we can probe.
318 */ 317 */
319 if (bus->self) 318 if (bus->self)
320 busdn = pci_device_to_OF_node(bus->self); 319 busdn = pci_device_to_OF_node(bus->self);
320 else if (devfn == 0)
321 return 0;
321 else 322 else
322 busdn = hose->arch_data; 323 busdn = hose->dn;
323 for (dn = busdn->child; dn; dn = dn->sibling) 324 for (dn = busdn->child; dn; dn = dn->sibling)
324 if (PCI_DN(dn) && PCI_DN(dn)->devfn == devfn) 325 if (PCI_DN(dn) && PCI_DN(dn)->devfn == devfn)
325 break; 326 break;
@@ -344,14 +345,15 @@ static int u3_ht_skip_device(struct pci_controller *hose,
344 + (((unsigned int)bus) << 16) \ 345 + (((unsigned int)bus) << 16) \
345 + 0x01000000UL) 346 + 0x01000000UL)
346 347
347static volatile void __iomem *u3_ht_cfg_access(struct pci_controller* hose, 348static void __iomem *u3_ht_cfg_access(struct pci_controller *hose, u8 bus,
348 u8 bus, u8 devfn, u8 offset) 349 u8 devfn, u8 offset, int *swap)
349{ 350{
351 *swap = 1;
350 if (bus == hose->first_busno) { 352 if (bus == hose->first_busno) {
351 /* For now, we don't self probe U3 HT bridge */ 353 if (devfn != 0)
352 if (PCI_SLOT(devfn) == 0) 354 return hose->cfg_data + U3_HT_CFA0(devfn, offset);
353 return NULL; 355 *swap = 0;
354 return hose->cfg_data + U3_HT_CFA0(devfn, offset); 356 return ((void __iomem *)hose->cfg_addr) + (offset << 2);
355 } else 357 } else
356 return hose->cfg_data + U3_HT_CFA1(bus, devfn, offset); 358 return hose->cfg_data + U3_HT_CFA1(bus, devfn, offset);
357} 359}
@@ -360,14 +362,15 @@ static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
360 int offset, int len, u32 *val) 362 int offset, int len, u32 *val)
361{ 363{
362 struct pci_controller *hose; 364 struct pci_controller *hose;
363 volatile void __iomem *addr; 365 void __iomem *addr;
366 int swap;
364 367
365 hose = pci_bus_to_host(bus); 368 hose = pci_bus_to_host(bus);
366 if (hose == NULL) 369 if (hose == NULL)
367 return PCIBIOS_DEVICE_NOT_FOUND; 370 return PCIBIOS_DEVICE_NOT_FOUND;
368 if (offset >= 0x100) 371 if (offset >= 0x100)
369 return PCIBIOS_BAD_REGISTER_NUMBER; 372 return PCIBIOS_BAD_REGISTER_NUMBER;
370 addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); 373 addr = u3_ht_cfg_access(hose, bus->number, devfn, offset, &swap);
371 if (!addr) 374 if (!addr)
372 return PCIBIOS_DEVICE_NOT_FOUND; 375 return PCIBIOS_DEVICE_NOT_FOUND;
373 376
@@ -397,10 +400,10 @@ static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
397 *val = in_8(addr); 400 *val = in_8(addr);
398 break; 401 break;
399 case 2: 402 case 2:
400 *val = in_le16(addr); 403 *val = swap ? in_le16(addr) : in_be16(addr);
401 break; 404 break;
402 default: 405 default:
403 *val = in_le32(addr); 406 *val = swap ? in_le32(addr) : in_be32(addr);
404 break; 407 break;
405 } 408 }
406 return PCIBIOS_SUCCESSFUL; 409 return PCIBIOS_SUCCESSFUL;
@@ -410,14 +413,15 @@ static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn,
410 int offset, int len, u32 val) 413 int offset, int len, u32 val)
411{ 414{
412 struct pci_controller *hose; 415 struct pci_controller *hose;
413 volatile void __iomem *addr; 416 void __iomem *addr;
417 int swap;
414 418
415 hose = pci_bus_to_host(bus); 419 hose = pci_bus_to_host(bus);
416 if (hose == NULL) 420 if (hose == NULL)
417 return PCIBIOS_DEVICE_NOT_FOUND; 421 return PCIBIOS_DEVICE_NOT_FOUND;
418 if (offset >= 0x100) 422 if (offset >= 0x100)
419 return PCIBIOS_BAD_REGISTER_NUMBER; 423 return PCIBIOS_BAD_REGISTER_NUMBER;
420 addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); 424 addr = u3_ht_cfg_access(hose, bus->number, devfn, offset, &swap);
421 if (!addr) 425 if (!addr)
422 return PCIBIOS_DEVICE_NOT_FOUND; 426 return PCIBIOS_DEVICE_NOT_FOUND;
423 427
@@ -439,10 +443,10 @@ static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn,
439 out_8(addr, val); 443 out_8(addr, val);
440 break; 444 break;
441 case 2: 445 case 2:
442 out_le16(addr, val); 446 swap ? out_le16(addr, val) : out_be16(addr, val);
443 break; 447 break;
444 default: 448 default:
445 out_le32((u32 __iomem *)addr, val); 449 swap ? out_le32(addr, val) : out_be32(addr, val);
446 break; 450 break;
447 } 451 }
448 return PCIBIOS_SUCCESSFUL; 452 return PCIBIOS_SUCCESSFUL;
@@ -725,7 +729,7 @@ static void __init setup_bandit(struct pci_controller *hose,
725static int __init setup_uninorth(struct pci_controller *hose, 729static int __init setup_uninorth(struct pci_controller *hose,
726 struct resource *addr) 730 struct resource *addr)
727{ 731{
728 pci_assign_all_buses = 1; 732 ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
729 has_uninorth = 1; 733 has_uninorth = 1;
730 hose->ops = &macrisc_pci_ops; 734 hose->ops = &macrisc_pci_ops;
731 hose->cfg_addr = ioremap(addr->start + 0x800000, 0x1000); 735 hose->cfg_addr = ioremap(addr->start + 0x800000, 0x1000);
@@ -773,31 +777,72 @@ static void __init setup_u4_pcie(struct pci_controller* hose)
773 */ 777 */
774 hose->first_busno = 0x00; 778 hose->first_busno = 0x00;
775 hose->last_busno = 0xff; 779 hose->last_busno = 0xff;
776 u4_pcie = hose;
777} 780}
778 781
779static void __init setup_u3_ht(struct pci_controller* hose) 782static void __init parse_region_decode(struct pci_controller *hose,
783 u32 decode)
780{ 784{
781 struct device_node *np = (struct device_node *)hose->arch_data; 785 unsigned long base, end, next = -1;
782 struct pci_controller *other = NULL; 786 int i, cur = -1;
783 int i, cur;
784 787
788 /* Iterate through all bits. We ignore the last bit as this region is
789 * reserved for the ROM among other niceties
790 */
791 for (i = 0; i < 31; i++) {
792 if ((decode & (0x80000000 >> i)) == 0)
793 continue;
794 if (i < 16) {
795 base = 0xf0000000 | (((u32)i) << 24);
796 end = base + 0x00ffffff;
797 } else {
798 base = ((u32)i-16) << 28;
799 end = base + 0x0fffffff;
800 }
801 if (base != next) {
802 if (++cur >= 3) {
803 printk(KERN_WARNING "PCI: Too many ranges !\n");
804 break;
805 }
806 hose->mem_resources[cur].flags = IORESOURCE_MEM;
807 hose->mem_resources[cur].name = hose->dn->full_name;
808 hose->mem_resources[cur].start = base;
809 hose->mem_resources[cur].end = end;
810 DBG(" %d: 0x%08lx-0x%08lx\n", cur, base, end);
811 } else {
812 DBG(" : -0x%08lx\n", end);
813 hose->mem_resources[cur].end = end;
814 }
815 next = end + 1;
816 }
817}
818
819static void __init setup_u3_ht(struct pci_controller* hose)
820{
821 struct device_node *np = hose->dn;
822 struct resource cfg_res, self_res;
823 u32 decode;
785 824
786 hose->ops = &u3_ht_pci_ops; 825 hose->ops = &u3_ht_pci_ops;
787 826
788 /* We hard code the address because of the different size of 827 /* Get base addresses from OF tree
789 * the reg address cell, we shall fix that by killing struct
790 * reg_property and using some accessor functions instead
791 */ 828 */
792 hose->cfg_data = ioremap(0xf2000000, 0x02000000); 829 if (of_address_to_resource(np, 0, &cfg_res) ||
830 of_address_to_resource(np, 1, &self_res)) {
831 printk(KERN_ERR "PCI: Failed to get U3/U4 HT resources !\n");
832 return;
833 }
834
835 /* Map external cfg space access into cfg_data and self registers
836 * into cfg_addr
837 */
838 hose->cfg_data = ioremap(cfg_res.start, 0x02000000);
839 hose->cfg_addr = ioremap(self_res.start,
840 self_res.end - self_res.start + 1);
793 841
794 /* 842 /*
795 * /ht node doesn't expose a "ranges" property, so we "remove" 843 * /ht node doesn't expose a "ranges" property, we read the register
796 * regions that have been allocated to AGP. So far, this version of 844 * that controls the decoding logic and use that for memory regions.
797 * the code doesn't assign any of the 0xfxxxxxxx "fine" memory regions 845 * The IO region is hard coded since it is fixed in HW as well.
798 * to /ht. We need to fix that sooner or later by either parsing all
799 * child "ranges" properties or figuring out the U3 address space
800 * decoding logic and then read its configuration register (if any).
801 */ 846 */
802 hose->io_base_phys = 0xf4000000; 847 hose->io_base_phys = 0xf4000000;
803 hose->pci_io_size = 0x00400000; 848 hose->pci_io_size = 0x00400000;
@@ -808,76 +853,33 @@ static void __init setup_u3_ht(struct pci_controller* hose)
808 hose->pci_mem_offset = 0; 853 hose->pci_mem_offset = 0;
809 hose->first_busno = 0; 854 hose->first_busno = 0;
810 hose->last_busno = 0xef; 855 hose->last_busno = 0xef;
811 hose->mem_resources[0].name = np->full_name;
812 hose->mem_resources[0].start = 0x80000000;
813 hose->mem_resources[0].end = 0xefffffff;
814 hose->mem_resources[0].flags = IORESOURCE_MEM;
815
816 u3_ht = hose;
817 856
818 if (u3_agp != NULL) 857 /* Note: fix offset when cfg_addr becomes a void * */
819 other = u3_agp; 858 decode = in_be32(hose->cfg_addr + 0x80);
820 else if (u4_pcie != NULL)
821 other = u4_pcie;
822
823 if (other == NULL) {
824 DBG("U3/4 has no AGP/PCIE, using full resource range\n");
825 return;
826 }
827 859
828 /* Fixup bus range vs. PCIE */ 860 DBG("PCI: Apple HT bridge decode register: 0x%08x\n", decode);
829 if (u4_pcie)
830 hose->last_busno = u4_pcie->first_busno - 1;
831 861
832 /* We "remove" the AGP resources from the resources allocated to HT, 862 /* NOTE: The decode register setup is a bit weird... region
833 * that is we create "holes". However, that code does assumptions 863 * 0xf8000000 for example is marked as enabled in there while it's
834 * that so far happen to be true (cross fingers...), typically that 864 & actually the memory controller registers.
835 * resources in the AGP node are properly ordered 865 * That means that we are incorrectly attributing it to HT.
866 *
867 * In a similar vein, region 0xf4000000 is actually the HT IO space but
868 * also marked as enabled in here and 0xf9000000 is used by some other
869 * internal bits of the northbridge.
870 *
871 * Unfortunately, we can't just mask out those bit as we would end
872 * up with more regions than we can cope (linux can only cope with
873 * 3 memory regions for a PHB at this stage).
874 *
875 * So for now, we just do a little hack. We happen to -know- that
876 * Apple firmware doesn't assign things below 0xfa000000 for that
877 * bridge anyway so we mask out all bits we don't want.
836 */ 878 */
837 cur = 0; 879 decode &= 0x003fffff;
838 for (i=0; i<3; i++) { 880
839 struct resource *res = &other->mem_resources[i]; 881 /* Now parse the resulting bits and build resources */
840 if (res->flags != IORESOURCE_MEM) 882 parse_region_decode(hose, decode);
841 continue;
842 /* We don't care about "fine" resources */
843 if (res->start >= 0xf0000000)
844 continue;
845 /* Check if it's just a matter of "shrinking" us in one
846 * direction
847 */
848 if (hose->mem_resources[cur].start == res->start) {
849 DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n",
850 cur, hose->mem_resources[cur].start,
851 res->end + 1);
852 hose->mem_resources[cur].start = res->end + 1;
853 continue;
854 }
855 if (hose->mem_resources[cur].end == res->end) {
856 DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n",
857 cur, hose->mem_resources[cur].end,
858 res->start - 1);
859 hose->mem_resources[cur].end = res->start - 1;
860 continue;
861 }
862 /* No, it's not the case, we need a hole */
863 if (cur == 2) {
864 /* not enough resources for a hole, we drop part
865 * of the range
866 */
867 printk(KERN_WARNING "Running out of resources"
868 " for /ht host !\n");
869 hose->mem_resources[cur].end = res->start - 1;
870 continue;
871 }
872 cur++;
873 DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n",
874 cur-1, res->start - 1, cur, res->end + 1);
875 hose->mem_resources[cur].name = np->full_name;
876 hose->mem_resources[cur].flags = IORESOURCE_MEM;
877 hose->mem_resources[cur].start = res->end + 1;
878 hose->mem_resources[cur].end = hose->mem_resources[cur-1].end;
879 hose->mem_resources[cur-1].end = res->start - 1;
880 }
881} 883}
882#endif /* CONFIG_PPC64 */ 884#endif /* CONFIG_PPC64 */
883 885
@@ -994,6 +996,8 @@ void __init pmac_pci_init(void)
994 struct device_node *np, *root; 996 struct device_node *np, *root;
995 struct device_node *ht = NULL; 997 struct device_node *ht = NULL;
996 998
999 ppc_pci_flags = PPC_PCI_CAN_SKIP_ISA_ALIGN;
1000
997 root = of_find_node_by_path("/"); 1001 root = of_find_node_by_path("/");
998 if (root == NULL) { 1002 if (root == NULL) {
999 printk(KERN_CRIT "pmac_pci_init: can't find root " 1003 printk(KERN_CRIT "pmac_pci_init: can't find root "
@@ -1032,15 +1036,15 @@ void __init pmac_pci_init(void)
1032 * future though 1036 * future though
1033 */ 1037 */
1034 if (u3_agp) { 1038 if (u3_agp) {
1035 struct device_node *np = u3_agp->arch_data; 1039 struct device_node *np = u3_agp->dn;
1036 PCI_DN(np)->busno = 0xf0; 1040 PCI_DN(np)->busno = 0xf0;
1037 for (np = np->child; np; np = np->sibling) 1041 for (np = np->child; np; np = np->sibling)
1038 PCI_DN(np)->busno = 0xf0; 1042 PCI_DN(np)->busno = 0xf0;
1039 } 1043 }
1040 /* pmac_check_ht_link(); */ 1044 /* pmac_check_ht_link(); */
1041 1045
1042 /* Tell pci.c to not use the common resource allocation mechanism */ 1046 /* We can allocate missing resources if any */
1043 pci_probe_only = 1; 1047 pci_probe_only = 0;
1044 1048
1045#else /* CONFIG_PPC64 */ 1049#else /* CONFIG_PPC64 */
1046 init_p2pbridge(); 1050 init_p2pbridge();
@@ -1051,13 +1055,13 @@ void __init pmac_pci_init(void)
1051 * some offset between bus number and domains for now when we 1055 * some offset between bus number and domains for now when we
1052 * assign all busses should help for now 1056 * assign all busses should help for now
1053 */ 1057 */
1054 if (pci_assign_all_buses) 1058 if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_BUS)
1055 pcibios_assign_bus_offset = 0x10; 1059 pcibios_assign_bus_offset = 0x10;
1056#endif 1060#endif
1057} 1061}
1058 1062
1059int 1063#ifdef CONFIG_PPC32
1060pmac_pci_enable_device_hook(struct pci_dev *dev, int initial) 1064int pmac_pci_enable_device_hook(struct pci_dev *dev)
1061{ 1065{
1062 struct device_node* node; 1066 struct device_node* node;
1063 int updatecfg = 0; 1067 int updatecfg = 0;
@@ -1099,24 +1103,21 @@ pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
1099 updatecfg = 1; 1103 updatecfg = 1;
1100 } 1104 }
1101 1105
1106 /*
1107 * Fixup various header fields on 32 bits. We don't do that on
1108 * 64 bits as some of these have strange values behind the HT
1109 * bridge and we must not, for example, enable MWI or set the
1110 * cache line size on them.
1111 */
1102 if (updatecfg) { 1112 if (updatecfg) {
1103 u16 cmd; 1113 u16 cmd;
1104 1114
1105 /*
1106 * Make sure PCI is correctly configured
1107 *
1108 * We use old pci_bios versions of the function since, by
1109 * default, gmac is not powered up, and so will be absent
1110 * from the kernel initial PCI lookup.
1111 *
1112 * Should be replaced by 2.4 new PCI mechanisms and really
1113 * register the device.
1114 */
1115 pci_read_config_word(dev, PCI_COMMAND, &cmd); 1115 pci_read_config_word(dev, PCI_COMMAND, &cmd);
1116 cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER 1116 cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER
1117 | PCI_COMMAND_INVALIDATE; 1117 | PCI_COMMAND_INVALIDATE;
1118 pci_write_config_word(dev, PCI_COMMAND, cmd); 1118 pci_write_config_word(dev, PCI_COMMAND, cmd);
1119 pci_write_config_byte(dev, PCI_LATENCY_TIMER, 16); 1119 pci_write_config_byte(dev, PCI_LATENCY_TIMER, 16);
1120
1120 pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 1121 pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
1121 L1_CACHE_BYTES >> 2); 1122 L1_CACHE_BYTES >> 2);
1122 } 1123 }
@@ -1124,6 +1125,18 @@ pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
1124 return 0; 1125 return 0;
1125} 1126}
1126 1127
1128void __devinit pmac_pci_fixup_ohci(struct pci_dev *dev)
1129{
1130 struct device_node *node = pci_device_to_OF_node(dev);
1131
1132 /* We don't want to assign resources to USB controllers
1133 * absent from the OF tree (iBook second controller)
1134 */
1135 if (dev->class == PCI_CLASS_SERIAL_USB_OHCI && !node)
1136 dev->resource[0].flags = 0;
1137}
1138DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_APPLE, PCI_ANY_ID, pmac_pci_fixup_ohci);
1139
1127/* We power down some devices after they have been probed. They'll 1140/* We power down some devices after they have been probed. They'll
1128 * be powered back on later on 1141 * be powered back on later on
1129 */ 1142 */
@@ -1171,7 +1184,6 @@ void __init pmac_pcibios_after_init(void)
1171 of_node_put(nd); 1184 of_node_put(nd);
1172} 1185}
1173 1186
1174#ifdef CONFIG_PPC32
1175void pmac_pci_fixup_cardbus(struct pci_dev* dev) 1187void pmac_pci_fixup_cardbus(struct pci_dev* dev)
1176{ 1188{
1177 if (!machine_is(powermac)) 1189 if (!machine_is(powermac))
@@ -1259,7 +1271,7 @@ void pmac_pci_fixup_pciata(struct pci_dev* dev)
1259 } 1271 }
1260} 1272}
1261DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, pmac_pci_fixup_pciata); 1273DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, pmac_pci_fixup_pciata);
1262#endif 1274#endif /* CONFIG_PPC32 */
1263 1275
1264/* 1276/*
1265 * Disable second function on K2-SATA, it's broken 1277 * Disable second function on K2-SATA, it's broken
diff --git a/arch/powerpc/platforms/powermac/pfunc_base.c b/arch/powerpc/platforms/powermac/pfunc_base.c
index 45d54b9ad9e0..db20de512f3e 100644
--- a/arch/powerpc/platforms/powermac/pfunc_base.c
+++ b/arch/powerpc/platforms/powermac/pfunc_base.c
@@ -363,8 +363,7 @@ int __init pmac_pfunc_base_install(void)
363 363
364 return 0; 364 return 0;
365} 365}
366 366machine_arch_initcall(powermac, pmac_pfunc_base_install);
367arch_initcall(pmac_pfunc_base_install);
368 367
369#ifdef CONFIG_PM 368#ifdef CONFIG_PM
370 369
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 84c0d4ef76a2..40736400ef80 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -690,6 +690,5 @@ static int __init init_pmacpic_sysfs(void)
690 sysdev_driver_register(&pmacpic_sysclass, &driver_pmacpic); 690 sysdev_driver_register(&pmacpic_sysclass, &driver_pmacpic);
691 return 0; 691 return 0;
692} 692}
693 693machine_subsys_initcall(powermac, init_pmacpic_sysfs);
694subsys_initcall(init_pmacpic_sysfs);
695 694
diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h
index fcde070f7054..b3abaaf61eb4 100644
--- a/arch/powerpc/platforms/powermac/pmac.h
+++ b/arch/powerpc/platforms/powermac/pmac.h
@@ -26,7 +26,7 @@ extern void pmac_pci_init(void);
26extern void pmac_nvram_update(void); 26extern void pmac_nvram_update(void);
27extern unsigned char pmac_nvram_read_byte(int addr); 27extern unsigned char pmac_nvram_read_byte(int addr);
28extern void pmac_nvram_write_byte(int addr, unsigned char val); 28extern void pmac_nvram_write_byte(int addr, unsigned char val);
29extern int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial); 29extern int pmac_pci_enable_device_hook(struct pci_dev *dev);
30extern void pmac_pcibios_after_init(void); 30extern void pmac_pcibios_after_init(void);
31extern int of_show_percpuinfo(struct seq_file *m, int i); 31extern int of_show_percpuinfo(struct seq_file *m, int i);
32 32
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 02c533096627..36ff1b6b7fac 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -51,6 +51,8 @@
51#include <linux/root_dev.h> 51#include <linux/root_dev.h>
52#include <linux/bitops.h> 52#include <linux/bitops.h>
53#include <linux/suspend.h> 53#include <linux/suspend.h>
54#include <linux/of_device.h>
55#include <linux/of_platform.h>
54 56
55#include <asm/reg.h> 57#include <asm/reg.h>
56#include <asm/sections.h> 58#include <asm/sections.h>
@@ -68,8 +70,6 @@
68#include <asm/btext.h> 70#include <asm/btext.h>
69#include <asm/pmac_feature.h> 71#include <asm/pmac_feature.h>
70#include <asm/time.h> 72#include <asm/time.h>
71#include <asm/of_device.h>
72#include <asm/of_platform.h>
73#include <asm/mmu_context.h> 73#include <asm/mmu_context.h>
74#include <asm/iommu.h> 74#include <asm/iommu.h>
75#include <asm/smu.h> 75#include <asm/smu.h>
@@ -94,7 +94,6 @@ extern struct machdep_calls pmac_md;
94#define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */ 94#define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */
95 95
96#ifdef CONFIG_PPC64 96#ifdef CONFIG_PPC64
97#include <asm/udbg.h>
98int sccdbg; 97int sccdbg;
99#endif 98#endif
100 99
@@ -398,17 +397,13 @@ static int initializing = 1;
398 397
399static int pmac_late_init(void) 398static int pmac_late_init(void)
400{ 399{
401 if (!machine_is(powermac))
402 return -ENODEV;
403
404 initializing = 0; 400 initializing = 0;
405 /* this is udbg (which is __init) and we can later use it during 401 /* this is udbg (which is __init) and we can later use it during
406 * cpu hotplug (in smp_core99_kick_cpu) */ 402 * cpu hotplug (in smp_core99_kick_cpu) */
407 ppc_md.progress = NULL; 403 ppc_md.progress = NULL;
408 return 0; 404 return 0;
409} 405}
410 406machine_late_initcall(powermac, pmac_late_init);
411late_initcall(pmac_late_init);
412 407
413/* 408/*
414 * This is __init_refok because we check for "initializing" before 409 * This is __init_refok because we check for "initializing" before
@@ -535,9 +530,6 @@ static int __init pmac_declare_of_platform_devices(void)
535 if (machine_is(chrp)) 530 if (machine_is(chrp))
536 return -1; 531 return -1;
537 532
538 if (!machine_is(powermac))
539 return 0;
540
541 np = of_find_node_by_name(NULL, "valkyrie"); 533 np = of_find_node_by_name(NULL, "valkyrie");
542 if (np) 534 if (np)
543 of_platform_device_create(np, "valkyrie", NULL); 535 of_platform_device_create(np, "valkyrie", NULL);
@@ -552,8 +544,7 @@ static int __init pmac_declare_of_platform_devices(void)
552 544
553 return 0; 545 return 0;
554} 546}
555 547machine_device_initcall(powermac, pmac_declare_of_platform_devices);
556device_initcall(pmac_declare_of_platform_devices);
557 548
558/* 549/*
559 * Called very early, MMU is off, device-tree isn't unflattened 550 * Called very early, MMU is off, device-tree isn't unflattened
@@ -613,9 +604,11 @@ static int pmac_pci_probe_mode(struct pci_bus *bus)
613 604
614 /* We need to use normal PCI probing for the AGP bus, 605 /* We need to use normal PCI probing for the AGP bus,
615 * since the device for the AGP bridge isn't in the tree. 606 * since the device for the AGP bridge isn't in the tree.
607 * Same for the PCIe host on U4 and the HT host bridge.
616 */ 608 */
617 if (bus->self == NULL && (of_device_is_compatible(node, "u3-agp") || 609 if (bus->self == NULL && (of_device_is_compatible(node, "u3-agp") ||
618 of_device_is_compatible(node, "u4-pcie"))) 610 of_device_is_compatible(node, "u4-pcie") ||
611 of_device_is_compatible(node, "u3-ht")))
619 return PCI_PROBE_NORMAL; 612 return PCI_PROBE_NORMAL;
620 return PCI_PROBE_DEVTREE; 613 return PCI_PROBE_DEVTREE;
621} 614}
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c
index bf9da56942e8..bbbefd64ab59 100644
--- a/arch/powerpc/platforms/powermac/time.c
+++ b/arch/powerpc/platforms/powermac/time.c
@@ -84,12 +84,14 @@ long __init pmac_time_init(void)
84 return delta; 84 return delta;
85} 85}
86 86
87#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
87static void to_rtc_time(unsigned long now, struct rtc_time *tm) 88static void to_rtc_time(unsigned long now, struct rtc_time *tm)
88{ 89{
89 to_tm(now, tm); 90 to_tm(now, tm);
90 tm->tm_year -= 1900; 91 tm->tm_year -= 1900;
91 tm->tm_mon -= 1; 92 tm->tm_mon -= 1;
92} 93}
94#endif
93 95
94static unsigned long from_rtc_time(struct rtc_time *tm) 96static unsigned long from_rtc_time(struct rtc_time *tm)
95{ 97{
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
index 298f1c9679fb..a5f4e95dfc3d 100644
--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -61,17 +61,6 @@ config PS3_DYNAMIC_DMA
61 This support is mainly for Linux kernel development. If unsure, 61 This support is mainly for Linux kernel development. If unsure,
62 say N. 62 say N.
63 63
64config PS3_USE_LPAR_ADDR
65 depends on PPC_PS3 && EXPERIMENTAL
66 bool "PS3 use lpar address space"
67 default y
68 help
69 This option is solely for experimentation by experts. Disables
70 translation of lpar addresses. SPE support currently won't work
71 without this set to y.
72
73 If you have any doubt, choose the default y.
74
75config PS3_VUART 64config PS3_VUART
76 depends on PPC_PS3 65 depends on PPC_PS3
77 tristate 66 tristate
@@ -138,4 +127,17 @@ config PS3_FLASH
138 be disabled on the kernel command line using "ps3flash=off", to 127 be disabled on the kernel command line using "ps3flash=off", to
139 not allocate this fixed buffer. 128 not allocate this fixed buffer.
140 129
130config PS3_LPM
131 tristate "PS3 Logical Performance Monitor support"
132 depends on PPC_PS3
133 help
134 Include support for the PS3 Logical Performance Monitor.
135
136 This support is required to use the logical performance monitor
137 of the PS3's LV1 hypervisor.
138
139 If you intend to use the advanced performance monitoring and
140 profiling support of the Cell processor with programs like
141 oprofile and perfmon2, then say Y or M, otherwise say N.
142
141endmenu 143endmenu
diff --git a/arch/powerpc/platforms/ps3/device-init.c b/arch/powerpc/platforms/ps3/device-init.c
index fd063fe0c9b3..9d251d0ca8c6 100644
--- a/arch/powerpc/platforms/ps3/device-init.c
+++ b/arch/powerpc/platforms/ps3/device-init.c
@@ -23,6 +23,7 @@
23#include <linux/kernel.h> 23#include <linux/kernel.h>
24#include <linux/kthread.h> 24#include <linux/kthread.h>
25#include <linux/init.h> 25#include <linux/init.h>
26#include <linux/reboot.h>
26 27
27#include <asm/firmware.h> 28#include <asm/firmware.h>
28#include <asm/lv1call.h> 29#include <asm/lv1call.h>
@@ -30,6 +31,89 @@
30 31
31#include "platform.h" 32#include "platform.h"
32 33
34static int __init ps3_register_lpm_devices(void)
35{
36 int result;
37 u64 tmp1;
38 u64 tmp2;
39 struct ps3_system_bus_device *dev;
40
41 pr_debug(" -> %s:%d\n", __func__, __LINE__);
42
43 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
44 if (!dev)
45 return -ENOMEM;
46
47 dev->match_id = PS3_MATCH_ID_LPM;
48 dev->dev_type = PS3_DEVICE_TYPE_LPM;
49
50 /* The current lpm driver only supports a single BE processor. */
51
52 result = ps3_repository_read_be_node_id(0, &dev->lpm.node_id);
53
54 if (result) {
55 pr_debug("%s:%d: ps3_repository_read_be_node_id failed \n",
56 __func__, __LINE__);
57 goto fail_read_repo;
58 }
59
60 result = ps3_repository_read_lpm_privileges(dev->lpm.node_id, &tmp1,
61 &dev->lpm.rights);
62
63 if (result) {
64 pr_debug("%s:%d: ps3_repository_read_lpm_privleges failed \n",
65 __func__, __LINE__);
66 goto fail_read_repo;
67 }
68
69 lv1_get_logical_partition_id(&tmp2);
70
71 if (tmp1 != tmp2) {
72 pr_debug("%s:%d: wrong lpar\n",
73 __func__, __LINE__);
74 result = -ENODEV;
75 goto fail_rights;
76 }
77
78 if (!(dev->lpm.rights & PS3_LPM_RIGHTS_USE_LPM)) {
79 pr_debug("%s:%d: don't have rights to use lpm\n",
80 __func__, __LINE__);
81 result = -EPERM;
82 goto fail_rights;
83 }
84
85 pr_debug("%s:%d: pu_id %lu, rights %lu(%lxh)\n",
86 __func__, __LINE__, dev->lpm.pu_id, dev->lpm.rights,
87 dev->lpm.rights);
88
89 result = ps3_repository_read_pu_id(0, &dev->lpm.pu_id);
90
91 if (result) {
92 pr_debug("%s:%d: ps3_repository_read_pu_id failed \n",
93 __func__, __LINE__);
94 goto fail_read_repo;
95 }
96
97 result = ps3_system_bus_device_register(dev);
98
99 if (result) {
100 pr_debug("%s:%d ps3_system_bus_device_register failed\n",
101 __func__, __LINE__);
102 goto fail_register;
103 }
104
105 pr_debug(" <- %s:%d\n", __func__, __LINE__);
106 return 0;
107
108
109fail_register:
110fail_rights:
111fail_read_repo:
112 kfree(dev);
113 pr_debug(" <- %s:%d: failed\n", __func__, __LINE__);
114 return result;
115}
116
33/** 117/**
34 * ps3_setup_gelic_device - Setup and register a gelic device instance. 118 * ps3_setup_gelic_device - Setup and register a gelic device instance.
35 * 119 *
@@ -238,166 +322,6 @@ static int __init ps3_setup_vuart_device(enum ps3_match_id match_id,
238 return result; 322 return result;
239} 323}
240 324
241static int ps3stor_wait_for_completion(u64 dev_id, u64 tag,
242 unsigned int timeout)
243{
244 int result = -1;
245 unsigned int retries = 0;
246 u64 status;
247
248 for (retries = 0; retries < timeout; retries++) {
249 result = lv1_storage_check_async_status(dev_id, tag, &status);
250 if (!result)
251 break;
252
253 msleep(1);
254 }
255
256 if (result)
257 pr_debug("%s:%u: check_async_status: %s, status %lx\n",
258 __func__, __LINE__, ps3_result(result), status);
259
260 return result;
261}
262
263/**
264 * ps3_storage_wait_for_device - Wait for a storage device to become ready.
265 * @repo: The repository device to wait for.
266 *
267 * Uses the hypervisor's storage device notification mechanism to wait until
268 * a storage device is ready. The device notification mechanism uses a
269 * psuedo device (id = -1) to asynchronously notify the guest when storage
270 * devices become ready. The notification device has a block size of 512
271 * bytes.
272 */
273
274static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo)
275{
276 int error = -ENODEV;
277 int result;
278 const u64 notification_dev_id = (u64)-1LL;
279 const unsigned int timeout = HZ;
280 u64 lpar;
281 u64 tag;
282 void *buf;
283 enum ps3_notify_type {
284 notify_device_ready = 0,
285 notify_region_probe = 1,
286 notify_region_update = 2,
287 };
288 struct {
289 u64 operation_code; /* must be zero */
290 u64 event_mask; /* OR of 1UL << enum ps3_notify_type */
291 } *notify_cmd;
292 struct {
293 u64 event_type; /* enum ps3_notify_type */
294 u64 bus_id;
295 u64 dev_id;
296 u64 dev_type;
297 u64 dev_port;
298 } *notify_event;
299
300 pr_debug(" -> %s:%u: (%u:%u:%u)\n", __func__, __LINE__, repo->bus_id,
301 repo->dev_id, repo->dev_type);
302
303 buf = kzalloc(512, GFP_KERNEL);
304 if (!buf)
305 return -ENOMEM;
306
307 lpar = ps3_mm_phys_to_lpar(__pa(buf));
308 notify_cmd = buf;
309 notify_event = buf;
310
311 result = lv1_open_device(repo->bus_id, notification_dev_id, 0);
312 if (result) {
313 printk(KERN_ERR "%s:%u: lv1_open_device %s\n", __func__,
314 __LINE__, ps3_result(result));
315 goto fail_free;
316 }
317
318 /* Setup and write the request for device notification. */
319
320 notify_cmd->operation_code = 0; /* must be zero */
321 notify_cmd->event_mask = 1UL << notify_region_probe;
322
323 result = lv1_storage_write(notification_dev_id, 0, 0, 1, 0, lpar,
324 &tag);
325 if (result) {
326 printk(KERN_ERR "%s:%u: write failed %s\n", __func__, __LINE__,
327 ps3_result(result));
328 goto fail_close;
329 }
330
331 /* Wait for the write completion */
332
333 result = ps3stor_wait_for_completion(notification_dev_id, tag,
334 timeout);
335 if (result) {
336 printk(KERN_ERR "%s:%u: write not completed %s\n", __func__,
337 __LINE__, ps3_result(result));
338 goto fail_close;
339 }
340
341 /* Loop here processing the requested notification events. */
342
343 while (1) {
344 memset(notify_event, 0, sizeof(*notify_event));
345
346 result = lv1_storage_read(notification_dev_id, 0, 0, 1, 0,
347 lpar, &tag);
348 if (result) {
349 printk(KERN_ERR "%s:%u: write failed %s\n", __func__,
350 __LINE__, ps3_result(result));
351 break;
352 }
353
354 result = ps3stor_wait_for_completion(notification_dev_id, tag,
355 timeout);
356 if (result) {
357 printk(KERN_ERR "%s:%u: read not completed %s\n",
358 __func__, __LINE__, ps3_result(result));
359 break;
360 }
361
362 pr_debug("%s:%d: notify event (%u:%u:%u): event_type 0x%lx, "
363 "port %lu\n", __func__, __LINE__, repo->bus_index,
364 repo->dev_index, repo->dev_type,
365 notify_event->event_type, notify_event->dev_port);
366
367 if (notify_event->event_type != notify_region_probe ||
368 notify_event->bus_id != repo->bus_id) {
369 pr_debug("%s:%u: bad notify_event: event %lu, "
370 "dev_id %lu, dev_type %lu\n",
371 __func__, __LINE__, notify_event->event_type,
372 notify_event->dev_id, notify_event->dev_type);
373 break;
374 }
375
376 if (notify_event->dev_id == repo->dev_id &&
377 notify_event->dev_type == repo->dev_type) {
378 pr_debug("%s:%u: device ready (%u:%u:%u)\n", __func__,
379 __LINE__, repo->bus_index, repo->dev_index,
380 repo->dev_type);
381 error = 0;
382 break;
383 }
384
385 if (notify_event->dev_id == repo->dev_id &&
386 notify_event->dev_type == PS3_DEV_TYPE_NOACCESS) {
387 pr_debug("%s:%u: no access: dev_id %u\n", __func__,
388 __LINE__, repo->dev_id);
389 break;
390 }
391 }
392
393fail_close:
394 lv1_close_device(repo->bus_id, notification_dev_id);
395fail_free:
396 kfree(buf);
397 pr_debug(" <- %s:%u\n", __func__, __LINE__);
398 return error;
399}
400
401static int ps3_setup_storage_dev(const struct ps3_repository_device *repo, 325static int ps3_setup_storage_dev(const struct ps3_repository_device *repo,
402 enum ps3_match_id match_id) 326 enum ps3_match_id match_id)
403{ 327{
@@ -449,16 +373,6 @@ static int ps3_setup_storage_dev(const struct ps3_repository_device *repo,
449 goto fail_find_interrupt; 373 goto fail_find_interrupt;
450 } 374 }
451 375
452 /* FIXME: Arrange to only do this on a 'cold' boot */
453
454 result = ps3_storage_wait_for_device(repo);
455 if (result) {
456 printk(KERN_ERR "%s:%u: storage_notification failed %d\n",
457 __func__, __LINE__, result);
458 result = -ENODEV;
459 goto fail_probe_notification;
460 }
461
462 for (i = 0; i < num_regions; i++) { 376 for (i = 0; i < num_regions; i++) {
463 unsigned int id; 377 unsigned int id;
464 u64 start, size; 378 u64 start, size;
@@ -494,7 +408,6 @@ static int ps3_setup_storage_dev(const struct ps3_repository_device *repo,
494 408
495fail_device_register: 409fail_device_register:
496fail_read_region: 410fail_read_region:
497fail_probe_notification:
498fail_find_interrupt: 411fail_find_interrupt:
499 kfree(p); 412 kfree(p);
500fail_malloc: 413fail_malloc:
@@ -659,62 +572,268 @@ static int ps3_register_repository_device(
659 return result; 572 return result;
660} 573}
661 574
575static void ps3_find_and_add_device(u64 bus_id, u64 dev_id)
576{
577 struct ps3_repository_device repo;
578 int res;
579 unsigned int retries;
580 unsigned long rem;
581
582 /*
583 * On some firmware versions (e.g. 1.90), the device may not show up
584 * in the repository immediately
585 */
586 for (retries = 0; retries < 10; retries++) {
587 res = ps3_repository_find_device_by_id(&repo, bus_id, dev_id);
588 if (!res)
589 goto found;
590
591 rem = msleep_interruptible(100);
592 if (rem)
593 break;
594 }
595 pr_warning("%s:%u: device %lu:%lu not found\n", __func__, __LINE__,
596 bus_id, dev_id);
597 return;
598
599found:
600 if (retries)
601 pr_debug("%s:%u: device %lu:%lu found after %u retries\n",
602 __func__, __LINE__, bus_id, dev_id, retries);
603
604 ps3_register_repository_device(&repo);
605 return;
606}
607
608#define PS3_NOTIFICATION_DEV_ID ULONG_MAX
609#define PS3_NOTIFICATION_INTERRUPT_ID 0
610
611struct ps3_notification_device {
612 struct ps3_system_bus_device sbd;
613 spinlock_t lock;
614 u64 tag;
615 u64 lv1_status;
616 struct completion done;
617};
618
619enum ps3_notify_type {
620 notify_device_ready = 0,
621 notify_region_probe = 1,
622 notify_region_update = 2,
623};
624
625struct ps3_notify_cmd {
626 u64 operation_code; /* must be zero */
627 u64 event_mask; /* OR of 1UL << enum ps3_notify_type */
628};
629
630struct ps3_notify_event {
631 u64 event_type; /* enum ps3_notify_type */
632 u64 bus_id;
633 u64 dev_id;
634 u64 dev_type;
635 u64 dev_port;
636};
637
638static irqreturn_t ps3_notification_interrupt(int irq, void *data)
639{
640 struct ps3_notification_device *dev = data;
641 int res;
642 u64 tag, status;
643
644 spin_lock(&dev->lock);
645 res = lv1_storage_get_async_status(PS3_NOTIFICATION_DEV_ID, &tag,
646 &status);
647 if (tag != dev->tag)
648 pr_err("%s:%u: tag mismatch, got %lx, expected %lx\n",
649 __func__, __LINE__, tag, dev->tag);
650
651 if (res) {
652 pr_err("%s:%u: res %d status 0x%lx\n", __func__, __LINE__, res,
653 status);
654 } else {
655 pr_debug("%s:%u: completed, status 0x%lx\n", __func__,
656 __LINE__, status);
657 dev->lv1_status = status;
658 complete(&dev->done);
659 }
660 spin_unlock(&dev->lock);
661 return IRQ_HANDLED;
662}
663
664static int ps3_notification_read_write(struct ps3_notification_device *dev,
665 u64 lpar, int write)
666{
667 const char *op = write ? "write" : "read";
668 unsigned long flags;
669 int res;
670
671 init_completion(&dev->done);
672 spin_lock_irqsave(&dev->lock, flags);
673 res = write ? lv1_storage_write(dev->sbd.dev_id, 0, 0, 1, 0, lpar,
674 &dev->tag)
675 : lv1_storage_read(dev->sbd.dev_id, 0, 0, 1, 0, lpar,
676 &dev->tag);
677 spin_unlock_irqrestore(&dev->lock, flags);
678 if (res) {
679 pr_err("%s:%u: %s failed %d\n", __func__, __LINE__, op, res);
680 return -EPERM;
681 }
682 pr_debug("%s:%u: notification %s issued\n", __func__, __LINE__, op);
683
684 res = wait_event_interruptible(dev->done.wait,
685 dev->done.done || kthread_should_stop());
686 if (kthread_should_stop())
687 res = -EINTR;
688 if (res) {
689 pr_debug("%s:%u: interrupted %s\n", __func__, __LINE__, op);
690 return res;
691 }
692
693 if (dev->lv1_status) {
694 pr_err("%s:%u: %s not completed, status 0x%lx\n", __func__,
695 __LINE__, op, dev->lv1_status);
696 return -EIO;
697 }
698 pr_debug("%s:%u: notification %s completed\n", __func__, __LINE__, op);
699
700 return 0;
701}
702
703static struct task_struct *probe_task;
704
662/** 705/**
663 * ps3_probe_thread - Background repository probing at system startup. 706 * ps3_probe_thread - Background repository probing at system startup.
664 * 707 *
665 * This implementation only supports background probing on a single bus. 708 * This implementation only supports background probing on a single bus.
709 * It uses the hypervisor's storage device notification mechanism to wait until
710 * a storage device is ready. The device notification mechanism uses a
711 * pseudo device to asynchronously notify the guest when storage devices become
712 * ready. The notification device has a block size of 512 bytes.
666 */ 713 */
667 714
668static int ps3_probe_thread(void *data) 715static int ps3_probe_thread(void *data)
669{ 716{
670 struct ps3_repository_device *repo = data; 717 struct ps3_notification_device dev;
671 int result; 718 int res;
672 unsigned int ms = 250; 719 unsigned int irq;
720 u64 lpar;
721 void *buf;
722 struct ps3_notify_cmd *notify_cmd;
723 struct ps3_notify_event *notify_event;
673 724
674 pr_debug(" -> %s:%u: kthread started\n", __func__, __LINE__); 725 pr_debug(" -> %s:%u: kthread started\n", __func__, __LINE__);
675 726
727 buf = kzalloc(512, GFP_KERNEL);
728 if (!buf)
729 return -ENOMEM;
730
731 lpar = ps3_mm_phys_to_lpar(__pa(buf));
732 notify_cmd = buf;
733 notify_event = buf;
734
735 /* dummy system bus device */
736 dev.sbd.bus_id = (u64)data;
737 dev.sbd.dev_id = PS3_NOTIFICATION_DEV_ID;
738 dev.sbd.interrupt_id = PS3_NOTIFICATION_INTERRUPT_ID;
739
740 res = lv1_open_device(dev.sbd.bus_id, dev.sbd.dev_id, 0);
741 if (res) {
742 pr_err("%s:%u: lv1_open_device failed %s\n", __func__,
743 __LINE__, ps3_result(res));
744 goto fail_free;
745 }
746
747 res = ps3_sb_event_receive_port_setup(&dev.sbd, PS3_BINDING_CPU_ANY,
748 &irq);
749 if (res) {
750 pr_err("%s:%u: ps3_sb_event_receive_port_setup failed %d\n",
751 __func__, __LINE__, res);
752 goto fail_close_device;
753 }
754
755 spin_lock_init(&dev.lock);
756
757 res = request_irq(irq, ps3_notification_interrupt, IRQF_DISABLED,
758 "ps3_notification", &dev);
759 if (res) {
760 pr_err("%s:%u: request_irq failed %d\n", __func__, __LINE__,
761 res);
762 goto fail_sb_event_receive_port_destroy;
763 }
764
765 /* Setup and write the request for device notification. */
766 notify_cmd->operation_code = 0; /* must be zero */
767 notify_cmd->event_mask = 1UL << notify_region_probe;
768
769 res = ps3_notification_read_write(&dev, lpar, 1);
770 if (res)
771 goto fail_free_irq;
772
773 /* Loop here processing the requested notification events. */
676 do { 774 do {
677 try_to_freeze(); 775 try_to_freeze();
678 776
679 pr_debug("%s:%u: probing...\n", __func__, __LINE__); 777 memset(notify_event, 0, sizeof(*notify_event));
680 778
681 do { 779 res = ps3_notification_read_write(&dev, lpar, 0);
682 result = ps3_repository_find_device(repo); 780 if (res)
683
684 if (result == -ENODEV)
685 pr_debug("%s:%u: nothing new\n", __func__,
686 __LINE__);
687 else if (result)
688 pr_debug("%s:%u: find device error.\n",
689 __func__, __LINE__);
690 else {
691 pr_debug("%s:%u: found device (%u:%u:%u)\n",
692 __func__, __LINE__, repo->bus_index,
693 repo->dev_index, repo->dev_type);
694 ps3_register_repository_device(repo);
695 ps3_repository_bump_device(repo);
696 ms = 250;
697 }
698 } while (!result);
699
700 pr_debug("%s:%u: ms %u\n", __func__, __LINE__, ms);
701
702 if ( ms > 60000)
703 break; 781 break;
704 782
705 msleep_interruptible(ms); 783 pr_debug("%s:%u: notify event type 0x%lx bus id %lu dev id %lu"
784 " type %lu port %lu\n", __func__, __LINE__,
785 notify_event->event_type, notify_event->bus_id,
786 notify_event->dev_id, notify_event->dev_type,
787 notify_event->dev_port);
706 788
707 /* An exponential backoff. */ 789 if (notify_event->event_type != notify_region_probe ||
708 ms <<= 1; 790 notify_event->bus_id != dev.sbd.bus_id) {
791 pr_warning("%s:%u: bad notify_event: event %lu, "
792 "dev_id %lu, dev_type %lu\n",
793 __func__, __LINE__, notify_event->event_type,
794 notify_event->dev_id,
795 notify_event->dev_type);
796 continue;
797 }
798
799 ps3_find_and_add_device(dev.sbd.bus_id, notify_event->dev_id);
709 800
710 } while (!kthread_should_stop()); 801 } while (!kthread_should_stop());
711 802
803fail_free_irq:
804 free_irq(irq, &dev);
805fail_sb_event_receive_port_destroy:
806 ps3_sb_event_receive_port_destroy(&dev.sbd, irq);
807fail_close_device:
808 lv1_close_device(dev.sbd.bus_id, dev.sbd.dev_id);
809fail_free:
810 kfree(buf);
811
812 probe_task = NULL;
813
712 pr_debug(" <- %s:%u: kthread finished\n", __func__, __LINE__); 814 pr_debug(" <- %s:%u: kthread finished\n", __func__, __LINE__);
713 815
714 return 0; 816 return 0;
715} 817}
716 818
717/** 819/**
820 * ps3_stop_probe_thread - Stops the background probe thread.
821 *
822 */
823
824static int ps3_stop_probe_thread(struct notifier_block *nb, unsigned long code,
825 void *data)
826{
827 if (probe_task)
828 kthread_stop(probe_task);
829 return 0;
830}
831
832static struct notifier_block nb = {
833 .notifier_call = ps3_stop_probe_thread
834};
835
836/**
718 * ps3_start_probe_thread - Starts the background probe thread. 837 * ps3_start_probe_thread - Starts the background probe thread.
719 * 838 *
720 */ 839 */
@@ -723,7 +842,7 @@ static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type)
723{ 842{
724 int result; 843 int result;
725 struct task_struct *task; 844 struct task_struct *task;
726 static struct ps3_repository_device repo; /* must be static */ 845 struct ps3_repository_device repo;
727 846
728 pr_debug(" -> %s:%d\n", __func__, __LINE__); 847 pr_debug(" -> %s:%d\n", __func__, __LINE__);
729 848
@@ -746,7 +865,8 @@ static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type)
746 return -ENODEV; 865 return -ENODEV;
747 } 866 }
748 867
749 task = kthread_run(ps3_probe_thread, &repo, "ps3-probe-%u", bus_type); 868 task = kthread_run(ps3_probe_thread, (void *)repo.bus_id,
869 "ps3-probe-%u", bus_type);
750 870
751 if (IS_ERR(task)) { 871 if (IS_ERR(task)) {
752 result = PTR_ERR(task); 872 result = PTR_ERR(task);
@@ -755,6 +875,9 @@ static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type)
755 return result; 875 return result;
756 } 876 }
757 877
878 probe_task = task;
879 register_reboot_notifier(&nb);
880
758 pr_debug(" <- %s:%d\n", __func__, __LINE__); 881 pr_debug(" <- %s:%d\n", __func__, __LINE__);
759 return 0; 882 return 0;
760} 883}
@@ -787,6 +910,8 @@ static int __init ps3_register_devices(void)
787 910
788 ps3_register_sound_devices(); 911 ps3_register_sound_devices();
789 912
913 ps3_register_lpm_devices();
914
790 pr_debug(" <- %s:%d\n", __func__, __LINE__); 915 pr_debug(" <- %s:%d\n", __func__, __LINE__);
791 return 0; 916 return 0;
792} 917}
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c
index 7bb3e1620974..68900476c842 100644
--- a/arch/powerpc/platforms/ps3/mm.c
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -36,11 +36,6 @@
36#endif 36#endif
37 37
38enum { 38enum {
39#if defined(CONFIG_PS3_USE_LPAR_ADDR)
40 USE_LPAR_ADDR = 1,
41#else
42 USE_LPAR_ADDR = 0,
43#endif
44#if defined(CONFIG_PS3_DYNAMIC_DMA) 39#if defined(CONFIG_PS3_DYNAMIC_DMA)
45 USE_DYNAMIC_DMA = 1, 40 USE_DYNAMIC_DMA = 1,
46#else 41#else
@@ -137,11 +132,8 @@ static struct map map;
137unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr) 132unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr)
138{ 133{
139 BUG_ON(is_kernel_addr(phys_addr)); 134 BUG_ON(is_kernel_addr(phys_addr));
140 if (USE_LPAR_ADDR) 135 return (phys_addr < map.rm.size || phys_addr >= map.total)
141 return phys_addr; 136 ? phys_addr : phys_addr + map.r1.offset;
142 else
143 return (phys_addr < map.rm.size || phys_addr >= map.total)
144 ? phys_addr : phys_addr + map.r1.offset;
145} 137}
146 138
147EXPORT_SYMBOL(ps3_mm_phys_to_lpar); 139EXPORT_SYMBOL(ps3_mm_phys_to_lpar);
@@ -309,7 +301,7 @@ static int __init ps3_mm_add_memory(void)
309 301
310 BUG_ON(!mem_init_done); 302 BUG_ON(!mem_init_done);
311 303
312 start_addr = USE_LPAR_ADDR ? map.r1.base : map.rm.size; 304 start_addr = map.rm.size;
313 start_pfn = start_addr >> PAGE_SHIFT; 305 start_pfn = start_addr >> PAGE_SHIFT;
314 nr_pages = (map.r1.size + PAGE_SIZE - 1) >> PAGE_SHIFT; 306 nr_pages = (map.r1.size + PAGE_SIZE - 1) >> PAGE_SHIFT;
315 307
@@ -359,7 +351,7 @@ static unsigned long dma_sb_lpar_to_bus(struct ps3_dma_region *r,
359static void __maybe_unused _dma_dump_region(const struct ps3_dma_region *r, 351static void __maybe_unused _dma_dump_region(const struct ps3_dma_region *r,
360 const char *func, int line) 352 const char *func, int line)
361{ 353{
362 DBG("%s:%d: dev %u:%u\n", func, line, r->dev->bus_id, 354 DBG("%s:%d: dev %lu:%lu\n", func, line, r->dev->bus_id,
363 r->dev->dev_id); 355 r->dev->dev_id);
364 DBG("%s:%d: page_size %u\n", func, line, r->page_size); 356 DBG("%s:%d: page_size %u\n", func, line, r->page_size);
365 DBG("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); 357 DBG("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr);
@@ -394,7 +386,7 @@ struct dma_chunk {
394static void _dma_dump_chunk (const struct dma_chunk* c, const char* func, 386static void _dma_dump_chunk (const struct dma_chunk* c, const char* func,
395 int line) 387 int line)
396{ 388{
397 DBG("%s:%d: r.dev %u:%u\n", func, line, 389 DBG("%s:%d: r.dev %lu:%lu\n", func, line,
398 c->region->dev->bus_id, c->region->dev->dev_id); 390 c->region->dev->bus_id, c->region->dev->dev_id);
399 DBG("%s:%d: r.bus_addr %lxh\n", func, line, c->region->bus_addr); 391 DBG("%s:%d: r.bus_addr %lxh\n", func, line, c->region->bus_addr);
400 DBG("%s:%d: r.page_size %u\n", func, line, c->region->page_size); 392 DBG("%s:%d: r.page_size %u\n", func, line, c->region->page_size);
@@ -658,7 +650,7 @@ static int dma_sb_region_create(struct ps3_dma_region *r)
658 BUG_ON(!r); 650 BUG_ON(!r);
659 651
660 if (!r->dev->bus_id) { 652 if (!r->dev->bus_id) {
661 pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__, 653 pr_info("%s:%d: %lu:%lu no dma\n", __func__, __LINE__,
662 r->dev->bus_id, r->dev->dev_id); 654 r->dev->bus_id, r->dev->dev_id);
663 return 0; 655 return 0;
664 } 656 }
@@ -724,7 +716,7 @@ static int dma_sb_region_free(struct ps3_dma_region *r)
724 BUG_ON(!r); 716 BUG_ON(!r);
725 717
726 if (!r->dev->bus_id) { 718 if (!r->dev->bus_id) {
727 pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__, 719 pr_info("%s:%d: %lu:%lu no dma\n", __func__, __LINE__,
728 r->dev->bus_id, r->dev->dev_id); 720 r->dev->bus_id, r->dev->dev_id);
729 return 0; 721 return 0;
730 } 722 }
@@ -1007,7 +999,7 @@ static int dma_sb_region_create_linear(struct ps3_dma_region *r)
1007 999
1008 if (r->offset + r->len > map.rm.size) { 1000 if (r->offset + r->len > map.rm.size) {
1009 /* Map (part of) 2nd RAM chunk */ 1001 /* Map (part of) 2nd RAM chunk */
1010 virt_addr = USE_LPAR_ADDR ? map.r1.base : map.rm.size; 1002 virt_addr = map.rm.size;
1011 len = r->len; 1003 len = r->len;
1012 if (r->offset >= map.rm.size) 1004 if (r->offset >= map.rm.size)
1013 virt_addr += r->offset - map.rm.size; 1005 virt_addr += r->offset - map.rm.size;
diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h
index 01f0c9506e11..235c13ebacd9 100644
--- a/arch/powerpc/platforms/ps3/platform.h
+++ b/arch/powerpc/platforms/ps3/platform.h
@@ -89,13 +89,11 @@ enum ps3_dev_type {
89 PS3_DEV_TYPE_STOR_ROM = TYPE_ROM, /* 5 */ 89 PS3_DEV_TYPE_STOR_ROM = TYPE_ROM, /* 5 */
90 PS3_DEV_TYPE_SB_GPIO = 6, 90 PS3_DEV_TYPE_SB_GPIO = 6,
91 PS3_DEV_TYPE_STOR_FLASH = TYPE_RBC, /* 14 */ 91 PS3_DEV_TYPE_STOR_FLASH = TYPE_RBC, /* 14 */
92 PS3_DEV_TYPE_STOR_DUMMY = 32,
93 PS3_DEV_TYPE_NOACCESS = 255,
94}; 92};
95 93
96int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, 94int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
97 u64 *value); 95 u64 *value);
98int ps3_repository_read_bus_id(unsigned int bus_index, unsigned int *bus_id); 96int ps3_repository_read_bus_id(unsigned int bus_index, u64 *bus_id);
99int ps3_repository_read_bus_type(unsigned int bus_index, 97int ps3_repository_read_bus_type(unsigned int bus_index,
100 enum ps3_bus_type *bus_type); 98 enum ps3_bus_type *bus_type);
101int ps3_repository_read_bus_num_dev(unsigned int bus_index, 99int ps3_repository_read_bus_num_dev(unsigned int bus_index,
@@ -119,7 +117,7 @@ enum ps3_reg_type {
119int ps3_repository_read_dev_str(unsigned int bus_index, 117int ps3_repository_read_dev_str(unsigned int bus_index,
120 unsigned int dev_index, const char *dev_str, u64 *value); 118 unsigned int dev_index, const char *dev_str, u64 *value);
121int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index, 119int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index,
122 unsigned int *dev_id); 120 u64 *dev_id);
123int ps3_repository_read_dev_type(unsigned int bus_index, 121int ps3_repository_read_dev_type(unsigned int bus_index,
124 unsigned int dev_index, enum ps3_dev_type *dev_type); 122 unsigned int dev_index, enum ps3_dev_type *dev_type);
125int ps3_repository_read_dev_intr(unsigned int bus_index, 123int ps3_repository_read_dev_intr(unsigned int bus_index,
@@ -138,21 +136,17 @@ int ps3_repository_read_dev_reg(unsigned int bus_index,
138/* repository bus enumerators */ 136/* repository bus enumerators */
139 137
140struct ps3_repository_device { 138struct ps3_repository_device {
141 enum ps3_bus_type bus_type;
142 unsigned int bus_index; 139 unsigned int bus_index;
143 unsigned int bus_id;
144 enum ps3_dev_type dev_type;
145 unsigned int dev_index; 140 unsigned int dev_index;
146 unsigned int dev_id; 141 enum ps3_bus_type bus_type;
142 enum ps3_dev_type dev_type;
143 u64 bus_id;
144 u64 dev_id;
147}; 145};
148 146
149static inline struct ps3_repository_device *ps3_repository_bump_device(
150 struct ps3_repository_device *repo)
151{
152 repo->dev_index++;
153 return repo;
154}
155int ps3_repository_find_device(struct ps3_repository_device *repo); 147int ps3_repository_find_device(struct ps3_repository_device *repo);
148int ps3_repository_find_device_by_id(struct ps3_repository_device *repo,
149 u64 bus_id, u64 dev_id);
156int ps3_repository_find_devices(enum ps3_bus_type bus_type, 150int ps3_repository_find_devices(enum ps3_bus_type bus_type,
157 int (*callback)(const struct ps3_repository_device *repo)); 151 int (*callback)(const struct ps3_repository_device *repo));
158int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from, 152int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from,
@@ -186,10 +180,10 @@ int ps3_repository_read_stor_dev_region(unsigned int bus_index,
186 unsigned int dev_index, unsigned int region_index, 180 unsigned int dev_index, unsigned int region_index,
187 unsigned int *region_id, u64 *region_start, u64 *region_size); 181 unsigned int *region_id, u64 *region_start, u64 *region_size);
188 182
189/* repository pu and memory info */ 183/* repository logical pu and memory info */
190 184
191int ps3_repository_read_num_pu(unsigned int *num_pu); 185int ps3_repository_read_num_pu(u64 *num_pu);
192int ps3_repository_read_ppe_id(unsigned int *pu_index, unsigned int *ppe_id); 186int ps3_repository_read_pu_id(unsigned int pu_index, u64 *pu_id);
193int ps3_repository_read_rm_base(unsigned int ppe_id, u64 *rm_base); 187int ps3_repository_read_rm_base(unsigned int ppe_id, u64 *rm_base);
194int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size); 188int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size);
195int ps3_repository_read_region_total(u64 *region_total); 189int ps3_repository_read_region_total(u64 *region_total);
@@ -200,9 +194,15 @@ int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size,
200 194
201int ps3_repository_read_num_be(unsigned int *num_be); 195int ps3_repository_read_num_be(unsigned int *num_be);
202int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id); 196int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id);
197int ps3_repository_read_be_id(u64 node_id, u64 *be_id);
203int ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq); 198int ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq);
204int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq); 199int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq);
205 200
201/* repository performance monitor info */
202
203int ps3_repository_read_lpm_privileges(unsigned int be_index, u64 *lpar,
204 u64 *rights);
205
206/* repository 'Other OS' area */ 206/* repository 'Other OS' area */
207 207
208int ps3_repository_read_boot_dat_addr(u64 *lpar_addr); 208int ps3_repository_read_boot_dat_addr(u64 *lpar_addr);
diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c
index 1c94824f7b63..22063adeb38b 100644
--- a/arch/powerpc/platforms/ps3/repository.c
+++ b/arch/powerpc/platforms/ps3/repository.c
@@ -33,7 +33,7 @@ enum ps3_lpar_id {
33}; 33};
34 34
35#define dump_field(_a, _b) _dump_field(_a, _b, __func__, __LINE__) 35#define dump_field(_a, _b) _dump_field(_a, _b, __func__, __LINE__)
36static void _dump_field(const char *hdr, u64 n, const char* func, int line) 36static void _dump_field(const char *hdr, u64 n, const char *func, int line)
37{ 37{
38#if defined(DEBUG) 38#if defined(DEBUG)
39 char s[16]; 39 char s[16];
@@ -50,8 +50,8 @@ static void _dump_field(const char *hdr, u64 n, const char* func, int line)
50 50
51#define dump_node_name(_a, _b, _c, _d, _e) \ 51#define dump_node_name(_a, _b, _c, _d, _e) \
52 _dump_node_name(_a, _b, _c, _d, _e, __func__, __LINE__) 52 _dump_node_name(_a, _b, _c, _d, _e, __func__, __LINE__)
53static void _dump_node_name (unsigned int lpar_id, u64 n1, u64 n2, u64 n3, 53static void _dump_node_name(unsigned int lpar_id, u64 n1, u64 n2, u64 n3,
54 u64 n4, const char* func, int line) 54 u64 n4, const char *func, int line)
55{ 55{
56 pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id); 56 pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id);
57 _dump_field("n1: ", n1, func, line); 57 _dump_field("n1: ", n1, func, line);
@@ -63,7 +63,7 @@ static void _dump_node_name (unsigned int lpar_id, u64 n1, u64 n2, u64 n3,
63#define dump_node(_a, _b, _c, _d, _e, _f, _g) \ 63#define dump_node(_a, _b, _c, _d, _e, _f, _g) \
64 _dump_node(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__) 64 _dump_node(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__)
65static void _dump_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4, 65static void _dump_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
66 u64 v1, u64 v2, const char* func, int line) 66 u64 v1, u64 v2, const char *func, int line)
67{ 67{
68 pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id); 68 pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id);
69 _dump_field("n1: ", n1, func, line); 69 _dump_field("n1: ", n1, func, line);
@@ -165,21 +165,18 @@ int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
165 make_first_field("bus", bus_index), 165 make_first_field("bus", bus_index),
166 make_field(bus_str, 0), 166 make_field(bus_str, 0),
167 0, 0, 167 0, 0,
168 value, 0); 168 value, NULL);
169} 169}
170 170
171int ps3_repository_read_bus_id(unsigned int bus_index, unsigned int *bus_id) 171int ps3_repository_read_bus_id(unsigned int bus_index, u64 *bus_id)
172{ 172{
173 int result; 173 int result;
174 u64 v1;
175 u64 v2; /* unused */
176 174
177 result = read_node(PS3_LPAR_ID_PME, 175 result = read_node(PS3_LPAR_ID_PME,
178 make_first_field("bus", bus_index), 176 make_first_field("bus", bus_index),
179 make_field("id", 0), 177 make_field("id", 0),
180 0, 0, 178 0, 0,
181 &v1, &v2); 179 bus_id, NULL);
182 *bus_id = v1;
183 return result; 180 return result;
184} 181}
185 182
@@ -193,7 +190,7 @@ int ps3_repository_read_bus_type(unsigned int bus_index,
193 make_first_field("bus", bus_index), 190 make_first_field("bus", bus_index),
194 make_field("type", 0), 191 make_field("type", 0),
195 0, 0, 192 0, 0,
196 &v1, 0); 193 &v1, NULL);
197 *bus_type = v1; 194 *bus_type = v1;
198 return result; 195 return result;
199} 196}
@@ -208,7 +205,7 @@ int ps3_repository_read_bus_num_dev(unsigned int bus_index,
208 make_first_field("bus", bus_index), 205 make_first_field("bus", bus_index),
209 make_field("num_dev", 0), 206 make_field("num_dev", 0),
210 0, 0, 207 0, 0,
211 &v1, 0); 208 &v1, NULL);
212 *num_dev = v1; 209 *num_dev = v1;
213 return result; 210 return result;
214} 211}
@@ -221,22 +218,20 @@ int ps3_repository_read_dev_str(unsigned int bus_index,
221 make_field("dev", dev_index), 218 make_field("dev", dev_index),
222 make_field(dev_str, 0), 219 make_field(dev_str, 0),
223 0, 220 0,
224 value, 0); 221 value, NULL);
225} 222}
226 223
227int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index, 224int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index,
228 unsigned int *dev_id) 225 u64 *dev_id)
229{ 226{
230 int result; 227 int result;
231 u64 v1;
232 228
233 result = read_node(PS3_LPAR_ID_PME, 229 result = read_node(PS3_LPAR_ID_PME,
234 make_first_field("bus", bus_index), 230 make_first_field("bus", bus_index),
235 make_field("dev", dev_index), 231 make_field("dev", dev_index),
236 make_field("id", 0), 232 make_field("id", 0),
237 0, 233 0,
238 &v1, 0); 234 dev_id, NULL);
239 *dev_id = v1;
240 return result; 235 return result;
241} 236}
242 237
@@ -251,14 +246,14 @@ int ps3_repository_read_dev_type(unsigned int bus_index,
251 make_field("dev", dev_index), 246 make_field("dev", dev_index),
252 make_field("type", 0), 247 make_field("type", 0),
253 0, 248 0,
254 &v1, 0); 249 &v1, NULL);
255 *dev_type = v1; 250 *dev_type = v1;
256 return result; 251 return result;
257} 252}
258 253
259int ps3_repository_read_dev_intr(unsigned int bus_index, 254int ps3_repository_read_dev_intr(unsigned int bus_index,
260 unsigned int dev_index, unsigned int intr_index, 255 unsigned int dev_index, unsigned int intr_index,
261 enum ps3_interrupt_type *intr_type, unsigned int* interrupt_id) 256 enum ps3_interrupt_type *intr_type, unsigned int *interrupt_id)
262{ 257{
263 int result; 258 int result;
264 u64 v1; 259 u64 v1;
@@ -287,7 +282,7 @@ int ps3_repository_read_dev_reg_type(unsigned int bus_index,
287 make_field("dev", dev_index), 282 make_field("dev", dev_index),
288 make_field("reg", reg_index), 283 make_field("reg", reg_index),
289 make_field("type", 0), 284 make_field("type", 0),
290 &v1, 0); 285 &v1, NULL);
291 *reg_type = v1; 286 *reg_type = v1;
292 return result; 287 return result;
293} 288}
@@ -332,7 +327,7 @@ int ps3_repository_find_device(struct ps3_repository_device *repo)
332 return result; 327 return result;
333 } 328 }
334 329
335 pr_debug("%s:%d: bus_type %u, bus_index %u, bus_id %u, num_dev %u\n", 330 pr_debug("%s:%d: bus_type %u, bus_index %u, bus_id %lu, num_dev %u\n",
336 __func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id, 331 __func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id,
337 num_dev); 332 num_dev);
338 333
@@ -349,47 +344,95 @@ int ps3_repository_find_device(struct ps3_repository_device *repo)
349 return result; 344 return result;
350 } 345 }
351 346
352 if (tmp.bus_type == PS3_BUS_TYPE_STORAGE) { 347 result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index,
353 /* 348 &tmp.dev_id);
354 * A storage device may show up in the repository before the
355 * hypervisor has finished probing its type and regions
356 */
357 unsigned int num_regions;
358
359 if (tmp.dev_type == PS3_DEV_TYPE_STOR_DUMMY) {
360 pr_debug("%s:%u storage device not ready\n", __func__,
361 __LINE__);
362 return -ENODEV;
363 }
364 349
365 result = ps3_repository_read_stor_dev_num_regions(tmp.bus_index, 350 if (result) {
366 tmp.dev_index, 351 pr_debug("%s:%d ps3_repository_read_dev_id failed\n", __func__,
367 &num_regions); 352 __LINE__);
353 return result;
354 }
355
356 pr_debug("%s:%d: found: dev_type %u, dev_index %u, dev_id %lu\n",
357 __func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id);
358
359 *repo = tmp;
360 return 0;
361}
362
363int ps3_repository_find_device_by_id(struct ps3_repository_device *repo,
364 u64 bus_id, u64 dev_id)
365{
366 int result = -ENODEV;
367 struct ps3_repository_device tmp;
368 unsigned int num_dev;
369
370 pr_debug(" -> %s:%u: find device by id %lu:%lu\n", __func__, __LINE__,
371 bus_id, dev_id);
372
373 for (tmp.bus_index = 0; tmp.bus_index < 10; tmp.bus_index++) {
374 result = ps3_repository_read_bus_id(tmp.bus_index,
375 &tmp.bus_id);
368 if (result) { 376 if (result) {
369 pr_debug("%s:%d read_stor_dev_num_regions failed\n", 377 pr_debug("%s:%u read_bus_id(%u) failed\n", __func__,
370 __func__, __LINE__); 378 __LINE__, tmp.bus_index);
371 return result; 379 return result;
372 } 380 }
373 381
374 if (!num_regions) { 382 if (tmp.bus_id == bus_id)
375 pr_debug("%s:%u storage device has no regions yet\n", 383 goto found_bus;
376 __func__, __LINE__); 384
377 return -ENODEV; 385 pr_debug("%s:%u: skip, bus_id %lu\n", __func__, __LINE__,
378 } 386 tmp.bus_id);
379 } 387 }
388 pr_debug(" <- %s:%u: bus not found\n", __func__, __LINE__);
389 return result;
380 390
381 result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index, 391found_bus:
382 &tmp.dev_id); 392 result = ps3_repository_read_bus_type(tmp.bus_index, &tmp.bus_type);
393 if (result) {
394 pr_debug("%s:%u read_bus_type(%u) failed\n", __func__,
395 __LINE__, tmp.bus_index);
396 return result;
397 }
383 398
399 result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev);
384 if (result) { 400 if (result) {
385 pr_debug("%s:%d ps3_repository_read_dev_id failed\n", __func__, 401 pr_debug("%s:%u read_bus_num_dev failed\n", __func__,
386 __LINE__); 402 __LINE__);
387 return result; 403 return result;
388 } 404 }
389 405
390 pr_debug("%s:%d: found: dev_type %u, dev_index %u, dev_id %u\n", 406 for (tmp.dev_index = 0; tmp.dev_index < num_dev; tmp.dev_index++) {
391 __func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id); 407 result = ps3_repository_read_dev_id(tmp.bus_index,
408 tmp.dev_index,
409 &tmp.dev_id);
410 if (result) {
411 pr_debug("%s:%u read_dev_id(%u:%u) failed\n", __func__,
412 __LINE__, tmp.bus_index, tmp.dev_index);
413 return result;
414 }
392 415
416 if (tmp.dev_id == dev_id)
417 goto found_dev;
418
419 pr_debug("%s:%u: skip, dev_id %lu\n", __func__, __LINE__,
420 tmp.dev_id);
421 }
422 pr_debug(" <- %s:%u: dev not found\n", __func__, __LINE__);
423 return result;
424
425found_dev:
426 result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index,
427 &tmp.dev_type);
428 if (result) {
429 pr_debug("%s:%u read_dev_type failed\n", __func__, __LINE__);
430 return result;
431 }
432
433 pr_debug(" <- %s:%u: found: type (%u:%u) index (%u:%u) id (%lu:%lu)\n",
434 __func__, __LINE__, tmp.bus_type, tmp.dev_type, tmp.bus_index,
435 tmp.dev_index, tmp.bus_id, tmp.dev_id);
393 *repo = tmp; 436 *repo = tmp;
394 return 0; 437 return 0;
395} 438}
@@ -402,50 +445,34 @@ int __devinit ps3_repository_find_devices(enum ps3_bus_type bus_type,
402 445
403 pr_debug(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type); 446 pr_debug(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type);
404 447
405 for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) { 448 repo.bus_type = bus_type;
449 result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index);
450 if (result) {
451 pr_debug(" <- %s:%u: bus not found\n", __func__, __LINE__);
452 return result;
453 }
406 454
407 result = ps3_repository_read_bus_type(repo.bus_index, 455 result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id);
408 &repo.bus_type); 456 if (result) {
457 pr_debug("%s:%d read_bus_id(%u) failed\n", __func__, __LINE__,
458 repo.bus_index);
459 return result;
460 }
409 461
410 if (result) { 462 for (repo.dev_index = 0; ; repo.dev_index++) {
411 pr_debug("%s:%d read_bus_type(%u) failed\n", 463 result = ps3_repository_find_device(&repo);
412 __func__, __LINE__, repo.bus_index); 464 if (result == -ENODEV) {
465 result = 0;
466 break;
467 } else if (result)
413 break; 468 break;
414 }
415
416 if (repo.bus_type != bus_type) {
417 pr_debug("%s:%d: skip, bus_type %u\n", __func__,
418 __LINE__, repo.bus_type);
419 continue;
420 }
421
422 result = ps3_repository_read_bus_id(repo.bus_index,
423 &repo.bus_id);
424 469
470 result = callback(&repo);
425 if (result) { 471 if (result) {
426 pr_debug("%s:%d read_bus_id(%u) failed\n", 472 pr_debug("%s:%d: abort at callback\n", __func__,
427 __func__, __LINE__, repo.bus_index); 473 __LINE__);
428 continue; 474 break;
429 }
430
431 for (repo.dev_index = 0; ; repo.dev_index++) {
432 result = ps3_repository_find_device(&repo);
433
434 if (result == -ENODEV) {
435 result = 0;
436 break;
437 } else if (result)
438 break;
439
440 result = callback(&repo);
441
442 if (result) {
443 pr_debug("%s:%d: abort at callback\n", __func__,
444 __LINE__);
445 break;
446 }
447 } 475 }
448 break;
449 } 476 }
450 477
451 pr_debug(" <- %s:%d\n", __func__, __LINE__); 478 pr_debug(" <- %s:%d\n", __func__, __LINE__);
@@ -561,7 +588,7 @@ int ps3_repository_read_stor_dev_port(unsigned int bus_index,
561 make_first_field("bus", bus_index), 588 make_first_field("bus", bus_index),
562 make_field("dev", dev_index), 589 make_field("dev", dev_index),
563 make_field("port", 0), 590 make_field("port", 0),
564 0, port, 0); 591 0, port, NULL);
565} 592}
566 593
567int ps3_repository_read_stor_dev_blk_size(unsigned int bus_index, 594int ps3_repository_read_stor_dev_blk_size(unsigned int bus_index,
@@ -571,7 +598,7 @@ int ps3_repository_read_stor_dev_blk_size(unsigned int bus_index,
571 make_first_field("bus", bus_index), 598 make_first_field("bus", bus_index),
572 make_field("dev", dev_index), 599 make_field("dev", dev_index),
573 make_field("blk_size", 0), 600 make_field("blk_size", 0),
574 0, blk_size, 0); 601 0, blk_size, NULL);
575} 602}
576 603
577int ps3_repository_read_stor_dev_num_blocks(unsigned int bus_index, 604int ps3_repository_read_stor_dev_num_blocks(unsigned int bus_index,
@@ -581,7 +608,7 @@ int ps3_repository_read_stor_dev_num_blocks(unsigned int bus_index,
581 make_first_field("bus", bus_index), 608 make_first_field("bus", bus_index),
582 make_field("dev", dev_index), 609 make_field("dev", dev_index),
583 make_field("n_blocks", 0), 610 make_field("n_blocks", 0),
584 0, num_blocks, 0); 611 0, num_blocks, NULL);
585} 612}
586 613
587int ps3_repository_read_stor_dev_num_regions(unsigned int bus_index, 614int ps3_repository_read_stor_dev_num_regions(unsigned int bus_index,
@@ -594,7 +621,7 @@ int ps3_repository_read_stor_dev_num_regions(unsigned int bus_index,
594 make_first_field("bus", bus_index), 621 make_first_field("bus", bus_index),
595 make_field("dev", dev_index), 622 make_field("dev", dev_index),
596 make_field("n_regs", 0), 623 make_field("n_regs", 0),
597 0, &v1, 0); 624 0, &v1, NULL);
598 *num_regions = v1; 625 *num_regions = v1;
599 return result; 626 return result;
600} 627}
@@ -611,7 +638,7 @@ int ps3_repository_read_stor_dev_region_id(unsigned int bus_index,
611 make_field("dev", dev_index), 638 make_field("dev", dev_index),
612 make_field("region", region_index), 639 make_field("region", region_index),
613 make_field("id", 0), 640 make_field("id", 0),
614 &v1, 0); 641 &v1, NULL);
615 *region_id = v1; 642 *region_id = v1;
616 return result; 643 return result;
617} 644}
@@ -624,7 +651,7 @@ int ps3_repository_read_stor_dev_region_size(unsigned int bus_index,
624 make_field("dev", dev_index), 651 make_field("dev", dev_index),
625 make_field("region", region_index), 652 make_field("region", region_index),
626 make_field("size", 0), 653 make_field("size", 0),
627 region_size, 0); 654 region_size, NULL);
628} 655}
629 656
630int ps3_repository_read_stor_dev_region_start(unsigned int bus_index, 657int ps3_repository_read_stor_dev_region_start(unsigned int bus_index,
@@ -635,7 +662,7 @@ int ps3_repository_read_stor_dev_region_start(unsigned int bus_index,
635 make_field("dev", dev_index), 662 make_field("dev", dev_index),
636 make_field("region", region_index), 663 make_field("region", region_index),
637 make_field("start", 0), 664 make_field("start", 0),
638 region_start, 0); 665 region_start, NULL);
639} 666}
640 667
641int ps3_repository_read_stor_dev_info(unsigned int bus_index, 668int ps3_repository_read_stor_dev_info(unsigned int bus_index,
@@ -684,6 +711,35 @@ int ps3_repository_read_stor_dev_region(unsigned int bus_index,
684 return result; 711 return result;
685} 712}
686 713
714/**
715 * ps3_repository_read_num_pu - Number of logical PU processors for this lpar.
716 */
717
718int ps3_repository_read_num_pu(u64 *num_pu)
719{
720 *num_pu = 0;
721 return read_node(PS3_LPAR_ID_CURRENT,
722 make_first_field("bi", 0),
723 make_field("pun", 0),
724 0, 0,
725 num_pu, NULL);
726}
727
728/**
729 * ps3_repository_read_pu_id - Read the logical PU id.
730 * @pu_index: Zero based index.
731 * @pu_id: The logical PU id.
732 */
733
734int ps3_repository_read_pu_id(unsigned int pu_index, u64 *pu_id)
735{
736 return read_node(PS3_LPAR_ID_CURRENT,
737 make_first_field("bi", 0),
738 make_field("pu", pu_index),
739 0, 0,
740 pu_id, NULL);
741}
742
687int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size) 743int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size)
688{ 744{
689 return read_node(PS3_LPAR_ID_CURRENT, 745 return read_node(PS3_LPAR_ID_CURRENT,
@@ -691,7 +747,7 @@ int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size)
691 make_field("pu", 0), 747 make_field("pu", 0),
692 ppe_id, 748 ppe_id,
693 make_field("rm_size", 0), 749 make_field("rm_size", 0),
694 rm_size, 0); 750 rm_size, NULL);
695} 751}
696 752
697int ps3_repository_read_region_total(u64 *region_total) 753int ps3_repository_read_region_total(u64 *region_total)
@@ -700,7 +756,7 @@ int ps3_repository_read_region_total(u64 *region_total)
700 make_first_field("bi", 0), 756 make_first_field("bi", 0),
701 make_field("rgntotal", 0), 757 make_field("rgntotal", 0),
702 0, 0, 758 0, 0,
703 region_total, 0); 759 region_total, NULL);
704} 760}
705 761
706/** 762/**
@@ -736,7 +792,7 @@ int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved)
736 make_first_field("bi", 0), 792 make_first_field("bi", 0),
737 make_field("spun", 0), 793 make_field("spun", 0),
738 0, 0, 794 0, 0,
739 &v1, 0); 795 &v1, NULL);
740 *num_spu_reserved = v1; 796 *num_spu_reserved = v1;
741 return result; 797 return result;
742} 798}
@@ -755,7 +811,7 @@ int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id)
755 make_first_field("bi", 0), 811 make_first_field("bi", 0),
756 make_field("spursvn", 0), 812 make_field("spursvn", 0),
757 0, 0, 813 0, 0,
758 &v1, 0); 814 &v1, NULL);
759 *num_resource_id = v1; 815 *num_resource_id = v1;
760 return result; 816 return result;
761} 817}
@@ -768,7 +824,7 @@ int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id)
768 */ 824 */
769 825
770int ps3_repository_read_spu_resource_id(unsigned int res_index, 826int ps3_repository_read_spu_resource_id(unsigned int res_index,
771 enum ps3_spu_resource_type* resource_type, unsigned int *resource_id) 827 enum ps3_spu_resource_type *resource_type, unsigned int *resource_id)
772{ 828{
773 int result; 829 int result;
774 u64 v1; 830 u64 v1;
@@ -785,14 +841,14 @@ int ps3_repository_read_spu_resource_id(unsigned int res_index,
785 return result; 841 return result;
786} 842}
787 843
788int ps3_repository_read_boot_dat_address(u64 *address) 844static int ps3_repository_read_boot_dat_address(u64 *address)
789{ 845{
790 return read_node(PS3_LPAR_ID_CURRENT, 846 return read_node(PS3_LPAR_ID_CURRENT,
791 make_first_field("bi", 0), 847 make_first_field("bi", 0),
792 make_field("boot_dat", 0), 848 make_field("boot_dat", 0),
793 make_field("address", 0), 849 make_field("address", 0),
794 0, 850 0,
795 address, 0); 851 address, NULL);
796} 852}
797 853
798int ps3_repository_read_boot_dat_size(unsigned int *size) 854int ps3_repository_read_boot_dat_size(unsigned int *size)
@@ -805,7 +861,7 @@ int ps3_repository_read_boot_dat_size(unsigned int *size)
805 make_field("boot_dat", 0), 861 make_field("boot_dat", 0),
806 make_field("size", 0), 862 make_field("size", 0),
807 0, 863 0,
808 &v1, 0); 864 &v1, NULL);
809 *size = v1; 865 *size = v1;
810 return result; 866 return result;
811} 867}
@@ -820,7 +876,7 @@ int ps3_repository_read_vuart_av_port(unsigned int *port)
820 make_field("vir_uart", 0), 876 make_field("vir_uart", 0),
821 make_field("port", 0), 877 make_field("port", 0),
822 make_field("avset", 0), 878 make_field("avset", 0),
823 &v1, 0); 879 &v1, NULL);
824 *port = v1; 880 *port = v1;
825 return result; 881 return result;
826} 882}
@@ -835,7 +891,7 @@ int ps3_repository_read_vuart_sysmgr_port(unsigned int *port)
835 make_field("vir_uart", 0), 891 make_field("vir_uart", 0),
836 make_field("port", 0), 892 make_field("port", 0),
837 make_field("sysmgr", 0), 893 make_field("sysmgr", 0),
838 &v1, 0); 894 &v1, NULL);
839 *port = v1; 895 *port = v1;
840 return result; 896 return result;
841} 897}
@@ -856,6 +912,10 @@ int ps3_repository_read_boot_dat_info(u64 *lpar_addr, unsigned int *size)
856 : ps3_repository_read_boot_dat_size(size); 912 : ps3_repository_read_boot_dat_size(size);
857} 913}
858 914
915/**
916 * ps3_repository_read_num_be - Number of physical BE processors in the system.
917 */
918
859int ps3_repository_read_num_be(unsigned int *num_be) 919int ps3_repository_read_num_be(unsigned int *num_be)
860{ 920{
861 int result; 921 int result;
@@ -866,11 +926,17 @@ int ps3_repository_read_num_be(unsigned int *num_be)
866 0, 926 0,
867 0, 927 0,
868 0, 928 0,
869 &v1, 0); 929 &v1, NULL);
870 *num_be = v1; 930 *num_be = v1;
871 return result; 931 return result;
872} 932}
873 933
934/**
935 * ps3_repository_read_be_node_id - Read the physical BE processor node id.
936 * @be_index: Zero based index.
937 * @node_id: The BE processor node id.
938 */
939
874int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id) 940int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id)
875{ 941{
876 return read_node(PS3_LPAR_ID_PME, 942 return read_node(PS3_LPAR_ID_PME,
@@ -878,7 +944,23 @@ int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id)
878 0, 944 0,
879 0, 945 0,
880 0, 946 0,
881 node_id, 0); 947 node_id, NULL);
948}
949
950/**
951 * ps3_repository_read_be_id - Read the physical BE processor id.
952 * @node_id: The BE processor node id.
953 * @be_id: The BE processor id.
954 */
955
956int ps3_repository_read_be_id(u64 node_id, u64 *be_id)
957{
958 return read_node(PS3_LPAR_ID_PME,
959 make_first_field("be", 0),
960 node_id,
961 0,
962 0,
963 be_id, NULL);
882} 964}
883 965
884int ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq) 966int ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq)
@@ -888,7 +970,7 @@ int ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq)
888 node_id, 970 node_id,
889 make_field("clock", 0), 971 make_field("clock", 0),
890 0, 972 0,
891 tb_freq, 0); 973 tb_freq, NULL);
892} 974}
893 975
894int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq) 976int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq)
@@ -897,11 +979,29 @@ int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq)
897 u64 node_id; 979 u64 node_id;
898 980
899 *tb_freq = 0; 981 *tb_freq = 0;
900 result = ps3_repository_read_be_node_id(0, &node_id); 982 result = ps3_repository_read_be_node_id(be_index, &node_id);
901 return result ? result 983 return result ? result
902 : ps3_repository_read_tb_freq(node_id, tb_freq); 984 : ps3_repository_read_tb_freq(node_id, tb_freq);
903} 985}
904 986
987int ps3_repository_read_lpm_privileges(unsigned int be_index, u64 *lpar,
988 u64 *rights)
989{
990 int result;
991 u64 node_id;
992
993 *lpar = 0;
994 *rights = 0;
995 result = ps3_repository_read_be_node_id(be_index, &node_id);
996 return result ? result
997 : read_node(PS3_LPAR_ID_PME,
998 make_first_field("be", 0),
999 node_id,
1000 make_field("lpm", 0),
1001 make_field("priv", 0),
1002 lpar, rights);
1003}
1004
905#if defined(DEBUG) 1005#if defined(DEBUG)
906 1006
907int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo) 1007int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo)
@@ -1034,7 +1134,7 @@ static int dump_device_info(struct ps3_repository_device *repo,
1034 continue; 1134 continue;
1035 } 1135 }
1036 1136
1037 pr_debug("%s:%d (%u:%u): dev_type %u, dev_id %u\n", __func__, 1137 pr_debug("%s:%d (%u:%u): dev_type %u, dev_id %lu\n", __func__,
1038 __LINE__, repo->bus_index, repo->dev_index, 1138 __LINE__, repo->bus_index, repo->dev_index,
1039 repo->dev_type, repo->dev_id); 1139 repo->dev_type, repo->dev_id);
1040 1140
@@ -1091,7 +1191,7 @@ int ps3_repository_dump_bus_info(void)
1091 continue; 1191 continue;
1092 } 1192 }
1093 1193
1094 pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n", 1194 pr_debug("%s:%d bus_%u: bus_type %u, bus_id %lu, num_dev %u\n",
1095 __func__, __LINE__, repo.bus_index, repo.bus_type, 1195 __func__, __LINE__, repo.bus_index, repo.bus_type,
1096 repo.bus_id, num_dev); 1196 repo.bus_id, num_dev);
1097 1197
diff --git a/arch/powerpc/platforms/ps3/spu.c b/arch/powerpc/platforms/ps3/spu.c
index d1630a074acf..5ad41189b494 100644
--- a/arch/powerpc/platforms/ps3/spu.c
+++ b/arch/powerpc/platforms/ps3/spu.c
@@ -28,6 +28,7 @@
28#include <asm/spu_priv1.h> 28#include <asm/spu_priv1.h>
29#include <asm/lv1call.h> 29#include <asm/lv1call.h>
30 30
31#include "../cell/spufs/spufs.h"
31#include "platform.h" 32#include "platform.h"
32 33
33/* spu_management_ops */ 34/* spu_management_ops */
@@ -419,10 +420,34 @@ static int ps3_init_affinity(void)
419 return 0; 420 return 0;
420} 421}
421 422
423/**
424 * ps3_enable_spu - Enable SPU run control.
425 *
426 * An outstanding enhancement for the PS3 would be to add a guard to check
427 * for incorrect access to the spu problem state when the spu context is
428 * disabled. This check could be implemented with a flag added to the spu
429 * context that would inhibit mapping problem state pages, and a routine
430 * to unmap spu problem state pages. When the spu is enabled with
431 * ps3_enable_spu() the flag would be set allowing pages to be mapped,
432 * and when the spu is disabled with ps3_disable_spu() the flag would be
433 * cleared and the mapped problem state pages would be unmapped.
434 */
435
436static void ps3_enable_spu(struct spu_context *ctx)
437{
438}
439
440static void ps3_disable_spu(struct spu_context *ctx)
441{
442 ctx->ops->runcntl_stop(ctx);
443}
444
422const struct spu_management_ops spu_management_ps3_ops = { 445const struct spu_management_ops spu_management_ps3_ops = {
423 .enumerate_spus = ps3_enumerate_spus, 446 .enumerate_spus = ps3_enumerate_spus,
424 .create_spu = ps3_create_spu, 447 .create_spu = ps3_create_spu,
425 .destroy_spu = ps3_destroy_spu, 448 .destroy_spu = ps3_destroy_spu,
449 .enable_spu = ps3_enable_spu,
450 .disable_spu = ps3_disable_spu,
426 .init_affinity = ps3_init_affinity, 451 .init_affinity = ps3_init_affinity,
427}; 452};
428 453
@@ -505,8 +530,6 @@ static void mfc_sr1_set(struct spu *spu, u64 sr1)
505 static const u64 allowed = ~(MFC_STATE1_LOCAL_STORAGE_DECODE_MASK 530 static const u64 allowed = ~(MFC_STATE1_LOCAL_STORAGE_DECODE_MASK
506 | MFC_STATE1_PROBLEM_STATE_MASK); 531 | MFC_STATE1_PROBLEM_STATE_MASK);
507 532
508 sr1 |= MFC_STATE1_MASTER_RUN_CONTROL_MASK;
509
510 BUG_ON((sr1 & allowed) != (spu_pdata(spu)->cache.sr1 & allowed)); 533 BUG_ON((sr1 & allowed) != (spu_pdata(spu)->cache.sr1 & allowed));
511 534
512 spu_pdata(spu)->cache.sr1 = sr1; 535 spu_pdata(spu)->cache.sr1 = sr1;
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c
index 6405f4a36763..43c493fca2d0 100644
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -42,8 +42,8 @@ struct {
42 int gpu; 42 int gpu;
43} static usage_hack; 43} static usage_hack;
44 44
45static int ps3_is_device(struct ps3_system_bus_device *dev, 45static int ps3_is_device(struct ps3_system_bus_device *dev, u64 bus_id,
46 unsigned int bus_id, unsigned int dev_id) 46 u64 dev_id)
47{ 47{
48 return dev->bus_id == bus_id && dev->dev_id == dev_id; 48 return dev->bus_id == bus_id && dev->dev_id == dev_id;
49} 49}
@@ -182,8 +182,8 @@ int ps3_open_hv_device(struct ps3_system_bus_device *dev)
182 case PS3_MATCH_ID_SYSTEM_MANAGER: 182 case PS3_MATCH_ID_SYSTEM_MANAGER:
183 pr_debug("%s:%d: unsupported match_id: %u\n", __func__, 183 pr_debug("%s:%d: unsupported match_id: %u\n", __func__,
184 __LINE__, dev->match_id); 184 __LINE__, dev->match_id);
185 pr_debug("%s:%d: bus_id: %u\n", __func__, 185 pr_debug("%s:%d: bus_id: %lu\n", __func__, __LINE__,
186 __LINE__, dev->bus_id); 186 dev->bus_id);
187 BUG(); 187 BUG();
188 return -EINVAL; 188 return -EINVAL;
189 189
@@ -220,8 +220,8 @@ int ps3_close_hv_device(struct ps3_system_bus_device *dev)
220 case PS3_MATCH_ID_SYSTEM_MANAGER: 220 case PS3_MATCH_ID_SYSTEM_MANAGER:
221 pr_debug("%s:%d: unsupported match_id: %u\n", __func__, 221 pr_debug("%s:%d: unsupported match_id: %u\n", __func__,
222 __LINE__, dev->match_id); 222 __LINE__, dev->match_id);
223 pr_debug("%s:%d: bus_id: %u\n", __func__, 223 pr_debug("%s:%d: bus_id: %lu\n", __func__, __LINE__,
224 __LINE__, dev->bus_id); 224 dev->bus_id);
225 BUG(); 225 BUG();
226 return -EINVAL; 226 return -EINVAL;
227 227
@@ -240,7 +240,7 @@ EXPORT_SYMBOL_GPL(ps3_close_hv_device);
240static void _dump_mmio_region(const struct ps3_mmio_region* r, 240static void _dump_mmio_region(const struct ps3_mmio_region* r,
241 const char* func, int line) 241 const char* func, int line)
242{ 242{
243 pr_debug("%s:%d: dev %u:%u\n", func, line, r->dev->bus_id, 243 pr_debug("%s:%d: dev %lu:%lu\n", func, line, r->dev->bus_id,
244 r->dev->dev_id); 244 r->dev->dev_id);
245 pr_debug("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); 245 pr_debug("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr);
246 pr_debug("%s:%d: len %lxh\n", func, line, r->len); 246 pr_debug("%s:%d: len %lxh\n", func, line, r->len);
@@ -715,6 +715,7 @@ int ps3_system_bus_device_register(struct ps3_system_bus_device *dev)
715 static unsigned int dev_ioc0_count; 715 static unsigned int dev_ioc0_count;
716 static unsigned int dev_sb_count; 716 static unsigned int dev_sb_count;
717 static unsigned int dev_vuart_count; 717 static unsigned int dev_vuart_count;
718 static unsigned int dev_lpm_count;
718 719
719 if (!dev->core.parent) 720 if (!dev->core.parent)
720 dev->core.parent = &ps3_system_bus; 721 dev->core.parent = &ps3_system_bus;
@@ -737,6 +738,10 @@ int ps3_system_bus_device_register(struct ps3_system_bus_device *dev)
737 snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), 738 snprintf(dev->core.bus_id, sizeof(dev->core.bus_id),
738 "vuart_%02x", ++dev_vuart_count); 739 "vuart_%02x", ++dev_vuart_count);
739 break; 740 break;
741 case PS3_DEVICE_TYPE_LPM:
742 snprintf(dev->core.bus_id, sizeof(dev->core.bus_id),
743 "lpm_%02x", ++dev_lpm_count);
744 break;
740 default: 745 default:
741 BUG(); 746 BUG();
742 }; 747 };
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index fb3d636e088b..9eb539ee5f9a 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -29,6 +29,8 @@
29#include <linux/rbtree.h> 29#include <linux/rbtree.h>
30#include <linux/seq_file.h> 30#include <linux/seq_file.h>
31#include <linux/spinlock.h> 31#include <linux/spinlock.h>
32#include <linux/of.h>
33
32#include <asm/atomic.h> 34#include <asm/atomic.h>
33#include <asm/eeh.h> 35#include <asm/eeh.h>
34#include <asm/eeh_event.h> 36#include <asm/eeh_event.h>
@@ -169,7 +171,6 @@ static void rtas_slot_error_detail(struct pci_dn *pdn, int severity,
169 */ 171 */
170static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) 172static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len)
171{ 173{
172 struct device_node *dn;
173 struct pci_dev *dev = pdn->pcidev; 174 struct pci_dev *dev = pdn->pcidev;
174 u32 cfg; 175 u32 cfg;
175 int cap, i; 176 int cap, i;
@@ -243,12 +244,12 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len)
243 244
244 /* Gather status on devices under the bridge */ 245 /* Gather status on devices under the bridge */
245 if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) { 246 if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) {
246 dn = pdn->node->child; 247 struct device_node *dn;
247 while (dn) { 248
249 for_each_child_of_node(pdn->node, dn) {
248 pdn = PCI_DN(dn); 250 pdn = PCI_DN(dn);
249 if (pdn) 251 if (pdn)
250 n += gather_pci_data(pdn, buf+n, len-n); 252 n += gather_pci_data(pdn, buf+n, len-n);
251 dn = dn->sibling;
252 } 253 }
253 } 254 }
254 255
@@ -372,7 +373,7 @@ struct device_node * find_device_pe(struct device_node *dn)
372 return dn; 373 return dn;
373} 374}
374 375
375/** Mark all devices that are peers of this device as failed. 376/** Mark all devices that are children of this device as failed.
376 * Mark the device driver too, so that it can see the failure 377 * Mark the device driver too, so that it can see the failure
377 * immediately; this is critical, since some drivers poll 378 * immediately; this is critical, since some drivers poll
378 * status registers in interrupts ... If a driver is polling, 379 * status registers in interrupts ... If a driver is polling,
@@ -380,9 +381,11 @@ struct device_node * find_device_pe(struct device_node *dn)
380 * an interrupt context, which is bad. 381 * an interrupt context, which is bad.
381 */ 382 */
382 383
383static void __eeh_mark_slot (struct device_node *dn, int mode_flag) 384static void __eeh_mark_slot(struct device_node *parent, int mode_flag)
384{ 385{
385 while (dn) { 386 struct device_node *dn;
387
388 for_each_child_of_node(parent, dn) {
386 if (PCI_DN(dn)) { 389 if (PCI_DN(dn)) {
387 /* Mark the pci device driver too */ 390 /* Mark the pci device driver too */
388 struct pci_dev *dev = PCI_DN(dn)->pcidev; 391 struct pci_dev *dev = PCI_DN(dn)->pcidev;
@@ -392,10 +395,8 @@ static void __eeh_mark_slot (struct device_node *dn, int mode_flag)
392 if (dev && dev->driver) 395 if (dev && dev->driver)
393 dev->error_state = pci_channel_io_frozen; 396 dev->error_state = pci_channel_io_frozen;
394 397
395 if (dn->child) 398 __eeh_mark_slot(dn, mode_flag);
396 __eeh_mark_slot (dn->child, mode_flag);
397 } 399 }
398 dn = dn->sibling;
399 } 400 }
400} 401}
401 402
@@ -415,19 +416,19 @@ void eeh_mark_slot (struct device_node *dn, int mode_flag)
415 if (dev) 416 if (dev)
416 dev->error_state = pci_channel_io_frozen; 417 dev->error_state = pci_channel_io_frozen;
417 418
418 __eeh_mark_slot (dn->child, mode_flag); 419 __eeh_mark_slot(dn, mode_flag);
419} 420}
420 421
421static void __eeh_clear_slot (struct device_node *dn, int mode_flag) 422static void __eeh_clear_slot(struct device_node *parent, int mode_flag)
422{ 423{
423 while (dn) { 424 struct device_node *dn;
425
426 for_each_child_of_node(parent, dn) {
424 if (PCI_DN(dn)) { 427 if (PCI_DN(dn)) {
425 PCI_DN(dn)->eeh_mode &= ~mode_flag; 428 PCI_DN(dn)->eeh_mode &= ~mode_flag;
426 PCI_DN(dn)->eeh_check_count = 0; 429 PCI_DN(dn)->eeh_check_count = 0;
427 if (dn->child) 430 __eeh_clear_slot(dn, mode_flag);
428 __eeh_clear_slot (dn->child, mode_flag);
429 } 431 }
430 dn = dn->sibling;
431 } 432 }
432} 433}
433 434
@@ -444,7 +445,7 @@ void eeh_clear_slot (struct device_node *dn, int mode_flag)
444 445
445 PCI_DN(dn)->eeh_mode &= ~mode_flag; 446 PCI_DN(dn)->eeh_mode &= ~mode_flag;
446 PCI_DN(dn)->eeh_check_count = 0; 447 PCI_DN(dn)->eeh_check_count = 0;
447 __eeh_clear_slot (dn->child, mode_flag); 448 __eeh_clear_slot(dn, mode_flag);
448 spin_unlock_irqrestore(&confirm_error_lock, flags); 449 spin_unlock_irqrestore(&confirm_error_lock, flags);
449} 450}
450 451
@@ -480,6 +481,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
480 no_dn++; 481 no_dn++;
481 return 0; 482 return 0;
482 } 483 }
484 dn = find_device_pe(dn);
483 pdn = PCI_DN(dn); 485 pdn = PCI_DN(dn);
484 486
485 /* Access to IO BARs might get this far and still not want checking. */ 487 /* Access to IO BARs might get this far and still not want checking. */
@@ -545,7 +547,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
545 547
546 /* Note that config-io to empty slots may fail; 548 /* Note that config-io to empty slots may fail;
547 * they are empty when they don't have children. */ 549 * they are empty when they don't have children. */
548 if ((rets[0] == 5) && (dn->child == NULL)) { 550 if ((rets[0] == 5) && (rets[2] == 0) && (dn->child == NULL)) {
549 false_positives++; 551 false_positives++;
550 pdn->eeh_false_positives ++; 552 pdn->eeh_false_positives ++;
551 rc = 0; 553 rc = 0;
@@ -848,11 +850,8 @@ void eeh_restore_bars(struct pci_dn *pdn)
848 if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(pdn->class_code)) 850 if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(pdn->class_code))
849 __restore_bars (pdn); 851 __restore_bars (pdn);
850 852
851 dn = pdn->node->child; 853 for_each_child_of_node(pdn->node, dn)
852 while (dn) {
853 eeh_restore_bars (PCI_DN(dn)); 854 eeh_restore_bars (PCI_DN(dn));
854 dn = dn->sibling;
855 }
856} 855}
857 856
858/** 857/**
@@ -1130,7 +1129,8 @@ static void eeh_add_device_early(struct device_node *dn)
1130void eeh_add_device_tree_early(struct device_node *dn) 1129void eeh_add_device_tree_early(struct device_node *dn)
1131{ 1130{
1132 struct device_node *sib; 1131 struct device_node *sib;
1133 for (sib = dn->child; sib; sib = sib->sibling) 1132
1133 for_each_child_of_node(dn, sib)
1134 eeh_add_device_tree_early(sib); 1134 eeh_add_device_tree_early(sib);
1135 eeh_add_device_early(dn); 1135 eeh_add_device_early(dn);
1136} 1136}
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index 57e025e84ab4..68ea5eee39a8 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -310,8 +310,6 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
310 const char *location, *pci_str, *drv_str; 310 const char *location, *pci_str, *drv_str;
311 311
312 frozen_dn = find_device_pe(event->dn); 312 frozen_dn = find_device_pe(event->dn);
313 frozen_bus = pcibios_find_pci_bus(frozen_dn);
314
315 if (!frozen_dn) { 313 if (!frozen_dn) {
316 314
317 location = of_get_property(event->dn, "ibm,loc-code", NULL); 315 location = of_get_property(event->dn, "ibm,loc-code", NULL);
@@ -321,6 +319,8 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
321 location, pci_name(event->dev)); 319 location, pci_name(event->dev));
322 return NULL; 320 return NULL;
323 } 321 }
322
323 frozen_bus = pcibios_find_pci_bus(frozen_dn);
324 location = of_get_property(frozen_dn, "ibm,loc-code", NULL); 324 location = of_get_property(frozen_dn, "ibm,loc-code", NULL);
325 location = location ? location : "unknown"; 325 location = location ? location : "unknown";
326 326
@@ -354,13 +354,6 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
354 if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES) 354 if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES)
355 goto excess_failures; 355 goto excess_failures;
356 356
357 /* Get the current PCI slot state. */
358 rc = eeh_wait_for_slot_status (frozen_pdn, MAX_WAIT_FOR_RECOVERY*1000);
359 if (rc < 0) {
360 printk(KERN_WARNING "EEH: Permanent failure\n");
361 goto hard_fail;
362 }
363
364 printk(KERN_WARNING 357 printk(KERN_WARNING
365 "EEH: This PCI device has failed %d times in the last hour:\n", 358 "EEH: This PCI device has failed %d times in the last hour:\n",
366 frozen_pdn->eeh_freeze_count); 359 frozen_pdn->eeh_freeze_count);
@@ -376,6 +369,14 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
376 */ 369 */
377 pci_walk_bus(frozen_bus, eeh_report_error, &result); 370 pci_walk_bus(frozen_bus, eeh_report_error, &result);
378 371
372 /* Get the current PCI slot state. This can take a long time,
373 * sometimes over 3 seconds for certain systems. */
374 rc = eeh_wait_for_slot_status (frozen_pdn, MAX_WAIT_FOR_RECOVERY*1000);
375 if (rc < 0) {
376 printk(KERN_WARNING "EEH: Permanent failure\n");
377 goto hard_fail;
378 }
379
379 /* Since rtas may enable MMIO when posting the error log, 380 /* Since rtas may enable MMIO when posting the error log,
380 * don't post the error log until after all dev drivers 381 * don't post the error log until after all dev drivers
381 * have been informed. 382 * have been informed.
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index be17d2395072..a65c76308201 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -251,7 +251,7 @@ static void iommu_table_setparms(struct pci_controller *phb,
251 const unsigned long *basep; 251 const unsigned long *basep;
252 const u32 *sizep; 252 const u32 *sizep;
253 253
254 node = (struct device_node *)phb->arch_data; 254 node = phb->dn;
255 255
256 basep = of_get_property(node, "linux,tce-base", NULL); 256 basep = of_get_property(node, "linux,tce-base", NULL);
257 sizep = of_get_property(node, "linux,tce-size", NULL); 257 sizep = of_get_property(node, "linux,tce-size", NULL);
@@ -296,11 +296,12 @@ static void iommu_table_setparms(struct pci_controller *phb,
296static void iommu_table_setparms_lpar(struct pci_controller *phb, 296static void iommu_table_setparms_lpar(struct pci_controller *phb,
297 struct device_node *dn, 297 struct device_node *dn,
298 struct iommu_table *tbl, 298 struct iommu_table *tbl,
299 const void *dma_window) 299 const void *dma_window,
300 int bussubno)
300{ 301{
301 unsigned long offset, size; 302 unsigned long offset, size;
302 303
303 tbl->it_busno = PCI_DN(dn)->bussubno; 304 tbl->it_busno = bussubno;
304 of_parse_dma_window(dn, dma_window, &tbl->it_index, &offset, &size); 305 of_parse_dma_window(dn, dma_window, &tbl->it_index, &offset, &size);
305 306
306 tbl->it_base = 0; 307 tbl->it_base = 0;
@@ -420,17 +421,10 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
420 pdn->full_name, ppci->iommu_table); 421 pdn->full_name, ppci->iommu_table);
421 422
422 if (!ppci->iommu_table) { 423 if (!ppci->iommu_table) {
423 /* Bussubno hasn't been copied yet.
424 * Do it now because iommu_table_setparms_lpar needs it.
425 */
426
427 ppci->bussubno = bus->number;
428
429 tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, 424 tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
430 ppci->phb->node); 425 ppci->phb->node);
431 426 iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window,
432 iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window); 427 bus->number);
433
434 ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node); 428 ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node);
435 DBG(" created table: %p\n", ppci->iommu_table); 429 DBG(" created table: %p\n", ppci->iommu_table);
436 } 430 }
@@ -523,14 +517,10 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
523 517
524 pci = PCI_DN(pdn); 518 pci = PCI_DN(pdn);
525 if (!pci->iommu_table) { 519 if (!pci->iommu_table) {
526 /* iommu_table_setparms_lpar needs bussubno. */
527 pci->bussubno = pci->phb->bus->number;
528
529 tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, 520 tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
530 pci->phb->node); 521 pci->phb->node);
531 522 iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window,
532 iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window); 523 pci->phb->bus->number);
533
534 pci->iommu_table = iommu_init_table(tbl, pci->phb->node); 524 pci->iommu_table = iommu_init_table(tbl, pci->phb->node);
535 DBG(" created table: %p\n", pci->iommu_table); 525 DBG(" created table: %p\n", pci->iommu_table);
536 } else { 526 } else {
@@ -556,7 +546,7 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti
556 case PSERIES_RECONFIG_REMOVE: 546 case PSERIES_RECONFIG_REMOVE:
557 if (pci && pci->iommu_table && 547 if (pci && pci->iommu_table &&
558 of_get_property(np, "ibm,dma-window", NULL)) 548 of_get_property(np, "ibm,dma-window", NULL))
559 iommu_free_table(np); 549 iommu_free_table(pci->iommu_table, np->full_name);
560 break; 550 break;
561 default: 551 default:
562 err = NOTIFY_DONE; 552 err = NOTIFY_DONE;
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index 47f0e0857f0e..5a5a19e40bb4 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -83,7 +83,7 @@ EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices);
83 83
84/* Must be called before pci_bus_add_devices */ 84/* Must be called before pci_bus_add_devices */
85void 85void
86pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) 86pcibios_fixup_new_pci_devices(struct pci_bus *bus)
87{ 87{
88 struct pci_dev *dev; 88 struct pci_dev *dev;
89 89
@@ -98,8 +98,6 @@ pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
98 /* Fill device archdata and setup iommu table */ 98 /* Fill device archdata and setup iommu table */
99 pcibios_setup_new_device(dev); 99 pcibios_setup_new_device(dev);
100 100
101 if(fix_bus)
102 pcibios_fixup_device_resources(dev, bus);
103 pci_read_irq_line(dev); 101 pci_read_irq_line(dev);
104 for (i = 0; i < PCI_NUM_RESOURCES; i++) { 102 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
105 struct resource *r = &dev->resource[i]; 103 struct resource *r = &dev->resource[i];
@@ -132,8 +130,8 @@ pcibios_pci_config_bridge(struct pci_dev *dev)
132 130
133 pci_scan_child_bus(child_bus); 131 pci_scan_child_bus(child_bus);
134 132
135 /* Fixup new pci devices without touching bus struct */ 133 /* Fixup new pci devices */
136 pcibios_fixup_new_pci_devices(child_bus, 0); 134 pcibios_fixup_new_pci_devices(child_bus);
137 135
138 /* Make the discovered devices available */ 136 /* Make the discovered devices available */
139 pci_bus_add_devices(child_bus); 137 pci_bus_add_devices(child_bus);
@@ -169,7 +167,7 @@ pcibios_add_pci_devices(struct pci_bus * bus)
169 /* use ofdt-based probe */ 167 /* use ofdt-based probe */
170 of_scan_bus(dn, bus); 168 of_scan_bus(dn, bus);
171 if (!list_empty(&bus->devices)) { 169 if (!list_empty(&bus->devices)) {
172 pcibios_fixup_new_pci_devices(bus, 0); 170 pcibios_fixup_new_pci_devices(bus);
173 pci_bus_add_devices(bus); 171 pci_bus_add_devices(bus);
174 eeh_add_device_tree_late(bus); 172 eeh_add_device_tree_late(bus);
175 } 173 }
@@ -178,7 +176,7 @@ pcibios_add_pci_devices(struct pci_bus * bus)
178 slotno = PCI_SLOT(PCI_DN(dn->child)->devfn); 176 slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
179 num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); 177 num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
180 if (num) { 178 if (num) {
181 pcibios_fixup_new_pci_devices(bus, 1); 179 pcibios_fixup_new_pci_devices(bus);
182 pci_bus_add_devices(bus); 180 pci_bus_add_devices(bus);
183 eeh_add_device_tree_late(bus); 181 eeh_add_device_tree_late(bus);
184 } 182 }
@@ -208,7 +206,7 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
208 eeh_add_device_tree_early(dn); 206 eeh_add_device_tree_early(dn);
209 207
210 scan_phb(phb); 208 scan_phb(phb);
211 pcibios_fixup_new_pci_devices(phb->bus, 0); 209 pcibios_fixup_new_pci_devices(phb->bus);
212 pci_bus_add_devices(phb->bus); 210 pci_bus_add_devices(phb->bus);
213 eeh_add_device_tree_late(phb->bus); 211 eeh_add_device_tree_late(phb->bus);
214 212
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h
index d003c80fa31d..d8680b589dc9 100644
--- a/arch/powerpc/platforms/pseries/plpar_wrappers.h
+++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h
@@ -8,11 +8,6 @@ static inline long poll_pending(void)
8 return plpar_hcall_norets(H_POLL_PENDING); 8 return plpar_hcall_norets(H_POLL_PENDING);
9} 9}
10 10
11static inline long prod_processor(void)
12{
13 return plpar_hcall_norets(H_PROD);
14}
15
16static inline long cede_processor(void) 11static inline long cede_processor(void)
17{ 12{
18 return plpar_hcall_norets(H_CEDE); 13 return plpar_hcall_norets(H_CEDE);
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index 116305b22a2b..ea4c65917a64 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -46,6 +46,7 @@
46#include <asm/pSeries_reconfig.h> 46#include <asm/pSeries_reconfig.h>
47#include <asm/mpic.h> 47#include <asm/mpic.h>
48#include <asm/vdso_datapage.h> 48#include <asm/vdso_datapage.h>
49#include <asm/cputhreads.h>
49 50
50#include "plpar_wrappers.h" 51#include "plpar_wrappers.h"
51#include "pseries.h" 52#include "pseries.h"
@@ -202,7 +203,7 @@ static int smp_pSeries_cpu_bootable(unsigned int nr)
202 */ 203 */
203 if (system_state < SYSTEM_RUNNING && 204 if (system_state < SYSTEM_RUNNING &&
204 cpu_has_feature(CPU_FTR_SMT) && 205 cpu_has_feature(CPU_FTR_SMT) &&
205 !smt_enabled_at_boot && nr % 2 != 0) 206 !smt_enabled_at_boot && cpu_thread_in_core(nr) != 0)
206 return 0; 207 return 0;
207 208
208 return 1; 209 return 1;
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 66e7d68ffeb1..8f8dd9c3ca6b 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -87,19 +87,25 @@ static int ibm_int_off;
87/* Direct HW low level accessors */ 87/* Direct HW low level accessors */
88 88
89 89
90static inline unsigned int direct_xirr_info_get(int n_cpu) 90static inline unsigned int direct_xirr_info_get(void)
91{ 91{
92 return in_be32(&xics_per_cpu[n_cpu]->xirr.word); 92 int cpu = smp_processor_id();
93
94 return in_be32(&xics_per_cpu[cpu]->xirr.word);
93} 95}
94 96
95static inline void direct_xirr_info_set(int n_cpu, int value) 97static inline void direct_xirr_info_set(int value)
96{ 98{
97 out_be32(&xics_per_cpu[n_cpu]->xirr.word, value); 99 int cpu = smp_processor_id();
100
101 out_be32(&xics_per_cpu[cpu]->xirr.word, value);
98} 102}
99 103
100static inline void direct_cppr_info(int n_cpu, u8 value) 104static inline void direct_cppr_info(u8 value)
101{ 105{
102 out_8(&xics_per_cpu[n_cpu]->xirr.bytes[0], value); 106 int cpu = smp_processor_id();
107
108 out_8(&xics_per_cpu[cpu]->xirr.bytes[0], value);
103} 109}
104 110
105static inline void direct_qirr_info(int n_cpu, u8 value) 111static inline void direct_qirr_info(int n_cpu, u8 value)
@@ -111,7 +117,7 @@ static inline void direct_qirr_info(int n_cpu, u8 value)
111/* LPAR low level accessors */ 117/* LPAR low level accessors */
112 118
113 119
114static inline unsigned int lpar_xirr_info_get(int n_cpu) 120static inline unsigned int lpar_xirr_info_get(void)
115{ 121{
116 unsigned long lpar_rc; 122 unsigned long lpar_rc;
117 unsigned long return_value; 123 unsigned long return_value;
@@ -122,7 +128,7 @@ static inline unsigned int lpar_xirr_info_get(int n_cpu)
122 return (unsigned int)return_value; 128 return (unsigned int)return_value;
123} 129}
124 130
125static inline void lpar_xirr_info_set(int n_cpu, int value) 131static inline void lpar_xirr_info_set(int value)
126{ 132{
127 unsigned long lpar_rc; 133 unsigned long lpar_rc;
128 unsigned long val64 = value & 0xffffffff; 134 unsigned long val64 = value & 0xffffffff;
@@ -133,7 +139,7 @@ static inline void lpar_xirr_info_set(int n_cpu, int value)
133 val64); 139 val64);
134} 140}
135 141
136static inline void lpar_cppr_info(int n_cpu, u8 value) 142static inline void lpar_cppr_info(u8 value)
137{ 143{
138 unsigned long lpar_rc; 144 unsigned long lpar_rc;
139 145
@@ -275,21 +281,19 @@ static unsigned int xics_startup(unsigned int virq)
275 281
276static void xics_eoi_direct(unsigned int virq) 282static void xics_eoi_direct(unsigned int virq)
277{ 283{
278 int cpu = smp_processor_id();
279 unsigned int irq = (unsigned int)irq_map[virq].hwirq; 284 unsigned int irq = (unsigned int)irq_map[virq].hwirq;
280 285
281 iosync(); 286 iosync();
282 direct_xirr_info_set(cpu, (0xff << 24) | irq); 287 direct_xirr_info_set((0xff << 24) | irq);
283} 288}
284 289
285 290
286static void xics_eoi_lpar(unsigned int virq) 291static void xics_eoi_lpar(unsigned int virq)
287{ 292{
288 int cpu = smp_processor_id();
289 unsigned int irq = (unsigned int)irq_map[virq].hwirq; 293 unsigned int irq = (unsigned int)irq_map[virq].hwirq;
290 294
291 iosync(); 295 iosync();
292 lpar_xirr_info_set(cpu, (0xff << 24) | irq); 296 lpar_xirr_info_set((0xff << 24) | irq);
293} 297}
294 298
295static inline unsigned int xics_remap_irq(unsigned int vec) 299static inline unsigned int xics_remap_irq(unsigned int vec)
@@ -312,16 +316,12 @@ static inline unsigned int xics_remap_irq(unsigned int vec)
312 316
313static unsigned int xics_get_irq_direct(void) 317static unsigned int xics_get_irq_direct(void)
314{ 318{
315 unsigned int cpu = smp_processor_id(); 319 return xics_remap_irq(direct_xirr_info_get());
316
317 return xics_remap_irq(direct_xirr_info_get(cpu));
318} 320}
319 321
320static unsigned int xics_get_irq_lpar(void) 322static unsigned int xics_get_irq_lpar(void)
321{ 323{
322 unsigned int cpu = smp_processor_id(); 324 return xics_remap_irq(lpar_xirr_info_get());
323
324 return xics_remap_irq(lpar_xirr_info_get(cpu));
325} 325}
326 326
327#ifdef CONFIG_SMP 327#ifdef CONFIG_SMP
@@ -387,12 +387,12 @@ void xics_cause_IPI(int cpu)
387 387
388#endif /* CONFIG_SMP */ 388#endif /* CONFIG_SMP */
389 389
390static void xics_set_cpu_priority(int cpu, unsigned char cppr) 390static void xics_set_cpu_priority(unsigned char cppr)
391{ 391{
392 if (firmware_has_feature(FW_FEATURE_LPAR)) 392 if (firmware_has_feature(FW_FEATURE_LPAR))
393 lpar_cppr_info(cpu, cppr); 393 lpar_cppr_info(cppr);
394 else 394 else
395 direct_cppr_info(cpu, cppr); 395 direct_cppr_info(cppr);
396 iosync(); 396 iosync();
397} 397}
398 398
@@ -440,9 +440,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
440 440
441void xics_setup_cpu(void) 441void xics_setup_cpu(void)
442{ 442{
443 int cpu = smp_processor_id(); 443 xics_set_cpu_priority(0xff);
444
445 xics_set_cpu_priority(cpu, 0xff);
446 444
447 /* 445 /*
448 * Put the calling processor into the GIQ. This is really only 446 * Put the calling processor into the GIQ. This is really only
@@ -783,7 +781,7 @@ void xics_teardown_cpu(int secondary)
783 unsigned int ipi; 781 unsigned int ipi;
784 struct irq_desc *desc; 782 struct irq_desc *desc;
785 783
786 xics_set_cpu_priority(cpu, 0); 784 xics_set_cpu_priority(0);
787 785
788 /* 786 /*
789 * Clear IPI 787 * Clear IPI
@@ -824,10 +822,11 @@ void xics_teardown_cpu(int secondary)
824void xics_migrate_irqs_away(void) 822void xics_migrate_irqs_away(void)
825{ 823{
826 int status; 824 int status;
827 unsigned int irq, virq, cpu = smp_processor_id(); 825 int cpu = smp_processor_id(), hw_cpu = hard_smp_processor_id();
826 unsigned int irq, virq;
828 827
829 /* Reject any interrupt that was queued to us... */ 828 /* Reject any interrupt that was queued to us... */
830 xics_set_cpu_priority(cpu, 0); 829 xics_set_cpu_priority(0);
831 830
832 /* remove ourselves from the global interrupt queue */ 831 /* remove ourselves from the global interrupt queue */
833 status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE, 832 status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
@@ -835,7 +834,7 @@ void xics_migrate_irqs_away(void)
835 WARN_ON(status < 0); 834 WARN_ON(status < 0);
836 835
837 /* Allow IPIs again... */ 836 /* Allow IPIs again... */
838 xics_set_cpu_priority(cpu, DEFAULT_PRIORITY); 837 xics_set_cpu_priority(DEFAULT_PRIORITY);
839 838
840 for_each_irq(virq) { 839 for_each_irq(virq) {
841 struct irq_desc *desc; 840 struct irq_desc *desc;
@@ -874,7 +873,7 @@ void xics_migrate_irqs_away(void)
874 * The irq has to be migrated only in the single cpu 873 * The irq has to be migrated only in the single cpu
875 * case. 874 * case.
876 */ 875 */
877 if (xics_status[0] != get_hard_smp_processor_id(cpu)) 876 if (xics_status[0] != hw_cpu)
878 goto unlock; 877 goto unlock;
879 878
880 printk(KERN_WARNING "IRQ %u affinity broken off cpu %u\n", 879 printk(KERN_WARNING "IRQ %u affinity broken off cpu %u\n",
diff --git a/arch/powerpc/platforms/pseries/xics.h b/arch/powerpc/platforms/pseries/xics.h
index db0ec3ba3ae2..9ffd809d29e2 100644
--- a/arch/powerpc/platforms/pseries/xics.h
+++ b/arch/powerpc/platforms/pseries/xics.h
@@ -21,9 +21,6 @@ extern void xics_cause_IPI(int cpu);
21extern void xics_request_IPIs(void); 21extern void xics_request_IPIs(void);
22extern void xics_migrate_irqs_away(void); 22extern void xics_migrate_irqs_away(void);
23 23
24/* first argument is ignored for now*/
25void pSeriesLP_cppr_info(int n_cpu, u8 value);
26
27struct xics_ipi_struct { 24struct xics_ipi_struct {
28 volatile unsigned long value; 25 volatile unsigned long value;
29} ____cacheline_aligned; 26} ____cacheline_aligned;