summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@insightbb.com>2007-05-01 00:24:54 -0400
committerDmitry Torokhov <dtor@insightbb.com>2007-05-01 00:24:54 -0400
commitbc95f3669f5e6f63cf0b84fe4922c3c6dd4aa775 (patch)
tree427fcf2a7287c16d4b5aa6cbf494d59579a6a8b1 /arch/powerpc/platforms
parent3d29cdff999c37b3876082278a8134a0642a02cd (diff)
parentdc87c3985e9b442c60994308a96f887579addc39 (diff)
downloadlinux-bc95f3669f5e6f63cf0b84fe4922c3c6dd4aa775.tar.bz2
Merge master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts: drivers/usb/input/Makefile drivers/usb/input/gtco.c
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/4xx/Kconfig372
-rw-r--r--arch/powerpc/platforms/52xx/Kconfig35
-rw-r--r--arch/powerpc/platforms/52xx/efika.c15
-rw-r--r--arch/powerpc/platforms/52xx/lite5200.c12
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_common.c2
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_pci.c2
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_pic.c4
-rw-r--r--arch/powerpc/platforms/82xx/Kconfig45
-rw-r--r--arch/powerpc/platforms/82xx/mpc82xx.c6
-rw-r--r--arch/powerpc/platforms/82xx/mpc82xx_ads.c12
-rw-r--r--arch/powerpc/platforms/83xx/Kconfig23
-rw-r--r--arch/powerpc/platforms/83xx/Makefile3
-rw-r--r--arch/powerpc/platforms/83xx/mpc8313_rdb.c11
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_mds.c66
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_mds.h19
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_rdb.c138
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_itx.c23
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_itx.h23
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_mds.c35
-rw-r--r--arch/powerpc/platforms/83xx/mpc836x_mds.c (renamed from arch/powerpc/platforms/83xx/mpc8360e_pb.c)97
-rw-r--r--arch/powerpc/platforms/83xx/pci.c2
-rw-r--r--arch/powerpc/platforms/85xx/Kconfig45
-rw-r--r--arch/powerpc/platforms/85xx/Makefile3
-rw-r--r--arch/powerpc/platforms/85xx/mpc8544_ds.c144
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ads.c16
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_cds.c17
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_mds.c (renamed from arch/powerpc/platforms/85xx/mpc8568_mds.c)48
-rw-r--r--arch/powerpc/platforms/85xx/pci.c2
-rw-r--r--arch/powerpc/platforms/86xx/Kconfig18
-rw-r--r--arch/powerpc/platforms/86xx/Makefile2
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_hpcn.c13
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_pcie.c173
-rw-r--r--arch/powerpc/platforms/86xx/pci.c4
-rw-r--r--arch/powerpc/platforms/8xx/Kconfig67
-rw-r--r--arch/powerpc/platforms/8xx/m8xx_setup.c8
-rw-r--r--arch/powerpc/platforms/8xx/mpc86xads.h2
-rw-r--r--arch/powerpc/platforms/8xx/mpc86xads_setup.c4
-rw-r--r--arch/powerpc/platforms/8xx/mpc885ads.h2
-rw-r--r--arch/powerpc/platforms/8xx/mpc885ads_setup.c4
-rw-r--r--arch/powerpc/platforms/Kconfig259
-rw-r--r--arch/powerpc/platforms/cell/Kconfig24
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq.c112
-rw-r--r--arch/powerpc/platforms/cell/cbe_regs.c168
-rw-r--r--arch/powerpc/platforms/cell/cbe_regs.h5
-rw-r--r--arch/powerpc/platforms/cell/cbe_thermal.c181
-rw-r--r--arch/powerpc/platforms/cell/interrupt.c4
-rw-r--r--arch/powerpc/platforms/cell/io-workarounds.c2
-rw-r--r--arch/powerpc/platforms/cell/iommu.c16
-rw-r--r--arch/powerpc/platforms/cell/ras.c160
-rw-r--r--arch/powerpc/platforms/cell/setup.c12
-rw-r--r--arch/powerpc/platforms/cell/spider-pic.c8
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c242
-rw-r--r--arch/powerpc/platforms/cell/spu_coredump.c34
-rw-r--r--arch/powerpc/platforms/cell/spu_manage.c18
-rw-r--r--arch/powerpc/platforms/cell/spufs/Makefile2
-rw-r--r--arch/powerpc/platforms/cell/spufs/backing_ops.c6
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c45
-rw-r--r--arch/powerpc/platforms/cell/spufs/coredump.c19
-rw-r--r--arch/powerpc/platforms/cell/spufs/fault.c211
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c176
-rw-r--r--arch/powerpc/platforms/cell/spufs/hw_ops.c9
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c44
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c123
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c131
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h38
-rw-r--r--arch/powerpc/platforms/cell/spufs/switch.c70
-rw-r--r--arch/powerpc/platforms/celleb/Kconfig9
-rw-r--r--arch/powerpc/platforms/celleb/Makefile3
-rw-r--r--arch/powerpc/platforms/celleb/iommu.c6
-rw-r--r--arch/powerpc/platforms/celleb/pci.c18
-rw-r--r--arch/powerpc/platforms/celleb/scc_epci.c82
-rw-r--r--arch/powerpc/platforms/celleb/setup.c14
-rw-r--r--arch/powerpc/platforms/chrp/Kconfig11
-rw-r--r--arch/powerpc/platforms/chrp/nvram.c2
-rw-r--r--arch/powerpc/platforms/chrp/pci.c25
-rw-r--r--arch/powerpc/platforms/chrp/pegasos_eth.c2
-rw-r--r--arch/powerpc/platforms/chrp/setup.c52
-rw-r--r--arch/powerpc/platforms/chrp/time.c13
-rw-r--r--arch/powerpc/platforms/embedded6xx/Kconfig265
-rw-r--r--arch/powerpc/platforms/embedded6xx/linkstation.c8
-rw-r--r--arch/powerpc/platforms/embedded6xx/ls_uart.c4
-rw-r--r--arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c15
-rw-r--r--arch/powerpc/platforms/iseries/Kconfig4
-rw-r--r--arch/powerpc/platforms/iseries/iommu.c4
-rw-r--r--arch/powerpc/platforms/iseries/irq.c4
-rw-r--r--arch/powerpc/platforms/iseries/pci.c5
-rw-r--r--arch/powerpc/platforms/iseries/setup.c10
-rw-r--r--arch/powerpc/platforms/iseries/viopath.c2
-rw-r--r--arch/powerpc/platforms/maple/Kconfig17
-rw-r--r--arch/powerpc/platforms/maple/pci.c8
-rw-r--r--arch/powerpc/platforms/maple/setup.c17
-rw-r--r--arch/powerpc/platforms/pasemi/Kconfig19
-rw-r--r--arch/powerpc/platforms/pasemi/Makefile3
-rw-r--r--arch/powerpc/platforms/pasemi/cpufreq.c308
-rw-r--r--arch/powerpc/platforms/pasemi/gpio_mdio.c339
-rw-r--r--arch/powerpc/platforms/pasemi/idle.c9
-rw-r--r--arch/powerpc/platforms/pasemi/iommu.c8
-rw-r--r--arch/powerpc/platforms/pasemi/pasemi.h8
-rw-r--r--arch/powerpc/platforms/pasemi/pci.c16
-rw-r--r--arch/powerpc/platforms/pasemi/setup.c28
-rw-r--r--arch/powerpc/platforms/powermac/Kconfig20
-rw-r--r--arch/powerpc/platforms/powermac/backlight.c36
-rw-r--r--arch/powerpc/platforms/powermac/cpufreq_32.c24
-rw-r--r--arch/powerpc/platforms/powermac/cpufreq_64.c16
-rw-r--r--arch/powerpc/platforms/powermac/feature.c106
-rw-r--r--arch/powerpc/platforms/powermac/low_i2c.c15
-rw-r--r--arch/powerpc/platforms/powermac/pci.c48
-rw-r--r--arch/powerpc/platforms/powermac/pfunc_base.c2
-rw-r--r--arch/powerpc/platforms/powermac/pfunc_core.c5
-rw-r--r--arch/powerpc/platforms/powermac/pic.c8
-rw-r--r--arch/powerpc/platforms/powermac/setup.c61
-rw-r--r--arch/powerpc/platforms/powermac/smp.c11
-rw-r--r--arch/powerpc/platforms/powermac/time.c38
-rw-r--r--arch/powerpc/platforms/powermac/udbg_scc.c6
-rw-r--r--arch/powerpc/platforms/prep/Kconfig9
-rw-r--r--arch/powerpc/platforms/ps3/Kconfig50
-rw-r--r--arch/powerpc/platforms/ps3/htab.c2
-rw-r--r--arch/powerpc/platforms/ps3/mm.c2
-rw-r--r--arch/powerpc/platforms/ps3/setup.c27
-rw-r--r--arch/powerpc/platforms/ps3/system-bus.c2
-rw-r--r--arch/powerpc/platforms/pseries/Kconfig10
-rw-r--r--arch/powerpc/platforms/pseries/Makefile7
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c204
-rw-r--r--arch/powerpc/platforms/pseries/eeh_driver.c78
-rw-r--r--arch/powerpc/platforms/pseries/eeh_event.c8
-rw-r--r--arch/powerpc/platforms/pseries/firmware.c2
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-cpu.c4
-rw-r--r--arch/powerpc/platforms/pseries/hvCall.S41
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c67
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c8
-rw-r--r--arch/powerpc/platforms/pseries/nvram.c2
-rw-r--r--arch/powerpc/platforms/pseries/pci.c3
-rw-r--r--arch/powerpc/platforms/pseries/pci_dlpar.c1
-rw-r--r--arch/powerpc/platforms/pseries/plpar_wrappers.h16
-rw-r--r--arch/powerpc/platforms/pseries/power.c87
-rw-r--r--arch/powerpc/platforms/pseries/pseries.h7
-rw-r--r--arch/powerpc/platforms/pseries/ras.c2
-rw-r--r--arch/powerpc/platforms/pseries/rtasd.c2
-rw-r--r--arch/powerpc/platforms/pseries/setup.c74
-rw-r--r--arch/powerpc/platforms/pseries/xics.c17
140 files changed, 3870 insertions, 2232 deletions
diff --git a/arch/powerpc/platforms/4xx/Kconfig b/arch/powerpc/platforms/4xx/Kconfig
index 2f2a13ed7667..ded357c17414 100644
--- a/arch/powerpc/platforms/4xx/Kconfig
+++ b/arch/powerpc/platforms/4xx/Kconfig
@@ -3,278 +3,206 @@ config 4xx
depends on 40x || 44x
default y
-config WANT_EARLY_SERIAL
+config BOOKE
bool
- select SERIAL_8250
- default n
-
-menu "AMCC 4xx options"
- depends on 4xx
-
-choice
- prompt "Machine Type"
- depends on 40x
- default WALNUT
-
-config BUBINGA
- bool "Bubinga"
- select WANT_EARLY_SERIAL
- help
- This option enables support for the IBM 405EP evaluation board.
-
-config CPCI405
- bool "CPCI405"
- help
- This option enables support for the CPCI405 board.
-
-config EP405
- bool "EP405/EP405PC"
- help
- This option enables support for the EP405/EP405PC boards.
-
-config REDWOOD_5
- bool "Redwood-5"
- help
- This option enables support for the IBM STB04 evaluation board.
-
-config REDWOOD_6
- bool "Redwood-6"
- help
- This option enables support for the IBM STBx25xx evaluation board.
-
-config SYCAMORE
- bool "Sycamore"
- help
- This option enables support for the IBM PPC405GPr evaluation board.
-
-config WALNUT
- bool "Walnut"
- help
- This option enables support for the IBM PPC405GP evaluation board.
-
-config XILINX_ML300
- bool "Xilinx-ML300"
- help
- This option enables support for the Xilinx ML300 evaluation board.
-
-endchoice
-
-choice
- prompt "Machine Type"
depends on 44x
- default EBONY
-
-config BAMBOO
- bool "Bamboo"
- select WANT_EARLY_SERIAL
- help
- This option enables support for the IBM PPC440EP evaluation board.
-
-config EBONY
- bool "Ebony"
- select WANT_EARLY_SERIAL
- help
- This option enables support for the IBM PPC440GP evaluation board.
-
-config LUAN
- bool "Luan"
- select WANT_EARLY_SERIAL
- help
- This option enables support for the IBM PPC440SP evaluation board.
-
-config OCOTEA
- bool "Ocotea"
- select WANT_EARLY_SERIAL
- help
- This option enables support for the IBM PPC440GX evaluation board.
+ default y
-endchoice
+menu "AMCC 40x options"
+ depends on 40x
-config EP405PC
- bool "EP405PC Support"
- depends on EP405
+#config BUBINGA
+# bool "Bubinga"
+# depends on 40x
+# default n
+# select 405EP
+# help
+# This option enables support for the IBM 405EP evaluation board.
+
+#config CPCI405
+# bool "CPCI405"
+# depends on 40x
+# default n
+# select 405GP
+# help
+# This option enables support for the CPCI405 board.
+
+#config EP405
+# bool "EP405/EP405PC"
+# depends on 40x
+# default n
+# select 405GP
+# help
+# This option enables support for the EP405/EP405PC boards.
+
+#config EP405PC
+# bool "EP405PC Support"
+# depends on EP405
+# default y
+# help
+# This option enables support for the extra features of the EP405PC board.
+
+#config REDWOOD_5
+# bool "Redwood-5"
+# depends on 40x
+# default n
+# select STB03xxx
+# help
+# This option enables support for the IBM STB04 evaluation board.
+
+#config REDWOOD_6
+# bool "Redwood-6"
+# depends on 40x
+# default n
+# select STB03xxx
+# help
+# This option enables support for the IBM STBx25xx evaluation board.
+
+#config SYCAMORE
+# bool "Sycamore"
+# depends on 40x
+# default n
+# select 405GPR
+# help
+# This option enables support for the IBM PPC405GPr evaluation board.
+
+#config WALNUT
+# bool "Walnut"
+# depends on 40x
+# default y
+# select 405GP
+# help
+# This option enables support for the IBM PPC405GP evaluation board.
+
+#config XILINX_ML300
+# bool "Xilinx-ML300"
+# depends on 40x
+# default y
+# select VIRTEX_II_PRO
+# help
+# This option enables support for the Xilinx ML300 evaluation board.
+endmenu
-# It's often necessary to know the specific 4xx processor type.
-# Fortunately, it is impled (so far) from the board type, so we
-# don't need to ask more redundant questions.
+# 40x specific CPU modules, selected based on the board above.
config NP405H
bool
- depends on ASH
- default y
+ #depends on ASH
-config 440EP
+# OAK doesn't exist but wanted to keep this around for any future 403GCX boards
+config 403GCX
bool
- depends on BAMBOO
- select PPC_FPU
- default y
+ #depends on OAK
+ select IBM405_ERR51
-config 440GP
+config 405GP
bool
- depends on EBONY
- default y
+ select IBM405_ERR77
+ select IBM405_ERR51
-config 440GX
+config 405EP
bool
- depends on OCOTEA
- default y
-config 440SP
+config 405GPR
bool
- depends on LUAN
- default y
-config 440
+config VIRTEX_II_PRO
bool
- depends on 440GP || 440SP || 440EP
- default y
+ select IBM405_ERR77
+ select IBM405_ERR51
-config 440A
+config STB03xxx
bool
- depends on 440GX
- default y
+ select IBM405_ERR77
+ select IBM405_ERR51
-config IBM440EP_ERR42
- bool
- depends on 440EP
- default y
+# 40x errata/workaround config symbols, selected by the CPU models above
# All 405-based cores up until the 405GPR and 405EP have this errata.
config IBM405_ERR77
bool
- depends on 40x && !403GCX && !405GPR && !405EP
- default y
# All 40x-based cores, up until the 405GPR and 405EP have this errata.
config IBM405_ERR51
bool
- depends on 40x && !405GPR && !405EP
- default y
-config BOOKE
- bool
+menu "AMCC 44x options"
depends on 44x
- default y
-
-config IBM_OCP
- bool
- depends on ASH || BAMBOO || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT
- default y
-config XILINX_OCP
- bool
- depends on XILINX_ML300
- default y
+#config BAMBOO
+# bool "Bamboo"
+# depends on 44x
+# default n
+# select 440EP
+# help
+# This option enables support for the IBM PPC440EP evaluation board.
-config IBM_EMAC4
- bool
- depends on 440GX || 440SP
- default y
-
-config BIOS_FIXUP
- bool
- depends on BUBINGA || EP405 || SYCAMORE || WALNUT
- default y
-
-# OAK doesn't exist but wanted to keep this around for any future 403GCX boards
-config 403GCX
- bool
- depends on OAK
- default y
-
-config 405EP
- bool
- depends on BUBINGA
- default y
-
-config 405GP
- bool
- depends on CPCI405 || EP405 || WALNUT
- default y
-
-config 405GPR
- bool
- depends on SYCAMORE
+config EBONY
+ bool "Ebony"
+ depends on 44x
default y
+ select 440GP
+ help
+ This option enables support for the IBM PPC440GP evaluation board.
-config VIRTEX_II_PRO
- bool
- depends on XILINX_ML300
- default y
+#config LUAN
+# bool "Luan"
+# depends on 44x
+# default n
+# select 440SP
+# help
+# This option enables support for the IBM PPC440SP evaluation board.
+
+#config OCOTEA
+# bool "Ocotea"
+# depends on 44x
+# default n
+# select 440GX
+# help
+# This option enables support for the IBM PPC440GX evaluation board.
-config STB03xxx
- bool
- depends on REDWOOD_5 || REDWOOD_6
- default y
+endmenu
-config EMBEDDEDBOOT
+# 44x specific CPU modules, selected based on the board above.
+config 440EP
bool
- depends on EP405 || XILINX_ML300
- default y
+ select PPC_FPU
+ select IBM440EP_ERR42
-config IBM_OPENBIOS
+config 440GP
bool
- depends on ASH || BUBINGA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT
- default y
+ select IBM_NEW_EMAC_ZMII
-config PPC4xx_DMA
- bool "PPC4xx DMA controller support"
- depends on 4xx
-
-config PPC4xx_EDMA
+config 440GX
bool
- depends on !STB03xxx && PPC4xx_DMA
- default y
-config PPC_GEN550
+config 440SP
bool
- depends on 4xx
- default y
-
-choice
- prompt "TTYS0 device and default console"
- depends on 40x
- default UART0_TTYS0
-
-config UART0_TTYS0
- bool "UART0"
-config UART0_TTYS1
- bool "UART1"
-
-endchoice
-
-config SERIAL_SICC
- bool "SICC Serial port support"
- depends on STB03xxx
-
-config UART1_DFLT_CONSOLE
+config 440A
bool
- depends on SERIAL_SICC && UART0_TTYS1
+ depends on 440GX
default y
-config SERIAL_SICC_CONSOLE
+# 44x errata/workaround config symbols, selected by the CPU models above
+config IBM440EP_ERR42
bool
- depends on SERIAL_SICC && UART0_TTYS1
- default y
-endmenu
+#config XILINX_OCP
+# bool
+# depends on XILINX_ML300
+# default y
-menu "IBM 40x options"
- depends on 40x
-
-config SERIAL_SICC
- bool "SICC Serial port"
- depends on STB03xxx
-
-config UART1_DFLT_CONSOLE
- bool
- depends on SERIAL_SICC && UART0_TTYS1
- default y
+#config BIOS_FIXUP
+# bool
+# depends on BUBINGA || EP405 || SYCAMORE || WALNUT
+# default y
-config SERIAL_SICC_CONSOLE
- bool
- depends on SERIAL_SICC && UART0_TTYS1
- default y
+#config PPC4xx_DMA
+# bool "PPC4xx DMA controller support"
+# depends on 4xx
-endmenu
+#config PPC4xx_EDMA
+# bool
+# depends on !STB03xxx && PPC4xx_DMA
+# default y
diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig
new file mode 100644
index 000000000000..bc4aa4a80a12
--- /dev/null
+++ b/arch/powerpc/platforms/52xx/Kconfig
@@ -0,0 +1,35 @@
+config PPC_MPC52xx
+ bool
+ default n
+
+config PPC_MPC5200
+ bool
+ select PPC_MPC52xx
+ default n
+
+config PPC_MPC5200_BUGFIX
+ bool "MPC5200 (L25R) bugfix support"
+ depends on PPC_MPC5200
+ default n
+ help
+ Enable workarounds for original MPC5200 errata. This is not required
+ for MPC5200B based boards.
+
+ It is safe to say 'Y' here
+
+config PPC_EFIKA
+ bool "bPlan Efika 5k2. MPC5200B based computer"
+ depends on PPC_MULTIPLATFORM && PPC32
+ select PPC_RTAS
+ select RTAS_PROC
+ select PPC_MPC52xx
+ select PPC_NATIVE
+ default n
+
+config PPC_LITE5200
+ bool "Freescale Lite5200 Eval Board"
+ depends on PPC_MULTIPLATFORM && PPC32
+ select PPC_MPC5200
+ default n
+
+
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c
index 8de034116681..a6bba97314eb 100644
--- a/arch/powerpc/platforms/52xx/efika.c
+++ b/arch/powerpc/platforms/52xx/efika.c
@@ -112,7 +112,7 @@ void __init efika_pcisetup(void)
return;
}
- bus_range = get_property(pcictrl, "bus-range", &len);
+ bus_range = of_get_property(pcictrl, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int)) {
printk(KERN_WARNING EFIKA_PLATFORM_NAME
": Can't get bus-range for %s\n", pcictrl->full_name);
@@ -158,18 +158,17 @@ void __init efika_pcisetup(void)
static void efika_show_cpuinfo(struct seq_file *m)
{
struct device_node *root;
- const char *revision = NULL;
- const char *codegendescription = NULL;
- const char *codegenvendor = NULL;
+ const char *revision;
+ const char *codegendescription;
+ const char *codegenvendor;
root = of_find_node_by_path("/");
if (!root)
return;
- revision = get_property(root, "revision", NULL);
- codegendescription =
- get_property(root, "CODEGEN,description", NULL);
- codegenvendor = get_property(root, "CODEGEN,vendor", NULL);
+ revision = of_get_property(root, "revision", NULL);
+ codegendescription = of_get_property(root, "CODEGEN,description", NULL);
+ codegenvendor = of_get_property(root, "CODEGEN,vendor", NULL);
if (codegendescription)
seq_printf(m, "machine\t\t: %s\n", codegendescription);
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
index cc3b40de21dd..8e2646ac417b 100644
--- a/arch/powerpc/platforms/52xx/lite5200.c
+++ b/arch/powerpc/platforms/52xx/lite5200.c
@@ -94,8 +94,8 @@ static void __init lite5200_setup_arch(void)
np = of_find_node_by_type(NULL, "cpu");
if (np) {
- unsigned int *fp =
- (int *)get_property(np, "clock-frequency", NULL);
+ const unsigned int *fp =
+ of_get_property(np, "clock-frequency", NULL);
if (fp != 0)
loops_per_jiffy = *fp / HZ;
else
@@ -108,9 +108,11 @@ static void __init lite5200_setup_arch(void)
lite5200_setup_cpu(); /* Platorm specific */
#ifdef CONFIG_PCI
- np = of_find_node_by_type(np, "pci");
- if (np)
+ np = of_find_node_by_type(NULL, "pci");
+ if (np) {
mpc52xx_add_bridge(np);
+ of_node_put(np);
+ }
#endif
#ifdef CONFIG_BLK_DEV_INITRD
@@ -132,7 +134,7 @@ void lite5200_show_cpuinfo(struct seq_file *m)
const char *model = NULL;
if (np)
- model = get_property(np, "model", NULL);
+ model = of_get_property(np, "model", NULL);
seq_printf(m, "vendor\t\t: Freescale Semiconductor\n");
seq_printf(m, "machine\t\t: %s\n", model ? model : "unknown");
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c
index ed0cb694aea8..2dd415ff55a9 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_common.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c
@@ -60,7 +60,7 @@ mpc52xx_find_ipb_freq(struct device_node *node)
of_node_get(node);
while (node) {
- p_ipb_freq = get_property(node, "bus-frequency", NULL);
+ p_ipb_freq = of_get_property(node, "bus-frequency", NULL);
if (p_ipb_freq)
break;
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
index faf161bdbc1c..34d34a26d305 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
@@ -370,7 +370,7 @@ mpc52xx_add_bridge(struct device_node *node)
return -EINVAL;
}
- bus_range = get_property(node, "bus-range", &len);
+ bus_range = of_get_property(node, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int)) {
printk(KERN_WARNING "Can't get %s bus-range, assume bus 0\n",
node->full_name);
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
index c75192567e55..fbfff95b4437 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
@@ -128,7 +128,7 @@ static void mpc52xx_main_mask(unsigned int virq)
pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
- io_be_setbit(&intr->main_mask, 15 - l2irq);
+ io_be_setbit(&intr->main_mask, 16 - l2irq);
}
static void mpc52xx_main_unmask(unsigned int virq)
@@ -141,7 +141,7 @@ static void mpc52xx_main_unmask(unsigned int virq)
pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
- io_be_clrbit(&intr->main_mask, 15 - l2irq);
+ io_be_clrbit(&intr->main_mask, 16 - l2irq);
}
static struct irq_chip mpc52xx_main_irqchip = {
diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig
index 47d841ecf2e2..de7fce9cb6eb 100644
--- a/arch/powerpc/platforms/82xx/Kconfig
+++ b/arch/powerpc/platforms/82xx/Kconfig
@@ -1,21 +1,36 @@
-menu "Platform support"
- depends on PPC_82xx
-
choice
- prompt "Machine Type"
- default MPC82xx_ADS
+ prompt "Machine Type"
+ depends on PPC_82xx
+ default MPC82xx_ADS
config MPC82xx_ADS
- bool "Freescale MPC82xx ADS"
- select DEFAULT_UIMAGE
- select PQ2ADS
- select 8272
- select 8260
- select CPM2
- select FSL_SOC
- help
- This option enables support for the MPC8272 ADS board
+ bool "Freescale MPC82xx ADS"
+ select DEFAULT_UIMAGE
+ select PQ2ADS
+ select 8272
+ select 8260
+ select FSL_SOC
+ help
+ This option enables support for the MPC8272 ADS board
endchoice
-endmenu
+config PQ2ADS
+ bool
+ default n
+
+config 8260
+ bool
+ depends on 6xx
+ select CPM2
+ help
+ The MPC8260 is a typical embedded CPU made by Freescale. Selecting
+ this option means that you wish to build a kernel for a machine with
+ an 8260 class CPU.
+
+config 8272
+ bool
+ select 8260
+ help
+ The MPC8272 CPM has a different internal dpram setup than other CPM2
+ devices
diff --git a/arch/powerpc/platforms/82xx/mpc82xx.c b/arch/powerpc/platforms/82xx/mpc82xx.c
index 74e7892cdfcf..cc9900d2e5ee 100644
--- a/arch/powerpc/platforms/82xx/mpc82xx.c
+++ b/arch/powerpc/platforms/82xx/mpc82xx.c
@@ -55,17 +55,17 @@
static int __init get_freq(char *name, unsigned long *val)
{
struct device_node *cpu;
- unsigned int *fp;
+ const unsigned int *fp;
int found = 0;
/* The cpu node should have timebase and clock frequency properties */
cpu = of_find_node_by_type(NULL, "cpu");
if (cpu) {
- fp = (unsigned int *)get_property(cpu, name, NULL);
+ fp = of_get_property(cpu, name, NULL);
if (fp) {
found = 1;
- *val = *fp++;
+ *val = *fp;
}
of_node_put(cpu);
diff --git a/arch/powerpc/platforms/82xx/mpc82xx_ads.c b/arch/powerpc/platforms/82xx/mpc82xx_ads.c
index 7334c1a15b90..47cb09f08052 100644
--- a/arch/powerpc/platforms/82xx/mpc82xx_ads.c
+++ b/arch/powerpc/platforms/82xx/mpc82xx_ads.c
@@ -456,7 +456,7 @@ void m82xx_pci_init_irq(void)
iounmap(immap);
return;
}
- irq_map = get_property(np, "interrupt-map", &size);
+ irq_map = of_get_property(np, "interrupt-map", &size);
if ((!irq_map) || (size <= 7)) {
printk(KERN_INFO "No interrupt-map property of pci node\n");
iounmap(immap);
@@ -481,7 +481,7 @@ void m82xx_pci_init_irq(void)
}
pci_pic_node = of_node_get(np);
/* PCI interrupt controller registers: status and mask */
- regs = get_property(np, "reg", &size);
+ regs = of_get_property(np, "reg", &size);
if ((!regs) || (size <= 2)) {
printk(KERN_INFO "No reg property in pci pic node\n");
iounmap(immap);
@@ -521,20 +521,20 @@ void __init add_bridge(struct device_node *np)
struct pci_controller *hose;
struct resource r;
const int *bus_range;
- const void *ptr;
+ const uint *ptr;
memset(&r, 0, sizeof(r));
if (of_address_to_resource(np, 0, &r)) {
printk(KERN_INFO "No PCI reg property in device tree\n");
return;
}
- if (!(ptr = get_property(np, "clock-frequency", NULL))) {
+ if (!(ptr = of_get_property(np, "clock-frequency", NULL))) {
printk(KERN_INFO "No clock-frequency property in PCI node");
return;
}
- pci_clk_frq = *(uint *) ptr;
+ pci_clk_frq = *ptr;
of_node_put(np);
- bus_range = get_property(np, "bus-range", &len);
+ bus_range = of_get_property(np, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int)) {
printk(KERN_WARNING "Can't get bus-range for %s, assume"
" bus 0\n", np->full_name);
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 1aea1e69ff31..19cafdf6df93 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -1,8 +1,6 @@
-menu "Platform support"
- depends on PPC_83xx
-
choice
prompt "Machine Type"
+ depends on PPC_83xx
default MPC834x_MDS
config MPC8313_RDB
@@ -18,6 +16,13 @@ config MPC832x_MDS
help
This option enables support for the MPC832x MDS evaluation board.
+config MPC832x_RDB
+ bool "Freescale MPC832x RDB"
+ select DEFAULT_UIMAGE
+ select QUICC_ENGINE
+ help
+ This option enables support for the MPC8323 RDB board.
+
config MPC834x_MDS
bool "Freescale MPC834x MDS"
select DEFAULT_UIMAGE
@@ -38,12 +43,12 @@ config MPC834x_ITX
Be aware that PCI initialization is the bootloader's
responsibility.
-config MPC8360E_PB
- bool "Freescale MPC8360E PB"
+config MPC836x_MDS
+ bool "Freescale MPC836x MDS"
select DEFAULT_UIMAGE
select QUICC_ENGINE
help
- This option enables support for the MPC836x EMDS Processor Board.
+ This option enables support for the MPC836x MDS Processor Board.
endchoice
@@ -57,7 +62,7 @@ config PPC_MPC832x
bool
select PPC_UDBG_16550
select PPC_INDIRECT_PCI
- default y if MPC832x_MDS
+ default y if MPC832x_MDS || MPC832x_RDB
config MPC834x
bool
@@ -69,6 +74,4 @@ config PPC_MPC836x
bool
select PPC_UDBG_16550
select PPC_INDIRECT_PCI
- default y if MPC8360E_PB
-
-endmenu
+ default y if MPC836x_MDS
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile
index 6c8199c4c382..31a91b53f528 100644
--- a/arch/powerpc/platforms/83xx/Makefile
+++ b/arch/powerpc/platforms/83xx/Makefile
@@ -4,7 +4,8 @@
obj-y := misc.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_MPC8313_RDB) += mpc8313_rdb.o
+obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o
obj-$(CONFIG_MPC834x_MDS) += mpc834x_mds.o
obj-$(CONFIG_MPC834x_ITX) += mpc834x_itx.o
-obj-$(CONFIG_MPC8360E_PB) += mpc8360e_pb.o
+obj-$(CONFIG_MPC836x_MDS) += mpc836x_mds.o
obj-$(CONFIG_MPC832x_MDS) += mpc832x_mds.o
diff --git a/arch/powerpc/platforms/83xx/mpc8313_rdb.c b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
index c3b98c34eb6b..32e9e9492841 100644
--- a/arch/powerpc/platforms/83xx/mpc8313_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
@@ -74,16 +74,9 @@ void __init mpc8313_rdb_init_IRQ(void)
*/
static int __init mpc8313_rdb_probe(void)
{
- char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
- "model", NULL);
- if (model == NULL)
- return 0;
- if (strcmp(model, "MPC8313ERDB"))
- return 0;
+ unsigned long root = of_get_flat_dt_root();
- DBG("MPC8313 RDB found\n");
-
- return 1;
+ return of_flat_dt_is_compatible(root, "MPC8313ERDB");
}
define_machine(mpc8313_rdb) {
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index 3ecb55f8a6e2..fff09f5d6edf 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -41,7 +41,6 @@
#include <asm/qe_ic.h>
#include "mpc83xx.h"
-#include "mpc832x_mds.h"
#undef DEBUG
#ifdef DEBUG
@@ -57,11 +56,6 @@ unsigned long isa_mem_base = 0;
static u8 *bcsr_regs = NULL;
-u8 *get_bcsr(void)
-{
- return bcsr_regs;
-}
-
/* ************************************************************************
*
* Setup the architecture
@@ -74,17 +68,6 @@ static void __init mpc832x_sys_setup_arch(void)
if (ppc_md.progress)
ppc_md.progress("mpc832x_sys_setup_arch()", 0);
- np = of_find_node_by_type(NULL, "cpu");
- if (np != 0) {
- unsigned int *fp =
- (int *)get_property(np, "clock-frequency", NULL);
- if (fp != 0)
- loops_per_jiffy = *fp / HZ;
- else
- loops_per_jiffy = 50000000 / HZ;
- of_node_put(np);
- }
-
/* Map BCSR area */
np = of_find_node_by_name(NULL, "bcsr");
if (np != 0) {
@@ -121,34 +104,23 @@ static void __init mpc832x_sys_setup_arch(void)
iounmap(bcsr_regs);
of_node_put(np);
}
-
#endif /* CONFIG_QUICC_ENGINE */
-
-#ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_start)
- ROOT_DEV = Root_RAM0;
- else
-#endif
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_HDA1;
-#endif
}
+static struct of_device_id mpc832x_ids[] = {
+ { .type = "soc", },
+ { .compatible = "soc", },
+ { .type = "qe", },
+ {},
+};
+
static int __init mpc832x_declare_of_platform_devices(void)
{
- struct device_node *np;
-
- for (np = NULL; (np = of_find_compatible_node(np, "network",
- "ucc_geth")) != NULL;) {
- int ucc_num;
- char bus_id[BUS_ID_SIZE];
+ if (!machine_is(mpc832x_mds))
+ return 0;
- ucc_num = *((uint *) get_property(np, "device-id", NULL)) - 1;
- snprintf(bus_id, BUS_ID_SIZE, "ucc_geth.%u", ucc_num);
- of_platform_device_create(np, bus_id, NULL);
- }
+ /* Publish the QE devices */
+ of_platform_bus_probe(NULL, mpc832x_ids, NULL);
return 0;
}
@@ -156,7 +128,6 @@ device_initcall(mpc832x_declare_of_platform_devices);
static void __init mpc832x_sys_init_IRQ(void)
{
-
struct device_node *np;
np = of_find_node_by_type(NULL, "ipic");
@@ -189,6 +160,9 @@ static int __init mpc832x_rtc_hookup(void)
{
struct timespec tv;
+ if (!machine_is(mpc832x_mds))
+ return 0;
+
ppc_md.get_rtc_time = ds1374_get_rtc_time;
ppc_md.set_rtc_time = ds1374_set_rtc_time;
@@ -207,17 +181,9 @@ late_initcall(mpc832x_rtc_hookup);
*/
static int __init mpc832x_sys_probe(void)
{
- char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
- "model", NULL);
-
- if (model == NULL)
- return 0;
- if (strcmp(model, "MPC8323EMDS"))
- return 0;
-
- DBG("%s found\n", model);
+ unsigned long root = of_get_flat_dt_root();
- return 1;
+ return of_flat_dt_is_compatible(root, "MPC832xMDS");
}
define_machine(mpc832x_mds) {
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.h b/arch/powerpc/platforms/83xx/mpc832x_mds.h
deleted file mode 100644
index a49588904f8a..000000000000
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
- *
- * Description:
- * MPC832x MDS board specific header.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-
-#ifndef __MACH_MPC832x_MDS_H__
-#define __MACH_MPC832x_MDS_H__
-
-extern u8 *get_bcsr(void);
-
-#endif /* __MACH_MPC832x_MDS_H__ */
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
new file mode 100644
index 000000000000..6b71e9ffb11a
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
@@ -0,0 +1,138 @@
+/*
+ * arch/powerpc/platforms/83xx/mpc832x_rdb.c
+ *
+ * Copyright (C) Freescale Semiconductor, Inc. 2007. All rights reserved.
+ *
+ * Description:
+ * MPC832x RDB board specific routines.
+ * This file is based on mpc832x_mds.c and mpc8313_rdb.c
+ * Author: Michael Barkowski <michael.barkowski@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/pci.h>
+
+#include <asm/of_platform.h>
+#include <asm/time.h>
+#include <asm/ipic.h>
+#include <asm/udbg.h>
+#include <asm/qe.h>
+#include <asm/qe_ic.h>
+
+#include "mpc83xx.h"
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init mpc832x_rdb_setup_arch(void)
+{
+ struct device_node *np;
+
+ if (ppc_md.progress)
+ ppc_md.progress("mpc832x_rdb_setup_arch()", 0);
+
+#ifdef CONFIG_PCI
+ for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
+ add_bridge(np);
+
+ ppc_md.pci_exclude_device = mpc83xx_exclude_device;
+#endif
+
+#ifdef CONFIG_QUICC_ENGINE
+ qe_reset();
+
+ if ((np = of_find_node_by_name(np, "par_io")) != NULL) {
+ par_io_init(np);
+ of_node_put(np);
+
+ for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;)
+ par_io_of_config(np);
+ }
+#endif /* CONFIG_QUICC_ENGINE */
+}
+
+static struct of_device_id mpc832x_ids[] = {
+ { .type = "soc", },
+ { .compatible = "soc", },
+ { .type = "qe", },
+ {},
+};
+
+static int __init mpc832x_declare_of_platform_devices(void)
+{
+ if (!machine_is(mpc832x_rdb))
+ return 0;
+
+ /* Publish the QE devices */
+ of_platform_bus_probe(NULL, mpc832x_ids, NULL);
+
+ return 0;
+}
+device_initcall(mpc832x_declare_of_platform_devices);
+
+void __init mpc832x_rdb_init_IRQ(void)
+{
+
+ struct device_node *np;
+
+ np = of_find_node_by_type(NULL, "ipic");
+ if (!np)
+ return;
+
+ ipic_init(np, 0);
+
+ /* Initialize the default interrupt mapping priorities,
+ * in case the boot rom changed something on us.
+ */
+ ipic_set_default_priority();
+ of_node_put(np);
+
+#ifdef CONFIG_QUICC_ENGINE
+ np = of_find_node_by_type(NULL, "qeic");
+ if (!np)
+ return;
+
+ qe_ic_init(np, 0);
+ of_node_put(np);
+#endif /* CONFIG_QUICC_ENGINE */
+}
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init mpc832x_rdb_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ return of_flat_dt_is_compatible(root, "MPC832xRDB");
+}
+
+define_machine(mpc832x_rdb) {
+ .name = "MPC832x RDB",
+ .probe = mpc832x_rdb_probe,
+ .setup_arch = mpc832x_rdb_setup_arch,
+ .init_IRQ = mpc832x_rdb_init_IRQ,
+ .get_irq = ipic_get_irq,
+ .restart = mpc83xx_restart,
+ .time_init = mpc83xx_time_init,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+};
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index 443a3172f370..3c009f6d4a4f 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -55,28 +55,12 @@ static void __init mpc834x_itx_setup_arch(void)
if (ppc_md.progress)
ppc_md.progress("mpc834x_itx_setup_arch()", 0);
- np = of_find_node_by_type(NULL, "cpu");
- if (np != 0) {
- const unsigned int *fp =
- get_property(np, "clock-frequency", NULL);
- if (fp != 0)
- loops_per_jiffy = *fp / HZ;
- else
- loops_per_jiffy = 50000000 / HZ;
- of_node_put(np);
- }
#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
add_bridge(np);
ppc_md.pci_exclude_device = mpc83xx_exclude_device;
#endif
-
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_HDA1;
-#endif
}
static void __init mpc834x_itx_init_IRQ(void)
@@ -100,10 +84,9 @@ static void __init mpc834x_itx_init_IRQ(void)
*/
static int __init mpc834x_itx_probe(void)
{
- /* We always match for now, eventually we should look at the flat
- dev tree to ensure this is the board we are suppose to run on
- */
- return 1;
+ unsigned long root = of_get_flat_dt_root();
+
+ return of_flat_dt_is_compatible(root, "MPC834xMITX");
}
define_machine(mpc834x_itx) {
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.h b/arch/powerpc/platforms/83xx/mpc834x_itx.h
deleted file mode 100644
index 174ca4ef55f3..000000000000
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * arch/powerpc/platforms/83xx/mpc834x_itx.h
- *
- * MPC834X ITX common board definitions
- *
- * Maintainer: Kumar Gala <galak@kernel.crashing.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-
-#ifndef __MACH_MPC83XX_ITX_H__
-#define __MACH_MPC83XX_ITX_H__
-
-#define PIRQA MPC83xx_IRQ_EXT4
-#define PIRQB MPC83xx_IRQ_EXT5
-#define PIRQC MPC83xx_IRQ_EXT6
-#define PIRQD MPC83xx_IRQ_EXT7
-
-#endif /* __MACH_MPC83XX_ITX_H__ */
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c
index d2736da76c46..8aa9a93e2aa2 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c
@@ -55,9 +55,9 @@ static int mpc834x_usb_cfg(void)
struct device_node *np = NULL;
int port0_is_dr = 0;
- if ((np = of_find_compatible_node(np, "usb", "fsl-usb2-dr")) != NULL)
+ if ((np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr")) != NULL)
port0_is_dr = 1;
- if ((np = of_find_compatible_node(np, "usb", "fsl-usb2-mph")) != NULL){
+ if ((np = of_find_compatible_node(NULL, "usb", "fsl-usb2-mph")) != NULL){
if (port0_is_dr) {
printk(KERN_WARNING
"There is only one USB port on PB board! \n");
@@ -103,8 +103,8 @@ static int mpc834x_usb_cfg(void)
return -1;
/*
- * if MDS board is plug into PIB board,
- * force to use the PHY on MDS board
+ * if Processor Board is plugged into PIB board,
+ * force to use the PHY on Processor Board
*/
bcsr5 = in_8(bcsr_regs + 5);
if (!(bcsr5 & BCSR5_INT_USB))
@@ -125,17 +125,6 @@ static void __init mpc834x_mds_setup_arch(void)
if (ppc_md.progress)
ppc_md.progress("mpc834x_mds_setup_arch()", 0);
- np = of_find_node_by_type(NULL, "cpu");
- if (np != 0) {
- const unsigned int *fp =
- get_property(np, "clock-frequency", NULL);
- if (fp != 0)
- loops_per_jiffy = *fp / HZ;
- else
- loops_per_jiffy = 50000000 / HZ;
- of_node_put(np);
- }
-
#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
add_bridge(np);
@@ -144,12 +133,6 @@ static void __init mpc834x_mds_setup_arch(void)
#endif
mpc834x_usb_cfg();
-
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_HDA1;
-#endif
}
static void __init mpc834x_mds_init_IRQ(void)
@@ -176,6 +159,9 @@ static int __init mpc834x_rtc_hookup(void)
{
struct timespec tv;
+ if (!machine_is(mpc834x_mds))
+ return 0;
+
ppc_md.get_rtc_time = ds1374_get_rtc_time;
ppc_md.set_rtc_time = ds1374_set_rtc_time;
@@ -194,10 +180,9 @@ late_initcall(mpc834x_rtc_hookup);
*/
static int __init mpc834x_mds_probe(void)
{
- /* We always match for now, eventually we should look at the flat
- dev tree to ensure this is the board we are suppose to run on
- */
- return 1;
+ unsigned long root = of_get_flat_dt_root();
+
+ return of_flat_dt_is_compatible(root, "MPC834xMDS");
}
define_machine(mpc834x_mds) {
diff --git a/arch/powerpc/platforms/83xx/mpc8360e_pb.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c
index ccce2f9f283d..526ed090a446 100644
--- a/arch/powerpc/platforms/83xx/mpc8360e_pb.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c
@@ -5,12 +5,12 @@
* Yin Olivia <Hong-hua.Yin@freescale.com>
*
* Description:
- * MPC8360E MDS PB board specific routines.
+ * MPC8360E MDS board specific routines.
*
* Changelog:
* Jun 21, 2006 Initial version
*
- * This program is free software; you can redistribute it and/or modify it
+ * This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
@@ -62,33 +62,17 @@ unsigned long isa_mem_base = 0;
static u8 *bcsr_regs = NULL;
-u8 *get_bcsr(void)
-{
- return bcsr_regs;
-}
-
/* ************************************************************************
*
* Setup the architecture
*
*/
-static void __init mpc8360_sys_setup_arch(void)
+static void __init mpc836x_mds_setup_arch(void)
{
struct device_node *np;
if (ppc_md.progress)
- ppc_md.progress("mpc8360_sys_setup_arch()", 0);
-
- np = of_find_node_by_type(NULL, "cpu");
- if (np != 0) {
- const unsigned int *fp =
- get_property(np, "clock-frequency", NULL);
- if (fp != 0)
- loops_per_jiffy = *fp / HZ;
- else
- loops_per_jiffy = 50000000 / HZ;
- of_node_put(np);
- }
+ ppc_md.progress("mpc836x_mds_setup_arch()", 0);
/* Map BCSR area */
np = of_find_node_by_name(NULL, "bcsr");
@@ -128,40 +112,29 @@ static void __init mpc8360_sys_setup_arch(void)
}
#endif /* CONFIG_QUICC_ENGINE */
-
-#ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_start)
- ROOT_DEV = Root_RAM0;
- else
-#endif
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_HDA1;
-#endif
}
-static int __init mpc8360_declare_of_platform_devices(void)
-{
- struct device_node *np;
+static struct of_device_id mpc836x_ids[] = {
+ { .type = "soc", },
+ { .compatible = "soc", },
+ { .type = "qe", },
+ {},
+};
- for (np = NULL; (np = of_find_compatible_node(np, "network",
- "ucc_geth")) != NULL;) {
- int ucc_num;
- char bus_id[BUS_ID_SIZE];
+static int __init mpc836x_declare_of_platform_devices(void)
+{
+ if (!machine_is(mpc836x_mds))
+ return 0;
- ucc_num = *((uint *) get_property(np, "device-id", NULL)) - 1;
- snprintf(bus_id, BUS_ID_SIZE, "ucc_geth.%u", ucc_num);
- of_platform_device_create(np, bus_id, NULL);
- }
+ /* Publish the QE devices */
+ of_platform_bus_probe(NULL, mpc836x_ids, NULL);
return 0;
}
-device_initcall(mpc8360_declare_of_platform_devices);
+device_initcall(mpc836x_declare_of_platform_devices);
-static void __init mpc8360_sys_init_IRQ(void)
+static void __init mpc836x_mds_init_IRQ(void)
{
-
struct device_node *np;
np = of_find_node_by_type(NULL, "ipic");
@@ -194,6 +167,9 @@ static int __init mpc8360_rtc_hookup(void)
{
struct timespec tv;
+ if (!machine_is(mpc836x_mds))
+ return 0;
+
ppc_md.get_rtc_time = ds1374_get_rtc_time;
ppc_md.set_rtc_time = ds1374_set_rtc_time;
@@ -210,28 +186,21 @@ late_initcall(mpc8360_rtc_hookup);
/*
* Called very early, MMU is off, device-tree isn't unflattened
*/
-static int __init mpc8360_sys_probe(void)
+static int __init mpc836x_mds_probe(void)
{
- char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
- "model", NULL);
- if (model == NULL)
- return 0;
- if (strcmp(model, "MPC8360EPB"))
- return 0;
-
- DBG("MPC8360EMDS-PB found\n");
+ unsigned long root = of_get_flat_dt_root();
- return 1;
+ return of_flat_dt_is_compatible(root, "MPC836xMDS");
}
-define_machine(mpc8360_sys) {
- .name = "MPC8360E PB",
- .probe = mpc8360_sys_probe,
- .setup_arch = mpc8360_sys_setup_arch,
- .init_IRQ = mpc8360_sys_init_IRQ,
- .get_irq = ipic_get_irq,
- .restart = mpc83xx_restart,
- .time_init = mpc83xx_time_init,
+define_machine(mpc836x_mds) {
+ .name = "MPC836x MDS",
+ .probe = mpc836x_mds_probe,
+ .setup_arch = mpc836x_mds_setup_arch,
+ .init_IRQ = mpc836x_mds_init_IRQ,
+ .get_irq = ipic_get_irq,
+ .restart = mpc83xx_restart,
+ .time_init = mpc83xx_time_init,
.calibrate_decr = generic_calibrate_decr,
- .progress = udbg_progress,
+ .progress = udbg_progress,
};
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c
index 9c3650555144..774457d09e94 100644
--- a/arch/powerpc/platforms/83xx/pci.c
+++ b/arch/powerpc/platforms/83xx/pci.c
@@ -60,7 +60,7 @@ int __init add_bridge(struct device_node *dev)
has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
/* Get bus range if any */
- bus_range = get_property(dev, "bus-range", &len);
+ bus_range = of_get_property(dev, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int)) {
printk(KERN_WARNING "Can't get bus-range for %s, assume"
" bus 0\n", dev->full_name);
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index 0efdd2f1babe..629926e01e90 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -1,8 +1,6 @@
-menu "Platform support"
- depends on PPC_85xx
-
choice
prompt "Machine Type"
+ depends on PPC_85xx
default MPC8540_ADS
config MPC8540_ADS
@@ -23,12 +21,18 @@ config MPC85xx_CDS
help
This option enables support for the MPC85xx CDS board
-config MPC8568_MDS
- bool "Freescale MPC8568 MDS"
+config MPC85xx_MDS
+ bool "Freescale MPC85xx MDS"
select DEFAULT_UIMAGE
# select QUICC_ENGINE
help
- This option enables support for the MPC8568 MDS board
+ This option enables support for the MPC85xx MDS board
+
+config MPC8544_DS
+ bool "Freescale MPC8544 DS"
+ select DEFAULT_UIMAGE
+ help
+ This option enables support for the MPC8544 DS board
endchoice
@@ -40,32 +44,15 @@ config MPC8540
config MPC8560
bool
- select PPC_INDIRECT_PCI
+ select CPM2
default y if MPC8560_ADS
config MPC85xx
bool
select PPC_UDBG_16550
select PPC_INDIRECT_PCI
- default y if MPC8540_ADS || MPC85xx_CDS || MPC8560_ADS || MPC8568_MDS
-
-config PPC_INDIRECT_PCI_BE
- bool
- depends on PPC_85xx
- default y
-
-config MPIC
- bool
- default y
-
-config CPM2
- bool
- depends on MPC8560
- default y
- help
- The CPM2 (Communications Processor Module) is a coprocessor on
- embedded CPUs made by Motorola. Selecting this option means that
- you wish to build a kernel for a machine with a CPM2 coprocessor
- on it.
-
-endmenu
+ select PPC_INDIRECT_PCI_BE
+ select MPIC
+ select SERIAL_8250_SHARE_IRQ if SERIAL_8250
+ default y if MPC8540_ADS || MPC85xx_CDS || MPC8560_ADS \
+ || MPC85xx_MDS || MPC8544_DS
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index e40e521816b8..4e02cbb14cf7 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -5,4 +5,5 @@ obj-$(CONFIG_PPC_85xx) += misc.o pci.o
obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o
obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o
obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o
-obj-$(CONFIG_MPC8568_MDS) += mpc8568_mds.o
+obj-$(CONFIG_MPC8544_DS) += mpc8544_ds.o
+obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o
diff --git a/arch/powerpc/platforms/85xx/mpc8544_ds.c b/arch/powerpc/platforms/85xx/mpc8544_ds.c
new file mode 100644
index 000000000000..2867f85e6325
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/mpc8544_ds.c
@@ -0,0 +1,144 @@
+/*
+ * MPC8544 DS Board Setup
+ *
+ * Author Xianghua Xiao (x.xiao@freescale.com)
+ * Copyright 2007 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/mpc85xx.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+#include <asm/i8259.h>
+
+#include <sysdev/fsl_soc.h>
+#include "mpc85xx.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
+#else
+#define DBG(fmt, args...)
+#endif
+
+
+void __init mpc8544_ds_pic_init(void)
+{
+ struct mpic *mpic;
+ struct resource r;
+ struct device_node *np = NULL;
+#ifdef CONFIG_PPC_I8259
+ struct device_node *cascade_node = NULL;
+ int cascade_irq;
+#endif
+
+ np = of_find_node_by_type(np, "open-pic");
+
+ if (np == NULL) {
+ printk(KERN_ERR "Could not find open-pic node\n");
+ return;
+ }
+
+ if (of_address_to_resource(np, 0, &r)) {
+ printk(KERN_ERR "Failed to map mpic register space\n");
+ of_node_put(np);
+ return;
+ }
+
+ /* Alloc mpic structure and per isu has 16 INT entries. */
+ mpic = mpic_alloc(np, r.start,
+ MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
+ 16, 64, " OPENPIC ");
+ BUG_ON(mpic == NULL);
+
+ /*
+ * 48 Internal Interrupts
+ */
+ mpic_assign_isu(mpic, 0, r.start + 0x10200);
+ mpic_assign_isu(mpic, 1, r.start + 0x10400);
+ mpic_assign_isu(mpic, 2, r.start + 0x10600);
+
+ /*
+ * 16 External interrupts
+ */
+ mpic_assign_isu(mpic, 3, r.start + 0x10000);
+
+ mpic_init(mpic);
+
+#ifdef CONFIG_PPC_I8259
+ /* Initialize the i8259 controller */
+ for_each_node_by_type(np, "interrupt-controller")
+ if (device_is_compatible(np, "chrp,iic")) {
+ cascade_node = np;
+ break;
+ }
+
+ if (cascade_node == NULL) {
+ printk(KERN_DEBUG "Could not find i8259 PIC\n");
+ return;
+ }
+
+ cascade_irq = irq_of_parse_and_map(cascade_node, 0);
+ if (cascade_irq == NO_IRQ) {
+ printk(KERN_ERR "Failed to map cascade interrupt\n");
+ return;
+ }
+
+ DBG("mpc8544ds: cascade mapped to irq %d\n", cascade_irq);
+
+ i8259_init(cascade_node, 0);
+ of_node_put(cascade_node);
+
+ set_irq_chained_handler(cascade_irq, mpc8544_8259_cascade);
+#endif /* CONFIG_PPC_I8259 */
+}
+
+
+/*
+ * Setup the architecture
+ */
+static void __init mpc8544_ds_setup_arch(void)
+{
+ if (ppc_md.progress)
+ ppc_md.progress("mpc8544_ds_setup_arch()", 0);
+
+ printk("MPC8544 DS board from Freescale Semiconductor\n");
+}
+
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init mpc8544_ds_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ return of_flat_dt_is_compatible(root, "MPC8544DS");
+}
+
+define_machine(mpc8544_ds) {
+ .name = "MPC8544 DS",
+ .probe = mpc8544_ds_probe,
+ .setup_arch = mpc8544_ds_setup_arch,
+ .init_IRQ = mpc8544_ds_pic_init,
+ .get_irq = mpic_get_irq,
+ .restart = mpc85xx_restart,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+};
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index c56fce57621c..5d27621f0927 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -17,7 +17,6 @@
#include <linux/kdev_t.h>
#include <linux/delay.h>
#include <linux/seq_file.h>
-#include <linux/root_dev.h>
#include <asm/system.h>
#include <asm/time.h>
@@ -228,7 +227,7 @@ static void __init mpc85xx_ads_setup_arch(void)
if (cpu != 0) {
const unsigned int *fp;
- fp = get_property(cpu, "clock-frequency", NULL);
+ fp = of_get_property(cpu, "clock-frequency", NULL);
if (fp != 0)
loops_per_jiffy = *fp / HZ;
else
@@ -245,12 +244,6 @@ static void __init mpc85xx_ads_setup_arch(void)
add_bridge(np);
ppc_md.pci_exclude_device = mpc85xx_exclude_device;
#endif
-
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_HDA1;
-#endif
}
static void mpc85xx_ads_show_cpuinfo(struct seq_file *m)
@@ -279,10 +272,9 @@ static void mpc85xx_ads_show_cpuinfo(struct seq_file *m)
*/
static int __init mpc85xx_ads_probe(void)
{
- /* We always match for now, eventually we should look at the flat
- dev tree to ensure this is the board we are suppose to run on
- */
- return 1;
+ unsigned long root = of_get_flat_dt_root();
+
+ return of_flat_dt_is_compatible(root, "MPC85xxADS");
}
define_machine(mpc85xx_ads) {
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index abc0aca6de40..7e71636f9098 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -22,7 +22,6 @@
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/seq_file.h>
-#include <linux/root_dev.h>
#include <linux/initrd.h>
#include <linux/module.h>
#include <linux/fsl_devices.h>
@@ -238,7 +237,7 @@ static void __init mpc85xx_cds_setup_arch(void)
if (cpu != 0) {
const unsigned int *fp;
- fp = get_property(cpu, "clock-frequency", NULL);
+ fp = of_get_property(cpu, "clock-frequency", NULL);
if (fp != 0)
loops_per_jiffy = *fp / HZ;
else
@@ -263,12 +262,6 @@ static void __init mpc85xx_cds_setup_arch(void)
ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup;
ppc_md.pci_exclude_device = mpc85xx_exclude_device;
#endif
-
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_HDA1;
-#endif
}
static void mpc85xx_cds_show_cpuinfo(struct seq_file *m)
@@ -298,11 +291,9 @@ static void mpc85xx_cds_show_cpuinfo(struct seq_file *m)
*/
static int __init mpc85xx_cds_probe(void)
{
- /* We always match for now, eventually we should look at
- * the flat dev tree to ensure this is the board we are
- * supposed to run on
- */
- return 1;
+ unsigned long root = of_get_flat_dt_root();
+
+ return of_flat_dt_is_compatible(root, "MPC85xxCDS");
}
define_machine(mpc85xx_cds) {
diff --git a/arch/powerpc/platforms/85xx/mpc8568_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 0861d1107bc8..54db41689954 100644
--- a/arch/powerpc/platforms/85xx/mpc8568_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -8,7 +8,7 @@
* Yin Olivia <Hong-hua.Yin@freescale.com>
*
* Description:
- * MPC8568E MDS PB board specific routines.
+ * MPC85xx MDS board specific routines.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -27,7 +27,6 @@
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/seq_file.h>
-#include <linux/root_dev.h>
#include <linux/initrd.h>
#include <linux/module.h>
#include <linux/fsl_devices.h>
@@ -70,19 +69,18 @@ unsigned long isa_mem_base = 0;
* Setup the architecture
*
*/
-static void __init mpc8568_mds_setup_arch(void)
+static void __init mpc85xx_mds_setup_arch(void)
{
struct device_node *np;
static u8 *bcsr_regs = NULL;
-
if (ppc_md.progress)
- ppc_md.progress("mpc8568_mds_setup_arch()", 0);
+ ppc_md.progress("mpc85xx_mds_setup_arch()", 0);
np = of_find_node_by_type(NULL, "cpu");
if (np != NULL) {
const unsigned int *fp =
- get_property(np, "clock-frequency", NULL);
+ of_get_property(np, "clock-frequency", NULL);
if (fp != NULL)
loops_per_jiffy = *fp / HZ;
else
@@ -145,26 +143,26 @@ static void __init mpc8568_mds_setup_arch(void)
#endif /* CONFIG_QUICC_ENGINE */
}
-static struct of_device_id mpc8568_ids[] = {
+static struct of_device_id mpc85xx_ids[] = {
{ .type = "soc", },
{ .compatible = "soc", },
{ .type = "qe", },
{},
};
-static int __init mpc8568_publish_devices(void)
+static int __init mpc85xx_publish_devices(void)
{
- if (!machine_is(mpc8568_mds))
+ if (!machine_is(mpc85xx_mds))
return 0;
/* Publish the QE devices */
- of_platform_bus_probe(NULL,mpc8568_ids,NULL);
+ of_platform_bus_probe(NULL,mpc85xx_ids,NULL);
return 0;
}
-device_initcall(mpc8568_publish_devices);
+device_initcall(mpc85xx_publish_devices);
-static void __init mpc8568_mds_pic_init(void)
+static void __init mpc85xx_mds_pic_init(void)
{
struct mpic *mpic;
struct resource r;
@@ -207,7 +205,6 @@ static void __init mpc8568_mds_pic_init(void)
mpic_init(mpic);
-
#ifdef CONFIG_QUICC_ENGINE
np = of_find_node_by_type(NULL, "qeic");
if (!np)
@@ -218,27 +215,18 @@ static void __init mpc8568_mds_pic_init(void)
#endif /* CONFIG_QUICC_ENGINE */
}
-
-static int __init mpc8568_mds_probe(void)
+static int __init mpc85xx_mds_probe(void)
{
- char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
- "model", NULL);
- if (model == NULL)
- return 0;
- if (strcmp(model, "MPC8568EMDS"))
- return 0;
-
- DBG("MPC8568EMDS found\n");
+ unsigned long root = of_get_flat_dt_root();
- return 1;
+ return of_flat_dt_is_compatible(root, "MPC85xxMDS");
}
-
-define_machine(mpc8568_mds) {
- .name = "MPC8568E MDS",
- .probe = mpc8568_mds_probe,
- .setup_arch = mpc8568_mds_setup_arch,
- .init_IRQ = mpc8568_mds_pic_init,
+define_machine(mpc85xx_mds) {
+ .name = "MPC85xx MDS",
+ .probe = mpc85xx_mds_probe,
+ .setup_arch = mpc85xx_mds_setup_arch,
+ .init_IRQ = mpc85xx_mds_pic_init,
.get_irq = mpic_get_irq,
.restart = mpc85xx_restart,
.calibrate_decr = generic_calibrate_decr,
diff --git a/arch/powerpc/platforms/85xx/pci.c b/arch/powerpc/platforms/85xx/pci.c
index 05930eeb6e7f..48f17e23d771 100644
--- a/arch/powerpc/platforms/85xx/pci.c
+++ b/arch/powerpc/platforms/85xx/pci.c
@@ -51,7 +51,7 @@ int __init add_bridge(struct device_node *dev)
has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
/* Get bus range if any */
- bus_range = get_property(dev, "bus-range", &len);
+ bus_range = of_get_property(dev, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int)) {
printk(KERN_WARNING "Can't get bus-range for %s, assume"
" bus 0\n", dev->full_name);
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
index 0c70944d0e37..d1bcff500464 100644
--- a/arch/powerpc/platforms/86xx/Kconfig
+++ b/arch/powerpc/platforms/86xx/Kconfig
@@ -1,8 +1,6 @@
-menu "Platform Support"
- depends on PPC_86xx
-
choice
prompt "Machine Type"
+ depends on PPC_86xx
default MPC8641_HPCN
config MPC8641_HPCN
@@ -14,20 +12,10 @@ config MPC8641_HPCN
endchoice
-
config MPC8641
bool
select PPC_INDIRECT_PCI
+ select PPC_INDIRECT_PCI_BE
select PPC_UDBG_16550
+ select MPIC
default y if MPC8641_HPCN
-
-config MPIC
- bool
- default y
-
-config PPC_INDIRECT_PCI_BE
- bool
- depends on PPC_86xx
- default y
-
-endmenu
diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile
index 476a6eeee710..418fd8f4d268 100644
--- a/arch/powerpc/platforms/86xx/Makefile
+++ b/arch/powerpc/platforms/86xx/Makefile
@@ -4,4 +4,4 @@
obj-$(CONFIG_SMP) += mpc86xx_smp.o
obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o
-obj-$(CONFIG_PCI) += pci.o mpc86xx_pcie.o
+obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index f4dd5f2f8a28..3d3d98f5bd4a 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -18,7 +18,6 @@
#include <linux/kdev_t.h>
#include <linux/delay.h>
#include <linux/seq_file.h>
-#include <linux/root_dev.h>
#include <asm/system.h>
#include <asm/time.h>
@@ -120,6 +119,8 @@ mpc86xx_hpcn_init_irq(void)
DBG("mpc86xxhpcn: cascade mapped to irq %d\n", cascade_irq);
i8259_init(cascade_node, 0);
+ of_node_put(cascade_node);
+
set_irq_chained_handler(cascade_irq, mpc86xx_8259_cascade);
#endif
}
@@ -348,7 +349,7 @@ mpc86xx_hpcn_setup_arch(void)
if (np != 0) {
const unsigned int *fp;
- fp = get_property(np, "clock-frequency", NULL);
+ fp = of_get_property(np, "clock-frequency", NULL);
if (fp != 0)
loops_per_jiffy = *fp / HZ;
else
@@ -365,12 +366,6 @@ mpc86xx_hpcn_setup_arch(void)
printk("MPC86xx HPCN board from Freescale Semiconductor\n");
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_HDA1;
-#endif
-
#ifdef CONFIG_SMP
mpc86xx_smp_init();
#endif
@@ -389,7 +384,7 @@ mpc86xx_hpcn_show_cpuinfo(struct seq_file *m)
root = of_find_node_by_path("/");
if (root)
- model = get_property(root, "model", NULL);
+ model = of_get_property(root, "model", NULL);
seq_printf(m, "Machine\t\t: %s\n", model);
of_node_put(root);
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_pcie.c b/arch/powerpc/platforms/86xx/mpc86xx_pcie.c
deleted file mode 100644
index a2f4f730213e..000000000000
--- a/arch/powerpc/platforms/86xx/mpc86xx_pcie.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Support for indirect PCI bridges.
- *
- * Copyright (C) 1998 Gabriel Paubert.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * "Temporary" MPC8548 Errata file -
- * The standard indirect_pci code should work with future silicon versions.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include <asm/machdep.h>
-
-#include "mpc86xx.h"
-
-#define PCI_CFG_OUT out_be32
-
-/* ERRATA PCI-Ex 14 PCIE Controller timeout */
-#define PCIE_FIX out_be32(hose->cfg_addr+0x4, 0x0400ffff)
-
-
-static int
-indirect_read_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 *val)
-{
- struct pci_controller *hose = bus->sysdata;
- volatile void __iomem *cfg_data;
- u32 temp;
-
- if (ppc_md.pci_exclude_device)
- if (ppc_md.pci_exclude_device(bus->number, devfn))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- /* Possible artifact of CDCpp50937 needs further investigation */
- if (devfn != 0x0 && bus->number == 0xff)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- PCIE_FIX;
- if (bus->number == 0xff) {
- PCI_CFG_OUT(hose->cfg_addr,
- (0x80000000 | ((offset & 0xf00) << 16) |
- ((bus->number - hose->bus_offset) << 16)
- | (devfn << 8) | ((offset & 0xfc) )));
- } else {
- PCI_CFG_OUT(hose->cfg_addr,
- (0x80000001 | ((offset & 0xf00) << 16) |
- ((bus->number - hose->bus_offset) << 16)
- | (devfn << 8) | ((offset & 0xfc) )));
- }
-
- /*
- * Note: the caller has already checked that offset is
- * suitably aligned and that len is 1, 2 or 4.
- */
- /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
- cfg_data = hose->cfg_data;
- PCIE_FIX;
- temp = in_le32(cfg_data);
- switch (len) {
- case 1:
- *val = (temp >> (((offset & 3))*8)) & 0xff;
- break;
- case 2:
- *val = (temp >> (((offset & 3))*8)) & 0xffff;
- break;
- default:
- *val = temp;
- break;
- }
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-indirect_write_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 val)
-{
- struct pci_controller *hose = bus->sysdata;
- volatile void __iomem *cfg_data;
- u32 temp;
-
- if (ppc_md.pci_exclude_device)
- if (ppc_md.pci_exclude_device(bus->number, devfn))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- /* Possible artifact of CDCpp50937 needs further investigation */
- if (devfn != 0x0 && bus->number == 0xff)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- PCIE_FIX;
- if (bus->number == 0xff) {
- PCI_CFG_OUT(hose->cfg_addr,
- (0x80000000 | ((offset & 0xf00) << 16) |
- ((bus->number - hose->bus_offset) << 16)
- | (devfn << 8) | ((offset & 0xfc) )));
- } else {
- PCI_CFG_OUT(hose->cfg_addr,
- (0x80000001 | ((offset & 0xf00) << 16) |
- ((bus->number - hose->bus_offset) << 16)
- | (devfn << 8) | ((offset & 0xfc) )));
- }
-
- /*
- * Note: the caller has already checked that offset is
- * suitably aligned and that len is 1, 2 or 4.
- */
- /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
- cfg_data = hose->cfg_data;
- switch (len) {
- case 1:
- PCIE_FIX;
- temp = in_le32(cfg_data);
- temp = (temp & ~(0xff << ((offset & 3) * 8))) |
- (val << ((offset & 3) * 8));
- PCIE_FIX;
- out_le32(cfg_data, temp);
- break;
- case 2:
- PCIE_FIX;
- temp = in_le32(cfg_data);
- temp = (temp & ~(0xffff << ((offset & 3) * 8)));
- temp |= (val << ((offset & 3) * 8)) ;
- PCIE_FIX;
- out_le32(cfg_data, temp);
- break;
- default:
- PCIE_FIX;
- out_le32(cfg_data, val);
- break;
- }
- PCIE_FIX;
- return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops indirect_pcie_ops = {
- indirect_read_config_pcie,
- indirect_write_config_pcie
-};
-
-void __init
-setup_indirect_pcie_nomap(struct pci_controller* hose, void __iomem * cfg_addr,
- void __iomem * cfg_data)
-{
- hose->cfg_addr = cfg_addr;
- hose->cfg_data = cfg_data;
- hose->ops = &indirect_pcie_ops;
-}
-
-void __init
-setup_indirect_pcie(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
-{
- unsigned long base = cfg_addr & PAGE_MASK;
- void __iomem *mbase, *addr, *data;
-
- mbase = ioremap(base, PAGE_SIZE);
- addr = mbase + (cfg_addr & ~PAGE_MASK);
- if ((cfg_data & PAGE_MASK) != base)
- mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
- data = mbase + (cfg_data & ~PAGE_MASK);
- setup_indirect_pcie_nomap(hose, addr, data);
-}
diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c
index 481e18ed5be9..8235c562661f 100644
--- a/arch/powerpc/platforms/86xx/pci.c
+++ b/arch/powerpc/platforms/86xx/pci.c
@@ -22,9 +22,9 @@
#include <asm/atomic.h>
#include <asm/io.h>
#include <asm/prom.h>
-#include <asm/immap_86xx.h>
#include <asm/pci-bridge.h>
#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pcie.h>
#include "mpc86xx.h"
@@ -163,7 +163,7 @@ int __init add_bridge(struct device_node *dev)
has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
/* Get bus range if any */
- bus_range = get_property(dev, "bus-range", &len);
+ bus_range = of_get_property(dev, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int))
printk(KERN_WARNING "Can't get bus-range for %s, assume"
" bus 0\n", dev->full_name);
diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig
index beea6834bb7e..39bb8c5ebe70 100644
--- a/arch/powerpc/platforms/8xx/Kconfig
+++ b/arch/powerpc/platforms/8xx/Kconfig
@@ -1,6 +1,3 @@
-menu "Platform support"
- depends on PPC_8xx
-
config FADS
bool
@@ -9,6 +6,7 @@ config CPM1
choice
prompt "8xx Machine Type"
+ depends on PPC_8xx
depends on 8xx
default MPC885ADS
@@ -36,38 +34,36 @@ config MPC885ADS
endchoice
menu "Freescale Ethernet driver platform-specific options"
- depends on (FS_ENET && MPC885ADS)
-
- config MPC8xx_SECOND_ETH
- bool "Second Ethernet channel"
- depends on MPC885ADS
- default y
- help
- This enables support for second Ethernet on MPC885ADS and MPC86xADS boards.
- The latter will use SCC1, for 885ADS you can select it below.
-
- choice
- prompt "Second Ethernet channel"
- depends on MPC8xx_SECOND_ETH
- default MPC8xx_SECOND_ETH_FEC2
-
- config MPC8xx_SECOND_ETH_FEC2
- bool "FEC2"
- depends on MPC885ADS
- help
- Enable FEC2 to serve as 2-nd Ethernet channel. Note that SMC2
- (often 2-nd UART) will not work if this is enabled.
-
- config MPC8xx_SECOND_ETH_SCC3
- bool "SCC3"
- depends on MPC885ADS
- help
- Enable SCC3 to serve as 2-nd Ethernet channel. Note that SMC1
- (often 1-nd UART) will not work if this is enabled.
-
- endchoice
+ depends on (FS_ENET && MPC885ADS)
-endmenu
+ config MPC8xx_SECOND_ETH
+ bool "Second Ethernet channel"
+ depends on MPC885ADS
+ default y
+ help
+ This enables support for second Ethernet on MPC885ADS and MPC86xADS boards.
+ The latter will use SCC1, for 885ADS you can select it below.
+
+ choice
+ prompt "Second Ethernet channel"
+ depends on MPC8xx_SECOND_ETH
+ default MPC8xx_SECOND_ETH_FEC2
+
+ config MPC8xx_SECOND_ETH_FEC2
+ bool "FEC2"
+ depends on MPC885ADS
+ help
+ Enable FEC2 to serve as 2-nd Ethernet channel. Note that SMC2
+ (often 2-nd UART) will not work if this is enabled.
+
+ config MPC8xx_SECOND_ETH_SCC3
+ bool "SCC3"
+ depends on MPC885ADS
+ help
+ Enable SCC3 to serve as 2-nd Ethernet channel. Note that SMC1
+ (often 1-nd UART) will not work if this is enabled.
+
+ endchoice
endmenu
@@ -98,7 +94,7 @@ config 8xx_CPU6
require workarounds for Linux (and most other OSes to work). If you
get a BUG() very early in boot, this might fix the problem. For
more details read the document entitled "MPC860 Family Device Errata
- Reference" on Motorola's website. This option also incurs a
+ Reference" on Freescale's website. This option also incurs a
performance hit.
If in doubt, say N here.
@@ -135,4 +131,3 @@ config UCODE_PATCH
depends on !NO_UCODE_PATCH
endmenu
-
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c
index 9ed7125f0150..0901dbada350 100644
--- a/arch/powerpc/platforms/8xx/m8xx_setup.c
+++ b/arch/powerpc/platforms/8xx/m8xx_setup.c
@@ -85,17 +85,17 @@ init_internal_rtc(void)
static int __init get_freq(char *name, unsigned long *val)
{
struct device_node *cpu;
- unsigned int *fp;
+ const unsigned int *fp;
int found = 0;
/* The cpu node should have timebase and clock frequency properties */
cpu = of_find_node_by_type(NULL, "cpu");
if (cpu) {
- fp = (unsigned int *)get_property(cpu, name, NULL);
+ fp = of_get_property(cpu, name, NULL);
if (fp) {
found = 1;
- *val = *fp++;
+ *val = *fp;
}
of_node_put(cpu);
@@ -262,7 +262,7 @@ void mpc8xx_show_cpuinfo(struct seq_file *m)
root = of_find_node_by_path("/");
if (root)
- model = get_property(root, "model", NULL);
+ model = of_get_property(root, "model", NULL);
seq_printf(m, "Machine\t\t: %s\n", model);
of_node_put(root);
diff --git a/arch/powerpc/platforms/8xx/mpc86xads.h b/arch/powerpc/platforms/8xx/mpc86xads.h
index b5d19dd0619c..59bad2f9ae51 100644
--- a/arch/powerpc/platforms/8xx/mpc86xads.h
+++ b/arch/powerpc/platforms/8xx/mpc86xads.h
@@ -37,7 +37,7 @@
#define CPM_MAP_ADDR (get_immrbase() + MPC8xx_CPM_OFFSET)
#define CPM_IRQ_OFFSET 16 // for compability with cpm_uart driver
-#define PCMCIA_MEM_ADDR (uint)0xff020000)
+#define PCMCIA_MEM_ADDR ((uint)0xff020000)
#define PCMCIA_MEM_SIZE ((uint)(64 * 1024))
/* Bits of interest in the BCSRs.
diff --git a/arch/powerpc/platforms/8xx/mpc86xads_setup.c b/arch/powerpc/platforms/8xx/mpc86xads_setup.c
index ef52ce701b0e..a35315af5c53 100644
--- a/arch/powerpc/platforms/8xx/mpc86xads_setup.c
+++ b/arch/powerpc/platforms/8xx/mpc86xads_setup.c
@@ -247,7 +247,7 @@ void init_smc_ioports(struct fs_uart_platform_info *data)
}
}
-int platform_device_skip(char *model, int id)
+int platform_device_skip(const char *model, int id)
{
return 0;
}
@@ -260,7 +260,7 @@ static void __init mpc86xads_setup_arch(void)
if (cpu != 0) {
const unsigned int *fp;
- fp = get_property(cpu, "clock-frequency", NULL);
+ fp = of_get_property(cpu, "clock-frequency", NULL);
if (fp != 0)
loops_per_jiffy = *fp / HZ;
else
diff --git a/arch/powerpc/platforms/8xx/mpc885ads.h b/arch/powerpc/platforms/8xx/mpc885ads.h
index 30cbebfe84c5..7c31aec284c2 100644
--- a/arch/powerpc/platforms/8xx/mpc885ads.h
+++ b/arch/powerpc/platforms/8xx/mpc885ads.h
@@ -37,7 +37,7 @@
#define CPM_MAP_ADDR (get_immrbase() + MPC8xx_CPM_OFFSET)
#define CPM_IRQ_OFFSET 16 // for compability with cpm_uart driver
-#define PCMCIA_MEM_ADDR (uint)0xff020000)
+#define PCMCIA_MEM_ADDR ((uint)0xff020000)
#define PCMCIA_MEM_SIZE ((uint)(64 * 1024))
/* Bits of interest in the BCSRs.
diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
index c5fefdf66c0a..a57b57785acd 100644
--- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c
+++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
@@ -322,7 +322,7 @@ void init_smc_ioports(struct fs_uart_platform_info *data)
}
}
-int platform_device_skip(char *model, int id)
+int platform_device_skip(const char *model, int id)
{
#ifdef CONFIG_MPC8xx_SECOND_ETH_SCC3
const char *dev = "FEC";
@@ -346,7 +346,7 @@ static void __init mpc885ads_setup_arch(void)
if (cpu != 0) {
const unsigned int *fp;
- fp = get_property(cpu, "clock-frequency", NULL);
+ fp = of_get_property(cpu, "clock-frequency", NULL);
if (fp != 0)
loops_per_jiffy = *fp / HZ;
else
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
new file mode 100644
index 000000000000..51e33347c147
--- /dev/null
+++ b/arch/powerpc/platforms/Kconfig
@@ -0,0 +1,259 @@
+menu "Platform support"
+
+choice
+ prompt "Machine type"
+ depends on PPC64 || CLASSIC32
+ default PPC_MULTIPLATFORM
+
+config PPC_MULTIPLATFORM
+ bool "Generic desktop/server/laptop"
+ help
+ Select this option if configuring for an IBM pSeries or
+ RS/6000 machine, an Apple machine, or a PReP, CHRP,
+ Maple or Cell-based machine.
+
+config EMBEDDED6xx
+ bool "Embedded 6xx/7xx/7xxx-based board"
+ depends on PPC32 && (BROKEN||BROKEN_ON_SMP)
+
+config APUS
+ bool "Amiga-APUS"
+ depends on PPC32 && BROKEN
+ help
+ Select APUS if configuring for a PowerUP Amiga.
+ More information is available at:
+ <http://linux-apus.sourceforge.net/>.
+endchoice
+
+source "arch/powerpc/platforms/pseries/Kconfig"
+source "arch/powerpc/platforms/iseries/Kconfig"
+source "arch/powerpc/platforms/chrp/Kconfig"
+source "arch/powerpc/platforms/52xx/Kconfig"
+source "arch/powerpc/platforms/powermac/Kconfig"
+source "arch/powerpc/platforms/prep/Kconfig"
+source "arch/powerpc/platforms/maple/Kconfig"
+source "arch/powerpc/platforms/pasemi/Kconfig"
+source "arch/powerpc/platforms/celleb/Kconfig"
+source "arch/powerpc/platforms/ps3/Kconfig"
+source "arch/powerpc/platforms/cell/Kconfig"
+source "arch/powerpc/platforms/8xx/Kconfig"
+source "arch/powerpc/platforms/82xx/Kconfig"
+source "arch/powerpc/platforms/83xx/Kconfig"
+source "arch/powerpc/platforms/85xx/Kconfig"
+source "arch/powerpc/platforms/86xx/Kconfig"
+source "arch/powerpc/platforms/embedded6xx/Kconfig"
+#source "arch/powerpc/platforms/4xx/Kconfig
+
+config PPC_NATIVE
+ bool
+ depends on PPC_MULTIPLATFORM
+ help
+ Support for running natively on the hardware, i.e. without
+ a hypervisor. This option is not user-selectable but should
+ be selected by all platforms that need it.
+
+config UDBG_RTAS_CONSOLE
+ bool "RTAS based debug console"
+ depends on PPC_RTAS
+ default n
+
+config PPC_UDBG_BEAT
+ bool "BEAT based debug console"
+ depends on PPC_CELLEB
+ default n
+
+config XICS
+ depends on PPC_PSERIES
+ bool
+ default y
+
+config MPIC
+ bool
+ default n
+
+config MPIC_WEIRD
+ bool
+ default n
+
+config PPC_I8259
+ bool
+ default n
+
+config U3_DART
+ bool
+ depends on PPC_MULTIPLATFORM && PPC64
+ default n
+
+config PPC_RTAS
+ bool
+ default n
+
+config RTAS_ERROR_LOGGING
+ bool
+ depends on PPC_RTAS
+ default n
+
+config RTAS_PROC
+ bool "Proc interface to RTAS"
+ depends on PPC_RTAS
+ default y
+
+config RTAS_FLASH
+ tristate "Firmware flash interface"
+ depends on PPC64 && RTAS_PROC
+
+config PPC_PMI
+ tristate "Support for PMI"
+ depends PPC_IBM_CELL_BLADE
+ help
+ PMI (Platform Management Interrupt) is a way to
+ communicate with the BMC (Baseboard Mangement Controller).
+ It is used in some IBM Cell blades.
+ default m
+
+config MMIO_NVRAM
+ bool
+ default n
+
+config MPIC_U3_HT_IRQS
+ bool
+ depends on PPC_MAPLE
+ default y
+
+config IBMVIO
+ depends on PPC_PSERIES || PPC_ISERIES
+ bool
+ default y
+
+config IBMEBUS
+ depends on PPC_PSERIES
+ bool "Support for GX bus based adapters"
+ help
+ Bus device driver for GX bus based adapters.
+
+config PPC_MPC106
+ bool
+ default n
+
+config PPC_970_NAP
+ bool
+ default n
+
+config PPC_INDIRECT_IO
+ bool
+ select GENERIC_IOMAP
+ default n
+
+config GENERIC_IOMAP
+ bool
+ default n
+
+source "drivers/cpufreq/Kconfig"
+
+menu "CPU Frequency drivers"
+ depends on CPU_FREQ
+
+config CPU_FREQ_PMAC
+ bool "Support for Apple PowerBooks"
+ depends on ADB_PMU && PPC32
+ select CPU_FREQ_TABLE
+ help
+ This adds support for frequency switching on Apple PowerBooks,
+ this currently includes some models of iBook & Titanium
+ PowerBook.
+
+config CPU_FREQ_PMAC64
+ bool "Support for some Apple G5s"
+ depends on PPC_PMAC && PPC64
+ select CPU_FREQ_TABLE
+ help
+ This adds support for frequency switching on Apple iMac G5,
+ and some of the more recent desktop G5 machines as well.
+
+config PPC_PASEMI_CPUFREQ
+ bool "Support for PA Semi PWRficient"
+ depends on PPC_PASEMI
+ default y
+ select CPU_FREQ_TABLE
+ help
+ This adds the support for frequency switching on PA Semi
+ PWRficient processors.
+
+endmenu
+
+config PPC601_SYNC_FIX
+ bool "Workarounds for PPC601 bugs"
+ depends on 6xx && (PPC_PREP || PPC_PMAC)
+ help
+ Some versions of the PPC601 (the first PowerPC chip) have bugs which
+ mean that extra synchronization instructions are required near
+ certain instructions, typically those that make major changes to the
+ CPU state. These extra instructions reduce performance slightly.
+ If you say N here, these extra instructions will not be included,
+ resulting in a kernel which will run faster but may not run at all
+ on some systems with the PPC601 chip.
+
+ If in doubt, say Y here.
+
+config TAU
+ bool "On-chip CPU temperature sensor support"
+ depends on CLASSIC32
+ help
+ G3 and G4 processors have an on-chip temperature sensor called the
+ 'Thermal Assist Unit (TAU)', which, in theory, can measure the on-die
+ temperature within 2-4 degrees Celsius. This option shows the current
+ on-die temperature in /proc/cpuinfo if the cpu supports it.
+
+ Unfortunately, on some chip revisions, this sensor is very inaccurate
+ and in many cases, does not work at all, so don't assume the cpu
+ temp is actually what /proc/cpuinfo says it is.
+
+config TAU_INT
+ bool "Interrupt driven TAU driver (DANGEROUS)"
+ depends on TAU
+ ---help---
+ The TAU supports an interrupt driven mode which causes an interrupt
+ whenever the temperature goes out of range. This is the fastest way
+ to get notified the temp has exceeded a range. With this option off,
+ a timer is used to re-check the temperature periodically.
+
+ However, on some cpus it appears that the TAU interrupt hardware
+ is buggy and can cause a situation which would lead unexplained hard
+ lockups.
+
+ Unless you are extending the TAU driver, or enjoy kernel/hardware
+ debugging, leave this option off.
+
+config TAU_AVERAGE
+ bool "Average high and low temp"
+ depends on TAU
+ ---help---
+ The TAU hardware can compare the temperature to an upper and lower
+ bound. The default behavior is to show both the upper and lower
+ bound in /proc/cpuinfo. If the range is large, the temperature is
+ either changing a lot, or the TAU hardware is broken (likely on some
+ G4's). If the range is small (around 4 degrees), the temperature is
+ relatively stable. If you say Y here, a single temperature value,
+ halfway between the upper and lower bounds, will be reported in
+ /proc/cpuinfo.
+
+ If in doubt, say N here.
+
+config QUICC_ENGINE
+ bool
+ help
+ The QUICC Engine (QE) is a new generation of communications
+ coprocessors on Freescale embedded CPUs (akin to CPM in older chips).
+ Selecting this option means that you wish to build a kernel
+ for a machine with a QE coprocessor.
+
+config CPM2
+ bool
+ default n
+ help
+ The CPM2 (Communications Processor Module) is a coprocessor on
+ embedded CPUs made by Freescale. Selecting this option means that
+ you wish to build a kernel for a machine with a CPM2 coprocessor
+ on it (826x, 827x, 8560).
+
+endmenu
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 06a85b704331..82551770917c 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -1,3 +1,26 @@
+config PPC_CELL
+ bool
+ default n
+
+config PPC_CELL_NATIVE
+ bool
+ select PPC_CELL
+ select PPC_DCR_MMIO
+ select PPC_OF_PLATFORM_PCI
+ select PPC_INDIRECT_IO
+ select PPC_NATIVE
+ select MPIC
+ default n
+
+config PPC_IBM_CELL_BLADE
+ bool "IBM Cell Blade"
+ depends on PPC_MULTIPLATFORM && PPC64
+ select PPC_CELL_NATIVE
+ select PPC_RTAS
+ select MMIO_NVRAM
+ select PPC_UDBG_16550
+ select UDBG_RTAS_CONSOLE
+
menu "Cell Broadband Engine options"
depends on PPC_CELL
@@ -18,6 +41,7 @@ config SPU_BASE
config CBE_RAS
bool "RAS features for bare metal Cell BE"
+ depends on PPC_CELL_NATIVE
default y
config CBE_THERM
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c
index a3850fd1e94c..f9ac3fe3be97 100644
--- a/arch/powerpc/platforms/cell/cbe_cpufreq.c
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c
@@ -25,9 +25,12 @@
#include <asm/hw_irq.h>
#include <asm/io.h>
+#include <asm/machdep.h>
#include <asm/processor.h>
#include <asm/prom.h>
#include <asm/time.h>
+#include <asm/pmi.h>
+#include <asm/of_platform.h>
#include "cbe_regs.h"
@@ -68,6 +71,38 @@ static u64 MIC_Slow_Next_Timer_table[] = {
* hardware specific functions
*/
+static struct of_device *pmi_dev;
+
+static int set_pmode_pmi(int cpu, unsigned int pmode)
+{
+ int ret;
+ pmi_message_t pmi_msg;
+#ifdef DEBUG
+ u64 time;
+#endif
+
+ pmi_msg.type = PMI_TYPE_FREQ_CHANGE;
+ pmi_msg.data1 = cbe_cpu_to_node(cpu);
+ pmi_msg.data2 = pmode;
+
+#ifdef DEBUG
+ time = (u64) get_cycles();
+#endif
+
+ pmi_send_message(pmi_dev, pmi_msg);
+ ret = pmi_msg.data2;
+
+ pr_debug("PMI returned slow mode %d\n", ret);
+
+#ifdef DEBUG
+ time = (u64) get_cycles() - time; /* actual cycles (not cpu cycles!) */
+ time = 1000000000 * time / CLOCK_TICK_RATE; /* time in ns (10^-9) */
+ pr_debug("had to wait %lu ns for a transition\n", time);
+#endif
+ return ret;
+}
+
+
static int get_pmode(int cpu)
{
int ret;
@@ -79,7 +114,7 @@ static int get_pmode(int cpu)
return ret;
}
-static int set_pmode(int cpu, unsigned int pmode)
+static int set_pmode_reg(int cpu, unsigned int pmode)
{
struct cbe_pmd_regs __iomem *pmd_regs;
struct cbe_mic_tm_regs __iomem *mic_tm_regs;
@@ -120,37 +155,71 @@ static int set_pmode(int cpu, unsigned int pmode)
return 0;
}
+static int set_pmode(int cpu, unsigned int slow_mode) {
+ if (pmi_dev)
+ return set_pmode_pmi(cpu, slow_mode);
+ else
+ return set_pmode_reg(cpu, slow_mode);
+}
+
+static void cbe_cpufreq_handle_pmi(struct of_device *dev, pmi_message_t pmi_msg)
+{
+ struct cpufreq_policy policy;
+ u8 cpu;
+ u8 cbe_pmode_new;
+
+ BUG_ON(pmi_msg.type != PMI_TYPE_FREQ_CHANGE);
+
+ cpu = cbe_node_to_cpu(pmi_msg.data1);
+ cbe_pmode_new = pmi_msg.data2;
+
+ cpufreq_get_policy(&policy, cpu);
+
+ policy.max = min(policy.max, cbe_freqs[cbe_pmode_new].frequency);
+ policy.min = min(policy.min, policy.max);
+
+ pr_debug("cbe_handle_pmi: new policy.min=%d policy.max=%d\n", policy.min, policy.max);
+ cpufreq_set_policy(&policy);
+}
+
+static struct pmi_handler cbe_pmi_handler = {
+ .type = PMI_TYPE_FREQ_CHANGE,
+ .handle_pmi_message = cbe_cpufreq_handle_pmi,
+};
+
+
/*
* cpufreq functions
*/
-static int cbe_cpufreq_cpu_init (struct cpufreq_policy *policy)
+static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy)
{
- u32 *max_freq;
+ const u32 *max_freqp;
+ u32 max_freq;
int i, cur_pmode;
struct device_node *cpu;
cpu = of_get_cpu_node(policy->cpu, NULL);
- if(!cpu)
+ if (!cpu)
return -ENODEV;
pr_debug("init cpufreq on CPU %d\n", policy->cpu);
- max_freq = (u32*) get_property(cpu, "clock-frequency", NULL);
+ max_freqp = of_get_property(cpu, "clock-frequency", NULL);
- if(!max_freq)
+ if (!max_freqp)
return -EINVAL;
- // we need the freq in kHz
- *max_freq /= 1000;
+ /* we need the freq in kHz */
+ max_freq = *max_freqp / 1000;
- pr_debug("max clock-frequency is at %u kHz\n", *max_freq);
+ pr_debug("max clock-frequency is at %u kHz\n", max_freq);
pr_debug("initializing frequency table\n");
- // initialize frequency table
+ /* initialize frequency table */
for (i=0; cbe_freqs[i].frequency!=CPUFREQ_TABLE_END; i++) {
- cbe_freqs[i].frequency = *max_freq / cbe_freqs[i].index;
+ cbe_freqs[i].frequency = max_freq / cbe_freqs[i].index;
pr_debug("%d: %d\n", i, cbe_freqs[i].frequency);
}
@@ -167,10 +236,10 @@ static int cbe_cpufreq_cpu_init (struct cpufreq_policy *policy)
policy->cpus = cpu_sibling_map[policy->cpu];
#endif
- cpufreq_frequency_table_get_attr (cbe_freqs, policy->cpu);
+ cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu);
/* this ensures that policy->cpuinfo_min and policy->cpuinfo_max are set correctly */
- return cpufreq_frequency_table_cpuinfo (policy, cbe_freqs);
+ return cpufreq_frequency_table_cpuinfo(policy, cbe_freqs);
}
static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy)
@@ -202,7 +271,7 @@ static int cbe_cpufreq_target(struct cpufreq_policy *policy, unsigned int target
freqs.new = cbe_freqs[cbe_pmode_new].frequency;
freqs.cpu = policy->cpu;
- mutex_lock (&cbe_switch_mutex);
+ mutex_lock(&cbe_switch_mutex);
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
pr_debug("setting frequency for cpu %d to %d kHz, 1/%d of max frequency\n",
@@ -233,11 +302,26 @@ static struct cpufreq_driver cbe_cpufreq_driver = {
static int __init cbe_cpufreq_init(void)
{
+ struct device_node *np;
+
+ if (!machine_is(cell))
+ return -ENODEV;
+
+ np = of_find_node_by_type(NULL, "ibm,pmi");
+
+ pmi_dev = of_find_device_by_node(np);
+
+ if (pmi_dev)
+ pmi_register_handler(pmi_dev, &cbe_pmi_handler);
+
return cpufreq_register_driver(&cbe_cpufreq_driver);
}
static void __exit cbe_cpufreq_exit(void)
{
+ if (pmi_dev)
+ pmi_unregister_handler(pmi_dev, &cbe_pmi_handler);
+
cpufreq_unregister_driver(&cbe_cpufreq_driver);
}
diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c
index 9a0ee62691d5..12c9674b4b1f 100644
--- a/arch/powerpc/platforms/cell/cbe_regs.c
+++ b/arch/powerpc/platforms/cell/cbe_regs.c
@@ -14,6 +14,8 @@
#include <asm/pgtable.h>
#include <asm/prom.h>
#include <asm/ptrace.h>
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
#include "cbe_regs.h"
@@ -27,6 +29,7 @@
static struct cbe_regs_map
{
struct device_node *cpu_node;
+ struct device_node *be_node;
struct cbe_pmd_regs __iomem *pmd_regs;
struct cbe_iic_regs __iomem *iic_regs;
struct cbe_mic_tm_regs __iomem *mic_tm_regs;
@@ -37,30 +40,43 @@ static int cbe_regs_map_count;
static struct cbe_thread_map
{
struct device_node *cpu_node;
+ struct device_node *be_node;
struct cbe_regs_map *regs;
+ unsigned int thread_id;
+ unsigned int cbe_id;
} cbe_thread_map[NR_CPUS];
+static cpumask_t cbe_local_mask[MAX_CBE] = { [0 ... MAX_CBE-1] = CPU_MASK_NONE };
+static cpumask_t cbe_first_online_cpu = CPU_MASK_NONE;
+
static struct cbe_regs_map *cbe_find_map(struct device_node *np)
{
int i;
struct device_node *tmp_np;
- if (strcasecmp(np->type, "spe") == 0) {
- if (np->data == NULL) {
- /* walk up path until cpu node was found */
- tmp_np = np->parent;
- while (tmp_np != NULL && strcasecmp(tmp_np->type, "cpu") != 0)
- tmp_np = tmp_np->parent;
+ if (strcasecmp(np->type, "spe")) {
+ for (i = 0; i < cbe_regs_map_count; i++)
+ if (cbe_regs_maps[i].cpu_node == np ||
+ cbe_regs_maps[i].be_node == np)
+ return &cbe_regs_maps[i];
+ return NULL;
+ }
- np->data = cbe_find_map(tmp_np);
- }
+ if (np->data)
return np->data;
- }
- for (i = 0; i < cbe_regs_map_count; i++)
- if (cbe_regs_maps[i].cpu_node == np)
- return &cbe_regs_maps[i];
- return NULL;
+ /* walk up path until cpu or be node was found */
+ tmp_np = np;
+ do {
+ tmp_np = tmp_np->parent;
+ /* on a correct devicetree we wont get up to root */
+ BUG_ON(!tmp_np);
+ } while (strcasecmp(tmp_np->type, "cpu") &&
+ strcasecmp(tmp_np->type, "be"));
+
+ np->data = cbe_find_map(tmp_np);
+
+ return np->data;
}
struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np)
@@ -130,38 +146,105 @@ struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu)
}
EXPORT_SYMBOL_GPL(cbe_get_cpu_mic_tm_regs);
-/* FIXME
- * This is little more than a stub at the moment. It should be
- * fleshed out so that it works for both SMT and non-SMT, no
- * matter if the passed cpu is odd or even.
- * For SMT enabled, returns 0 for even-numbered cpu; otherwise 1.
- * For SMT disabled, returns 0 for all cpus.
- */
u32 cbe_get_hw_thread_id(int cpu)
{
- return (cpu & 1);
+ return cbe_thread_map[cpu].thread_id;
}
EXPORT_SYMBOL_GPL(cbe_get_hw_thread_id);
-void __init cbe_regs_init(void)
+u32 cbe_cpu_to_node(int cpu)
{
- int i;
- struct device_node *cpu;
+ return cbe_thread_map[cpu].cbe_id;
+}
+EXPORT_SYMBOL_GPL(cbe_cpu_to_node);
- /* Build local fast map of CPUs */
- for_each_possible_cpu(i)
- cbe_thread_map[i].cpu_node = of_get_cpu_node(i, NULL);
+u32 cbe_node_to_cpu(int node)
+{
+ return find_first_bit( (unsigned long *) &cbe_local_mask[node], sizeof(cpumask_t));
+}
+EXPORT_SYMBOL_GPL(cbe_node_to_cpu);
- /* Find maps for each device tree CPU */
- for_each_node_by_type(cpu, "cpu") {
- struct cbe_regs_map *map = &cbe_regs_maps[cbe_regs_map_count++];
+static struct device_node *cbe_get_be_node(int cpu_id)
+{
+ struct device_node *np;
+
+ for_each_node_by_type (np, "be") {
+ int len,i;
+ const phandle *cpu_handle;
+
+ cpu_handle = of_get_property(np, "cpus", &len);
+
+ for (i=0; i<len; i++)
+ if (of_find_node_by_phandle(cpu_handle[i]) == of_get_cpu_node(cpu_id, NULL))
+ return np;
+ }
+
+ return NULL;
+}
+
+void __init cbe_fill_regs_map(struct cbe_regs_map *map)
+{
+ if(map->be_node) {
+ struct device_node *be, *np;
+
+ be = map->be_node;
+
+ for_each_node_by_type(np, "pervasive")
+ if (of_get_parent(np) == be)
+ map->pmd_regs = of_iomap(np, 0);
+
+ for_each_node_by_type(np, "CBEA-Internal-Interrupt-Controller")
+ if (of_get_parent(np) == be)
+ map->iic_regs = of_iomap(np, 2);
+ for_each_node_by_type(np, "mic-tm")
+ if (of_get_parent(np) == be)
+ map->mic_tm_regs = of_iomap(np, 0);
+ } else {
+ struct device_node *cpu;
/* That hack must die die die ! */
const struct address_prop {
unsigned long address;
unsigned int len;
} __attribute__((packed)) *prop;
+ cpu = map->cpu_node;
+
+ prop = of_get_property(cpu, "pervasive", NULL);
+ if (prop != NULL)
+ map->pmd_regs = ioremap(prop->address, prop->len);
+
+ prop = of_get_property(cpu, "iic", NULL);
+ if (prop != NULL)
+ map->iic_regs = ioremap(prop->address, prop->len);
+
+ prop = of_get_property(cpu, "mic-tm", NULL);
+ if (prop != NULL)
+ map->mic_tm_regs = ioremap(prop->address, prop->len);
+ }
+}
+
+
+void __init cbe_regs_init(void)
+{
+ int i;
+ unsigned int thread_id;
+ struct device_node *cpu;
+
+ /* Build local fast map of CPUs */
+ for_each_possible_cpu(i) {
+ cbe_thread_map[i].cpu_node = of_get_cpu_node(i, &thread_id);
+ cbe_thread_map[i].be_node = cbe_get_be_node(i);
+ cbe_thread_map[i].thread_id = thread_id;
+ }
+
+ /* Find maps for each device tree CPU */
+ for_each_node_by_type(cpu, "cpu") {
+ struct cbe_regs_map *map;
+ unsigned int cbe_id;
+
+ cbe_id = cbe_regs_map_count++;
+ map = &cbe_regs_maps[cbe_id];
if (cbe_regs_map_count > MAX_CBE) {
printk(KERN_ERR "cbe_regs: More BE chips than supported"
@@ -170,22 +253,21 @@ void __init cbe_regs_init(void)
return;
}
map->cpu_node = cpu;
- for_each_possible_cpu(i)
- if (cbe_thread_map[i].cpu_node == cpu)
- cbe_thread_map[i].regs = map;
- prop = get_property(cpu, "pervasive", NULL);
- if (prop != NULL)
- map->pmd_regs = ioremap(prop->address, prop->len);
+ for_each_possible_cpu(i) {
+ struct cbe_thread_map *thread = &cbe_thread_map[i];
- prop = get_property(cpu, "iic", NULL);
- if (prop != NULL)
- map->iic_regs = ioremap(prop->address, prop->len);
+ if (thread->cpu_node == cpu) {
+ thread->regs = map;
+ thread->cbe_id = cbe_id;
+ map->be_node = thread->be_node;
+ cpu_set(i, cbe_local_mask[cbe_id]);
+ if(thread->thread_id == 0)
+ cpu_set(i, cbe_first_online_cpu);
+ }
+ }
- prop = (struct address_prop *)get_property(cpu, "mic-tm",
- NULL);
- if (prop != NULL)
- map->mic_tm_regs = ioremap(prop->address, prop->len);
+ cbe_fill_regs_map(map);
}
}
diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h
index 440a7ecc66ea..17d597144877 100644
--- a/arch/powerpc/platforms/cell/cbe_regs.h
+++ b/arch/powerpc/platforms/cell/cbe_regs.h
@@ -255,6 +255,11 @@ struct cbe_mic_tm_regs {
extern struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np);
extern struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu);
+/* some utility functions to deal with SMT */
+extern u32 cbe_get_hw_thread_id(int cpu);
+extern u32 cbe_cpu_to_node(int cpu);
+extern u32 cbe_node_to_cpu(int node);
+
/* Init this module early */
extern void cbe_regs_init(void);
diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c
index 70e0d968d30f..f370f0fa6f4c 100644
--- a/arch/powerpc/platforms/cell/cbe_thermal.c
+++ b/arch/powerpc/platforms/cell/cbe_thermal.c
@@ -1,6 +1,31 @@
/*
* thermal support for the cell processor
*
+ * This module adds some sysfs attributes to cpu and spu nodes.
+ * Base for measurements are the digital thermal sensors (DTS)
+ * located on the chip.
+ * The accuracy is 2 degrees, starting from 65 up to 125 degrees celsius
+ * The attributes can be found under
+ * /sys/devices/system/cpu/cpuX/thermal
+ * /sys/devices/system/spu/spuX/thermal
+ *
+ * The following attributes are added for each node:
+ * temperature:
+ * contains the current temperature measured by the DTS
+ * throttle_begin:
+ * throttling begins when temperature is greater or equal to
+ * throttle_begin. Setting this value to 125 prevents throttling.
+ * throttle_end:
+ * throttling is being ceased, if the temperature is lower than
+ * throttle_end. Due to a delay between applying throttling and
+ * a reduced temperature this value should be less than throttle_begin.
+ * A value equal to throttle_begin provides only a very little hysteresis.
+ * throttle_full_stop:
+ * If the temperatrue is greater or equal to throttle_full_stop,
+ * full throttling is applied to the cpu or spu. This value should be
+ * greater than throttle_begin and throttle_end. Setting this value to
+ * 65 prevents the unit from running code at all.
+ *
* (C) Copyright IBM Deutschland Entwicklung GmbH 2005
*
* Author: Christian Krafft <krafft@de.ibm.com>
@@ -31,6 +56,26 @@
#include "cbe_regs.h"
#include "spu_priv1_mmio.h"
+#define TEMP_MIN 65
+#define TEMP_MAX 125
+
+#define SYSDEV_PREFIX_ATTR(_prefix,_name,_mode) \
+struct sysdev_attribute attr_ ## _prefix ## _ ## _name = { \
+ .attr = { .name = __stringify(_name), .mode = _mode }, \
+ .show = _prefix ## _show_ ## _name, \
+ .store = _prefix ## _store_ ## _name, \
+};
+
+static inline u8 reg_to_temp(u8 reg_value)
+{
+ return ((reg_value & 0x3f) << 1) + TEMP_MIN;
+}
+
+static inline u8 temp_to_reg(u8 temp)
+{
+ return ((temp - TEMP_MIN) >> 1) & 0x3f;
+}
+
static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev)
{
struct spu *spu;
@@ -43,14 +88,14 @@ static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev)
/* returns the value for a given spu in a given register */
static u8 spu_read_register_value(struct sys_device *sysdev, union spe_reg __iomem *reg)
{
- unsigned int *id;
+ const unsigned int *id;
union spe_reg value;
struct spu *spu;
/* getting the id from the reg attribute will not work on future device-tree layouts
* in future we should store the id to the spu struct and use it here */
spu = container_of(sysdev, struct spu, sysdev);
- id = (unsigned int *)get_property(spu_devnode(spu), "reg", NULL);
+ id = of_get_property(spu_devnode(spu), "reg", NULL);
value.val = in_be64(&reg->val);
return value.spe[*id];
@@ -58,20 +103,81 @@ static u8 spu_read_register_value(struct sys_device *sysdev, union spe_reg __iom
static ssize_t spu_show_temp(struct sys_device *sysdev, char *buf)
{
- int value;
+ u8 value;
struct cbe_pmd_regs __iomem *pmd_regs;
pmd_regs = get_pmd_regs(sysdev);
value = spu_read_register_value(sysdev, &pmd_regs->ts_ctsr1);
- /* clear all other bits */
+
+ return sprintf(buf, "%d\n", reg_to_temp(value));
+}
+
+static ssize_t show_throttle(struct cbe_pmd_regs __iomem *pmd_regs, char *buf, int pos)
+{
+ u64 value;
+
+ value = in_be64(&pmd_regs->tm_tpr.val);
+ /* access the corresponding byte */
+ value >>= pos;
value &= 0x3F;
- /* temp is stored in steps of 2 degrees */
- value *= 2;
- /* base temp is 65 degrees */
- value += 65;
- return sprintf(buf, "%d\n", (int) value);
+ return sprintf(buf, "%d\n", reg_to_temp(value));
+}
+
+static ssize_t store_throttle(struct cbe_pmd_regs __iomem *pmd_regs, const char *buf, size_t size, int pos)
+{
+ u64 reg_value;
+ int temp;
+ u64 new_value;
+ int ret;
+
+ ret = sscanf(buf, "%u", &temp);
+
+ if (ret != 1 || temp < TEMP_MIN || temp > TEMP_MAX)
+ return -EINVAL;
+
+ new_value = temp_to_reg(temp);
+
+ reg_value = in_be64(&pmd_regs->tm_tpr.val);
+
+ /* zero out bits for new value */
+ reg_value &= ~(0xffull << pos);
+ /* set bits to new value */
+ reg_value |= new_value << pos;
+
+ out_be64(&pmd_regs->tm_tpr.val, reg_value);
+ return size;
+}
+
+static ssize_t spu_show_throttle_end(struct sys_device *sysdev, char *buf)
+{
+ return show_throttle(get_pmd_regs(sysdev), buf, 0);
+}
+
+static ssize_t spu_show_throttle_begin(struct sys_device *sysdev, char *buf)
+{
+ return show_throttle(get_pmd_regs(sysdev), buf, 8);
+}
+
+static ssize_t spu_show_throttle_full_stop(struct sys_device *sysdev, char *buf)
+{
+ return show_throttle(get_pmd_regs(sysdev), buf, 16);
+}
+
+static ssize_t spu_store_throttle_end(struct sys_device *sysdev, const char *buf, size_t size)
+{
+ return store_throttle(get_pmd_regs(sysdev), buf, size, 0);
+}
+
+static ssize_t spu_store_throttle_begin(struct sys_device *sysdev, const char *buf, size_t size)
+{
+ return store_throttle(get_pmd_regs(sysdev), buf, size, 8);
+}
+
+static ssize_t spu_store_throttle_full_stop(struct sys_device *sysdev, const char *buf, size_t size)
+{
+ return store_throttle(get_pmd_regs(sysdev), buf, size, 16);
}
static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos)
@@ -82,16 +188,9 @@ static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos)
pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id);
value = in_be64(&pmd_regs->ts_ctsr2);
- /* access the corresponding byte */
- value >>= pos;
- /* clear all other bits */
- value &= 0x3F;
- /* temp is stored in steps of 2 degrees */
- value *= 2;
- /* base temp is 65 degrees */
- value += 65;
+ value = (value >> pos) & 0x3f;
- return sprintf(buf, "%d\n", (int) value);
+ return sprintf(buf, "%d\n", reg_to_temp(value));
}
@@ -108,13 +207,52 @@ static ssize_t ppe_show_temp1(struct sys_device *sysdev, char *buf)
return ppe_show_temp(sysdev, buf, 0);
}
+static ssize_t ppe_show_throttle_end(struct sys_device *sysdev, char *buf)
+{
+ return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 32);
+}
+
+static ssize_t ppe_show_throttle_begin(struct sys_device *sysdev, char *buf)
+{
+ return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 40);
+}
+
+static ssize_t ppe_show_throttle_full_stop(struct sys_device *sysdev, char *buf)
+{
+ return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 48);
+}
+
+static ssize_t ppe_store_throttle_end(struct sys_device *sysdev, const char *buf, size_t size)
+{
+ return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 32);
+}
+
+static ssize_t ppe_store_throttle_begin(struct sys_device *sysdev, const char *buf, size_t size)
+{
+ return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 40);
+}
+
+static ssize_t ppe_store_throttle_full_stop(struct sys_device *sysdev, const char *buf, size_t size)
+{
+ return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 48);
+}
+
+
static struct sysdev_attribute attr_spu_temperature = {
.attr = {.name = "temperature", .mode = 0400 },
.show = spu_show_temp,
};
+static SYSDEV_PREFIX_ATTR(spu, throttle_end, 0600);
+static SYSDEV_PREFIX_ATTR(spu, throttle_begin, 0600);
+static SYSDEV_PREFIX_ATTR(spu, throttle_full_stop, 0600);
+
+
static struct attribute *spu_attributes[] = {
&attr_spu_temperature.attr,
+ &attr_spu_throttle_end.attr,
+ &attr_spu_throttle_begin.attr,
+ &attr_spu_throttle_full_stop.attr,
NULL,
};
@@ -133,9 +271,16 @@ static struct sysdev_attribute attr_ppe_temperature1 = {
.show = ppe_show_temp1,
};
+static SYSDEV_PREFIX_ATTR(ppe, throttle_end, 0600);
+static SYSDEV_PREFIX_ATTR(ppe, throttle_begin, 0600);
+static SYSDEV_PREFIX_ATTR(ppe, throttle_full_stop, 0600);
+
static struct attribute *ppe_attributes[] = {
&attr_ppe_temperature0.attr,
&attr_ppe_temperature1.attr,
+ &attr_ppe_throttle_end.attr,
+ &attr_ppe_throttle_begin.attr,
+ &attr_ppe_throttle_full_stop.attr,
NULL,
};
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index 6666d037eb44..4fc4e92775d0 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -261,7 +261,7 @@ static int iic_host_xlate(struct irq_host *h, struct device_node *ct,
return -ENODEV;
if (intsize != 1)
return -ENODEV;
- val = get_property(ct, "#interrupt-cells", NULL);
+ val = of_get_property(ct, "#interrupt-cells", NULL);
if (val == NULL || *val != 1)
return -ENODEV;
@@ -327,7 +327,7 @@ static int __init setup_iic(void)
if (!device_is_compatible(dn,
"IBM,CBEA-Internal-Interrupt-Controller"))
continue;
- np = get_property(dn, "ibm,interrupt-server-ranges", NULL);
+ np = of_get_property(dn, "ibm,interrupt-server-ranges", NULL);
if (np == NULL) {
printk(KERN_WARNING "IIC: CPU association not found\n");
of_node_put(dn);
diff --git a/arch/powerpc/platforms/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c
index 7c73128305ec..d68d920eb2c4 100644
--- a/arch/powerpc/platforms/cell/io-workarounds.c
+++ b/arch/powerpc/platforms/cell/io-workarounds.c
@@ -318,7 +318,7 @@ static int __init spider_pci_workaround_init(void)
*/
list_for_each_entry(phb, &hose_list, list_node) {
struct device_node *np = phb->arch_data;
- const char *model = get_property(np, "model", NULL);
+ const char *model = of_get_property(np, "model", NULL);
/* If no model property or name isn't exactly "pci", skip */
if (model == NULL || strcmp(np->name, "pci"))
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index 67d617b60a23..760caa76841a 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -291,9 +291,9 @@ static int cell_iommu_find_ioc(int nid, unsigned long *base)
const unsigned int *nidp;
const unsigned long *tmp;
- nidp = get_property(np, "node-id", NULL);
+ nidp = of_get_property(np, "node-id", NULL);
if (nidp && *nidp == nid) {
- tmp = get_property(np, "ioc-translation", NULL);
+ tmp = of_get_property(np, "ioc-translation", NULL);
if (tmp) {
*base = *tmp;
of_node_put(np);
@@ -430,7 +430,7 @@ cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np,
struct iommu_window *window;
const unsigned int *ioid;
- ioid = get_property(np, "ioid", NULL);
+ ioid = of_get_property(np, "ioid", NULL);
if (ioid == NULL)
printk(KERN_WARNING "iommu: missing ioid for %s using 0\n",
np->full_name);
@@ -496,7 +496,7 @@ static void cell_dma_dev_setup(struct device *dev)
struct dev_archdata *archdata = &dev->archdata;
/* If we run without iommu, no need to do anything */
- if (pci_dma_ops == &dma_direct_ops)
+ if (get_pci_dma_ops() == &dma_direct_ops)
return;
/* Current implementation uses the first window available in that
@@ -530,7 +530,7 @@ static int cell_of_bus_notify(struct notifier_block *nb, unsigned long action,
return 0;
/* We use the PCI DMA ops */
- dev->archdata.dma_ops = pci_dma_ops;
+ dev->archdata.dma_ops = get_pci_dma_ops();
cell_dma_dev_setup(dev);
@@ -549,7 +549,7 @@ static int __init cell_iommu_get_window(struct device_node *np,
unsigned long index;
/* Use ibm,dma-window if available, else, hard code ! */
- dma_window = get_property(np, "ibm,dma-window", NULL);
+ dma_window = of_get_property(np, "ibm,dma-window", NULL);
if (dma_window == NULL) {
*base = 0;
*size = 0x80000000u;
@@ -646,7 +646,7 @@ static int __init cell_iommu_init_disabled(void)
unsigned long base = 0, size;
/* When no iommu is present, we use direct DMA ops */
- pci_dma_ops = &dma_direct_ops;
+ set_pci_dma_ops(&dma_direct_ops);
/* First make sure all IOC translation is turned off */
cell_disable_iommus();
@@ -734,7 +734,7 @@ static int __init cell_iommu_init(void)
}
/* Setup default PCI iommu ops */
- pci_dma_ops = &dma_iommu_ops;
+ set_pci_dma_ops(&dma_iommu_ops);
bail:
/* Register callbacks on OF platform device addition/removal
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c
index 0984c7071695..3961a085b432 100644
--- a/arch/powerpc/platforms/cell/ras.c
+++ b/arch/powerpc/platforms/cell/ras.c
@@ -3,11 +3,13 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/smp.h>
+#include <linux/reboot.h>
#include <asm/reg.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/machdep.h>
+#include <asm/rtas.h>
#include "ras.h"
#include "cbe_regs.h"
@@ -82,6 +84,164 @@ static int cbe_machine_check_handler(struct pt_regs *regs)
return 0;
}
+struct ptcal_area {
+ struct list_head list;
+ int nid;
+ int order;
+ struct page *pages;
+};
+
+static LIST_HEAD(ptcal_list);
+
+static int ptcal_start_tok, ptcal_stop_tok;
+
+static int __init cbe_ptcal_enable_on_node(int nid, int order)
+{
+ struct ptcal_area *area;
+ int ret = -ENOMEM;
+ unsigned long addr;
+
+#ifdef CONFIG_CRASH_DUMP
+ rtas_call(ptcal_stop_tok, 1, 1, NULL, nid);
+#endif
+
+ area = kmalloc(sizeof(*area), GFP_KERNEL);
+ if (!area)
+ goto out_err;
+
+ area->nid = nid;
+ area->order = order;
+ area->pages = alloc_pages_node(area->nid, GFP_KERNEL, area->order);
+
+ if (!area->pages)
+ goto out_free_area;
+
+ addr = __pa(page_address(area->pages));
+
+ ret = -EIO;
+ if (rtas_call(ptcal_start_tok, 3, 1, NULL, area->nid,
+ (unsigned int)(addr >> 32),
+ (unsigned int)(addr & 0xffffffff))) {
+ printk(KERN_ERR "%s: error enabling PTCAL on node %d!\n",
+ __FUNCTION__, nid);
+ goto out_free_pages;
+ }
+
+ list_add(&area->list, &ptcal_list);
+
+ return 0;
+
+out_free_pages:
+ __free_pages(area->pages, area->order);
+out_free_area:
+ kfree(area);
+out_err:
+ return ret;
+}
+
+static int __init cbe_ptcal_enable(void)
+{
+ const u32 *size;
+ struct device_node *np;
+ int order, found_mic = 0;
+
+ np = of_find_node_by_path("/rtas");
+ if (!np)
+ return -ENODEV;
+
+ size = of_get_property(np, "ibm,cbe-ptcal-size", NULL);
+ if (!size)
+ return -ENODEV;
+
+ pr_debug("%s: enabling PTCAL, size = 0x%x\n", __FUNCTION__, *size);
+ order = get_order(*size);
+ of_node_put(np);
+
+ /* support for malta device trees, with be@/mic@ nodes */
+ for_each_node_by_type(np, "mic-tm") {
+ cbe_ptcal_enable_on_node(of_node_to_nid(np), order);
+ found_mic = 1;
+ }
+
+ if (found_mic)
+ return 0;
+
+ /* support for older device tree - use cpu nodes */
+ for_each_node_by_type(np, "cpu") {
+ const u32 *nid = of_get_property(np, "node-id", NULL);
+ if (!nid) {
+ printk(KERN_ERR "%s: node %s is missing node-id?\n",
+ __FUNCTION__, np->full_name);
+ continue;
+ }
+ cbe_ptcal_enable_on_node(*nid, order);
+ found_mic = 1;
+ }
+
+ return found_mic ? 0 : -ENODEV;
+}
+
+static int cbe_ptcal_disable(void)
+{
+ struct ptcal_area *area, *tmp;
+ int ret = 0;
+
+ pr_debug("%s: disabling PTCAL\n", __FUNCTION__);
+
+ list_for_each_entry_safe(area, tmp, &ptcal_list, list) {
+ /* disable ptcal on this node */
+ if (rtas_call(ptcal_stop_tok, 1, 1, NULL, area->nid)) {
+ printk(KERN_ERR "%s: error disabling PTCAL "
+ "on node %d!\n", __FUNCTION__,
+ area->nid);
+ ret = -EIO;
+ continue;
+ }
+
+ /* ensure we can access the PTCAL area */
+ memset(page_address(area->pages), 0,
+ 1 << (area->order + PAGE_SHIFT));
+
+ /* clean up */
+ list_del(&area->list);
+ __free_pages(area->pages, area->order);
+ kfree(area);
+ }
+
+ return ret;
+}
+
+static int cbe_ptcal_notify_reboot(struct notifier_block *nb,
+ unsigned long code, void *data)
+{
+ return cbe_ptcal_disable();
+}
+
+static struct notifier_block cbe_ptcal_reboot_notifier = {
+ .notifier_call = cbe_ptcal_notify_reboot
+};
+
+int __init cbe_ptcal_init(void)
+{
+ int ret;
+ ptcal_start_tok = rtas_token("ibm,cbe-start-ptcal");
+ ptcal_stop_tok = rtas_token("ibm,cbe-stop-ptcal");
+
+ if (ptcal_start_tok == RTAS_UNKNOWN_SERVICE
+ || ptcal_stop_tok == RTAS_UNKNOWN_SERVICE)
+ return -ENODEV;
+
+ ret = register_reboot_notifier(&cbe_ptcal_reboot_notifier);
+ if (ret) {
+ printk(KERN_ERR "Can't disable PTCAL, so not enabling\n");
+ return ret;
+ }
+
+ return cbe_ptcal_enable();
+}
+
+arch_initcall(cbe_ptcal_init);
+
void __init cbe_ras_init(void)
{
unsigned long hid0;
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index 36989c2eee66..54b96183cb64 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -71,7 +71,7 @@ static void cell_show_cpuinfo(struct seq_file *m)
root = of_find_node_by_path("/");
if (root)
- model = get_property(root, "model", NULL);
+ model = of_get_property(root, "model", NULL);
seq_printf(m, "machine\t\t: CHRP %s\n", model);
of_node_put(root);
}
@@ -190,15 +190,6 @@ static int __init cell_probe(void)
return 1;
}
-/*
- * Cell has no legacy IO; anything calling this function has to
- * fail or bad things will happen
- */
-static int cell_check_legacy_ioport(unsigned int baseport)
-{
- return -ENODEV;
-}
-
define_machine(cell) {
.name = "Cell",
.probe = cell_probe,
@@ -211,7 +202,6 @@ define_machine(cell) {
.get_rtc_time = rtas_get_rtc_time,
.set_rtc_time = rtas_set_rtc_time,
.calibrate_decr = generic_calibrate_decr,
- .check_legacy_ioport = cell_check_legacy_ioport,
.progress = cell_progress,
.init_IRQ = cell_init_irq,
.pci_setup_phb = rtas_setup_phb,
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index 21a9ebd4978e..fb1f15797bbb 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -254,25 +254,25 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic)
}
/* Now do the horrible hacks */
- tmp = get_property(pic->of_node, "#interrupt-cells", NULL);
+ tmp = of_get_property(pic->of_node, "#interrupt-cells", NULL);
if (tmp == NULL)
return NO_IRQ;
intsize = *tmp;
- imap = get_property(pic->of_node, "interrupt-map", &imaplen);
+ imap = of_get_property(pic->of_node, "interrupt-map", &imaplen);
if (imap == NULL || imaplen < (intsize + 1))
return NO_IRQ;
iic = of_find_node_by_phandle(imap[intsize]);
if (iic == NULL)
return NO_IRQ;
imap += intsize + 1;
- tmp = get_property(iic, "#interrupt-cells", NULL);
+ tmp = of_get_property(iic, "#interrupt-cells", NULL);
if (tmp == NULL)
return NO_IRQ;
intsize = *tmp;
/* Assume unit is last entry of interrupt specifier */
unit = imap[intsize - 1];
/* Ok, we have a unit, now let's try to get the node */
- tmp = get_property(iic, "ibm,interrupt-server-ranges", NULL);
+ tmp = of_get_property(iic, "ibm,interrupt-server-ranges", NULL);
if (tmp == NULL) {
of_node_put(iic);
return NO_IRQ;
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index c43999a10deb..fec51525252e 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -36,10 +36,65 @@
#include <asm/xmon.h>
const struct spu_management_ops *spu_management_ops;
+EXPORT_SYMBOL_GPL(spu_management_ops);
+
const struct spu_priv1_ops *spu_priv1_ops;
+static struct list_head spu_list[MAX_NUMNODES];
+static LIST_HEAD(spu_full_list);
+static DEFINE_MUTEX(spu_mutex);
+static DEFINE_SPINLOCK(spu_list_lock);
+
EXPORT_SYMBOL_GPL(spu_priv1_ops);
+void spu_invalidate_slbs(struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ if (spu_mfc_sr1_get(spu) & MFC_STATE1_RELOCATE_MASK)
+ out_be64(&priv2->slb_invalidate_all_W, 0UL);
+}
+EXPORT_SYMBOL_GPL(spu_invalidate_slbs);
+
+/* This is called by the MM core when a segment size is changed, to
+ * request a flush of all the SPEs using a given mm
+ */
+void spu_flush_all_slbs(struct mm_struct *mm)
+{
+ struct spu *spu;
+ unsigned long flags;
+
+ spin_lock_irqsave(&spu_list_lock, flags);
+ list_for_each_entry(spu, &spu_full_list, full_list) {
+ if (spu->mm == mm)
+ spu_invalidate_slbs(spu);
+ }
+ spin_unlock_irqrestore(&spu_list_lock, flags);
+}
+
+/* The hack below stinks... try to do something better one of
+ * these days... Does it even work properly with NR_CPUS == 1 ?
+ */
+static inline void mm_needs_global_tlbie(struct mm_struct *mm)
+{
+ int nr = (NR_CPUS > 1) ? NR_CPUS : NR_CPUS + 1;
+
+ /* Global TLBIE broadcast required with SPEs. */
+ __cpus_setall(&mm->cpu_vm_mask, nr);
+}
+
+void spu_associate_mm(struct spu *spu, struct mm_struct *mm)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&spu_list_lock, flags);
+ spu->mm = mm;
+ spin_unlock_irqrestore(&spu_list_lock, flags);
+ if (mm)
+ mm_needs_global_tlbie(mm);
+}
+EXPORT_SYMBOL_GPL(spu_associate_mm);
+
static int __spu_trap_invalid_dma(struct spu *spu)
{
pr_debug("%s\n", __FUNCTION__);
@@ -74,6 +129,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
struct spu_priv2 __iomem *priv2 = spu->priv2;
struct mm_struct *mm = spu->mm;
u64 esid, vsid, llp;
+ int psize;
pr_debug("%s\n", __FUNCTION__);
@@ -90,22 +146,25 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
case USER_REGION_ID:
#ifdef CONFIG_HUGETLB_PAGE
if (in_hugepage_area(mm->context, ea))
- llp = mmu_psize_defs[mmu_huge_psize].sllp;
+ psize = mmu_huge_psize;
else
#endif
- llp = mmu_psize_defs[mmu_virtual_psize].sllp;
+ psize = mm->context.user_psize;
vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) |
- SLB_VSID_USER | llp;
+ SLB_VSID_USER;
break;
case VMALLOC_REGION_ID:
- llp = mmu_psize_defs[mmu_virtual_psize].sllp;
+ if (ea < VMALLOC_END)
+ psize = mmu_vmalloc_psize;
+ else
+ psize = mmu_io_psize;
vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) |
- SLB_VSID_KERNEL | llp;
+ SLB_VSID_KERNEL;
break;
case KERNEL_REGION_ID:
- llp = mmu_psize_defs[mmu_linear_psize].sllp;
+ psize = mmu_linear_psize;
vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) |
- SLB_VSID_KERNEL | llp;
+ SLB_VSID_KERNEL;
break;
default:
/* Future: support kernel segments so that drivers
@@ -114,9 +173,10 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
pr_debug("invalid region access at %016lx\n", ea);
return 1;
}
+ llp = mmu_psize_defs[psize].sllp;
out_be64(&priv2->slb_index_W, spu->slb_replace);
- out_be64(&priv2->slb_vsid_RW, vsid);
+ out_be64(&priv2->slb_vsid_RW, vsid | llp);
out_be64(&priv2->slb_esid_RW, esid);
spu->slb_replace++;
@@ -232,7 +292,6 @@ spu_irq_class_1(int irq, void *data)
return stat ? IRQ_HANDLED : IRQ_NONE;
}
-EXPORT_SYMBOL_GPL(spu_irq_class_1_bottom);
static irqreturn_t
spu_irq_class_2(int irq, void *data)
@@ -330,10 +389,6 @@ static void spu_free_irqs(struct spu *spu)
free_irq(spu->irqs[2], spu);
}
-static struct list_head spu_list[MAX_NUMNODES];
-static LIST_HEAD(spu_full_list);
-static DEFINE_MUTEX(spu_mutex);
-
static void spu_init_channels(struct spu *spu)
{
static const struct {
@@ -377,10 +432,11 @@ struct spu *spu_alloc_node(int node)
spu = list_entry(spu_list[node].next, struct spu, list);
list_del_init(&spu->list);
pr_debug("Got SPU %d %d\n", spu->number, spu->node);
- spu_init_channels(spu);
}
mutex_unlock(&spu_mutex);
+ if (spu)
+ spu_init_channels(spu);
return spu;
}
EXPORT_SYMBOL_GPL(spu_alloc_node);
@@ -407,108 +463,6 @@ void spu_free(struct spu *spu)
}
EXPORT_SYMBOL_GPL(spu_free);
-static int spu_handle_mm_fault(struct spu *spu)
-{
- struct mm_struct *mm = spu->mm;
- struct vm_area_struct *vma;
- u64 ea, dsisr, is_write;
- int ret;
-
- ea = spu->dar;
- dsisr = spu->dsisr;
-#if 0
- if (!IS_VALID_EA(ea)) {
- return -EFAULT;
- }
-#endif /* XXX */
- if (mm == NULL) {
- return -EFAULT;
- }
- if (mm->pgd == NULL) {
- return -EFAULT;
- }
-
- down_read(&mm->mmap_sem);
- vma = find_vma(mm, ea);
- if (!vma)
- goto bad_area;
- if (vma->vm_start <= ea)
- goto good_area;
- if (!(vma->vm_flags & VM_GROWSDOWN))
- goto bad_area;
-#if 0
- if (expand_stack(vma, ea))
- goto bad_area;
-#endif /* XXX */
-good_area:
- is_write = dsisr & MFC_DSISR_ACCESS_PUT;
- if (is_write) {
- if (!(vma->vm_flags & VM_WRITE))
- goto bad_area;
- } else {
- if (dsisr & MFC_DSISR_ACCESS_DENIED)
- goto bad_area;
- if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
- goto bad_area;
- }
- ret = 0;
- switch (handle_mm_fault(mm, vma, ea, is_write)) {
- case VM_FAULT_MINOR:
- current->min_flt++;
- break;
- case VM_FAULT_MAJOR:
- current->maj_flt++;
- break;
- case VM_FAULT_SIGBUS:
- ret = -EFAULT;
- goto bad_area;
- case VM_FAULT_OOM:
- ret = -ENOMEM;
- goto bad_area;
- default:
- BUG();
- }
- up_read(&mm->mmap_sem);
- return ret;
-
-bad_area:
- up_read(&mm->mmap_sem);
- return -EFAULT;
-}
-
-int spu_irq_class_1_bottom(struct spu *spu)
-{
- u64 ea, dsisr, access, error = 0UL;
- int ret = 0;
-
- ea = spu->dar;
- dsisr = spu->dsisr;
- if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) {
- u64 flags;
-
- access = (_PAGE_PRESENT | _PAGE_USER);
- access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL;
- local_irq_save(flags);
- if (hash_page(ea, access, 0x300) != 0)
- error |= CLASS1_ENABLE_STORAGE_FAULT_INTR;
- local_irq_restore(flags);
- }
- if (error & CLASS1_ENABLE_STORAGE_FAULT_INTR) {
- if ((ret = spu_handle_mm_fault(spu)) != 0)
- error |= CLASS1_ENABLE_STORAGE_FAULT_INTR;
- else
- error &= ~CLASS1_ENABLE_STORAGE_FAULT_INTR;
- }
- spu->dar = 0UL;
- spu->dsisr = 0UL;
- if (!error) {
- spu_restart_dma(spu);
- } else {
- spu->dma_callback(spu, SPE_EVENT_SPE_DATA_STORAGE);
- }
- return ret;
-}
-
struct sysdev_class spu_sysdev_class = {
set_kset_name("spu")
};
@@ -582,17 +536,12 @@ static int spu_create_sysdev(struct spu *spu)
return 0;
}
-static void spu_destroy_sysdev(struct spu *spu)
-{
- sysfs_remove_device_from_node(&spu->sysdev, spu->node);
- sysdev_unregister(&spu->sysdev);
-}
-
static int __init create_spu(void *data)
{
struct spu *spu;
int ret;
static int number;
+ unsigned long flags;
ret = -ENOMEM;
spu = kzalloc(sizeof (*spu), GFP_KERNEL);
@@ -620,8 +569,10 @@ static int __init create_spu(void *data)
goto out_free_irqs;
mutex_lock(&spu_mutex);
+ spin_lock_irqsave(&spu_list_lock, flags);
list_add(&spu->list, &spu_list[spu->node]);
list_add(&spu->full_list, &spu_full_list);
+ spin_unlock_irqrestore(&spu_list_lock, flags);
mutex_unlock(&spu_mutex);
goto out;
@@ -636,58 +587,37 @@ out:
return ret;
}
-static void destroy_spu(struct spu *spu)
-{
- list_del_init(&spu->list);
- list_del_init(&spu->full_list);
-
- spu_destroy_sysdev(spu);
- spu_free_irqs(spu);
- spu_destroy_spu(spu);
- kfree(spu);
-}
-
-static void cleanup_spu_base(void)
-{
- struct spu *spu, *tmp;
- int node;
-
- mutex_lock(&spu_mutex);
- for (node = 0; node < MAX_NUMNODES; node++) {
- list_for_each_entry_safe(spu, tmp, &spu_list[node], list)
- destroy_spu(spu);
- }
- mutex_unlock(&spu_mutex);
- sysdev_class_unregister(&spu_sysdev_class);
-}
-module_exit(cleanup_spu_base);
-
static int __init init_spu_base(void)
{
- int i, ret;
+ int i, ret = 0;
+
+ for (i = 0; i < MAX_NUMNODES; i++)
+ INIT_LIST_HEAD(&spu_list[i]);
if (!spu_management_ops)
- return 0;
+ goto out;
/* create sysdev class for spus */
ret = sysdev_class_register(&spu_sysdev_class);
if (ret)
- return ret;
-
- for (i = 0; i < MAX_NUMNODES; i++)
- INIT_LIST_HEAD(&spu_list[i]);
+ goto out;
ret = spu_enumerate_spus(create_spu);
if (ret) {
printk(KERN_WARNING "%s: Error initializing spus\n",
__FUNCTION__);
- cleanup_spu_base();
- return ret;
+ goto out_unregister_sysdev_class;
}
xmon_register_spus(&spu_full_list);
+ return 0;
+
+ out_unregister_sysdev_class:
+ sysdev_class_unregister(&spu_sysdev_class);
+ out:
+
return ret;
}
module_init(init_spu_base);
diff --git a/arch/powerpc/platforms/cell/spu_coredump.c b/arch/powerpc/platforms/cell/spu_coredump.c
index 6915b418ee73..4fd37ff1e210 100644
--- a/arch/powerpc/platforms/cell/spu_coredump.c
+++ b/arch/powerpc/platforms/cell/spu_coredump.c
@@ -26,19 +26,18 @@
#include <asm/spu.h>
-static struct spu_coredump_calls spu_coredump_calls;
+static struct spu_coredump_calls *spu_coredump_calls;
static DEFINE_MUTEX(spu_coredump_mutex);
int arch_notes_size(void)
{
long ret;
- struct module *owner = spu_coredump_calls.owner;
ret = -ENOSYS;
mutex_lock(&spu_coredump_mutex);
- if (owner && try_module_get(owner)) {
- ret = spu_coredump_calls.arch_notes_size();
- module_put(owner);
+ if (spu_coredump_calls && try_module_get(spu_coredump_calls->owner)) {
+ ret = spu_coredump_calls->arch_notes_size();
+ module_put(spu_coredump_calls->owner);
}
mutex_unlock(&spu_coredump_mutex);
return ret;
@@ -46,36 +45,35 @@ int arch_notes_size(void)
void arch_write_notes(struct file *file)
{
- struct module *owner = spu_coredump_calls.owner;
-
mutex_lock(&spu_coredump_mutex);
- if (owner && try_module_get(owner)) {
- spu_coredump_calls.arch_write_notes(file);
- module_put(owner);
+ if (spu_coredump_calls && try_module_get(spu_coredump_calls->owner)) {
+ spu_coredump_calls->arch_write_notes(file);
+ module_put(spu_coredump_calls->owner);
}
mutex_unlock(&spu_coredump_mutex);
}
int register_arch_coredump_calls(struct spu_coredump_calls *calls)
{
- if (spu_coredump_calls.owner)
- return -EBUSY;
+ int ret = 0;
+
mutex_lock(&spu_coredump_mutex);
- spu_coredump_calls.arch_notes_size = calls->arch_notes_size;
- spu_coredump_calls.arch_write_notes = calls->arch_write_notes;
- spu_coredump_calls.owner = calls->owner;
+ if (spu_coredump_calls)
+ ret = -EBUSY;
+ else
+ spu_coredump_calls = calls;
mutex_unlock(&spu_coredump_mutex);
- return 0;
+ return ret;
}
EXPORT_SYMBOL_GPL(register_arch_coredump_calls);
void unregister_arch_coredump_calls(struct spu_coredump_calls *calls)
{
- BUG_ON(spu_coredump_calls.owner != calls->owner);
+ BUG_ON(spu_coredump_calls != calls);
mutex_lock(&spu_coredump_mutex);
- spu_coredump_calls.owner = NULL;
+ spu_coredump_calls = NULL;
mutex_unlock(&spu_coredump_mutex);
}
EXPORT_SYMBOL_GPL(unregister_arch_coredump_calls);
diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c
index e34599f53d28..1d4562ae463d 100644
--- a/arch/powerpc/platforms/cell/spu_manage.c
+++ b/arch/powerpc/platforms/cell/spu_manage.c
@@ -48,11 +48,11 @@ static u64 __init find_spu_unit_number(struct device_node *spe)
{
const unsigned int *prop;
int proplen;
- prop = get_property(spe, "unit-id", &proplen);
+ prop = of_get_property(spe, "unit-id", &proplen);
if (proplen == 4)
return (u64)*prop;
- prop = get_property(spe, "reg", &proplen);
+ prop = of_get_property(spe, "reg", &proplen);
if (proplen == 4)
return (u64)*prop;
@@ -76,12 +76,12 @@ static int __init spu_map_interrupts_old(struct spu *spu,
int nid;
/* Get the interrupt source unit from the device-tree */
- tmp = get_property(np, "isrc", NULL);
+ tmp = of_get_property(np, "isrc", NULL);
if (!tmp)
return -ENODEV;
isrc = tmp[0];
- tmp = get_property(np->parent->parent, "node-id", NULL);
+ tmp = of_get_property(np->parent->parent, "node-id", NULL);
if (!tmp) {
printk(KERN_WARNING "%s: can't find node-id\n", __FUNCTION__);
nid = spu->node;
@@ -110,7 +110,7 @@ static void __iomem * __init spu_map_prop_old(struct spu *spu,
} __attribute__((packed)) *prop;
int proplen;
- prop = get_property(n, name, &proplen);
+ prop = of_get_property(n, name, &proplen);
if (prop == NULL || proplen != sizeof (struct address_prop))
return NULL;
@@ -124,11 +124,11 @@ static int __init spu_map_device_old(struct spu *spu)
int ret;
ret = -ENODEV;
- spu->name = get_property(node, "name", NULL);
+ spu->name = of_get_property(node, "name", NULL);
if (!spu->name)
goto out;
- prop = get_property(node, "local-store", NULL);
+ prop = of_get_property(node, "local-store", NULL);
if (!prop)
goto out;
spu->local_store_phys = *(unsigned long *)prop;
@@ -139,7 +139,7 @@ static int __init spu_map_device_old(struct spu *spu)
if (!spu->local_store)
goto out;
- prop = get_property(node, "problem", NULL);
+ prop = of_get_property(node, "problem", NULL);
if (!prop)
goto out_unmap;
spu->problem_phys = *(unsigned long *)prop;
@@ -226,7 +226,7 @@ static int __init spu_map_device(struct spu *spu)
struct device_node *np = spu->devnode;
int ret = -ENODEV;
- spu->name = get_property(np, "name", NULL);
+ spu->name = of_get_property(np, "name", NULL);
if (!spu->name)
goto out;
diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile
index 472217d19faf..2cd89c11af5a 100644
--- a/arch/powerpc/platforms/cell/spufs/Makefile
+++ b/arch/powerpc/platforms/cell/spufs/Makefile
@@ -1,4 +1,4 @@
-obj-y += switch.o
+obj-y += switch.o fault.o
obj-$(CONFIG_SPU_FS) += spufs.o
spufs-y += inode.o file.o context.o syscalls.o coredump.o
diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c
index 1898f0d3a8b8..3322528fa6eb 100644
--- a/arch/powerpc/platforms/cell/spufs/backing_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c
@@ -350,6 +350,11 @@ static int spu_backing_send_mfc_command(struct spu_context *ctx,
return ret;
}
+static void spu_backing_restart_dma(struct spu_context *ctx)
+{
+ /* nothing to do here */
+}
+
struct spu_context_ops spu_backing_ops = {
.mbox_read = spu_backing_mbox_read,
.mbox_stat_read = spu_backing_mbox_stat_read,
@@ -376,4 +381,5 @@ struct spu_context_ops spu_backing_ops = {
.read_mfc_tagstatus = spu_backing_read_mfc_tagstatus,
.get_mfc_free_elements = spu_backing_get_mfc_free_elements,
.send_mfc_command = spu_backing_send_mfc_command,
+ .restart_dma = spu_backing_restart_dma,
};
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 04ad2e364e97..a87d9ca3dba2 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -41,9 +41,10 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
goto out_free;
}
spin_lock_init(&ctx->mmio_lock);
+ spin_lock_init(&ctx->mapping_lock);
kref_init(&ctx->kref);
mutex_init(&ctx->state_mutex);
- init_MUTEX(&ctx->run_sema);
+ mutex_init(&ctx->run_mutex);
init_waitqueue_head(&ctx->ibox_wq);
init_waitqueue_head(&ctx->wbox_wq);
init_waitqueue_head(&ctx->stop_wq);
@@ -51,6 +52,7 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
ctx->state = SPU_STATE_SAVED;
ctx->ops = &spu_backing_ops;
ctx->owner = get_task_mm(current);
+ INIT_LIST_HEAD(&ctx->rq);
if (gang)
spu_gang_add_ctx(gang, ctx);
ctx->rt_priority = current->rt_priority;
@@ -75,6 +77,7 @@ void destroy_spu_context(struct kref *kref)
spu_fini_csa(&ctx->csa);
if (ctx->gang)
spu_gang_remove_ctx(ctx->gang, ctx);
+ BUG_ON(!list_empty(&ctx->rq));
kfree(ctx);
}
@@ -119,46 +122,6 @@ void spu_unmap_mappings(struct spu_context *ctx)
}
/**
- * spu_acquire_exclusive - lock spu contex and protect against userspace access
- * @ctx: spu contex to lock
- *
- * Note:
- * Returns 0 and with the context locked on success
- * Returns negative error and with the context _unlocked_ on failure.
- */
-int spu_acquire_exclusive(struct spu_context *ctx)
-{
- int ret = -EINVAL;
-
- spu_acquire(ctx);
- /*
- * Context is about to be freed, so we can't acquire it anymore.
- */
- if (!ctx->owner)
- goto out_unlock;
-
- if (ctx->state == SPU_STATE_SAVED) {
- ret = spu_activate(ctx, 0);
- if (ret)
- goto out_unlock;
- } else {
- /*
- * We need to exclude userspace access to the context.
- *
- * To protect against memory access we invalidate all ptes
- * and make sure the pagefault handlers block on the mutex.
- */
- spu_unmap_mappings(ctx);
- }
-
- return 0;
-
- out_unlock:
- spu_release(ctx);
- return ret;
-}
-
-/**
* spu_acquire_runnable - lock spu contex and make sure it is in runnable state
* @ctx: spu contex to lock
*
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 725e19561159..5d9ad5a0307b 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -169,12 +169,12 @@ static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i,
struct spu_context *ctx;
loff_t pos = 0;
int sz, dfd, rc, total = 0;
- const int bufsz = 4096;
+ const int bufsz = PAGE_SIZE;
char *name;
char fullname[80], *buf;
struct elf_note en;
- buf = kmalloc(bufsz, GFP_KERNEL);
+ buf = (void *)get_zeroed_page(GFP_KERNEL);
if (!buf)
return;
@@ -187,9 +187,8 @@ static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i,
sz = spufs_coredump_read[i].size;
ctx = ctx_info->ctx;
- if (!ctx) {
- return;
- }
+ if (!ctx)
+ goto out;
sprintf(fullname, "SPU/%d/%s", dfd, name);
en.n_namesz = strlen(fullname) + 1;
@@ -197,23 +196,25 @@ static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i,
en.n_type = NT_SPU;
if (!spufs_dump_write(file, &en, sizeof(en)))
- return;
+ goto out;
if (!spufs_dump_write(file, fullname, en.n_namesz))
- return;
+ goto out;
if (!spufs_dump_seek(file, roundup((unsigned long)file->f_pos, 4)))
- return;
+ goto out;
do {
rc = do_coredump_read(i, ctx, buf, bufsz, &pos);
if (rc > 0) {
if (!spufs_dump_write(file, buf, rc))
- return;
+ goto out;
total += rc;
}
} while (rc == bufsz && total < sz);
spufs_dump_seek(file, roundup((unsigned long)file->f_pos
- total + sz, 4));
+out:
+ free_page((unsigned long)buf);
}
static void spufs_arch_write_notes(struct file *file)
diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c
new file mode 100644
index 000000000000..0f75c07e29d8
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/fault.c
@@ -0,0 +1,211 @@
+/*
+ * Low-level SPU handling
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * Author: Arnd Bergmann <arndb@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+
+#include <asm/spu.h>
+#include <asm/spu_csa.h>
+
+#include "spufs.h"
+
+/*
+ * This ought to be kept in sync with the powerpc specific do_page_fault
+ * function. Currently, there are a few corner cases that we haven't had
+ * to handle fortunately.
+ */
+static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, unsigned long dsisr)
+{
+ struct vm_area_struct *vma;
+ unsigned long is_write;
+ int ret;
+
+#if 0
+ if (!IS_VALID_EA(ea)) {
+ return -EFAULT;
+ }
+#endif /* XXX */
+ if (mm == NULL) {
+ return -EFAULT;
+ }
+ if (mm->pgd == NULL) {
+ return -EFAULT;
+ }
+
+ down_read(&mm->mmap_sem);
+ vma = find_vma(mm, ea);
+ if (!vma)
+ goto bad_area;
+ if (vma->vm_start <= ea)
+ goto good_area;
+ if (!(vma->vm_flags & VM_GROWSDOWN))
+ goto bad_area;
+ if (expand_stack(vma, ea))
+ goto bad_area;
+good_area:
+ is_write = dsisr & MFC_DSISR_ACCESS_PUT;
+ if (is_write) {
+ if (!(vma->vm_flags & VM_WRITE))
+ goto bad_area;
+ } else {
+ if (dsisr & MFC_DSISR_ACCESS_DENIED)
+ goto bad_area;
+ if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ goto bad_area;
+ }
+ ret = 0;
+ switch (handle_mm_fault(mm, vma, ea, is_write)) {
+ case VM_FAULT_MINOR:
+ current->min_flt++;
+ break;
+ case VM_FAULT_MAJOR:
+ current->maj_flt++;
+ break;
+ case VM_FAULT_SIGBUS:
+ ret = -EFAULT;
+ goto bad_area;
+ case VM_FAULT_OOM:
+ ret = -ENOMEM;
+ goto bad_area;
+ default:
+ BUG();
+ }
+ up_read(&mm->mmap_sem);
+ return ret;
+
+bad_area:
+ up_read(&mm->mmap_sem);
+ return -EFAULT;
+}
+
+static void spufs_handle_dma_error(struct spu_context *ctx,
+ unsigned long ea, int type)
+{
+ if (ctx->flags & SPU_CREATE_EVENTS_ENABLED) {
+ ctx->event_return |= type;
+ wake_up_all(&ctx->stop_wq);
+ } else {
+ siginfo_t info;
+ memset(&info, 0, sizeof(info));
+
+ switch (type) {
+ case SPE_EVENT_INVALID_DMA:
+ info.si_signo = SIGBUS;
+ info.si_code = BUS_OBJERR;
+ break;
+ case SPE_EVENT_SPE_DATA_STORAGE:
+ info.si_signo = SIGBUS;
+ info.si_addr = (void __user *)ea;
+ info.si_code = BUS_ADRERR;
+ break;
+ case SPE_EVENT_DMA_ALIGNMENT:
+ info.si_signo = SIGBUS;
+ /* DAR isn't set for an alignment fault :( */
+ info.si_code = BUS_ADRALN;
+ break;
+ case SPE_EVENT_SPE_ERROR:
+ info.si_signo = SIGILL;
+ info.si_addr = (void __user *)(unsigned long)
+ ctx->ops->npc_read(ctx) - 4;
+ info.si_code = ILL_ILLOPC;
+ break;
+ }
+ if (info.si_signo)
+ force_sig_info(info.si_signo, &info, current);
+ }
+}
+
+void spufs_dma_callback(struct spu *spu, int type)
+{
+ spufs_handle_dma_error(spu->ctx, spu->dar, type);
+}
+EXPORT_SYMBOL_GPL(spufs_dma_callback);
+
+/*
+ * bottom half handler for page faults, we can't do this from
+ * interrupt context, since we might need to sleep.
+ * we also need to give up the mutex so we can get scheduled
+ * out while waiting for the backing store.
+ *
+ * TODO: try calling hash_page from the interrupt handler first
+ * in order to speed up the easy case.
+ */
+int spufs_handle_class1(struct spu_context *ctx)
+{
+ u64 ea, dsisr, access;
+ unsigned long flags;
+ int ret;
+
+ /*
+ * dar and dsisr get passed from the registers
+ * to the spu_context, to this function, but not
+ * back to the spu if it gets scheduled again.
+ *
+ * if we don't handle the fault for a saved context
+ * in time, we can still expect to get the same fault
+ * the immediately after the context restore.
+ */
+ if (ctx->state == SPU_STATE_RUNNABLE) {
+ ea = ctx->spu->dar;
+ dsisr = ctx->spu->dsisr;
+ ctx->spu->dar= ctx->spu->dsisr = 0;
+ } else {
+ ea = ctx->csa.priv1.mfc_dar_RW;
+ dsisr = ctx->csa.priv1.mfc_dsisr_RW;
+ ctx->csa.priv1.mfc_dar_RW = 0;
+ ctx->csa.priv1.mfc_dsisr_RW = 0;
+ }
+
+ if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)))
+ return 0;
+
+ pr_debug("ctx %p: ea %016lx, dsisr %016lx state %d\n", ctx, ea,
+ dsisr, ctx->state);
+
+ /* we must not hold the lock when entering spu_handle_mm_fault */
+ spu_release(ctx);
+
+ access = (_PAGE_PRESENT | _PAGE_USER);
+ access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL;
+ local_irq_save(flags);
+ ret = hash_page(ea, access, 0x300);
+ local_irq_restore(flags);
+
+ /* hashing failed, so try the actual fault handler */
+ if (ret)
+ ret = spu_handle_mm_fault(current->mm, ea, dsisr);
+
+ spu_acquire(ctx);
+ /*
+ * If we handled the fault successfully and are in runnable
+ * state, restart the DMA.
+ * In case of unhandled error report the problem to user space.
+ */
+ if (!ret) {
+ if (ctx->spu)
+ ctx->ops->restart_dma(ctx);
+ } else
+ spufs_handle_dma_error(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(spufs_handle_class1);
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index b00653d69c01..d010b2464a98 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -44,9 +44,25 @@ spufs_mem_open(struct inode *inode, struct file *file)
{
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;
+
+ spin_lock(&ctx->mapping_lock);
file->private_data = ctx;
- ctx->local_store = inode->i_mapping;
- smp_wmb();
+ if (!i->i_openers++)
+ ctx->local_store = inode->i_mapping;
+ spin_unlock(&ctx->mapping_lock);
+ return 0;
+}
+
+static int
+spufs_mem_release(struct inode *inode, struct file *file)
+{
+ struct spufs_inode_info *i = SPUFS_I(inode);
+ struct spu_context *ctx = i->i_ctx;
+
+ spin_lock(&ctx->mapping_lock);
+ if (!--i->i_openers)
+ ctx->local_store = NULL;
+ spin_unlock(&ctx->mapping_lock);
return 0;
}
@@ -63,8 +79,8 @@ static ssize_t
spufs_mem_read(struct file *file, char __user *buffer,
size_t size, loff_t *pos)
{
- int ret;
struct spu_context *ctx = file->private_data;
+ ssize_t ret;
spu_acquire(ctx);
ret = __spufs_mem_read(ctx, buffer, size, pos);
@@ -74,25 +90,29 @@ spufs_mem_read(struct file *file, char __user *buffer,
static ssize_t
spufs_mem_write(struct file *file, const char __user *buffer,
- size_t size, loff_t *pos)
+ size_t size, loff_t *ppos)
{
struct spu_context *ctx = file->private_data;
char *local_store;
+ loff_t pos = *ppos;
int ret;
- size = min_t(ssize_t, LS_SIZE - *pos, size);
- if (size <= 0)
+ if (pos < 0)
+ return -EINVAL;
+ if (pos > LS_SIZE)
return -EFBIG;
- *pos += size;
+ if (size > LS_SIZE - pos)
+ size = LS_SIZE - pos;
spu_acquire(ctx);
-
local_store = ctx->ops->get_ls(ctx);
- ret = copy_from_user(local_store + *pos - size,
- buffer, size) ? -EFAULT : size;
-
+ ret = copy_from_user(local_store + pos, buffer, size);
spu_release(ctx);
- return ret;
+
+ if (ret)
+ return -EFAULT;
+ *ppos = pos + size;
+ return size;
}
static unsigned long spufs_mem_mmap_nopfn(struct vm_area_struct *vma,
@@ -145,6 +165,7 @@ spufs_mem_mmap(struct file *file, struct vm_area_struct *vma)
static const struct file_operations spufs_mem_fops = {
.open = spufs_mem_open,
+ .release = spufs_mem_release,
.read = spufs_mem_read,
.write = spufs_mem_write,
.llseek = generic_file_llseek,
@@ -234,16 +255,33 @@ static int spufs_cntl_open(struct inode *inode, struct file *file)
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;
+ spin_lock(&ctx->mapping_lock);
file->private_data = ctx;
- ctx->cntl = inode->i_mapping;
- smp_wmb();
+ if (!i->i_openers++)
+ ctx->cntl = inode->i_mapping;
+ spin_unlock(&ctx->mapping_lock);
return simple_attr_open(inode, file, spufs_cntl_get,
spufs_cntl_set, "0x%08lx");
}
+static int
+spufs_cntl_release(struct inode *inode, struct file *file)
+{
+ struct spufs_inode_info *i = SPUFS_I(inode);
+ struct spu_context *ctx = i->i_ctx;
+
+ simple_attr_close(inode, file);
+
+ spin_lock(&ctx->mapping_lock);
+ if (!--i->i_openers)
+ ctx->cntl = NULL;
+ spin_unlock(&ctx->mapping_lock);
+ return 0;
+}
+
static const struct file_operations spufs_cntl_fops = {
.open = spufs_cntl_open,
- .release = simple_attr_close,
+ .release = spufs_cntl_release,
.read = simple_attr_read,
.write = simple_attr_write,
.mmap = spufs_cntl_mmap,
@@ -719,12 +757,28 @@ static int spufs_signal1_open(struct inode *inode, struct file *file)
{
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;
+
+ spin_lock(&ctx->mapping_lock);
file->private_data = ctx;
- ctx->signal1 = inode->i_mapping;
- smp_wmb();
+ if (!i->i_openers++)
+ ctx->signal1 = inode->i_mapping;
+ spin_unlock(&ctx->mapping_lock);
return nonseekable_open(inode, file);
}
+static int
+spufs_signal1_release(struct inode *inode, struct file *file)
+{
+ struct spufs_inode_info *i = SPUFS_I(inode);
+ struct spu_context *ctx = i->i_ctx;
+
+ spin_lock(&ctx->mapping_lock);
+ if (!--i->i_openers)
+ ctx->signal1 = NULL;
+ spin_unlock(&ctx->mapping_lock);
+ return 0;
+}
+
static ssize_t __spufs_signal1_read(struct spu_context *ctx, char __user *buf,
size_t len, loff_t *pos)
{
@@ -817,6 +871,7 @@ static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma)
static const struct file_operations spufs_signal1_fops = {
.open = spufs_signal1_open,
+ .release = spufs_signal1_release,
.read = spufs_signal1_read,
.write = spufs_signal1_write,
.mmap = spufs_signal1_mmap,
@@ -826,12 +881,28 @@ static int spufs_signal2_open(struct inode *inode, struct file *file)
{
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;
+
+ spin_lock(&ctx->mapping_lock);
file->private_data = ctx;
- ctx->signal2 = inode->i_mapping;
- smp_wmb();
+ if (!i->i_openers++)
+ ctx->signal2 = inode->i_mapping;
+ spin_unlock(&ctx->mapping_lock);
return nonseekable_open(inode, file);
}
+static int
+spufs_signal2_release(struct inode *inode, struct file *file)
+{
+ struct spufs_inode_info *i = SPUFS_I(inode);
+ struct spu_context *ctx = i->i_ctx;
+
+ spin_lock(&ctx->mapping_lock);
+ if (!--i->i_openers)
+ ctx->signal2 = NULL;
+ spin_unlock(&ctx->mapping_lock);
+ return 0;
+}
+
static ssize_t __spufs_signal2_read(struct spu_context *ctx, char __user *buf,
size_t len, loff_t *pos)
{
@@ -928,6 +999,7 @@ static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma)
static const struct file_operations spufs_signal2_fops = {
.open = spufs_signal2_open,
+ .release = spufs_signal2_release,
.read = spufs_signal2_read,
.write = spufs_signal2_write,
.mmap = spufs_signal2_mmap,
@@ -1027,13 +1099,30 @@ static int spufs_mss_open(struct inode *inode, struct file *file)
struct spu_context *ctx = i->i_ctx;
file->private_data = i->i_ctx;
- ctx->mss = inode->i_mapping;
- smp_wmb();
+
+ spin_lock(&ctx->mapping_lock);
+ if (!i->i_openers++)
+ ctx->mss = inode->i_mapping;
+ spin_unlock(&ctx->mapping_lock);
return nonseekable_open(inode, file);
}
+static int
+spufs_mss_release(struct inode *inode, struct file *file)
+{
+ struct spufs_inode_info *i = SPUFS_I(inode);
+ struct spu_context *ctx = i->i_ctx;
+
+ spin_lock(&ctx->mapping_lock);
+ if (!--i->i_openers)
+ ctx->mss = NULL;
+ spin_unlock(&ctx->mapping_lock);
+ return 0;
+}
+
static const struct file_operations spufs_mss_fops = {
.open = spufs_mss_open,
+ .release = spufs_mss_release,
.mmap = spufs_mss_mmap,
};
@@ -1068,14 +1157,30 @@ static int spufs_psmap_open(struct inode *inode, struct file *file)
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;
+ spin_lock(&ctx->mapping_lock);
file->private_data = i->i_ctx;
- ctx->psmap = inode->i_mapping;
- smp_wmb();
+ if (!i->i_openers++)
+ ctx->psmap = inode->i_mapping;
+ spin_unlock(&ctx->mapping_lock);
return nonseekable_open(inode, file);
}
+static int
+spufs_psmap_release(struct inode *inode, struct file *file)
+{
+ struct spufs_inode_info *i = SPUFS_I(inode);
+ struct spu_context *ctx = i->i_ctx;
+
+ spin_lock(&ctx->mapping_lock);
+ if (!--i->i_openers)
+ ctx->psmap = NULL;
+ spin_unlock(&ctx->mapping_lock);
+ return 0;
+}
+
static const struct file_operations spufs_psmap_fops = {
.open = spufs_psmap_open,
+ .release = spufs_psmap_release,
.mmap = spufs_psmap_mmap,
};
@@ -1122,12 +1227,27 @@ static int spufs_mfc_open(struct inode *inode, struct file *file)
if (atomic_read(&inode->i_count) != 1)
return -EBUSY;
+ spin_lock(&ctx->mapping_lock);
file->private_data = ctx;
- ctx->mfc = inode->i_mapping;
- smp_wmb();
+ if (!i->i_openers++)
+ ctx->mfc = inode->i_mapping;
+ spin_unlock(&ctx->mapping_lock);
return nonseekable_open(inode, file);
}
+static int
+spufs_mfc_release(struct inode *inode, struct file *file)
+{
+ struct spufs_inode_info *i = SPUFS_I(inode);
+ struct spu_context *ctx = i->i_ctx;
+
+ spin_lock(&ctx->mapping_lock);
+ if (!--i->i_openers)
+ ctx->mfc = NULL;
+ spin_unlock(&ctx->mapping_lock);
+ return 0;
+}
+
/* interrupt-level mfc callback function. */
void spufs_mfc_callback(struct spu *spu)
{
@@ -1309,7 +1429,10 @@ static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer,
if (ret)
goto out;
- spu_acquire_runnable(ctx, 0);
+ ret = spu_acquire_runnable(ctx, 0);
+ if (ret)
+ goto out;
+
if (file->f_flags & O_NONBLOCK) {
ret = ctx->ops->send_mfc_command(ctx, &cmd);
} else {
@@ -1395,6 +1518,7 @@ static int spufs_mfc_fasync(int fd, struct file *file, int on)
static const struct file_operations spufs_mfc_fops = {
.open = spufs_mfc_open,
+ .release = spufs_mfc_release,
.read = spufs_mfc_read,
.write = spufs_mfc_write,
.poll = spufs_mfc_poll,
diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c
index ae42e03b8c86..428875c5e4ec 100644
--- a/arch/powerpc/platforms/cell/spufs/hw_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c
@@ -296,6 +296,14 @@ static int spu_hw_send_mfc_command(struct spu_context *ctx,
}
}
+static void spu_hw_restart_dma(struct spu_context *ctx)
+{
+ struct spu_priv2 __iomem *priv2 = ctx->spu->priv2;
+
+ if (!test_bit(SPU_CONTEXT_SWITCH_PENDING, &ctx->spu->flags))
+ out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND);
+}
+
struct spu_context_ops spu_hw_ops = {
.mbox_read = spu_hw_mbox_read,
.mbox_stat_read = spu_hw_mbox_stat_read,
@@ -320,4 +328,5 @@ struct spu_context_ops spu_hw_ops = {
.read_mfc_tagstatus = spu_hw_read_mfc_tagstatus,
.get_mfc_free_elements = spu_hw_get_mfc_free_elements,
.send_mfc_command = spu_hw_send_mfc_command,
+ .restart_dma = spu_hw_restart_dma,
};
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 8079983ef94f..13e4f70ec8c0 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -36,6 +36,7 @@
#include <asm/prom.h>
#include <asm/semaphore.h>
#include <asm/spu.h>
+#include <asm/spu_priv1.h>
#include <asm/uaccess.h>
#include "spufs.h"
@@ -54,6 +55,7 @@ spufs_alloc_inode(struct super_block *sb)
ei->i_gang = NULL;
ei->i_ctx = NULL;
+ ei->i_openers = 0;
return &ei->vfs_inode;
}
@@ -520,13 +522,14 @@ out:
/* File system initialization */
enum {
- Opt_uid, Opt_gid, Opt_err,
+ Opt_uid, Opt_gid, Opt_mode, Opt_err,
};
static match_table_t spufs_tokens = {
- { Opt_uid, "uid=%d" },
- { Opt_gid, "gid=%d" },
- { Opt_err, NULL },
+ { Opt_uid, "uid=%d" },
+ { Opt_gid, "gid=%d" },
+ { Opt_mode, "mode=%o" },
+ { Opt_err, NULL },
};
static int
@@ -553,6 +556,11 @@ spufs_parse_options(char *options, struct inode *root)
return 0;
root->i_gid = option;
break;
+ case Opt_mode:
+ if (match_octal(&args[0], &option))
+ return 0;
+ root->i_mode = option | S_IFDIR;
+ break;
default:
return 0;
}
@@ -560,6 +568,11 @@ spufs_parse_options(char *options, struct inode *root)
return 1;
}
+static void spufs_exit_isolated_loader(void)
+{
+ kfree(isolated_loader);
+}
+
static void
spufs_init_isolated_loader(void)
{
@@ -571,7 +584,7 @@ spufs_init_isolated_loader(void)
if (!dn)
return;
- loader = get_property(dn, "loader", &size);
+ loader = of_get_property(dn, "loader", &size);
if (!loader)
return;
@@ -653,6 +666,10 @@ static int __init spufs_init(void)
{
int ret;
+ ret = -ENODEV;
+ if (!spu_management_ops)
+ goto out;
+
ret = -ENOMEM;
spufs_inode_cache = kmem_cache_create("spufs_inode_cache",
sizeof(struct spufs_inode_info), 0,
@@ -660,25 +677,29 @@ static int __init spufs_init(void)
if (!spufs_inode_cache)
goto out;
- if (spu_sched_init() != 0) {
- kmem_cache_destroy(spufs_inode_cache);
- goto out;
- }
- ret = register_filesystem(&spufs_type);
+ ret = spu_sched_init();
if (ret)
goto out_cache;
+ ret = register_filesystem(&spufs_type);
+ if (ret)
+ goto out_sched;
ret = register_spu_syscalls(&spufs_calls);
if (ret)
goto out_fs;
ret = register_arch_coredump_calls(&spufs_coredump_calls);
if (ret)
- goto out_fs;
+ goto out_syscalls;
spufs_init_isolated_loader();
return 0;
+
+out_syscalls:
+ unregister_spu_syscalls(&spufs_calls);
out_fs:
unregister_filesystem(&spufs_type);
+out_sched:
+ spu_sched_exit();
out_cache:
kmem_cache_destroy(spufs_inode_cache);
out:
@@ -689,6 +710,7 @@ module_init(spufs_init);
static void __exit spufs_exit(void)
{
spu_sched_exit();
+ spufs_exit_isolated_loader();
unregister_arch_coredump_calls(&spufs_coredump_calls);
unregister_spu_syscalls(&spufs_calls);
unregister_filesystem(&spufs_type);
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index 353a8fa07ab8..57626600b1a4 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -18,27 +18,6 @@ void spufs_stop_callback(struct spu *spu)
wake_up_all(&ctx->stop_wq);
}
-void spufs_dma_callback(struct spu *spu, int type)
-{
- struct spu_context *ctx = spu->ctx;
-
- if (ctx->flags & SPU_CREATE_EVENTS_ENABLED) {
- ctx->event_return |= type;
- wake_up_all(&ctx->stop_wq);
- } else {
- switch (type) {
- case SPE_EVENT_DMA_ALIGNMENT:
- case SPE_EVENT_SPE_DATA_STORAGE:
- case SPE_EVENT_INVALID_DMA:
- force_sig(SIGBUS, /* info, */ current);
- break;
- case SPE_EVENT_SPE_ERROR:
- force_sig(SIGILL, /* info */ current);
- break;
- }
- }
-}
-
static inline int spu_stopped(struct spu_context *ctx, u32 * stat)
{
struct spu *spu;
@@ -63,13 +42,18 @@ static int spu_setup_isolated(struct spu_context *ctx)
const u32 status_loading = SPU_STATUS_RUNNING
| SPU_STATUS_ISOLATED_STATE | SPU_STATUS_ISOLATED_LOAD_STATUS;
+ ret = -ENODEV;
if (!isolated_loader)
- return -ENODEV;
-
- ret = spu_acquire_exclusive(ctx);
- if (ret)
goto out;
+ /*
+ * We need to exclude userspace access to the context.
+ *
+ * To protect against memory access we invalidate all ptes
+ * and make sure the pagefault handlers block on the mutex.
+ */
+ spu_unmap_mappings(ctx);
+
mfc_cntl = &ctx->spu->priv2->mfc_control_RW;
/* purge the MFC DMA queue to ensure no spurious accesses before we
@@ -82,7 +66,7 @@ static int spu_setup_isolated(struct spu_context *ctx)
printk(KERN_ERR "%s: timeout flushing MFC DMA queue\n",
__FUNCTION__);
ret = -EIO;
- goto out_unlock;
+ goto out;
}
cond_resched();
}
@@ -119,12 +103,15 @@ static int spu_setup_isolated(struct spu_context *ctx)
pr_debug("%s: isolated LOAD failed\n", __FUNCTION__);
ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
ret = -EACCES;
+ goto out_drop_priv;
+ }
- } else if (!(status & SPU_STATUS_ISOLATED_STATE)) {
+ if (!(status & SPU_STATUS_ISOLATED_STATE)) {
/* This isn't allowed by the CBEA, but check anyway */
pr_debug("%s: SPU fell out of isolated mode?\n", __FUNCTION__);
ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_STOP);
ret = -EINVAL;
+ goto out_drop_priv;
}
out_drop_priv:
@@ -132,30 +119,19 @@ out_drop_priv:
sr1 |= MFC_STATE1_PROBLEM_STATE_MASK;
spu_mfc_sr1_set(ctx->spu, sr1);
-out_unlock:
- spu_release(ctx);
out:
return ret;
}
-static inline int spu_run_init(struct spu_context *ctx, u32 * npc)
+static int spu_run_init(struct spu_context *ctx, u32 * npc)
{
- int ret;
- unsigned long runcntl = SPU_RUNCNTL_RUNNABLE;
-
- ret = spu_acquire_runnable(ctx, SPU_ACTIVATE_NOWAKE);
- if (ret)
- return ret;
-
if (ctx->flags & SPU_CREATE_ISOLATE) {
+ unsigned long runcntl;
+
if (!(ctx->ops->status_read(ctx) & SPU_STATUS_ISOLATED_STATE)) {
- /* Need to release ctx, because spu_setup_isolated will
- * acquire it exclusively.
- */
- spu_release(ctx);
- ret = spu_setup_isolated(ctx);
- if (!ret)
- ret = spu_acquire_runnable(ctx, SPU_ACTIVATE_NOWAKE);
+ int ret = spu_setup_isolated(ctx);
+ if (ret)
+ return ret;
}
/* if userspace has set the runcntrl register (eg, to issue an
@@ -164,16 +140,17 @@ static inline int spu_run_init(struct spu_context *ctx, u32 * npc)
(SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE);
if (runcntl == 0)
runcntl = SPU_RUNCNTL_RUNNABLE;
+ ctx->ops->runcntl_write(ctx, runcntl);
} else {
spu_start_tick(ctx);
ctx->ops->npc_write(ctx, *npc);
+ ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
}
- ctx->ops->runcntl_write(ctx, runcntl);
- return ret;
+ return 0;
}
-static inline int spu_run_fini(struct spu_context *ctx, u32 * npc,
+static int spu_run_fini(struct spu_context *ctx, u32 * npc,
u32 * status)
{
int ret = 0;
@@ -189,19 +166,27 @@ static inline int spu_run_fini(struct spu_context *ctx, u32 * npc,
return ret;
}
-static inline int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc,
+static int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc,
u32 *status)
{
int ret;
- if ((ret = spu_run_fini(ctx, npc, status)) != 0)
+ ret = spu_run_fini(ctx, npc, status);
+ if (ret)
return ret;
- if (*status & (SPU_STATUS_STOPPED_BY_STOP |
- SPU_STATUS_STOPPED_BY_HALT)) {
+
+ if (*status & (SPU_STATUS_STOPPED_BY_STOP | SPU_STATUS_STOPPED_BY_HALT))
return *status;
- }
- if ((ret = spu_run_init(ctx, npc)) != 0)
+
+ ret = spu_acquire_runnable(ctx, 0);
+ if (ret)
+ return ret;
+
+ ret = spu_run_init(ctx, npc);
+ if (ret) {
+ spu_release(ctx);
return ret;
+ }
return 0;
}
@@ -253,17 +238,17 @@ int spu_process_callback(struct spu_context *ctx)
{
struct spu_syscall_block s;
u32 ls_pointer, npc;
- char *ls;
+ void __iomem *ls;
long spu_ret;
int ret;
/* get syscall block from local store */
- npc = ctx->ops->npc_read(ctx);
- ls = ctx->ops->get_ls(ctx);
- ls_pointer = *(u32*)(ls + npc);
+ npc = ctx->ops->npc_read(ctx) & ~3;
+ ls = (void __iomem *)ctx->ops->get_ls(ctx);
+ ls_pointer = in_be32(ls + npc);
if (ls_pointer > (LS_SIZE - sizeof(s)))
return -EFAULT;
- memcpy(&s, ls + ls_pointer, sizeof (s));
+ memcpy_fromio(&s, ls + ls_pointer, sizeof(s));
/* do actual syscall without pinning the spu */
ret = 0;
@@ -283,7 +268,7 @@ int spu_process_callback(struct spu_context *ctx)
}
/* write result, jump over indirect pointer */
- memcpy(ls + ls_pointer, &spu_ret, sizeof (spu_ret));
+ memcpy_toio(ls + ls_pointer, &spu_ret, sizeof(spu_ret));
ctx->ops->npc_write(ctx, npc);
ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
return ret;
@@ -292,11 +277,8 @@ int spu_process_callback(struct spu_context *ctx)
static inline int spu_process_events(struct spu_context *ctx)
{
struct spu *spu = ctx->spu;
- u64 pte_fault = MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED;
int ret = 0;
- if (spu->dsisr & pte_fault)
- ret = spu_irq_class_1_bottom(spu);
if (spu->class_0_pending)
ret = spu_irq_class_0_bottom(spu);
if (!ret && signal_pending(current))
@@ -310,14 +292,21 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
int ret;
u32 status;
- if (down_interruptible(&ctx->run_sema))
+ if (mutex_lock_interruptible(&ctx->run_mutex))
return -ERESTARTSYS;
ctx->ops->master_start(ctx);
ctx->event_return = 0;
- ret = spu_run_init(ctx, npc);
+
+ ret = spu_acquire_runnable(ctx, 0);
if (ret)
+ return ret;
+
+ ret = spu_run_init(ctx, npc);
+ if (ret) {
+ spu_release(ctx);
goto out;
+ }
do {
ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, &status));
@@ -330,6 +319,10 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
break;
status &= ~SPU_STATUS_STOPPED_BY_STOP;
}
+ ret = spufs_handle_class1(ctx);
+ if (ret)
+ break;
+
if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
ret = spu_reacquire_runnable(ctx, npc, &status);
if (ret) {
@@ -363,6 +356,6 @@ out2:
out:
*event = ctx->event_return;
- up(&ctx->run_sema);
+ mutex_unlock(&ctx->run_mutex);
return ret;
}
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 2f25e68b4bac..91030b8abdca 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -71,14 +71,27 @@ static inline int node_allowed(int node)
void spu_start_tick(struct spu_context *ctx)
{
- if (ctx->policy == SCHED_RR)
+ if (ctx->policy == SCHED_RR) {
+ /*
+ * Make sure the exiting bit is cleared.
+ */
+ clear_bit(SPU_SCHED_EXITING, &ctx->sched_flags);
+ mb();
queue_delayed_work(spu_sched_wq, &ctx->sched_work, SPU_TIMESLICE);
+ }
}
void spu_stop_tick(struct spu_context *ctx)
{
- if (ctx->policy == SCHED_RR)
+ if (ctx->policy == SCHED_RR) {
+ /*
+ * While the work can be rearming normally setting this flag
+ * makes sure it does not rearm itself anymore.
+ */
+ set_bit(SPU_SCHED_EXITING, &ctx->sched_flags);
+ mb();
cancel_delayed_work(&ctx->sched_work);
+ }
}
void spu_sched_tick(struct work_struct *work)
@@ -86,7 +99,15 @@ void spu_sched_tick(struct work_struct *work)
struct spu_context *ctx =
container_of(work, struct spu_context, sched_work.work);
struct spu *spu;
- int rearm = 1;
+ int preempted = 0;
+
+ /*
+ * If this context is being stopped avoid rescheduling from the
+ * scheduler tick because we would block on the state_mutex.
+ * The caller will yield the spu later on anyway.
+ */
+ if (test_bit(SPU_SCHED_EXITING, &ctx->sched_flags))
+ return;
mutex_lock(&ctx->state_mutex);
spu = ctx->spu;
@@ -94,12 +115,19 @@ void spu_sched_tick(struct work_struct *work)
int best = sched_find_first_bit(spu_prio->bitmap);
if (best <= ctx->prio) {
spu_deactivate(ctx);
- rearm = 0;
+ preempted = 1;
}
}
mutex_unlock(&ctx->state_mutex);
- if (rearm)
+ if (preempted) {
+ /*
+ * We need to break out of the wait loop in spu_run manually
+ * to ensure this context gets put on the runqueue again
+ * ASAP.
+ */
+ wake_up(&ctx->stop_wq);
+ } else
spu_start_tick(ctx);
}
@@ -127,14 +155,6 @@ static void spu_remove_from_active_list(struct spu *spu)
mutex_unlock(&spu_prio->active_mutex[node]);
}
-static inline void mm_needs_global_tlbie(struct mm_struct *mm)
-{
- int nr = (NR_CPUS > 1) ? NR_CPUS : NR_CPUS + 1;
-
- /* Global TLBIE broadcast required with SPEs. */
- __cpus_setall(&mm->cpu_vm_mask, nr);
-}
-
static BLOCKING_NOTIFIER_HEAD(spu_switch_notifier);
static void spu_switch_notify(struct spu *spu, struct spu_context *ctx)
@@ -167,8 +187,7 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx)
ctx->spu = spu;
ctx->ops = &spu_hw_ops;
spu->pid = current->pid;
- spu->mm = ctx->owner;
- mm_needs_global_tlbie(spu->mm);
+ spu_associate_mm(spu, ctx->owner);
spu->ibox_callback = spufs_ibox_callback;
spu->wbox_callback = spufs_wbox_callback;
spu->stop_callback = spufs_stop_callback;
@@ -205,7 +224,7 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
spu->stop_callback = NULL;
spu->mfc_callback = NULL;
spu->dma_callback = NULL;
- spu->mm = NULL;
+ spu_associate_mm(spu, NULL);
spu->pid = 0;
ctx->ops = &spu_backing_ops;
ctx->spu = NULL;
@@ -217,62 +236,42 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
* spu_add_to_rq - add a context to the runqueue
* @ctx: context to add
*/
-static void spu_add_to_rq(struct spu_context *ctx)
+static void __spu_add_to_rq(struct spu_context *ctx)
{
- spin_lock(&spu_prio->runq_lock);
- list_add_tail(&ctx->rq, &spu_prio->runq[ctx->prio]);
- set_bit(ctx->prio, spu_prio->bitmap);
- spin_unlock(&spu_prio->runq_lock);
-}
+ int prio = ctx->prio;
-/**
- * spu_del_from_rq - remove a context from the runqueue
- * @ctx: context to remove
- */
-static void spu_del_from_rq(struct spu_context *ctx)
-{
- spin_lock(&spu_prio->runq_lock);
- list_del_init(&ctx->rq);
- if (list_empty(&spu_prio->runq[ctx->prio]))
- clear_bit(ctx->prio, spu_prio->bitmap);
- spin_unlock(&spu_prio->runq_lock);
+ list_add_tail(&ctx->rq, &spu_prio->runq[prio]);
+ set_bit(prio, spu_prio->bitmap);
}
-/**
- * spu_grab_context - remove one context from the runqueue
- * @prio: priority of the context to be removed
- *
- * This function removes one context from the runqueue for priority @prio.
- * If there is more than one context with the given priority the first
- * task on the runqueue will be taken.
- *
- * Returns the spu_context it just removed.
- *
- * Must be called with spu_prio->runq_lock held.
- */
-static struct spu_context *spu_grab_context(int prio)
+static void __spu_del_from_rq(struct spu_context *ctx)
{
- struct list_head *rq = &spu_prio->runq[prio];
+ int prio = ctx->prio;
- if (list_empty(rq))
- return NULL;
- return list_entry(rq->next, struct spu_context, rq);
+ if (!list_empty(&ctx->rq))
+ list_del_init(&ctx->rq);
+ if (list_empty(&spu_prio->runq[prio]))
+ clear_bit(prio, spu_prio->bitmap);
}
static void spu_prio_wait(struct spu_context *ctx)
{
DEFINE_WAIT(wait);
- set_bit(SPU_SCHED_WAKE, &ctx->sched_flags);
+ spin_lock(&spu_prio->runq_lock);
prepare_to_wait_exclusive(&ctx->stop_wq, &wait, TASK_INTERRUPTIBLE);
if (!signal_pending(current)) {
+ __spu_add_to_rq(ctx);
+ spin_unlock(&spu_prio->runq_lock);
mutex_unlock(&ctx->state_mutex);
schedule();
mutex_lock(&ctx->state_mutex);
+ spin_lock(&spu_prio->runq_lock);
+ __spu_del_from_rq(ctx);
}
+ spin_unlock(&spu_prio->runq_lock);
__set_current_state(TASK_RUNNING);
remove_wait_queue(&ctx->stop_wq, &wait);
- clear_bit(SPU_SCHED_WAKE, &ctx->sched_flags);
}
/**
@@ -291,9 +290,14 @@ static void spu_reschedule(struct spu *spu)
spin_lock(&spu_prio->runq_lock);
best = sched_find_first_bit(spu_prio->bitmap);
if (best < MAX_PRIO) {
- struct spu_context *ctx = spu_grab_context(best);
- if (ctx && test_bit(SPU_SCHED_WAKE, &ctx->sched_flags))
- wake_up(&ctx->stop_wq);
+ struct list_head *rq = &spu_prio->runq[best];
+ struct spu_context *ctx;
+
+ BUG_ON(list_empty(rq));
+
+ ctx = list_entry(rq->next, struct spu_context, rq);
+ __spu_del_from_rq(ctx);
+ wake_up(&ctx->stop_wq);
}
spin_unlock(&spu_prio->runq_lock);
}
@@ -376,6 +380,12 @@ static struct spu *find_victim(struct spu_context *ctx)
}
spu_unbind_context(spu, victim);
mutex_unlock(&victim->state_mutex);
+ /*
+ * We need to break out of the wait loop in spu_run
+ * manually to ensure this context gets put on the
+ * runqueue again ASAP.
+ */
+ wake_up(&victim->stop_wq);
return spu;
}
}
@@ -388,7 +398,7 @@ static struct spu *find_victim(struct spu_context *ctx)
* @ctx: spu context to schedule
* @flags: flags (currently ignored)
*
- * Tries to find a free spu to run @ctx. If no free spu is availble
+ * Tries to find a free spu to run @ctx. If no free spu is available
* add the context to the runqueue so it gets woken up once an spu
* is available.
*/
@@ -413,10 +423,7 @@ int spu_activate(struct spu_context *ctx, unsigned long flags)
return 0;
}
- spu_add_to_rq(ctx);
- if (!(flags & SPU_ACTIVATE_NOWAKE))
- spu_prio_wait(ctx);
- spu_del_from_rq(ctx);
+ spu_prio_wait(ctx);
} while (!signal_pending(current));
return -ERESTARTSYS;
@@ -450,7 +457,6 @@ void spu_deactivate(struct spu_context *ctx)
void spu_yield(struct spu_context *ctx)
{
struct spu *spu;
- int need_yield = 0;
if (mutex_trylock(&ctx->state_mutex)) {
if ((spu = ctx->spu) != NULL) {
@@ -459,13 +465,10 @@ void spu_yield(struct spu_context *ctx)
pr_debug("%s: yielding SPU %d NODE %d\n",
__FUNCTION__, spu->number, spu->node);
spu_deactivate(ctx);
- need_yield = 1;
}
}
mutex_unlock(&ctx->state_mutex);
}
- if (unlikely(need_yield))
- yield();
}
int __init spu_sched_init(void)
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 0c437891dfd5..0a947fd7de57 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -41,7 +41,7 @@ struct spu_gang;
/* ctx->sched_flags */
enum {
- SPU_SCHED_WAKE = 0,
+ SPU_SCHED_EXITING = 0,
};
struct spu_context {
@@ -50,16 +50,17 @@ struct spu_context {
spinlock_t mmio_lock; /* protects mmio access */
struct address_space *local_store; /* local store mapping. */
struct address_space *mfc; /* 'mfc' area mappings. */
- struct address_space *cntl; /* 'control' area mappings. */
- struct address_space *signal1; /* 'signal1' area mappings. */
- struct address_space *signal2; /* 'signal2' area mappings. */
- struct address_space *mss; /* 'mss' area mappings. */
- struct address_space *psmap; /* 'psmap' area mappings. */
+ struct address_space *cntl; /* 'control' area mappings. */
+ struct address_space *signal1; /* 'signal1' area mappings. */
+ struct address_space *signal2; /* 'signal2' area mappings. */
+ struct address_space *mss; /* 'mss' area mappings. */
+ struct address_space *psmap; /* 'psmap' area mappings. */
+ spinlock_t mapping_lock;
u64 object_id; /* user space pointer for oprofile */
enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state;
struct mutex state_mutex;
- struct semaphore run_sema;
+ struct mutex run_mutex;
struct mm_struct *owner;
@@ -140,6 +141,7 @@ struct spu_context_ops {
struct spu_dma_info * info);
void (*proxydma_info_read) (struct spu_context * ctx,
struct spu_proxydma_info * info);
+ void (*restart_dma)(struct spu_context *ctx);
};
extern struct spu_context_ops spu_hw_ops;
@@ -149,6 +151,7 @@ struct spufs_inode_info {
struct spu_context *i_ctx;
struct spu_gang *i_gang;
struct inode vfs_inode;
+ int i_openers;
};
#define SPUFS_I(inode) \
container_of(inode, struct spufs_inode_info, vfs_inode)
@@ -170,6 +173,9 @@ int put_spu_gang(struct spu_gang *gang);
void spu_gang_remove_ctx(struct spu_gang *gang, struct spu_context *ctx);
void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx);
+/* fault handling */
+int spufs_handle_class1(struct spu_context *ctx);
+
/* context management */
static inline void spu_acquire(struct spu_context *ctx)
{
@@ -190,10 +196,7 @@ void spu_unmap_mappings(struct spu_context *ctx);
void spu_forget(struct spu_context *ctx);
int spu_acquire_runnable(struct spu_context *ctx, unsigned long flags);
void spu_acquire_saved(struct spu_context *ctx);
-int spu_acquire_exclusive(struct spu_context *ctx);
-enum {
- SPU_ACTIVATE_NOWAKE = 1,
-};
+
int spu_activate(struct spu_context *ctx, unsigned long flags);
void spu_deactivate(struct spu_context *ctx);
void spu_yield(struct spu_context *ctx);
@@ -220,14 +223,13 @@ extern char *isolated_loader;
prepare_to_wait(&(wq), &__wait, TASK_INTERRUPTIBLE); \
if (condition) \
break; \
- if (!signal_pending(current)) { \
- spu_release(ctx); \
- schedule(); \
- spu_acquire(ctx); \
- continue; \
+ if (signal_pending(current)) { \
+ __ret = -ERESTARTSYS; \
+ break; \
} \
- __ret = -ERESTARTSYS; \
- break; \
+ spu_release(ctx); \
+ schedule(); \
+ spu_acquire(ctx); \
} \
finish_wait(&(wq), &__wait); \
__ret; \
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index c08981ff7fc6..8347c4a3f894 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -468,26 +468,6 @@ static inline void wait_purge_complete(struct spu_state *csa, struct spu *spu)
MFC_CNTL_PURGE_DMA_COMPLETE);
}
-static inline void save_mfc_slbs(struct spu_state *csa, struct spu *spu)
-{
- struct spu_priv2 __iomem *priv2 = spu->priv2;
- int i;
-
- /* Save, Step 29:
- * If MFC_SR1[R]='1', save SLBs in CSA.
- */
- if (spu_mfc_sr1_get(spu) & MFC_STATE1_RELOCATE_MASK) {
- csa->priv2.slb_index_W = in_be64(&priv2->slb_index_W);
- for (i = 0; i < 8; i++) {
- out_be64(&priv2->slb_index_W, i);
- eieio();
- csa->slb_esid_RW[i] = in_be64(&priv2->slb_esid_RW);
- csa->slb_vsid_RW[i] = in_be64(&priv2->slb_vsid_RW);
- eieio();
- }
- }
-}
-
static inline void setup_mfc_sr1(struct spu_state *csa, struct spu *spu)
{
/* Save, Step 30:
@@ -708,20 +688,6 @@ static inline void resume_mfc_queue(struct spu_state *csa, struct spu *spu)
out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESUME_DMA_QUEUE);
}
-static inline void invalidate_slbs(struct spu_state *csa, struct spu *spu)
-{
- struct spu_priv2 __iomem *priv2 = spu->priv2;
-
- /* Save, Step 45:
- * Restore, Step 19:
- * If MFC_SR1[R]=1, write 0 to SLB_Invalidate_All.
- */
- if (spu_mfc_sr1_get(spu) & MFC_STATE1_RELOCATE_MASK) {
- out_be64(&priv2->slb_invalidate_all_W, 0UL);
- eieio();
- }
-}
-
static inline void get_kernel_slb(u64 ea, u64 slb[2])
{
u64 llp;
@@ -765,7 +731,7 @@ static inline void setup_mfc_slbs(struct spu_state *csa, struct spu *spu)
* MFC_SR1[R]=1 (in other words, assume that
* translation is desired by OS environment).
*/
- invalidate_slbs(csa, spu);
+ spu_invalidate_slbs(spu);
get_kernel_slb((unsigned long)&spu_save_code[0], code_slb);
get_kernel_slb((unsigned long)csa->lscsa, lscsa_slb);
load_mfc_slb(spu, code_slb, 0);
@@ -1718,27 +1684,6 @@ static inline void check_ppuint_mb_stat(struct spu_state *csa, struct spu *spu)
}
}
-static inline void restore_mfc_slbs(struct spu_state *csa, struct spu *spu)
-{
- struct spu_priv2 __iomem *priv2 = spu->priv2;
- int i;
-
- /* Restore, Step 68:
- * If MFC_SR1[R]='1', restore SLBs from CSA.
- */
- if (csa->priv1.mfc_sr1_RW & MFC_STATE1_RELOCATE_MASK) {
- for (i = 0; i < 8; i++) {
- out_be64(&priv2->slb_index_W, i);
- eieio();
- out_be64(&priv2->slb_esid_RW, csa->slb_esid_RW[i]);
- out_be64(&priv2->slb_vsid_RW, csa->slb_vsid_RW[i]);
- eieio();
- }
- out_be64(&priv2->slb_index_W, csa->priv2.slb_index_W);
- eieio();
- }
-}
-
static inline void restore_mfc_sr1(struct spu_state *csa, struct spu *spu)
{
/* Restore, Step 69:
@@ -1875,7 +1820,6 @@ static void save_csa(struct spu_state *prev, struct spu *spu)
set_mfc_tclass_id(prev, spu); /* Step 26. */
purge_mfc_queue(prev, spu); /* Step 27. */
wait_purge_complete(prev, spu); /* Step 28. */
- save_mfc_slbs(prev, spu); /* Step 29. */
setup_mfc_sr1(prev, spu); /* Step 30. */
save_spu_npc(prev, spu); /* Step 31. */
save_spu_privcntl(prev, spu); /* Step 32. */
@@ -1987,7 +1931,7 @@ static void harvest(struct spu_state *prev, struct spu *spu)
reset_spu_privcntl(prev, spu); /* Step 16. */
reset_spu_lslr(prev, spu); /* Step 17. */
setup_mfc_sr1(prev, spu); /* Step 18. */
- invalidate_slbs(prev, spu); /* Step 19. */
+ spu_invalidate_slbs(spu); /* Step 19. */
reset_ch_part1(prev, spu); /* Step 20. */
reset_ch_part2(prev, spu); /* Step 21. */
enable_interrupts(prev, spu); /* Step 22. */
@@ -2055,7 +1999,7 @@ static void restore_csa(struct spu_state *next, struct spu *spu)
restore_spu_mb(next, spu); /* Step 65. */
check_ppu_mb_stat(next, spu); /* Step 66. */
check_ppuint_mb_stat(next, spu); /* Step 67. */
- restore_mfc_slbs(next, spu); /* Step 68. */
+ spu_invalidate_slbs(spu); /* Modified Step 68. */
restore_mfc_sr1(next, spu); /* Step 69. */
restore_other_spu_access(next, spu); /* Step 70. */
restore_spu_runcntl(next, spu); /* Step 71. */
@@ -2140,6 +2084,10 @@ int spu_save(struct spu_state *prev, struct spu *spu)
int rc;
acquire_spu_lock(spu); /* Step 1. */
+ prev->dar = spu->dar;
+ prev->dsisr = spu->dsisr;
+ spu->dar = 0;
+ spu->dsisr = 0;
rc = __do_spu_save(prev, spu); /* Steps 2-53. */
release_spu_lock(spu);
if (rc != 0 && rc != 2 && rc != 6) {
@@ -2165,9 +2113,9 @@ int spu_restore(struct spu_state *new, struct spu *spu)
acquire_spu_lock(spu);
harvest(NULL, spu);
- spu->dar = 0;
- spu->dsisr = 0;
spu->slb_replace = 0;
+ new->dar = 0;
+ new->dsisr = 0;
spu->class_0_pending = 0;
rc = __do_spu_restore(new, spu);
release_spu_lock(spu);
diff --git a/arch/powerpc/platforms/celleb/Kconfig b/arch/powerpc/platforms/celleb/Kconfig
new file mode 100644
index 000000000000..2db1e293433e
--- /dev/null
+++ b/arch/powerpc/platforms/celleb/Kconfig
@@ -0,0 +1,9 @@
+config PPC_CELLEB
+ bool "Toshiba's Cell Reference Set 'Celleb' Architecture"
+ depends on PPC_MULTIPLATFORM && PPC64
+ select PPC_CELL
+ select PPC_OF_PLATFORM_PCI
+ select HAS_TXX9_SERIAL
+ select PPC_UDBG_BEAT
+ select USB_OHCI_BIG_ENDIAN_MMIO
+ select USB_EHCI_BIG_ENDIAN_MMIO
diff --git a/arch/powerpc/platforms/celleb/Makefile b/arch/powerpc/platforms/celleb/Makefile
index 3baf658ac543..f4f82520dc4f 100644
--- a/arch/powerpc/platforms/celleb/Makefile
+++ b/arch/powerpc/platforms/celleb/Makefile
@@ -1,9 +1,8 @@
obj-y += interrupt.o iommu.o setup.o \
htab.o beat.o pci.o \
- scc_epci.o hvCall.o
+ scc_epci.o scc_uhc.o hvCall.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PPC_UDBG_BEAT) += udbg_beat.o
-obj-$(CONFIG_USB) += scc_uhc.o
obj-$(CONFIG_HAS_TXX9_SERIAL) += scc_sio.o
obj-$(CONFIG_SPU_BASE) += spu_priv1.o
diff --git a/arch/powerpc/platforms/celleb/iommu.c b/arch/powerpc/platforms/celleb/iommu.c
index f63b94c65353..755d869d8553 100644
--- a/arch/powerpc/platforms/celleb/iommu.c
+++ b/arch/powerpc/platforms/celleb/iommu.c
@@ -37,7 +37,7 @@ static int __init find_dma_window(u64 *io_space_id, u64 *ioid,
const unsigned long *dma_window;
for_each_node_by_type(dn, "ioif") {
- dma_window = get_property(dn, "toshiba,dma-window", NULL);
+ dma_window = of_get_property(dn, "toshiba,dma-window", NULL);
if (dma_window) {
*io_space_id = (dma_window[0] >> 32) & 0xffffffffUL;
*ioid = dma_window[0] & 0x7ffUL;
@@ -80,7 +80,7 @@ static int celleb_of_bus_notify(struct notifier_block *nb,
if (action != BUS_NOTIFY_ADD_DEVICE)
return 0;
- dev->archdata.dma_ops = pci_dma_ops;
+ dev->archdata.dma_ops = get_pci_dma_ops();
return 0;
}
@@ -95,7 +95,7 @@ static int __init celleb_init_iommu(void)
return -ENODEV;
celleb_init_direct_mapping();
- pci_dma_ops = &dma_direct_ops;
+ set_pci_dma_ops(&dma_direct_ops);
bus_register_notifier(&of_platform_bus_type, &celleb_of_bus_notifier);
return 0;
diff --git a/arch/powerpc/platforms/celleb/pci.c b/arch/powerpc/platforms/celleb/pci.c
index 98de836dfed3..d1adf34cd5e8 100644
--- a/arch/powerpc/platforms/celleb/pci.c
+++ b/arch/powerpc/platforms/celleb/pci.c
@@ -309,13 +309,13 @@ static int __devinit celleb_setup_fake_pci_device(struct device_node *node,
goto error;
}
- name = get_property(node, "model", &rlen);
+ name = of_get_property(node, "model", &rlen);
if (!name) {
printk(KERN_ERR "PCI: model property not found.\n");
goto error;
}
- wi4 = get_property(node, "reg", &rlen);
+ wi4 = of_get_property(node, "reg", &rlen);
if (wi4 == NULL)
goto error;
@@ -352,10 +352,10 @@ static int __devinit celleb_setup_fake_pci_device(struct device_node *node,
}
pr_debug("PCI: res assigned 0x%016lx\n", (unsigned long)*res);
- wi0 = get_property(node, "device-id", NULL);
- wi1 = get_property(node, "vendor-id", NULL);
- wi2 = get_property(node, "class-code", NULL);
- wi3 = get_property(node, "revision-id", NULL);
+ wi0 = of_get_property(node, "device-id", NULL);
+ wi1 = of_get_property(node, "vendor-id", NULL);
+ wi2 = of_get_property(node, "class-code", NULL);
+ wi3 = of_get_property(node, "revision-id", NULL);
celleb_config_write_fake(*config, PCI_DEVICE_ID, 2, wi0[0] & 0xffff);
celleb_config_write_fake(*config, PCI_VENDOR_ID, 2, wi1[0] & 0xffff);
@@ -376,7 +376,7 @@ static int __devinit celleb_setup_fake_pci_device(struct device_node *node,
celleb_setup_pci_base_addrs(hose, devno, fn, num_base_addr);
- li = get_property(node, "interrupts", &rlen);
+ li = of_get_property(node, "interrupts", &rlen);
val = li[0];
celleb_config_write_fake(*config, PCI_INTERRUPT_PIN, 1, 1);
celleb_config_write_fake(*config, PCI_INTERRUPT_LINE, 1, val);
@@ -424,7 +424,7 @@ static int __devinit phb_set_bus_ranges(struct device_node *dev,
const int *bus_range;
unsigned int len;
- bus_range = get_property(dev, "bus-range", &len);
+ bus_range = of_get_property(dev, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int))
return 1;
@@ -451,7 +451,7 @@ int __devinit celleb_setup_phb(struct pci_controller *phb)
struct device_node *node;
unsigned int rlen;
- name = get_property(dev, "name", &rlen);
+ name = of_get_property(dev, "name", &rlen);
if (!name)
return 1;
diff --git a/arch/powerpc/platforms/celleb/scc_epci.c b/arch/powerpc/platforms/celleb/scc_epci.c
index c11b39c3776a..fb23d53eb09c 100644
--- a/arch/powerpc/platforms/celleb/scc_epci.c
+++ b/arch/powerpc/platforms/celleb/scc_epci.c
@@ -43,11 +43,34 @@
#define iob() __asm__ __volatile__("eieio; sync":::"memory")
+static inline volatile void __iomem *celleb_epci_get_epci_base(
+ struct pci_controller *hose)
+{
+ /*
+ * Note:
+ * Celleb epci uses cfg_addr as a base address for
+ * epci control registers.
+ */
+
+ return hose->cfg_addr;
+}
+
+static inline volatile void __iomem *celleb_epci_get_epci_cfg(
+ struct pci_controller *hose)
+{
+ /*
+ * Note:
+ * Celleb epci uses cfg_data as a base address for
+ * configuration area for epci devices.
+ */
+
+ return hose->cfg_data;
+}
#if 0 /* test code for epci dummy read */
static void celleb_epci_dummy_read(struct pci_dev *dev)
{
- void __iomem *epci_base;
+ volatile void __iomem *epci_base;
struct device_node *node;
struct pci_controller *hose;
u32 val;
@@ -58,7 +81,7 @@ static void celleb_epci_dummy_read(struct pci_dev *dev)
if (!hose)
return;
- epci_base = hose->cfg_addr;
+ epci_base = celleb_epci_get_epci_base(hose);
val = in_be32(epci_base + SCC_EPCI_WATRP);
iosync();
@@ -70,19 +93,20 @@ static void celleb_epci_dummy_read(struct pci_dev *dev)
static inline void clear_and_disable_master_abort_interrupt(
struct pci_controller *hose)
{
- void __iomem *addr;
- addr = hose->cfg_addr + PCI_COMMAND;
- out_be32(addr, in_be32(addr) | (PCI_STATUS_REC_MASTER_ABORT << 16));
+ volatile void __iomem *epci_base, *reg;
+ epci_base = celleb_epci_get_epci_base(hose);
+ reg = epci_base + PCI_COMMAND;
+ out_be32(reg, in_be32(reg) | (PCI_STATUS_REC_MASTER_ABORT << 16));
}
static int celleb_epci_check_abort(struct pci_controller *hose,
- void __iomem *addr)
+ volatile void __iomem *addr)
{
- void __iomem *reg, *epci_base;
+ volatile void __iomem *reg, *epci_base;
u32 val;
iob();
- epci_base = hose->cfg_addr;
+ epci_base = celleb_epci_get_epci_base(hose);
reg = epci_base + PCI_COMMAND;
val = in_be32(reg);
@@ -108,20 +132,21 @@ static int celleb_epci_check_abort(struct pci_controller *hose,
return PCIBIOS_SUCCESSFUL;
}
-static void __iomem *celleb_epci_make_config_addr(struct pci_controller *hose,
+static volatile void __iomem *celleb_epci_make_config_addr(
+ struct pci_controller *hose,
unsigned int devfn, int where)
{
- void __iomem *addr;
+ volatile void __iomem *addr;
struct pci_bus *bus = hose->bus;
if (bus->self)
- addr = hose->cfg_data +
+ addr = celleb_epci_get_epci_cfg(hose) +
(((bus->number & 0xff) << 16)
| ((devfn & 0xff) << 8)
| (where & 0xff)
| 0x01000000);
else
- addr = hose->cfg_data +
+ addr = celleb_epci_get_epci_cfg(hose) +
(((devfn & 0xff) << 8) | (where & 0xff));
pr_debug("EPCI: config_addr = 0x%p\n", addr);
@@ -132,7 +157,7 @@ static void __iomem *celleb_epci_make_config_addr(struct pci_controller *hose,
static int celleb_epci_read_config(struct pci_bus *bus,
unsigned int devfn, int where, int size, u32 * val)
{
- void __iomem *addr;
+ volatile void __iomem *epci_base, *addr;
struct device_node *node;
struct pci_controller *hose;
@@ -142,13 +167,14 @@ static int celleb_epci_read_config(struct pci_bus *bus,
node = (struct device_node *)bus->sysdata;
hose = pci_find_hose_for_OF_device(node);
- if (!hose->cfg_data)
+ if (!celleb_epci_get_epci_cfg(hose))
return PCIBIOS_DEVICE_NOT_FOUND;
if (bus->number == hose->first_busno && devfn == 0) {
/* EPCI controller self */
- addr = hose->cfg_addr + where;
+ epci_base = celleb_epci_get_epci_base(hose);
+ addr = epci_base + where;
switch (size) {
case 1:
@@ -185,7 +211,7 @@ static int celleb_epci_read_config(struct pci_bus *bus,
}
pr_debug("EPCI: "
- "addr=0x%lx, devfn=0x%x, where=0x%x, size=0x%x, val=0x%x\n",
+ "addr=0x%p, devfn=0x%x, where=0x%x, size=0x%x, val=0x%x\n",
addr, devfn, where, size, *val);
return celleb_epci_check_abort(hose, NULL);
@@ -194,7 +220,7 @@ static int celleb_epci_read_config(struct pci_bus *bus,
static int celleb_epci_write_config(struct pci_bus *bus,
unsigned int devfn, int where, int size, u32 val)
{
- void __iomem *addr;
+ volatile void __iomem *epci_base, *addr;
struct device_node *node;
struct pci_controller *hose;
@@ -204,13 +230,15 @@ static int celleb_epci_write_config(struct pci_bus *bus,
node = (struct device_node *)bus->sysdata;
hose = pci_find_hose_for_OF_device(node);
- if (!hose->cfg_data)
+
+ if (!celleb_epci_get_epci_cfg(hose))
return PCIBIOS_DEVICE_NOT_FOUND;
if (bus->number == hose->first_busno && devfn == 0) {
/* EPCI controller self */
- addr = hose->cfg_addr + where;
+ epci_base = celleb_epci_get_epci_base(hose);
+ addr = epci_base + where;
switch (size) {
case 1:
@@ -258,10 +286,10 @@ struct pci_ops celleb_epci_ops = {
static int __devinit celleb_epci_init(struct pci_controller *hose)
{
u32 val;
- void __iomem *reg, *epci_base;
+ volatile void __iomem *reg, *epci_base;
int hwres = 0;
- epci_base = hose->cfg_addr;
+ epci_base = celleb_epci_get_epci_base(hose);
/* PCI core reset(Internal bus and PCI clock) */
reg = epci_base + SCC_EPCI_CKCTRL;
@@ -382,6 +410,18 @@ int __devinit celleb_setup_epci(struct device_node *node,
pr_debug("PCI: celleb_setup_epci()\n");
+ /*
+ * Note:
+ * Celleb epci uses cfg_addr and cfg_data member of
+ * pci_controller structure in irregular way.
+ *
+ * cfg_addr is used to map for control registers of
+ * celleb epci.
+ *
+ * cfg_data is used for configuration area of devices
+ * on Celleb epci buses.
+ */
+
if (of_address_to_resource(node, 0, &r))
goto error;
hose->cfg_addr = ioremap(r.start, (r.end - r.start + 1));
diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c
index 1de63acfda87..596ab2a788d4 100644
--- a/arch/powerpc/platforms/celleb/setup.c
+++ b/arch/powerpc/platforms/celleb/setup.c
@@ -67,7 +67,7 @@ static void celleb_show_cpuinfo(struct seq_file *m)
root = of_find_node_by_path("/");
if (root)
- model = get_property(root, "model", NULL);
+ model = of_get_property(root, "model", NULL);
/* using "CHRP" is to trick anaconda into installing FCx into Celleb */
seq_printf(m, "machine\t\t: %s %s\n", celleb_machine_type, model);
of_node_put(root);
@@ -128,19 +128,12 @@ static int __init celleb_probe(void)
return 1;
}
-/*
- * Cell has no legacy IO; anything calling this function has to
- * fail or bad things will happen
- */
-static int celleb_check_legacy_ioport(unsigned int baseport)
-{
- return -ENODEV;
-}
-
+#ifdef CONFIG_KEXEC
static void celleb_kexec_cpu_down(int crash, int secondary)
{
beatic_deinit_IRQ();
}
+#endif
static struct of_device_id celleb_bus_ids[] = {
{ .type = "scc", },
@@ -171,7 +164,6 @@ define_machine(celleb) {
.get_rtc_time = beat_get_rtc_time,
.set_rtc_time = beat_set_rtc_time,
.calibrate_decr = generic_calibrate_decr,
- .check_legacy_ioport = celleb_check_legacy_ioport,
.progress = celleb_progress,
.power_save = beat_power_save,
.nvram_size = beat_nvram_get_size,
diff --git a/arch/powerpc/platforms/chrp/Kconfig b/arch/powerpc/platforms/chrp/Kconfig
new file mode 100644
index 000000000000..d2c690531963
--- /dev/null
+++ b/arch/powerpc/platforms/chrp/Kconfig
@@ -0,0 +1,11 @@
+config PPC_CHRP
+ bool "Common Hardware Reference Platform (CHRP) based machines"
+ depends on PPC_MULTIPLATFORM && PPC32
+ select MPIC
+ select PPC_I8259
+ select PPC_INDIRECT_PCI
+ select PPC_RTAS
+ select PPC_MPC106
+ select PPC_UDBG_16550
+ select PPC_NATIVE
+ default y
diff --git a/arch/powerpc/platforms/chrp/nvram.c b/arch/powerpc/platforms/chrp/nvram.c
index 0dd4a64757d9..8efd4244701c 100644
--- a/arch/powerpc/platforms/chrp/nvram.c
+++ b/arch/powerpc/platforms/chrp/nvram.c
@@ -74,7 +74,7 @@ void __init chrp_nvram_init(void)
if (nvram == NULL)
return;
- nbytes_p = get_property(nvram, "#bytes", &proplen);
+ nbytes_p = of_get_property(nvram, "#bytes", &proplen);
if (nbytes_p == NULL || proplen != sizeof(unsigned int))
return;
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index ddb4a116ea89..1469d6478f67 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -7,7 +7,6 @@
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/init.h>
-#include <linux/ide.h>
#include <asm/io.h>
#include <asm/pgtable.h>
@@ -137,9 +136,11 @@ hydra_init(void)
struct device_node *np;
struct resource r;
- np = find_devices("mac-io");
- if (np == NULL || of_address_to_resource(np, 0, &r))
+ np = of_find_node_by_name(NULL, "mac-io");
+ if (np == NULL || of_address_to_resource(np, 0, &r)) {
+ of_node_put(np);
return 0;
+ }
Hydra = ioremap(r.start, r.end-r.start);
printk("Hydra Mac I/O at %llx\n", (unsigned long long)r.start);
printk("Hydra Feature_Control was %x",
@@ -186,10 +187,9 @@ setup_python(struct pci_controller *hose, struct device_node *dev)
/* Marvell Discovery II based Pegasos 2 */
static void __init setup_peg2(struct pci_controller *hose, struct device_node *dev)
{
- struct device_node *root = find_path_device("/");
+ struct device_node *root = of_find_node_by_path("/");
struct device_node *rtas;
- of_node_get(root);
rtas = of_find_node_by_name (root, "rtas");
if (rtas) {
hose->ops = &rtas_pci_ops;
@@ -199,6 +199,7 @@ static void __init setup_peg2(struct pci_controller *hose, struct device_node *d
" your firmware\n");
}
pci_assign_all_buses = 1;
+ /* keep the reference to the root node */
}
void __init
@@ -211,14 +212,14 @@ chrp_find_bridges(void)
const unsigned int *dma;
const char *model, *machine;
int is_longtrail = 0, is_mot = 0, is_pegasos = 0;
- struct device_node *root = find_path_device("/");
+ struct device_node *root = of_find_node_by_path("/");
struct resource r;
/*
* The PCI host bridge nodes on some machines don't have
* properties to adequately identify them, so we have to
* look at what sort of machine this is as well.
*/
- machine = get_property(root, "model", NULL);
+ machine = of_get_property(root, "model", NULL);
if (machine != NULL) {
is_longtrail = strncmp(machine, "IBM,LongTrail", 13) == 0;
is_mot = strncmp(machine, "MOT", 3) == 0;
@@ -237,7 +238,7 @@ chrp_find_bridges(void)
dev->full_name);
continue;
}
- bus_range = get_property(dev, "bus-range", &len);
+ bus_range = of_get_property(dev, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int)) {
printk(KERN_WARNING "Can't get bus-range for %s\n",
dev->full_name);
@@ -263,7 +264,7 @@ chrp_find_bridges(void)
hose->first_busno = bus_range[0];
hose->last_busno = bus_range[1];
- model = get_property(dev, "model", NULL);
+ model = of_get_property(dev, "model", NULL);
if (model == NULL)
model = "<none>";
if (device_is_compatible(dev, "IBM,python")) {
@@ -285,7 +286,8 @@ chrp_find_bridges(void)
r.start + 0x000f8000,
r.start + 0x000f8010);
if (index == 0) {
- dma = get_property(dev, "system-dma-base",&len);
+ dma = of_get_property(dev, "system-dma-base",
+ &len);
if (dma && len >= sizeof(*dma)) {
dma = (unsigned int *)
(((unsigned long)dma) +
@@ -303,12 +305,13 @@ chrp_find_bridges(void)
/* check the first bridge for a property that we can
use to set pci_dram_offset */
- dma = get_property(dev, "ibm,dma-ranges", &len);
+ dma = of_get_property(dev, "ibm,dma-ranges", &len);
if (index == 0 && dma != NULL && len >= 6 * sizeof(*dma)) {
pci_dram_offset = dma[2] - dma[3];
printk("pci_dram_offset = %lx\n", pci_dram_offset);
}
}
+ of_node_put(root);
}
/* SL82C105 IDE Control/Status Register */
diff --git a/arch/powerpc/platforms/chrp/pegasos_eth.c b/arch/powerpc/platforms/chrp/pegasos_eth.c
index 6ad4b1a72c96..71045677559a 100644
--- a/arch/powerpc/platforms/chrp/pegasos_eth.c
+++ b/arch/powerpc/platforms/chrp/pegasos_eth.c
@@ -58,6 +58,7 @@ static struct resource mv643xx_eth0_resources[] = {
static struct mv643xx_eth_platform_data eth0_pd = {
+ .port_number = 0,
.tx_sram_addr = PEGASOS2_SRAM_BASE_ETH0,
.tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE,
.tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16,
@@ -87,6 +88,7 @@ static struct resource mv643xx_eth1_resources[] = {
};
static struct mv643xx_eth_platform_data eth1_pd = {
+ .port_number = 1,
.tx_sram_addr = PEGASOS2_SRAM_BASE_ETH1,
.tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE,
.tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16,
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 117c9a0055bd..1870038a8e0a 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -28,7 +28,6 @@
#include <linux/adb.h>
#include <linux/module.h>
#include <linux/delay.h>
-#include <linux/ide.h>
#include <linux/console.h>
#include <linux/seq_file.h>
#include <linux/root_dev.h>
@@ -111,9 +110,9 @@ void chrp_show_cpuinfo(struct seq_file *m)
struct device_node *root;
const char *model = "";
- root = find_path_device("/");
+ root = of_find_node_by_path("/");
if (root)
- model = get_property(root, "model", NULL);
+ model = of_get_property(root, "model", NULL);
seq_printf(m, "machine\t\t: CHRP %s\n", model);
/* longtrail (goldengate) stuff */
@@ -161,6 +160,7 @@ void chrp_show_cpuinfo(struct seq_file *m)
gg2_cachetypes[(t>>2) & 3],
gg2_cachemodes[t & 3]);
}
+ of_node_put(root);
}
/*
@@ -205,13 +205,15 @@ static void __init sio_init(void)
{
struct device_node *root;
- if ((root = find_path_device("/")) &&
- !strncmp(get_property(root, "model", NULL), "IBM,LongTrail", 13)) {
+ if ((root = of_find_node_by_path("/")) &&
+ !strncmp(of_get_property(root, "model", NULL),
+ "IBM,LongTrail", 13)) {
/* logical device 0 (KBC/Keyboard) */
sio_fixup_irq("keyboard", 0, 1, 2);
/* select logical device 1 (KBC/Mouse) */
sio_fixup_irq("mouse", 1, 12, 2);
}
+ of_node_put(root);
}
@@ -224,12 +226,12 @@ static void __init pegasos_set_l2cr(void)
return;
/* Enable L2 cache if needed */
- np = find_type_devices("cpu");
+ np = of_find_node_by_type(NULL, "cpu");
if (np != NULL) {
- const unsigned int *l2cr = get_property(np, "l2cr", NULL);
+ const unsigned int *l2cr = of_get_property(np, "l2cr", NULL);
if (l2cr == NULL) {
printk ("Pegasos l2cr : no cpu l2cr property found\n");
- return;
+ goto out;
}
if (!((*l2cr) & 0x80000000)) {
printk ("Pegasos l2cr : L2 cache was not active, "
@@ -238,6 +240,8 @@ static void __init pegasos_set_l2cr(void)
_set_L2CR((*l2cr) | 0x80000000);
}
}
+out:
+ of_node_put(np);
}
static void briq_restart(char *cmd)
@@ -250,14 +254,14 @@ static void briq_restart(char *cmd)
void __init chrp_setup_arch(void)
{
- struct device_node *root = find_path_device ("/");
+ struct device_node *root = of_find_node_by_path("/");
const char *machine = NULL;
/* init to some ~sane value until calibrate_delay() runs */
loops_per_jiffy = 50000000/HZ;
if (root)
- machine = get_property(root, "model", NULL);
+ machine = of_get_property(root, "model", NULL);
if (machine && strncmp(machine, "Pegasos", 7) == 0) {
_chrp_type = _CHRP_Pegasos;
} else if (machine && strncmp(machine, "IBM", 3) == 0) {
@@ -273,6 +277,7 @@ void __init chrp_setup_arch(void)
/* Let's assume it is an IBM chrp if all else fails */
_chrp_type = _CHRP_IBM;
}
+ of_node_put(root);
printk("chrp type = %x [%s]\n", _chrp_type, chrp_names[_chrp_type]);
rtas_initialize();
@@ -361,8 +366,8 @@ static void __init chrp_find_openpic(void)
return;
root = of_find_node_by_path("/");
if (root) {
- opprop = get_property(root, "platform-open-pic", &oplen);
- na = prom_n_addr_cells(root);
+ opprop = of_get_property(root, "platform-open-pic", &oplen);
+ na = of_n_addr_cells(root);
}
if (opprop && oplen >= na * sizeof(unsigned int)) {
opaddr = opprop[na-1]; /* assume 32-bit */
@@ -378,7 +383,7 @@ static void __init chrp_find_openpic(void)
printk(KERN_INFO "OpenPIC at %lx\n", opaddr);
- iranges = get_property(np, "interrupt-ranges", &len);
+ iranges = of_get_property(np, "interrupt-ranges", &len);
if (iranges == NULL)
len = 0; /* non-distributed mpic */
else
@@ -427,7 +432,7 @@ static void __init chrp_find_openpic(void)
of_node_put(np);
}
-#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
+#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_XMON)
static struct irqaction xmon_irqaction = {
.handler = xmon_irq,
.mask = CPU_MASK_NONE,
@@ -463,15 +468,16 @@ static void __init chrp_find_8259(void)
* Also, Pegasos-type platforms don't have a proper node to start
* from anyway
*/
- for (np = find_devices("pci"); np != NULL; np = np->next) {
- const unsigned int *addrp = get_property(np,
+ for_each_node_by_name(np, "pci") {
+ const unsigned int *addrp = of_get_property(np,
"8259-interrupt-acknowledge", NULL);
if (addrp == NULL)
continue;
- chrp_int_ack = addrp[prom_n_addr_cells(np)-1];
+ chrp_int_ack = addrp[of_n_addr_cells(np)-1];
break;
}
+ of_node_put(np);
if (np == NULL)
printk(KERN_WARNING "Cannot find PCI interrupt acknowledge"
" address, polling\n");
@@ -493,7 +499,7 @@ static void __init chrp_find_8259(void)
void __init chrp_init_IRQ(void)
{
-#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
+#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_XMON)
struct device_node *kbd;
#endif
chrp_find_openpic();
@@ -510,13 +516,14 @@ void __init chrp_init_IRQ(void)
if (_chrp_type == _CHRP_Pegasos)
ppc_md.get_irq = i8259_irq;
-#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
+#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_XMON)
/* see if there is a keyboard in the device tree
with a parent of type "adb" */
- for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next)
+ for_each_node_by_name(kbd, "keyboard")
if (kbd->parent && kbd->parent->type
&& strcmp(kbd->parent->type, "adb") == 0)
break;
+ of_node_put(kbd);
if (kbd)
setup_irq(HYDRA_INT_ADB_NMI, &xmon_irqaction);
#endif
@@ -542,9 +549,9 @@ chrp_init2(void)
/* Get the event scan rate for the rtas so we know how
* often it expects a heartbeat. -- Cort
*/
- device = find_devices("rtas");
+ device = of_find_node_by_name(NULL, "rtas");
if (device)
- p = get_property(device, "rtas-event-scan-rate", NULL);
+ p = of_get_property(device, "rtas-event-scan-rate", NULL);
if (p && *p) {
/*
* Arrange to call chrp_event_scan at least *p times
@@ -571,6 +578,7 @@ chrp_init2(void)
printk("RTAS Event Scan Rate: %u (%lu jiffies)\n",
*p, interval);
}
+ of_node_put(device);
if (ppc_md.progress)
ppc_md.progress(" Have fun! ", 0x7777);
diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c
index 7d7889026936..96d1e4b3c493 100644
--- a/arch/powerpc/platforms/chrp/time.c
+++ b/arch/powerpc/platforms/chrp/time.c
@@ -39,12 +39,17 @@ long __init chrp_time_init(void)
struct resource r;
int base;
- rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
+ rtcs = of_find_compatible_node(NULL, "rtc", "pnpPNP,b00");
if (rtcs == NULL)
- rtcs = find_compatible_devices("rtc", "ds1385-rtc");
- if (rtcs == NULL || of_address_to_resource(rtcs, 0, &r))
+ rtcs = of_find_compatible_node(NULL, "rtc", "ds1385-rtc");
+ if (rtcs == NULL)
+ return 0;
+ if (of_address_to_resource(rtcs, 0, &r)) {
+ of_node_put(rtcs);
return 0;
-
+ }
+ of_node_put(rtcs);
+
base = r.start;
nvram_as1 = 0;
nvram_as0 = base;
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index 886c522d78e9..9557908ef545 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -2,83 +2,12 @@ choice
prompt "Machine Type"
depends on EMBEDDED6xx
-config KATANA
- bool "Artesyn-Katana"
- help
- Select KATANA if configuring an Artesyn KATANA 750i or 3750
- cPCI board.
-
-config WILLOW
- bool "Cogent-Willow"
-
-config CPCI690
- bool "Force-CPCI690"
- help
- Select CPCI690 if configuring a Force CPCI690 cPCI board.
-
-config POWERPMC250
- bool "Force-PowerPMC250"
-
-config CHESTNUT
- bool "IBM 750FX Eval board or 750GX Eval board"
- help
- Select CHESTNUT if configuring an IBM 750FX Eval Board or a
- IBM 750GX Eval board.
-
-config SPRUCE
- bool "IBM-Spruce"
- select PPC_INDIRECT_PCI
-
-config HDPU
- bool "Sky-HDPU"
- help
- Select HDPU if configuring a Sky Computers Compute Blade.
-
-config HDPU_FEATURES
- depends on HDPU
- tristate "HDPU-Features"
- help
- Select to enable HDPU enhanced features.
-
-config EV64260
- bool "Marvell-EV64260BP"
- help
- Select EV64260 if configuring a Marvell (formerly Galileo)
- EV64260BP Evaluation platform.
-
-config LOPEC
- bool "Motorola-LoPEC"
- select PPC_I8259
-
-config MVME5100
- bool "Motorola-MVME5100"
- select PPC_INDIRECT_PCI
-
-config PPLUS
- bool "Motorola-PowerPlus"
- select PPC_I8259
- select PPC_INDIRECT_PCI
-
-config PRPMC750
- bool "Motorola-PrPMC750"
- select PPC_INDIRECT_PCI
-
-config PRPMC800
- bool "Motorola-PrPMC800"
- select PPC_INDIRECT_PCI
-
-config SANDPOINT
- bool "Motorola-Sandpoint"
- select PPC_I8259
- help
- Select SANDPOINT if configuring for a Motorola Sandpoint X3
- (any flavor).
-
config LINKSTATION
bool "Linkstation / Kurobox(HG) from Buffalo"
select MPIC
select FSL_SOC
select PPC_UDBG_16550 if SERIAL_8250
+ select DEFAULT_UIMAGE
help
Select LINKSTATION if configuring for one of PPC- (MPC8241)
based NAS systems from Buffalo Technology. So far only
@@ -96,212 +25,24 @@ config MPC7448HPC2
help
Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga)
platform
-
-config RADSTONE_PPC7D
- bool "Radstone Technology PPC7D board"
- select PPC_I8259
-
-config PAL4
- bool "SBS-Palomar4"
-
-config EST8260
- bool "EST8260"
- ---help---
- The EST8260 is a single-board computer manufactured by Wind River
- Systems, Inc. (formerly Embedded Support Tools Corp.) and based on
- the MPC8260. Wind River Systems has a website at
- <http://www.windriver.com/>, but the EST8260 cannot be found on it
- and has probably been discontinued or rebadged.
-
-config SBC82xx
- bool "SBC82xx"
- ---help---
- SBC PowerQUICC II, single-board computer with MPC82xx CPU
- Manufacturer: Wind River Systems, Inc.
- Date of Release: May 2003
- End of Life: -
- URL: <http://www.windriver.com/>
-
-config SBS8260
- bool "SBS8260"
-
-config RPX8260
- bool "RPXSUPER"
-
-config TQM8260
- bool "TQM8260"
- ---help---
- MPC8260 based module, little larger than credit card,
- up to 128 MB global + 64 MB local RAM, 32 MB Flash,
- 32 kB EEPROM, 256 kB L@ Cache, 10baseT + 100baseT Ethernet,
- 2 x serial ports, ...
- Manufacturer: TQ Components, www.tq-group.de
- Date of Release: June 2001
- End of Life: not yet :-)
- URL: <http://www.denx.de/PDF/TQM82xx_SPEC_Rev005.pdf>
-
-config ADS8272
- bool "ADS8272"
-
-config PQ2FADS
- bool "Freescale-PQ2FADS"
- help
- Select PQ2FADS if you wish to configure for a Freescale
- PQ2FADS board (-VR or -ZU).
-
-config EV64360
- bool "Marvell-EV64360BP"
- help
- Select EV64360 if configuring a Marvell EV64360BP Evaluation
- platform.
endchoice
-config PQ2ADS
- bool
- depends on ADS8272
- default y
-
-config TQM8xxL
- bool
- depends on 8xx && (TQM823L || TQM850L || FPS850L || TQM855L || TQM860L)
- default y
-
-config 8260
- bool "CPM2 Support" if WILLOW
- depends on 6xx
- default y if TQM8260 || RPX8260 || EST8260 || SBS8260 || SBC82xx || PQ2FADS
- help
- The MPC8260 is a typical embedded CPU made by Motorola. Selecting
- this option means that you wish to build a kernel for a machine with
- an 8260 class CPU.
-
-config 8272
- bool
- depends on 6xx
- default y if ADS8272
- select 8260
- help
- The MPC8272 CPM has a different internal dpram setup than other CPM2
- devices
-
-config CPM2
- bool
- depends on 8260 || MPC8560 || MPC8555
- default y
- help
- The CPM2 (Communications Processor Module) is a coprocessor on
- embedded CPUs made by Motorola. Selecting this option means that
- you wish to build a kernel for a machine with a CPM2 coprocessor
- on it (826x, 827x, 8560).
-
-config PPC_GEN550
- bool
- depends on SANDPOINT || SPRUCE || PPLUS || \
- PRPMC750 || PRPMC800 || LOPEC || \
- (EV64260 && !SERIAL_MPSC) || CHESTNUT || RADSTONE_PPC7D || \
- 83xx || LINKSTATION
- default y
-
-config FORCE
- bool
- depends on 6xx && POWERPMC250
- default y
-
-config GT64260
- bool
- depends on EV64260 || CPCI690
- default y
-
-config MV64360 # Really MV64360 & MV64460
- bool
- depends on CHESTNUT || KATANA || RADSTONE_PPC7D || HDPU || EV64360
- default y
-
-config MV64X60
- bool
- depends on (GT64260 || MV64360)
- select PPC_INDIRECT_PCI
- default y
-
config TSI108_BRIDGE
bool
depends on MPC7448HPC2
default y
-menu "Set bridge options"
- depends on MV64X60
-
-config NOT_COHERENT_CACHE
- bool "Turn off Cache Coherency"
- default n
- help
- Some 64x60 bridges lock up when trying to enforce cache coherency.
- When this option is selected, cache coherency will be turned off.
- Note that this can cause other problems (e.g., stale data being
- speculatively loaded via a cached mapping). Use at your own risk.
-
-config MV64X60_BASE
- hex "Set bridge base used by firmware"
- default "0xf1000000"
- help
- A firmware can leave the base address of the bridge's registers at
- a non-standard location. If so, set this value to reflect the
- address of that non-standard location.
-
-config MV64X60_NEW_BASE
- hex "Set bridge base used by kernel"
- default "0xf1000000"
- help
- If the current base address of the bridge's registers is not where
- you want it, set this value to the address that you want it moved to.
-
-endmenu
-
-config NONMONARCH_SUPPORT
- bool "Enable Non-Monarch Support"
- depends on PRPMC800
-
-config HARRIER
- bool
- depends on PRPMC800
- default y
-
-config EPIC_SERIAL_MODE
- bool
- depends on 6xx && (LOPEC || SANDPOINT)
- default y
-
config MPC10X_BRIDGE
bool
- depends on POWERPMC250 || LOPEC || SANDPOINT || LINKSTATION
+ depends on LINKSTATION
select PPC_INDIRECT_PCI
default y
config MPC10X_OPENPIC
bool
- depends on POWERPMC250 || LOPEC || SANDPOINT || LINKSTATION
+ depends on LINKSTATION
default y
config MPC10X_STORE_GATHERING
bool "Enable MPC10x store gathering"
depends on MPC10X_BRIDGE
-
-config SANDPOINT_ENABLE_UART1
- bool "Enable DUART mode on Sandpoint"
- depends on SANDPOINT
- help
- If this option is enabled then the MPC824x processor will run
- in DUART mode instead of UART mode.
-
-config HARRIER_STORE_GATHERING
- bool "Enable Harrier store gathering"
- depends on HARRIER
-
-config MVME5100_IPMC761_PRESENT
- bool "MVME5100 configured with an IPMC761"
- depends on MVME5100
- select PPC_I8259
-
-config SPRUCE_BAUD_33M
- bool "Spruce baud clock support"
- depends on SPRUCE
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c
index 3f6c4114f908..b412f006a9c5 100644
--- a/arch/powerpc/platforms/embedded6xx/linkstation.c
+++ b/arch/powerpc/platforms/embedded6xx/linkstation.c
@@ -58,11 +58,11 @@ static int __init add_bridge(struct device_node *dev)
{
int len;
struct pci_controller *hose;
- int *bus_range;
+ const int *bus_range;
printk("Adding PCI host bridge %s\n", dev->full_name);
- bus_range = (int *) get_property(dev, "bus-range", &len);
+ bus_range = of_get_property(dev, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int))
printk(KERN_WARNING "Can't get bus-range for %s, assume"
" bus 0\n", dev->full_name);
@@ -106,7 +106,7 @@ static void __init linkstation_init_IRQ(void)
{
struct mpic *mpic;
struct device_node *dnp;
- void *prop;
+ const u32 *prop;
int size;
phys_addr_t paddr;
@@ -114,7 +114,7 @@ static void __init linkstation_init_IRQ(void)
if (dnp == NULL)
return;
- prop = (struct device_node *)get_property(dnp, "reg", &size);
+ prop = of_get_property(dnp, "reg", &size);
paddr = (phys_addr_t)of_translate_address(dnp, prop);
mpic = mpic_alloc(dnp, paddr, MPIC_PRIMARY | MPIC_WANTS_RESET, 4, 32, " EPIC ");
diff --git a/arch/powerpc/platforms/embedded6xx/ls_uart.c b/arch/powerpc/platforms/embedded6xx/ls_uart.c
index 0e837762cc5b..d0bee9f19e4e 100644
--- a/arch/powerpc/platforms/embedded6xx/ls_uart.c
+++ b/arch/powerpc/platforms/embedded6xx/ls_uart.c
@@ -110,8 +110,8 @@ static int __init ls_uarts_init(void)
if (!avr)
return -EINVAL;
- avr_clock = *(u32*)get_property(avr, "clock-frequency", &len);
- phys_addr = ((u32*)get_property(avr, "reg", &len))[0];
+ avr_clock = *(u32*)of_get_property(avr, "clock-frequency", &len);
+ phys_addr = ((u32*)of_get_property(avr, "reg", &len))[0];
if (!avr_clock || !phys_addr)
return -EINVAL;
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
index 3fcc85f60fbf..c3f64ddb0be6 100644
--- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
+++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
@@ -25,7 +25,6 @@
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/irq.h>
-#include <linux/ide.h>
#include <linux/seq_file.h>
#include <linux/root_dev.h>
#include <linux/serial.h>
@@ -82,7 +81,7 @@ static void __init mpc7448_hpc2_setup_arch(void)
if (cpu != 0) {
const unsigned int *fp;
- fp = get_property(cpu, "clock-frequency", NULL);
+ fp = of_get_property(cpu, "clock-frequency", NULL);
if (fp != 0)
loops_per_jiffy = *fp / HZ;
else
@@ -91,16 +90,6 @@ static void __init mpc7448_hpc2_setup_arch(void)
}
tsi108_csr_vir_base = get_vir_csrbase();
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_HDA1;
-#endif
-
-#ifdef CONFIG_BLK_DEV_INITRD
- ROOT_DEV = Root_RAM0;
-#endif
-
/* setup PCI host bridge */
#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
@@ -143,7 +132,7 @@ static void __init mpc7448_hpc2_init_IRQ(void)
tsi_pic = of_find_node_by_type(NULL, "open-pic");
if (tsi_pic) {
unsigned int size;
- const void *prop = get_property(tsi_pic, "reg", &size);
+ const void *prop = of_get_property(tsi_pic, "reg", &size);
mpic_paddr = of_translate_address(tsi_pic, prop);
}
diff --git a/arch/powerpc/platforms/iseries/Kconfig b/arch/powerpc/platforms/iseries/Kconfig
index 54e6b3b6f261..46c3a8e7c3a8 100644
--- a/arch/powerpc/platforms/iseries/Kconfig
+++ b/arch/powerpc/platforms/iseries/Kconfig
@@ -1,3 +1,7 @@
+config PPC_ISERIES
+ bool "IBM Legacy iSeries"
+ depends on PPC_MULTIPLATFORM && PPC64
+ select PPC_INDIRECT_IO
menu "iSeries device drivers"
depends on PPC_ISERIES
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index d7a756d5135c..3b6a9666c2c0 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -171,7 +171,7 @@ void iommu_devnode_init_iSeries(struct pci_dev *pdev, struct device_node *dn)
{
struct iommu_table *tbl;
struct pci_dn *pdn = PCI_DN(dn);
- const u32 *lsn = get_property(dn, "linux,logical-slot-number", NULL);
+ const u32 *lsn = of_get_property(dn, "linux,logical-slot-number", NULL);
BUG_ON(lsn == NULL);
@@ -194,5 +194,5 @@ void iommu_init_early_iSeries(void)
ppc_md.tce_build = tce_build_iSeries;
ppc_md.tce_free = tce_free_iSeries;
- pci_dma_ops = &dma_iommu_ops;
+ set_pci_dma_ops(&dma_iommu_ops);
}
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index 5225abfafd9b..63b33675848b 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -30,7 +30,6 @@
#include <linux/param.h>
#include <linux/string.h>
#include <linux/bootmem.h>
-#include <linux/ide.h>
#include <linux/irq.h>
#include <linux/spinlock.h>
@@ -337,6 +336,8 @@ unsigned int iSeries_get_irq(void)
return irq;
}
+#ifdef CONFIG_PCI
+
static int iseries_irq_host_map(struct irq_host *h, unsigned int virq,
irq_hw_number_t hw)
{
@@ -384,3 +385,4 @@ void __init iSeries_init_IRQ(void)
"failed with rc 0x%x\n", ret);
}
+#endif /* CONFIG_PCI */
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index 4a06d9c34986..9c974227155e 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -24,7 +24,6 @@
#include <linux/string.h>
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/ide.h>
#include <linux/pci.h>
#include <asm/io.h>
@@ -177,7 +176,7 @@ void __init iSeries_pci_final_fixup(void)
struct pci_dn *pdn = PCI_DN(node);
const u32 *agent;
- agent = get_property(node, "linux,agent-id", NULL);
+ agent = of_get_property(node, "linux,agent-id", NULL);
if ((pdn != NULL) && (agent != NULL)) {
u8 irq = iSeries_allocate_IRQ(pdn->busno, 0,
pdn->bussubno);
@@ -755,7 +754,7 @@ void __init iSeries_pcibios_init(void)
if ((node->type == NULL) || (strcmp(node->type, "pci") != 0))
continue;
- busp = get_property(node, "bus-range", NULL);
+ busp = of_get_property(node, "bus-range", NULL);
if (busp == NULL)
continue;
bus = *busp;
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index cce7e309340c..7f5dcee814d4 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -628,15 +628,6 @@ static void iseries_iounmap(volatile void __iomem *token)
{
}
-/*
- * iSeries has no legacy IO, anything calling this function has to
- * fail or bad things will happen
- */
-static int iseries_check_legacy_ioport(unsigned int baseport)
-{
- return -ENODEV;
-}
-
static int __init iseries_probe(void)
{
unsigned long root = of_get_flat_dt_root();
@@ -667,7 +658,6 @@ define_machine(iseries) {
.calibrate_decr = generic_calibrate_decr,
.progress = iSeries_progress,
.probe = iseries_probe,
- .check_legacy_ioport = iseries_check_legacy_ioport,
.ioremap = iseries_ioremap,
.iounmap = iseries_iounmap,
/* XXX Implement enable_pmcs for iSeries */
diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c
index e2100ece9c65..2ca2d8a9de97 100644
--- a/arch/powerpc/platforms/iseries/viopath.c
+++ b/arch/powerpc/platforms/iseries/viopath.c
@@ -155,7 +155,7 @@ static int proc_viopath_show(struct seq_file *m, void *v)
node = of_find_node_by_path("/");
sysid = NULL;
if (node != NULL)
- sysid = get_property(node, "system-id", NULL);
+ sysid = of_get_property(node, "system-id", NULL);
if (sysid == NULL)
seq_printf(m, "SRLNBR=<UNKNOWN>\n");
diff --git a/arch/powerpc/platforms/maple/Kconfig b/arch/powerpc/platforms/maple/Kconfig
new file mode 100644
index 000000000000..f7c95eb5d8ba
--- /dev/null
+++ b/arch/powerpc/platforms/maple/Kconfig
@@ -0,0 +1,17 @@
+config PPC_MAPLE
+ depends on PPC_MULTIPLATFORM && PPC64
+ bool "Maple 970FX Evaluation Board"
+ select MPIC
+ select U3_DART
+ select MPIC_U3_HT_IRQS
+ select GENERIC_TBSYNC
+ select PPC_UDBG_16550
+ select PPC_970_NAP
+ select PPC_NATIVE
+ select PPC_RTAS
+ select MMIO_NVRAM
+ select ATA_NONSTANDARD if ATA
+ default n
+ help
+ This option enables support for the Maple 970FX Evaluation Board.
+ For more information, refer to <http://www.970eval.com>
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index 73c59904697f..b1d3b99c3f9d 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -44,11 +44,11 @@ static int __init fixup_one_level_bus_range(struct device_node *node, int higher
int len;
/* For PCI<->PCI bridges or CardBus bridges, we go down */
- class_code = get_property(node, "class-code", NULL);
+ class_code = of_get_property(node, "class-code", NULL);
if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
continue;
- bus_range = get_property(node, "bus-range", &len);
+ bus_range = of_get_property(node, "bus-range", &len);
if (bus_range != NULL && len > 2 * sizeof(int)) {
if (bus_range[1] > higher)
higher = bus_range[1];
@@ -77,7 +77,7 @@ static void __init fixup_bus_range(struct device_node *bridge)
bridge->full_name);
return;
}
- bus_range = (int *)prop->value;
+ bus_range = prop->value;
bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]);
}
@@ -454,7 +454,7 @@ static int __init add_bridge(struct device_node *dev)
DBG("Adding PCI host bridge %s\n", dev->full_name);
- bus_range = get_property(dev, "bus-range", &len);
+ bus_range = of_get_property(dev, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int)) {
printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
dev->full_name);
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index 82d3f9e28d7c..2a30c5b2532e 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -32,7 +32,6 @@
#include <linux/initrd.h>
#include <linux/vt_kern.h>
#include <linux/console.h>
-#include <linux/ide.h>
#include <linux/pci.h>
#include <linux/adb.h>
#include <linux/cuda.h>
@@ -114,8 +113,8 @@ static void maple_restart(char *cmd)
printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
goto fail;
}
- maple_nvram_offset = get_property(sp, "restart-addr", NULL);
- maple_nvram_command = get_property(sp, "restart-value", NULL);
+ maple_nvram_offset = of_get_property(sp, "restart-addr", NULL);
+ maple_nvram_command = of_get_property(sp, "restart-value", NULL);
of_node_put(sp);
/* send command */
@@ -141,8 +140,8 @@ static void maple_power_off(void)
printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
goto fail;
}
- maple_nvram_offset = get_property(sp, "power-off-addr", NULL);
- maple_nvram_command = get_property(sp, "power-off-value", NULL);
+ maple_nvram_offset = of_get_property(sp, "power-off-addr", NULL);
+ maple_nvram_command = of_get_property(sp, "power-off-value", NULL);
of_node_put(sp);
/* send command */
@@ -249,8 +248,8 @@ static void __init maple_init_IRQ(void)
/* Find address list in /platform-open-pic */
root = of_find_node_by_path("/");
- naddr = prom_n_addr_cells(root);
- opprop = get_property(root, "platform-open-pic", &opplen);
+ naddr = of_n_addr_cells(root);
+ opprop = of_get_property(root, "platform-open-pic", &opplen);
if (opprop != 0) {
openpic_addr = of_read_number(opprop, naddr);
has_isus = (opplen > naddr);
@@ -261,11 +260,11 @@ static void __init maple_init_IRQ(void)
BUG_ON(openpic_addr == 0);
/* Check for a big endian MPIC */
- if (get_property(np, "big-endian", NULL) != NULL)
+ if (of_get_property(np, "big-endian", NULL) != NULL)
flags |= MPIC_BIG_ENDIAN;
/* XXX Maple specific bits */
- flags |= MPIC_BROKEN_U3 | MPIC_WANTS_RESET;
+ flags |= MPIC_U3_HT_IRQS | MPIC_WANTS_RESET;
/* All U3/U4 are big-endian, older SLOF firmware doesn't encode this */
flags |= MPIC_BIG_ENDIAN;
diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig
index 68dc529dfd2f..eb4dbc705b06 100644
--- a/arch/powerpc/platforms/pasemi/Kconfig
+++ b/arch/powerpc/platforms/pasemi/Kconfig
@@ -1,3 +1,15 @@
+config PPC_PASEMI
+ depends on PPC_MULTIPLATFORM && PPC64
+ bool "PA Semi SoC-based platforms"
+ default n
+ select MPIC
+ select PPC_UDBG_16550
+ select GENERIC_TBSYNC
+ select PPC_NATIVE
+ help
+ This option enables support for PA Semi's PWRficient line
+ of SoC processors, including PA6T-1682M
+
menu "PA Semi PWRficient options"
depends on PPC_PASEMI
@@ -7,4 +19,11 @@ config PPC_PASEMI_IOMMU
help
IOMMU support for PA6T-1682M
+config PPC_PASEMI_MDIO
+ depends on PHYLIB
+ tristate "MDIO support via GPIO"
+ default y
+ help
+ Driver for MDIO via GPIO on PWRficient platforms
+
endmenu
diff --git a/arch/powerpc/platforms/pasemi/Makefile b/arch/powerpc/platforms/pasemi/Makefile
index e657ccae90a9..2cd2a4f26a48 100644
--- a/arch/powerpc/platforms/pasemi/Makefile
+++ b/arch/powerpc/platforms/pasemi/Makefile
@@ -1,2 +1,3 @@
obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o
-
+obj-$(CONFIG_PPC_PASEMI_MDIO) += gpio_mdio.o
+obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o
diff --git a/arch/powerpc/platforms/pasemi/cpufreq.c b/arch/powerpc/platforms/pasemi/cpufreq.c
new file mode 100644
index 000000000000..2a57d6023685
--- /dev/null
+++ b/arch/powerpc/platforms/pasemi/cpufreq.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2007 PA Semi, Inc
+ *
+ * Authors: Egor Martovetsky <egor@pasemi.com>
+ * Olof Johansson <olof@lixom.net>
+ *
+ * Maintained by: Olof Johansson <olof@lixom.net>
+ *
+ * Based on arch/powerpc/platforms/cell/cbe_cpufreq.c:
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/cpufreq.h>
+#include <linux/timer.h>
+
+#include <asm/hw_irq.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+
+#define SDCASR_REG 0x0100
+#define SDCASR_REG_STRIDE 0x1000
+#define SDCPWR_CFGA0_REG 0x0100
+#define SDCPWR_PWST0_REG 0x0000
+#define SDCPWR_GIZTIME_REG 0x0440
+
+/* SDCPWR_GIZTIME_REG fields */
+#define SDCPWR_GIZTIME_GR 0x80000000
+#define SDCPWR_GIZTIME_LONGLOCK 0x000000ff
+
+/* Offset of ASR registers from SDC base */
+#define SDCASR_OFFSET 0x120000
+
+static void __iomem *sdcpwr_mapbase;
+static void __iomem *sdcasr_mapbase;
+
+static DEFINE_MUTEX(pas_switch_mutex);
+
+/* Current astate, is used when waking up from power savings on
+ * one core, in case the other core has switched states during
+ * the idle time.
+ */
+static int current_astate;
+
+/* We support 5(A0-A4) power states excluding turbo(A5-A6) modes */
+static struct cpufreq_frequency_table pas_freqs[] = {
+ {0, 0},
+ {1, 0},
+ {2, 0},
+ {3, 0},
+ {4, 0},
+ {0, CPUFREQ_TABLE_END},
+};
+
+static struct freq_attr *pas_cpu_freqs_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
+/*
+ * hardware specific functions
+ */
+
+static int get_astate_freq(int astate)
+{
+ u32 ret;
+ ret = in_le32(sdcpwr_mapbase + SDCPWR_CFGA0_REG + (astate * 0x10));
+
+ return ret & 0x3f;
+}
+
+static int get_cur_astate(int cpu)
+{
+ u32 ret;
+
+ ret = in_le32(sdcpwr_mapbase + SDCPWR_PWST0_REG);
+ ret = (ret >> (cpu * 4)) & 0x7;
+
+ return ret;
+}
+
+static int get_gizmo_latency(void)
+{
+ u32 giztime, ret;
+
+ giztime = in_le32(sdcpwr_mapbase + SDCPWR_GIZTIME_REG);
+
+ /* just provide the upper bound */
+ if (giztime & SDCPWR_GIZTIME_GR)
+ ret = (giztime & SDCPWR_GIZTIME_LONGLOCK) * 128000;
+ else
+ ret = (giztime & SDCPWR_GIZTIME_LONGLOCK) * 1000;
+
+ return ret;
+}
+
+static void set_astate(int cpu, unsigned int astate)
+{
+ u64 flags;
+
+ /* Return if called before init has run */
+ if (unlikely(!sdcasr_mapbase))
+ return;
+
+ local_irq_save(flags);
+
+ out_le32(sdcasr_mapbase + SDCASR_REG + SDCASR_REG_STRIDE*cpu, astate);
+
+ local_irq_restore(flags);
+}
+
+void restore_astate(int cpu)
+{
+ set_astate(cpu, current_astate);
+}
+
+/*
+ * cpufreq functions
+ */
+
+static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+ const u32 *max_freqp;
+ u32 max_freq;
+ int i, cur_astate;
+ struct resource res;
+ struct device_node *cpu, *dn;
+ int err = -ENODEV;
+
+ cpu = of_get_cpu_node(policy->cpu, NULL);
+
+ if (!cpu)
+ goto out;
+
+ dn = of_find_compatible_node(NULL, "sdc", "1682m-sdc");
+ if (!dn)
+ goto out;
+ err = of_address_to_resource(dn, 0, &res);
+ of_node_put(dn);
+ if (err)
+ goto out;
+ sdcasr_mapbase = ioremap(res.start + SDCASR_OFFSET, 0x2000);
+ if (!sdcasr_mapbase) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ dn = of_find_compatible_node(NULL, "gizmo", "1682m-gizmo");
+ if (!dn) {
+ err = -ENODEV;
+ goto out_unmap_sdcasr;
+ }
+ err = of_address_to_resource(dn, 0, &res);
+ of_node_put(dn);
+ if (err)
+ goto out_unmap_sdcasr;
+ sdcpwr_mapbase = ioremap(res.start, 0x1000);
+ if (!sdcpwr_mapbase) {
+ err = -EINVAL;
+ goto out_unmap_sdcasr;
+ }
+
+ pr_debug("init cpufreq on CPU %d\n", policy->cpu);
+
+ max_freqp = of_get_property(cpu, "clock-frequency", NULL);
+ if (!max_freqp) {
+ err = -EINVAL;
+ goto out_unmap_sdcpwr;
+ }
+
+ /* we need the freq in kHz */
+ max_freq = *max_freqp / 1000;
+
+ pr_debug("max clock-frequency is at %u kHz\n", max_freq);
+ pr_debug("initializing frequency table\n");
+
+ /* initialize frequency table */
+ for (i=0; pas_freqs[i].frequency!=CPUFREQ_TABLE_END; i++) {
+ pas_freqs[i].frequency = get_astate_freq(pas_freqs[i].index) * 100000;
+ pr_debug("%d: %d\n", i, pas_freqs[i].frequency);
+ }
+
+ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+
+ policy->cpuinfo.transition_latency = get_gizmo_latency();
+
+ cur_astate = get_cur_astate(policy->cpu);
+ pr_debug("current astate is at %d\n",cur_astate);
+
+ policy->cur = pas_freqs[cur_astate].frequency;
+ policy->cpus = cpu_online_map;
+
+ cpufreq_frequency_table_get_attr(pas_freqs, policy->cpu);
+
+ /* this ensures that policy->cpuinfo_min and policy->cpuinfo_max
+ * are set correctly
+ */
+ return cpufreq_frequency_table_cpuinfo(policy, pas_freqs);
+
+out_unmap_sdcpwr:
+ iounmap(sdcpwr_mapbase);
+
+out_unmap_sdcasr:
+ iounmap(sdcasr_mapbase);
+out:
+ return err;
+}
+
+static int pas_cpufreq_cpu_exit(struct cpufreq_policy *policy)
+{
+ if (sdcasr_mapbase)
+ iounmap(sdcasr_mapbase);
+ if (sdcpwr_mapbase)
+ iounmap(sdcpwr_mapbase);
+
+ cpufreq_frequency_table_put_attr(policy->cpu);
+ return 0;
+}
+
+static int pas_cpufreq_verify(struct cpufreq_policy *policy)
+{
+ return cpufreq_frequency_table_verify(policy, pas_freqs);
+}
+
+static int pas_cpufreq_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ struct cpufreq_freqs freqs;
+ int pas_astate_new;
+ int i;
+
+ cpufreq_frequency_table_target(policy,
+ pas_freqs,
+ target_freq,
+ relation,
+ &pas_astate_new);
+
+ freqs.old = policy->cur;
+ freqs.new = pas_freqs[pas_astate_new].frequency;
+ freqs.cpu = policy->cpu;
+
+ mutex_lock(&pas_switch_mutex);
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+ pr_debug("setting frequency for cpu %d to %d kHz, 1/%d of max frequency\n",
+ policy->cpu,
+ pas_freqs[pas_astate_new].frequency,
+ pas_freqs[pas_astate_new].index);
+
+ current_astate = pas_astate_new;
+
+ for_each_online_cpu(i)
+ set_astate(i, pas_astate_new);
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ mutex_unlock(&pas_switch_mutex);
+
+ return 0;
+}
+
+static struct cpufreq_driver pas_cpufreq_driver = {
+ .name = "pas-cpufreq",
+ .owner = THIS_MODULE,
+ .flags = CPUFREQ_CONST_LOOPS,
+ .init = pas_cpufreq_cpu_init,
+ .exit = pas_cpufreq_cpu_exit,
+ .verify = pas_cpufreq_verify,
+ .target = pas_cpufreq_target,
+ .attr = pas_cpu_freqs_attr,
+};
+
+/*
+ * module init and destoy
+ */
+
+static int __init pas_cpufreq_init(void)
+{
+ if (!machine_is_compatible("PA6T-1682M"))
+ return -ENODEV;
+
+ return cpufreq_register_driver(&pas_cpufreq_driver);
+}
+
+static void __exit pas_cpufreq_exit(void)
+{
+ cpufreq_unregister_driver(&pas_cpufreq_driver);
+}
+
+module_init(pas_cpufreq_init);
+module_exit(pas_cpufreq_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>, Olof Johansson <olof@lixom.net>");
diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c
new file mode 100644
index 000000000000..c91a33593bb8
--- /dev/null
+++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2006-2007 PA Semi, Inc
+ *
+ * Author: Olof Johansson, PA Semi
+ *
+ * Maintained by: Olof Johansson <olof@lixom.net>
+ *
+ * Based on drivers/net/fs_enet/mii-bitbang.c.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <asm/of_platform.h>
+
+#define DELAY 1
+
+static void __iomem *gpio_regs;
+
+struct gpio_priv {
+ int mdc_pin;
+ int mdio_pin;
+};
+
+#define MDC_PIN(bus) (((struct gpio_priv *)bus->priv)->mdc_pin)
+#define MDIO_PIN(bus) (((struct gpio_priv *)bus->priv)->mdio_pin)
+
+static inline void mdio_lo(struct mii_bus *bus)
+{
+ out_le32(gpio_regs+0x10, 1 << MDIO_PIN(bus));
+}
+
+static inline void mdio_hi(struct mii_bus *bus)
+{
+ out_le32(gpio_regs, 1 << MDIO_PIN(bus));
+}
+
+static inline void mdc_lo(struct mii_bus *bus)
+{
+ out_le32(gpio_regs+0x10, 1 << MDC_PIN(bus));
+}
+
+static inline void mdc_hi(struct mii_bus *bus)
+{
+ out_le32(gpio_regs, 1 << MDC_PIN(bus));
+}
+
+static inline void mdio_active(struct mii_bus *bus)
+{
+ out_le32(gpio_regs+0x20, (1 << MDC_PIN(bus)) | (1 << MDIO_PIN(bus)));
+}
+
+static inline void mdio_tristate(struct mii_bus *bus)
+{
+ out_le32(gpio_regs+0x30, (1 << MDIO_PIN(bus)));
+}
+
+static inline int mdio_read(struct mii_bus *bus)
+{
+ return !!(in_le32(gpio_regs+0x40) & (1 << MDIO_PIN(bus)));
+}
+
+static void clock_out(struct mii_bus *bus, int bit)
+{
+ if (bit)
+ mdio_hi(bus);
+ else
+ mdio_lo(bus);
+ udelay(DELAY);
+ mdc_hi(bus);
+ udelay(DELAY);
+ mdc_lo(bus);
+}
+
+/* Utility to send the preamble, address, and register (common to read and write). */
+static void bitbang_pre(struct mii_bus *bus, int read, u8 addr, u8 reg)
+{
+ int i;
+
+ /* CFE uses a really long preamble (40 bits). We'll do the same. */
+ mdio_active(bus);
+ for (i = 0; i < 40; i++) {
+ clock_out(bus, 1);
+ }
+
+ /* send the start bit (01) and the read opcode (10) or write (10) */
+ clock_out(bus, 0);
+ clock_out(bus, 1);
+
+ clock_out(bus, read);
+ clock_out(bus, !read);
+
+ /* send the PHY address */
+ for (i = 0; i < 5; i++) {
+ clock_out(bus, (addr & 0x10) != 0);
+ addr <<= 1;
+ }
+
+ /* send the register address */
+ for (i = 0; i < 5; i++) {
+ clock_out(bus, (reg & 0x10) != 0);
+ reg <<= 1;
+ }
+}
+
+static int gpio_mdio_read(struct mii_bus *bus, int phy_id, int location)
+{
+ u16 rdreg;
+ int ret, i;
+ u8 addr = phy_id & 0xff;
+ u8 reg = location & 0xff;
+
+ bitbang_pre(bus, 1, addr, reg);
+
+ /* tri-state our MDIO I/O pin so we can read */
+ mdio_tristate(bus);
+ udelay(DELAY);
+ mdc_hi(bus);
+ udelay(DELAY);
+ mdc_lo(bus);
+
+ /* read 16 bits of register data, MSB first */
+ rdreg = 0;
+ for (i = 0; i < 16; i++) {
+ mdc_lo(bus);
+ udelay(DELAY);
+ mdc_hi(bus);
+ udelay(DELAY);
+ mdc_lo(bus);
+ udelay(DELAY);
+ rdreg <<= 1;
+ rdreg |= mdio_read(bus);
+ }
+
+ mdc_hi(bus);
+ udelay(DELAY);
+ mdc_lo(bus);
+ udelay(DELAY);
+
+ ret = rdreg;
+
+ return ret;
+}
+
+static int gpio_mdio_write(struct mii_bus *bus, int phy_id, int location, u16 val)
+{
+ int i;
+
+ u8 addr = phy_id & 0xff;
+ u8 reg = location & 0xff;
+ u16 value = val & 0xffff;
+
+ bitbang_pre(bus, 0, addr, reg);
+
+ /* send the turnaround (10) */
+ mdc_lo(bus);
+ mdio_hi(bus);
+ udelay(DELAY);
+ mdc_hi(bus);
+ udelay(DELAY);
+ mdc_lo(bus);
+ mdio_lo(bus);
+ udelay(DELAY);
+ mdc_hi(bus);
+ udelay(DELAY);
+
+ /* write 16 bits of register data, MSB first */
+ for (i = 0; i < 16; i++) {
+ mdc_lo(bus);
+ if (value & 0x8000)
+ mdio_hi(bus);
+ else
+ mdio_lo(bus);
+ udelay(DELAY);
+ mdc_hi(bus);
+ udelay(DELAY);
+ value <<= 1;
+ }
+
+ /*
+ * Tri-state the MDIO line.
+ */
+ mdio_tristate(bus);
+ mdc_lo(bus);
+ udelay(DELAY);
+ mdc_hi(bus);
+ udelay(DELAY);
+ return 0;
+}
+
+static int gpio_mdio_reset(struct mii_bus *bus)
+{
+ /*nothing here - dunno how to reset it*/
+ return 0;
+}
+
+
+static int __devinit gpio_mdio_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ struct device *dev = &ofdev->dev;
+ struct device_node *np = ofdev->node;
+ struct device_node *gpio_np;
+ struct mii_bus *new_bus;
+ struct resource res;
+ struct gpio_priv *priv;
+ const unsigned int *prop;
+ int err = 0;
+ int i;
+
+ gpio_np = of_find_compatible_node(NULL, "gpio", "1682m-gpio");
+
+ if (!gpio_np)
+ return -ENODEV;
+
+ err = of_address_to_resource(gpio_np, 0, &res);
+ of_node_put(gpio_np);
+
+ if (err)
+ return -EINVAL;
+
+ if (!gpio_regs)
+ gpio_regs = ioremap(res.start, 0x100);
+
+ if (!gpio_regs)
+ return -EPERM;
+
+ priv = kzalloc(sizeof(struct gpio_priv), GFP_KERNEL);
+ if (priv == NULL)
+ return -ENOMEM;
+
+ new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+
+ if (new_bus == NULL)
+ return -ENOMEM;
+
+ new_bus->name = "pasemi gpio mdio bus",
+ new_bus->read = &gpio_mdio_read,
+ new_bus->write = &gpio_mdio_write,
+ new_bus->reset = &gpio_mdio_reset,
+
+ prop = of_get_property(np, "reg", NULL);
+ new_bus->id = *prop;
+ new_bus->priv = priv;
+
+ new_bus->phy_mask = 0;
+
+ new_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+ for(i = 0; i < PHY_MAX_ADDR; ++i)
+ new_bus->irq[i] = irq_create_mapping(NULL, 10);
+
+
+ prop = of_get_property(np, "mdc-pin", NULL);
+ priv->mdc_pin = *prop;
+
+ prop = of_get_property(np, "mdio-pin", NULL);
+ priv->mdio_pin = *prop;
+
+ new_bus->dev = dev;
+ dev_set_drvdata(dev, new_bus);
+
+ err = mdiobus_register(new_bus);
+
+ if (0 != err) {
+ printk(KERN_ERR "%s: Cannot register as MDIO bus, err %d\n",
+ new_bus->name, err);
+ goto bus_register_fail;
+ }
+
+ return 0;
+
+bus_register_fail:
+ kfree(new_bus);
+
+ return err;
+}
+
+
+static int gpio_mdio_remove(struct of_device *dev)
+{
+ struct mii_bus *bus = dev_get_drvdata(&dev->dev);
+
+ mdiobus_unregister(bus);
+
+ dev_set_drvdata(&dev->dev, NULL);
+
+ kfree(bus->priv);
+ bus->priv = NULL;
+ kfree(bus);
+
+ return 0;
+}
+
+static struct of_device_id gpio_mdio_match[] =
+{
+ {
+ .compatible = "gpio-mdio",
+ },
+ {},
+};
+
+static struct of_platform_driver gpio_mdio_driver =
+{
+ .name = "gpio-mdio-bitbang",
+ .match_table = gpio_mdio_match,
+ .probe = gpio_mdio_probe,
+ .remove = gpio_mdio_remove,
+};
+
+int gpio_mdio_init(void)
+{
+ return of_register_platform_driver(&gpio_mdio_driver);
+}
+
+void gpio_mdio_exit(void)
+{
+ of_unregister_platform_driver(&gpio_mdio_driver);
+}
+device_initcall(gpio_mdio_init);
+
diff --git a/arch/powerpc/platforms/pasemi/idle.c b/arch/powerpc/platforms/pasemi/idle.c
index 1ca3ff381591..5985ce0c5c48 100644
--- a/arch/powerpc/platforms/pasemi/idle.c
+++ b/arch/powerpc/platforms/pasemi/idle.c
@@ -61,6 +61,10 @@ static int pasemi_system_reset_exception(struct pt_regs *regs)
/* do system reset */
return 0;
}
+
+ /* Set higher astate since we come out of power savings at 0 */
+ restore_astate(hard_smp_processor_id());
+
/* everything handled */
regs->msr |= MSR_RI;
return 1;
@@ -68,6 +72,11 @@ static int pasemi_system_reset_exception(struct pt_regs *regs)
void __init pasemi_idle_init(void)
{
+#ifndef CONFIG_PPC_PASEMI_CPUFREQ
+ printk(KERN_WARNING "No cpufreq driver, powersavings modes disabled\n");
+ current_mode = 0;
+#endif
+
ppc_md.system_reset_exception = pasemi_system_reset_exception;
ppc_md.power_save = modes[current_mode].entry;
printk(KERN_INFO "Using PA6T idle loop (%s)\n", modes[current_mode].name);
diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c
index 459a53b7d24d..95fa6a7d15ee 100644
--- a/arch/powerpc/platforms/pasemi/iommu.c
+++ b/arch/powerpc/platforms/pasemi/iommu.c
@@ -77,7 +77,7 @@
#define IOBMAP_L2E_V 0x80000000
#define IOBMAP_L2E_V_CACHED 0xc0000000
-static u32 *iob;
+static u32 __iomem *iob;
static u32 iob_l1_emptyval;
static u32 iob_l2_emptyval;
static u32 *iob_l2_base;
@@ -249,13 +249,13 @@ void iommu_init_early_pasemi(void)
iommu_off = 1;
#else
iommu_off = of_chosen &&
- get_property(of_chosen, "linux,iommu-off", NULL);
+ of_get_property(of_chosen, "linux,iommu-off", NULL);
#endif
if (iommu_off) {
/* Direct I/O, IOMMU off */
ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_null;
ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_null;
- pci_dma_ops = &dma_direct_ops;
+ set_pci_dma_ops(&dma_direct_ops);
return;
}
@@ -266,7 +266,7 @@ void iommu_init_early_pasemi(void)
ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pasemi;
ppc_md.tce_build = iobmap_build;
ppc_md.tce_free = iobmap_free;
- pci_dma_ops = &dma_iommu_ops;
+ set_pci_dma_ops(&dma_iommu_ops);
}
void __init alloc_iobmap_l2(void)
diff --git a/arch/powerpc/platforms/pasemi/pasemi.h b/arch/powerpc/platforms/pasemi/pasemi.h
index 2d3927e6edb0..be8495497611 100644
--- a/arch/powerpc/platforms/pasemi/pasemi.h
+++ b/arch/powerpc/platforms/pasemi/pasemi.h
@@ -14,6 +14,14 @@ extern void __init pasemi_idle_init(void);
extern void idle_spin(void);
extern void idle_doze(void);
+/* Restore astate to last set */
+#ifdef CONFIG_PPC_PASEMI_CPUFREQ
+extern void restore_astate(int cpu);
+#else
+static inline void restore_astate(int cpu)
+{
+}
+#endif
#endif /* _PASEMI_PASEMI_H */
diff --git a/arch/powerpc/platforms/pasemi/pci.c b/arch/powerpc/platforms/pasemi/pci.c
index 7ecb2ba24db9..056243da360b 100644
--- a/arch/powerpc/platforms/pasemi/pci.c
+++ b/arch/powerpc/platforms/pasemi/pci.c
@@ -33,7 +33,17 @@
#define PA_PXP_CFA(bus, devfn, off) (((bus) << 20) | ((devfn) << 12) | (off))
-#define CONFIG_OFFSET_VALID(off) ((off) < 4096)
+static inline int pa_pxp_offset_valid(u8 bus, u8 devfn, int offset)
+{
+ /* Device 0 Function 0 is special: It's config space spans function 1 as
+ * well, so allow larger offset. It's really a two-function device but the
+ * second function does not probe.
+ */
+ if (bus == 0 && devfn == 0)
+ return offset < 8192;
+ else
+ return offset < 4096;
+}
static void volatile __iomem *pa_pxp_cfg_addr(struct pci_controller *hose,
u8 bus, u8 devfn, int offset)
@@ -51,7 +61,7 @@ static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn,
if (!hose)
return PCIBIOS_DEVICE_NOT_FOUND;
- if (!CONFIG_OFFSET_VALID(offset))
+ if (!pa_pxp_offset_valid(bus->number, devfn, offset))
return PCIBIOS_BAD_REGISTER_NUMBER;
addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset);
@@ -85,7 +95,7 @@ static int pa_pxp_write_config(struct pci_bus *bus, unsigned int devfn,
if (!hose)
return PCIBIOS_DEVICE_NOT_FOUND;
- if (!CONFIG_OFFSET_VALID(offset))
+ if (!pa_pxp_offset_valid(bus->number, devfn, offset))
return PCIBIOS_BAD_REGISTER_NUMBER;
addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset);
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
index 449cf1a08291..f88f0ec4c8cb 100644
--- a/arch/powerpc/platforms/pasemi/setup.c
+++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -35,6 +35,7 @@
#include <asm/mpic.h>
#include <asm/smp.h>
#include <asm/time.h>
+#include <asm/of_platform.h>
#include "pasemi.h"
@@ -101,12 +102,6 @@ void __init pas_setup_arch(void)
pasemi_idle_init();
}
-/* No legacy IO on our parts */
-static int pas_check_legacy_ioport(unsigned int baseport)
-{
- return -ENODEV;
-}
-
static __init void pas_init_IRQ(void)
{
struct device_node *np;
@@ -136,8 +131,8 @@ static __init void pas_init_IRQ(void)
/* Find address list in /platform-open-pic */
root = of_find_node_by_path("/");
- naddr = prom_n_addr_cells(root);
- opprop = get_property(root, "platform-open-pic", &opplen);
+ naddr = of_n_addr_cells(root);
+ opprop = of_get_property(root, "platform-open-pic", &opplen);
if (!opprop) {
printk(KERN_ERR "No platform-open-pic property.\n");
of_node_put(root);
@@ -147,7 +142,7 @@ static __init void pas_init_IRQ(void)
printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
mpic = mpic_alloc(mpic_node, openpic_addr,
- MPIC_PRIMARY|MPIC_LARGE_VECTORS,
+ MPIC_PRIMARY|MPIC_LARGE_VECTORS|MPIC_WANTS_RESET,
0, 0, " PAS-OPIC ");
BUG_ON(!mpic);
@@ -209,6 +204,20 @@ static void __init pas_init_early(void)
iommu_init_early_pasemi();
}
+static struct of_device_id pasemi_bus_ids[] = {
+ { .type = "sdc", },
+ {},
+};
+
+static int __init pasemi_publish_devices(void)
+{
+ /* Publish OF platform devices for southbridge IOs */
+ of_platform_bus_probe(NULL, pasemi_bus_ids, NULL);
+
+ return 0;
+}
+device_initcall(pasemi_publish_devices);
+
/*
* Called very early, MMU is off, device-tree isn't unflattened
@@ -237,7 +246,6 @@ define_machine(pas) {
.restart = pas_restart,
.get_boot_time = pas_get_boot_time,
.calibrate_decr = generic_calibrate_decr,
- .check_legacy_ioport = pas_check_legacy_ioport,
.progress = pas_progress,
.machine_check_exception = pas_machine_check_handler,
.pci_irq_fixup = pas_pci_irq_fixup,
diff --git a/arch/powerpc/platforms/powermac/Kconfig b/arch/powerpc/platforms/powermac/Kconfig
new file mode 100644
index 000000000000..5b7afe50039a
--- /dev/null
+++ b/arch/powerpc/platforms/powermac/Kconfig
@@ -0,0 +1,20 @@
+config PPC_PMAC
+ bool "Apple PowerMac based machines"
+ depends on PPC_MULTIPLATFORM
+ select MPIC
+ select PPC_INDIRECT_PCI if PPC32
+ select PPC_MPC106 if PPC32
+ select PPC_NATIVE
+ default y
+
+config PPC_PMAC64
+ bool
+ depends on PPC_PMAC && POWER4
+ select MPIC
+ select U3_DART
+ select MPIC_U3_HT_IRQS
+ select GENERIC_TBSYNC
+ select PPC_970_NAP
+ default y
+
+
diff --git a/arch/powerpc/platforms/powermac/backlight.c b/arch/powerpc/platforms/powermac/backlight.c
index c3a89414ddc0..d679964ae2ab 100644
--- a/arch/powerpc/platforms/powermac/backlight.c
+++ b/arch/powerpc/platforms/powermac/backlight.c
@@ -37,33 +37,35 @@ static int pmac_backlight_set_legacy_queued;
*/
static atomic_t kernel_backlight_disabled = ATOMIC_INIT(0);
-/* Protect the pmac_backlight variable */
+/* Protect the pmac_backlight variable below.
+ You should hold this lock when using the pmac_backlight pointer to
+ prevent its potential removal. */
DEFINE_MUTEX(pmac_backlight_mutex);
/* Main backlight storage
*
- * Backlight drivers in this variable are required to have the "props"
+ * Backlight drivers in this variable are required to have the "ops"
* attribute set and to have an update_status function.
*
* We can only store one backlight here, but since Apple laptops have only one
* internal display, it doesn't matter. Other backlight drivers can be used
* independently.
*
- * Lock ordering:
- * pmac_backlight_mutex (global, main backlight)
- * pmac_backlight->sem (backlight class)
*/
struct backlight_device *pmac_backlight;
int pmac_has_backlight_type(const char *type)
{
- struct device_node* bk_node = find_devices("backlight");
+ struct device_node* bk_node = of_find_node_by_name(NULL, "backlight");
if (bk_node) {
- const char *prop = get_property(bk_node,
+ const char *prop = of_get_property(bk_node,
"backlight-control", NULL);
- if (prop && strncmp(prop, type, strlen(type)) == 0)
+ if (prop && strncmp(prop, type, strlen(type)) == 0) {
+ of_node_put(bk_node);
return 1;
+ }
+ of_node_put(bk_node);
}
return 0;
@@ -104,8 +106,7 @@ static void pmac_backlight_key_worker(struct work_struct *work)
struct backlight_properties *props;
int brightness;
- down(&pmac_backlight->sem);
- props = pmac_backlight->props;
+ props = &pmac_backlight->props;
brightness = props->brightness +
((pmac_backlight_key_queued?-1:1) *
@@ -117,9 +118,7 @@ static void pmac_backlight_key_worker(struct work_struct *work)
brightness = props->max_brightness;
props->brightness = brightness;
- props->update_status(pmac_backlight);
-
- up(&pmac_backlight->sem);
+ backlight_update_status(pmac_backlight);
}
mutex_unlock(&pmac_backlight_mutex);
}
@@ -145,8 +144,7 @@ static int __pmac_backlight_set_legacy_brightness(int brightness)
if (pmac_backlight) {
struct backlight_properties *props;
- down(&pmac_backlight->sem);
- props = pmac_backlight->props;
+ props = &pmac_backlight->props;
props->brightness = brightness *
(props->max_brightness + 1) /
(OLD_BACKLIGHT_MAX + 1);
@@ -156,8 +154,7 @@ static int __pmac_backlight_set_legacy_brightness(int brightness)
else if (props->brightness < 0)
props->brightness = 0;
- props->update_status(pmac_backlight);
- up(&pmac_backlight->sem);
+ backlight_update_status(pmac_backlight);
error = 0;
}
@@ -196,14 +193,11 @@ int pmac_backlight_get_legacy_brightness()
if (pmac_backlight) {
struct backlight_properties *props;
- down(&pmac_backlight->sem);
- props = pmac_backlight->props;
+ props = &pmac_backlight->props;
result = props->brightness *
(OLD_BACKLIGHT_MAX + 1) /
(props->max_brightness + 1);
-
- up(&pmac_backlight->sem);
}
mutex_unlock(&pmac_backlight_mutex);
diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c
index c2b6b4134f68..8943a9456bb7 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_32.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_32.c
@@ -421,7 +421,7 @@ static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
static u32 read_gpio(struct device_node *np)
{
- const u32 *reg = get_property(np, "reg", NULL);
+ const u32 *reg = of_get_property(np, "reg", NULL);
u32 offset;
if (reg == NULL)
@@ -521,13 +521,14 @@ static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode)
int lenp, rc;
const u32 *freqs, *ratio;
- freqs = get_property(cpunode, "bus-frequencies", &lenp);
+ freqs = of_get_property(cpunode, "bus-frequencies", &lenp);
lenp /= sizeof(u32);
if (freqs == NULL || lenp != 2) {
printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n");
return 1;
}
- ratio = get_property(cpunode, "processor-to-bus-ratio*2", NULL);
+ ratio = of_get_property(cpunode, "processor-to-bus-ratio*2",
+ NULL);
if (ratio == NULL) {
printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n");
return 1;
@@ -562,7 +563,7 @@ static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode)
/* If we use the PMU, look for the min & max frequencies in the
* device-tree
*/
- value = get_property(cpunode, "min-clock-frequency", NULL);
+ value = of_get_property(cpunode, "min-clock-frequency", NULL);
if (!value)
return 1;
low_freq = (*value) / 1000;
@@ -571,7 +572,7 @@ static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode)
if (low_freq < 100000)
low_freq *= 10;
- value = get_property(cpunode, "max-clock-frequency", NULL);
+ value = of_get_property(cpunode, "max-clock-frequency", NULL);
if (!value)
return 1;
hi_freq = (*value) / 1000;
@@ -585,7 +586,7 @@ static int pmac_cpufreq_init_7447A(struct device_node *cpunode)
{
struct device_node *volt_gpio_np;
- if (get_property(cpunode, "dynamic-power-step", NULL) == NULL)
+ if (of_get_property(cpunode, "dynamic-power-step", NULL) == NULL)
return 1;
volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select");
@@ -614,11 +615,11 @@ static int pmac_cpufreq_init_750FX(struct device_node *cpunode)
u32 pvr;
const u32 *value;
- if (get_property(cpunode, "dynamic-power-step", NULL) == NULL)
+ if (of_get_property(cpunode, "dynamic-power-step", NULL) == NULL)
return 1;
hi_freq = cur_freq;
- value = get_property(cpunode, "reduced-clock-frequency", NULL);
+ value = of_get_property(cpunode, "reduced-clock-frequency", NULL);
if (!value)
return 1;
low_freq = (*value) / 1000;
@@ -657,19 +658,19 @@ static int __init pmac_cpufreq_setup(void)
return 0;
/* Assume only one CPU */
- cpunode = find_type_devices("cpu");
+ cpunode = of_find_node_by_type(NULL, "cpu");
if (!cpunode)
goto out;
/* Get current cpu clock freq */
- value = get_property(cpunode, "clock-frequency", NULL);
+ value = of_get_property(cpunode, "clock-frequency", NULL);
if (!value)
goto out;
cur_freq = (*value) / 1000;
/* Check for 7447A based MacRISC3 */
if (machine_is_compatible("MacRISC3") &&
- get_property(cpunode, "dynamic-power-step", NULL) &&
+ of_get_property(cpunode, "dynamic-power-step", NULL) &&
PVR_VER(mfspr(SPRN_PVR)) == 0x8003) {
pmac_cpufreq_init_7447A(cpunode);
/* Check for other MacRISC3 machines */
@@ -707,6 +708,7 @@ static int __init pmac_cpufreq_setup(void)
else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000)
pmac_cpufreq_init_750FX(cpunode);
out:
+ of_node_put(cpunode);
if (set_speed_proc == NULL)
return -ENODEV;
diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c
index 9d22361a26d6..567d5523b690 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_64.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_64.c
@@ -410,7 +410,7 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus)
/* Get first CPU node */
for (cpunode = NULL;
(cpunode = of_get_next_child(cpus, cpunode)) != NULL;) {
- const u32 *reg = get_property(cpunode, "reg", NULL);
+ const u32 *reg = of_get_property(cpunode, "reg", NULL);
if (reg == NULL || (*reg) != 0)
continue;
if (!strcmp(cpunode->type, "cpu"))
@@ -422,7 +422,7 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus)
}
/* Check 970FX for now */
- valp = get_property(cpunode, "cpu-version", NULL);
+ valp = of_get_property(cpunode, "cpu-version", NULL);
if (!valp) {
DBG("No cpu-version property !\n");
goto bail_noprops;
@@ -434,7 +434,7 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus)
}
/* Look for the powertune data in the device-tree */
- g5_pmode_data = get_property(cpunode, "power-mode-data",&psize);
+ g5_pmode_data = of_get_property(cpunode, "power-mode-data",&psize);
if (!g5_pmode_data) {
DBG("No power-mode-data !\n");
goto bail_noprops;
@@ -493,7 +493,7 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus)
* half freq in this version. So far, I haven't yet seen a machine
* supporting anything else.
*/
- valp = get_property(cpunode, "clock-frequency", NULL);
+ valp = of_get_property(cpunode, "clock-frequency", NULL);
if (!valp)
return -ENODEV;
max_freq = (*valp)/1000;
@@ -563,7 +563,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
/* Lookup the cpuid eeprom node */
cpuid = of_find_node_by_path("/u3@0,f8000000/i2c@f8001000/cpuid@a0");
if (cpuid != NULL)
- eeprom = get_property(cpuid, "cpuid", NULL);
+ eeprom = of_get_property(cpuid, "cpuid", NULL);
if (eeprom == NULL) {
printk(KERN_ERR "cpufreq: Can't find cpuid EEPROM !\n");
rc = -ENODEV;
@@ -573,13 +573,13 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
/* Lookup the i2c hwclock */
for (hwclock = NULL;
(hwclock = of_find_node_by_name(hwclock, "i2c-hwclock")) != NULL;){
- const char *loc = get_property(hwclock,
+ const char *loc = of_get_property(hwclock,
"hwctrl-location", NULL);
if (loc == NULL)
continue;
if (strcmp(loc, "CPU CLOCK"))
continue;
- if (!get_property(hwclock, "platform-get-frequency", NULL))
+ if (!of_get_property(hwclock, "platform-get-frequency", NULL))
continue;
break;
}
@@ -638,7 +638,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
*/
/* Get max frequency from device-tree */
- valp = get_property(cpunode, "clock-frequency", NULL);
+ valp = of_get_property(cpunode, "clock-frequency", NULL);
if (!valp) {
printk(KERN_ERR "cpufreq: Can't find CPU frequency !\n");
rc = -ENODEV;
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index c29a6a064d22..52cfdd86c928 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -810,6 +810,7 @@ core99_ata100_enable(struct device_node *node, long value)
unsigned long flags;
struct pci_dev *pdev = NULL;
u8 pbus, pid;
+ int rc;
if (uninorth_rev < 0x24)
return -ENODEV;
@@ -828,7 +829,9 @@ core99_ata100_enable(struct device_node *node, long value)
pdev = pci_find_slot(pbus, pid);
if (pdev == NULL)
return 0;
- pci_enable_device(pdev);
+ rc = pci_enable_device(pdev);
+ if (rc)
+ return rc;
pci_set_master(pdev);
}
return 0;
@@ -1041,6 +1044,7 @@ core99_reset_cpu(struct device_node *node, long param, long value)
unsigned long flags;
struct macio_chip *macio;
struct device_node *np;
+ struct device_node *cpus;
const int dflt_reset_lines[] = { KL_GPIO_RESET_CPU0,
KL_GPIO_RESET_CPU1,
KL_GPIO_RESET_CPU2,
@@ -1050,12 +1054,12 @@ core99_reset_cpu(struct device_node *node, long param, long value)
if (macio->type != macio_keylargo)
return -ENODEV;
- np = find_path_device("/cpus");
- if (np == NULL)
+ cpus = of_find_node_by_path("/cpus");
+ if (cpus == NULL)
return -ENODEV;
- for (np = np->child; np != NULL; np = np->sibling) {
- const u32 *num = get_property(np, "reg", NULL);
- const u32 *rst = get_property(np, "soft-reset", NULL);
+ for (np = cpus->child; np != NULL; np = np->sibling) {
+ const u32 *num = of_get_property(np, "reg", NULL);
+ const u32 *rst = of_get_property(np, "soft-reset", NULL);
if (num == NULL || rst == NULL)
continue;
if (param == *num) {
@@ -1063,6 +1067,7 @@ core99_reset_cpu(struct device_node *node, long param, long value)
break;
}
}
+ of_node_put(cpus);
if (np == NULL || reset_io == 0)
reset_io = dflt_reset_lines[param];
@@ -1092,7 +1097,7 @@ core99_usb_enable(struct device_node *node, long param, long value)
macio->type != macio_intrepid)
return -ENODEV;
- prop = get_property(node, "AAPL,clock-id", NULL);
+ prop = of_get_property(node, "AAPL,clock-id", NULL);
if (!prop)
return -ENODEV;
if (strncmp(prop, "usb0u048", 8) == 0)
@@ -1494,17 +1499,18 @@ static long g5_reset_cpu(struct device_node *node, long param, long value)
unsigned long flags;
struct macio_chip *macio;
struct device_node *np;
+ struct device_node *cpus;
macio = &macio_chips[0];
if (macio->type != macio_keylargo2 && macio->type != macio_shasta)
return -ENODEV;
- np = find_path_device("/cpus");
- if (np == NULL)
+ cpus = of_find_node_by_path("/cpus");
+ if (cpus == NULL)
return -ENODEV;
- for (np = np->child; np != NULL; np = np->sibling) {
- const u32 *num = get_property(np, "reg", NULL);
- const u32 *rst = get_property(np, "soft-reset", NULL);
+ for (np = cpus->child; np != NULL; np = np->sibling) {
+ const u32 *num = of_get_property(np, "reg", NULL);
+ const u32 *rst = of_get_property(np, "soft-reset", NULL);
if (num == NULL || rst == NULL)
continue;
if (param == *num) {
@@ -1512,6 +1518,7 @@ static long g5_reset_cpu(struct device_node *node, long param, long value)
break;
}
}
+ of_node_put(cpus);
if (np == NULL || reset_io == 0)
return -ENODEV;
@@ -2401,14 +2408,15 @@ static int __init probe_motherboard(void)
struct macio_chip *macio = &macio_chips[0];
const char *model = NULL;
struct device_node *dt;
+ int ret = 0;
/* Lookup known motherboard type in device-tree. First try an
* exact match on the "model" property, then try a "compatible"
* match is none is found.
*/
- dt = find_devices("device-tree");
+ dt = of_find_node_by_name(NULL, "device-tree");
if (dt != NULL)
- model = get_property(dt, "model", NULL);
+ model = of_get_property(dt, "model", NULL);
for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
if (strcmp(model, pmac_mb_defs[i].model_string) == 0) {
pmac_mb = pmac_mb_defs[i];
@@ -2471,15 +2479,18 @@ static int __init probe_motherboard(void)
break;
#endif /* CONFIG_POWER4 */
default:
- return -ENODEV;
+ ret = -ENODEV;
+ goto done;
}
found:
#ifndef CONFIG_POWER4
/* Fixup Hooper vs. Comet */
if (pmac_mb.model_id == PMAC_TYPE_HOOPER) {
u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4);
- if (!mach_id_ptr)
- return -ENODEV;
+ if (!mach_id_ptr) {
+ ret = -ENODEV;
+ goto done;
+ }
/* Here, I used to disable the media-bay on comet. It
* appears this is wrong, the floppy connector is actually
* a kind of media-bay and works with the current driver.
@@ -2496,18 +2507,26 @@ found:
* that all Apple OF revs did it properly, I do it the paranoid way.
*/
while (uninorth_base && uninorth_rev > 3) {
- struct device_node *np = find_path_device("/cpus");
- if (!np || !np->child) {
+ struct device_node *cpus = of_find_node_by_path("/cpus");
+ struct device_node *np;
+
+ if (!cpus || !cpus->child) {
printk(KERN_WARNING "Can't find CPU(s) in device tree !\n");
+ of_node_put(cpus);
break;
}
- np = np->child;
+ np = cpus->child;
/* Nap mode not supported on SMP */
- if (np->sibling)
+ if (np->sibling) {
+ of_node_put(cpus);
break;
+ }
/* Nap mode not supported if flush-on-lock property is present */
- if (get_property(np, "flush-on-lock", NULL))
+ if (of_get_property(np, "flush-on-lock", NULL)) {
+ of_node_put(cpus);
break;
+ }
+ of_node_put(cpus);
powersave_nap = 1;
printk(KERN_DEBUG "Processor NAP mode on idle enabled.\n");
break;
@@ -2529,7 +2548,9 @@ found:
printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name);
- return 0;
+done:
+ of_node_put(dt);
+ return ret;
}
/* Initialize the Core99 UniNorth host bridge and memory controller
@@ -2555,7 +2576,7 @@ static void __init probe_uninorth(void)
if (uninorth_node == NULL)
return;
- addrp = get_property(uninorth_node, "reg", NULL);
+ addrp = of_get_property(uninorth_node, "reg", NULL);
if (addrp == NULL)
return;
address = of_translate_address(uninorth_node, addrp);
@@ -2639,7 +2660,7 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ
return;
}
if (type == macio_keylargo || type == macio_keylargo2) {
- const u32 *did = get_property(node, "device-id", NULL);
+ const u32 *did = of_get_property(node, "device-id", NULL);
if (*did == 0x00000025)
type = macio_pangea;
if (*did == 0x0000003e)
@@ -2652,7 +2673,7 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ
macio_chips[i].base = base;
macio_chips[i].flags = MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON;
macio_chips[i].name = macio_names[type];
- revp = get_property(node, "revision-id", NULL);
+ revp = of_get_property(node, "revision-id", NULL);
if (revp)
macio_chips[i].rev = *revp;
printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n",
@@ -2703,8 +2724,8 @@ initial_serial_shutdown(struct device_node *np)
int port_type = PMAC_SCC_ASYNC;
int modem = 0;
- slots = get_property(np, "slot-names", &len);
- conn = get_property(np, "AAPL,connector", &len);
+ slots = of_get_property(np, "slot-names", &len);
+ conn = of_get_property(np, "AAPL,connector", &len);
if (conn && (strcmp(conn, "infrared") == 0))
port_type = PMAC_SCC_IRDA;
else if (device_is_compatible(np, "cobalt"))
@@ -2732,12 +2753,14 @@ set_initial_features(void)
* differenciate them all and since that hack was there for a long
* time, I'll keep it around
*/
- if (macio_chips[0].type == macio_ohare && !find_devices("via-pmu")) {
+ if (macio_chips[0].type == macio_ohare) {
struct macio_chip *macio = &macio_chips[0];
- MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES);
- } else if (macio_chips[0].type == macio_ohare) {
- struct macio_chip *macio = &macio_chips[0];
- MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
+ np = of_find_node_by_name(NULL, "via-pmu");
+ if (np)
+ MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
+ else
+ MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES);
+ of_node_put(np);
} else if (macio_chips[1].type == macio_ohare) {
struct macio_chip *macio = &macio_chips[1];
MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
@@ -2830,14 +2853,13 @@ set_initial_features(void)
}
/* Switch airport off */
- np = find_devices("radio");
- while(np) {
+ for_each_node_by_name(np, "radio") {
if (np && np->parent == macio_chips[0].of_node) {
macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON;
core99_airport_enable(np, 0, 0);
}
- np = np->next;
}
+ of_node_put(np);
}
/* On all machines that support sound PM, switch sound off */
@@ -2857,16 +2879,12 @@ set_initial_features(void)
#endif /* CONFIG_POWER4 */
/* On all machines, switch modem & serial ports off */
- np = find_devices("ch-a");
- while(np) {
+ for_each_node_by_name(np, "ch-a")
initial_serial_shutdown(np);
- np = np->next;
- }
- np = find_devices("ch-b");
- while(np) {
+ of_node_put(np);
+ for_each_node_by_name(np, "ch-b")
initial_serial_shutdown(np);
- np = np->next;
- }
+ of_node_put(np);
}
void __init
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index bfc4829162f1..5430e146b3e9 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -491,7 +491,7 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np)
* on all i2c keywest nodes so far ... we would have to fallback
* to macio parsing if that wasn't the case
*/
- addrp = get_property(np, "AAPL,address", NULL);
+ addrp = of_get_property(np, "AAPL,address", NULL);
if (addrp == NULL) {
printk(KERN_ERR "low_i2c: Can't find address for %s\n",
np->full_name);
@@ -505,13 +505,13 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np)
host->timeout_timer.function = kw_i2c_timeout;
host->timeout_timer.data = (unsigned long)host;
- psteps = get_property(np, "AAPL,address-step", NULL);
+ psteps = of_get_property(np, "AAPL,address-step", NULL);
steps = psteps ? (*psteps) : 0x10;
for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++)
steps >>= 1;
/* Select interface rate */
host->speed = KW_I2C_MODE_25KHZ;
- prate = get_property(np, "AAPL,i2c-rate", NULL);
+ prate = of_get_property(np, "AAPL,i2c-rate", NULL);
if (prate) switch(*prate) {
case 100:
host->speed = KW_I2C_MODE_100KHZ;
@@ -619,7 +619,7 @@ static void __init kw_i2c_probe(void)
} else {
for (child = NULL;
(child = of_get_next_child(np, child)) != NULL;) {
- const u32 *reg = get_property(child,
+ const u32 *reg = of_get_property(child,
"reg", NULL);
if (reg == NULL)
continue;
@@ -905,7 +905,7 @@ static void __init smu_i2c_probe(void)
if (strcmp(busnode->type, "i2c") &&
strcmp(busnode->type, "i2c-bus"))
continue;
- reg = get_property(busnode, "reg", NULL);
+ reg = of_get_property(busnode, "reg", NULL);
if (reg == NULL)
continue;
@@ -950,7 +950,8 @@ struct pmac_i2c_bus *pmac_i2c_find_bus(struct device_node *node)
if (p == bus->busnode) {
if (prev && bus->flags & pmac_i2c_multibus) {
const u32 *reg;
- reg = get_property(prev, "reg", NULL);
+ reg = of_get_property(prev, "reg",
+ NULL);
if (!reg)
continue;
if (((*reg) >> 8) != bus->channel)
@@ -971,7 +972,7 @@ EXPORT_SYMBOL_GPL(pmac_i2c_find_bus);
u8 pmac_i2c_get_dev_addr(struct device_node *device)
{
- const u32 *reg = get_property(device, "reg", NULL);
+ const u32 *reg = of_get_property(device, "reg", NULL);
if (reg == NULL)
return 0;
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index f42475b27c15..22c4ae4c6934 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -70,11 +70,11 @@ static int __init fixup_one_level_bus_range(struct device_node *node, int higher
int len;
/* For PCI<->PCI bridges or CardBus bridges, we go down */
- class_code = get_property(node, "class-code", NULL);
+ class_code = of_get_property(node, "class-code", NULL);
if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
continue;
- bus_range = get_property(node, "bus-range", &len);
+ bus_range = of_get_property(node, "bus-range", &len);
if (bus_range != NULL && len > 2 * sizeof(int)) {
if (bus_range[1] > higher)
higher = bus_range[1];
@@ -100,7 +100,7 @@ static void __init fixup_bus_range(struct device_node *bridge)
if (prop == NULL || prop->length < 2 * sizeof(int))
return;
- bus_range = (int *)prop->value;
+ bus_range = prop->value;
bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]);
}
@@ -246,8 +246,8 @@ static int chaos_validate_dev(struct pci_bus *bus, int devfn, int offset)
if (np == NULL)
return PCIBIOS_DEVICE_NOT_FOUND;
- vendor = get_property(np, "vendor-id", NULL);
- device = get_property(np, "device-id", NULL);
+ vendor = of_get_property(np, "vendor-id", NULL);
+ device = of_get_property(np, "device-id", NULL);
if (vendor == NULL || device == NULL)
return PCIBIOS_DEVICE_NOT_FOUND;
@@ -622,13 +622,14 @@ static void __init init_p2pbridge(void)
/* XXX it would be better here to identify the specific
PCI-PCI bridge chip we have. */
- if ((p2pbridge = find_devices("pci-bridge")) == 0
+ p2pbridge = of_find_node_by_name(NULL, "pci-bridge");
+ if (p2pbridge == NULL
|| p2pbridge->parent == NULL
|| strcmp(p2pbridge->parent->name, "pci") != 0)
- return;
+ goto done;
if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) {
DBG("Can't find PCI infos for PCI<->PCI bridge\n");
- return;
+ goto done;
}
/* Warning: At this point, we have not yet renumbered all busses.
* So we must use OF walking to find out hose
@@ -636,16 +637,18 @@ static void __init init_p2pbridge(void)
hose = pci_find_hose_for_OF_device(p2pbridge);
if (!hose) {
DBG("Can't find hose for PCI<->PCI bridge\n");
- return;
+ goto done;
}
if (early_read_config_word(hose, bus, devfn,
PCI_BRIDGE_CONTROL, &val) < 0) {
printk(KERN_ERR "init_p2pbridge: couldn't read bridge"
" control\n");
- return;
+ goto done;
}
val &= ~PCI_BRIDGE_CTL_MASTER_ABORT;
early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val);
+done:
+ of_node_put(p2pbridge);
}
static void __init init_second_ohare(void)
@@ -691,17 +694,17 @@ static void __init fixup_nec_usb2(void)
const u32 *prop;
u8 bus, devfn;
- prop = get_property(nec, "vendor-id", NULL);
+ prop = of_get_property(nec, "vendor-id", NULL);
if (prop == NULL)
continue;
if (0x1033 != *prop)
continue;
- prop = get_property(nec, "device-id", NULL);
+ prop = of_get_property(nec, "device-id", NULL);
if (prop == NULL)
continue;
if (0x0035 != *prop)
continue;
- prop = get_property(nec, "reg", NULL);
+ prop = of_get_property(nec, "reg", NULL);
if (prop == NULL)
continue;
devfn = (prop[0] >> 8) & 0xff;
@@ -909,7 +912,7 @@ static int __init add_bridge(struct device_node *dev)
has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
/* Get bus range if any */
- bus_range = get_property(dev, "bus-range", &len);
+ bus_range = of_get_property(dev, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int)) {
printk(KERN_WARNING "Can't get bus-range for %s, assume"
" bus 0\n", dev->full_name);
@@ -1191,13 +1194,15 @@ void __init pmac_pcibios_after_init(void)
* -- BenH
*/
for_each_pci_dev(dev) {
- if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE)
- pci_enable_device(dev);
+ if ((dev->class >> 16) != PCI_BASE_CLASS_STORAGE)
+ continue;
+ if (pci_enable_device(dev))
+ printk(KERN_WARNING
+ "pci: Failed to enable %s\n", pci_name(dev));
}
#endif /* CONFIG_BLK_DEV_IDE */
- nd = find_devices("firewire");
- while (nd) {
+ for_each_node_by_name(nd, "firewire") {
if (nd->parent && (device_is_compatible(nd, "pci106b,18") ||
device_is_compatible(nd, "pci106b,30") ||
device_is_compatible(nd, "pci11c1,5811"))
@@ -1205,15 +1210,14 @@ void __init pmac_pcibios_after_init(void)
pmac_call_feature(PMAC_FTR_1394_ENABLE, nd, 0, 0);
pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0);
}
- nd = nd->next;
}
- nd = find_devices("ethernet");
- while (nd) {
+ of_node_put(nd);
+ for_each_node_by_name(nd, "ethernet") {
if (nd->parent && device_is_compatible(nd, "gmac")
&& device_is_compatible(nd->parent, "uni-north"))
pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0);
- nd = nd->next;
}
+ of_node_put(nd);
}
#ifdef CONFIG_PPC32
diff --git a/arch/powerpc/platforms/powermac/pfunc_base.c b/arch/powerpc/platforms/powermac/pfunc_base.c
index 5c6c15c5f9a3..45d54b9ad9e0 100644
--- a/arch/powerpc/platforms/powermac/pfunc_base.c
+++ b/arch/powerpc/platforms/powermac/pfunc_base.c
@@ -114,7 +114,7 @@ static void macio_gpio_init_one(struct macio_chip *macio)
* we just create them all
*/
for (gp = NULL; (gp = of_get_next_child(gparent, gp)) != NULL;) {
- const u32 *reg = get_property(gp, "reg", NULL);
+ const u32 *reg = of_get_property(gp, "reg", NULL);
unsigned long offset;
if (reg == NULL)
continue;
diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c
index 7651f278615a..85434231ae14 100644
--- a/arch/powerpc/platforms/powermac/pfunc_core.c
+++ b/arch/powerpc/platforms/powermac/pfunc_core.c
@@ -692,8 +692,7 @@ static int pmf_add_functions(struct pmf_device *dev, void *driverdata)
name = pp->name + plen;
if (strlen(name) && pp->length >= 12)
count += pmf_add_function_prop(dev, driverdata, name,
- (u32 *)pp->value,
- pp->length);
+ pp->value, pp->length);
}
return count;
}
@@ -821,7 +820,7 @@ struct pmf_function *__pmf_find_function(struct device_node *target,
* one, then we fallback to a direct call attempt
*/
snprintf(fname, 63, "platform-%s", name);
- prop = get_property(target, fname, NULL);
+ prop = of_get_property(target, fname, NULL);
if (prop == NULL)
goto find_it;
ph = *prop;
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 5e5c0e4add91..ae5097ac0378 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -482,14 +482,14 @@ static struct mpic * __init pmac_setup_one_mpic(struct device_node *np,
pmac_call_feature(PMAC_FTR_ENABLE_MPIC, np, 0, 0);
flags |= MPIC_WANTS_RESET;
- if (get_property(np, "big-endian", NULL))
+ if (of_get_property(np, "big-endian", NULL))
flags |= MPIC_BIG_ENDIAN;
/* Primary Big Endian means HT interrupts. This is quite dodgy
* but works until I find a better way
*/
if (master && (flags & MPIC_BIG_ENDIAN))
- flags |= MPIC_BROKEN_U3;
+ flags |= MPIC_U3_HT_IRQS;
mpic = mpic_alloc(np, r.start, flags, 0, 0, name);
if (mpic == NULL)
@@ -510,7 +510,7 @@ static int __init pmac_pic_probe_mpic(void)
for (np = NULL; (np = of_find_node_by_type(np, "open-pic"))
!= NULL;) {
if (master == NULL &&
- get_property(np, "interrupts", NULL) == NULL)
+ of_get_property(np, "interrupts", NULL) == NULL)
master = of_node_get(np);
else if (slave == NULL)
slave = of_node_get(np);
@@ -575,7 +575,7 @@ void __init pmac_pic_init(void)
#ifdef CONFIG_PPC32
if (!pmac_newworld)
flags |= OF_IMAP_OLDWORLD_MAC;
- if (get_property(of_chosen, "linux,bootx", NULL) != NULL)
+ if (of_get_property(of_chosen, "linux,bootx", NULL) != NULL)
flags |= OF_IMAP_NO_PHANDLE;
#endif /* CONFIG_PPC_32 */
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 651fa424ea06..b820cabac697 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -42,7 +42,6 @@
#include <linux/initrd.h>
#include <linux/vt_kern.h>
#include <linux/console.h>
-#include <linux/ide.h>
#include <linux/pci.h>
#include <linux/adb.h>
#include <linux/cuda.h>
@@ -135,12 +134,12 @@ static void pmac_show_cpuinfo(struct seq_file *m)
seq_printf(m, "machine\t\t: ");
np = of_find_node_by_path("/");
if (np != NULL) {
- pp = get_property(np, "model", NULL);
+ pp = of_get_property(np, "model", NULL);
if (pp != NULL)
seq_printf(m, "%s\n", pp);
else
seq_printf(m, "PowerMac\n");
- pp = get_property(np, "compatible", &plen);
+ pp = of_get_property(np, "compatible", &plen);
if (pp != NULL) {
seq_printf(m, "motherboard\t:");
while (plen > 0) {
@@ -164,11 +163,13 @@ static void pmac_show_cpuinfo(struct seq_file *m)
if (np == NULL)
np = of_find_node_by_type(NULL, "cache");
if (np != NULL) {
- const unsigned int *ic = get_property(np, "i-cache-size", NULL);
- const unsigned int *dc = get_property(np, "d-cache-size", NULL);
+ const unsigned int *ic =
+ of_get_property(np, "i-cache-size", NULL);
+ const unsigned int *dc =
+ of_get_property(np, "d-cache-size", NULL);
seq_printf(m, "L2 cache\t:");
has_l2cache = 1;
- if (get_property(np, "cache-unified", NULL) != 0 && dc) {
+ if (of_get_property(np, "cache-unified", NULL) != 0 && dc) {
seq_printf(m, " %dK unified", *dc / 1024);
} else {
if (ic)
@@ -177,7 +178,7 @@ static void pmac_show_cpuinfo(struct seq_file *m)
seq_printf(m, "%s %dK data",
(ic? " +": ""), *dc / 1024);
}
- pp = get_property(np, "ram-type", NULL);
+ pp = of_get_property(np, "ram-type", NULL);
if (pp)
seq_printf(m, " %s", pp);
seq_printf(m, "\n");
@@ -192,8 +193,11 @@ static void pmac_show_cpuinfo(struct seq_file *m)
#ifndef CONFIG_ADB_CUDA
int find_via_cuda(void)
{
- if (!find_devices("via-cuda"))
+ struct device_node *dn = of_find_node_by_name(NULL, "via-cuda");
+
+ if (!dn)
return 0;
+ of_node_put(dn);
printk("WARNING ! Your machine is CUDA-based but your kernel\n");
printk(" wasn't compiled with CONFIG_ADB_CUDA option !\n");
return 0;
@@ -203,8 +207,11 @@ int find_via_cuda(void)
#ifndef CONFIG_ADB_PMU
int find_via_pmu(void)
{
- if (!find_devices("via-pmu"))
+ struct device_node *dn = of_find_node_by_name(NULL, "via-pmu");
+
+ if (!dn)
return 0;
+ of_node_put(dn);
printk("WARNING ! Your machine is PMU-based but your kernel\n");
printk(" wasn't compiled with CONFIG_ADB_PMU option !\n");
return 0;
@@ -224,6 +231,8 @@ static volatile u32 *sysctrl_regs;
static void __init ohare_init(void)
{
+ struct device_node *dn;
+
/* this area has the CPU identification register
and some registers used by smp boards */
sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000);
@@ -233,7 +242,9 @@ static void __init ohare_init(void)
* We assume that we have a PSX memory controller iff
* we have an ohare I/O controller.
*/
- if (find_devices("ohare") != NULL) {
+ dn = of_find_node_by_name(NULL, "ohare");
+ if (dn) {
+ of_node_put(dn);
if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) {
if (sysctrl_regs[4] & 0x10)
sysctrl_regs[4] |= 0x04000020;
@@ -249,18 +260,19 @@ static void __init l2cr_init(void)
{
/* Checks "l2cr-value" property in the registry */
if (cpu_has_feature(CPU_FTR_L2CR)) {
- struct device_node *np = find_devices("cpus");
+ struct device_node *np = of_find_node_by_name(NULL, "cpus");
if (np == 0)
- np = find_type_devices("cpu");
+ np = of_find_node_by_type(NULL, "cpu");
if (np != 0) {
const unsigned int *l2cr =
- get_property(np, "l2cr-value", NULL);
+ of_get_property(np, "l2cr-value", NULL);
if (l2cr != 0) {
ppc_override_l2cr = 1;
ppc_override_l2cr_value = *l2cr;
_set_L2CR(0);
_set_L2CR(ppc_override_l2cr_value);
}
+ of_node_put(np);
}
}
@@ -286,7 +298,7 @@ static void __init pmac_setup_arch(void)
loops_per_jiffy = 50000000 / HZ;
cpu = of_find_node_by_type(NULL, "cpu");
if (cpu != NULL) {
- fp = get_property(cpu, "clock-frequency", NULL);
+ fp = of_get_property(cpu, "clock-frequency", NULL);
if (fp != NULL) {
if (pvr >= 0x30 && pvr < 0x80)
/* PPC970 etc. */
@@ -303,7 +315,7 @@ static void __init pmac_setup_arch(void)
/* See if newworld or oldworld */
for (ic = NULL; (ic = of_find_all_nodes(ic)) != NULL; )
- if (get_property(ic, "interrupt-controller", NULL))
+ if (of_get_property(ic, "interrupt-controller", NULL))
break;
if (ic) {
pmac_newworld = 1;
@@ -341,8 +353,15 @@ static void __init pmac_setup_arch(void)
#ifdef CONFIG_SMP
/* Check for Core99 */
- if (find_devices("uni-n") || find_devices("u3") || find_devices("u4"))
+ ic = of_find_node_by_name(NULL, "uni-n");
+ if (!ic)
+ ic = of_find_node_by_name(NULL, "u3");
+ if (!ic)
+ ic = of_find_node_by_name(NULL, "u4");
+ if (ic) {
+ of_node_put(ic);
smp_ops = &core99_smp_ops;
+ }
#ifdef CONFIG_PPC32
else
smp_ops = &psurge_smp_ops;
@@ -616,15 +635,6 @@ static void __init pmac_init_early(void)
#endif
}
-/*
- * pmac has no legacy IO, anything calling this function has to
- * fail or bad things will happen
- */
-static int pmac_check_legacy_ioport(unsigned int baseport)
-{
- return -ENODEV;
-}
-
static int __init pmac_declare_of_platform_devices(void)
{
struct device_node *np;
@@ -736,7 +746,6 @@ define_machine(powermac) {
.get_rtc_time = pmac_get_rtc_time,
.calibrate_decr = pmac_calibrate_decr,
.feature_call = pmac_do_feature_call,
- .check_legacy_ioport = pmac_check_legacy_ioport,
.progress = udbg_progress,
#ifdef CONFIG_PPC64
.pci_probe_mode = pmac_pci_probe_mode,
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index d73fb73802bb..6f32c4eca6e5 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -264,6 +264,7 @@ static void __init psurge_quad_init(void)
static int __init smp_psurge_probe(void)
{
int i, ncpus;
+ struct device_node *dn;
/* We don't do SMP on the PPC601 -- paulus */
if (PVR_VER(mfspr(SPRN_PVR)) == 1)
@@ -279,8 +280,10 @@ static int __init smp_psurge_probe(void)
* in the hammerhead memory controller in the case of the
* dual-cpu powersurge board. -- paulus.
*/
- if (find_devices("hammerhead") == NULL)
+ dn = of_find_node_by_name(NULL, "hammerhead");
+ if (dn == NULL)
return 1;
+ of_node_put(dn);
hhead_base = ioremap(HAMMERHEAD_BASE, 0x800);
quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024);
@@ -567,7 +570,7 @@ static void __init smp_core99_setup_i2c_hwsync(int ncpus)
pmac_tb_clock_chip_host = pmac_i2c_find_bus(cc);
if (pmac_tb_clock_chip_host == NULL)
continue;
- reg = get_property(cc, "reg", NULL);
+ reg = of_get_property(cc, "reg", NULL);
if (reg == NULL)
continue;
switch (*reg) {
@@ -695,7 +698,7 @@ static void __init smp_core99_setup(int ncpus)
struct device_node *cpus =
of_find_node_by_path("/cpus");
if (cpus &&
- get_property(cpus, "platform-cpu-timebase", NULL)) {
+ of_get_property(cpus, "platform-cpu-timebase", NULL)) {
pmac_tb_freeze = smp_core99_pfunc_tb_freeze;
printk(KERN_INFO "Processor timebase sync using"
" platform function\n");
@@ -712,7 +715,7 @@ static void __init smp_core99_setup(int ncpus)
core99_tb_gpio = KL_GPIO_TB_ENABLE; /* default value */
cpu = of_find_node_by_type(NULL, "cpu");
if (cpu != NULL) {
- tbprop = get_property(cpu, "timebase-enable", NULL);
+ tbprop = of_get_property(cpu, "timebase-enable", NULL);
if (tbprop)
core99_tb_gpio = *tbprop;
of_node_put(cpu);
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c
index a4173906e945..bf9da56942e8 100644
--- a/arch/powerpc/platforms/powermac/time.c
+++ b/arch/powerpc/platforms/powermac/time.c
@@ -297,49 +297,11 @@ int __init via_calibrate_decr(void)
}
#endif
-#ifdef CONFIG_PM
-/*
- * Reset the time after a sleep.
- */
-static int
-time_sleep_notify(struct pmu_sleep_notifier *self, int when)
-{
- static unsigned long time_diff;
- unsigned long flags;
- unsigned long seq;
- struct timespec tv;
-
- switch (when) {
- case PBOOK_SLEEP_NOW:
- do {
- seq = read_seqbegin_irqsave(&xtime_lock, flags);
- time_diff = xtime.tv_sec - pmac_get_boot_time();
- } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
- break;
- case PBOOK_WAKE:
- tv.tv_sec = pmac_get_boot_time() + time_diff;
- tv.tv_nsec = 0;
- do_settimeofday(&tv);
- break;
- }
- return PBOOK_SLEEP_OK;
-}
-
-static struct pmu_sleep_notifier time_sleep_notifier = {
- time_sleep_notify, SLEEP_LEVEL_MISC,
-};
-#endif /* CONFIG_PM */
-
/*
* Query the OF and get the decr frequency.
*/
void __init pmac_calibrate_decr(void)
{
-#if defined(CONFIG_PM) && defined(CONFIG_ADB_PMU)
- /* XXX why here? */
- pmu_register_sleep_notifier(&time_sleep_notifier);
-#endif
-
generic_calibrate_decr();
#ifdef CONFIG_PPC32
diff --git a/arch/powerpc/platforms/powermac/udbg_scc.c b/arch/powerpc/platforms/powermac/udbg_scc.c
index 379db05b0082..47de4d3fc167 100644
--- a/arch/powerpc/platforms/powermac/udbg_scc.c
+++ b/arch/powerpc/platforms/powermac/udbg_scc.c
@@ -81,7 +81,7 @@ void udbg_scc_init(int force_scc)
macio = of_get_parent(escc);
if (macio == NULL)
goto bail;
- path = get_property(of_chosen, "linux,stdout-path", NULL);
+ path = of_get_property(of_chosen, "linux,stdout-path", NULL);
if (path != NULL)
stdout = of_find_node_by_path(path);
for (ch = NULL; (ch = of_get_next_child(escc, ch)) != NULL;) {
@@ -96,13 +96,13 @@ void udbg_scc_init(int force_scc)
ch = ch_def ? ch_def : ch_a;
/* Get address within mac-io ASIC */
- reg = get_property(escc, "reg", NULL);
+ reg = of_get_property(escc, "reg", NULL);
if (reg == NULL)
goto bail;
addr = reg[0];
/* Get address of mac-io PCI itself */
- reg = get_property(macio, "assigned-addresses", NULL);
+ reg = of_get_property(macio, "assigned-addresses", NULL);
if (reg == NULL)
goto bail;
addr += reg[2];
diff --git a/arch/powerpc/platforms/prep/Kconfig b/arch/powerpc/platforms/prep/Kconfig
index 673ac47a1626..29d411279b0c 100644
--- a/arch/powerpc/platforms/prep/Kconfig
+++ b/arch/powerpc/platforms/prep/Kconfig
@@ -1,3 +1,12 @@
+config PPC_PREP
+ bool "PowerPC Reference Platform (PReP) based machines"
+ depends on PPC_MULTIPLATFORM && PPC32 && BROKEN
+ select MPIC
+ select PPC_I8259
+ select PPC_INDIRECT_PCI
+ select PPC_UDBG_16550
+ select PPC_NATIVE
+ default n
config PREP_RESIDUAL
bool "Support for PReP Residual Data"
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
index 4be3943d1c0d..40f0008af4d1 100644
--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -1,9 +1,40 @@
+config PPC_PS3
+ bool "Sony PS3 (incomplete)"
+ depends on PPC_MULTIPLATFORM && PPC64
+ select PPC_CELL
+ select USB_ARCH_HAS_OHCI
+ select USB_OHCI_LITTLE_ENDIAN
+ select USB_OHCI_BIG_ENDIAN_MMIO
+ select USB_ARCH_HAS_EHCI
+ select USB_EHCI_BIG_ENDIAN_MMIO
+ help
+ This option enables support for the Sony PS3 game console
+ and other platforms using the PS3 hypervisor.
+ Support for this platform is not yet complete, so
+ enabling this will not result in a bootable kernel on a
+ PS3 system.
+
menu "PS3 Platform Options"
depends on PPC_PS3
+config PS3_ADVANCED
+ depends on PPC_PS3
+ bool "PS3 Advanced configuration options"
+ help
+ This gives you access to some advanced options for the PS3. The
+ defaults should be fine for most users, but these options may make
+ it possible to better control the kernel configuration if you know
+ what you are doing.
+
+ Note that the answer to this question won't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about these options.
+
+ Most users should say N to this question.
+
config PS3_HTAB_SIZE
depends on PPC_PS3
- int "PS3 Platform pagetable size"
+ int "PS3 Platform pagetable size" if PS3_ADVANCED
range 18 20
default 20
help
@@ -42,7 +73,7 @@ config PS3_USE_LPAR_ADDR
config PS3_VUART
depends on PPC_PS3
- bool "PS3 Virtual UART support"
+ bool "PS3 Virtual UART support" if PS3_ADVANCED
default y
help
Include support for the PS3 Virtual UART.
@@ -52,9 +83,8 @@ config PS3_VUART
general, all users will say Y.
config PS3_PS3AV
- tristate "PS3 AV settings driver"
- depends on PPC_PS3
- select PS3_VUART
+ tristate "PS3 AV settings driver" if PS3_ADVANCED
+ depends on PS3_VUART
default y
help
Include support for the PS3 AV Settings driver.
@@ -62,4 +92,14 @@ config PS3_PS3AV
This support is required for graphics and sound. In
general, all users will say Y or M.
+config PS3_SYS_MANAGER
+ bool "PS3 System Manager driver" if PS3_ADVANCED
+ depends on PS3_VUART
+ default y
+ help
+ Include support for the PS3 System Manager.
+
+ This support is required for system control. In
+ general, all users will say Y.
+
endmenu
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
index e12e59fea13a..ea60c451cf87 100644
--- a/arch/powerpc/platforms/ps3/htab.c
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -39,7 +39,7 @@ static unsigned long htab_addr;
static unsigned char *bolttab;
static unsigned char *inusetab;
-static spinlock_t ps3_bolttab_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(ps3_bolttab_lock);
#define debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g) \
_debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__)
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c
index 42354de3f557..2014d2b44449 100644
--- a/arch/powerpc/platforms/ps3/mm.c
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -294,7 +294,7 @@ static int __init ps3_mm_add_memory(void)
unsigned long nr_pages;
if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
- return 0;
+ return -ENODEV;
BUG_ON(!mem_init_done);
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index 13d669a8ecae..ac5df9688dcb 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -42,6 +42,10 @@
#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
#endif
+#if !defined(CONFIG_SMP)
+static void smp_send_stop(void) {}
+#endif
+
int ps3_get_firmware_version(union ps3_firmware_version *v)
{
int result = lv1_get_version_info(&v->raw);
@@ -66,22 +70,35 @@ static void ps3_power_save(void)
lv1_pause(0);
}
+static void ps3_restart(char *cmd)
+{
+ DBG("%s:%d cmd '%s'\n", __func__, __LINE__, cmd);
+
+ smp_send_stop();
+ ps3_sys_manager_restart(); /* never returns */
+}
+
+static void ps3_power_off(void)
+{
+ DBG("%s:%d\n", __func__, __LINE__);
+
+ smp_send_stop();
+ ps3_sys_manager_power_off(); /* never returns */
+}
+
static void ps3_panic(char *str)
{
DBG("%s:%d %s\n", __func__, __LINE__, str);
-#ifdef CONFIG_SMP
smp_send_stop();
-#endif
printk("\n");
printk(" System does not reboot automatically.\n");
printk(" Please press POWER button.\n");
printk("\n");
- for (;;) ;
+ while(1);
}
-
static void prealloc(struct ps3_prealloc *p)
{
if (!p->size)
@@ -219,6 +236,8 @@ define_machine(ps3) {
.get_rtc_time = ps3_get_rtc_time,
.calibrate_decr = ps3_calibrate_decr,
.progress = ps3_progress,
+ .restart = ps3_restart,
+ .power_off = ps3_power_off,
#if defined(CONFIG_KEXEC)
.kexec_cpu_down = ps3_kexec_cpu_down,
.machine_kexec = ps3_machine_kexec,
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c
index a9f7e4a39a2a..3c48cce98a5c 100644
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -172,7 +172,7 @@ int __init ps3_system_bus_init(void)
int result;
if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
- return 0;
+ return -ENODEV;
result = bus_register(&ps3_system_bus_type);
BUG_ON(result);
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index a57032cf6f1b..16e4e401b820 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -1,3 +1,13 @@
+config PPC_PSERIES
+ depends on PPC_MULTIPLATFORM && PPC64
+ bool "IBM pSeries & new (POWER5-based) iSeries"
+ select MPIC
+ select PPC_I8259
+ select PPC_RTAS
+ select RTAS_ERROR_LOGGING
+ select PPC_UDBG_16550
+ select PPC_NATIVE
+ default y
config PPC_SPLPAR
depends on PPC_PSERIES
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index dc0583bdbc63..90235d598751 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -2,14 +2,15 @@ ifeq ($(CONFIG_PPC64),y)
EXTRA_CFLAGS += -mno-minimal-toc
endif
-obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \
- setup.o iommu.o ras.o rtasd.o pci_dlpar.o \
- firmware.o
+obj-y := lpar.o hvCall.o nvram.o reconfig.o \
+ setup.o iommu.o ras.o rtasd.o \
+ firmware.o power.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_XICS) += xics.o
obj-$(CONFIG_SCANLOG) += scanlog.o
obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o
obj-$(CONFIG_KEXEC) += kexec.o
+obj-$(CONFIG_PCI) += pci.o pci_dlpar.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 6cedbc002e0f..48fbd442e9df 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -74,7 +74,10 @@
* is broken and panic. This sets the threshold for how many read
* attempts we allow before panicking.
*/
-#define EEH_MAX_FAILS 100000
+#define EEH_MAX_FAILS 2100000
+
+/* Time to wait for a PCI slot to retport status, in milliseconds */
+#define PCI_BUS_RESET_WAIT_MSEC (60*1000)
/* RTAS tokens */
static int ibm_set_eeh_option;
@@ -83,6 +86,7 @@ static int ibm_read_slot_reset_state;
static int ibm_read_slot_reset_state2;
static int ibm_slot_error_detail;
static int ibm_get_config_addr_info;
+static int ibm_get_config_addr_info2;
static int ibm_configure_bridge;
int eeh_subsystem_enabled;
@@ -168,6 +172,55 @@ static int read_slot_reset_state(struct pci_dn *pdn, int rets[])
}
/**
+ * eeh_wait_for_slot_status - returns error status of slot
+ * @pdn pci device node
+ * @max_wait_msecs maximum number to millisecs to wait
+ *
+ * Return negative value if a permanent error, else return
+ * Partition Endpoint (PE) status value.
+ *
+ * If @max_wait_msecs is positive, then this routine will
+ * sleep until a valid status can be obtained, or until
+ * the max allowed wait time is exceeded, in which case
+ * a -2 is returned.
+ */
+int
+eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs)
+{
+ int rc;
+ int rets[3];
+ int mwait;
+
+ while (1) {
+ rc = read_slot_reset_state(pdn, rets);
+ if (rc) return rc;
+ if (rets[1] == 0) return -1; /* EEH is not supported */
+
+ if (rets[0] != 5) return rets[0]; /* return actual status */
+
+ if (rets[2] == 0) return -1; /* permanently unavailable */
+
+ if (max_wait_msecs <= 0) return -1;
+
+ mwait = rets[2];
+ if (mwait <= 0) {
+ printk (KERN_WARNING
+ "EEH: Firmware returned bad wait value=%d\n", mwait);
+ mwait = 1000;
+ } else if (mwait > 300*1000) {
+ printk (KERN_WARNING
+ "EEH: Firmware is taking too long, time=%d\n", mwait);
+ mwait = 300*1000;
+ }
+ max_wait_msecs -= mwait;
+ msleep (mwait);
+ }
+
+ printk(KERN_WARNING "EEH: Timed out waiting for slot status\n");
+ return -2;
+}
+
+/**
* eeh_token_to_phys - convert EEH address token to phys address
* @token i/o token, should be address in the form 0xA....
*/
@@ -229,7 +282,7 @@ void eeh_mark_slot (struct device_node *dn, int mode_flag)
dn = find_device_pe (dn);
/* Back up one, since config addrs might be shared */
- if (PCI_DN(dn) && PCI_DN(dn)->eeh_pe_config_addr)
+ if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent))
dn = dn->parent;
PCI_DN(dn)->eeh_mode |= mode_flag;
@@ -263,7 +316,7 @@ void eeh_clear_slot (struct device_node *dn, int mode_flag)
dn = find_device_pe (dn);
/* Back up one, since config addrs might be shared */
- if (PCI_DN(dn) && PCI_DN(dn)->eeh_pe_config_addr)
+ if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent))
dn = dn->parent;
PCI_DN(dn)->eeh_mode &= ~mode_flag;
@@ -293,7 +346,6 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
int rets[3];
unsigned long flags;
struct pci_dn *pdn;
- enum pci_channel_state state;
int rc = 0;
total_mmio_ffs++;
@@ -367,25 +419,25 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
goto dn_unlock;
}
- /* If EEH is not supported on this device, punt. */
- if (rets[1] != 1) {
- printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n",
- ret, dn->full_name);
+ /* Note that config-io to empty slots may fail;
+ * they are empty when they don't have children. */
+ if ((rets[0] == 5) && (dn->child == NULL)) {
false_positives++;
rc = 0;
goto dn_unlock;
}
- /* If not the kind of error we know about, punt. */
- if (rets[0] != 2 && rets[0] != 4 && rets[0] != 5) {
+ /* If EEH is not supported on this device, punt. */
+ if (rets[1] != 1) {
+ printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n",
+ ret, dn->full_name);
false_positives++;
rc = 0;
goto dn_unlock;
}
- /* Note that config-io to empty slots may fail;
- * we recognize empty because they don't have children. */
- if ((rets[0] == 5) && (dn->child == NULL)) {
+ /* If not the kind of error we know about, punt. */
+ if (rets[0] != 1 && rets[0] != 2 && rets[0] != 4 && rets[0] != 5) {
false_positives++;
rc = 0;
goto dn_unlock;
@@ -399,17 +451,12 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
eeh_mark_slot (dn, EEH_MODE_ISOLATED);
spin_unlock_irqrestore(&confirm_error_lock, flags);
- state = pci_channel_io_normal;
- if ((rets[0] == 2) || (rets[0] == 4))
- state = pci_channel_io_frozen;
- if (rets[0] == 5)
- state = pci_channel_io_perm_failure;
- eeh_send_failure_event (dn, dev, state, rets[2]);
+ eeh_send_failure_event (dn, dev);
/* Most EEH events are due to device driver bugs. Having
* a stack trace will help the device-driver authors figure
* out what happened. So print that out. */
- if (rets[0] != 5) dump_stack();
+ dump_stack();
return 1;
dn_unlock:
@@ -458,38 +505,6 @@ EXPORT_SYMBOL(eeh_check_failure);
/* The code below deals with error recovery */
/**
- * eeh_slot_availability - returns error status of slot
- * @pdn pci device node
- *
- * Return negative value if a permanent error, else return
- * a number of milliseconds to wait until the PCI slot is
- * ready to be used.
- */
-static int
-eeh_slot_availability(struct pci_dn *pdn)
-{
- int rc;
- int rets[3];
-
- rc = read_slot_reset_state(pdn, rets);
-
- if (rc) return rc;
-
- if (rets[1] == 0) return -1; /* EEH is not supported */
- if (rets[0] == 0) return 0; /* Oll Korrect */
- if (rets[0] == 5) {
- if (rets[2] == 0) return -1; /* permanently unavailable */
- return rets[2]; /* number of millisecs to wait */
- }
- if (rets[0] == 1)
- return 250;
-
- printk (KERN_ERR "EEH: Slot unavailable: rc=%d, rets=%d %d %d\n",
- rc, rets[0], rets[1], rets[2]);
- return -2;
-}
-
-/**
* rtas_pci_enable - enable MMIO or DMA transfers for this slot
* @pdn pci device node
*/
@@ -512,9 +527,13 @@ rtas_pci_enable(struct pci_dn *pdn, int function)
function);
if (rc)
- printk(KERN_WARNING "EEH: Cannot enable function %d, err=%d dn=%s\n",
+ printk(KERN_WARNING "EEH: Unexpected state change %d, err=%d dn=%s\n",
function, rc, pdn->node->full_name);
+ rc = eeh_wait_for_slot_status (pdn, PCI_BUS_RESET_WAIT_MSEC);
+ if ((rc == 4) && (function == EEH_THAW_MMIO))
+ return 0;
+
return rc;
}
@@ -595,36 +614,24 @@ int rtas_set_slot_reset(struct pci_dn *pdn)
{
int i, rc;
- __rtas_set_slot_reset(pdn);
+ /* Take three shots at resetting the bus */
+ for (i=0; i<3; i++) {
+ __rtas_set_slot_reset(pdn);
- /* Now double check with the firmware to make sure the device is
- * ready to be used; if not, wait for recovery. */
- for (i=0; i<10; i++) {
- rc = eeh_slot_availability (pdn);
+ rc = eeh_wait_for_slot_status(pdn, PCI_BUS_RESET_WAIT_MSEC);
if (rc == 0)
return 0;
- if (rc == -2) {
- printk (KERN_ERR "EEH: failed (%d) to reset slot %s\n",
- i, pdn->node->full_name);
- __rtas_set_slot_reset(pdn);
- continue;
- }
-
if (rc < 0) {
printk (KERN_ERR "EEH: unrecoverable slot failure %s\n",
pdn->node->full_name);
return -1;
}
-
- msleep (rc+100);
+ printk (KERN_ERR "EEH: bus reset %d failed on slot %s\n",
+ i+1, pdn->node->full_name);
}
- rc = eeh_slot_availability (pdn);
- if (rc)
- printk (KERN_ERR "EEH: timeout resetting slot %s\n", pdn->node->full_name);
-
- return rc;
+ return -1;
}
/* ------------------------------------------------------- */
@@ -744,16 +751,48 @@ struct eeh_early_enable_info {
unsigned int buid_lo;
};
+static int get_pe_addr (int config_addr,
+ struct eeh_early_enable_info *info)
+{
+ unsigned int rets[3];
+ int ret;
+
+ /* Use latest config-addr token on power6 */
+ if (ibm_get_config_addr_info2 != RTAS_UNKNOWN_SERVICE) {
+ /* Make sure we have a PE in hand */
+ ret = rtas_call (ibm_get_config_addr_info2, 4, 2, rets,
+ config_addr, info->buid_hi, info->buid_lo, 1);
+ if (ret || (rets[0]==0))
+ return 0;
+
+ ret = rtas_call (ibm_get_config_addr_info2, 4, 2, rets,
+ config_addr, info->buid_hi, info->buid_lo, 0);
+ if (ret)
+ return 0;
+ return rets[0];
+ }
+
+ /* Use older config-addr token on power5 */
+ if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) {
+ ret = rtas_call (ibm_get_config_addr_info, 4, 2, rets,
+ config_addr, info->buid_hi, info->buid_lo, 0);
+ if (ret)
+ return 0;
+ return rets[0];
+ }
+ return 0;
+}
+
/* Enable eeh for the given device node. */
static void *early_enable_eeh(struct device_node *dn, void *data)
{
unsigned int rets[3];
struct eeh_early_enable_info *info = data;
int ret;
- const char *status = get_property(dn, "status", NULL);
- const u32 *class_code = get_property(dn, "class-code", NULL);
- const u32 *vendor_id = get_property(dn, "vendor-id", NULL);
- const u32 *device_id = get_property(dn, "device-id", NULL);
+ const char *status = of_get_property(dn, "status", NULL);
+ const u32 *class_code = of_get_property(dn, "class-code", NULL);
+ const u32 *vendor_id = of_get_property(dn, "vendor-id", NULL);
+ const u32 *device_id = of_get_property(dn, "device-id", NULL);
const u32 *regs;
int enable;
struct pci_dn *pdn = PCI_DN(dn);
@@ -796,7 +835,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
/* Ok... see if this device supports EEH. Some do, some don't,
* and the only way to find out is to check each and every one. */
- regs = get_property(dn, "reg", NULL);
+ regs = of_get_property(dn, "reg", NULL);
if (regs) {
/* First register entry is addr (00BBSS00) */
/* Try to enable eeh */
@@ -810,15 +849,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
/* If the newer, better, ibm,get-config-addr-info is supported,
* then use that instead. */
- pdn->eeh_pe_config_addr = 0;
- if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) {
- ret = rtas_call (ibm_get_config_addr_info, 4, 2, rets,
- pdn->eeh_config_addr,
- info->buid_hi, info->buid_lo,
- 0);
- if (ret == 0)
- pdn->eeh_pe_config_addr = rets[0];
- }
+ pdn->eeh_pe_config_addr = get_pe_addr(pdn->eeh_config_addr, info);
/* Some older systems (Power4) allow the
* ibm,set-eeh-option call to succeed even on nodes
@@ -889,6 +920,7 @@ void __init eeh_init(void)
ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state");
ibm_slot_error_detail = rtas_token("ibm,slot-error-detail");
ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info");
+ ibm_get_config_addr_info2 = rtas_token("ibm,get-config-addr-info2");
ibm_configure_bridge = rtas_token ("ibm,configure-bridge");
if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE)
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index a4c0bf84ef2e..3170e003f76a 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -158,7 +158,8 @@ static void eeh_report_reset(struct pci_dev *dev, void *userdata)
return;
rc = driver->err_handler->slot_reset(dev);
- if (*res == PCI_ERS_RESULT_NONE) *res = rc;
+ if ((*res == PCI_ERS_RESULT_NONE) ||
+ (*res == PCI_ERS_RESULT_RECOVERED)) *res = rc;
if (*res == PCI_ERS_RESULT_DISCONNECT &&
rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
}
@@ -248,6 +249,7 @@ static void eeh_report_failure(struct pci_dev *dev, void *userdata)
static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
{
+ struct device_node *dn;
int cnt, rc;
/* pcibios will clear the counter; save the value */
@@ -263,23 +265,20 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
if (rc)
return rc;
- /* New-style config addrs might be shared across multiple devices,
- * Walk over all functions on this device */
- if (pe_dn->eeh_pe_config_addr) {
- struct device_node *pe = pe_dn->node;
- pe = pe->parent->child;
- while (pe) {
- struct pci_dn *ppe = PCI_DN(pe);
- if (pe_dn->eeh_pe_config_addr == ppe->eeh_pe_config_addr) {
- rtas_configure_bridge(ppe);
- eeh_restore_bars(ppe);
- }
- pe = pe->sibling;
+ /* Walk over all functions on this device. */
+ dn = pe_dn->node;
+ if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent))
+ dn = dn->parent->child;
+
+ while (dn) {
+ struct pci_dn *ppe = PCI_DN(dn);
+ /* On Power4, always true because eeh_pe_config_addr=0 */
+ if (pe_dn->eeh_pe_config_addr == ppe->eeh_pe_config_addr) {
+ rtas_configure_bridge(ppe);
+ eeh_restore_bars(ppe);
}
- } else {
- rtas_configure_bridge(pe_dn);
- eeh_restore_bars(pe_dn);
- }
+ dn = dn->sibling;
+ }
/* Give the system 5 seconds to finish running the user-space
* hotplug shutdown scripts, e.g. ifdown for ethernet. Yes,
@@ -299,7 +298,7 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
/* The longest amount of time to wait for a pci device
* to come back on line, in seconds.
*/
-#define MAX_WAIT_FOR_RECOVERY 15
+#define MAX_WAIT_FOR_RECOVERY 150
struct pci_dn * handle_eeh_events (struct eeh_event *event)
{
@@ -315,14 +314,14 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
if (!frozen_dn) {
- location = get_property(event->dn, "ibm,loc-code", NULL);
+ location = of_get_property(event->dn, "ibm,loc-code", NULL);
location = location ? location : "unknown";
printk(KERN_ERR "EEH: Error: Cannot find partition endpoint "
"for location=%s pci addr=%s\n",
location, pci_name(event->dev));
return NULL;
}
- location = get_property(frozen_dn, "ibm,loc-code", NULL);
+ location = of_get_property(frozen_dn, "ibm,loc-code", NULL);
location = location ? location : "unknown";
/* There are two different styles for coming up with the PE.
@@ -341,13 +340,6 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
return NULL;
}
-#if 0
- /* We may get "permanent failure" messages on empty slots.
- * These are false alarms. Empty slots have no child dn. */
- if ((event->state == pci_channel_io_perm_failure) && (frozen_device == NULL))
- return;
-#endif
-
frozen_pdn = PCI_DN(frozen_dn);
frozen_pdn->eeh_freeze_count++;
@@ -362,13 +354,12 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES)
goto excess_failures;
- /* If the reset state is a '5' and the time to reset is 0 (infinity)
- * or is more then 15 seconds, then mark this as a permanent failure.
- */
- if ((event->state == pci_channel_io_perm_failure) &&
- ((event->time_unavail <= 0) ||
- (event->time_unavail > MAX_WAIT_FOR_RECOVERY*1000)))
+ /* Get the current PCI slot state. */
+ rc = eeh_wait_for_slot_status (frozen_pdn, MAX_WAIT_FOR_RECOVERY*1000);
+ if (rc < 0) {
+ printk(KERN_WARNING "EEH: Permanent failure\n");
goto hard_fail;
+ }
eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */);
printk(KERN_WARNING
@@ -390,14 +381,18 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
*/
if (result == PCI_ERS_RESULT_NONE) {
rc = eeh_reset_device(frozen_pdn, frozen_bus);
- if (rc)
+ if (rc) {
+ printk(KERN_WARNING "EEH: Unable to reset, rc=%d\n", rc);
goto hard_fail;
+ }
}
/* If all devices reported they can proceed, then re-enable MMIO */
if (result == PCI_ERS_RESULT_CAN_RECOVER) {
rc = rtas_pci_enable(frozen_pdn, EEH_THAW_MMIO);
+ if (rc < 0)
+ goto hard_fail;
if (rc) {
result = PCI_ERS_RESULT_NEED_RESET;
} else {
@@ -410,6 +405,8 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
if (result == PCI_ERS_RESULT_CAN_RECOVER) {
rc = rtas_pci_enable(frozen_pdn, EEH_THAW_DMA);
+ if (rc < 0)
+ goto hard_fail;
if (rc)
result = PCI_ERS_RESULT_NEED_RESET;
else
@@ -417,21 +414,28 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
}
/* If any device has a hard failure, then shut off everything. */
- if (result == PCI_ERS_RESULT_DISCONNECT)
+ if (result == PCI_ERS_RESULT_DISCONNECT) {
+ printk(KERN_WARNING "EEH: Device driver gave up\n");
goto hard_fail;
+ }
/* If any device called out for a reset, then reset the slot */
if (result == PCI_ERS_RESULT_NEED_RESET) {
rc = eeh_reset_device(frozen_pdn, NULL);
- if (rc)
+ if (rc) {
+ printk(KERN_WARNING "EEH: Cannot reset, rc=%d\n", rc);
goto hard_fail;
+ }
result = PCI_ERS_RESULT_NONE;
pci_walk_bus(frozen_bus, eeh_report_reset, &result);
}
/* All devices should claim they have recovered by now. */
- if (result != PCI_ERS_RESULT_RECOVERED)
+ if ((result != PCI_ERS_RESULT_RECOVERED) &&
+ (result != PCI_ERS_RESULT_NONE)) {
+ printk(KERN_WARNING "EEH: Not recovered\n");
goto hard_fail;
+ }
/* Tell all device drivers that they can resume operations */
pci_walk_bus(frozen_bus, eeh_report_resume, NULL);
diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c
index 49037edf7d39..ddb80f5d850b 100644
--- a/arch/powerpc/platforms/pseries/eeh_event.c
+++ b/arch/powerpc/platforms/pseries/eeh_event.c
@@ -118,9 +118,7 @@ static void eeh_thread_launcher(struct work_struct *dummy)
* (from a workqueue).
*/
int eeh_send_failure_event (struct device_node *dn,
- struct pci_dev *dev,
- enum pci_channel_state state,
- int time_unavail)
+ struct pci_dev *dev)
{
unsigned long flags;
struct eeh_event *event;
@@ -128,7 +126,7 @@ int eeh_send_failure_event (struct device_node *dn,
if (!mem_init_done) {
printk(KERN_ERR "EEH: event during early boot not handled\n");
- location = get_property(dn, "ibm,loc-code", NULL);
+ location = of_get_property(dn, "ibm,loc-code", NULL);
printk(KERN_ERR "EEH: device node = %s\n", dn->full_name);
printk(KERN_ERR "EEH: PCI location = %s\n", location);
return 1;
@@ -144,8 +142,6 @@ int eeh_send_failure_event (struct device_node *dn,
event->dn = dn;
event->dev = dev;
- event->state = state;
- event->time_unavail = time_unavail;
/* We may or may not be called in an interrupt context */
spin_lock_irqsave(&eeh_eventlist_lock, flags);
diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c
index 90522e3c9d46..29bf83bfb1f0 100644
--- a/arch/powerpc/platforms/pseries/firmware.c
+++ b/arch/powerpc/platforms/pseries/firmware.c
@@ -80,7 +80,7 @@ void __init fw_feature_init(void)
goto out;
}
- hypertas = get_property(dn, "ibm,hypertas-functions", &len);
+ hypertas = of_get_property(dn, "ibm,hypertas-functions", &len);
if (hypertas == NULL)
goto out;
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index f460b9cbfd46..9711eb0d5496 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -143,7 +143,7 @@ static int pseries_add_processor(struct device_node *np)
int err = -ENOSPC, len, nthreads, i;
const u32 *intserv;
- intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len);
+ intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", &len);
if (!intserv)
return 0;
@@ -203,7 +203,7 @@ static void pseries_remove_processor(struct device_node *np)
int len, nthreads, i;
const u32 *intserv;
- intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len);
+ intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", &len);
if (!intserv)
return;
diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S
index 5c7e38789897..c1427b3634ec 100644
--- a/arch/powerpc/platforms/pseries/hvCall.S
+++ b/arch/powerpc/platforms/pseries/hvCall.S
@@ -30,9 +30,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_PURR);
/*
* postcall is performed immediately before function return which
- * allows liberal use of volatile registers.
+ * allows liberal use of volatile registers. We branch around this
+ * in early init (eg when populating the MMU hashtable) by using an
+ * unconditional cpu feature.
*/
#define HCALL_INST_POSTCALL \
+BEGIN_FTR_SECTION; \
+ b 1f; \
+END_FTR_SECTION(0, 1); \
ld r4,STK_PARM(r3)(r1); /* validate opcode */ \
cmpldi cr7,r4,MAX_HCALL_OPCODE; \
bgt- cr7,1f; \
@@ -123,6 +128,40 @@ _GLOBAL(plpar_hcall)
blr /* return r3 = status */
+/*
+ * plpar_hcall_raw can be called in real mode. kexec/kdump need some
+ * hypervisor calls to be executed in real mode. So plpar_hcall_raw
+ * does not access the per cpu hypervisor call statistics variables,
+ * since these variables may not be present in the RMO region.
+ */
+_GLOBAL(plpar_hcall_raw)
+ HMT_MEDIUM
+
+ mfcr r0
+ stw r0,8(r1)
+
+ std r4,STK_PARM(r4)(r1) /* Save ret buffer */
+
+ mr r4,r5
+ mr r5,r6
+ mr r6,r7
+ mr r7,r8
+ mr r8,r9
+ mr r9,r10
+
+ HVSC /* invoke the hypervisor */
+
+ ld r12,STK_PARM(r4)(r1)
+ std r4, 0(r12)
+ std r5, 8(r12)
+ std r6, 16(r12)
+ std r7, 24(r12)
+
+ lwz r0,8(r1)
+ mtcrf 0xff,r0
+
+ blr /* return r3 = status */
+
_GLOBAL(plpar_hcall9)
HMT_MEDIUM
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index e6653a868b91..66665c82415c 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -242,6 +242,7 @@ static unsigned long tce_get_pSeriesLP(struct iommu_table *tbl, long tcenum)
return tce_ret;
}
+#ifdef CONFIG_PCI
static void iommu_table_setparms(struct pci_controller *phb,
struct device_node *dn,
struct iommu_table *tbl)
@@ -252,8 +253,8 @@ static void iommu_table_setparms(struct pci_controller *phb,
node = (struct device_node *)phb->arch_data;
- basep = get_property(node, "linux,tce-base", NULL);
- sizep = get_property(node, "linux,tce-size", NULL);
+ basep = of_get_property(node, "linux,tce-base", NULL);
+ sizep = of_get_property(node, "linux,tce-size", NULL);
if (basep == NULL || sizep == NULL) {
printk(KERN_ERR "PCI_DMA: iommu_table_setparms: %s has "
"missing tce entries !\n", dn->full_name);
@@ -403,7 +404,7 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
/* Find nearest ibm,dma-window, walking up the device tree */
for (pdn = dn; pdn != NULL; pdn = pdn->parent) {
- dma_window = get_property(pdn, "ibm,dma-window", NULL);
+ dma_window = of_get_property(pdn, "ibm,dma-window", NULL);
if (dma_window != NULL)
break;
}
@@ -478,29 +479,6 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
pci_name(dev));
}
-static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node)
-{
- int err = NOTIFY_OK;
- struct device_node *np = node;
- struct pci_dn *pci = PCI_DN(np);
-
- switch (action) {
- case PSERIES_RECONFIG_REMOVE:
- if (pci && pci->iommu_table &&
- get_property(np, "ibm,dma-window", NULL))
- iommu_free_table(np);
- break;
- default:
- err = NOTIFY_DONE;
- break;
- }
- return err;
-}
-
-static struct notifier_block iommu_reconfig_nb = {
- .notifier_call = iommu_reconfig_notifier,
-};
-
static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
{
struct device_node *pdn, *dn;
@@ -521,7 +499,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table;
pdn = pdn->parent) {
- dma_window = get_property(pdn, "ibm,dma-window", NULL);
+ dma_window = of_get_property(pdn, "ibm,dma-window", NULL);
if (dma_window)
break;
}
@@ -554,15 +532,44 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
dev->dev.archdata.dma_data = pci->iommu_table;
}
+#else /* CONFIG_PCI */
+#define pci_dma_bus_setup_pSeries NULL
+#define pci_dma_dev_setup_pSeries NULL
+#define pci_dma_bus_setup_pSeriesLP NULL
+#define pci_dma_dev_setup_pSeriesLP NULL
+#endif /* !CONFIG_PCI */
+
+static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node)
+{
+ int err = NOTIFY_OK;
+ struct device_node *np = node;
+ struct pci_dn *pci = PCI_DN(np);
+
+ switch (action) {
+ case PSERIES_RECONFIG_REMOVE:
+ if (pci && pci->iommu_table &&
+ of_get_property(np, "ibm,dma-window", NULL))
+ iommu_free_table(np);
+ break;
+ default:
+ err = NOTIFY_DONE;
+ break;
+ }
+ return err;
+}
+
+static struct notifier_block iommu_reconfig_nb = {
+ .notifier_call = iommu_reconfig_notifier,
+};
/* These are called very early. */
void iommu_init_early_pSeries(void)
{
- if (of_chosen && get_property(of_chosen, "linux,iommu-off", NULL)) {
+ if (of_chosen && of_get_property(of_chosen, "linux,iommu-off", NULL)) {
/* Direct I/O, IOMMU off */
ppc_md.pci_dma_dev_setup = NULL;
ppc_md.pci_dma_bus_setup = NULL;
- pci_dma_ops = &dma_direct_ops;
+ set_pci_dma_ops(&dma_direct_ops);
return;
}
@@ -588,6 +595,6 @@ void iommu_init_early_pSeries(void)
pSeries_reconfig_notifier_register(&iommu_reconfig_nb);
- pci_dma_ops = &dma_iommu_ops;
+ set_pci_dma_ops(&dma_iommu_ops);
}
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 7496005566ef..3a70e8ad7bc8 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -209,13 +209,13 @@ void __init find_udbg_vterm(void)
/* find the boot console from /chosen/stdout */
if (!of_chosen)
return;
- name = get_property(of_chosen, "linux,stdout-path", NULL);
+ name = of_get_property(of_chosen, "linux,stdout-path", NULL);
if (name == NULL)
return;
stdout_node = of_find_node_by_path(name);
if (!stdout_node)
return;
- name = get_property(stdout_node, "name", NULL);
+ name = of_get_property(stdout_node, "name", NULL);
if (!name) {
printk(KERN_WARNING "stdout node missing 'name' property!\n");
goto out;
@@ -226,7 +226,7 @@ void __init find_udbg_vterm(void)
/* Check if it's a virtual terminal */
if (strncmp(name, "vty", 3) != 0)
goto out;
- termno = get_property(stdout_node, "reg", NULL);
+ termno = of_get_property(stdout_node, "reg", NULL);
if (termno == NULL)
goto out;
vtermno = termno[0];
@@ -378,7 +378,7 @@ static void pSeries_lpar_hptab_clear(void)
/* TODO: Use bulk call */
for (i = 0; i < hpte_count; i++)
- plpar_pte_remove(0, i, 0, &dummy1, &dummy2);
+ plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2);
}
/*
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index 64163cecdf93..f68903e15bd5 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -130,7 +130,7 @@ int __init pSeries_nvram_init(void)
if (nvram == NULL)
return -ENODEV;
- nbytes_p = get_property(nvram, "#bytes", &proplen);
+ nbytes_p = of_get_property(nvram, "#bytes", &proplen);
if (nbytes_p == NULL || proplen != sizeof(unsigned int))
return -EIO;
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c
index fa59124ce3fe..2c6ded29f73d 100644
--- a/arch/powerpc/platforms/pseries/pci.c
+++ b/arch/powerpc/platforms/pseries/pci.c
@@ -25,6 +25,7 @@
#include <linux/pci.h>
#include <linux/string.h>
+#include <asm/eeh.h>
#include <asm/pci-bridge.h>
#include <asm/prom.h>
#include <asm/ppc-pci.h>
@@ -39,7 +40,7 @@ void pcibios_name_device(struct pci_dev *dev)
*/
dn = pci_device_to_OF_node(dev);
if (dn) {
- char *loc_code = get_property(dn, "ibm,loc-code", 0);
+ const char *loc_code = of_get_property(dn, "ibm,loc-code", 0);
if (loc_code) {
int loc_len = strlen(loc_code);
if (loc_len < sizeof(dev->dev.name)) {
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index ac56b868913a..fdc1a369f767 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -29,6 +29,7 @@
#include <asm/pci-bridge.h>
#include <asm/ppc-pci.h>
#include <asm/firmware.h>
+#include <asm/eeh.h>
static struct pci_bus *
find_bus_among_children(struct pci_bus *bus,
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h
index 3eb7b294d92f..2e4d10c9eea8 100644
--- a/arch/powerpc/platforms/pseries/plpar_wrappers.h
+++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h
@@ -78,6 +78,22 @@ static inline long plpar_pte_remove(unsigned long flags, unsigned long ptex,
return rc;
}
+/* plpar_pte_remove_raw can be called in real mode. It calls plpar_hcall_raw */
+static inline long plpar_pte_remove_raw(unsigned long flags, unsigned long ptex,
+ unsigned long avpn, unsigned long *old_pteh_ret,
+ unsigned long *old_ptel_ret)
+{
+ long rc;
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+ rc = plpar_hcall_raw(H_REMOVE, retbuf, flags, ptex, avpn);
+
+ *old_pteh_ret = retbuf[0];
+ *old_ptel_ret = retbuf[1];
+
+ return rc;
+}
+
static inline long plpar_pte_read(unsigned long flags, unsigned long ptex,
unsigned long *old_pteh_ret, unsigned long *old_ptel_ret)
{
diff --git a/arch/powerpc/platforms/pseries/power.c b/arch/powerpc/platforms/pseries/power.c
new file mode 100644
index 000000000000..2624b71df73d
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/power.c
@@ -0,0 +1,87 @@
+/*
+ * Interface for power-management for ppc64 compliant platform
+ *
+ * Manish Ahuja <mahuja@us.ibm.com>
+ *
+ * Feb 2007
+ *
+ * Copyright (C) 2007 IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kobject.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+unsigned long rtas_poweron_auto; /* default and normal state is 0 */
+
+static ssize_t auto_poweron_show(struct subsystem *subsys, char *buf)
+{
+ return sprintf(buf, "%lu\n", rtas_poweron_auto);
+}
+
+static ssize_t
+auto_poweron_store(struct subsystem *subsys, const char *buf, size_t n)
+{
+ int ret;
+ unsigned long ups_restart;
+ ret = sscanf(buf, "%lu", &ups_restart);
+
+ if ((ret == 1) && ((ups_restart == 1) || (ups_restart == 0))){
+ rtas_poweron_auto = ups_restart;
+ return n;
+ }
+ return -EINVAL;
+}
+
+static struct subsys_attribute auto_poweron_attr = {
+ .attr = {
+ .name = __stringify(auto_poweron),
+ .mode = 0644,
+ },
+ .show = auto_poweron_show,
+ .store = auto_poweron_store,
+};
+
+#ifndef CONFIG_PM
+decl_subsys(power,NULL,NULL);
+
+static struct attribute *g[] = {
+ &auto_poweron_attr.attr,
+ NULL,
+};
+
+static struct attribute_group attr_group = {
+ .attrs = g,
+};
+
+static int __init pm_init(void)
+{
+ int error = subsystem_register(&power_subsys);
+ if (!error)
+ error = sysfs_create_group(&power_subsys.kset.kobj,&attr_group);
+ return error;
+}
+core_initcall(pm_init);
+#else
+extern struct subsystem power_subsys;
+
+static int __init apo_pm_init(void)
+{
+ return (subsys_create_file(&power_subsys, &auto_poweron_attr));
+}
+__initcall(apo_pm_init);
+#endif
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
index b43f1397a5b6..22bc01989749 100644
--- a/arch/powerpc/platforms/pseries/pseries.h
+++ b/arch/powerpc/platforms/pseries/pseries.h
@@ -29,8 +29,11 @@ static inline smp_init_pseries_xics(void) { };
extern void setup_kexec_cpu_down_xics(void);
extern void setup_kexec_cpu_down_mpic(void);
#else
-static inline setup_kexec_cpu_down_xics(void) { };
-static inline setup_kexec_cpu_down_mpic(void) { };
+static inline void setup_kexec_cpu_down_xics(void) { }
+static inline void setup_kexec_cpu_down_mpic(void) { }
#endif
+/* Poweron flag used for enabling auto ups restart */
+extern unsigned long rtas_poweron_auto;
+
#endif /* _PSERIES_PSERIES_H */
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index edc038873113..53aa04101ced 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -85,7 +85,7 @@ static void request_ras_irqs(struct device_node *np,
* map those interrupts using the default interrupt host and default
* trigger
*/
- opicprop = get_property(np, "open-pic-interrupt", &opicplen);
+ opicprop = of_get_property(np, "open-pic-interrupt", &opicplen);
if (opicprop) {
opicplen /= sizeof(u32);
for (i = 0; i < opicplen; i++) {
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c
index 77d0937d5c07..9797b10b2935 100644
--- a/arch/powerpc/platforms/pseries/rtasd.c
+++ b/arch/powerpc/platforms/pseries/rtasd.c
@@ -363,7 +363,7 @@ static int get_eventscan_parms(void)
node = of_find_node_by_path("/rtas");
- ip = get_property(node, "rtas-event-scan-rate", NULL);
+ ip = of_get_property(node, "rtas-event-scan-rate", NULL);
if (ip == NULL) {
printk(KERN_ERR "rtasd: no rtas-event-scan-rate\n");
of_node_put(node);
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 435a04596526..33eec2822c66 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -65,6 +65,7 @@
#include <asm/udbg.h>
#include <asm/smp.h>
#include <asm/firmware.h>
+#include <asm/eeh.h>
#include "plpar_wrappers.h"
#include "pseries.h"
@@ -92,7 +93,7 @@ static void pSeries_show_cpuinfo(struct seq_file *m)
root = of_find_node_by_path("/");
if (root)
- model = get_property(root, "model", NULL);
+ model = of_get_property(root, "model", NULL);
seq_printf(m, "machine\t\t: CHRP %s\n", model);
of_node_put(root);
}
@@ -138,8 +139,8 @@ static void __init pseries_mpic_init_IRQ(void)
struct mpic *mpic;
np = of_find_node_by_path("/");
- naddr = prom_n_addr_cells(np);
- opprop = get_property(np, "platform-open-pic", &opplen);
+ naddr = of_n_addr_cells(np);
+ opprop = of_get_property(np, "platform-open-pic", &opplen);
if (opprop != 0) {
openpic_addr = of_read_number(opprop, naddr);
printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
@@ -188,11 +189,11 @@ static void __init pseries_mpic_init_IRQ(void)
break;
if (strcmp(np->name, "pci") != 0)
continue;
- addrp = get_property(np, "8259-interrupt-acknowledge",
+ addrp = of_get_property(np, "8259-interrupt-acknowledge",
NULL);
if (addrp == NULL)
continue;
- naddr = prom_n_addr_cells(np);
+ naddr = of_n_addr_cells(np);
intack = addrp[naddr-1];
if (naddr > 1)
intack |= ((unsigned long)addrp[naddr-2]) << 32;
@@ -225,7 +226,7 @@ static void __init pseries_discover_pic(void)
for (np = NULL; (np = of_find_node_by_name(np,
"interrupt-controller"));) {
- typep = get_property(np, "compatible", NULL);
+ typep = of_get_property(np, "compatible", NULL);
if (strstr(typep, "open-pic")) {
pSeries_mpic_node = of_node_get(np);
ppc_md.init_IRQ = pseries_mpic_init_IRQ;
@@ -334,32 +335,6 @@ static void __init pSeries_init_early(void)
DBG(" <- pSeries_init_early()\n");
}
-
-static int pSeries_check_legacy_ioport(unsigned int baseport)
-{
- struct device_node *np;
-
-#define I8042_DATA_REG 0x60
-#define FDC_BASE 0x3f0
-
-
- switch(baseport) {
- case I8042_DATA_REG:
- np = of_find_node_by_type(NULL, "8042");
- if (np == NULL)
- return -ENODEV;
- of_node_put(np);
- break;
- case FDC_BASE:
- np = of_find_node_by_type(NULL, "fdc");
- if (np == NULL)
- return -ENODEV;
- of_node_put(np);
- break;
- }
- return 0;
-}
-
/*
* Called very early, MMU is off, device-tree isn't unflattened
*/
@@ -486,6 +461,38 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus)
return PCI_PROBE_NORMAL;
}
+/**
+ * pSeries_power_off - tell firmware about how to power off the system.
+ *
+ * This function calls either the power-off rtas token in normal cases
+ * or the ibm,power-off-ups token (if present & requested) in case of
+ * a power failure. If power-off token is used, power on will only be
+ * possible with power button press. If ibm,power-off-ups token is used
+ * it will allow auto poweron after power is restored.
+ */
+void pSeries_power_off(void)
+{
+ int rc;
+ int rtas_poweroff_ups_token = rtas_token("ibm,power-off-ups");
+
+ if (rtas_flash_term_hook)
+ rtas_flash_term_hook(SYS_POWER_OFF);
+
+ if (rtas_poweron_auto == 0 ||
+ rtas_poweroff_ups_token == RTAS_UNKNOWN_SERVICE) {
+ rc = rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1);
+ printk(KERN_INFO "RTAS power-off returned %d\n", rc);
+ } else {
+ rc = rtas_call(rtas_poweroff_ups_token, 0, 1, NULL);
+ printk(KERN_INFO "RTAS ibm,power-off-ups returned %d\n", rc);
+ }
+ for (;;);
+}
+
+#ifndef CONFIG_PCI
+void pSeries_final_fixup(void) { }
+#endif
+
define_machine(pseries) {
.name = "pSeries",
.probe = pSeries_probe,
@@ -496,7 +503,7 @@ define_machine(pseries) {
.pcibios_fixup = pSeries_final_fixup,
.pci_probe_mode = pSeries_pci_probe_mode,
.restart = rtas_restart,
- .power_off = rtas_power_off,
+ .power_off = pSeries_power_off,
.halt = rtas_halt,
.panic = rtas_os_term,
.get_boot_time = rtas_get_boot_time,
@@ -504,7 +511,6 @@ define_machine(pseries) {
.set_rtc_time = rtas_set_rtc_time,
.calibrate_decr = generic_calibrate_decr,
.progress = rtas_progress,
- .check_legacy_ioport = pSeries_check_legacy_ioport,
.system_reset_exception = pSeries_system_reset_exception,
.machine_check_exception = pSeries_machine_check_exception,
};
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 81d172d65038..896cbf340c42 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -576,7 +576,7 @@ static void __init xics_init_one_node(struct device_node *np,
* This happens to be the case so far but we are playing with fire...
* should be fixed one of these days. -BenH.
*/
- ireg = get_property(np, "ibm,interrupt-server-ranges", NULL);
+ ireg = of_get_property(np, "ibm,interrupt-server-ranges", NULL);
/* Do that ever happen ? we'll know soon enough... but even good'old
* f80 does have that property ..
@@ -588,7 +588,7 @@ static void __init xics_init_one_node(struct device_node *np,
*/
*indx = *ireg;
}
- ireg = get_property(np, "reg", &ilen);
+ ireg = of_get_property(np, "reg", &ilen);
if (!ireg)
panic("xics_init_IRQ: can't find interrupt reg property");
@@ -640,10 +640,10 @@ static void __init xics_setup_8259_cascade(void)
break;
if (strcmp(np->name, "pci") != 0)
continue;
- addrp = get_property(np, "8259-interrupt-acknowledge", NULL);
+ addrp = of_get_property(np, "8259-interrupt-acknowledge", NULL);
if (addrp == NULL)
continue;
- naddr = prom_n_addr_cells(np);
+ naddr = of_n_addr_cells(np);
intack = addrp[naddr-1];
if (naddr > 1)
intack |= ((unsigned long)addrp[naddr-2]) << 32;
@@ -664,10 +664,11 @@ static struct device_node *cpuid_to_of_node(int cpu)
int i, len;
const u32 *intserv;
- intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len);
+ intserv = of_get_property(np, "ibm,ppc-interrupt-server#s",
+ &len);
if (!intserv)
- intserv = get_property(np, "reg", &len);
+ intserv = of_get_property(np, "reg", &len);
i = len / sizeof(u32);
@@ -709,7 +710,7 @@ void __init xics_init_IRQ(void)
/* Find the server numbers for the boot cpu. */
np = cpuid_to_of_node(boot_cpuid);
BUG_ON(!np);
- ireg = get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
+ ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
if (!ireg)
goto skip_gserver_check;
i = ilen / sizeof(int);
@@ -725,7 +726,7 @@ void __init xics_init_IRQ(void)
default_server = hcpuid;
default_distrib_server = ireg[j+1];
- isize = get_property(np,
+ isize = of_get_property(np,
"ibm,interrupt-server#-size", NULL);
if (isize)
interrupt_server_size = *isize;