aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/.gitignore1
-rw-r--r--arch/powerpc/Kconfig105
-rw-r--r--arch/powerpc/Kconfig.debug13
-rw-r--r--arch/powerpc/boot/.gitignore13
-rw-r--r--arch/powerpc/boot/Makefile15
-rw-r--r--arch/powerpc/boot/dts/kuroboxHG.dts148
-rw-r--r--arch/powerpc/boot/dts/lite5200.dts313
-rw-r--r--arch/powerpc/boot/dts/lite5200b.dts318
-rw-r--r--arch/powerpc/boot/dts/mpc7448hpc2.dts44
-rw-r--r--arch/powerpc/boot/flatdevtree.c880
-rw-r--r--arch/powerpc/boot/flatdevtree.h62
-rw-r--r--arch/powerpc/boot/flatdevtree_env.h47
-rw-r--r--arch/powerpc/boot/flatdevtree_misc.c51
-rw-r--r--arch/powerpc/boot/io.h53
-rw-r--r--arch/powerpc/boot/main.c57
-rw-r--r--arch/powerpc/boot/mktree.c152
-rw-r--r--arch/powerpc/boot/ns16550.c74
-rw-r--r--arch/powerpc/boot/of.c8
-rw-r--r--arch/powerpc/boot/ops.h26
-rw-r--r--arch/powerpc/boot/serial.c142
-rw-r--r--arch/powerpc/boot/simple_alloc.c149
-rw-r--r--arch/powerpc/boot/stdio.c3
-rw-r--r--arch/powerpc/boot/util.S88
-rwxr-xr-xarch/powerpc/boot/wrapper3
-rw-r--r--arch/powerpc/boot/zImage.coff.lds.S4
-rw-r--r--arch/powerpc/configs/cell_defconfig50
-rw-r--r--arch/powerpc/configs/linkstation_defconfig1583
-rw-r--r--arch/powerpc/configs/lite5200_defconfig931
-rw-r--r--arch/powerpc/configs/ppc64_defconfig4
-rw-r--r--arch/powerpc/configs/ps3_defconfig837
-rw-r--r--arch/powerpc/kernel/Makefile15
-rw-r--r--arch/powerpc/kernel/asm-offsets.c3
-rw-r--r--arch/powerpc/kernel/cpu_setup_ppc970.S16
-rw-r--r--arch/powerpc/kernel/cputable.c62
-rw-r--r--arch/powerpc/kernel/crash.c4
-rw-r--r--arch/powerpc/kernel/dma_64.c249
-rw-r--r--arch/powerpc/kernel/entry_64.S51
-rw-r--r--arch/powerpc/kernel/head_64.S163
-rw-r--r--arch/powerpc/kernel/ibmebus.c9
-rw-r--r--arch/powerpc/kernel/idle.c7
-rw-r--r--arch/powerpc/kernel/idle_power4.S8
-rw-r--r--arch/powerpc/kernel/io.c105
-rw-r--r--arch/powerpc/kernel/iomap.c2
-rw-r--r--arch/powerpc/kernel/iommu.c6
-rw-r--r--arch/powerpc/kernel/irq.c80
-rw-r--r--arch/powerpc/kernel/of_device.c173
-rw-r--r--arch/powerpc/kernel/of_platform.c489
-rw-r--r--arch/powerpc/kernel/pci_32.c96
-rw-r--r--arch/powerpc/kernel/pci_64.c70
-rw-r--r--arch/powerpc/kernel/pci_direct_iommu.c98
-rw-r--r--arch/powerpc/kernel/pci_iommu.c164
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c4
-rw-r--r--arch/powerpc/kernel/prom.c111
-rw-r--r--arch/powerpc/kernel/prom_init.c18
-rw-r--r--arch/powerpc/kernel/prom_parse.c290
-rw-r--r--arch/powerpc/kernel/rtas.c5
-rw-r--r--arch/powerpc/kernel/rtas_flash.c4
-rw-r--r--arch/powerpc/kernel/rtas_pci.c35
-rw-r--r--arch/powerpc/kernel/setup_32.c6
-rw-r--r--arch/powerpc/kernel/setup_64.c18
-rw-r--r--arch/powerpc/kernel/smp-tbsync.c5
-rw-r--r--arch/powerpc/kernel/smp.c1
-rw-r--r--arch/powerpc/kernel/sys_ppc32.c1
-rw-r--r--arch/powerpc/kernel/sysfs.c76
-rw-r--r--arch/powerpc/kernel/time.c7
-rw-r--r--arch/powerpc/kernel/traps.c8
-rw-r--r--arch/powerpc/kernel/vio.c94
-rw-r--r--arch/powerpc/mm/Makefile2
-rw-r--r--arch/powerpc/mm/fault.c25
-rw-r--r--arch/powerpc/mm/hash_native_64.c2
-rw-r--r--arch/powerpc/mm/hash_utils_64.c2
-rw-r--r--arch/powerpc/mm/init_64.c2
-rw-r--r--arch/powerpc/mm/pgtable_32.c33
-rw-r--r--arch/powerpc/mm/pgtable_64.c52
-rw-r--r--arch/powerpc/mm/slb.c13
-rw-r--r--arch/powerpc/oprofile/Makefile1
-rw-r--r--arch/powerpc/oprofile/common.c15
-rw-r--r--arch/powerpc/oprofile/op_model_cell.c724
-rw-r--r--arch/powerpc/platforms/52xx/Makefile9
-rw-r--r--arch/powerpc/platforms/52xx/efika-pci.c119
-rw-r--r--arch/powerpc/platforms/52xx/efika-setup.c150
-rw-r--r--arch/powerpc/platforms/52xx/efika.h19
-rw-r--r--arch/powerpc/platforms/52xx/lite5200.c162
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_common.c126
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_pic.c473
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_pic.h53
-rw-r--r--arch/powerpc/platforms/82xx/mpc82xx_ads.c13
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_mds.c2
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_itx.c3
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_sys.c3
-rw-r--r--arch/powerpc/platforms/83xx/mpc8360e_pb.c2
-rw-r--r--arch/powerpc/platforms/83xx/mpc83xx.h1
-rw-r--r--arch/powerpc/platforms/83xx/pci.c9
-rw-r--r--arch/powerpc/platforms/85xx/misc.c8
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ads.c11
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_hpcn.c10
-rw-r--r--arch/powerpc/platforms/Makefile4
-rw-r--r--arch/powerpc/platforms/cell/Kconfig14
-rw-r--r--arch/powerpc/platforms/cell/Makefile7
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq.c248
-rw-r--r--arch/powerpc/platforms/cell/cbe_regs.c71
-rw-r--r--arch/powerpc/platforms/cell/cbe_regs.h203
-rw-r--r--arch/powerpc/platforms/cell/cbe_thermal.c226
-rw-r--r--arch/powerpc/platforms/cell/interrupt.c16
-rw-r--r--arch/powerpc/platforms/cell/interrupt.h2
-rw-r--r--arch/powerpc/platforms/cell/io-workarounds.c346
-rw-r--r--arch/powerpc/platforms/cell/iommu.c1049
-rw-r--r--arch/powerpc/platforms/cell/iommu.h65
-rw-r--r--arch/powerpc/platforms/cell/pervasive.c101
-rw-r--r--arch/powerpc/platforms/cell/pmu.c429
-rw-r--r--arch/powerpc/platforms/cell/setup.c78
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c415
-rw-r--r--arch/powerpc/platforms/cell/spu_coredump.c81
-rw-r--r--arch/powerpc/platforms/cell/spu_priv1_mmio.c428
-rw-r--r--arch/powerpc/platforms/cell/spu_priv1_mmio.h26
-rw-r--r--arch/powerpc/platforms/cell/spufs/Makefile2
-rw-r--r--arch/powerpc/platforms/cell/spufs/backing_ops.c31
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c27
-rw-r--r--arch/powerpc/platforms/cell/spufs/coredump.c238
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c536
-rw-r--r--arch/powerpc/platforms/cell/spufs/hw_ops.c51
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c58
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c149
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h33
-rw-r--r--arch/powerpc/platforms/cell/spufs/switch.c63
-rw-r--r--arch/powerpc/platforms/chrp/chrp.h1
-rw-r--r--arch/powerpc/platforms/chrp/pci.c9
-rw-r--r--arch/powerpc/platforms/chrp/setup.c2
-rw-r--r--arch/powerpc/platforms/embedded6xx/Kconfig30
-rw-r--r--arch/powerpc/platforms/embedded6xx/Makefile1
-rw-r--r--arch/powerpc/platforms/embedded6xx/linkstation.c211
-rw-r--r--arch/powerpc/platforms/embedded6xx/ls_uart.c131
-rw-r--r--arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c94
-rw-r--r--arch/powerpc/platforms/iseries/Makefile8
-rw-r--r--arch/powerpc/platforms/iseries/dt.c15
-rw-r--r--arch/powerpc/platforms/iseries/iommu.c16
-rw-r--r--arch/powerpc/platforms/iseries/ksyms.c6
-rw-r--r--arch/powerpc/platforms/iseries/misc.S35
-rw-r--r--arch/powerpc/platforms/iseries/pci.c372
-rw-r--r--arch/powerpc/platforms/iseries/setup.c48
-rw-r--r--arch/powerpc/platforms/iseries/viopath.c3
-rw-r--r--arch/powerpc/platforms/maple/maple.h2
-rw-r--r--arch/powerpc/platforms/maple/pci.c47
-rw-r--r--arch/powerpc/platforms/maple/setup.c2
-rw-r--r--arch/powerpc/platforms/pasemi/pasemi.h1
-rw-r--r--arch/powerpc/platforms/pasemi/pci.c8
-rw-r--r--arch/powerpc/platforms/pasemi/setup.c17
-rw-r--r--arch/powerpc/platforms/powermac/feature.c8
-rw-r--r--arch/powerpc/platforms/powermac/pci.c35
-rw-r--r--arch/powerpc/platforms/powermac/pmac.h2
-rw-r--r--arch/powerpc/platforms/powermac/setup.c7
-rw-r--r--arch/powerpc/platforms/ps3/Kconfig43
-rw-r--r--arch/powerpc/platforms/ps3/Makefile4
-rw-r--r--arch/powerpc/platforms/ps3/exports.c27
-rw-r--r--arch/powerpc/platforms/ps3/htab.c277
-rw-r--r--arch/powerpc/platforms/ps3/hvcall.S804
-rw-r--r--arch/powerpc/platforms/ps3/interrupt.c575
-rw-r--r--arch/powerpc/platforms/ps3/mm.c831
-rw-r--r--arch/powerpc/platforms/ps3/os-area.c259
-rw-r--r--arch/powerpc/platforms/ps3/platform.h68
-rw-r--r--arch/powerpc/platforms/ps3/repository.c840
-rw-r--r--arch/powerpc/platforms/ps3/setup.c173
-rw-r--r--arch/powerpc/platforms/ps3/smp.c158
-rw-r--r--arch/powerpc/platforms/ps3/spu.c613
-rw-r--r--arch/powerpc/platforms/ps3/time.c104
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c90
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c4
-rw-r--r--arch/powerpc/platforms/pseries/pci.c35
-rw-r--r--arch/powerpc/platforms/pseries/pci_dlpar.c6
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c3
-rw-r--r--arch/powerpc/platforms/pseries/setup.c5
-rw-r--r--arch/powerpc/platforms/pseries/xics.c68
-rw-r--r--arch/powerpc/sysdev/Makefile5
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c34
-rw-r--r--arch/powerpc/sysdev/dcr-low.S39
-rw-r--r--arch/powerpc/sysdev/dcr.c137
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c28
-rw-r--r--arch/powerpc/sysdev/mpic.c172
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe.c3
-rw-r--r--arch/powerpc/sysdev/qe_lib/ucc_fast.c4
-rw-r--r--arch/powerpc/sysdev/qe_lib/ucc_slow.c4
-rw-r--r--arch/powerpc/sysdev/rom.c31
-rw-r--r--arch/powerpc/sysdev/todc.c392
-rw-r--r--arch/powerpc/sysdev/tsi108_pci.c48
-rw-r--r--arch/powerpc/xmon/Makefile9
-rw-r--r--arch/powerpc/xmon/dis-asm.h31
-rw-r--r--arch/powerpc/xmon/ppc-dis.c29
-rw-r--r--arch/powerpc/xmon/ppc-opc.c778
-rw-r--r--arch/powerpc/xmon/ppc.h39
-rw-r--r--arch/powerpc/xmon/spu-dis.c248
-rw-r--r--arch/powerpc/xmon/spu-insns.h410
-rw-r--r--arch/powerpc/xmon/spu-opc.c44
-rw-r--r--arch/powerpc/xmon/spu.h126
-rw-r--r--arch/powerpc/xmon/xmon.c356
194 files changed, 21134 insertions, 3699 deletions
diff --git a/arch/powerpc/.gitignore b/arch/powerpc/.gitignore
new file mode 100644
index 000000000000..a1a869c8c840
--- /dev/null
+++ b/arch/powerpc/.gitignore
@@ -0,0 +1 @@
include
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 116d7d3683ed..291c95ac4b31 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -112,7 +112,7 @@ choice
112 default 6xx 112 default 6xx
113 113
114config CLASSIC32 114config CLASSIC32
115 bool "6xx/7xx/74xx" 115 bool "52xx/6xx/7xx/74xx"
116 select PPC_FPU 116 select PPC_FPU
117 select 6xx 117 select 6xx
118 help 118 help
@@ -121,16 +121,18 @@ config CLASSIC32
121 versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the AMCC 121 versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the AMCC
122 embedded versions (403 and 405) and the high end 64 bit Power 122 embedded versions (403 and 405) and the high end 64 bit Power
123 processors (POWER 3, POWER4, and IBM PPC970 also known as G5). 123 processors (POWER 3, POWER4, and IBM PPC970 also known as G5).
124
125 This option is the catch-all for 6xx types, including some of the
126 embedded versions. Unless there is see an option for the specific
127 chip family you are using, you want this option.
128
129 You do not want this if you are building a kernel for a 64 bit
130 IBM RS/6000 or an Apple G5, choose 6xx.
131
132 If unsure, select this option
124 133
125 Unless you are building a kernel for one of the embedded processor
126 systems, 64 bit IBM RS/6000 or an Apple G5, choose 6xx.
127 Note that the kernel runs in 32-bit mode even on 64-bit chips. 134 Note that the kernel runs in 32-bit mode even on 64-bit chips.
128 135
129config PPC_52xx
130 bool "Freescale 52xx"
131 select 6xx
132 select PPC_FPU
133
134config PPC_82xx 136config PPC_82xx
135 bool "Freescale 82xx" 137 bool "Freescale 82xx"
136 select 6xx 138 select 6xx
@@ -160,9 +162,11 @@ config PPC_86xx
160 162
161config 40x 163config 40x
162 bool "AMCC 40x" 164 bool "AMCC 40x"
165 select PPC_DCR_NATIVE
163 166
164config 44x 167config 44x
165 bool "AMCC 44x" 168 bool "AMCC 44x"
169 select PPC_DCR_NATIVE
166 170
167config 8xx 171config 8xx
168 bool "Freescale 8xx" 172 bool "Freescale 8xx"
@@ -208,6 +212,24 @@ config PPC_FPU
208 bool 212 bool
209 default y if PPC64 213 default y if PPC64
210 214
215config PPC_DCR_NATIVE
216 bool
217 default n
218
219config PPC_DCR_MMIO
220 bool
221 default n
222
223config PPC_DCR
224 bool
225 depends on PPC_DCR_NATIVE || PPC_DCR_MMIO
226 default y
227
228config PPC_OF_PLATFORM_PCI
229 bool
230 depends on PPC64 # not supported on 32 bits yet
231 default n
232
211config BOOKE 233config BOOKE
212 bool 234 bool
213 depends on E200 || E500 235 depends on E200 || E500
@@ -227,6 +249,7 @@ config PTE_64BIT
227config PHYS_64BIT 249config PHYS_64BIT
228 bool 'Large physical address support' if E500 250 bool 'Large physical address support' if E500
229 depends on 44x || E500 251 depends on 44x || E500
252 select RESOURCES_64BIT
230 default y if 44x 253 default y if 44x
231 ---help--- 254 ---help---
232 This option enables kernel support for larger than 32-bit physical 255 This option enables kernel support for larger than 32-bit physical
@@ -369,11 +392,13 @@ config PPC_PSERIES
369 select PPC_RTAS 392 select PPC_RTAS
370 select RTAS_ERROR_LOGGING 393 select RTAS_ERROR_LOGGING
371 select PPC_UDBG_16550 394 select PPC_UDBG_16550
395 select PPC_NATIVE
372 default y 396 default y
373 397
374config PPC_ISERIES 398config PPC_ISERIES
375 bool "IBM Legacy iSeries" 399 bool "IBM Legacy iSeries"
376 depends on PPC_MULTIPLATFORM && PPC64 400 depends on PPC_MULTIPLATFORM && PPC64
401 select PPC_INDIRECT_IO
377 402
378config PPC_CHRP 403config PPC_CHRP
379 bool "Common Hardware Reference Platform (CHRP) based machines" 404 bool "Common Hardware Reference Platform (CHRP) based machines"
@@ -384,14 +409,35 @@ config PPC_CHRP
384 select PPC_RTAS 409 select PPC_RTAS
385 select PPC_MPC106 410 select PPC_MPC106
386 select PPC_UDBG_16550 411 select PPC_UDBG_16550
412 select PPC_NATIVE
413 default y
414
415config PPC_MPC52xx
416 bool
417 default n
418
419config PPC_EFIKA
420 bool "bPlan Efika 5k2. MPC5200B based computer"
421 depends on PPC_MULTIPLATFORM && PPC32
422 select PPC_RTAS
423 select RTAS_PROC
424 select PPC_MPC52xx
425 select PPC_NATIVE
387 default y 426 default y
388 427
428config PPC_LITE5200
429 bool "Freescale Lite5200 Eval Board"
430 depends on PPC_MULTIPLATFORM && PPC32
431 select PPC_MPC52xx
432 default n
433
389config PPC_PMAC 434config PPC_PMAC
390 bool "Apple PowerMac based machines" 435 bool "Apple PowerMac based machines"
391 depends on PPC_MULTIPLATFORM 436 depends on PPC_MULTIPLATFORM
392 select MPIC 437 select MPIC
393 select PPC_INDIRECT_PCI if PPC32 438 select PPC_INDIRECT_PCI if PPC32
394 select PPC_MPC106 if PPC32 439 select PPC_MPC106 if PPC32
440 select PPC_NATIVE
395 default y 441 default y
396 442
397config PPC_PMAC64 443config PPC_PMAC64
@@ -411,6 +457,7 @@ config PPC_PREP
411 select PPC_I8259 457 select PPC_I8259
412 select PPC_INDIRECT_PCI 458 select PPC_INDIRECT_PCI
413 select PPC_UDBG_16550 459 select PPC_UDBG_16550
460 select PPC_NATIVE
414 default y 461 default y
415 462
416config PPC_MAPLE 463config PPC_MAPLE
@@ -422,6 +469,7 @@ config PPC_MAPLE
422 select GENERIC_TBSYNC 469 select GENERIC_TBSYNC
423 select PPC_UDBG_16550 470 select PPC_UDBG_16550
424 select PPC_970_NAP 471 select PPC_970_NAP
472 select PPC_NATIVE
425 default n 473 default n
426 help 474 help
427 This option enables support for the Maple 970FX Evaluation Board. 475 This option enables support for the Maple 970FX Evaluation Board.
@@ -434,6 +482,7 @@ config PPC_PASEMI
434 select MPIC 482 select MPIC
435 select PPC_UDBG_16550 483 select PPC_UDBG_16550
436 select GENERIC_TBSYNC 484 select GENERIC_TBSYNC
485 select PPC_NATIVE
437 help 486 help
438 This option enables support for PA Semi's PWRficient line 487 This option enables support for PA Semi's PWRficient line
439 of SoC processors, including PA6T-1682M 488 of SoC processors, including PA6T-1682M
@@ -445,6 +494,11 @@ config PPC_CELL
445config PPC_CELL_NATIVE 494config PPC_CELL_NATIVE
446 bool 495 bool
447 select PPC_CELL 496 select PPC_CELL
497 select PPC_DCR_MMIO
498 select PPC_OF_PLATFORM_PCI
499 select PPC_INDIRECT_IO
500 select PPC_NATIVE
501 select MPIC
448 default n 502 default n
449 503
450config PPC_IBM_CELL_BLADE 504config PPC_IBM_CELL_BLADE
@@ -456,6 +510,22 @@ config PPC_IBM_CELL_BLADE
456 select PPC_UDBG_16550 510 select PPC_UDBG_16550
457 select UDBG_RTAS_CONSOLE 511 select UDBG_RTAS_CONSOLE
458 512
513config PPC_PS3
514 bool "Sony PS3"
515 depends on PPC_MULTIPLATFORM && PPC64
516 select PPC_CELL
517 help
518 This option enables support for the Sony PS3 game console
519 and other platforms using the PS3 hypervisor.
520
521config PPC_NATIVE
522 bool
523 depends on PPC_MULTIPLATFORM
524 help
525 Support for running natively on the hardware, i.e. without
526 a hypervisor. This option is not user-selectable but should
527 be selected by all platforms that need it.
528
459config UDBG_RTAS_CONSOLE 529config UDBG_RTAS_CONSOLE
460 bool "RTAS based debug console" 530 bool "RTAS based debug console"
461 depends on PPC_RTAS 531 depends on PPC_RTAS
@@ -517,6 +587,15 @@ config PPC_970_NAP
517 bool 587 bool
518 default n 588 default n
519 589
590config PPC_INDIRECT_IO
591 bool
592 select GENERIC_IOMAP
593 default n
594
595config GENERIC_IOMAP
596 bool
597 default n
598
520source "drivers/cpufreq/Kconfig" 599source "drivers/cpufreq/Kconfig"
521 600
522config CPU_FREQ_PMAC 601config CPU_FREQ_PMAC
@@ -594,12 +673,6 @@ config TAU_AVERAGE
594 673
595 If in doubt, say N here. 674 If in doubt, say N here.
596 675
597config PPC_TODC
598 depends on EMBEDDED6xx
599 bool "Generic Time-of-day Clock (TODC) support"
600 ---help---
601 This adds support for many TODC/RTC chips.
602
603endmenu 676endmenu
604 677
605source arch/powerpc/platforms/embedded6xx/Kconfig 678source arch/powerpc/platforms/embedded6xx/Kconfig
@@ -610,6 +683,7 @@ source arch/powerpc/platforms/85xx/Kconfig
610source arch/powerpc/platforms/86xx/Kconfig 683source arch/powerpc/platforms/86xx/Kconfig
611source arch/powerpc/platforms/8xx/Kconfig 684source arch/powerpc/platforms/8xx/Kconfig
612source arch/powerpc/platforms/cell/Kconfig 685source arch/powerpc/platforms/cell/Kconfig
686source arch/powerpc/platforms/ps3/Kconfig
613 687
614menu "Kernel options" 688menu "Kernel options"
615 689
@@ -790,7 +864,6 @@ source "arch/powerpc/platforms/prep/Kconfig"
790 864
791config CMDLINE_BOOL 865config CMDLINE_BOOL
792 bool "Default bootloader kernel arguments" 866 bool "Default bootloader kernel arguments"
793 depends on !PPC_ISERIES
794 867
795config CMDLINE 868config CMDLINE
796 string "Initial kernel command string" 869 string "Initial kernel command string"
@@ -880,7 +953,7 @@ config MCA
880 953
881config PCI 954config PCI
882 bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \ 955 bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \
883 || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) || MPC7448HPC2 956 || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) || MPC7448HPC2 || PPC_PS3
884 default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \ 957 default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \
885 && !PPC_85xx && !PPC_86xx 958 && !PPC_85xx && !PPC_86xx
886 default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS 959 default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 5ad149b47e34..f0e51edde022 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -77,7 +77,7 @@ config KGDB_CONSOLE
77 77
78config XMON 78config XMON
79 bool "Include xmon kernel debugger" 79 bool "Include xmon kernel debugger"
80 depends on DEBUGGER && !PPC_ISERIES 80 depends on DEBUGGER
81 help 81 help
82 Include in-kernel hooks for the xmon kernel monitor/debugger. 82 Include in-kernel hooks for the xmon kernel monitor/debugger.
83 Unless you are intending to debug the kernel, say N here. 83 Unless you are intending to debug the kernel, say N here.
@@ -98,6 +98,15 @@ config XMON_DEFAULT
98 xmon is normally disabled unless booted with 'xmon=on'. 98 xmon is normally disabled unless booted with 'xmon=on'.
99 Use 'xmon=off' to disable xmon init during runtime. 99 Use 'xmon=off' to disable xmon init during runtime.
100 100
101config XMON_DISASSEMBLY
102 bool "Include disassembly support in xmon"
103 depends on XMON
104 default y
105 help
106 Include support for disassembling in xmon. You probably want
107 to say Y here, unless you're building for a memory-constrained
108 system.
109
101config IRQSTACKS 110config IRQSTACKS
102 bool "Use separate kernel stacks when processing interrupts" 111 bool "Use separate kernel stacks when processing interrupts"
103 depends on PPC64 112 depends on PPC64
@@ -116,7 +125,7 @@ config BDI_SWITCH
116 125
117config BOOTX_TEXT 126config BOOTX_TEXT
118 bool "Support for early boot text console (BootX or OpenFirmware only)" 127 bool "Support for early boot text console (BootX or OpenFirmware only)"
119 depends PPC_OF && !PPC_ISERIES 128 depends PPC_OF
120 help 129 help
121 Say Y here to see progress messages from the boot firmware in text 130 Say Y here to see progress messages from the boot firmware in text
122 mode. Requires either BootX or Open Firmware. 131 mode. Requires either BootX or Open Firmware.
diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore
index 45c9ad23526e..0734b2fc1d95 100644
--- a/arch/powerpc/boot/.gitignore
+++ b/arch/powerpc/boot/.gitignore
@@ -1,19 +1,32 @@
1addnote 1addnote
2empty.c
3hack-coff
2infblock.c 4infblock.c
3infblock.h 5infblock.h
4infcodes.c 6infcodes.c
5infcodes.h 7infcodes.h
6inffast.c 8inffast.c
7inffast.h 9inffast.h
10inffixed.h
8inflate.c 11inflate.c
12inflate.h
9inftrees.c 13inftrees.c
10inftrees.h 14inftrees.h
11infutil.c 15infutil.c
12infutil.h 16infutil.h
13kernel-vmlinux.strip.c 17kernel-vmlinux.strip.c
14kernel-vmlinux.strip.gz 18kernel-vmlinux.strip.gz
19mktree
15uImage 20uImage
16zImage 21zImage
22zImage.chrp
23zImage.coff
24zImage.coff.lds
25zImage.lds
26zImage.miboot
27zImage.pmac
28zImage.pseries
29zImage.sandpoint
17zImage.vmode 30zImage.vmode
18zconf.h 31zconf.h
19zlib.h 32zlib.h
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 4b2be611f77f..343dbcfdf08a 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -40,7 +40,8 @@ zliblinuxheader := zlib.h zconf.h zutil.h
40$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \ 40$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \
41 $(addprefix $(obj)/,$(zlibheader)) 41 $(addprefix $(obj)/,$(zlibheader))
42 42
43src-wlib := string.S stdio.c main.c div64.S $(zlib) 43src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
44 ns16550.c serial.c simple_alloc.c div64.S util.S $(zlib)
44src-plat := of.c 45src-plat := of.c
45src-boot := crt0.S $(src-wlib) $(src-plat) empty.c 46src-boot := crt0.S $(src-wlib) $(src-plat) empty.c
46 47
@@ -74,7 +75,7 @@ $(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S
74 @cp $< $@ 75 @cp $< $@
75 76
76clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \ 77clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \
77 $(obj)/empty.c 78 empty.c zImage zImage.coff.lds zImage.lds zImage.sandpoint
78 79
79quiet_cmd_bootcc = BOOTCC $@ 80quiet_cmd_bootcc = BOOTCC $@
80 cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $< 81 cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $<
@@ -93,13 +94,13 @@ $(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S
93$(obj)/wrapper.a: $(obj-wlib) 94$(obj)/wrapper.a: $(obj-wlib)
94 $(call cmd,bootar) 95 $(call cmd,bootar)
95 96
96hostprogs-y := addnote addRamDisk hack-coff 97hostprogs-y := addnote addRamDisk hack-coff mktree
97 98
98extra-y := $(obj)/crt0.o $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ 99extra-y := $(obj)/crt0.o $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
99 $(obj)/zImage.lds $(obj)/zImage.coff.lds 100 $(obj)/zImage.lds $(obj)/zImage.coff.lds
100 101
101wrapper :=$(srctree)/$(src)/wrapper 102wrapper :=$(srctree)/$(src)/wrapper
102wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff) 103wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree)
103 104
104############# 105#############
105# Bits for building various flavours of zImage 106# Bits for building various flavours of zImage
@@ -148,13 +149,18 @@ $(obj)/zImage.miboot: vmlinux $(wrapperbits)
148$(obj)/zImage.initrd.miboot: vmlinux $(wrapperbits) 149$(obj)/zImage.initrd.miboot: vmlinux $(wrapperbits)
149 $(call cmd,wrap_initrd,miboot) 150 $(call cmd,wrap_initrd,miboot)
150 151
152$(obj)/zImage.ps3: vmlinux
153 $(STRIP) -s -R .comment $< -o $@
154
151$(obj)/uImage: vmlinux $(wrapperbits) 155$(obj)/uImage: vmlinux $(wrapperbits)
152 $(call cmd,wrap,uboot) 156 $(call cmd,wrap,uboot)
153 157
154image-$(CONFIG_PPC_PSERIES) += zImage.pseries 158image-$(CONFIG_PPC_PSERIES) += zImage.pseries
155image-$(CONFIG_PPC_MAPLE) += zImage.pseries 159image-$(CONFIG_PPC_MAPLE) += zImage.pseries
156image-$(CONFIG_PPC_IBM_CELL_BLADE) += zImage.pseries 160image-$(CONFIG_PPC_IBM_CELL_BLADE) += zImage.pseries
161image-$(CONFIG_PPC_PS3) += zImage.ps3
157image-$(CONFIG_PPC_CHRP) += zImage.chrp 162image-$(CONFIG_PPC_CHRP) += zImage.chrp
163image-$(CONFIG_PPC_EFIKA) += zImage.chrp
158image-$(CONFIG_PPC_PMAC) += zImage.pmac 164image-$(CONFIG_PPC_PMAC) += zImage.pmac
159image-$(CONFIG_DEFAULT_UIMAGE) += uImage 165image-$(CONFIG_DEFAULT_UIMAGE) += uImage
160 166
@@ -176,3 +182,4 @@ install: $(CONFIGURE) $(image-y)
176 182
177clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip.gz) 183clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip.gz)
178clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.bin.gz) 184clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.bin.gz)
185clean-files += $(image-)
diff --git a/arch/powerpc/boot/dts/kuroboxHG.dts b/arch/powerpc/boot/dts/kuroboxHG.dts
new file mode 100644
index 000000000000..d06b0b018899
--- /dev/null
+++ b/arch/powerpc/boot/dts/kuroboxHG.dts
@@ -0,0 +1,148 @@
1/*
2 * Device Tree Souce for Buffalo KuroboxHG
3 *
4 * Choose CONFIG_LINKSTATION to build a kernel for KuroboxHG, or use
5 * the default configuration linkstation_defconfig.
6 *
7 * Based on sandpoint.dts
8 *
9 * 2006 (c) G. Liakhovetski <g.liakhovetski@gmx.de>
10 *
11 * This file is licensed under
12 * the terms of the GNU General Public License version 2. This program
13 * is licensed "as is" without any warranty of any kind, whether express
14 * or implied.
15
16XXXX add flash parts, rtc, ??
17
18build with: "dtc -f -I dts -O dtb -o kuroboxHG.dtb -V 16 kuroboxHG.dts"
19
20
21 */
22
23/ {
24 linux,phandle = <1000>;
25 model = "KuroboxHG";
26 compatible = "linkstation";
27 #address-cells = <1>;
28 #size-cells = <1>;
29
30 cpus {
31 linux,phandle = <2000>;
32 #cpus = <1>;
33 #address-cells = <1>;
34 #size-cells = <0>;
35
36 PowerPC,603e { /* Really 8241 */
37 linux,phandle = <2100>;
38 linux,boot-cpu;
39 device_type = "cpu";
40 reg = <0>;
41 clock-frequency = <fdad680>; /* Fixed by bootwrapper */
42 timebase-frequency = <1F04000>; /* Fixed by bootwrapper */
43 bus-frequency = <0>; /* From bootloader */
44 /* Following required by dtc but not used */
45 i-cache-line-size = <0>;
46 d-cache-line-size = <0>;
47 i-cache-size = <4000>;
48 d-cache-size = <4000>;
49 };
50 };
51
52 memory {
53 linux,phandle = <3000>;
54 device_type = "memory";
55 reg = <00000000 08000000>;
56 };
57
58 soc10x { /* AFAICT need to make soc for 8245's uarts to be defined */
59 linux,phandle = <4000>;
60 #address-cells = <1>;
61 #size-cells = <1>;
62 #interrupt-cells = <2>;
63 device_type = "soc";
64 compatible = "mpc10x";
65 store-gathering = <0>; /* 0 == off, !0 == on */
66 reg = <80000000 00100000>;
67 ranges = <80000000 80000000 70000000 /* pci mem space */
68 fc000000 fc000000 00100000 /* EUMB */
69 fe000000 fe000000 00c00000 /* pci i/o space */
70 fec00000 fec00000 00300000 /* pci cfg regs */
71 fef00000 fef00000 00100000>; /* pci iack */
72
73 i2c@80003000 {
74 linux,phandle = <4300>;
75 device_type = "i2c";
76 compatible = "fsl-i2c";
77 reg = <80003000 1000>;
78 interrupts = <5 2>;
79 interrupt-parent = <4400>;
80 };
81
82 serial@80004500 {
83 linux,phandle = <4511>;
84 device_type = "serial";
85 compatible = "ns16550";
86 reg = <80004500 8>;
87 clock-frequency = <7c044a8>;
88 current-speed = <2580>;
89 interrupts = <9 2>;
90 interrupt-parent = <4400>;
91 };
92
93 serial@80004600 {
94 linux,phandle = <4512>;
95 device_type = "serial";
96 compatible = "ns16550";
97 reg = <80004600 8>;
98 clock-frequency = <7c044a8>;
99 current-speed = <e100>;
100 interrupts = <a 0>;
101 interrupt-parent = <4400>;
102 };
103
104 pic@80040000 {
105 linux,phandle = <4400>;
106 #interrupt-cells = <2>;
107 #address-cells = <0>;
108 device_type = "open-pic";
109 compatible = "chrp,open-pic";
110 interrupt-controller;
111 reg = <80040000 40000>;
112 built-in;
113 };
114
115 pci@fec00000 {
116 linux,phandle = <4500>;
117 #address-cells = <3>;
118 #size-cells = <2>;
119 #interrupt-cells = <1>;
120 device_type = "pci";
121 compatible = "mpc10x-pci";
122 reg = <fec00000 400000>;
123 ranges = <01000000 0 0 fe000000 0 00c00000
124 02000000 0 80000000 80000000 0 70000000>;
125 bus-range = <0 ff>;
126 clock-frequency = <7f28155>;
127 interrupt-parent = <4400>;
128 interrupt-map-mask = <f800 0 0 7>;
129 interrupt-map = <
130 /* IDSEL 0x11 - IRQ0 ETH */
131 5800 0 0 1 4400 0 1
132 5800 0 0 2 4400 1 1
133 5800 0 0 3 4400 2 1
134 5800 0 0 4 4400 3 1
135 /* IDSEL 0x12 - IRQ1 IDE0 */
136 6000 0 0 1 4400 1 1
137 6000 0 0 2 4400 2 1
138 6000 0 0 3 4400 3 1
139 6000 0 0 4 4400 0 1
140 /* IDSEL 0x14 - IRQ3 USB2.0 */
141 7000 0 0 1 4400 3 1
142 7000 0 0 2 4400 3 1
143 7000 0 0 3 4400 3 1
144 7000 0 0 4 4400 3 1
145 >;
146 };
147 };
148};
diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts
new file mode 100644
index 000000000000..8bc0d259796d
--- /dev/null
+++ b/arch/powerpc/boot/dts/lite5200.dts
@@ -0,0 +1,313 @@
1/*
2 * Lite5200 board Device Tree Source
3 *
4 * Copyright 2006 Secret Lab Technologies Ltd.
5 * Grant Likely <grant.likely@secretlab.ca>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13/ {
14 model = "Lite5200";
15 compatible = "lite5200\0lite52xx\0mpc5200\0mpc52xx";
16 #address-cells = <1>;
17 #size-cells = <1>;
18
19 cpus {
20 #cpus = <1>;
21 #address-cells = <1>;
22 #size-cells = <0>;
23
24 PowerPC,5200@0 {
25 device_type = "cpu";
26 reg = <0>;
27 d-cache-line-size = <20>;
28 i-cache-line-size = <20>;
29 d-cache-size = <4000>; // L1, 16K
30 i-cache-size = <4000>; // L1, 16K
31 timebase-frequency = <0>; // from bootloader
32 bus-frequency = <0>; // from bootloader
33 clock-frequency = <0>; // from bootloader
34 32-bit;
35 };
36 };
37
38 memory {
39 device_type = "memory";
40 reg = <00000000 04000000>; // 64MB
41 };
42
43 soc5200@f0000000 {
44 #interrupt-cells = <3>;
45 device_type = "soc";
46 ranges = <0 f0000000 f0010000>;
47 reg = <f0000000 00010000>;
48 bus-frequency = <0>; // from bootloader
49
50 cdm@200 {
51 compatible = "mpc5200-cdm\0mpc52xx-cdm";
52 reg = <200 38>;
53 };
54
55 pic@500 {
56 // 5200 interrupts are encoded into two levels;
57 linux,phandle = <500>;
58 interrupt-controller;
59 #interrupt-cells = <3>;
60 device_type = "interrupt-controller";
61 compatible = "mpc5200-pic\0mpc52xx-pic";
62 reg = <500 80>;
63 built-in;
64 };
65
66 gpt@600 { // General Purpose Timer
67 compatible = "mpc5200-gpt\0mpc52xx-gpt";
68 device_type = "gpt";
69 reg = <600 10>;
70 interrupts = <1 9 0>;
71 interrupt-parent = <500>;
72 };
73
74 gpt@610 { // General Purpose Timer
75 compatible = "mpc5200-gpt\0mpc52xx-gpt";
76 device_type = "gpt";
77 reg = <610 10>;
78 interrupts = <1 a 0>;
79 interrupt-parent = <500>;
80 };
81
82 gpt@620 { // General Purpose Timer
83 compatible = "mpc5200-gpt\0mpc52xx-gpt";
84 device_type = "gpt";
85 reg = <620 10>;
86 interrupts = <1 b 0>;
87 interrupt-parent = <500>;
88 };
89
90 gpt@630 { // General Purpose Timer
91 compatible = "mpc5200-gpt\0mpc52xx-gpt";
92 device_type = "gpt";
93 reg = <630 10>;
94 interrupts = <1 c 0>;
95 interrupt-parent = <500>;
96 };
97
98 gpt@640 { // General Purpose Timer
99 compatible = "mpc5200-gpt\0mpc52xx-gpt";
100 device_type = "gpt";
101 reg = <640 10>;
102 interrupts = <1 d 0>;
103 interrupt-parent = <500>;
104 };
105
106 gpt@650 { // General Purpose Timer
107 compatible = "mpc5200-gpt\0mpc52xx-gpt";
108 device_type = "gpt";
109 reg = <650 10>;
110 interrupts = <1 e 0>;
111 interrupt-parent = <500>;
112 };
113
114 gpt@660 { // General Purpose Timer
115 compatible = "mpc5200-gpt\0mpc52xx-gpt";
116 device_type = "gpt";
117 reg = <660 10>;
118 interrupts = <1 f 0>;
119 interrupt-parent = <500>;
120 };
121
122 gpt@670 { // General Purpose Timer
123 compatible = "mpc5200-gpt\0mpc52xx-gpt";
124 device_type = "gpt";
125 reg = <670 10>;
126 interrupts = <1 10 0>;
127 interrupt-parent = <500>;
128 };
129
130 rtc@800 { // Real time clock
131 compatible = "mpc5200-rtc\0mpc52xx-rtc";
132 device_type = "rtc";
133 reg = <800 100>;
134 interrupts = <1 5 0 1 6 0>;
135 interrupt-parent = <500>;
136 };
137
138 mscan@900 {
139 device_type = "mscan";
140 compatible = "mpc5200-mscan\0mpc52xx-mscan";
141 interrupts = <2 11 0>;
142 interrupt-parent = <500>;
143 reg = <900 80>;
144 };
145
146 mscan@980 {
147 device_type = "mscan";
148 compatible = "mpc5200-mscan\0mpc52xx-mscan";
149 interrupts = <1 12 0>;
150 interrupt-parent = <500>;
151 reg = <980 80>;
152 };
153
154 gpio@b00 {
155 compatible = "mpc5200-gpio\0mpc52xx-gpio";
156 reg = <b00 40>;
157 interrupts = <1 7 0>;
158 interrupt-parent = <500>;
159 };
160
161 gpio-wkup@b00 {
162 compatible = "mpc5200-gpio-wkup\0mpc52xx-gpio-wkup";
163 reg = <c00 40>;
164 interrupts = <1 8 0 0 3 0>;
165 interrupt-parent = <500>;
166 };
167
168 pci@0d00 {
169 #interrupt-cells = <1>;
170 #size-cells = <2>;
171 #address-cells = <3>;
172 device_type = "pci";
173 compatible = "mpc5200-pci\0mpc52xx-pci";
174 reg = <d00 100>;
175 interrupt-map-mask = <f800 0 0 7>;
176 interrupt-map = <c000 0 0 1 500 0 0 3
177 c000 0 0 2 500 0 0 3
178 c000 0 0 3 500 0 0 3
179 c000 0 0 4 500 0 0 3>;
180 clock-frequency = <0>; // From boot loader
181 interrupts = <2 8 0 2 9 0 2 a 0>;
182 interrupt-parent = <500>;
183 bus-range = <0 0>;
184 ranges = <42000000 0 80000000 80000000 0 20000000
185 02000000 0 a0000000 a0000000 0 10000000
186 01000000 0 00000000 b0000000 0 01000000>;
187 };
188
189 spi@f00 {
190 device_type = "spi";
191 compatible = "mpc5200-spi\0mpc52xx-spi";
192 reg = <f00 20>;
193 interrupts = <2 d 0 2 e 0>;
194 interrupt-parent = <500>;
195 };
196
197 usb@1000 {
198 device_type = "usb-ohci-be";
199 compatible = "mpc5200-ohci\0mpc52xx-ohci\0ohci-be";
200 reg = <1000 ff>;
201 interrupts = <2 6 0>;
202 interrupt-parent = <500>;
203 };
204
205 bestcomm@1200 {
206 device_type = "dma-controller";
207 compatible = "mpc5200-bestcomm\0mpc52xx-bestcomm";
208 reg = <1200 80>;
209 interrupts = <3 0 0 3 1 0 3 2 0 3 3 0
210 3 4 0 3 5 0 3 6 0 3 7 0
211 3 8 0 3 9 0 3 a 0 3 b 0
212 3 c 0 3 d 0 3 e 0 3 f 0>;
213 interrupt-parent = <500>;
214 };
215
216 xlb@1f00 {
217 compatible = "mpc5200-xlb\0mpc52xx-xlb";
218 reg = <1f00 100>;
219 };
220
221 serial@2000 { // PSC1
222 device_type = "serial";
223 compatible = "mpc5200-psc-uart\0mpc52xx-psc-uart";
224 port-number = <0>; // Logical port assignment
225 reg = <2000 100>;
226 interrupts = <2 1 0>;
227 interrupt-parent = <500>;
228 };
229
230 // PSC2 in spi mode example
231 spi@2200 { // PSC2
232 device_type = "spi";
233 compatible = "mpc5200-psc-spi\0mpc52xx-psc-spi";
234 reg = <2200 100>;
235 interrupts = <2 2 0>;
236 interrupt-parent = <500>;
237 };
238
239 // PSC3 in CODEC mode example
240 i2s@2400 { // PSC3
241 device_type = "i2s";
242 compatible = "mpc5200-psc-i2s\0mpc52xx-psc-i2s";
243 reg = <2400 100>;
244 interrupts = <2 3 0>;
245 interrupt-parent = <500>;
246 };
247
248 // PSC4 unconfigured
249 //serial@2600 { // PSC4
250 // device_type = "serial";
251 // compatible = "mpc5200-psc-uart\0mpc52xx-psc-uart";
252 // reg = <2600 100>;
253 // interrupts = <2 b 0>;
254 // interrupt-parent = <500>;
255 //};
256
257 // PSC5 unconfigured
258 //serial@2800 { // PSC5
259 // device_type = "serial";
260 // compatible = "mpc5200-psc-uart\0mpc52xx-psc-uart";
261 // reg = <2800 100>;
262 // interrupts = <2 c 0>;
263 // interrupt-parent = <500>;
264 //};
265
266 // PSC6 in AC97 mode example
267 ac97@2c00 { // PSC6
268 device_type = "ac97";
269 compatible = "mpc5200-psc-ac97\0mpc52xx-psc-ac97";
270 reg = <2c00 100>;
271 interrupts = <2 4 0>;
272 interrupt-parent = <500>;
273 };
274
275 ethernet@3000 {
276 device_type = "network";
277 compatible = "mpc5200-fec\0mpc52xx-fec";
278 reg = <3000 800>;
279 mac-address = [ 02 03 04 05 06 07 ]; // Bad!
280 interrupts = <2 5 0>;
281 interrupt-parent = <500>;
282 };
283
284 ata@3a00 {
285 device_type = "ata";
286 compatible = "mpc5200-ata\0mpc52xx-ata";
287 reg = <3a00 100>;
288 interrupts = <2 7 0>;
289 interrupt-parent = <500>;
290 };
291
292 i2c@3d00 {
293 device_type = "i2c";
294 compatible = "mpc5200-i2c\0mpc52xx-i2c";
295 reg = <3d00 40>;
296 interrupts = <2 f 0>;
297 interrupt-parent = <500>;
298 };
299
300 i2c@3d40 {
301 device_type = "i2c";
302 compatible = "mpc5200-i2c\0mpc52xx-i2c";
303 reg = <3d40 40>;
304 interrupts = <2 10 0>;
305 interrupt-parent = <500>;
306 };
307 sram@8000 {
308 device_type = "sram";
309 compatible = "mpc5200-sram\0mpc52xx-sram\0sram";
310 reg = <8000 4000>;
311 };
312 };
313};
diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts
new file mode 100644
index 000000000000..81cb76418a78
--- /dev/null
+++ b/arch/powerpc/boot/dts/lite5200b.dts
@@ -0,0 +1,318 @@
1/*
2 * Lite5200B board Device Tree Source
3 *
4 * Copyright 2006 Secret Lab Technologies Ltd.
5 * Grant Likely <grant.likely@secretlab.ca>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13/ {
14 model = "Lite5200b";
15 compatible = "lite5200b\0lite52xx\0mpc5200b\0mpc52xx";
16 #address-cells = <1>;
17 #size-cells = <1>;
18
19 cpus {
20 #cpus = <1>;
21 #address-cells = <1>;
22 #size-cells = <0>;
23
24 PowerPC,5200@0 {
25 device_type = "cpu";
26 reg = <0>;
27 d-cache-line-size = <20>;
28 i-cache-line-size = <20>;
29 d-cache-size = <4000>; // L1, 16K
30 i-cache-size = <4000>; // L1, 16K
31 timebase-frequency = <0>; // from bootloader
32 bus-frequency = <0>; // from bootloader
33 clock-frequency = <0>; // from bootloader
34 32-bit;
35 };
36 };
37
38 memory {
39 device_type = "memory";
40 reg = <00000000 10000000>; // 256MB
41 };
42
43 soc5200@f0000000 {
44 #interrupt-cells = <3>;
45 device_type = "soc";
46 ranges = <0 f0000000 f0010000>;
47 reg = <f0000000 00010000>;
48 bus-frequency = <0>; // from bootloader
49
50 cdm@200 {
51 compatible = "mpc5200b-cdm\0mpc52xx-cdm";
52 reg = <200 38>;
53 };
54
55 pic@500 {
56 // 5200 interrupts are encoded into two levels;
57 linux,phandle = <500>;
58 interrupt-controller;
59 #interrupt-cells = <3>;
60 device_type = "interrupt-controller";
61 compatible = "mpc5200b-pic\0mpc52xx-pic";
62 reg = <500 80>;
63 built-in;
64 };
65
66 gpt@600 { // General Purpose Timer
67 compatible = "mpc5200b-gpt\0mpc52xx-gpt";
68 device_type = "gpt";
69 reg = <600 10>;
70 interrupts = <1 9 0>;
71 interrupt-parent = <500>;
72 };
73
74 gpt@610 { // General Purpose Timer
75 compatible = "mpc5200b-gpt\0mpc52xx-gpt";
76 device_type = "gpt";
77 reg = <610 10>;
78 interrupts = <1 a 0>;
79 interrupt-parent = <500>;
80 };
81
82 gpt@620 { // General Purpose Timer
83 compatible = "mpc5200b-gpt\0mpc52xx-gpt";
84 device_type = "gpt";
85 reg = <620 10>;
86 interrupts = <1 b 0>;
87 interrupt-parent = <500>;
88 };
89
90 gpt@630 { // General Purpose Timer
91 compatible = "mpc5200b-gpt\0mpc52xx-gpt";
92 device_type = "gpt";
93 reg = <630 10>;
94 interrupts = <1 c 0>;
95 interrupt-parent = <500>;
96 };
97
98 gpt@640 { // General Purpose Timer
99 compatible = "mpc5200b-gpt\0mpc52xx-gpt";
100 device_type = "gpt";
101 reg = <640 10>;
102 interrupts = <1 d 0>;
103 interrupt-parent = <500>;
104 };
105
106 gpt@650 { // General Purpose Timer
107 compatible = "mpc5200b-gpt\0mpc52xx-gpt";
108 device_type = "gpt";
109 reg = <650 10>;
110 interrupts = <1 e 0>;
111 interrupt-parent = <500>;
112 };
113
114 gpt@660 { // General Purpose Timer
115 compatible = "mpc5200b-gpt\0mpc52xx-gpt";
116 device_type = "gpt";
117 reg = <660 10>;
118 interrupts = <1 f 0>;
119 interrupt-parent = <500>;
120 };
121
122 gpt@670 { // General Purpose Timer
123 compatible = "mpc5200b-gpt\0mpc52xx-gpt";
124 device_type = "gpt";
125 reg = <670 10>;
126 interrupts = <1 10 0>;
127 interrupt-parent = <500>;
128 };
129
130 rtc@800 { // Real time clock
131 compatible = "mpc5200b-rtc\0mpc52xx-rtc";
132 device_type = "rtc";
133 reg = <800 100>;
134 interrupts = <1 5 0 1 6 0>;
135 interrupt-parent = <500>;
136 };
137
138 mscan@900 {
139 device_type = "mscan";
140 compatible = "mpc5200b-mscan\0mpc52xx-mscan";
141 interrupts = <2 11 0>;
142 interrupt-parent = <500>;
143 reg = <900 80>;
144 };
145
146 mscan@980 {
147 device_type = "mscan";
148 compatible = "mpc5200b-mscan\0mpc52xx-mscan";
149 interrupts = <1 12 0>;
150 interrupt-parent = <500>;
151 reg = <980 80>;
152 };
153
154 gpio@b00 {
155 compatible = "mpc5200b-gpio\0mpc52xx-gpio";
156 reg = <b00 40>;
157 interrupts = <1 7 0>;
158 interrupt-parent = <500>;
159 };
160
161 gpio-wkup@b00 {
162 compatible = "mpc5200b-gpio-wkup\0mpc52xx-gpio-wkup";
163 reg = <c00 40>;
164 interrupts = <1 8 0 0 3 0>;
165 interrupt-parent = <500>;
166 };
167
168 pci@0d00 {
169 #interrupt-cells = <1>;
170 #size-cells = <2>;
171 #address-cells = <3>;
172 device_type = "pci";
173 compatible = "mpc5200b-pci\0mpc52xx-pci";
174 reg = <d00 100>;
175 interrupt-map-mask = <f800 0 0 7>;
176 interrupt-map = <c000 0 0 1 500 0 0 3 // 1st slot
177 c000 0 0 2 500 1 1 3
178 c000 0 0 3 500 1 2 3
179 c000 0 0 4 500 1 3 3
180
181 c800 0 0 1 500 1 1 3 // 2nd slot
182 c800 0 0 2 500 1 2 3
183 c800 0 0 3 500 1 3 3
184 c800 0 0 4 500 0 0 3>;
185 clock-frequency = <0>; // From boot loader
186 interrupts = <2 8 0 2 9 0 2 a 0>;
187 interrupt-parent = <500>;
188 bus-range = <0 0>;
189 ranges = <42000000 0 80000000 80000000 0 20000000
190 02000000 0 a0000000 a0000000 0 10000000
191 01000000 0 00000000 b0000000 0 01000000>;
192 };
193
194 spi@f00 {
195 device_type = "spi";
196 compatible = "mpc5200b-spi\0mpc52xx-spi";
197 reg = <f00 20>;
198 interrupts = <2 d 0 2 e 0>;
199 interrupt-parent = <500>;
200 };
201
202 usb@1000 {
203 device_type = "usb-ohci-be";
204 compatible = "mpc5200b-ohci\0mpc52xx-ohci\0ohci-be";
205 reg = <1000 ff>;
206 interrupts = <2 6 0>;
207 interrupt-parent = <500>;
208 };
209
210 bestcomm@1200 {
211 device_type = "dma-controller";
212 compatible = "mpc5200b-bestcomm\0mpc52xx-bestcomm";
213 reg = <1200 80>;
214 interrupts = <3 0 0 3 1 0 3 2 0 3 3 0
215 3 4 0 3 5 0 3 6 0 3 7 0
216 3 8 0 3 9 0 3 a 0 3 b 0
217 3 c 0 3 d 0 3 e 0 3 f 0>;
218 interrupt-parent = <500>;
219 };
220
221 xlb@1f00 {
222 compatible = "mpc5200b-xlb\0mpc52xx-xlb";
223 reg = <1f00 100>;
224 };
225
226 serial@2000 { // PSC1
227 device_type = "serial";
228 compatible = "mpc5200b-psc-uart\0mpc52xx-psc-uart";
229 port-number = <0>; // Logical port assignment
230 reg = <2000 100>;
231 interrupts = <2 1 0>;
232 interrupt-parent = <500>;
233 };
234
235 // PSC2 in spi mode example
236 spi@2200 { // PSC2
237 device_type = "spi";
238 compatible = "mpc5200b-psc-spi\0mpc52xx-psc-spi";
239 reg = <2200 100>;
240 interrupts = <2 2 0>;
241 interrupt-parent = <500>;
242 };
243
244 // PSC3 in CODEC mode example
245 i2s@2400 { // PSC3
246 device_type = "i2s";
247 compatible = "mpc5200b-psc-i2s\0mpc52xx-psc-i2s";
248 reg = <2400 100>;
249 interrupts = <2 3 0>;
250 interrupt-parent = <500>;
251 };
252
253 // PSC4 unconfigured
254 //serial@2600 { // PSC4
255 // device_type = "serial";
256 // compatible = "mpc5200b-psc-uart\0mpc52xx-psc-uart";
257 // reg = <2600 100>;
258 // interrupts = <2 b 0>;
259 // interrupt-parent = <500>;
260 //};
261
262 // PSC5 unconfigured
263 //serial@2800 { // PSC5
264 // device_type = "serial";
265 // compatible = "mpc5200b-psc-uart\0mpc52xx-psc-uart";
266 // reg = <2800 100>;
267 // interrupts = <2 c 0>;
268 // interrupt-parent = <500>;
269 //};
270
271 // PSC6 in AC97 mode example
272 ac97@2c00 { // PSC6
273 device_type = "ac97";
274 compatible = "mpc5200b-psc-ac97\0mpc52xx-psc-ac97";
275 reg = <2c00 100>;
276 interrupts = <2 4 0>;
277 interrupt-parent = <500>;
278 };
279
280 ethernet@3000 {
281 device_type = "network";
282 compatible = "mpc5200b-fec\0mpc52xx-fec";
283 reg = <3000 800>;
284 mac-address = [ 02 03 04 05 06 07 ]; // Bad!
285 interrupts = <2 5 0>;
286 interrupt-parent = <500>;
287 };
288
289 ata@3a00 {
290 device_type = "ata";
291 compatible = "mpc5200b-ata\0mpc52xx-ata";
292 reg = <3a00 100>;
293 interrupts = <2 7 0>;
294 interrupt-parent = <500>;
295 };
296
297 i2c@3d00 {
298 device_type = "i2c";
299 compatible = "mpc5200b-i2c\0mpc52xx-i2c";
300 reg = <3d00 40>;
301 interrupts = <2 f 0>;
302 interrupt-parent = <500>;
303 };
304
305 i2c@3d40 {
306 device_type = "i2c";
307 compatible = "mpc5200b-i2c\0mpc52xx-i2c";
308 reg = <3d40 40>;
309 interrupts = <2 10 0>;
310 interrupt-parent = <500>;
311 };
312 sram@8000 {
313 device_type = "sram";
314 compatible = "mpc5200b-sram\0mpc52xx-sram\0sram";
315 reg = <8000 4000>;
316 };
317 };
318};
diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts
index d7b985e6bd2f..c4d9562cbaad 100644
--- a/arch/powerpc/boot/dts/mpc7448hpc2.dts
+++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts
@@ -161,29 +161,41 @@
161 interrupt-map = < 161 interrupt-map = <
162 162
163 /* IDSEL 0x11 */ 163 /* IDSEL 0x11 */
164 0800 0 0 1 7400 24 0 164 0800 0 0 1 1180 24 0
165 0800 0 0 2 7400 25 0 165 0800 0 0 2 1180 25 0
166 0800 0 0 3 7400 26 0 166 0800 0 0 3 1180 26 0
167 0800 0 0 4 7400 27 0 167 0800 0 0 4 1180 27 0
168 168
169 /* IDSEL 0x12 */ 169 /* IDSEL 0x12 */
170 1000 0 0 1 7400 25 0 170 1000 0 0 1 1180 25 0
171 1000 0 0 2 7400 26 0 171 1000 0 0 2 1180 26 0
172 1000 0 0 3 7400 27 0 172 1000 0 0 3 1180 27 0
173 1000 0 0 4 7400 24 0 173 1000 0 0 4 1180 24 0
174 174
175 /* IDSEL 0x13 */ 175 /* IDSEL 0x13 */
176 1800 0 0 1 7400 26 0 176 1800 0 0 1 1180 26 0
177 1800 0 0 2 7400 27 0 177 1800 0 0 2 1180 27 0
178 1800 0 0 3 7400 24 0 178 1800 0 0 3 1180 24 0
179 1800 0 0 4 7400 25 0 179 1800 0 0 4 1180 25 0
180 180
181 /* IDSEL 0x14 */ 181 /* IDSEL 0x14 */
182 2000 0 0 1 7400 27 0 182 2000 0 0 1 1180 27 0
183 2000 0 0 2 7400 24 0 183 2000 0 0 2 1180 24 0
184 2000 0 0 3 7400 25 0 184 2000 0 0 3 1180 25 0
185 2000 0 0 4 7400 26 0 185 2000 0 0 4 1180 26 0
186 >; 186 >;
187 router@1180 {
188 linux,phandle = <1180>;
189 clock-frequency = <0>;
190 interrupt-controller;
191 device_type = "pic-router";
192 #address-cells = <0>;
193 #interrupt-cells = <2>;
194 built-in;
195 big-endian;
196 interrupts = <17 2>;
197 interrupt-parent = <7400>;
198 };
187 }; 199 };
188 }; 200 };
189 201
diff --git a/arch/powerpc/boot/flatdevtree.c b/arch/powerpc/boot/flatdevtree.c
new file mode 100644
index 000000000000..c76c194715b2
--- /dev/null
+++ b/arch/powerpc/boot/flatdevtree.c
@@ -0,0 +1,880 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * Copyright Pantelis Antoniou 2006
17 * Copyright (C) IBM Corporation 2006
18 *
19 * Authors: Pantelis Antoniou <pantelis@embeddedalley.com>
20 * Hollis Blanchard <hollisb@us.ibm.com>
21 * Mark A. Greer <mgreer@mvista.com>
22 * Paul Mackerras <paulus@samba.org>
23 */
24
25#include <string.h>
26#include <stddef.h>
27#include "flatdevtree.h"
28#include "flatdevtree_env.h"
29
30#define _ALIGN(x, al) (((x) + (al) - 1) & ~((al) - 1))
31
32/* Routines for keeping node ptrs returned by ft_find_device current */
33/* First entry not used b/c it would return 0 and be taken as NULL/error */
34static void *ft_node_add(struct ft_cxt *cxt, char *node)
35{
36 unsigned int i;
37
38 for (i = 1; i < cxt->nodes_used; i++) /* already there? */
39 if (cxt->node_tbl[i] == node)
40 return (void *)i;
41
42 if (cxt->nodes_used < cxt->node_max) {
43 cxt->node_tbl[cxt->nodes_used] = node;
44 return (void *)cxt->nodes_used++;
45 }
46
47 return NULL;
48}
49
50static char *ft_node_ph2node(struct ft_cxt *cxt, const void *phandle)
51{
52 unsigned int i = (unsigned int)phandle;
53
54 if (i < cxt->nodes_used)
55 return cxt->node_tbl[i];
56 return NULL;
57}
58
59static void ft_node_update_before(struct ft_cxt *cxt, char *addr, int shift)
60{
61 unsigned int i;
62
63 if (shift == 0)
64 return;
65
66 for (i = 1; i < cxt->nodes_used; i++)
67 if (cxt->node_tbl[i] < addr)
68 cxt->node_tbl[i] += shift;
69}
70
71static void ft_node_update_after(struct ft_cxt *cxt, char *addr, int shift)
72{
73 unsigned int i;
74
75 if (shift == 0)
76 return;
77
78 for (i = 1; i < cxt->nodes_used; i++)
79 if (cxt->node_tbl[i] >= addr)
80 cxt->node_tbl[i] += shift;
81}
82
83/* Struct used to return info from ft_next() */
84struct ft_atom {
85 u32 tag;
86 const char *name;
87 void *data;
88 u32 size;
89};
90
91/* Set ptrs to current one's info; return addr of next one */
92static char *ft_next(struct ft_cxt *cxt, char *p, struct ft_atom *ret)
93{
94 u32 sz;
95
96 if (p >= cxt->rgn[FT_STRUCT].start + cxt->rgn[FT_STRUCT].size)
97 return NULL;
98
99 ret->tag = be32_to_cpu(*(u32 *) p);
100 p += 4;
101
102 switch (ret->tag) { /* Tag */
103 case OF_DT_BEGIN_NODE:
104 ret->name = p;
105 ret->data = (void *)(p - 4); /* start of node */
106 p += _ALIGN(strlen(p) + 1, 4);
107 break;
108 case OF_DT_PROP:
109 ret->size = sz = be32_to_cpu(*(u32 *) p);
110 ret->name = cxt->str_anchor + be32_to_cpu(*(u32 *) (p + 4));
111 ret->data = (void *)(p + 8);
112 p += 8 + _ALIGN(sz, 4);
113 break;
114 case OF_DT_END_NODE:
115 case OF_DT_NOP:
116 break;
117 case OF_DT_END:
118 default:
119 p = NULL;
120 break;
121 }
122
123 return p;
124}
125
126#define HDR_SIZE _ALIGN(sizeof(struct boot_param_header), 8)
127#define EXPAND_INCR 1024 /* alloc this much extra when expanding */
128
129/* See if the regions are in the standard order and non-overlapping */
130static int ft_ordered(struct ft_cxt *cxt)
131{
132 char *p = (char *)cxt->bph + HDR_SIZE;
133 enum ft_rgn_id r;
134
135 for (r = FT_RSVMAP; r <= FT_STRINGS; ++r) {
136 if (p > cxt->rgn[r].start)
137 return 0;
138 p = cxt->rgn[r].start + cxt->rgn[r].size;
139 }
140 return p <= (char *)cxt->bph + cxt->max_size;
141}
142
143/* Copy the tree to a newly-allocated region and put things in order */
144static int ft_reorder(struct ft_cxt *cxt, int nextra)
145{
146 unsigned long tot;
147 enum ft_rgn_id r;
148 char *p, *pend;
149 int stroff;
150
151 tot = HDR_SIZE + EXPAND_INCR;
152 for (r = FT_RSVMAP; r <= FT_STRINGS; ++r)
153 tot += cxt->rgn[r].size;
154 if (nextra > 0)
155 tot += nextra;
156 tot = _ALIGN(tot, 8);
157
158 if (!cxt->realloc)
159 return 0;
160 p = cxt->realloc(NULL, tot);
161 if (!p)
162 return 0;
163
164 memcpy(p, cxt->bph, sizeof(struct boot_param_header));
165 /* offsets get fixed up later */
166
167 cxt->bph = (struct boot_param_header *)p;
168 cxt->max_size = tot;
169 pend = p + tot;
170 p += HDR_SIZE;
171
172 memcpy(p, cxt->rgn[FT_RSVMAP].start, cxt->rgn[FT_RSVMAP].size);
173 cxt->rgn[FT_RSVMAP].start = p;
174 p += cxt->rgn[FT_RSVMAP].size;
175
176 memcpy(p, cxt->rgn[FT_STRUCT].start, cxt->rgn[FT_STRUCT].size);
177 ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start,
178 p - cxt->rgn[FT_STRUCT].start);
179 cxt->p += p - cxt->rgn[FT_STRUCT].start;
180 cxt->rgn[FT_STRUCT].start = p;
181
182 p = pend - cxt->rgn[FT_STRINGS].size;
183 memcpy(p, cxt->rgn[FT_STRINGS].start, cxt->rgn[FT_STRINGS].size);
184 stroff = cxt->str_anchor - cxt->rgn[FT_STRINGS].start;
185 cxt->rgn[FT_STRINGS].start = p;
186 cxt->str_anchor = p + stroff;
187
188 cxt->isordered = 1;
189 return 1;
190}
191
192static inline char *prev_end(struct ft_cxt *cxt, enum ft_rgn_id r)
193{
194 if (r > FT_RSVMAP)
195 return cxt->rgn[r - 1].start + cxt->rgn[r - 1].size;
196 return (char *)cxt->bph + HDR_SIZE;
197}
198
199static inline char *next_start(struct ft_cxt *cxt, enum ft_rgn_id r)
200{
201 if (r < FT_STRINGS)
202 return cxt->rgn[r + 1].start;
203 return (char *)cxt->bph + cxt->max_size;
204}
205
206/*
207 * See if we can expand region rgn by nextra bytes by using up
208 * free space after or before the region.
209 */
210static int ft_shuffle(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn,
211 int nextra)
212{
213 char *p = *pp;
214 char *rgn_start, *rgn_end;
215
216 rgn_start = cxt->rgn[rgn].start;
217 rgn_end = rgn_start + cxt->rgn[rgn].size;
218 if (nextra <= 0 || rgn_end + nextra <= next_start(cxt, rgn)) {
219 /* move following stuff */
220 if (p < rgn_end) {
221 if (nextra < 0)
222 memmove(p, p - nextra, rgn_end - p + nextra);
223 else
224 memmove(p + nextra, p, rgn_end - p);
225 if (rgn == FT_STRUCT)
226 ft_node_update_after(cxt, p, nextra);
227 }
228 cxt->rgn[rgn].size += nextra;
229 if (rgn == FT_STRINGS)
230 /* assumes strings only added at beginning */
231 cxt->str_anchor += nextra;
232 return 1;
233 }
234 if (prev_end(cxt, rgn) <= rgn_start - nextra) {
235 /* move preceding stuff */
236 if (p > rgn_start) {
237 memmove(rgn_start - nextra, rgn_start, p - rgn_start);
238 if (rgn == FT_STRUCT)
239 ft_node_update_before(cxt, p, -nextra);
240 }
241 *p -= nextra;
242 cxt->rgn[rgn].start -= nextra;
243 cxt->rgn[rgn].size += nextra;
244 return 1;
245 }
246 return 0;
247}
248
249static int ft_make_space(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn,
250 int nextra)
251{
252 unsigned long size, ssize, tot;
253 char *str, *next;
254 enum ft_rgn_id r;
255
256 if (!cxt->isordered && !ft_reorder(cxt, nextra))
257 return 0;
258 if (ft_shuffle(cxt, pp, rgn, nextra))
259 return 1;
260
261 /* See if there is space after the strings section */
262 ssize = cxt->rgn[FT_STRINGS].size;
263 if (cxt->rgn[FT_STRINGS].start + ssize
264 < (char *)cxt->bph + cxt->max_size) {
265 /* move strings up as far as possible */
266 str = (char *)cxt->bph + cxt->max_size - ssize;
267 cxt->str_anchor += str - cxt->rgn[FT_STRINGS].start;
268 memmove(str, cxt->rgn[FT_STRINGS].start, ssize);
269 cxt->rgn[FT_STRINGS].start = str;
270 /* enough space now? */
271 if (rgn >= FT_STRUCT && ft_shuffle(cxt, pp, rgn, nextra))
272 return 1;
273 }
274
275 /* how much total free space is there following this region? */
276 tot = 0;
277 for (r = rgn; r < FT_STRINGS; ++r) {
278 char *r_end = cxt->rgn[r].start + cxt->rgn[r].size;
279 tot += next_start(cxt, rgn) - r_end;
280 }
281
282 /* cast is to shut gcc up; we know nextra >= 0 */
283 if (tot < (unsigned int)nextra) {
284 /* have to reallocate */
285 char *newp, *new_start;
286 int shift;
287
288 if (!cxt->realloc)
289 return 0;
290 size = _ALIGN(cxt->max_size + (nextra - tot) + EXPAND_INCR, 8);
291 newp = cxt->realloc(cxt->bph, size);
292 if (!newp)
293 return 0;
294 cxt->max_size = size;
295 shift = newp - (char *)cxt->bph;
296
297 if (shift) { /* realloc can return same addr */
298 cxt->bph = (struct boot_param_header *)newp;
299 ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start,
300 shift);
301 for (r = FT_RSVMAP; r <= FT_STRINGS; ++r) {
302 new_start = cxt->rgn[r].start + shift;
303 cxt->rgn[r].start = new_start;
304 }
305 *pp += shift;
306 cxt->str_anchor += shift;
307 }
308
309 /* move strings up to the end */
310 str = newp + size - ssize;
311 cxt->str_anchor += str - cxt->rgn[FT_STRINGS].start;
312 memmove(str, cxt->rgn[FT_STRINGS].start, ssize);
313 cxt->rgn[FT_STRINGS].start = str;
314
315 if (ft_shuffle(cxt, pp, rgn, nextra))
316 return 1;
317 }
318
319 /* must be FT_RSVMAP and we need to move FT_STRUCT up */
320 if (rgn == FT_RSVMAP) {
321 next = cxt->rgn[FT_RSVMAP].start + cxt->rgn[FT_RSVMAP].size
322 + nextra;
323 ssize = cxt->rgn[FT_STRUCT].size;
324 if (next + ssize >= cxt->rgn[FT_STRINGS].start)
325 return 0; /* "can't happen" */
326 memmove(next, cxt->rgn[FT_STRUCT].start, ssize);
327 ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start, nextra);
328 cxt->rgn[FT_STRUCT].start = next;
329
330 if (ft_shuffle(cxt, pp, rgn, nextra))
331 return 1;
332 }
333
334 return 0; /* "can't happen" */
335}
336
337static void ft_put_word(struct ft_cxt *cxt, u32 v)
338{
339 *(u32 *) cxt->p = cpu_to_be32(v);
340 cxt->p += 4;
341}
342
343static void ft_put_bin(struct ft_cxt *cxt, const void *data, unsigned int sz)
344{
345 unsigned long sza = _ALIGN(sz, 4);
346
347 /* zero out the alignment gap if necessary */
348 if (sz < sza)
349 *(u32 *) (cxt->p + sza - 4) = 0;
350
351 /* copy in the data */
352 memcpy(cxt->p, data, sz);
353
354 cxt->p += sza;
355}
356
357int ft_begin_node(struct ft_cxt *cxt, const char *name)
358{
359 unsigned long nlen = strlen(name) + 1;
360 unsigned long len = 8 + _ALIGN(nlen, 4);
361
362 if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len))
363 return -1;
364 ft_put_word(cxt, OF_DT_BEGIN_NODE);
365 ft_put_bin(cxt, name, strlen(name) + 1);
366 return 0;
367}
368
369void ft_end_node(struct ft_cxt *cxt)
370{
371 ft_put_word(cxt, OF_DT_END_NODE);
372}
373
374void ft_nop(struct ft_cxt *cxt)
375{
376 if (ft_make_space(cxt, &cxt->p, FT_STRUCT, 4))
377 ft_put_word(cxt, OF_DT_NOP);
378}
379
380#define NO_STRING 0x7fffffff
381
382static int lookup_string(struct ft_cxt *cxt, const char *name)
383{
384 char *p, *end;
385
386 p = cxt->rgn[FT_STRINGS].start;
387 end = p + cxt->rgn[FT_STRINGS].size;
388 while (p < end) {
389 if (strcmp(p, (char *)name) == 0)
390 return p - cxt->str_anchor;
391 p += strlen(p) + 1;
392 }
393
394 return NO_STRING;
395}
396
397/* lookup string and insert if not found */
398static int map_string(struct ft_cxt *cxt, const char *name)
399{
400 int off;
401 char *p;
402
403 off = lookup_string(cxt, name);
404 if (off != NO_STRING)
405 return off;
406 p = cxt->rgn[FT_STRINGS].start;
407 if (!ft_make_space(cxt, &p, FT_STRINGS, strlen(name) + 1))
408 return NO_STRING;
409 strcpy(p, name);
410 return p - cxt->str_anchor;
411}
412
413int ft_prop(struct ft_cxt *cxt, const char *name, const void *data,
414 unsigned int sz)
415{
416 int off, len;
417
418 off = lookup_string(cxt, name);
419 if (off == NO_STRING)
420 return -1;
421
422 len = 12 + _ALIGN(sz, 4);
423 if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len))
424 return -1;
425
426 ft_put_word(cxt, OF_DT_PROP);
427 ft_put_word(cxt, sz);
428 ft_put_word(cxt, off);
429 ft_put_bin(cxt, data, sz);
430 return 0;
431}
432
433int ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str)
434{
435 return ft_prop(cxt, name, str, strlen(str) + 1);
436}
437
438int ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val)
439{
440 u32 v = cpu_to_be32((u32) val);
441
442 return ft_prop(cxt, name, &v, 4);
443}
444
445/* Calculate the size of the reserved map */
446static unsigned long rsvmap_size(struct ft_cxt *cxt)
447{
448 struct ft_reserve *res;
449
450 res = (struct ft_reserve *)cxt->rgn[FT_RSVMAP].start;
451 while (res->start || res->len)
452 ++res;
453 return (char *)(res + 1) - cxt->rgn[FT_RSVMAP].start;
454}
455
456/* Calculate the size of the struct region by stepping through it */
457static unsigned long struct_size(struct ft_cxt *cxt)
458{
459 char *p = cxt->rgn[FT_STRUCT].start;
460 char *next;
461 struct ft_atom atom;
462
463 /* make check in ft_next happy */
464 if (cxt->rgn[FT_STRUCT].size == 0)
465 cxt->rgn[FT_STRUCT].size = 0xfffffffful - (unsigned long)p;
466
467 while ((next = ft_next(cxt, p, &atom)) != NULL)
468 p = next;
469 return p + 4 - cxt->rgn[FT_STRUCT].start;
470}
471
472/* add `adj' on to all string offset values in the struct area */
473static void adjust_string_offsets(struct ft_cxt *cxt, int adj)
474{
475 char *p = cxt->rgn[FT_STRUCT].start;
476 char *next;
477 struct ft_atom atom;
478 int off;
479
480 while ((next = ft_next(cxt, p, &atom)) != NULL) {
481 if (atom.tag == OF_DT_PROP) {
482 off = be32_to_cpu(*(u32 *) (p + 8));
483 *(u32 *) (p + 8) = cpu_to_be32(off + adj);
484 }
485 p = next;
486 }
487}
488
489/* start construction of the flat OF tree from scratch */
490void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size,
491 void *(*realloc_fn) (void *, unsigned long))
492{
493 struct boot_param_header *bph = blob;
494 char *p;
495 struct ft_reserve *pres;
496
497 /* clear the cxt */
498 memset(cxt, 0, sizeof(*cxt));
499
500 cxt->bph = bph;
501 cxt->max_size = max_size;
502 cxt->realloc = realloc_fn;
503 cxt->isordered = 1;
504
505 /* zero everything in the header area */
506 memset(bph, 0, sizeof(*bph));
507
508 bph->magic = cpu_to_be32(OF_DT_HEADER);
509 bph->version = cpu_to_be32(0x10);
510 bph->last_comp_version = cpu_to_be32(0x10);
511
512 /* start pointers */
513 cxt->rgn[FT_RSVMAP].start = p = blob + HDR_SIZE;
514 cxt->rgn[FT_RSVMAP].size = sizeof(struct ft_reserve);
515 pres = (struct ft_reserve *)p;
516 cxt->rgn[FT_STRUCT].start = p += sizeof(struct ft_reserve);
517 cxt->rgn[FT_STRUCT].size = 4;
518 cxt->rgn[FT_STRINGS].start = blob + max_size;
519 cxt->rgn[FT_STRINGS].size = 0;
520
521 /* init rsvmap and struct */
522 pres->start = 0;
523 pres->len = 0;
524 *(u32 *) p = cpu_to_be32(OF_DT_END);
525
526 cxt->str_anchor = blob;
527}
528
529/* open up an existing blob to be examined or modified */
530int ft_open(struct ft_cxt *cxt, void *blob, unsigned int max_size,
531 unsigned int max_find_device,
532 void *(*realloc_fn) (void *, unsigned long))
533{
534 struct boot_param_header *bph = blob;
535
536 /* can't cope with version < 16 */
537 if (be32_to_cpu(bph->version) < 16)
538 return -1;
539
540 /* clear the cxt */
541 memset(cxt, 0, sizeof(*cxt));
542
543 /* alloc node_tbl to track node ptrs returned by ft_find_device */
544 ++max_find_device;
545 cxt->node_tbl = realloc_fn(NULL, max_find_device * sizeof(char *));
546 if (!cxt->node_tbl)
547 return -1;
548 memset(cxt->node_tbl, 0, max_find_device * sizeof(char *));
549 cxt->node_max = max_find_device;
550 cxt->nodes_used = 1; /* don't use idx 0 b/c looks like NULL */
551
552 cxt->bph = bph;
553 cxt->max_size = max_size;
554 cxt->realloc = realloc_fn;
555
556 cxt->rgn[FT_RSVMAP].start = blob + be32_to_cpu(bph->off_mem_rsvmap);
557 cxt->rgn[FT_RSVMAP].size = rsvmap_size(cxt);
558 cxt->rgn[FT_STRUCT].start = blob + be32_to_cpu(bph->off_dt_struct);
559 cxt->rgn[FT_STRUCT].size = struct_size(cxt);
560 cxt->rgn[FT_STRINGS].start = blob + be32_to_cpu(bph->off_dt_strings);
561 cxt->rgn[FT_STRINGS].size = be32_to_cpu(bph->dt_strings_size);
562 /* Leave as '0' to force first ft_make_space call to do a ft_reorder
563 * and move dt to an area allocated by realloc.
564 cxt->isordered = ft_ordered(cxt);
565 */
566
567 cxt->p = cxt->rgn[FT_STRUCT].start;
568 cxt->str_anchor = cxt->rgn[FT_STRINGS].start;
569
570 return 0;
571}
572
573/* add a reserver physical area to the rsvmap */
574int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size)
575{
576 char *p;
577 struct ft_reserve *pres;
578
579 p = cxt->rgn[FT_RSVMAP].start + cxt->rgn[FT_RSVMAP].size
580 - sizeof(struct ft_reserve);
581 if (!ft_make_space(cxt, &p, FT_RSVMAP, sizeof(struct ft_reserve)))
582 return -1;
583
584 pres = (struct ft_reserve *)p;
585 pres->start = cpu_to_be64(physaddr);
586 pres->len = cpu_to_be64(size);
587
588 return 0;
589}
590
591void ft_begin_tree(struct ft_cxt *cxt)
592{
593 cxt->p = cxt->rgn[FT_STRUCT].start;
594}
595
596void ft_end_tree(struct ft_cxt *cxt)
597{
598 struct boot_param_header *bph = cxt->bph;
599 char *p, *oldstr, *str, *endp;
600 unsigned long ssize;
601 int adj;
602
603 if (!cxt->isordered)
604 return; /* we haven't touched anything */
605
606 /* adjust string offsets */
607 oldstr = cxt->rgn[FT_STRINGS].start;
608 adj = cxt->str_anchor - oldstr;
609 if (adj)
610 adjust_string_offsets(cxt, adj);
611
612 /* make strings end on 8-byte boundary */
613 ssize = cxt->rgn[FT_STRINGS].size;
614 endp = (char *)_ALIGN((unsigned long)cxt->rgn[FT_STRUCT].start
615 + cxt->rgn[FT_STRUCT].size + ssize, 8);
616 str = endp - ssize;
617
618 /* move strings down to end of structs */
619 memmove(str, oldstr, ssize);
620 cxt->str_anchor = str;
621 cxt->rgn[FT_STRINGS].start = str;
622
623 /* fill in header fields */
624 p = (char *)bph;
625 bph->totalsize = cpu_to_be32(endp - p);
626 bph->off_mem_rsvmap = cpu_to_be32(cxt->rgn[FT_RSVMAP].start - p);
627 bph->off_dt_struct = cpu_to_be32(cxt->rgn[FT_STRUCT].start - p);
628 bph->off_dt_strings = cpu_to_be32(cxt->rgn[FT_STRINGS].start - p);
629 bph->dt_strings_size = cpu_to_be32(ssize);
630}
631
632void *ft_find_device(struct ft_cxt *cxt, const char *srch_path)
633{
634 char *node;
635
636 /* require absolute path */
637 if (srch_path[0] != '/')
638 return NULL;
639 node = ft_find_descendent(cxt, cxt->rgn[FT_STRUCT].start, srch_path);
640 return ft_node_add(cxt, node);
641}
642
643void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path)
644{
645 struct ft_atom atom;
646 char *p;
647 const char *cp, *q;
648 int cl;
649 int depth = -1;
650 int dmatch = 0;
651 const char *path_comp[FT_MAX_DEPTH];
652
653 cp = srch_path;
654 cl = 0;
655 p = top;
656
657 while ((p = ft_next(cxt, p, &atom)) != NULL) {
658 switch (atom.tag) {
659 case OF_DT_BEGIN_NODE:
660 ++depth;
661 if (depth != dmatch)
662 break;
663 cxt->genealogy[depth] = atom.data;
664 cxt->genealogy[depth + 1] = NULL;
665 if (depth && !(strncmp(atom.name, cp, cl) == 0
666 && (atom.name[cl] == '/'
667 || atom.name[cl] == '\0'
668 || atom.name[cl] == '@')))
669 break;
670 path_comp[dmatch] = cp;
671 /* it matches so far, advance to next path component */
672 cp += cl;
673 /* skip slashes */
674 while (*cp == '/')
675 ++cp;
676 /* we're done if this is the end of the string */
677 if (*cp == 0)
678 return atom.data;
679 /* look for end of this component */
680 q = strchr(cp, '/');
681 if (q)
682 cl = q - cp;
683 else
684 cl = strlen(cp);
685 ++dmatch;
686 break;
687 case OF_DT_END_NODE:
688 if (depth == 0)
689 return NULL;
690 if (dmatch > depth) {
691 --dmatch;
692 cl = cp - path_comp[dmatch] - 1;
693 cp = path_comp[dmatch];
694 while (cl > 0 && cp[cl - 1] == '/')
695 --cl;
696 }
697 --depth;
698 break;
699 }
700 }
701 return NULL;
702}
703
704void *ft_get_parent(struct ft_cxt *cxt, const void *phandle)
705{
706 void *node;
707 int d;
708 struct ft_atom atom;
709 char *p;
710
711 node = ft_node_ph2node(cxt, phandle);
712 if (node == NULL)
713 return NULL;
714
715 for (d = 0; cxt->genealogy[d] != NULL; ++d)
716 if (cxt->genealogy[d] == node)
717 return cxt->genealogy[d > 0 ? d - 1 : 0];
718
719 /* have to do it the hard way... */
720 p = cxt->rgn[FT_STRUCT].start;
721 d = 0;
722 while ((p = ft_next(cxt, p, &atom)) != NULL) {
723 switch (atom.tag) {
724 case OF_DT_BEGIN_NODE:
725 cxt->genealogy[d] = atom.data;
726 if (node == atom.data) {
727 /* found it */
728 cxt->genealogy[d + 1] = NULL;
729 return d > 0 ? cxt->genealogy[d - 1] : node;
730 }
731 ++d;
732 break;
733 case OF_DT_END_NODE:
734 --d;
735 break;
736 }
737 }
738 return NULL;
739}
740
741int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
742 void *buf, const unsigned int buflen)
743{
744 struct ft_atom atom;
745 void *node;
746 char *p;
747 int depth;
748 unsigned int size;
749
750 node = ft_node_ph2node(cxt, phandle);
751 if (node == NULL)
752 return -1;
753
754 depth = 0;
755 p = (char *)node;
756
757 while ((p = ft_next(cxt, p, &atom)) != NULL) {
758 switch (atom.tag) {
759 case OF_DT_BEGIN_NODE:
760 ++depth;
761 break;
762 case OF_DT_PROP:
763 if ((depth != 1) || strcmp(atom.name, propname))
764 break;
765 size = min(atom.size, buflen);
766 memcpy(buf, atom.data, size);
767 return atom.size;
768 case OF_DT_END_NODE:
769 if (--depth <= 0)
770 return -1;
771 }
772 }
773 return -1;
774}
775
776int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
777 const void *buf, const unsigned int buflen)
778{
779 struct ft_atom atom;
780 void *node;
781 char *p, *next;
782 int nextra, depth;
783
784 node = ft_node_ph2node(cxt, phandle);
785 if (node == NULL)
786 return -1;
787
788 depth = 0;
789 p = node;
790
791 while ((next = ft_next(cxt, p, &atom)) != NULL) {
792 switch (atom.tag) {
793 case OF_DT_BEGIN_NODE:
794 ++depth;
795 break;
796 case OF_DT_END_NODE:
797 if (--depth > 0)
798 break;
799 /* haven't found the property, insert here */
800 cxt->p = p;
801 return ft_prop(cxt, propname, buf, buflen);
802 case OF_DT_PROP:
803 if ((depth != 1) || strcmp(atom.name, propname))
804 break;
805 /* found an existing property, overwrite it */
806 nextra = _ALIGN(buflen, 4) - _ALIGN(atom.size, 4);
807 cxt->p = atom.data;
808 if (nextra && !ft_make_space(cxt, &cxt->p, FT_STRUCT,
809 nextra))
810 return -1;
811 *(u32 *) (cxt->p - 8) = cpu_to_be32(buflen);
812 ft_put_bin(cxt, buf, buflen);
813 return 0;
814 }
815 p = next;
816 }
817 return -1;
818}
819
820int ft_del_prop(struct ft_cxt *cxt, const void *phandle, const char *propname)
821{
822 struct ft_atom atom;
823 void *node;
824 char *p, *next;
825 int size;
826
827 node = ft_node_ph2node(cxt, phandle);
828 if (node == NULL)
829 return -1;
830
831 p = node;
832 while ((next = ft_next(cxt, p, &atom)) != NULL) {
833 switch (atom.tag) {
834 case OF_DT_BEGIN_NODE:
835 case OF_DT_END_NODE:
836 return -1;
837 case OF_DT_PROP:
838 if (strcmp(atom.name, propname))
839 break;
840 /* found the property, remove it */
841 size = 12 + -_ALIGN(atom.size, 4);
842 cxt->p = p;
843 if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, -size))
844 return -1;
845 return 0;
846 }
847 p = next;
848 }
849 return -1;
850}
851
852void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *path)
853{
854 struct ft_atom atom;
855 char *p, *next;
856 int depth = 0;
857
858 p = cxt->rgn[FT_STRUCT].start;
859 while ((next = ft_next(cxt, p, &atom)) != NULL) {
860 switch (atom.tag) {
861 case OF_DT_BEGIN_NODE:
862 ++depth;
863 if (depth == 1 && strcmp(atom.name, path) == 0)
864 /* duplicate node path, return error */
865 return NULL;
866 break;
867 case OF_DT_END_NODE:
868 --depth;
869 if (depth > 0)
870 break;
871 /* end of node, insert here */
872 cxt->p = p;
873 ft_begin_node(cxt, path);
874 ft_end_node(cxt);
875 return p;
876 }
877 p = next;
878 }
879 return NULL;
880}
diff --git a/arch/powerpc/boot/flatdevtree.h b/arch/powerpc/boot/flatdevtree.h
index 761c8dc84008..b9cd9f61f351 100644
--- a/arch/powerpc/boot/flatdevtree.h
+++ b/arch/powerpc/boot/flatdevtree.h
@@ -17,7 +17,7 @@
17#ifndef FLATDEVTREE_H 17#ifndef FLATDEVTREE_H
18#define FLATDEVTREE_H 18#define FLATDEVTREE_H
19 19
20#include "types.h" 20#include "flatdevtree_env.h"
21 21
22/* Definitions used by the flattened device tree */ 22/* Definitions used by the flattened device tree */
23#define OF_DT_HEADER 0xd00dfeed /* marker */ 23#define OF_DT_HEADER 0xd00dfeed /* marker */
@@ -43,4 +43,64 @@ struct boot_param_header {
43 u32 dt_strings_size; /* size of the DT strings block */ 43 u32 dt_strings_size; /* size of the DT strings block */
44}; 44};
45 45
46struct ft_reserve {
47 u64 start;
48 u64 len;
49};
50
51struct ft_region {
52 char *start;
53 unsigned long size;
54};
55
56enum ft_rgn_id {
57 FT_RSVMAP,
58 FT_STRUCT,
59 FT_STRINGS,
60 FT_N_REGION
61};
62
63#define FT_MAX_DEPTH 50
64
65struct ft_cxt {
66 struct boot_param_header *bph;
67 int max_size; /* maximum size of tree */
68 int isordered; /* everything in standard order */
69 void *(*realloc)(void *, unsigned long);
70 char *str_anchor;
71 char *p; /* current insertion point in structs */
72 struct ft_region rgn[FT_N_REGION];
73 void *genealogy[FT_MAX_DEPTH+1];
74 char **node_tbl;
75 unsigned int node_max;
76 unsigned int nodes_used;
77};
78
79int ft_begin_node(struct ft_cxt *cxt, const char *name);
80void ft_end_node(struct ft_cxt *cxt);
81
82void ft_begin_tree(struct ft_cxt *cxt);
83void ft_end_tree(struct ft_cxt *cxt);
84
85void ft_nop(struct ft_cxt *cxt);
86int ft_prop(struct ft_cxt *cxt, const char *name,
87 const void *data, unsigned int sz);
88int ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str);
89int ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val);
90void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size,
91 void *(*realloc_fn)(void *, unsigned long));
92int ft_open(struct ft_cxt *cxt, void *blob, unsigned int max_size,
93 unsigned int max_find_device,
94 void *(*realloc_fn)(void *, unsigned long));
95int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size);
96
97void ft_dump_blob(const void *bphp);
98void ft_merge_blob(struct ft_cxt *cxt, void *blob);
99void *ft_find_device(struct ft_cxt *cxt, const char *srch_path);
100void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path);
101int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
102 void *buf, const unsigned int buflen);
103int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
104 const void *buf, const unsigned int buflen);
105
46#endif /* FLATDEVTREE_H */ 106#endif /* FLATDEVTREE_H */
diff --git a/arch/powerpc/boot/flatdevtree_env.h b/arch/powerpc/boot/flatdevtree_env.h
new file mode 100644
index 000000000000..83bc1c718836
--- /dev/null
+++ b/arch/powerpc/boot/flatdevtree_env.h
@@ -0,0 +1,47 @@
1/*
2 * This file adds the header file glue so that the shared files
3 * flatdevicetree.[ch] can compile and work in the powerpc bootwrapper.
4 *
5 * strncmp & strchr copied from <file:lib/strings.c>
6 * Copyright (C) 1991, 1992 Linus Torvalds
7 *
8 * Maintained by: Mark A. Greer <mgreer@mvista.com>
9 */
10#ifndef _PPC_BOOT_FLATDEVTREE_ENV_H_
11#define _PPC_BOOT_FLATDEVTREE_ENV_H_
12
13#include <stdarg.h>
14#include <stddef.h>
15#include "types.h"
16#include "string.h"
17#include "stdio.h"
18#include "ops.h"
19
20#define be16_to_cpu(x) (x)
21#define cpu_to_be16(x) (x)
22#define be32_to_cpu(x) (x)
23#define cpu_to_be32(x) (x)
24#define be64_to_cpu(x) (x)
25#define cpu_to_be64(x) (x)
26
27static inline int strncmp(const char *cs, const char *ct, size_t count)
28{
29 signed char __res = 0;
30
31 while (count) {
32 if ((__res = *cs - *ct++) != 0 || !*cs++)
33 break;
34 count--;
35 }
36 return __res;
37}
38
39static inline char *strchr(const char *s, int c)
40{
41 for (; *s != (char)c; ++s)
42 if (*s == '\0')
43 return NULL;
44 return (char *)s;
45}
46
47#endif /* _PPC_BOOT_FLATDEVTREE_ENV_H_ */
diff --git a/arch/powerpc/boot/flatdevtree_misc.c b/arch/powerpc/boot/flatdevtree_misc.c
new file mode 100644
index 000000000000..04da38fa477f
--- /dev/null
+++ b/arch/powerpc/boot/flatdevtree_misc.c
@@ -0,0 +1,51 @@
1/*
2 * This file does the necessary interface mapping between the bootwrapper
3 * device tree operations and the interface provided by shared source
4 * files flatdevicetree.[ch].
5 *
6 * Author: Mark A. Greer <mgreer@mvista.com>
7 *
8 * 2006 (c) MontaVista Software, Inc. This file is licensed under
9 * the terms of the GNU General Public License version 2. This program
10 * is licensed "as is" without any warranty of any kind, whether express
11 * or implied.
12 */
13#include <stddef.h>
14#include "flatdevtree.h"
15#include "ops.h"
16
17static struct ft_cxt cxt;
18
19static void *ft_finddevice(const char *name)
20{
21 return ft_find_device(&cxt, name);
22}
23
24static int ft_getprop(const void *phandle, const char *propname, void *buf,
25 const int buflen)
26{
27 return ft_get_prop(&cxt, phandle, propname, buf, buflen);
28}
29
30static int ft_setprop(const void *phandle, const char *propname,
31 const void *buf, const int buflen)
32{
33 return ft_set_prop(&cxt, phandle, propname, buf, buflen);
34}
35
36static unsigned long ft_finalize(void)
37{
38 ft_end_tree(&cxt);
39 return (unsigned long)cxt.bph;
40}
41
42int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device)
43{
44 dt_ops.finddevice = ft_finddevice;
45 dt_ops.getprop = ft_getprop;
46 dt_ops.setprop = ft_setprop;
47 dt_ops.finalize = ft_finalize;
48
49 return ft_open(&cxt, dt_blob, max_size, max_find_device,
50 platform_ops.realloc);
51}
diff --git a/arch/powerpc/boot/io.h b/arch/powerpc/boot/io.h
new file mode 100644
index 000000000000..32974ed49e02
--- /dev/null
+++ b/arch/powerpc/boot/io.h
@@ -0,0 +1,53 @@
1#ifndef _IO_H
2#define __IO_H
3/*
4 * Low-level I/O routines.
5 *
6 * Copied from <file:include/asm-powerpc/io.h> (which has no copyright)
7 */
8static inline int in_8(const volatile unsigned char *addr)
9{
10 int ret;
11
12 __asm__ __volatile__("lbz%U1%X1 %0,%1; twi 0,%0,0; isync"
13 : "=r" (ret) : "m" (*addr));
14 return ret;
15}
16
17static inline void out_8(volatile unsigned char *addr, int val)
18{
19 __asm__ __volatile__("stb%U0%X0 %1,%0; sync"
20 : "=m" (*addr) : "r" (val));
21}
22
23static inline unsigned in_le32(const volatile unsigned *addr)
24{
25 unsigned ret;
26
27 __asm__ __volatile__("lwbrx %0,0,%1; twi 0,%0,0; isync"
28 : "=r" (ret) : "r" (addr), "m" (*addr));
29 return ret;
30}
31
32static inline unsigned in_be32(const volatile unsigned *addr)
33{
34 unsigned ret;
35
36 __asm__ __volatile__("lwz%U1%X1 %0,%1; twi 0,%0,0; isync"
37 : "=r" (ret) : "m" (*addr));
38 return ret;
39}
40
41static inline void out_le32(volatile unsigned *addr, int val)
42{
43 __asm__ __volatile__("stwbrx %1,0,%2; sync" : "=m" (*addr)
44 : "r" (val), "r" (addr));
45}
46
47static inline void out_be32(volatile unsigned *addr, int val)
48{
49 __asm__ __volatile__("stw%U0%X0 %1,%0; sync"
50 : "=m" (*addr) : "r" (val));
51}
52
53#endif /* _IO_H */
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index d719bb9333d1..6f6b50d238b6 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -27,6 +27,8 @@ extern char _vmlinux_start[];
27extern char _vmlinux_end[]; 27extern char _vmlinux_end[];
28extern char _initrd_start[]; 28extern char _initrd_start[];
29extern char _initrd_end[]; 29extern char _initrd_end[];
30extern char _dtb_start[];
31extern char _dtb_end[];
30 32
31struct addr_range { 33struct addr_range {
32 unsigned long addr; 34 unsigned long addr;
@@ -167,7 +169,7 @@ static int is_elf32(void *hdr)
167 return 1; 169 return 1;
168} 170}
169 171
170static void prep_kernel(unsigned long *a1, unsigned long *a2) 172static void prep_kernel(unsigned long a1, unsigned long a2)
171{ 173{
172 int len; 174 int len;
173 175
@@ -203,11 +205,14 @@ static void prep_kernel(unsigned long *a1, unsigned long *a2)
203 } 205 }
204 206
205 /* 207 /*
206 * Now we try to alloc memory for the initrd (and copy it there) 208 * Now find the initrd
209 *
210 * First see if we have an image attached to us. If so
211 * allocate memory for it and copy it there.
207 */ 212 */
208 initrd.size = (unsigned long)(_initrd_end - _initrd_start); 213 initrd.size = (unsigned long)(_initrd_end - _initrd_start);
209 initrd.memsize = initrd.size; 214 initrd.memsize = initrd.size;
210 if ( initrd.size > 0 ) { 215 if (initrd.size > 0) {
211 printf("Allocating 0x%lx bytes for initrd ...\n\r", 216 printf("Allocating 0x%lx bytes for initrd ...\n\r",
212 initrd.size); 217 initrd.size);
213 initrd.addr = (unsigned long)malloc((u32)initrd.size); 218 initrd.addr = (unsigned long)malloc((u32)initrd.size);
@@ -216,8 +221,6 @@ static void prep_kernel(unsigned long *a1, unsigned long *a2)
216 "ramdisk !\n\r"); 221 "ramdisk !\n\r");
217 exit(); 222 exit();
218 } 223 }
219 *a1 = initrd.addr;
220 *a2 = initrd.size;
221 printf("initial ramdisk moving 0x%lx <- 0x%lx " 224 printf("initial ramdisk moving 0x%lx <- 0x%lx "
222 "(0x%lx bytes)\n\r", initrd.addr, 225 "(0x%lx bytes)\n\r", initrd.addr,
223 (unsigned long)_initrd_start, initrd.size); 226 (unsigned long)_initrd_start, initrd.size);
@@ -225,6 +228,12 @@ static void prep_kernel(unsigned long *a1, unsigned long *a2)
225 initrd.size); 228 initrd.size);
226 printf("initrd head: 0x%lx\n\r", 229 printf("initrd head: 0x%lx\n\r",
227 *((unsigned long *)initrd.addr)); 230 *((unsigned long *)initrd.addr));
231 } else if (a2 != 0) {
232 /* Otherwise, see if yaboot or another loader gave us an initrd */
233 initrd.addr = a1;
234 initrd.memsize = initrd.size = a2;
235 printf("Using loader supplied initrd at 0x%lx (0x%lx bytes)\n\r",
236 initrd.addr, initrd.size);
228 } 237 }
229 238
230 /* Eventually gunzip the kernel */ 239 /* Eventually gunzip the kernel */
@@ -250,10 +259,6 @@ static void prep_kernel(unsigned long *a1, unsigned long *a2)
250 flush_cache((void *)vmlinux.addr, vmlinux.size); 259 flush_cache((void *)vmlinux.addr, vmlinux.size);
251} 260}
252 261
253void __attribute__ ((weak)) ft_init(void *dt_blob)
254{
255}
256
257/* A buffer that may be edited by tools operating on a zImage binary so as to 262/* A buffer that may be edited by tools operating on a zImage binary so as to
258 * edit the command line passed to vmlinux (by setting /chosen/bootargs). 263 * edit the command line passed to vmlinux (by setting /chosen/bootargs).
259 * The buffer is put in it's own section so that tools may locate it easier. 264 * The buffer is put in it's own section so that tools may locate it easier.
@@ -285,36 +290,22 @@ static void set_cmdline(char *buf)
285 setprop(devp, "bootargs", buf, strlen(buf) + 1); 290 setprop(devp, "bootargs", buf, strlen(buf) + 1);
286} 291}
287 292
288/* Section where ft can be tacked on after zImage is built */
289union blobspace {
290 struct boot_param_header hdr;
291 char space[8*1024];
292} dt_blob __attribute__((__section__("__builtin_ft")));
293
294struct platform_ops platform_ops; 293struct platform_ops platform_ops;
295struct dt_ops dt_ops; 294struct dt_ops dt_ops;
296struct console_ops console_ops; 295struct console_ops console_ops;
297 296
298void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) 297void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
299{ 298{
300 int have_dt = 0;
301 kernel_entry_t kentry; 299 kernel_entry_t kentry;
302 char cmdline[COMMAND_LINE_SIZE]; 300 char cmdline[COMMAND_LINE_SIZE];
301 unsigned long ft_addr = 0;
303 302
304 memset(__bss_start, 0, _end - __bss_start); 303 memset(__bss_start, 0, _end - __bss_start);
305 memset(&platform_ops, 0, sizeof(platform_ops)); 304 memset(&platform_ops, 0, sizeof(platform_ops));
306 memset(&dt_ops, 0, sizeof(dt_ops)); 305 memset(&dt_ops, 0, sizeof(dt_ops));
307 memset(&console_ops, 0, sizeof(console_ops)); 306 memset(&console_ops, 0, sizeof(console_ops));
308 307
309 /* Override the dt_ops and device tree if there was an flat dev 308 if (platform_init(promptr, _dtb_start, _dtb_end))
310 * tree attached to the zImage.
311 */
312 if (dt_blob.hdr.magic == OF_DT_HEADER) {
313 have_dt = 1;
314 ft_init(&dt_blob);
315 }
316
317 if (platform_init(promptr))
318 exit(); 309 exit();
319 if (console_ops.open && (console_ops.open() < 0)) 310 if (console_ops.open && (console_ops.open() < 0))
320 exit(); 311 exit();
@@ -324,7 +315,7 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
324 printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", 315 printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r",
325 _start, sp); 316 _start, sp);
326 317
327 prep_kernel(&a1, &a2); 318 prep_kernel(a1, a2);
328 319
329 /* If cmdline came from zimage wrapper or if we can edit the one 320 /* If cmdline came from zimage wrapper or if we can edit the one
330 * in the dt, print it out and edit it, if possible. 321 * in the dt, print it out and edit it, if possible.
@@ -338,15 +329,23 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
338 set_cmdline(cmdline); 329 set_cmdline(cmdline);
339 } 330 }
340 331
332 printf("Finalizing device tree...");
333 if (dt_ops.finalize)
334 ft_addr = dt_ops.finalize();
335 if (ft_addr)
336 printf(" flat tree at 0x%lx\n\r", ft_addr);
337 else
338 printf(" using OF tree (promptr=%p)\n\r", promptr);
339
341 if (console_ops.close) 340 if (console_ops.close)
342 console_ops.close(); 341 console_ops.close();
343 342
344 kentry = (kernel_entry_t) vmlinux.addr; 343 kentry = (kernel_entry_t) vmlinux.addr;
345 if (have_dt) 344 if (ft_addr)
346 kentry(dt_ops.ft_addr(), 0, NULL); 345 kentry(ft_addr, 0, NULL);
347 else 346 else
348 /* XXX initrd addr/size should be passed in properties */ 347 /* XXX initrd addr/size should be passed in properties */
349 kentry(a1, a2, promptr); 348 kentry(initrd.addr, initrd.size, promptr);
350 349
351 /* console closed so printf below may not work */ 350 /* console closed so printf below may not work */
352 printf("Error: Linux kernel returned to zImage boot wrapper!\n\r"); 351 printf("Error: Linux kernel returned to zImage boot wrapper!\n\r");
diff --git a/arch/powerpc/boot/mktree.c b/arch/powerpc/boot/mktree.c
new file mode 100644
index 000000000000..4cb892993651
--- /dev/null
+++ b/arch/powerpc/boot/mktree.c
@@ -0,0 +1,152 @@
1/*
2 * Makes a tree bootable image for IBM Evaluation boards.
3 * Basically, just take a zImage, skip the ELF header, and stuff
4 * a 32 byte header on the front.
5 *
6 * We use htonl, which is a network macro, to make sure we're doing
7 * The Right Thing on an LE machine. It's non-obvious, but it should
8 * work on anything BSD'ish.
9 */
10
11#include <fcntl.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <sys/stat.h>
16#include <unistd.h>
17#include <netinet/in.h>
18#ifdef __sun__
19#include <inttypes.h>
20#else
21#include <stdint.h>
22#endif
23
24/* This gets tacked on the front of the image. There are also a few
25 * bytes allocated after the _start label used by the boot rom (see
26 * head.S for details).
27 */
28typedef struct boot_block {
29 uint32_t bb_magic; /* 0x0052504F */
30 uint32_t bb_dest; /* Target address of the image */
31 uint32_t bb_num_512blocks; /* Size, rounded-up, in 512 byte blks */
32 uint32_t bb_debug_flag; /* Run debugger or image after load */
33 uint32_t bb_entry_point; /* The image address to start */
34 uint32_t bb_checksum; /* 32 bit checksum including header */
35 uint32_t reserved[2];
36} boot_block_t;
37
38#define IMGBLK 512
39char tmpbuf[IMGBLK];
40
41int main(int argc, char *argv[])
42{
43 int in_fd, out_fd;
44 int nblks, i;
45 uint cksum, *cp;
46 struct stat st;
47 boot_block_t bt;
48
49 if (argc < 3) {
50 fprintf(stderr, "usage: %s <zImage-file> <boot-image> [entry-point]\n",argv[0]);
51 exit(1);
52 }
53
54 if (stat(argv[1], &st) < 0) {
55 perror("stat");
56 exit(2);
57 }
58
59 nblks = (st.st_size + IMGBLK) / IMGBLK;
60
61 bt.bb_magic = htonl(0x0052504F);
62
63 /* If we have the optional entry point parameter, use it */
64 if (argc == 4)
65 bt.bb_dest = bt.bb_entry_point = htonl(strtoul(argv[3], NULL, 0));
66 else
67 bt.bb_dest = bt.bb_entry_point = htonl(0x500000);
68
69 /* We know these from the linker command.
70 * ...and then move it up into memory a little more so the
71 * relocation can happen.
72 */
73 bt.bb_num_512blocks = htonl(nblks);
74 bt.bb_debug_flag = 0;
75
76 bt.bb_checksum = 0;
77
78 /* To be neat and tidy :-).
79 */
80 bt.reserved[0] = 0;
81 bt.reserved[1] = 0;
82
83 if ((in_fd = open(argv[1], O_RDONLY)) < 0) {
84 perror("zImage open");
85 exit(3);
86 }
87
88 if ((out_fd = open(argv[2], (O_RDWR | O_CREAT | O_TRUNC), 0666)) < 0) {
89 perror("bootfile open");
90 exit(3);
91 }
92
93 cksum = 0;
94 cp = (void *)&bt;
95 for (i=0; i<sizeof(bt)/sizeof(uint); i++)
96 cksum += *cp++;
97
98 /* Assume zImage is an ELF file, and skip the 64K header.
99 */
100 if (read(in_fd, tmpbuf, IMGBLK) != IMGBLK) {
101 fprintf(stderr, "%s is too small to be an ELF image\n",
102 argv[1]);
103 exit(4);
104 }
105
106 if ((*(uint *)tmpbuf) != htonl(0x7f454c46)) {
107 fprintf(stderr, "%s is not an ELF image\n", argv[1]);
108 exit(4);
109 }
110
111 if (lseek(in_fd, (64 * 1024), SEEK_SET) < 0) {
112 fprintf(stderr, "%s failed to seek in ELF image\n", argv[1]);
113 exit(4);
114 }
115
116 nblks -= (64 * 1024) / IMGBLK;
117
118 /* And away we go......
119 */
120 if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) {
121 perror("boot-image write");
122 exit(5);
123 }
124
125 while (nblks-- > 0) {
126 if (read(in_fd, tmpbuf, IMGBLK) < 0) {
127 perror("zImage read");
128 exit(5);
129 }
130 cp = (uint *)tmpbuf;
131 for (i=0; i<sizeof(tmpbuf)/sizeof(uint); i++)
132 cksum += *cp++;
133 if (write(out_fd, tmpbuf, sizeof(tmpbuf)) != sizeof(tmpbuf)) {
134 perror("boot-image write");
135 exit(5);
136 }
137 }
138
139 /* rewrite the header with the computed checksum.
140 */
141 bt.bb_checksum = htonl(cksum);
142 if (lseek(out_fd, 0, SEEK_SET) < 0) {
143 perror("rewrite seek");
144 exit(1);
145 }
146 if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) {
147 perror("boot-image rewrite");
148 exit(1);
149 }
150
151 exit(0);
152}
diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c
new file mode 100644
index 000000000000..1ffe72e35cdc
--- /dev/null
+++ b/arch/powerpc/boot/ns16550.c
@@ -0,0 +1,74 @@
1/*
2 * 16550 serial console support.
3 *
4 * Original copied from <file:arch/ppc/boot/common/ns16550.c>
5 * (which had no copyright)
6 * Modifications: 2006 (c) MontaVista Software, Inc.
7 *
8 * Modified by: Mark A. Greer <mgreer@mvista.com>
9 */
10#include <stdarg.h>
11#include <stddef.h>
12#include "types.h"
13#include "string.h"
14#include "stdio.h"
15#include "io.h"
16#include "ops.h"
17
18#define UART_DLL 0 /* Out: Divisor Latch Low */
19#define UART_DLM 1 /* Out: Divisor Latch High */
20#define UART_FCR 2 /* Out: FIFO Control Register */
21#define UART_LCR 3 /* Out: Line Control Register */
22#define UART_MCR 4 /* Out: Modem Control Register */
23#define UART_LSR 5 /* In: Line Status Register */
24#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
25#define UART_LSR_DR 0x01 /* Receiver data ready */
26#define UART_MSR 6 /* In: Modem Status Register */
27#define UART_SCR 7 /* I/O: Scratch Register */
28
29static unsigned char *reg_base;
30static u32 reg_shift;
31
32static int ns16550_open(void)
33{
34 out_8(reg_base + (UART_FCR << reg_shift), 0x06);
35 return 0;
36}
37
38static void ns16550_putc(unsigned char c)
39{
40 while ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_THRE) == 0);
41 out_8(reg_base, c);
42}
43
44static unsigned char ns16550_getc(void)
45{
46 while ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_DR) == 0);
47 return in_8(reg_base);
48}
49
50static u8 ns16550_tstc(void)
51{
52 return ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_DR) != 0);
53}
54
55int ns16550_console_init(void *devp, struct serial_console_data *scdp)
56{
57 int n;
58
59 n = getprop(devp, "virtual-reg", &reg_base, sizeof(reg_base));
60 if (n != sizeof(reg_base))
61 return -1;
62
63 n = getprop(devp, "reg-shift", &reg_shift, sizeof(reg_shift));
64 if (n != sizeof(reg_shift))
65 reg_shift = 0;
66
67 scdp->open = ns16550_open;
68 scdp->putc = ns16550_putc;
69 scdp->getc = ns16550_getc;
70 scdp->tstc = ns16550_tstc;
71 scdp->close = NULL;
72
73 return 0;
74}
diff --git a/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c
index 3a71845afc6c..0182f384f3e6 100644
--- a/arch/powerpc/boot/of.c
+++ b/arch/powerpc/boot/of.c
@@ -256,24 +256,18 @@ static void of_console_write(char *buf, int len)
256 call_prom("write", 3, 1, of_stdout_handle, buf, len); 256 call_prom("write", 3, 1, of_stdout_handle, buf, len);
257} 257}
258 258
259int platform_init(void *promptr) 259int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end)
260{ 260{
261 platform_ops.fixups = NULL;
262 platform_ops.image_hdr = of_image_hdr; 261 platform_ops.image_hdr = of_image_hdr;
263 platform_ops.malloc = of_try_claim; 262 platform_ops.malloc = of_try_claim;
264 platform_ops.free = NULL;
265 platform_ops.exit = of_exit; 263 platform_ops.exit = of_exit;
266 264
267 dt_ops.finddevice = of_finddevice; 265 dt_ops.finddevice = of_finddevice;
268 dt_ops.getprop = of_getprop; 266 dt_ops.getprop = of_getprop;
269 dt_ops.setprop = of_setprop; 267 dt_ops.setprop = of_setprop;
270 dt_ops.translate_addr = NULL;
271 268
272 console_ops.open = of_console_open; 269 console_ops.open = of_console_open;
273 console_ops.write = of_console_write; 270 console_ops.write = of_console_write;
274 console_ops.edit_cmdline = NULL;
275 console_ops.close = NULL;
276 console_ops.data = NULL;
277 271
278 prom = (int (*)(void *))promptr; 272 prom = (int (*)(void *))promptr;
279 return 0; 273 return 0;
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
index 135eb4bb03b4..8abb6516bb7c 100644
--- a/arch/powerpc/boot/ops.h
+++ b/arch/powerpc/boot/ops.h
@@ -22,7 +22,8 @@ struct platform_ops {
22 void (*fixups)(void); 22 void (*fixups)(void);
23 void (*image_hdr)(const void *); 23 void (*image_hdr)(const void *);
24 void * (*malloc)(u32 size); 24 void * (*malloc)(u32 size);
25 void (*free)(void *ptr, u32 size); 25 void (*free)(void *ptr);
26 void * (*realloc)(void *ptr, unsigned long size);
26 void (*exit)(void); 27 void (*exit)(void);
27}; 28};
28extern struct platform_ops platform_ops; 29extern struct platform_ops platform_ops;
@@ -30,13 +31,11 @@ extern struct platform_ops platform_ops;
30/* Device Tree operations */ 31/* Device Tree operations */
31struct dt_ops { 32struct dt_ops {
32 void * (*finddevice)(const char *name); 33 void * (*finddevice)(const char *name);
33 int (*getprop)(const void *node, const char *name, void *buf, 34 int (*getprop)(const void *phandle, const char *name, void *buf,
34 const int buflen); 35 const int buflen);
35 int (*setprop)(const void *node, const char *name, 36 int (*setprop)(const void *phandle, const char *name,
36 const void *buf, const int buflen); 37 const void *buf, const int buflen);
37 u64 (*translate_addr)(const char *path, const u32 *in_addr, 38 unsigned long (*finalize)(void);
38 const u32 addr_len);
39 unsigned long (*ft_addr)(void);
40}; 39};
41extern struct dt_ops dt_ops; 40extern struct dt_ops dt_ops;
42 41
@@ -59,10 +58,13 @@ struct serial_console_data {
59 void (*close)(void); 58 void (*close)(void);
60}; 59};
61 60
62extern int platform_init(void *promptr); 61int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end);
63extern void simple_alloc_init(void); 62int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device);
64extern void ft_init(void *dt_blob); 63int serial_console_init(void);
65extern int serial_console_init(void); 64int ns16550_console_init(void *devp, struct serial_console_data *scdp);
65void *simple_alloc_init(char *base, u32 heap_size, u32 granularity,
66 u32 max_allocs);
67
66 68
67static inline void *finddevice(const char *name) 69static inline void *finddevice(const char *name)
68{ 70{
@@ -84,10 +86,10 @@ static inline void *malloc(u32 size)
84 return (platform_ops.malloc) ? platform_ops.malloc(size) : NULL; 86 return (platform_ops.malloc) ? platform_ops.malloc(size) : NULL;
85} 87}
86 88
87static inline void free(void *ptr, u32 size) 89static inline void free(void *ptr)
88{ 90{
89 if (platform_ops.free) 91 if (platform_ops.free)
90 platform_ops.free(ptr, size); 92 platform_ops.free(ptr);
91} 93}
92 94
93static inline void exit(void) 95static inline void exit(void)
diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c
new file mode 100644
index 000000000000..e8de4cf59be7
--- /dev/null
+++ b/arch/powerpc/boot/serial.c
@@ -0,0 +1,142 @@
1/*
2 * Generic serial console support
3 *
4 * Author: Mark A. Greer <mgreer@mvista.com>
5 *
6 * Code in serial_edit_cmdline() copied from <file:arch/ppc/boot/simple/misc.c>
7 * and was written by Matt Porter <mporter@kernel.crashing.org>.
8 *
9 * 2001,2006 (c) MontaVista Software, Inc. This file is licensed under
10 * the terms of the GNU General Public License version 2. This program
11 * is licensed "as is" without any warranty of any kind, whether express
12 * or implied.
13 */
14#include <stdarg.h>
15#include <stddef.h>
16#include "types.h"
17#include "string.h"
18#include "stdio.h"
19#include "io.h"
20#include "ops.h"
21
22extern void udelay(long delay);
23
24static int serial_open(void)
25{
26 struct serial_console_data *scdp = console_ops.data;
27 return scdp->open();
28}
29
30static void serial_write(char *buf, int len)
31{
32 struct serial_console_data *scdp = console_ops.data;
33
34 while (*buf != '\0')
35 scdp->putc(*buf++);
36}
37
38static void serial_edit_cmdline(char *buf, int len)
39{
40 int timer = 0, count;
41 char ch, *cp;
42 struct serial_console_data *scdp = console_ops.data;
43
44 cp = buf;
45 count = strlen(buf);
46 cp = &buf[count];
47 count++;
48
49 while (timer++ < 5*1000) {
50 if (scdp->tstc()) {
51 while (((ch = scdp->getc()) != '\n') && (ch != '\r')) {
52 /* Test for backspace/delete */
53 if ((ch == '\b') || (ch == '\177')) {
54 if (cp != buf) {
55 cp--;
56 count--;
57 printf("\b \b");
58 }
59 /* Test for ^x/^u (and wipe the line) */
60 } else if ((ch == '\030') || (ch == '\025')) {
61 while (cp != buf) {
62 cp--;
63 count--;
64 printf("\b \b");
65 }
66 } else if (count < len) {
67 *cp++ = ch;
68 count++;
69 scdp->putc(ch);
70 }
71 }
72 break; /* Exit 'timer' loop */
73 }
74 udelay(1000); /* 1 msec */
75 }
76 *cp = 0;
77}
78
79static void serial_close(void)
80{
81 struct serial_console_data *scdp = console_ops.data;
82
83 if (scdp->close)
84 scdp->close();
85}
86
87static void *serial_get_stdout_devp(void)
88{
89 void *devp;
90 char devtype[MAX_PROP_LEN];
91 char path[MAX_PATH_LEN];
92
93 devp = finddevice("/chosen");
94 if (devp == NULL)
95 goto err_out;
96
97 if (getprop(devp, "linux,stdout-path", path, MAX_PATH_LEN) > 0) {
98 devp = finddevice(path);
99 if (devp == NULL)
100 goto err_out;
101
102 if ((getprop(devp, "device_type", devtype, sizeof(devtype)) > 0)
103 && !strcmp(devtype, "serial"))
104 return devp;
105 }
106err_out:
107 return NULL;
108}
109
110static struct serial_console_data serial_cd;
111
112/* Node's "compatible" property determines which serial driver to use */
113int serial_console_init(void)
114{
115 void *devp;
116 int rc = -1;
117 char compat[MAX_PROP_LEN];
118
119 devp = serial_get_stdout_devp();
120 if (devp == NULL)
121 goto err_out;
122
123 if (getprop(devp, "compatible", compat, sizeof(compat)) < 0)
124 goto err_out;
125
126 if (!strcmp(compat, "ns16550"))
127 rc = ns16550_console_init(devp, &serial_cd);
128
129 /* Add other serial console driver calls here */
130
131 if (!rc) {
132 console_ops.open = serial_open;
133 console_ops.write = serial_write;
134 console_ops.edit_cmdline = serial_edit_cmdline;
135 console_ops.close = serial_close;
136 console_ops.data = &serial_cd;
137
138 return 0;
139 }
140err_out:
141 return -1;
142}
diff --git a/arch/powerpc/boot/simple_alloc.c b/arch/powerpc/boot/simple_alloc.c
new file mode 100644
index 000000000000..cfe3a7505ba0
--- /dev/null
+++ b/arch/powerpc/boot/simple_alloc.c
@@ -0,0 +1,149 @@
1/*
2 * Implement primitive realloc(3) functionality.
3 *
4 * Author: Mark A. Greer <mgreer@mvista.com>
5 *
6 * 2006 (c) MontaVista, Software, Inc. This file is licensed under
7 * the terms of the GNU General Public License version 2. This program
8 * is licensed "as is" without any warranty of any kind, whether express
9 * or implied.
10 */
11
12#include <stddef.h>
13#include "types.h"
14#include "page.h"
15#include "string.h"
16#include "ops.h"
17
18#define ENTRY_BEEN_USED 0x01
19#define ENTRY_IN_USE 0x02
20
21static struct alloc_info {
22 u32 flags;
23 u32 base;
24 u32 size;
25} *alloc_tbl;
26
27static u32 tbl_entries;
28static u32 alloc_min;
29static u32 next_base;
30static u32 space_left;
31
32/*
33 * First time an entry is used, its base and size are set.
34 * An entry can be freed and re-malloc'd but its base & size don't change.
35 * Should be smart enough for needs of bootwrapper.
36 */
37static void *simple_malloc(u32 size)
38{
39 u32 i;
40 struct alloc_info *p = alloc_tbl;
41
42 if (size == 0)
43 goto err_out;
44
45 size = _ALIGN_UP(size, alloc_min);
46
47 for (i=0; i<tbl_entries; i++, p++)
48 if (!(p->flags & ENTRY_BEEN_USED)) { /* never been used */
49 if (size <= space_left) {
50 p->base = next_base;
51 p->size = size;
52 p->flags = ENTRY_BEEN_USED | ENTRY_IN_USE;
53 next_base += size;
54 space_left -= size;
55 return (void *)p->base;
56 }
57 goto err_out; /* not enough space left */
58 }
59 /* reuse an entry keeping same base & size */
60 else if (!(p->flags & ENTRY_IN_USE) && (size <= p->size)) {
61 p->flags |= ENTRY_IN_USE;
62 return (void *)p->base;
63 }
64err_out:
65 return NULL;
66}
67
68static struct alloc_info *simple_find_entry(void *ptr)
69{
70 u32 i;
71 struct alloc_info *p = alloc_tbl;
72
73 for (i=0; i<tbl_entries; i++,p++) {
74 if (!(p->flags & ENTRY_BEEN_USED))
75 break;
76 if ((p->flags & ENTRY_IN_USE) && (p->base == (u32)ptr))
77 return p;
78 }
79 return NULL;
80}
81
82static void simple_free(void *ptr)
83{
84 struct alloc_info *p = simple_find_entry(ptr);
85
86 if (p != NULL)
87 p->flags &= ~ENTRY_IN_USE;
88}
89
90/*
91 * Change size of area pointed to by 'ptr' to 'size'.
92 * If 'ptr' is NULL, then its a malloc(). If 'size' is 0, then its a free().
93 * 'ptr' must be NULL or a pointer to a non-freed area previously returned by
94 * simple_realloc() or simple_malloc().
95 */
96static void *simple_realloc(void *ptr, unsigned long size)
97{
98 struct alloc_info *p;
99 void *new;
100
101 if (size == 0) {
102 simple_free(ptr);
103 return NULL;
104 }
105
106 if (ptr == NULL)
107 return simple_malloc(size);
108
109 p = simple_find_entry(ptr);
110 if (p == NULL) /* ptr not from simple_malloc/simple_realloc */
111 return NULL;
112 if (size <= p->size) /* fits in current block */
113 return ptr;
114
115 new = simple_malloc(size);
116 memcpy(new, ptr, p->size);
117 simple_free(ptr);
118 return new;
119}
120
121/*
122 * Returns addr of first byte after heap so caller can see if it took
123 * too much space. If so, change args & try again.
124 */
125void *simple_alloc_init(char *base, u32 heap_size, u32 granularity,
126 u32 max_allocs)
127{
128 u32 heap_base, tbl_size;
129
130 heap_size = _ALIGN_UP(heap_size, granularity);
131 alloc_min = granularity;
132 tbl_entries = max_allocs;
133
134 tbl_size = tbl_entries * sizeof(struct alloc_info);
135
136 alloc_tbl = (struct alloc_info *)_ALIGN_UP((unsigned long)base, 8);
137 memset(alloc_tbl, 0, tbl_size);
138
139 heap_base = _ALIGN_UP((u32)alloc_tbl + tbl_size, alloc_min);
140
141 next_base = heap_base;
142 space_left = heap_size;
143
144 platform_ops.malloc = simple_malloc;
145 platform_ops.free = simple_free;
146 platform_ops.realloc = simple_realloc;
147
148 return (void *)(heap_base + heap_size);
149}
diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c
index 6d5f6382e1ce..0a9feeb98342 100644
--- a/arch/powerpc/boot/stdio.c
+++ b/arch/powerpc/boot/stdio.c
@@ -320,6 +320,7 @@ printf(const char *fmt, ...)
320 va_start(args, fmt); 320 va_start(args, fmt);
321 n = vsprintf(sprint_buf, fmt, args); 321 n = vsprintf(sprint_buf, fmt, args);
322 va_end(args); 322 va_end(args);
323 console_ops.write(sprint_buf, n); 323 if (console_ops.write)
324 console_ops.write(sprint_buf, n);
324 return n; 325 return n;
325} 326}
diff --git a/arch/powerpc/boot/util.S b/arch/powerpc/boot/util.S
new file mode 100644
index 000000000000..427ddfc11991
--- /dev/null
+++ b/arch/powerpc/boot/util.S
@@ -0,0 +1,88 @@
1/*
2 * Copied from <file:arch/powerpc/kernel/misc_32.S>
3 *
4 * This file contains miscellaneous low-level functions.
5 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
6 *
7 * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
8 * and Paul Mackerras.
9 *
10 * kexec bits:
11 * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
12 * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version
17 * 2 of the License, or (at your option) any later version.
18 *
19 */
20#include "ppc_asm.h"
21
22#define SPRN_PVR 0x11F /* Processor Version Register */
23
24 .text
25
26/* udelay (on non-601 processors) needs to know the period of the
27 * timebase in nanoseconds. This used to be hardcoded to be 60ns
28 * (period of 66MHz/4). Now a variable is used that is initialized to
29 * 60 for backward compatibility, but it can be overridden as necessary
30 * with code something like this:
31 * extern unsigned long timebase_period_ns;
32 * timebase_period_ns = 1000000000 / bd->bi_tbfreq;
33 */
34 .data
35 .globl timebase_period_ns
36timebase_period_ns:
37 .long 60
38
39 .text
40/*
41 * Delay for a number of microseconds
42 */
43 .globl udelay
44udelay:
45 mfspr r4,SPRN_PVR
46 srwi r4,r4,16
47 cmpwi 0,r4,1 /* 601 ? */
48 bne .udelay_not_601
4900: li r0,86 /* Instructions / microsecond? */
50 mtctr r0
5110: addi r0,r0,0 /* NOP */
52 bdnz 10b
53 subic. r3,r3,1
54 bne 00b
55 blr
56
57.udelay_not_601:
58 mulli r4,r3,1000 /* nanoseconds */
59 /* Change r4 to be the number of ticks using:
60 * (nanoseconds + (timebase_period_ns - 1 )) / timebase_period_ns
61 * timebase_period_ns defaults to 60 (16.6MHz) */
62 mflr r5
63 bl 0f
640: mflr r6
65 mtlr r5
66 lis r5,0b@ha
67 addi r5,r5,0b@l
68 subf r5,r5,r6 /* In case we're relocated */
69 addis r5,r5,timebase_period_ns@ha
70 lwz r5,timebase_period_ns@l(r5)
71 add r4,r4,r5
72 addi r4,r4,-1
73 divw r4,r4,r5 /* BUS ticks */
741: mftbu r5
75 mftb r6
76 mftbu r7
77 cmpw 0,r5,r7
78 bne 1b /* Get [synced] base time */
79 addc r9,r6,r4 /* Compute end time */
80 addze r8,r5
812: mftbu r5
82 cmpw 0,r5,r8
83 blt 2b
84 bgt 3f
85 mftb r6
86 cmpw 0,r6,r9
87 blt 2b
883: blr
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index b5fb1fee76f8..024e4d425c59 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -184,6 +184,9 @@ fi
184 184
185if [ -n "$dtb" ]; then 185if [ -n "$dtb" ]; then
186 addsec $tmp "$dtb" .kernel:dtb 186 addsec $tmp "$dtb" .kernel:dtb
187 if [ -n "$dts" ]; then
188 rm $dtb
189 fi
187fi 190fi
188 191
189if [ "$platform" != "miboot" ]; then 192if [ "$platform" != "miboot" ]; then
diff --git a/arch/powerpc/boot/zImage.coff.lds.S b/arch/powerpc/boot/zImage.coff.lds.S
index 05f32388b953..a360905e5428 100644
--- a/arch/powerpc/boot/zImage.coff.lds.S
+++ b/arch/powerpc/boot/zImage.coff.lds.S
@@ -21,6 +21,10 @@ SECTIONS
21 *(.got2) 21 *(.got2)
22 __got2_end = .; 22 __got2_end = .;
23 23
24 _dtb_start = .;
25 *(.kernel:dtb)
26 _dtb_end = .;
27
24 _vmlinux_start = .; 28 _vmlinux_start = .;
25 *(.kernel:vmlinux.strip) 29 *(.kernel:vmlinux.strip)
26 _vmlinux_end = .; 30 _vmlinux_end = .;
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index 0aba06d7d2ec..a98c982c73ad 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -1,7 +1,7 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.18 3# Linux kernel version: 2.6.19-rc6
4# Wed Oct 4 15:30:50 2006 4# Wed Nov 22 15:33:04 2006
5# 5#
6CONFIG_PPC64=y 6CONFIG_PPC64=y
7CONFIG_64BIT=y 7CONFIG_64BIT=y
@@ -32,6 +32,10 @@ CONFIG_AUDIT_ARCH=y
32CONFIG_POWER3=y 32CONFIG_POWER3=y
33CONFIG_POWER4=y 33CONFIG_POWER4=y
34CONFIG_PPC_FPU=y 34CONFIG_PPC_FPU=y
35# CONFIG_PPC_DCR_NATIVE is not set
36CONFIG_PPC_DCR_MMIO=y
37CONFIG_PPC_DCR=y
38CONFIG_PPC_OF_PLATFORM_PCI=y
35CONFIG_ALTIVEC=y 39CONFIG_ALTIVEC=y
36CONFIG_PPC_STD_MMU=y 40CONFIG_PPC_STD_MMU=y
37CONFIG_VIRT_CPU_ACCOUNTING=y 41CONFIG_VIRT_CPU_ACCOUNTING=y
@@ -67,7 +71,7 @@ CONFIG_INITRAMFS_SOURCE=""
67CONFIG_CC_OPTIMIZE_FOR_SIZE=y 71CONFIG_CC_OPTIMIZE_FOR_SIZE=y
68CONFIG_SYSCTL=y 72CONFIG_SYSCTL=y
69# CONFIG_EMBEDDED is not set 73# CONFIG_EMBEDDED is not set
70# CONFIG_SYSCTL_SYSCALL is not set 74CONFIG_SYSCTL_SYSCALL=y
71CONFIG_KALLSYMS=y 75CONFIG_KALLSYMS=y
72# CONFIG_KALLSYMS_ALL is not set 76# CONFIG_KALLSYMS_ALL is not set
73# CONFIG_KALLSYMS_EXTRA_PASS is not set 77# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -131,6 +135,7 @@ CONFIG_PPC_CELL=y
131CONFIG_PPC_CELL_NATIVE=y 135CONFIG_PPC_CELL_NATIVE=y
132CONFIG_PPC_IBM_CELL_BLADE=y 136CONFIG_PPC_IBM_CELL_BLADE=y
133CONFIG_UDBG_RTAS_CONSOLE=y 137CONFIG_UDBG_RTAS_CONSOLE=y
138CONFIG_PPC_PS3=y
134# CONFIG_U3_DART is not set 139# CONFIG_U3_DART is not set
135CONFIG_PPC_RTAS=y 140CONFIG_PPC_RTAS=y
136# CONFIG_RTAS_ERROR_LOGGING is not set 141# CONFIG_RTAS_ERROR_LOGGING is not set
@@ -139,9 +144,23 @@ CONFIG_RTAS_FLASH=y
139CONFIG_MMIO_NVRAM=y 144CONFIG_MMIO_NVRAM=y
140# CONFIG_PPC_MPC106 is not set 145# CONFIG_PPC_MPC106 is not set
141# CONFIG_PPC_970_NAP is not set 146# CONFIG_PPC_970_NAP is not set
142# CONFIG_CPU_FREQ is not set 147CONFIG_PPC_INDIRECT_IO=y
148CONFIG_GENERIC_IOMAP=y
149CONFIG_CPU_FREQ=y
150CONFIG_CPU_FREQ_TABLE=y
151CONFIG_CPU_FREQ_DEBUG=y
152CONFIG_CPU_FREQ_STAT=y
153# CONFIG_CPU_FREQ_STAT_DETAILS is not set
154CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
155# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
156CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
157CONFIG_CPU_FREQ_GOV_POWERSAVE=y
158CONFIG_CPU_FREQ_GOV_USERSPACE=y
159CONFIG_CPU_FREQ_GOV_ONDEMAND=y
160CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
161# CONFIG_CPU_FREQ_PMAC64 is not set
143# CONFIG_WANT_EARLY_SERIAL is not set 162# CONFIG_WANT_EARLY_SERIAL is not set
144# CONFIG_MPIC is not set 163CONFIG_MPIC=y
145 164
146# 165#
147# Cell Broadband Engine options 166# Cell Broadband Engine options
@@ -149,6 +168,15 @@ CONFIG_MMIO_NVRAM=y
149CONFIG_SPU_FS=m 168CONFIG_SPU_FS=m
150CONFIG_SPU_BASE=y 169CONFIG_SPU_BASE=y
151CONFIG_CBE_RAS=y 170CONFIG_CBE_RAS=y
171CONFIG_CBE_THERM=m
172CONFIG_CBE_CPUFREQ=m
173
174#
175# PS3 Platform Options
176#
177CONFIG_PS3_HTAB_SIZE=20
178# CONFIG_PS3_DYNAMIC_DMA is not set
179CONFIG_PS3_USE_LPAR_ADDR=y
152 180
153# 181#
154# Kernel options 182# Kernel options
@@ -166,13 +194,14 @@ CONFIG_BINFMT_MISC=m
166CONFIG_FORCE_MAX_ZONEORDER=9 194CONFIG_FORCE_MAX_ZONEORDER=9
167# CONFIG_IOMMU_VMERGE is not set 195# CONFIG_IOMMU_VMERGE is not set
168CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y 196CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
169CONFIG_KEXEC=y 197# CONFIG_KEXEC is not set
170# CONFIG_CRASH_DUMP is not set 198# CONFIG_CRASH_DUMP is not set
171CONFIG_IRQ_ALL_CPUS=y 199CONFIG_IRQ_ALL_CPUS=y
172CONFIG_NUMA=y 200CONFIG_NUMA=y
173CONFIG_NODES_SHIFT=4 201CONFIG_NODES_SHIFT=4
174CONFIG_ARCH_SELECT_MEMORY_MODEL=y 202CONFIG_ARCH_SELECT_MEMORY_MODEL=y
175CONFIG_ARCH_SPARSEMEM_ENABLE=y 203CONFIG_ARCH_SPARSEMEM_ENABLE=y
204CONFIG_ARCH_SPARSEMEM_DEFAULT=y
176CONFIG_ARCH_POPULATES_NODE_MAP=y 205CONFIG_ARCH_POPULATES_NODE_MAP=y
177CONFIG_SELECT_MEMORY_MODEL=y 206CONFIG_SELECT_MEMORY_MODEL=y
178# CONFIG_FLATMEM_MANUAL is not set 207# CONFIG_FLATMEM_MANUAL is not set
@@ -189,6 +218,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
189CONFIG_MIGRATION=y 218CONFIG_MIGRATION=y
190CONFIG_RESOURCES_64BIT=y 219CONFIG_RESOURCES_64BIT=y
191CONFIG_ARCH_MEMORY_PROBE=y 220CONFIG_ARCH_MEMORY_PROBE=y
221CONFIG_NODES_SPAN_OTHER_NODES=y
192CONFIG_PPC_64K_PAGES=y 222CONFIG_PPC_64K_PAGES=y
193CONFIG_SCHED_SMT=y 223CONFIG_SCHED_SMT=y
194CONFIG_PROC_DEVICETREE=y 224CONFIG_PROC_DEVICETREE=y
@@ -207,7 +237,6 @@ CONFIG_GENERIC_ISA_DMA=y
207CONFIG_PCI=y 237CONFIG_PCI=y
208CONFIG_PCI_DOMAINS=y 238CONFIG_PCI_DOMAINS=y
209CONFIG_PCIEPORTBUS=y 239CONFIG_PCIEPORTBUS=y
210# CONFIG_PCI_MULTITHREAD_PROBE is not set
211# CONFIG_PCI_DEBUG is not set 240# CONFIG_PCI_DEBUG is not set
212 241
213# 242#
@@ -280,7 +309,6 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=y
280# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set 309# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
281# CONFIG_IPV6_SIT is not set 310# CONFIG_IPV6_SIT is not set
282CONFIG_IPV6_TUNNEL=m 311CONFIG_IPV6_TUNNEL=m
283# CONFIG_IPV6_SUBTREES is not set
284# CONFIG_IPV6_MULTIPLE_TABLES is not set 312# CONFIG_IPV6_MULTIPLE_TABLES is not set
285# CONFIG_NETWORK_SECMARK is not set 313# CONFIG_NETWORK_SECMARK is not set
286CONFIG_NETFILTER=y 314CONFIG_NETFILTER=y
@@ -1107,7 +1135,8 @@ CONFIG_PLIST=y
1107# 1135#
1108# Instrumentation Support 1136# Instrumentation Support
1109# 1137#
1110# CONFIG_PROFILING is not set 1138CONFIG_PROFILING=y
1139CONFIG_OPROFILE=y
1111# CONFIG_KPROBES is not set 1140# CONFIG_KPROBES is not set
1112 1141
1113# 1142#
@@ -1142,6 +1171,7 @@ CONFIG_DEBUG_FS=y
1142CONFIG_DEBUGGER=y 1171CONFIG_DEBUGGER=y
1143CONFIG_XMON=y 1172CONFIG_XMON=y
1144CONFIG_XMON_DEFAULT=y 1173CONFIG_XMON_DEFAULT=y
1174CONFIG_XMON_DISASSEMBLY=y
1145CONFIG_IRQSTACKS=y 1175CONFIG_IRQSTACKS=y
1146# CONFIG_BOOTX_TEXT is not set 1176# CONFIG_BOOTX_TEXT is not set
1147# CONFIG_PPC_EARLY_DEBUG is not set 1177# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1159,7 +1189,7 @@ CONFIG_CRYPTO=y
1159CONFIG_CRYPTO_ALGAPI=y 1189CONFIG_CRYPTO_ALGAPI=y
1160CONFIG_CRYPTO_BLKCIPHER=m 1190CONFIG_CRYPTO_BLKCIPHER=m
1161CONFIG_CRYPTO_HASH=y 1191CONFIG_CRYPTO_HASH=y
1162# CONFIG_CRYPTO_MANAGER is not set 1192CONFIG_CRYPTO_MANAGER=y
1163CONFIG_CRYPTO_HMAC=y 1193CONFIG_CRYPTO_HMAC=y
1164# CONFIG_CRYPTO_NULL is not set 1194# CONFIG_CRYPTO_NULL is not set
1165# CONFIG_CRYPTO_MD4 is not set 1195# CONFIG_CRYPTO_MD4 is not set
diff --git a/arch/powerpc/configs/linkstation_defconfig b/arch/powerpc/configs/linkstation_defconfig
new file mode 100644
index 000000000000..23fd210eb56a
--- /dev/null
+++ b/arch/powerpc/configs/linkstation_defconfig
@@ -0,0 +1,1583 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.19-rc4
4# Wed Nov 15 20:36:30 2006
5#
6# CONFIG_PPC64 is not set
7CONFIG_PPC32=y
8CONFIG_PPC_MERGE=y
9CONFIG_MMU=y
10CONFIG_GENERIC_HARDIRQS=y
11CONFIG_IRQ_PER_CPU=y
12CONFIG_RWSEM_XCHGADD_ALGORITHM=y
13CONFIG_GENERIC_HWEIGHT=y
14CONFIG_GENERIC_CALIBRATE_DELAY=y
15CONFIG_GENERIC_FIND_NEXT_BIT=y
16CONFIG_PPC=y
17CONFIG_EARLY_PRINTK=y
18CONFIG_GENERIC_NVRAM=y
19CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
20CONFIG_ARCH_MAY_HAVE_PC_FDC=y
21CONFIG_PPC_OF=y
22CONFIG_PPC_UDBG_16550=y
23# CONFIG_GENERIC_TBSYNC is not set
24CONFIG_AUDIT_ARCH=y
25# CONFIG_DEFAULT_UIMAGE is not set
26
27#
28# Processor support
29#
30CONFIG_CLASSIC32=y
31# CONFIG_PPC_52xx is not set
32# CONFIG_PPC_82xx is not set
33# CONFIG_PPC_83xx is not set
34# CONFIG_PPC_85xx is not set
35# CONFIG_PPC_86xx is not set
36# CONFIG_40x is not set
37# CONFIG_44x is not set
38# CONFIG_8xx is not set
39# CONFIG_E200 is not set
40CONFIG_6xx=y
41CONFIG_PPC_FPU=y
42# CONFIG_PPC_DCR_NATIVE is not set
43# CONFIG_PPC_DCR_MMIO is not set
44# CONFIG_ALTIVEC is not set
45CONFIG_PPC_STD_MMU=y
46CONFIG_PPC_STD_MMU_32=y
47# CONFIG_SMP is not set
48CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
49
50#
51# Code maturity level options
52#
53CONFIG_EXPERIMENTAL=y
54CONFIG_BROKEN_ON_SMP=y
55CONFIG_INIT_ENV_ARG_LIMIT=32
56
57#
58# General setup
59#
60CONFIG_LOCALVERSION="-kuroboxHG"
61CONFIG_LOCALVERSION_AUTO=y
62CONFIG_SWAP=y
63CONFIG_SYSVIPC=y
64# CONFIG_IPC_NS is not set
65CONFIG_POSIX_MQUEUE=y
66# CONFIG_BSD_PROCESS_ACCT is not set
67# CONFIG_TASKSTATS is not set
68# CONFIG_UTS_NS is not set
69# CONFIG_AUDIT is not set
70CONFIG_IKCONFIG=y
71CONFIG_IKCONFIG_PROC=y
72# CONFIG_RELAY is not set
73CONFIG_INITRAMFS_SOURCE=""
74# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
75CONFIG_SYSCTL=y
76# CONFIG_EMBEDDED is not set
77# CONFIG_SYSCTL_SYSCALL is not set
78CONFIG_KALLSYMS=y
79# CONFIG_KALLSYMS_ALL is not set
80# CONFIG_KALLSYMS_EXTRA_PASS is not set
81CONFIG_HOTPLUG=y
82CONFIG_PRINTK=y
83CONFIG_BUG=y
84CONFIG_ELF_CORE=y
85CONFIG_BASE_FULL=y
86CONFIG_FUTEX=y
87CONFIG_EPOLL=y
88CONFIG_SHMEM=y
89CONFIG_SLAB=y
90CONFIG_VM_EVENT_COUNTERS=y
91CONFIG_RT_MUTEXES=y
92# CONFIG_TINY_SHMEM is not set
93CONFIG_BASE_SMALL=0
94# CONFIG_SLOB is not set
95
96#
97# Loadable module support
98#
99CONFIG_MODULES=y
100CONFIG_MODULE_UNLOAD=y
101# CONFIG_MODULE_FORCE_UNLOAD is not set
102# CONFIG_MODVERSIONS is not set
103# CONFIG_MODULE_SRCVERSION_ALL is not set
104CONFIG_KMOD=y
105
106#
107# Block layer
108#
109CONFIG_BLOCK=y
110# CONFIG_LBD is not set
111# CONFIG_BLK_DEV_IO_TRACE is not set
112# CONFIG_LSF is not set
113
114#
115# IO Schedulers
116#
117CONFIG_IOSCHED_NOOP=y
118CONFIG_IOSCHED_AS=y
119CONFIG_IOSCHED_DEADLINE=y
120CONFIG_IOSCHED_CFQ=y
121CONFIG_DEFAULT_AS=y
122# CONFIG_DEFAULT_DEADLINE is not set
123# CONFIG_DEFAULT_CFQ is not set
124# CONFIG_DEFAULT_NOOP is not set
125CONFIG_DEFAULT_IOSCHED="anticipatory"
126
127#
128# Platform support
129#
130# CONFIG_PPC_MULTIPLATFORM is not set
131CONFIG_EMBEDDED6xx=y
132# CONFIG_APUS is not set
133# CONFIG_PPC_CELL is not set
134# CONFIG_PPC_CELL_NATIVE is not set
135# CONFIG_PPC_RTAS is not set
136# CONFIG_MMIO_NVRAM is not set
137# CONFIG_PPC_MPC106 is not set
138# CONFIG_PPC_970_NAP is not set
139# CONFIG_PPC_INDIRECT_IO is not set
140# CONFIG_GENERIC_IOMAP is not set
141# CONFIG_CPU_FREQ is not set
142# CONFIG_TAU is not set
143# CONFIG_KATANA is not set
144# CONFIG_WILLOW is not set
145# CONFIG_CPCI690 is not set
146# CONFIG_POWERPMC250 is not set
147# CONFIG_CHESTNUT is not set
148# CONFIG_SPRUCE is not set
149# CONFIG_HDPU is not set
150# CONFIG_EV64260 is not set
151# CONFIG_LOPEC is not set
152# CONFIG_MVME5100 is not set
153# CONFIG_PPLUS is not set
154# CONFIG_PRPMC750 is not set
155# CONFIG_PRPMC800 is not set
156# CONFIG_SANDPOINT is not set
157CONFIG_LINKSTATION=y
158# CONFIG_MPC7448HPC2 is not set
159# CONFIG_RADSTONE_PPC7D is not set
160# CONFIG_PAL4 is not set
161# CONFIG_GEMINI is not set
162# CONFIG_EST8260 is not set
163# CONFIG_SBC82xx is not set
164# CONFIG_SBS8260 is not set
165# CONFIG_RPX8260 is not set
166# CONFIG_TQM8260 is not set
167# CONFIG_ADS8272 is not set
168# CONFIG_PQ2FADS is not set
169# CONFIG_LITE5200 is not set
170# CONFIG_EV64360 is not set
171CONFIG_PPC_GEN550=y
172CONFIG_MPC10X_BRIDGE=y
173CONFIG_MPC10X_OPENPIC=y
174# CONFIG_MPC10X_STORE_GATHERING is not set
175# CONFIG_WANT_EARLY_SERIAL is not set
176CONFIG_MPIC=y
177
178#
179# Kernel options
180#
181# CONFIG_HIGHMEM is not set
182CONFIG_HZ_100=y
183# CONFIG_HZ_250 is not set
184# CONFIG_HZ_1000 is not set
185CONFIG_HZ=100
186CONFIG_PREEMPT_NONE=y
187# CONFIG_PREEMPT_VOLUNTARY is not set
188# CONFIG_PREEMPT is not set
189CONFIG_BINFMT_ELF=y
190# CONFIG_BINFMT_MISC is not set
191CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
192CONFIG_ARCH_FLATMEM_ENABLE=y
193CONFIG_ARCH_POPULATES_NODE_MAP=y
194CONFIG_SELECT_MEMORY_MODEL=y
195CONFIG_FLATMEM_MANUAL=y
196# CONFIG_DISCONTIGMEM_MANUAL is not set
197# CONFIG_SPARSEMEM_MANUAL is not set
198CONFIG_FLATMEM=y
199CONFIG_FLAT_NODE_MEM_MAP=y
200# CONFIG_SPARSEMEM_STATIC is not set
201CONFIG_SPLIT_PTLOCK_CPUS=4
202# CONFIG_RESOURCES_64BIT is not set
203CONFIG_PROC_DEVICETREE=y
204# CONFIG_CMDLINE_BOOL is not set
205# CONFIG_PM is not set
206# CONFIG_SECCOMP is not set
207CONFIG_ISA_DMA_API=y
208
209#
210# Bus options
211#
212CONFIG_GENERIC_ISA_DMA=y
213# CONFIG_MPIC_WEIRD is not set
214# CONFIG_PPC_I8259 is not set
215CONFIG_PPC_INDIRECT_PCI=y
216CONFIG_FSL_SOC=y
217CONFIG_PCI=y
218CONFIG_PCI_DOMAINS=y
219# CONFIG_PCIEPORTBUS is not set
220# CONFIG_PCI_MULTITHREAD_PROBE is not set
221# CONFIG_PCI_DEBUG is not set
222
223#
224# PCCARD (PCMCIA/CardBus) support
225#
226# CONFIG_PCCARD is not set
227
228#
229# PCI Hotplug Support
230#
231# CONFIG_HOTPLUG_PCI is not set
232
233#
234# Advanced setup
235#
236# CONFIG_ADVANCED_OPTIONS is not set
237
238#
239# Default settings for advanced configuration options are used
240#
241CONFIG_HIGHMEM_START=0xfe000000
242CONFIG_LOWMEM_SIZE=0x30000000
243CONFIG_KERNEL_START=0xc0000000
244CONFIG_TASK_SIZE=0x80000000
245CONFIG_BOOT_LOAD=0x00800000
246
247#
248# Networking
249#
250CONFIG_NET=y
251
252#
253# Networking options
254#
255# CONFIG_NETDEBUG is not set
256CONFIG_PACKET=y
257CONFIG_PACKET_MMAP=y
258CONFIG_UNIX=y
259CONFIG_XFRM=y
260# CONFIG_XFRM_USER is not set
261# CONFIG_XFRM_SUB_POLICY is not set
262# CONFIG_NET_KEY is not set
263CONFIG_INET=y
264CONFIG_IP_MULTICAST=y
265# CONFIG_IP_ADVANCED_ROUTER is not set
266CONFIG_IP_FIB_HASH=y
267CONFIG_IP_PNP=y
268CONFIG_IP_PNP_DHCP=y
269CONFIG_IP_PNP_BOOTP=y
270# CONFIG_IP_PNP_RARP is not set
271# CONFIG_NET_IPIP is not set
272# CONFIG_NET_IPGRE is not set
273# CONFIG_IP_MROUTE is not set
274# CONFIG_ARPD is not set
275# CONFIG_SYN_COOKIES is not set
276# CONFIG_INET_AH is not set
277# CONFIG_INET_ESP is not set
278# CONFIG_INET_IPCOMP is not set
279# CONFIG_INET_XFRM_TUNNEL is not set
280# CONFIG_INET_TUNNEL is not set
281CONFIG_INET_XFRM_MODE_TRANSPORT=y
282CONFIG_INET_XFRM_MODE_TUNNEL=y
283CONFIG_INET_XFRM_MODE_BEET=y
284CONFIG_INET_DIAG=y
285CONFIG_INET_TCP_DIAG=y
286# CONFIG_TCP_CONG_ADVANCED is not set
287CONFIG_TCP_CONG_CUBIC=y
288CONFIG_DEFAULT_TCP_CONG="cubic"
289
290#
291# IP: Virtual Server Configuration
292#
293# CONFIG_IP_VS is not set
294# CONFIG_IPV6 is not set
295# CONFIG_INET6_XFRM_TUNNEL is not set
296# CONFIG_INET6_TUNNEL is not set
297# CONFIG_NETWORK_SECMARK is not set
298CONFIG_NETFILTER=y
299# CONFIG_NETFILTER_DEBUG is not set
300
301#
302# Core Netfilter Configuration
303#
304# CONFIG_NETFILTER_NETLINK is not set
305CONFIG_NETFILTER_XTABLES=m
306CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
307# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
308CONFIG_NETFILTER_XT_TARGET_MARK=m
309# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
310# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
311# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
312CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
313# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
314# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
315CONFIG_NETFILTER_XT_MATCH_ESP=m
316# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
317CONFIG_NETFILTER_XT_MATCH_LENGTH=m
318CONFIG_NETFILTER_XT_MATCH_LIMIT=m
319CONFIG_NETFILTER_XT_MATCH_MAC=m
320CONFIG_NETFILTER_XT_MATCH_MARK=m
321# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
322CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
323CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
324# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
325# CONFIG_NETFILTER_XT_MATCH_REALM is not set
326# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
327CONFIG_NETFILTER_XT_MATCH_STATE=m
328# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
329# CONFIG_NETFILTER_XT_MATCH_STRING is not set
330# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
331
332#
333# IP: Netfilter Configuration
334#
335CONFIG_IP_NF_CONNTRACK=m
336# CONFIG_IP_NF_CT_ACCT is not set
337# CONFIG_IP_NF_CONNTRACK_MARK is not set
338# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
339# CONFIG_IP_NF_CT_PROTO_SCTP is not set
340CONFIG_IP_NF_FTP=m
341CONFIG_IP_NF_IRC=m
342# CONFIG_IP_NF_NETBIOS_NS is not set
343CONFIG_IP_NF_TFTP=m
344# CONFIG_IP_NF_AMANDA is not set
345# CONFIG_IP_NF_PPTP is not set
346# CONFIG_IP_NF_H323 is not set
347# CONFIG_IP_NF_SIP is not set
348# CONFIG_IP_NF_QUEUE is not set
349CONFIG_IP_NF_IPTABLES=m
350CONFIG_IP_NF_MATCH_IPRANGE=m
351# CONFIG_IP_NF_MATCH_TOS is not set
352# CONFIG_IP_NF_MATCH_RECENT is not set
353# CONFIG_IP_NF_MATCH_ECN is not set
354# CONFIG_IP_NF_MATCH_AH is not set
355# CONFIG_IP_NF_MATCH_TTL is not set
356# CONFIG_IP_NF_MATCH_OWNER is not set
357# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
358# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
359CONFIG_IP_NF_FILTER=m
360CONFIG_IP_NF_TARGET_REJECT=m
361# CONFIG_IP_NF_TARGET_LOG is not set
362# CONFIG_IP_NF_TARGET_ULOG is not set
363# CONFIG_IP_NF_TARGET_TCPMSS is not set
364CONFIG_IP_NF_NAT=m
365CONFIG_IP_NF_NAT_NEEDED=y
366CONFIG_IP_NF_TARGET_MASQUERADE=m
367CONFIG_IP_NF_TARGET_REDIRECT=m
368CONFIG_IP_NF_TARGET_NETMAP=m
369CONFIG_IP_NF_TARGET_SAME=m
370# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
371CONFIG_IP_NF_NAT_IRC=m
372CONFIG_IP_NF_NAT_FTP=m
373CONFIG_IP_NF_NAT_TFTP=m
374CONFIG_IP_NF_MANGLE=m
375CONFIG_IP_NF_TARGET_TOS=m
376CONFIG_IP_NF_TARGET_ECN=m
377CONFIG_IP_NF_TARGET_TTL=m
378CONFIG_IP_NF_RAW=m
379CONFIG_IP_NF_ARPTABLES=m
380CONFIG_IP_NF_ARPFILTER=m
381CONFIG_IP_NF_ARP_MANGLE=m
382
383#
384# DCCP Configuration (EXPERIMENTAL)
385#
386# CONFIG_IP_DCCP is not set
387
388#
389# SCTP Configuration (EXPERIMENTAL)
390#
391# CONFIG_IP_SCTP is not set
392
393#
394# TIPC Configuration (EXPERIMENTAL)
395#
396# CONFIG_TIPC is not set
397# CONFIG_ATM is not set
398# CONFIG_BRIDGE is not set
399# CONFIG_VLAN_8021Q is not set
400# CONFIG_DECNET is not set
401# CONFIG_LLC2 is not set
402# CONFIG_IPX is not set
403# CONFIG_ATALK is not set
404# CONFIG_X25 is not set
405# CONFIG_LAPB is not set
406# CONFIG_ECONET is not set
407# CONFIG_WAN_ROUTER is not set
408
409#
410# QoS and/or fair queueing
411#
412# CONFIG_NET_SCHED is not set
413
414#
415# Network testing
416#
417# CONFIG_NET_PKTGEN is not set
418# CONFIG_HAMRADIO is not set
419# CONFIG_IRDA is not set
420# CONFIG_BT is not set
421CONFIG_IEEE80211=m
422CONFIG_IEEE80211_DEBUG=y
423CONFIG_IEEE80211_CRYPT_WEP=m
424CONFIG_IEEE80211_CRYPT_CCMP=m
425CONFIG_IEEE80211_CRYPT_TKIP=m
426CONFIG_IEEE80211_SOFTMAC=m
427CONFIG_IEEE80211_SOFTMAC_DEBUG=y
428CONFIG_WIRELESS_EXT=y
429
430#
431# Device Drivers
432#
433
434#
435# Generic Driver Options
436#
437CONFIG_STANDALONE=y
438CONFIG_PREVENT_FIRMWARE_BUILD=y
439CONFIG_FW_LOADER=m
440# CONFIG_DEBUG_DRIVER is not set
441# CONFIG_SYS_HYPERVISOR is not set
442
443#
444# Connector - unified userspace <-> kernelspace linker
445#
446# CONFIG_CONNECTOR is not set
447
448#
449# Memory Technology Devices (MTD)
450#
451CONFIG_MTD=y
452# CONFIG_MTD_DEBUG is not set
453CONFIG_MTD_CONCAT=y
454CONFIG_MTD_PARTITIONS=y
455# CONFIG_MTD_REDBOOT_PARTS is not set
456# CONFIG_MTD_CMDLINE_PARTS is not set
457
458#
459# User Modules And Translation Layers
460#
461CONFIG_MTD_CHAR=y
462CONFIG_MTD_BLOCK=y
463# CONFIG_FTL is not set
464# CONFIG_NFTL is not set
465# CONFIG_INFTL is not set
466# CONFIG_RFD_FTL is not set
467# CONFIG_SSFDC is not set
468
469#
470# RAM/ROM/Flash chip drivers
471#
472CONFIG_MTD_CFI=y
473CONFIG_MTD_JEDECPROBE=y
474CONFIG_MTD_GEN_PROBE=y
475CONFIG_MTD_CFI_ADV_OPTIONS=y
476CONFIG_MTD_CFI_NOSWAP=y
477# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
478# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
479CONFIG_MTD_CFI_GEOMETRY=y
480CONFIG_MTD_MAP_BANK_WIDTH_1=y
481# CONFIG_MTD_MAP_BANK_WIDTH_2 is not set
482# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
483# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
484# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
485# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
486CONFIG_MTD_CFI_I1=y
487# CONFIG_MTD_CFI_I2 is not set
488# CONFIG_MTD_CFI_I4 is not set
489# CONFIG_MTD_CFI_I8 is not set
490# CONFIG_MTD_OTP is not set
491# CONFIG_MTD_CFI_INTELEXT is not set
492CONFIG_MTD_CFI_AMDSTD=y
493# CONFIG_MTD_CFI_STAA is not set
494CONFIG_MTD_CFI_UTIL=y
495# CONFIG_MTD_RAM is not set
496# CONFIG_MTD_ROM is not set
497# CONFIG_MTD_ABSENT is not set
498# CONFIG_MTD_OBSOLETE_CHIPS is not set
499
500#
501# Mapping drivers for chip access
502#
503# CONFIG_MTD_COMPLEX_MAPPINGS is not set
504CONFIG_MTD_PHYSMAP=y
505CONFIG_MTD_PHYSMAP_START=0xffc00000
506CONFIG_MTD_PHYSMAP_LEN=0x400000
507CONFIG_MTD_PHYSMAP_BANKWIDTH=1
508# CONFIG_MTD_PLATRAM is not set
509
510#
511# Self-contained MTD device drivers
512#
513# CONFIG_MTD_PMC551 is not set
514# CONFIG_MTD_SLRAM is not set
515# CONFIG_MTD_PHRAM is not set
516# CONFIG_MTD_MTDRAM is not set
517# CONFIG_MTD_BLOCK2MTD is not set
518
519#
520# Disk-On-Chip Device Drivers
521#
522# CONFIG_MTD_DOC2000 is not set
523# CONFIG_MTD_DOC2001 is not set
524# CONFIG_MTD_DOC2001PLUS is not set
525
526#
527# NAND Flash Device Drivers
528#
529# CONFIG_MTD_NAND is not set
530
531#
532# OneNAND Flash Device Drivers
533#
534# CONFIG_MTD_ONENAND is not set
535
536#
537# Parallel port support
538#
539# CONFIG_PARPORT is not set
540
541#
542# Plug and Play support
543#
544
545#
546# Block devices
547#
548# CONFIG_BLK_DEV_FD is not set
549# CONFIG_BLK_CPQ_DA is not set
550# CONFIG_BLK_CPQ_CISS_DA is not set
551# CONFIG_BLK_DEV_DAC960 is not set
552# CONFIG_BLK_DEV_UMEM is not set
553# CONFIG_BLK_DEV_COW_COMMON is not set
554CONFIG_BLK_DEV_LOOP=y
555# CONFIG_BLK_DEV_CRYPTOLOOP is not set
556# CONFIG_BLK_DEV_NBD is not set
557# CONFIG_BLK_DEV_SX8 is not set
558# CONFIG_BLK_DEV_UB is not set
559CONFIG_BLK_DEV_RAM=y
560CONFIG_BLK_DEV_RAM_COUNT=2
561CONFIG_BLK_DEV_RAM_SIZE=8192
562CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
563CONFIG_BLK_DEV_INITRD=y
564# CONFIG_CDROM_PKTCDVD is not set
565# CONFIG_ATA_OVER_ETH is not set
566
567#
568# Misc devices
569#
570# CONFIG_SGI_IOC4 is not set
571# CONFIG_TIFM_CORE is not set
572
573#
574# ATA/ATAPI/MFM/RLL support
575#
576# CONFIG_IDE is not set
577
578#
579# SCSI device support
580#
581# CONFIG_RAID_ATTRS is not set
582CONFIG_SCSI=y
583# CONFIG_SCSI_NETLINK is not set
584CONFIG_SCSI_PROC_FS=y
585
586#
587# SCSI support type (disk, tape, CD-ROM)
588#
589CONFIG_BLK_DEV_SD=y
590# CONFIG_CHR_DEV_ST is not set
591# CONFIG_CHR_DEV_OSST is not set
592# CONFIG_BLK_DEV_SR is not set
593CONFIG_CHR_DEV_SG=y
594# CONFIG_CHR_DEV_SCH is not set
595
596#
597# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
598#
599CONFIG_SCSI_MULTI_LUN=y
600# CONFIG_SCSI_CONSTANTS is not set
601# CONFIG_SCSI_LOGGING is not set
602
603#
604# SCSI Transports
605#
606# CONFIG_SCSI_SPI_ATTRS is not set
607# CONFIG_SCSI_FC_ATTRS is not set
608# CONFIG_SCSI_ISCSI_ATTRS is not set
609# CONFIG_SCSI_SAS_ATTRS is not set
610# CONFIG_SCSI_SAS_LIBSAS is not set
611
612#
613# SCSI low-level drivers
614#
615# CONFIG_ISCSI_TCP is not set
616# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
617# CONFIG_SCSI_3W_9XXX is not set
618# CONFIG_SCSI_ACARD is not set
619# CONFIG_SCSI_AACRAID is not set
620# CONFIG_SCSI_AIC7XXX is not set
621# CONFIG_SCSI_AIC7XXX_OLD is not set
622# CONFIG_SCSI_AIC79XX is not set
623# CONFIG_SCSI_AIC94XX is not set
624# CONFIG_SCSI_DPT_I2O is not set
625# CONFIG_SCSI_ARCMSR is not set
626# CONFIG_MEGARAID_NEWGEN is not set
627# CONFIG_MEGARAID_LEGACY is not set
628# CONFIG_MEGARAID_SAS is not set
629# CONFIG_SCSI_HPTIOP is not set
630# CONFIG_SCSI_BUSLOGIC is not set
631# CONFIG_SCSI_DMX3191D is not set
632# CONFIG_SCSI_EATA is not set
633# CONFIG_SCSI_FUTURE_DOMAIN is not set
634# CONFIG_SCSI_GDTH is not set
635# CONFIG_SCSI_IPS is not set
636# CONFIG_SCSI_INITIO is not set
637# CONFIG_SCSI_INIA100 is not set
638# CONFIG_SCSI_STEX is not set
639# CONFIG_SCSI_SYM53C8XX_2 is not set
640# CONFIG_SCSI_IPR is not set
641# CONFIG_SCSI_QLOGIC_1280 is not set
642# CONFIG_SCSI_QLA_FC is not set
643# CONFIG_SCSI_QLA_ISCSI is not set
644# CONFIG_SCSI_LPFC is not set
645# CONFIG_SCSI_DC395x is not set
646# CONFIG_SCSI_DC390T is not set
647# CONFIG_SCSI_NSP32 is not set
648# CONFIG_SCSI_DEBUG is not set
649
650#
651# Serial ATA (prod) and Parallel ATA (experimental) drivers
652#
653CONFIG_ATA=y
654# CONFIG_SATA_AHCI is not set
655# CONFIG_SATA_SVW is not set
656# CONFIG_ATA_PIIX is not set
657# CONFIG_SATA_MV is not set
658# CONFIG_SATA_NV is not set
659# CONFIG_PDC_ADMA is not set
660# CONFIG_SATA_QSTOR is not set
661# CONFIG_SATA_PROMISE is not set
662# CONFIG_SATA_SX4 is not set
663# CONFIG_SATA_SIL is not set
664# CONFIG_SATA_SIL24 is not set
665# CONFIG_SATA_SIS is not set
666# CONFIG_SATA_ULI is not set
667# CONFIG_SATA_VIA is not set
668# CONFIG_SATA_VITESSE is not set
669# CONFIG_PATA_ALI is not set
670# CONFIG_PATA_AMD is not set
671# CONFIG_PATA_ARTOP is not set
672# CONFIG_PATA_ATIIXP is not set
673# CONFIG_PATA_CMD64X is not set
674# CONFIG_PATA_CS5520 is not set
675# CONFIG_PATA_CS5530 is not set
676# CONFIG_PATA_CYPRESS is not set
677# CONFIG_PATA_EFAR is not set
678# CONFIG_ATA_GENERIC is not set
679# CONFIG_PATA_HPT366 is not set
680# CONFIG_PATA_HPT37X is not set
681# CONFIG_PATA_HPT3X2N is not set
682# CONFIG_PATA_HPT3X3 is not set
683# CONFIG_PATA_IT821X is not set
684# CONFIG_PATA_JMICRON is not set
685# CONFIG_PATA_TRIFLEX is not set
686# CONFIG_PATA_MPIIX is not set
687# CONFIG_PATA_OLDPIIX is not set
688# CONFIG_PATA_NETCELL is not set
689# CONFIG_PATA_NS87410 is not set
690# CONFIG_PATA_OPTI is not set
691# CONFIG_PATA_OPTIDMA is not set
692# CONFIG_PATA_PDC_OLD is not set
693# CONFIG_PATA_RADISYS is not set
694# CONFIG_PATA_RZ1000 is not set
695# CONFIG_PATA_SC1200 is not set
696# CONFIG_PATA_SERVERWORKS is not set
697# CONFIG_PATA_PDC2027X is not set
698CONFIG_PATA_SIL680=y
699# CONFIG_PATA_SIS is not set
700# CONFIG_PATA_VIA is not set
701# CONFIG_PATA_WINBOND is not set
702
703#
704# Multi-device support (RAID and LVM)
705#
706# CONFIG_MD is not set
707
708#
709# Fusion MPT device support
710#
711# CONFIG_FUSION is not set
712# CONFIG_FUSION_SPI is not set
713# CONFIG_FUSION_FC is not set
714# CONFIG_FUSION_SAS is not set
715
716#
717# IEEE 1394 (FireWire) support
718#
719# CONFIG_IEEE1394 is not set
720
721#
722# I2O device support
723#
724# CONFIG_I2O is not set
725
726#
727# Macintosh device drivers
728#
729# CONFIG_WINDFARM is not set
730
731#
732# Network device support
733#
734CONFIG_NETDEVICES=y
735# CONFIG_DUMMY is not set
736# CONFIG_BONDING is not set
737# CONFIG_EQUALIZER is not set
738CONFIG_TUN=m
739
740#
741# ARCnet devices
742#
743# CONFIG_ARCNET is not set
744
745#
746# PHY device support
747#
748
749#
750# Ethernet (10 or 100Mbit)
751#
752# CONFIG_NET_ETHERNET is not set
753
754#
755# Ethernet (1000 Mbit)
756#
757# CONFIG_ACENIC is not set
758# CONFIG_DL2K is not set
759# CONFIG_E1000 is not set
760# CONFIG_NS83820 is not set
761# CONFIG_HAMACHI is not set
762# CONFIG_YELLOWFIN is not set
763CONFIG_R8169=y
764# CONFIG_R8169_NAPI is not set
765# CONFIG_SIS190 is not set
766# CONFIG_SKGE is not set
767# CONFIG_SKY2 is not set
768# CONFIG_SK98LIN is not set
769# CONFIG_TIGON3 is not set
770# CONFIG_BNX2 is not set
771# CONFIG_QLA3XXX is not set
772
773#
774# Ethernet (10000 Mbit)
775#
776# CONFIG_CHELSIO_T1 is not set
777# CONFIG_IXGB is not set
778# CONFIG_S2IO is not set
779# CONFIG_MYRI10GE is not set
780
781#
782# Token Ring devices
783#
784# CONFIG_TR is not set
785
786#
787# Wireless LAN (non-hamradio)
788#
789CONFIG_NET_RADIO=y
790# CONFIG_NET_WIRELESS_RTNETLINK is not set
791
792#
793# Obsolete Wireless cards support (pre-802.11)
794#
795# CONFIG_STRIP is not set
796
797#
798# Wireless 802.11b ISA/PCI cards support
799#
800# CONFIG_IPW2100 is not set
801# CONFIG_IPW2200 is not set
802# CONFIG_AIRO is not set
803# CONFIG_HERMES is not set
804# CONFIG_ATMEL is not set
805
806#
807# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
808#
809# CONFIG_PRISM54 is not set
810# CONFIG_USB_ZD1201 is not set
811# CONFIG_HOSTAP is not set
812# CONFIG_BCM43XX is not set
813# CONFIG_ZD1211RW is not set
814CONFIG_NET_WIRELESS=y
815
816#
817# Wan interfaces
818#
819# CONFIG_WAN is not set
820# CONFIG_FDDI is not set
821# CONFIG_HIPPI is not set
822# CONFIG_PPP is not set
823# CONFIG_SLIP is not set
824# CONFIG_NET_FC is not set
825# CONFIG_SHAPER is not set
826CONFIG_NETCONSOLE=y
827CONFIG_NETPOLL=y
828# CONFIG_NETPOLL_RX is not set
829# CONFIG_NETPOLL_TRAP is not set
830CONFIG_NET_POLL_CONTROLLER=y
831
832#
833# ISDN subsystem
834#
835# CONFIG_ISDN is not set
836
837#
838# Telephony Support
839#
840# CONFIG_PHONE is not set
841
842#
843# Input device support
844#
845CONFIG_INPUT=y
846# CONFIG_INPUT_FF_MEMLESS is not set
847
848#
849# Userland interfaces
850#
851CONFIG_INPUT_MOUSEDEV=y
852# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
853CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
854CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
855# CONFIG_INPUT_JOYDEV is not set
856# CONFIG_INPUT_TSDEV is not set
857CONFIG_INPUT_EVDEV=m
858# CONFIG_INPUT_EVBUG is not set
859
860#
861# Input Device Drivers
862#
863# CONFIG_INPUT_KEYBOARD is not set
864# CONFIG_INPUT_MOUSE is not set
865# CONFIG_INPUT_JOYSTICK is not set
866# CONFIG_INPUT_TOUCHSCREEN is not set
867CONFIG_INPUT_MISC=y
868CONFIG_INPUT_UINPUT=m
869
870#
871# Hardware I/O ports
872#
873CONFIG_SERIO=y
874# CONFIG_SERIO_I8042 is not set
875CONFIG_SERIO_SERPORT=y
876# CONFIG_SERIO_PCIPS2 is not set
877# CONFIG_SERIO_RAW is not set
878# CONFIG_GAMEPORT is not set
879
880#
881# Character devices
882#
883CONFIG_VT=y
884CONFIG_VT_CONSOLE=y
885CONFIG_HW_CONSOLE=y
886# CONFIG_VT_HW_CONSOLE_BINDING is not set
887# CONFIG_SERIAL_NONSTANDARD is not set
888
889#
890# Serial drivers
891#
892CONFIG_SERIAL_8250=y
893CONFIG_SERIAL_8250_CONSOLE=y
894CONFIG_SERIAL_8250_PCI=y
895CONFIG_SERIAL_8250_NR_UARTS=4
896CONFIG_SERIAL_8250_RUNTIME_UARTS=4
897# CONFIG_SERIAL_8250_EXTENDED is not set
898
899#
900# Non-8250 serial port support
901#
902CONFIG_SERIAL_CORE=y
903CONFIG_SERIAL_CORE_CONSOLE=y
904# CONFIG_SERIAL_JSM is not set
905CONFIG_UNIX98_PTYS=y
906CONFIG_LEGACY_PTYS=y
907CONFIG_LEGACY_PTY_COUNT=256
908
909#
910# IPMI
911#
912# CONFIG_IPMI_HANDLER is not set
913
914#
915# Watchdog Cards
916#
917# CONFIG_WATCHDOG is not set
918CONFIG_HW_RANDOM=y
919# CONFIG_NVRAM is not set
920# CONFIG_GEN_RTC is not set
921# CONFIG_DTLK is not set
922# CONFIG_R3964 is not set
923# CONFIG_APPLICOM is not set
924
925#
926# Ftape, the floppy tape device driver
927#
928# CONFIG_AGP is not set
929# CONFIG_DRM is not set
930# CONFIG_RAW_DRIVER is not set
931
932#
933# TPM devices
934#
935# CONFIG_TCG_TPM is not set
936
937#
938# I2C support
939#
940CONFIG_I2C=y
941CONFIG_I2C_CHARDEV=y
942
943#
944# I2C Algorithms
945#
946# CONFIG_I2C_ALGOBIT is not set
947# CONFIG_I2C_ALGOPCF is not set
948# CONFIG_I2C_ALGOPCA is not set
949
950#
951# I2C Hardware Bus support
952#
953# CONFIG_I2C_ALI1535 is not set
954# CONFIG_I2C_ALI1563 is not set
955# CONFIG_I2C_ALI15X3 is not set
956# CONFIG_I2C_AMD756 is not set
957# CONFIG_I2C_AMD8111 is not set
958# CONFIG_I2C_I801 is not set
959# CONFIG_I2C_I810 is not set
960# CONFIG_I2C_PIIX4 is not set
961CONFIG_I2C_MPC=y
962# CONFIG_I2C_NFORCE2 is not set
963# CONFIG_I2C_OCORES is not set
964# CONFIG_I2C_PARPORT_LIGHT is not set
965# CONFIG_I2C_PROSAVAGE is not set
966# CONFIG_I2C_SAVAGE4 is not set
967# CONFIG_I2C_SIS5595 is not set
968# CONFIG_I2C_SIS630 is not set
969# CONFIG_I2C_SIS96X is not set
970# CONFIG_I2C_STUB is not set
971# CONFIG_I2C_VIA is not set
972# CONFIG_I2C_VIAPRO is not set
973# CONFIG_I2C_VOODOO3 is not set
974# CONFIG_I2C_PCA_ISA is not set
975
976#
977# Miscellaneous I2C Chip support
978#
979# CONFIG_SENSORS_DS1337 is not set
980# CONFIG_SENSORS_DS1374 is not set
981CONFIG_SENSORS_EEPROM=m
982# CONFIG_SENSORS_PCF8574 is not set
983# CONFIG_SENSORS_PCA9539 is not set
984# CONFIG_SENSORS_PCF8591 is not set
985# CONFIG_SENSORS_M41T00 is not set
986# CONFIG_SENSORS_MAX6875 is not set
987# CONFIG_I2C_DEBUG_CORE is not set
988# CONFIG_I2C_DEBUG_ALGO is not set
989# CONFIG_I2C_DEBUG_BUS is not set
990# CONFIG_I2C_DEBUG_CHIP is not set
991
992#
993# SPI support
994#
995# CONFIG_SPI is not set
996# CONFIG_SPI_MASTER is not set
997
998#
999# Dallas's 1-wire bus
1000#
1001# CONFIG_W1 is not set
1002
1003#
1004# Hardware Monitoring support
1005#
1006CONFIG_HWMON=y
1007# CONFIG_HWMON_VID is not set
1008# CONFIG_SENSORS_ABITUGURU is not set
1009# CONFIG_SENSORS_ADM1021 is not set
1010# CONFIG_SENSORS_ADM1025 is not set
1011# CONFIG_SENSORS_ADM1026 is not set
1012# CONFIG_SENSORS_ADM1031 is not set
1013# CONFIG_SENSORS_ADM9240 is not set
1014# CONFIG_SENSORS_ASB100 is not set
1015# CONFIG_SENSORS_ATXP1 is not set
1016# CONFIG_SENSORS_DS1621 is not set
1017# CONFIG_SENSORS_F71805F is not set
1018# CONFIG_SENSORS_FSCHER is not set
1019# CONFIG_SENSORS_FSCPOS is not set
1020# CONFIG_SENSORS_GL518SM is not set
1021# CONFIG_SENSORS_GL520SM is not set
1022# CONFIG_SENSORS_IT87 is not set
1023# CONFIG_SENSORS_LM63 is not set
1024# CONFIG_SENSORS_LM75 is not set
1025# CONFIG_SENSORS_LM77 is not set
1026# CONFIG_SENSORS_LM78 is not set
1027# CONFIG_SENSORS_LM80 is not set
1028# CONFIG_SENSORS_LM83 is not set
1029# CONFIG_SENSORS_LM85 is not set
1030# CONFIG_SENSORS_LM87 is not set
1031# CONFIG_SENSORS_LM90 is not set
1032# CONFIG_SENSORS_LM92 is not set
1033# CONFIG_SENSORS_MAX1619 is not set
1034# CONFIG_SENSORS_PC87360 is not set
1035# CONFIG_SENSORS_SIS5595 is not set
1036# CONFIG_SENSORS_SMSC47M1 is not set
1037# CONFIG_SENSORS_SMSC47M192 is not set
1038# CONFIG_SENSORS_SMSC47B397 is not set
1039# CONFIG_SENSORS_VIA686A is not set
1040# CONFIG_SENSORS_VT1211 is not set
1041# CONFIG_SENSORS_VT8231 is not set
1042# CONFIG_SENSORS_W83781D is not set
1043# CONFIG_SENSORS_W83791D is not set
1044# CONFIG_SENSORS_W83792D is not set
1045# CONFIG_SENSORS_W83L785TS is not set
1046# CONFIG_SENSORS_W83627HF is not set
1047# CONFIG_SENSORS_W83627EHF is not set
1048# CONFIG_HWMON_DEBUG_CHIP is not set
1049
1050#
1051# Multimedia devices
1052#
1053# CONFIG_VIDEO_DEV is not set
1054
1055#
1056# Digital Video Broadcasting Devices
1057#
1058# CONFIG_DVB is not set
1059# CONFIG_USB_DABUSB is not set
1060
1061#
1062# Graphics support
1063#
1064CONFIG_FIRMWARE_EDID=y
1065# CONFIG_FB is not set
1066
1067#
1068# Console display driver support
1069#
1070# CONFIG_VGA_CONSOLE is not set
1071CONFIG_DUMMY_CONSOLE=y
1072# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
1073
1074#
1075# Sound
1076#
1077# CONFIG_SOUND is not set
1078
1079#
1080# USB support
1081#
1082CONFIG_USB_ARCH_HAS_HCD=y
1083CONFIG_USB_ARCH_HAS_OHCI=y
1084CONFIG_USB_ARCH_HAS_EHCI=y
1085CONFIG_USB=y
1086# CONFIG_USB_DEBUG is not set
1087
1088#
1089# Miscellaneous USB options
1090#
1091CONFIG_USB_DEVICEFS=y
1092# CONFIG_USB_BANDWIDTH is not set
1093# CONFIG_USB_DYNAMIC_MINORS is not set
1094# CONFIG_USB_OTG is not set
1095
1096#
1097# USB Host Controller Drivers
1098#
1099CONFIG_USB_EHCI_HCD=y
1100# CONFIG_USB_EHCI_SPLIT_ISO is not set
1101# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
1102# CONFIG_USB_EHCI_TT_NEWSCHED is not set
1103# CONFIG_USB_ISP116X_HCD is not set
1104CONFIG_USB_OHCI_HCD=y
1105# CONFIG_USB_OHCI_BIG_ENDIAN is not set
1106CONFIG_USB_OHCI_LITTLE_ENDIAN=y
1107# CONFIG_USB_UHCI_HCD is not set
1108# CONFIG_USB_SL811_HCD is not set
1109
1110#
1111# USB Device Class drivers
1112#
1113# CONFIG_USB_ACM is not set
1114# CONFIG_USB_PRINTER is not set
1115
1116#
1117# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
1118#
1119
1120#
1121# may also be needed; see USB_STORAGE Help for more information
1122#
1123CONFIG_USB_STORAGE=m
1124# CONFIG_USB_STORAGE_DEBUG is not set
1125# CONFIG_USB_STORAGE_DATAFAB is not set
1126# CONFIG_USB_STORAGE_FREECOM is not set
1127# CONFIG_USB_STORAGE_DPCM is not set
1128# CONFIG_USB_STORAGE_USBAT is not set
1129# CONFIG_USB_STORAGE_SDDR09 is not set
1130# CONFIG_USB_STORAGE_SDDR55 is not set
1131# CONFIG_USB_STORAGE_JUMPSHOT is not set
1132# CONFIG_USB_STORAGE_ALAUDA is not set
1133# CONFIG_USB_STORAGE_ONETOUCH is not set
1134# CONFIG_USB_STORAGE_KARMA is not set
1135# CONFIG_USB_LIBUSUAL is not set
1136
1137#
1138# USB Input Devices
1139#
1140# CONFIG_USB_HID is not set
1141
1142#
1143# USB HID Boot Protocol drivers
1144#
1145# CONFIG_USB_KBD is not set
1146# CONFIG_USB_MOUSE is not set
1147# CONFIG_USB_AIPTEK is not set
1148# CONFIG_USB_WACOM is not set
1149# CONFIG_USB_ACECAD is not set
1150# CONFIG_USB_KBTAB is not set
1151# CONFIG_USB_POWERMATE is not set
1152# CONFIG_USB_TOUCHSCREEN is not set
1153# CONFIG_USB_YEALINK is not set
1154# CONFIG_USB_XPAD is not set
1155# CONFIG_USB_ATI_REMOTE is not set
1156# CONFIG_USB_ATI_REMOTE2 is not set
1157# CONFIG_USB_KEYSPAN_REMOTE is not set
1158# CONFIG_USB_APPLETOUCH is not set
1159
1160#
1161# USB Imaging devices
1162#
1163# CONFIG_USB_MDC800 is not set
1164# CONFIG_USB_MICROTEK is not set
1165
1166#
1167# USB Network Adapters
1168#
1169# CONFIG_USB_CATC is not set
1170# CONFIG_USB_KAWETH is not set
1171# CONFIG_USB_PEGASUS is not set
1172# CONFIG_USB_RTL8150 is not set
1173# CONFIG_USB_USBNET is not set
1174CONFIG_USB_MON=y
1175
1176#
1177# USB port drivers
1178#
1179
1180#
1181# USB Serial Converter support
1182#
1183CONFIG_USB_SERIAL=y
1184CONFIG_USB_SERIAL_CONSOLE=y
1185# CONFIG_USB_SERIAL_GENERIC is not set
1186# CONFIG_USB_SERIAL_AIRCABLE is not set
1187# CONFIG_USB_SERIAL_AIRPRIME is not set
1188# CONFIG_USB_SERIAL_ARK3116 is not set
1189# CONFIG_USB_SERIAL_BELKIN is not set
1190# CONFIG_USB_SERIAL_WHITEHEAT is not set
1191# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
1192# CONFIG_USB_SERIAL_CP2101 is not set
1193# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
1194# CONFIG_USB_SERIAL_EMPEG is not set
1195CONFIG_USB_SERIAL_FTDI_SIO=y
1196# CONFIG_USB_SERIAL_FUNSOFT is not set
1197# CONFIG_USB_SERIAL_VISOR is not set
1198# CONFIG_USB_SERIAL_IPAQ is not set
1199# CONFIG_USB_SERIAL_IR is not set
1200# CONFIG_USB_SERIAL_EDGEPORT is not set
1201# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
1202# CONFIG_USB_SERIAL_GARMIN is not set
1203# CONFIG_USB_SERIAL_IPW is not set
1204# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
1205# CONFIG_USB_SERIAL_KEYSPAN is not set
1206# CONFIG_USB_SERIAL_KLSI is not set
1207# CONFIG_USB_SERIAL_KOBIL_SCT is not set
1208# CONFIG_USB_SERIAL_MCT_U232 is not set
1209# CONFIG_USB_SERIAL_MOS7720 is not set
1210# CONFIG_USB_SERIAL_MOS7840 is not set
1211# CONFIG_USB_SERIAL_NAVMAN is not set
1212# CONFIG_USB_SERIAL_PL2303 is not set
1213# CONFIG_USB_SERIAL_HP4X is not set
1214# CONFIG_USB_SERIAL_SAFE is not set
1215# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
1216# CONFIG_USB_SERIAL_TI is not set
1217# CONFIG_USB_SERIAL_CYBERJACK is not set
1218# CONFIG_USB_SERIAL_XIRCOM is not set
1219# CONFIG_USB_SERIAL_OPTION is not set
1220# CONFIG_USB_SERIAL_OMNINET is not set
1221
1222#
1223# USB Miscellaneous drivers
1224#
1225# CONFIG_USB_EMI62 is not set
1226# CONFIG_USB_EMI26 is not set
1227# CONFIG_USB_ADUTUX is not set
1228# CONFIG_USB_AUERSWALD is not set
1229# CONFIG_USB_RIO500 is not set
1230# CONFIG_USB_LEGOTOWER is not set
1231# CONFIG_USB_LCD is not set
1232# CONFIG_USB_LED is not set
1233# CONFIG_USB_CYPRESS_CY7C63 is not set
1234# CONFIG_USB_CYTHERM is not set
1235# CONFIG_USB_PHIDGET is not set
1236# CONFIG_USB_IDMOUSE is not set
1237# CONFIG_USB_FTDI_ELAN is not set
1238# CONFIG_USB_APPLEDISPLAY is not set
1239# CONFIG_USB_SISUSBVGA is not set
1240# CONFIG_USB_LD is not set
1241# CONFIG_USB_TRANCEVIBRATOR is not set
1242# CONFIG_USB_TEST is not set
1243
1244#
1245# USB DSL modem support
1246#
1247
1248#
1249# USB Gadget Support
1250#
1251# CONFIG_USB_GADGET is not set
1252
1253#
1254# MMC/SD Card support
1255#
1256# CONFIG_MMC is not set
1257
1258#
1259# LED devices
1260#
1261# CONFIG_NEW_LEDS is not set
1262
1263#
1264# LED drivers
1265#
1266
1267#
1268# LED Triggers
1269#
1270
1271#
1272# InfiniBand support
1273#
1274# CONFIG_INFINIBAND is not set
1275
1276#
1277# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
1278#
1279
1280#
1281# Real Time Clock
1282#
1283CONFIG_RTC_LIB=y
1284CONFIG_RTC_CLASS=y
1285CONFIG_RTC_HCTOSYS=y
1286CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
1287# CONFIG_RTC_DEBUG is not set
1288
1289#
1290# RTC interfaces
1291#
1292CONFIG_RTC_INTF_SYSFS=y
1293CONFIG_RTC_INTF_PROC=y
1294CONFIG_RTC_INTF_DEV=y
1295# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
1296
1297#
1298# RTC drivers
1299#
1300# CONFIG_RTC_DRV_X1205 is not set
1301# CONFIG_RTC_DRV_DS1307 is not set
1302# CONFIG_RTC_DRV_DS1553 is not set
1303# CONFIG_RTC_DRV_ISL1208 is not set
1304# CONFIG_RTC_DRV_DS1672 is not set
1305# CONFIG_RTC_DRV_DS1742 is not set
1306# CONFIG_RTC_DRV_PCF8563 is not set
1307# CONFIG_RTC_DRV_PCF8583 is not set
1308CONFIG_RTC_DRV_RS5C372=y
1309# CONFIG_RTC_DRV_M48T86 is not set
1310# CONFIG_RTC_DRV_TEST is not set
1311# CONFIG_RTC_DRV_V3020 is not set
1312
1313#
1314# DMA Engine support
1315#
1316# CONFIG_DMA_ENGINE is not set
1317
1318#
1319# DMA Clients
1320#
1321
1322#
1323# DMA Devices
1324#
1325
1326#
1327# File systems
1328#
1329CONFIG_EXT2_FS=y
1330# CONFIG_EXT2_FS_XATTR is not set
1331# CONFIG_EXT2_FS_XIP is not set
1332CONFIG_EXT3_FS=y
1333CONFIG_EXT3_FS_XATTR=y
1334# CONFIG_EXT3_FS_POSIX_ACL is not set
1335# CONFIG_EXT3_FS_SECURITY is not set
1336# CONFIG_EXT4DEV_FS is not set
1337CONFIG_JBD=y
1338# CONFIG_JBD_DEBUG is not set
1339CONFIG_FS_MBCACHE=y
1340# CONFIG_REISERFS_FS is not set
1341# CONFIG_JFS_FS is not set
1342CONFIG_FS_POSIX_ACL=y
1343# CONFIG_XFS_FS is not set
1344# CONFIG_GFS2_FS is not set
1345# CONFIG_OCFS2_FS is not set
1346# CONFIG_MINIX_FS is not set
1347# CONFIG_ROMFS_FS is not set
1348CONFIG_INOTIFY=y
1349CONFIG_INOTIFY_USER=y
1350# CONFIG_QUOTA is not set
1351CONFIG_DNOTIFY=y
1352# CONFIG_AUTOFS_FS is not set
1353# CONFIG_AUTOFS4_FS is not set
1354# CONFIG_FUSE_FS is not set
1355
1356#
1357# CD-ROM/DVD Filesystems
1358#
1359CONFIG_ISO9660_FS=m
1360CONFIG_JOLIET=y
1361CONFIG_ZISOFS=y
1362CONFIG_ZISOFS_FS=m
1363CONFIG_UDF_FS=m
1364CONFIG_UDF_NLS=y
1365
1366#
1367# DOS/FAT/NT Filesystems
1368#
1369CONFIG_FAT_FS=m
1370CONFIG_MSDOS_FS=m
1371CONFIG_VFAT_FS=m
1372CONFIG_FAT_DEFAULT_CODEPAGE=437
1373CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
1374CONFIG_NTFS_FS=m
1375# CONFIG_NTFS_DEBUG is not set
1376# CONFIG_NTFS_RW is not set
1377
1378#
1379# Pseudo filesystems
1380#
1381CONFIG_PROC_FS=y
1382CONFIG_PROC_KCORE=y
1383CONFIG_PROC_SYSCTL=y
1384CONFIG_SYSFS=y
1385CONFIG_TMPFS=y
1386# CONFIG_TMPFS_POSIX_ACL is not set
1387# CONFIG_HUGETLB_PAGE is not set
1388CONFIG_RAMFS=y
1389# CONFIG_CONFIGFS_FS is not set
1390
1391#
1392# Miscellaneous filesystems
1393#
1394# CONFIG_ADFS_FS is not set
1395# CONFIG_AFFS_FS is not set
1396# CONFIG_HFS_FS is not set
1397# CONFIG_HFSPLUS_FS is not set
1398# CONFIG_BEFS_FS is not set
1399# CONFIG_BFS_FS is not set
1400# CONFIG_EFS_FS is not set
1401# CONFIG_JFFS_FS is not set
1402# CONFIG_JFFS2_FS is not set
1403# CONFIG_CRAMFS is not set
1404# CONFIG_VXFS_FS is not set
1405# CONFIG_HPFS_FS is not set
1406# CONFIG_QNX4FS_FS is not set
1407# CONFIG_SYSV_FS is not set
1408# CONFIG_UFS_FS is not set
1409
1410#
1411# Network File Systems
1412#
1413CONFIG_NFS_FS=y
1414CONFIG_NFS_V3=y
1415CONFIG_NFS_V3_ACL=y
1416CONFIG_NFS_V4=y
1417# CONFIG_NFS_DIRECTIO is not set
1418CONFIG_NFSD=m
1419CONFIG_NFSD_V3=y
1420# CONFIG_NFSD_V3_ACL is not set
1421# CONFIG_NFSD_V4 is not set
1422CONFIG_NFSD_TCP=y
1423CONFIG_ROOT_NFS=y
1424CONFIG_LOCKD=y
1425CONFIG_LOCKD_V4=y
1426CONFIG_EXPORTFS=m
1427CONFIG_NFS_ACL_SUPPORT=y
1428CONFIG_NFS_COMMON=y
1429CONFIG_SUNRPC=y
1430CONFIG_SUNRPC_GSS=y
1431CONFIG_RPCSEC_GSS_KRB5=y
1432# CONFIG_RPCSEC_GSS_SPKM3 is not set
1433# CONFIG_SMB_FS is not set
1434# CONFIG_CIFS is not set
1435# CONFIG_NCP_FS is not set
1436# CONFIG_CODA_FS is not set
1437# CONFIG_AFS_FS is not set
1438# CONFIG_9P_FS is not set
1439
1440#
1441# Partition Types
1442#
1443# CONFIG_PARTITION_ADVANCED is not set
1444CONFIG_MSDOS_PARTITION=y
1445
1446#
1447# Native Language Support
1448#
1449CONFIG_NLS=m
1450CONFIG_NLS_DEFAULT="iso8859-1"
1451CONFIG_NLS_CODEPAGE_437=m
1452# CONFIG_NLS_CODEPAGE_737 is not set
1453# CONFIG_NLS_CODEPAGE_775 is not set
1454# CONFIG_NLS_CODEPAGE_850 is not set
1455# CONFIG_NLS_CODEPAGE_852 is not set
1456# CONFIG_NLS_CODEPAGE_855 is not set
1457# CONFIG_NLS_CODEPAGE_857 is not set
1458# CONFIG_NLS_CODEPAGE_860 is not set
1459# CONFIG_NLS_CODEPAGE_861 is not set
1460# CONFIG_NLS_CODEPAGE_862 is not set
1461# CONFIG_NLS_CODEPAGE_863 is not set
1462# CONFIG_NLS_CODEPAGE_864 is not set
1463# CONFIG_NLS_CODEPAGE_865 is not set
1464# CONFIG_NLS_CODEPAGE_866 is not set
1465# CONFIG_NLS_CODEPAGE_869 is not set
1466# CONFIG_NLS_CODEPAGE_936 is not set
1467# CONFIG_NLS_CODEPAGE_950 is not set
1468# CONFIG_NLS_CODEPAGE_932 is not set
1469# CONFIG_NLS_CODEPAGE_949 is not set
1470# CONFIG_NLS_CODEPAGE_874 is not set
1471# CONFIG_NLS_ISO8859_8 is not set
1472# CONFIG_NLS_CODEPAGE_1250 is not set
1473# CONFIG_NLS_CODEPAGE_1251 is not set
1474# CONFIG_NLS_ASCII is not set
1475CONFIG_NLS_ISO8859_1=m
1476# CONFIG_NLS_ISO8859_2 is not set
1477# CONFIG_NLS_ISO8859_3 is not set
1478# CONFIG_NLS_ISO8859_4 is not set
1479# CONFIG_NLS_ISO8859_5 is not set
1480# CONFIG_NLS_ISO8859_6 is not set
1481# CONFIG_NLS_ISO8859_7 is not set
1482# CONFIG_NLS_ISO8859_9 is not set
1483# CONFIG_NLS_ISO8859_13 is not set
1484# CONFIG_NLS_ISO8859_14 is not set
1485# CONFIG_NLS_ISO8859_15 is not set
1486# CONFIG_NLS_KOI8_R is not set
1487# CONFIG_NLS_KOI8_U is not set
1488CONFIG_NLS_UTF8=m
1489
1490#
1491# Library routines
1492#
1493# CONFIG_CRC_CCITT is not set
1494# CONFIG_CRC16 is not set
1495CONFIG_CRC32=y
1496CONFIG_LIBCRC32C=m
1497CONFIG_ZLIB_INFLATE=m
1498CONFIG_ZLIB_DEFLATE=m
1499CONFIG_PLIST=y
1500
1501#
1502# Instrumentation Support
1503#
1504CONFIG_PROFILING=y
1505CONFIG_OPROFILE=m
1506
1507#
1508# Kernel hacking
1509#
1510# CONFIG_PRINTK_TIME is not set
1511CONFIG_ENABLE_MUST_CHECK=y
1512CONFIG_MAGIC_SYSRQ=y
1513# CONFIG_UNUSED_SYMBOLS is not set
1514CONFIG_DEBUG_KERNEL=y
1515CONFIG_LOG_BUF_SHIFT=14
1516CONFIG_DETECT_SOFTLOCKUP=y
1517# CONFIG_SCHEDSTATS is not set
1518# CONFIG_DEBUG_SLAB is not set
1519# CONFIG_DEBUG_RT_MUTEXES is not set
1520# CONFIG_RT_MUTEX_TESTER is not set
1521# CONFIG_DEBUG_SPINLOCK is not set
1522# CONFIG_DEBUG_MUTEXES is not set
1523# CONFIG_DEBUG_RWSEMS is not set
1524# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
1525# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
1526# CONFIG_DEBUG_KOBJECT is not set
1527# CONFIG_DEBUG_INFO is not set
1528# CONFIG_DEBUG_FS is not set
1529# CONFIG_DEBUG_VM is not set
1530# CONFIG_DEBUG_LIST is not set
1531CONFIG_FORCED_INLINING=y
1532# CONFIG_HEADERS_CHECK is not set
1533# CONFIG_RCU_TORTURE_TEST is not set
1534# CONFIG_DEBUGGER is not set
1535# CONFIG_BDI_SWITCH is not set
1536# CONFIG_BOOTX_TEXT is not set
1537# CONFIG_SERIAL_TEXT_DEBUG is not set
1538# CONFIG_PPC_EARLY_DEBUG is not set
1539
1540#
1541# Security options
1542#
1543# CONFIG_KEYS is not set
1544# CONFIG_SECURITY is not set
1545
1546#
1547# Cryptographic options
1548#
1549CONFIG_CRYPTO=y
1550CONFIG_CRYPTO_ALGAPI=y
1551CONFIG_CRYPTO_BLKCIPHER=y
1552CONFIG_CRYPTO_MANAGER=y
1553# CONFIG_CRYPTO_HMAC is not set
1554# CONFIG_CRYPTO_NULL is not set
1555CONFIG_CRYPTO_MD4=m
1556CONFIG_CRYPTO_MD5=y
1557CONFIG_CRYPTO_SHA1=m
1558# CONFIG_CRYPTO_SHA256 is not set
1559# CONFIG_CRYPTO_SHA512 is not set
1560# CONFIG_CRYPTO_WP512 is not set
1561# CONFIG_CRYPTO_TGR192 is not set
1562CONFIG_CRYPTO_ECB=m
1563CONFIG_CRYPTO_CBC=y
1564CONFIG_CRYPTO_DES=y
1565CONFIG_CRYPTO_BLOWFISH=m
1566CONFIG_CRYPTO_TWOFISH=m
1567CONFIG_CRYPTO_TWOFISH_COMMON=m
1568CONFIG_CRYPTO_SERPENT=m
1569CONFIG_CRYPTO_AES=m
1570# CONFIG_CRYPTO_CAST5 is not set
1571# CONFIG_CRYPTO_CAST6 is not set
1572# CONFIG_CRYPTO_TEA is not set
1573CONFIG_CRYPTO_ARC4=m
1574# CONFIG_CRYPTO_KHAZAD is not set
1575# CONFIG_CRYPTO_ANUBIS is not set
1576CONFIG_CRYPTO_DEFLATE=m
1577CONFIG_CRYPTO_MICHAEL_MIC=m
1578CONFIG_CRYPTO_CRC32C=m
1579# CONFIG_CRYPTO_TEST is not set
1580
1581#
1582# Hardware crypto devices
1583#
diff --git a/arch/powerpc/configs/lite5200_defconfig b/arch/powerpc/configs/lite5200_defconfig
new file mode 100644
index 000000000000..ee7655776d45
--- /dev/null
+++ b/arch/powerpc/configs/lite5200_defconfig
@@ -0,0 +1,931 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.19-rc6
4# Mon Nov 27 11:08:20 2006
5#
6# CONFIG_PPC64 is not set
7CONFIG_PPC32=y
8CONFIG_PPC_MERGE=y
9CONFIG_MMU=y
10CONFIG_GENERIC_HARDIRQS=y
11CONFIG_IRQ_PER_CPU=y
12CONFIG_RWSEM_XCHGADD_ALGORITHM=y
13CONFIG_GENERIC_HWEIGHT=y
14CONFIG_GENERIC_CALIBRATE_DELAY=y
15CONFIG_GENERIC_FIND_NEXT_BIT=y
16CONFIG_PPC=y
17CONFIG_EARLY_PRINTK=y
18CONFIG_GENERIC_NVRAM=y
19CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
20CONFIG_ARCH_MAY_HAVE_PC_FDC=y
21CONFIG_PPC_OF=y
22# CONFIG_PPC_UDBG_16550 is not set
23# CONFIG_GENERIC_TBSYNC is not set
24CONFIG_AUDIT_ARCH=y
25# CONFIG_DEFAULT_UIMAGE is not set
26
27#
28# Processor support
29#
30CONFIG_CLASSIC32=y
31# CONFIG_PPC_52xx is not set
32# CONFIG_PPC_82xx is not set
33# CONFIG_PPC_83xx is not set
34# CONFIG_PPC_85xx is not set
35# CONFIG_PPC_86xx is not set
36# CONFIG_40x is not set
37# CONFIG_44x is not set
38# CONFIG_8xx is not set
39# CONFIG_E200 is not set
40CONFIG_6xx=y
41CONFIG_PPC_FPU=y
42# CONFIG_PPC_DCR_NATIVE is not set
43# CONFIG_PPC_DCR_MMIO is not set
44# CONFIG_ALTIVEC is not set
45CONFIG_PPC_STD_MMU=y
46CONFIG_PPC_STD_MMU_32=y
47# CONFIG_SMP is not set
48CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
49
50#
51# Code maturity level options
52#
53CONFIG_EXPERIMENTAL=y
54CONFIG_BROKEN_ON_SMP=y
55CONFIG_INIT_ENV_ARG_LIMIT=32
56
57#
58# General setup
59#
60CONFIG_LOCALVERSION=""
61CONFIG_LOCALVERSION_AUTO=y
62CONFIG_SWAP=y
63CONFIG_SYSVIPC=y
64# CONFIG_IPC_NS is not set
65# CONFIG_POSIX_MQUEUE is not set
66# CONFIG_BSD_PROCESS_ACCT is not set
67# CONFIG_TASKSTATS is not set
68# CONFIG_UTS_NS is not set
69# CONFIG_AUDIT is not set
70# CONFIG_IKCONFIG is not set
71# CONFIG_RELAY is not set
72CONFIG_INITRAMFS_SOURCE=""
73# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
74CONFIG_SYSCTL=y
75CONFIG_EMBEDDED=y
76# CONFIG_SYSCTL_SYSCALL is not set
77# CONFIG_KALLSYMS is not set
78CONFIG_HOTPLUG=y
79CONFIG_PRINTK=y
80CONFIG_BUG=y
81CONFIG_ELF_CORE=y
82CONFIG_BASE_FULL=y
83CONFIG_FUTEX=y
84# CONFIG_EPOLL is not set
85CONFIG_SHMEM=y
86CONFIG_SLAB=y
87CONFIG_VM_EVENT_COUNTERS=y
88CONFIG_RT_MUTEXES=y
89# CONFIG_TINY_SHMEM is not set
90CONFIG_BASE_SMALL=0
91# CONFIG_SLOB is not set
92
93#
94# Loadable module support
95#
96CONFIG_MODULES=y
97CONFIG_MODULE_UNLOAD=y
98# CONFIG_MODULE_FORCE_UNLOAD is not set
99# CONFIG_MODVERSIONS is not set
100# CONFIG_MODULE_SRCVERSION_ALL is not set
101# CONFIG_KMOD is not set
102
103#
104# Block layer
105#
106CONFIG_BLOCK=y
107# CONFIG_LBD is not set
108# CONFIG_BLK_DEV_IO_TRACE is not set
109# CONFIG_LSF is not set
110
111#
112# IO Schedulers
113#
114CONFIG_IOSCHED_NOOP=y
115CONFIG_IOSCHED_AS=y
116CONFIG_IOSCHED_DEADLINE=y
117CONFIG_IOSCHED_CFQ=y
118CONFIG_DEFAULT_AS=y
119# CONFIG_DEFAULT_DEADLINE is not set
120# CONFIG_DEFAULT_CFQ is not set
121# CONFIG_DEFAULT_NOOP is not set
122CONFIG_DEFAULT_IOSCHED="anticipatory"
123
124#
125# Platform support
126#
127CONFIG_PPC_MULTIPLATFORM=y
128# CONFIG_EMBEDDED6xx is not set
129# CONFIG_APUS is not set
130# CONFIG_PPC_CHRP is not set
131CONFIG_PPC_MPC52xx=y
132# CONFIG_PPC_EFIKA is not set
133CONFIG_PPC_LITE5200=y
134# CONFIG_PPC_PMAC is not set
135# CONFIG_PPC_CELL is not set
136# CONFIG_PPC_CELL_NATIVE is not set
137# CONFIG_PPC_RTAS is not set
138# CONFIG_MMIO_NVRAM is not set
139# CONFIG_PPC_MPC106 is not set
140# CONFIG_PPC_970_NAP is not set
141# CONFIG_PPC_INDIRECT_IO is not set
142# CONFIG_GENERIC_IOMAP is not set
143# CONFIG_CPU_FREQ is not set
144# CONFIG_TAU is not set
145# CONFIG_WANT_EARLY_SERIAL is not set
146# CONFIG_MPIC is not set
147
148#
149# Kernel options
150#
151# CONFIG_HIGHMEM is not set
152# CONFIG_HZ_100 is not set
153CONFIG_HZ_250=y
154# CONFIG_HZ_1000 is not set
155CONFIG_HZ=250
156CONFIG_PREEMPT_NONE=y
157# CONFIG_PREEMPT_VOLUNTARY is not set
158# CONFIG_PREEMPT is not set
159CONFIG_BINFMT_ELF=y
160# CONFIG_BINFMT_MISC is not set
161CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
162# CONFIG_KEXEC is not set
163CONFIG_ARCH_FLATMEM_ENABLE=y
164CONFIG_ARCH_POPULATES_NODE_MAP=y
165CONFIG_SELECT_MEMORY_MODEL=y
166CONFIG_FLATMEM_MANUAL=y
167# CONFIG_DISCONTIGMEM_MANUAL is not set
168# CONFIG_SPARSEMEM_MANUAL is not set
169CONFIG_FLATMEM=y
170CONFIG_FLAT_NODE_MEM_MAP=y
171# CONFIG_SPARSEMEM_STATIC is not set
172CONFIG_SPLIT_PTLOCK_CPUS=4
173# CONFIG_RESOURCES_64BIT is not set
174CONFIG_PROC_DEVICETREE=y
175# CONFIG_CMDLINE_BOOL is not set
176CONFIG_PM=y
177# CONFIG_PM_LEGACY is not set
178# CONFIG_PM_DEBUG is not set
179# CONFIG_PM_SYSFS_DEPRECATED is not set
180# CONFIG_SOFTWARE_SUSPEND is not set
181CONFIG_SECCOMP=y
182CONFIG_ISA_DMA_API=y
183
184#
185# Bus options
186#
187CONFIG_GENERIC_ISA_DMA=y
188# CONFIG_MPIC_WEIRD is not set
189# CONFIG_PPC_I8259 is not set
190# CONFIG_PPC_INDIRECT_PCI is not set
191CONFIG_PCI=y
192CONFIG_PCI_DOMAINS=y
193# CONFIG_PCIEPORTBUS is not set
194# CONFIG_PCI_DEBUG is not set
195
196#
197# PCCARD (PCMCIA/CardBus) support
198#
199# CONFIG_PCCARD is not set
200
201#
202# PCI Hotplug Support
203#
204# CONFIG_HOTPLUG_PCI is not set
205
206#
207# Advanced setup
208#
209# CONFIG_ADVANCED_OPTIONS is not set
210
211#
212# Default settings for advanced configuration options are used
213#
214CONFIG_HIGHMEM_START=0xfe000000
215CONFIG_LOWMEM_SIZE=0x30000000
216CONFIG_KERNEL_START=0xc0000000
217CONFIG_TASK_SIZE=0x80000000
218CONFIG_BOOT_LOAD=0x00800000
219
220#
221# Networking
222#
223CONFIG_NET=y
224
225#
226# Networking options
227#
228# CONFIG_NETDEBUG is not set
229CONFIG_PACKET=y
230# CONFIG_PACKET_MMAP is not set
231CONFIG_UNIX=y
232CONFIG_XFRM=y
233CONFIG_XFRM_USER=m
234# CONFIG_XFRM_SUB_POLICY is not set
235# CONFIG_NET_KEY is not set
236CONFIG_INET=y
237CONFIG_IP_MULTICAST=y
238# CONFIG_IP_ADVANCED_ROUTER is not set
239CONFIG_IP_FIB_HASH=y
240CONFIG_IP_PNP=y
241CONFIG_IP_PNP_DHCP=y
242CONFIG_IP_PNP_BOOTP=y
243# CONFIG_IP_PNP_RARP is not set
244# CONFIG_NET_IPIP is not set
245# CONFIG_NET_IPGRE is not set
246# CONFIG_IP_MROUTE is not set
247# CONFIG_ARPD is not set
248CONFIG_SYN_COOKIES=y
249# CONFIG_INET_AH is not set
250# CONFIG_INET_ESP is not set
251# CONFIG_INET_IPCOMP is not set
252# CONFIG_INET_XFRM_TUNNEL is not set
253# CONFIG_INET_TUNNEL is not set
254CONFIG_INET_XFRM_MODE_TRANSPORT=y
255CONFIG_INET_XFRM_MODE_TUNNEL=y
256CONFIG_INET_XFRM_MODE_BEET=y
257CONFIG_INET_DIAG=y
258CONFIG_INET_TCP_DIAG=y
259# CONFIG_TCP_CONG_ADVANCED is not set
260CONFIG_TCP_CONG_CUBIC=y
261CONFIG_DEFAULT_TCP_CONG="cubic"
262# CONFIG_IPV6 is not set
263# CONFIG_INET6_XFRM_TUNNEL is not set
264# CONFIG_INET6_TUNNEL is not set
265# CONFIG_NETWORK_SECMARK is not set
266# CONFIG_NETFILTER is not set
267
268#
269# DCCP Configuration (EXPERIMENTAL)
270#
271# CONFIG_IP_DCCP is not set
272
273#
274# SCTP Configuration (EXPERIMENTAL)
275#
276# CONFIG_IP_SCTP is not set
277
278#
279# TIPC Configuration (EXPERIMENTAL)
280#
281# CONFIG_TIPC is not set
282# CONFIG_ATM is not set
283# CONFIG_BRIDGE is not set
284# CONFIG_VLAN_8021Q is not set
285# CONFIG_DECNET is not set
286# CONFIG_LLC2 is not set
287# CONFIG_IPX is not set
288# CONFIG_ATALK is not set
289# CONFIG_X25 is not set
290# CONFIG_LAPB is not set
291# CONFIG_ECONET is not set
292# CONFIG_WAN_ROUTER is not set
293
294#
295# QoS and/or fair queueing
296#
297# CONFIG_NET_SCHED is not set
298
299#
300# Network testing
301#
302# CONFIG_NET_PKTGEN is not set
303# CONFIG_HAMRADIO is not set
304# CONFIG_IRDA is not set
305# CONFIG_BT is not set
306# CONFIG_IEEE80211 is not set
307
308#
309# Device Drivers
310#
311
312#
313# Generic Driver Options
314#
315CONFIG_STANDALONE=y
316CONFIG_PREVENT_FIRMWARE_BUILD=y
317# CONFIG_FW_LOADER is not set
318# CONFIG_DEBUG_DRIVER is not set
319# CONFIG_SYS_HYPERVISOR is not set
320
321#
322# Connector - unified userspace <-> kernelspace linker
323#
324# CONFIG_CONNECTOR is not set
325
326#
327# Memory Technology Devices (MTD)
328#
329# CONFIG_MTD is not set
330
331#
332# Parallel port support
333#
334# CONFIG_PARPORT is not set
335
336#
337# Plug and Play support
338#
339
340#
341# Block devices
342#
343# CONFIG_BLK_DEV_FD is not set
344# CONFIG_BLK_CPQ_DA is not set
345# CONFIG_BLK_CPQ_CISS_DA is not set
346# CONFIG_BLK_DEV_DAC960 is not set
347# CONFIG_BLK_DEV_UMEM is not set
348# CONFIG_BLK_DEV_COW_COMMON is not set
349CONFIG_BLK_DEV_LOOP=y
350# CONFIG_BLK_DEV_CRYPTOLOOP is not set
351# CONFIG_BLK_DEV_NBD is not set
352# CONFIG_BLK_DEV_SX8 is not set
353CONFIG_BLK_DEV_RAM=y
354CONFIG_BLK_DEV_RAM_COUNT=16
355CONFIG_BLK_DEV_RAM_SIZE=32768
356CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
357CONFIG_BLK_DEV_INITRD=y
358# CONFIG_CDROM_PKTCDVD is not set
359# CONFIG_ATA_OVER_ETH is not set
360
361#
362# Misc devices
363#
364# CONFIG_SGI_IOC4 is not set
365# CONFIG_TIFM_CORE is not set
366
367#
368# ATA/ATAPI/MFM/RLL support
369#
370# CONFIG_IDE is not set
371
372#
373# SCSI device support
374#
375# CONFIG_RAID_ATTRS is not set
376CONFIG_SCSI=y
377# CONFIG_SCSI_NETLINK is not set
378# CONFIG_SCSI_PROC_FS is not set
379
380#
381# SCSI support type (disk, tape, CD-ROM)
382#
383# CONFIG_BLK_DEV_SD is not set
384# CONFIG_CHR_DEV_ST is not set
385# CONFIG_CHR_DEV_OSST is not set
386# CONFIG_BLK_DEV_SR is not set
387# CONFIG_CHR_DEV_SG is not set
388# CONFIG_CHR_DEV_SCH is not set
389
390#
391# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
392#
393# CONFIG_SCSI_MULTI_LUN is not set
394# CONFIG_SCSI_CONSTANTS is not set
395# CONFIG_SCSI_LOGGING is not set
396
397#
398# SCSI Transports
399#
400# CONFIG_SCSI_SPI_ATTRS is not set
401# CONFIG_SCSI_FC_ATTRS is not set
402# CONFIG_SCSI_ISCSI_ATTRS is not set
403# CONFIG_SCSI_SAS_ATTRS is not set
404# CONFIG_SCSI_SAS_LIBSAS is not set
405
406#
407# SCSI low-level drivers
408#
409# CONFIG_ISCSI_TCP is not set
410# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
411# CONFIG_SCSI_3W_9XXX is not set
412# CONFIG_SCSI_ACARD is not set
413# CONFIG_SCSI_AACRAID is not set
414# CONFIG_SCSI_AIC7XXX is not set
415# CONFIG_SCSI_AIC7XXX_OLD is not set
416# CONFIG_SCSI_AIC79XX is not set
417# CONFIG_SCSI_AIC94XX is not set
418# CONFIG_SCSI_DPT_I2O is not set
419# CONFIG_SCSI_ARCMSR is not set
420# CONFIG_MEGARAID_NEWGEN is not set
421# CONFIG_MEGARAID_LEGACY is not set
422# CONFIG_MEGARAID_SAS is not set
423# CONFIG_SCSI_HPTIOP is not set
424# CONFIG_SCSI_BUSLOGIC is not set
425# CONFIG_SCSI_DMX3191D is not set
426# CONFIG_SCSI_EATA is not set
427# CONFIG_SCSI_FUTURE_DOMAIN is not set
428# CONFIG_SCSI_GDTH is not set
429# CONFIG_SCSI_IPS is not set
430# CONFIG_SCSI_INITIO is not set
431# CONFIG_SCSI_INIA100 is not set
432# CONFIG_SCSI_STEX is not set
433# CONFIG_SCSI_SYM53C8XX_2 is not set
434# CONFIG_SCSI_IPR is not set
435# CONFIG_SCSI_QLOGIC_1280 is not set
436# CONFIG_SCSI_QLA_FC is not set
437# CONFIG_SCSI_QLA_ISCSI is not set
438# CONFIG_SCSI_LPFC is not set
439# CONFIG_SCSI_DC395x is not set
440# CONFIG_SCSI_DC390T is not set
441# CONFIG_SCSI_NSP32 is not set
442# CONFIG_SCSI_DEBUG is not set
443
444#
445# Serial ATA (prod) and Parallel ATA (experimental) drivers
446#
447CONFIG_ATA=y
448# CONFIG_SATA_AHCI is not set
449# CONFIG_SATA_SVW is not set
450# CONFIG_ATA_PIIX is not set
451# CONFIG_SATA_MV is not set
452# CONFIG_SATA_NV is not set
453# CONFIG_PDC_ADMA is not set
454# CONFIG_SATA_QSTOR is not set
455# CONFIG_SATA_PROMISE is not set
456# CONFIG_SATA_SX4 is not set
457# CONFIG_SATA_SIL is not set
458# CONFIG_SATA_SIL24 is not set
459# CONFIG_SATA_SIS is not set
460# CONFIG_SATA_ULI is not set
461# CONFIG_SATA_VIA is not set
462# CONFIG_SATA_VITESSE is not set
463# CONFIG_PATA_ALI is not set
464# CONFIG_PATA_AMD is not set
465# CONFIG_PATA_ARTOP is not set
466# CONFIG_PATA_ATIIXP is not set
467# CONFIG_PATA_CMD64X is not set
468# CONFIG_PATA_CS5520 is not set
469# CONFIG_PATA_CS5530 is not set
470# CONFIG_PATA_CYPRESS is not set
471# CONFIG_PATA_EFAR is not set
472# CONFIG_ATA_GENERIC is not set
473# CONFIG_PATA_HPT366 is not set
474# CONFIG_PATA_HPT37X is not set
475# CONFIG_PATA_HPT3X2N is not set
476# CONFIG_PATA_HPT3X3 is not set
477# CONFIG_PATA_IT821X is not set
478# CONFIG_PATA_JMICRON is not set
479# CONFIG_PATA_TRIFLEX is not set
480CONFIG_PATA_MPC52xx=y
481# CONFIG_PATA_MPIIX is not set
482# CONFIG_PATA_OLDPIIX is not set
483# CONFIG_PATA_NETCELL is not set
484# CONFIG_PATA_NS87410 is not set
485# CONFIG_PATA_OPTI is not set
486# CONFIG_PATA_OPTIDMA is not set
487# CONFIG_PATA_PDC_OLD is not set
488# CONFIG_PATA_RADISYS is not set
489# CONFIG_PATA_RZ1000 is not set
490# CONFIG_PATA_SC1200 is not set
491# CONFIG_PATA_SERVERWORKS is not set
492# CONFIG_PATA_PDC2027X is not set
493# CONFIG_PATA_SIL680 is not set
494# CONFIG_PATA_SIS is not set
495# CONFIG_PATA_VIA is not set
496# CONFIG_PATA_WINBOND is not set
497
498#
499# Multi-device support (RAID and LVM)
500#
501# CONFIG_MD is not set
502
503#
504# Fusion MPT device support
505#
506# CONFIG_FUSION is not set
507# CONFIG_FUSION_SPI is not set
508# CONFIG_FUSION_FC is not set
509# CONFIG_FUSION_SAS is not set
510
511#
512# IEEE 1394 (FireWire) support
513#
514# CONFIG_IEEE1394 is not set
515
516#
517# I2O device support
518#
519# CONFIG_I2O is not set
520
521#
522# Macintosh device drivers
523#
524# CONFIG_WINDFARM is not set
525
526#
527# Network device support
528#
529CONFIG_NETDEVICES=y
530# CONFIG_DUMMY is not set
531# CONFIG_BONDING is not set
532# CONFIG_EQUALIZER is not set
533# CONFIG_TUN is not set
534
535#
536# ARCnet devices
537#
538# CONFIG_ARCNET is not set
539
540#
541# PHY device support
542#
543
544#
545# Ethernet (10 or 100Mbit)
546#
547# CONFIG_NET_ETHERNET is not set
548
549#
550# Ethernet (1000 Mbit)
551#
552# CONFIG_ACENIC is not set
553# CONFIG_DL2K is not set
554# CONFIG_E1000 is not set
555# CONFIG_NS83820 is not set
556# CONFIG_HAMACHI is not set
557# CONFIG_YELLOWFIN is not set
558# CONFIG_R8169 is not set
559# CONFIG_SIS190 is not set
560# CONFIG_SKGE is not set
561# CONFIG_SKY2 is not set
562# CONFIG_SK98LIN is not set
563# CONFIG_TIGON3 is not set
564# CONFIG_BNX2 is not set
565# CONFIG_MV643XX_ETH is not set
566# CONFIG_QLA3XXX is not set
567
568#
569# Ethernet (10000 Mbit)
570#
571# CONFIG_CHELSIO_T1 is not set
572# CONFIG_IXGB is not set
573# CONFIG_S2IO is not set
574# CONFIG_MYRI10GE is not set
575
576#
577# Token Ring devices
578#
579# CONFIG_TR is not set
580
581#
582# Wireless LAN (non-hamradio)
583#
584# CONFIG_NET_RADIO is not set
585
586#
587# Wan interfaces
588#
589# CONFIG_WAN is not set
590# CONFIG_FDDI is not set
591# CONFIG_HIPPI is not set
592# CONFIG_PPP is not set
593# CONFIG_SLIP is not set
594# CONFIG_NET_FC is not set
595# CONFIG_SHAPER is not set
596# CONFIG_NETCONSOLE is not set
597# CONFIG_NETPOLL is not set
598# CONFIG_NET_POLL_CONTROLLER is not set
599
600#
601# ISDN subsystem
602#
603# CONFIG_ISDN is not set
604
605#
606# Telephony Support
607#
608# CONFIG_PHONE is not set
609
610#
611# Input device support
612#
613# CONFIG_INPUT is not set
614
615#
616# Hardware I/O ports
617#
618# CONFIG_SERIO is not set
619# CONFIG_GAMEPORT is not set
620
621#
622# Character devices
623#
624# CONFIG_VT is not set
625# CONFIG_SERIAL_NONSTANDARD is not set
626
627#
628# Serial drivers
629#
630# CONFIG_SERIAL_8250 is not set
631
632#
633# Non-8250 serial port support
634#
635CONFIG_SERIAL_CORE=y
636CONFIG_SERIAL_CORE_CONSOLE=y
637CONFIG_SERIAL_MPC52xx=y
638CONFIG_SERIAL_MPC52xx_CONSOLE=y
639CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=9600
640# CONFIG_SERIAL_JSM is not set
641CONFIG_UNIX98_PTYS=y
642CONFIG_LEGACY_PTYS=y
643CONFIG_LEGACY_PTY_COUNT=256
644
645#
646# IPMI
647#
648# CONFIG_IPMI_HANDLER is not set
649
650#
651# Watchdog Cards
652#
653# CONFIG_WATCHDOG is not set
654# CONFIG_HW_RANDOM is not set
655# CONFIG_NVRAM is not set
656# CONFIG_GEN_RTC is not set
657# CONFIG_DTLK is not set
658# CONFIG_R3964 is not set
659# CONFIG_APPLICOM is not set
660
661#
662# Ftape, the floppy tape device driver
663#
664# CONFIG_AGP is not set
665# CONFIG_DRM is not set
666# CONFIG_RAW_DRIVER is not set
667
668#
669# TPM devices
670#
671# CONFIG_TCG_TPM is not set
672
673#
674# I2C support
675#
676# CONFIG_I2C is not set
677
678#
679# SPI support
680#
681# CONFIG_SPI is not set
682# CONFIG_SPI_MASTER is not set
683
684#
685# Dallas's 1-wire bus
686#
687# CONFIG_W1 is not set
688
689#
690# Hardware Monitoring support
691#
692# CONFIG_HWMON is not set
693# CONFIG_HWMON_VID is not set
694
695#
696# Multimedia devices
697#
698# CONFIG_VIDEO_DEV is not set
699
700#
701# Digital Video Broadcasting Devices
702#
703# CONFIG_DVB is not set
704
705#
706# Graphics support
707#
708# CONFIG_FIRMWARE_EDID is not set
709# CONFIG_FB is not set
710# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
711
712#
713# Sound
714#
715# CONFIG_SOUND is not set
716
717#
718# USB support
719#
720CONFIG_USB_ARCH_HAS_HCD=y
721CONFIG_USB_ARCH_HAS_OHCI=y
722CONFIG_USB_ARCH_HAS_EHCI=y
723# CONFIG_USB is not set
724
725#
726# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
727#
728
729#
730# USB Gadget Support
731#
732# CONFIG_USB_GADGET is not set
733
734#
735# MMC/SD Card support
736#
737# CONFIG_MMC is not set
738
739#
740# LED devices
741#
742# CONFIG_NEW_LEDS is not set
743
744#
745# LED drivers
746#
747
748#
749# LED Triggers
750#
751
752#
753# InfiniBand support
754#
755# CONFIG_INFINIBAND is not set
756
757#
758# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
759#
760
761#
762# Real Time Clock
763#
764# CONFIG_RTC_CLASS is not set
765
766#
767# DMA Engine support
768#
769# CONFIG_DMA_ENGINE is not set
770
771#
772# DMA Clients
773#
774
775#
776# DMA Devices
777#
778
779#
780# File systems
781#
782CONFIG_EXT2_FS=y
783# CONFIG_EXT2_FS_XATTR is not set
784# CONFIG_EXT2_FS_XIP is not set
785CONFIG_EXT3_FS=y
786CONFIG_EXT3_FS_XATTR=y
787# CONFIG_EXT3_FS_POSIX_ACL is not set
788# CONFIG_EXT3_FS_SECURITY is not set
789# CONFIG_EXT4DEV_FS is not set
790CONFIG_JBD=y
791# CONFIG_JBD_DEBUG is not set
792CONFIG_FS_MBCACHE=y
793# CONFIG_REISERFS_FS is not set
794# CONFIG_JFS_FS is not set
795# CONFIG_FS_POSIX_ACL is not set
796# CONFIG_XFS_FS is not set
797# CONFIG_GFS2_FS is not set
798# CONFIG_OCFS2_FS is not set
799# CONFIG_MINIX_FS is not set
800# CONFIG_ROMFS_FS is not set
801CONFIG_INOTIFY=y
802CONFIG_INOTIFY_USER=y
803# CONFIG_QUOTA is not set
804CONFIG_DNOTIFY=y
805# CONFIG_AUTOFS_FS is not set
806# CONFIG_AUTOFS4_FS is not set
807# CONFIG_FUSE_FS is not set
808
809#
810# CD-ROM/DVD Filesystems
811#
812# CONFIG_ISO9660_FS is not set
813# CONFIG_UDF_FS is not set
814
815#
816# DOS/FAT/NT Filesystems
817#
818# CONFIG_MSDOS_FS is not set
819# CONFIG_VFAT_FS is not set
820# CONFIG_NTFS_FS is not set
821
822#
823# Pseudo filesystems
824#
825CONFIG_PROC_FS=y
826CONFIG_PROC_KCORE=y
827CONFIG_PROC_SYSCTL=y
828CONFIG_SYSFS=y
829CONFIG_TMPFS=y
830# CONFIG_TMPFS_POSIX_ACL is not set
831# CONFIG_HUGETLB_PAGE is not set
832CONFIG_RAMFS=y
833# CONFIG_CONFIGFS_FS is not set
834
835#
836# Miscellaneous filesystems
837#
838# CONFIG_ADFS_FS is not set
839# CONFIG_AFFS_FS is not set
840# CONFIG_HFS_FS is not set
841# CONFIG_HFSPLUS_FS is not set
842# CONFIG_BEFS_FS is not set
843# CONFIG_BFS_FS is not set
844# CONFIG_EFS_FS is not set
845# CONFIG_CRAMFS is not set
846# CONFIG_VXFS_FS is not set
847# CONFIG_HPFS_FS is not set
848# CONFIG_QNX4FS_FS is not set
849# CONFIG_SYSV_FS is not set
850# CONFIG_UFS_FS is not set
851
852#
853# Network File Systems
854#
855# CONFIG_NFS_FS is not set
856# CONFIG_NFSD is not set
857# CONFIG_SMB_FS is not set
858# CONFIG_CIFS is not set
859# CONFIG_NCP_FS is not set
860# CONFIG_CODA_FS is not set
861# CONFIG_AFS_FS is not set
862# CONFIG_9P_FS is not set
863
864#
865# Partition Types
866#
867# CONFIG_PARTITION_ADVANCED is not set
868CONFIG_MSDOS_PARTITION=y
869
870#
871# Native Language Support
872#
873# CONFIG_NLS is not set
874
875#
876# Library routines
877#
878# CONFIG_CRC_CCITT is not set
879# CONFIG_CRC16 is not set
880# CONFIG_CRC32 is not set
881# CONFIG_LIBCRC32C is not set
882CONFIG_PLIST=y
883
884#
885# Instrumentation Support
886#
887# CONFIG_PROFILING is not set
888
889#
890# Kernel hacking
891#
892CONFIG_PRINTK_TIME=y
893CONFIG_ENABLE_MUST_CHECK=y
894# CONFIG_MAGIC_SYSRQ is not set
895# CONFIG_UNUSED_SYMBOLS is not set
896CONFIG_DEBUG_KERNEL=y
897CONFIG_LOG_BUF_SHIFT=14
898CONFIG_DETECT_SOFTLOCKUP=y
899# CONFIG_SCHEDSTATS is not set
900# CONFIG_DEBUG_SLAB is not set
901# CONFIG_DEBUG_RT_MUTEXES is not set
902# CONFIG_RT_MUTEX_TESTER is not set
903# CONFIG_DEBUG_SPINLOCK is not set
904# CONFIG_DEBUG_MUTEXES is not set
905# CONFIG_DEBUG_RWSEMS is not set
906# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
907# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
908# CONFIG_DEBUG_KOBJECT is not set
909CONFIG_DEBUG_INFO=y
910# CONFIG_DEBUG_FS is not set
911# CONFIG_DEBUG_VM is not set
912# CONFIG_DEBUG_LIST is not set
913CONFIG_FORCED_INLINING=y
914# CONFIG_HEADERS_CHECK is not set
915# CONFIG_RCU_TORTURE_TEST is not set
916# CONFIG_DEBUGGER is not set
917# CONFIG_BDI_SWITCH is not set
918# CONFIG_BOOTX_TEXT is not set
919# CONFIG_SERIAL_TEXT_DEBUG is not set
920# CONFIG_PPC_EARLY_DEBUG is not set
921
922#
923# Security options
924#
925# CONFIG_KEYS is not set
926# CONFIG_SECURITY is not set
927
928#
929# Cryptographic options
930#
931# CONFIG_CRYPTO is not set
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index be11df7c11aa..1c009651f925 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -1386,8 +1386,8 @@ CONFIG_INOTIFY=y
1386CONFIG_INOTIFY_USER=y 1386CONFIG_INOTIFY_USER=y
1387# CONFIG_QUOTA is not set 1387# CONFIG_QUOTA is not set
1388CONFIG_DNOTIFY=y 1388CONFIG_DNOTIFY=y
1389CONFIG_AUTOFS_FS=y 1389# CONFIG_AUTOFS_FS is not set
1390# CONFIG_AUTOFS4_FS is not set 1390CONFIG_AUTOFS4_FS=m
1391# CONFIG_FUSE_FS is not set 1391# CONFIG_FUSE_FS is not set
1392 1392
1393# 1393#
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig
new file mode 100644
index 000000000000..f2d888e014a9
--- /dev/null
+++ b/arch/powerpc/configs/ps3_defconfig
@@ -0,0 +1,837 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.19-rc6
4# Tue Nov 21 19:38:53 2006
5#
6CONFIG_PPC64=y
7CONFIG_64BIT=y
8CONFIG_PPC_MERGE=y
9CONFIG_MMU=y
10CONFIG_GENERIC_HARDIRQS=y
11CONFIG_IRQ_PER_CPU=y
12CONFIG_RWSEM_XCHGADD_ALGORITHM=y
13CONFIG_GENERIC_HWEIGHT=y
14CONFIG_GENERIC_CALIBRATE_DELAY=y
15CONFIG_GENERIC_FIND_NEXT_BIT=y
16CONFIG_PPC=y
17CONFIG_EARLY_PRINTK=y
18CONFIG_COMPAT=y
19CONFIG_SYSVIPC_COMPAT=y
20CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
21CONFIG_ARCH_MAY_HAVE_PC_FDC=y
22CONFIG_PPC_OF=y
23# CONFIG_PPC_UDBG_16550 is not set
24# CONFIG_GENERIC_TBSYNC is not set
25CONFIG_AUDIT_ARCH=y
26# CONFIG_DEFAULT_UIMAGE is not set
27
28#
29# Processor support
30#
31# CONFIG_POWER4_ONLY is not set
32CONFIG_POWER3=y
33CONFIG_POWER4=y
34CONFIG_PPC_FPU=y
35# CONFIG_PPC_DCR_NATIVE is not set
36# CONFIG_PPC_DCR_MMIO is not set
37# CONFIG_PPC_OF_PLATFORM_PCI is not set
38CONFIG_ALTIVEC=y
39CONFIG_PPC_STD_MMU=y
40CONFIG_VIRT_CPU_ACCOUNTING=y
41CONFIG_SMP=y
42CONFIG_NR_CPUS=2
43CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
44
45#
46# Code maturity level options
47#
48CONFIG_EXPERIMENTAL=y
49CONFIG_LOCK_KERNEL=y
50CONFIG_INIT_ENV_ARG_LIMIT=32
51
52#
53# General setup
54#
55CONFIG_LOCALVERSION=""
56CONFIG_LOCALVERSION_AUTO=y
57CONFIG_SWAP=y
58CONFIG_SYSVIPC=y
59# CONFIG_IPC_NS is not set
60# CONFIG_POSIX_MQUEUE is not set
61# CONFIG_BSD_PROCESS_ACCT is not set
62# CONFIG_TASKSTATS is not set
63# CONFIG_UTS_NS is not set
64# CONFIG_AUDIT is not set
65# CONFIG_IKCONFIG is not set
66# CONFIG_CPUSETS is not set
67# CONFIG_RELAY is not set
68CONFIG_INITRAMFS_SOURCE=""
69# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
70CONFIG_SYSCTL=y
71CONFIG_EMBEDDED=y
72# CONFIG_SYSCTL_SYSCALL is not set
73CONFIG_KALLSYMS=y
74CONFIG_KALLSYMS_ALL=y
75CONFIG_KALLSYMS_EXTRA_PASS=y
76CONFIG_HOTPLUG=y
77CONFIG_PRINTK=y
78CONFIG_BUG=y
79CONFIG_ELF_CORE=y
80CONFIG_BASE_FULL=y
81CONFIG_FUTEX=y
82CONFIG_EPOLL=y
83CONFIG_SHMEM=y
84CONFIG_SLAB=y
85CONFIG_VM_EVENT_COUNTERS=y
86CONFIG_RT_MUTEXES=y
87# CONFIG_TINY_SHMEM is not set
88CONFIG_BASE_SMALL=0
89# CONFIG_SLOB is not set
90
91#
92# Loadable module support
93#
94CONFIG_MODULES=y
95CONFIG_MODULE_UNLOAD=y
96# CONFIG_MODULE_FORCE_UNLOAD is not set
97# CONFIG_MODVERSIONS is not set
98# CONFIG_MODULE_SRCVERSION_ALL is not set
99CONFIG_KMOD=y
100CONFIG_STOP_MACHINE=y
101
102#
103# Block layer
104#
105CONFIG_BLOCK=y
106# CONFIG_BLK_DEV_IO_TRACE is not set
107
108#
109# IO Schedulers
110#
111CONFIG_IOSCHED_NOOP=y
112CONFIG_IOSCHED_AS=y
113CONFIG_IOSCHED_DEADLINE=y
114CONFIG_IOSCHED_CFQ=y
115CONFIG_DEFAULT_AS=y
116# CONFIG_DEFAULT_DEADLINE is not set
117# CONFIG_DEFAULT_CFQ is not set
118# CONFIG_DEFAULT_NOOP is not set
119CONFIG_DEFAULT_IOSCHED="anticipatory"
120
121#
122# Platform support
123#
124CONFIG_PPC_MULTIPLATFORM=y
125# CONFIG_EMBEDDED6xx is not set
126# CONFIG_APUS is not set
127# CONFIG_PPC_PSERIES is not set
128# CONFIG_PPC_ISERIES is not set
129# CONFIG_PPC_PMAC is not set
130# CONFIG_PPC_MAPLE is not set
131# CONFIG_PPC_PASEMI is not set
132CONFIG_PPC_CELL=y
133# CONFIG_PPC_CELL_NATIVE is not set
134# CONFIG_PPC_IBM_CELL_BLADE is not set
135CONFIG_PPC_PS3=y
136# CONFIG_U3_DART is not set
137# CONFIG_PPC_RTAS is not set
138# CONFIG_MMIO_NVRAM is not set
139# CONFIG_PPC_MPC106 is not set
140# CONFIG_PPC_970_NAP is not set
141# CONFIG_PPC_INDIRECT_IO is not set
142# CONFIG_GENERIC_IOMAP is not set
143# CONFIG_CPU_FREQ is not set
144# CONFIG_WANT_EARLY_SERIAL is not set
145# CONFIG_MPIC is not set
146
147#
148# Cell Broadband Engine options
149#
150CONFIG_SPU_FS=y
151CONFIG_SPU_BASE=y
152# CONFIG_CBE_RAS is not set
153
154#
155# PS3 Platform Options
156#
157CONFIG_PS3_HTAB_SIZE=20
158CONFIG_PS3_DYNAMIC_DMA=y
159CONFIG_PS3_USE_LPAR_ADDR=y
160
161#
162# Kernel options
163#
164# CONFIG_HZ_100 is not set
165CONFIG_HZ_250=y
166# CONFIG_HZ_1000 is not set
167CONFIG_HZ=250
168CONFIG_PREEMPT_NONE=y
169# CONFIG_PREEMPT_VOLUNTARY is not set
170# CONFIG_PREEMPT is not set
171# CONFIG_PREEMPT_BKL is not set
172CONFIG_BINFMT_ELF=y
173CONFIG_BINFMT_MISC=y
174CONFIG_FORCE_MAX_ZONEORDER=9
175# CONFIG_IOMMU_VMERGE is not set
176CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
177# CONFIG_KEXEC is not set
178# CONFIG_CRASH_DUMP is not set
179# CONFIG_IRQ_ALL_CPUS is not set
180# CONFIG_NUMA is not set
181CONFIG_ARCH_SELECT_MEMORY_MODEL=y
182CONFIG_ARCH_FLATMEM_ENABLE=y
183CONFIG_ARCH_SPARSEMEM_ENABLE=y
184CONFIG_ARCH_SPARSEMEM_DEFAULT=y
185CONFIG_ARCH_POPULATES_NODE_MAP=y
186CONFIG_SELECT_MEMORY_MODEL=y
187# CONFIG_FLATMEM_MANUAL is not set
188# CONFIG_DISCONTIGMEM_MANUAL is not set
189CONFIG_SPARSEMEM_MANUAL=y
190CONFIG_SPARSEMEM=y
191CONFIG_HAVE_MEMORY_PRESENT=y
192# CONFIG_SPARSEMEM_STATIC is not set
193CONFIG_SPARSEMEM_EXTREME=y
194CONFIG_MEMORY_HOTPLUG=y
195CONFIG_MEMORY_HOTPLUG_SPARSE=y
196CONFIG_SPLIT_PTLOCK_CPUS=4
197CONFIG_RESOURCES_64BIT=y
198CONFIG_ARCH_MEMORY_PROBE=y
199CONFIG_PPC_64K_PAGES=y
200# CONFIG_SCHED_SMT is not set
201CONFIG_PROC_DEVICETREE=y
202CONFIG_CMDLINE_BOOL=y
203CONFIG_CMDLINE="root=/dev/nfs rw ip=dhcp"
204# CONFIG_PM is not set
205# CONFIG_SECCOMP is not set
206CONFIG_ISA_DMA_API=y
207
208#
209# Bus options
210#
211CONFIG_GENERIC_ISA_DMA=y
212# CONFIG_MPIC_WEIRD is not set
213# CONFIG_PPC_I8259 is not set
214# CONFIG_PCI is not set
215# CONFIG_PCI_DOMAINS is not set
216
217#
218# PCCARD (PCMCIA/CardBus) support
219#
220# CONFIG_PCCARD is not set
221
222#
223# PCI Hotplug Support
224#
225CONFIG_KERNEL_START=0xc000000000000000
226
227#
228# Networking
229#
230CONFIG_NET=y
231
232#
233# Networking options
234#
235# CONFIG_NETDEBUG is not set
236# CONFIG_PACKET is not set
237CONFIG_UNIX=y
238# CONFIG_NET_KEY is not set
239CONFIG_INET=y
240# CONFIG_IP_MULTICAST is not set
241# CONFIG_IP_ADVANCED_ROUTER is not set
242CONFIG_IP_FIB_HASH=y
243CONFIG_IP_PNP=y
244CONFIG_IP_PNP_DHCP=y
245# CONFIG_IP_PNP_BOOTP is not set
246# CONFIG_IP_PNP_RARP is not set
247# CONFIG_NET_IPIP is not set
248# CONFIG_NET_IPGRE is not set
249# CONFIG_ARPD is not set
250# CONFIG_SYN_COOKIES is not set
251# CONFIG_INET_AH is not set
252# CONFIG_INET_ESP is not set
253# CONFIG_INET_IPCOMP is not set
254# CONFIG_INET_XFRM_TUNNEL is not set
255# CONFIG_INET_TUNNEL is not set
256# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
257# CONFIG_INET_XFRM_MODE_TUNNEL is not set
258# CONFIG_INET_XFRM_MODE_BEET is not set
259# CONFIG_INET_DIAG is not set
260# CONFIG_TCP_CONG_ADVANCED is not set
261CONFIG_TCP_CONG_CUBIC=y
262CONFIG_DEFAULT_TCP_CONG="cubic"
263# CONFIG_IPV6 is not set
264# CONFIG_INET6_XFRM_TUNNEL is not set
265# CONFIG_INET6_TUNNEL is not set
266# CONFIG_NETWORK_SECMARK is not set
267# CONFIG_NETFILTER is not set
268
269#
270# DCCP Configuration (EXPERIMENTAL)
271#
272# CONFIG_IP_DCCP is not set
273
274#
275# SCTP Configuration (EXPERIMENTAL)
276#
277# CONFIG_IP_SCTP is not set
278
279#
280# TIPC Configuration (EXPERIMENTAL)
281#
282# CONFIG_TIPC is not set
283# CONFIG_ATM is not set
284# CONFIG_BRIDGE is not set
285# CONFIG_VLAN_8021Q is not set
286# CONFIG_DECNET is not set
287# CONFIG_LLC2 is not set
288# CONFIG_IPX is not set
289# CONFIG_ATALK is not set
290# CONFIG_X25 is not set
291# CONFIG_LAPB is not set
292# CONFIG_ECONET is not set
293# CONFIG_WAN_ROUTER is not set
294
295#
296# QoS and/or fair queueing
297#
298# CONFIG_NET_SCHED is not set
299
300#
301# Network testing
302#
303# CONFIG_NET_PKTGEN is not set
304# CONFIG_HAMRADIO is not set
305# CONFIG_IRDA is not set
306# CONFIG_BT is not set
307# CONFIG_IEEE80211 is not set
308
309#
310# Device Drivers
311#
312
313#
314# Generic Driver Options
315#
316CONFIG_STANDALONE=y
317CONFIG_PREVENT_FIRMWARE_BUILD=y
318# CONFIG_FW_LOADER is not set
319# CONFIG_DEBUG_DRIVER is not set
320# CONFIG_SYS_HYPERVISOR is not set
321
322#
323# Connector - unified userspace <-> kernelspace linker
324#
325# CONFIG_CONNECTOR is not set
326
327#
328# Memory Technology Devices (MTD)
329#
330# CONFIG_MTD is not set
331
332#
333# Parallel port support
334#
335# CONFIG_PARPORT is not set
336
337#
338# Plug and Play support
339#
340
341#
342# Block devices
343#
344# CONFIG_BLK_DEV_FD is not set
345# CONFIG_BLK_DEV_COW_COMMON is not set
346# CONFIG_BLK_DEV_LOOP is not set
347# CONFIG_BLK_DEV_NBD is not set
348# CONFIG_BLK_DEV_RAM is not set
349# CONFIG_BLK_DEV_INITRD is not set
350# CONFIG_CDROM_PKTCDVD is not set
351# CONFIG_ATA_OVER_ETH is not set
352
353#
354# Misc devices
355#
356# CONFIG_TIFM_CORE is not set
357
358#
359# ATA/ATAPI/MFM/RLL support
360#
361# CONFIG_IDE is not set
362
363#
364# SCSI device support
365#
366# CONFIG_RAID_ATTRS is not set
367CONFIG_SCSI=y
368# CONFIG_SCSI_NETLINK is not set
369CONFIG_SCSI_PROC_FS=y
370
371#
372# SCSI support type (disk, tape, CD-ROM)
373#
374# CONFIG_BLK_DEV_SD is not set
375# CONFIG_CHR_DEV_ST is not set
376# CONFIG_CHR_DEV_OSST is not set
377# CONFIG_BLK_DEV_SR is not set
378# CONFIG_CHR_DEV_SG is not set
379# CONFIG_CHR_DEV_SCH is not set
380
381#
382# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
383#
384# CONFIG_SCSI_MULTI_LUN is not set
385# CONFIG_SCSI_CONSTANTS is not set
386# CONFIG_SCSI_LOGGING is not set
387
388#
389# SCSI Transports
390#
391# CONFIG_SCSI_SPI_ATTRS is not set
392# CONFIG_SCSI_FC_ATTRS is not set
393# CONFIG_SCSI_ISCSI_ATTRS is not set
394# CONFIG_SCSI_SAS_ATTRS is not set
395# CONFIG_SCSI_SAS_LIBSAS is not set
396
397#
398# SCSI low-level drivers
399#
400# CONFIG_ISCSI_TCP is not set
401# CONFIG_SCSI_DEBUG is not set
402
403#
404# Serial ATA (prod) and Parallel ATA (experimental) drivers
405#
406# CONFIG_ATA is not set
407
408#
409# Multi-device support (RAID and LVM)
410#
411# CONFIG_MD is not set
412
413#
414# Fusion MPT device support
415#
416# CONFIG_FUSION is not set
417
418#
419# IEEE 1394 (FireWire) support
420#
421
422#
423# I2O device support
424#
425
426#
427# Macintosh device drivers
428#
429# CONFIG_WINDFARM is not set
430
431#
432# Network device support
433#
434CONFIG_NETDEVICES=y
435# CONFIG_DUMMY is not set
436# CONFIG_BONDING is not set
437# CONFIG_EQUALIZER is not set
438# CONFIG_TUN is not set
439
440#
441# PHY device support
442#
443
444#
445# Ethernet (10 or 100Mbit)
446#
447# CONFIG_NET_ETHERNET is not set
448
449#
450# Ethernet (1000 Mbit)
451#
452
453#
454# Ethernet (10000 Mbit)
455#
456
457#
458# Token Ring devices
459#
460
461#
462# Wireless LAN (non-hamradio)
463#
464# CONFIG_NET_RADIO is not set
465
466#
467# Wan interfaces
468#
469# CONFIG_WAN is not set
470# CONFIG_PPP is not set
471# CONFIG_SLIP is not set
472# CONFIG_SHAPER is not set
473# CONFIG_NETCONSOLE is not set
474# CONFIG_NETPOLL is not set
475# CONFIG_NET_POLL_CONTROLLER is not set
476
477#
478# ISDN subsystem
479#
480# CONFIG_ISDN is not set
481
482#
483# Telephony Support
484#
485# CONFIG_PHONE is not set
486
487#
488# Input device support
489#
490CONFIG_INPUT=y
491# CONFIG_INPUT_FF_MEMLESS is not set
492
493#
494# Userland interfaces
495#
496# CONFIG_INPUT_MOUSEDEV is not set
497# CONFIG_INPUT_JOYDEV is not set
498# CONFIG_INPUT_TSDEV is not set
499CONFIG_INPUT_EVDEV=y
500# CONFIG_INPUT_EVBUG is not set
501
502#
503# Input Device Drivers
504#
505# CONFIG_INPUT_KEYBOARD is not set
506# CONFIG_INPUT_MOUSE is not set
507# CONFIG_INPUT_JOYSTICK is not set
508# CONFIG_INPUT_TOUCHSCREEN is not set
509# CONFIG_INPUT_MISC is not set
510
511#
512# Hardware I/O ports
513#
514# CONFIG_SERIO is not set
515# CONFIG_GAMEPORT is not set
516
517#
518# Character devices
519#
520CONFIG_VT=y
521CONFIG_VT_CONSOLE=y
522CONFIG_HW_CONSOLE=y
523# CONFIG_VT_HW_CONSOLE_BINDING is not set
524# CONFIG_SERIAL_NONSTANDARD is not set
525
526#
527# Serial drivers
528#
529# CONFIG_SERIAL_8250 is not set
530
531#
532# Non-8250 serial port support
533#
534CONFIG_UNIX98_PTYS=y
535# CONFIG_LEGACY_PTYS is not set
536
537#
538# IPMI
539#
540# CONFIG_IPMI_HANDLER is not set
541
542#
543# Watchdog Cards
544#
545# CONFIG_WATCHDOG is not set
546# CONFIG_HW_RANDOM is not set
547CONFIG_GEN_RTC=y
548# CONFIG_GEN_RTC_X is not set
549# CONFIG_DTLK is not set
550# CONFIG_R3964 is not set
551
552#
553# Ftape, the floppy tape device driver
554#
555# CONFIG_RAW_DRIVER is not set
556# CONFIG_HANGCHECK_TIMER is not set
557
558#
559# TPM devices
560#
561# CONFIG_TCG_TPM is not set
562
563#
564# I2C support
565#
566# CONFIG_I2C is not set
567
568#
569# SPI support
570#
571# CONFIG_SPI is not set
572# CONFIG_SPI_MASTER is not set
573
574#
575# Dallas's 1-wire bus
576#
577# CONFIG_W1 is not set
578
579#
580# Hardware Monitoring support
581#
582# CONFIG_HWMON is not set
583# CONFIG_HWMON_VID is not set
584
585#
586# Multimedia devices
587#
588# CONFIG_VIDEO_DEV is not set
589
590#
591# Digital Video Broadcasting Devices
592#
593# CONFIG_DVB is not set
594
595#
596# Graphics support
597#
598# CONFIG_FIRMWARE_EDID is not set
599# CONFIG_FB is not set
600
601#
602# Console display driver support
603#
604# CONFIG_VGA_CONSOLE is not set
605CONFIG_DUMMY_CONSOLE=y
606# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
607
608#
609# Sound
610#
611# CONFIG_SOUND is not set
612
613#
614# USB support
615#
616# CONFIG_USB_ARCH_HAS_HCD is not set
617# CONFIG_USB_ARCH_HAS_OHCI is not set
618# CONFIG_USB_ARCH_HAS_EHCI is not set
619
620#
621# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
622#
623
624#
625# USB Gadget Support
626#
627# CONFIG_USB_GADGET is not set
628
629#
630# MMC/SD Card support
631#
632# CONFIG_MMC is not set
633
634#
635# LED devices
636#
637# CONFIG_NEW_LEDS is not set
638
639#
640# LED drivers
641#
642
643#
644# LED Triggers
645#
646
647#
648# InfiniBand support
649#
650
651#
652# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
653#
654
655#
656# Real Time Clock
657#
658# CONFIG_RTC_CLASS is not set
659
660#
661# DMA Engine support
662#
663# CONFIG_DMA_ENGINE is not set
664
665#
666# DMA Clients
667#
668
669#
670# DMA Devices
671#
672
673#
674# File systems
675#
676# CONFIG_EXT2_FS is not set
677# CONFIG_EXT3_FS is not set
678# CONFIG_EXT4DEV_FS is not set
679# CONFIG_REISERFS_FS is not set
680# CONFIG_JFS_FS is not set
681# CONFIG_FS_POSIX_ACL is not set
682# CONFIG_XFS_FS is not set
683# CONFIG_GFS2_FS is not set
684# CONFIG_OCFS2_FS is not set
685# CONFIG_MINIX_FS is not set
686# CONFIG_ROMFS_FS is not set
687CONFIG_INOTIFY=y
688CONFIG_INOTIFY_USER=y
689# CONFIG_QUOTA is not set
690CONFIG_DNOTIFY=y
691# CONFIG_AUTOFS_FS is not set
692# CONFIG_AUTOFS4_FS is not set
693# CONFIG_FUSE_FS is not set
694
695#
696# CD-ROM/DVD Filesystems
697#
698# CONFIG_ISO9660_FS is not set
699# CONFIG_UDF_FS is not set
700
701#
702# DOS/FAT/NT Filesystems
703#
704# CONFIG_MSDOS_FS is not set
705# CONFIG_VFAT_FS is not set
706# CONFIG_NTFS_FS is not set
707
708#
709# Pseudo filesystems
710#
711CONFIG_PROC_FS=y
712CONFIG_PROC_KCORE=y
713CONFIG_PROC_SYSCTL=y
714CONFIG_SYSFS=y
715CONFIG_TMPFS=y
716# CONFIG_TMPFS_POSIX_ACL is not set
717# CONFIG_HUGETLBFS is not set
718# CONFIG_HUGETLB_PAGE is not set
719CONFIG_RAMFS=y
720# CONFIG_CONFIGFS_FS is not set
721
722#
723# Miscellaneous filesystems
724#
725# CONFIG_ADFS_FS is not set
726# CONFIG_AFFS_FS is not set
727# CONFIG_HFS_FS is not set
728# CONFIG_HFSPLUS_FS is not set
729# CONFIG_BEFS_FS is not set
730# CONFIG_BFS_FS is not set
731# CONFIG_EFS_FS is not set
732# CONFIG_CRAMFS is not set
733# CONFIG_VXFS_FS is not set
734# CONFIG_HPFS_FS is not set
735# CONFIG_QNX4FS_FS is not set
736# CONFIG_SYSV_FS is not set
737# CONFIG_UFS_FS is not set
738
739#
740# Network File Systems
741#
742CONFIG_NFS_FS=y
743CONFIG_NFS_V3=y
744# CONFIG_NFS_V3_ACL is not set
745# CONFIG_NFS_V4 is not set
746# CONFIG_NFS_DIRECTIO is not set
747# CONFIG_NFSD is not set
748CONFIG_ROOT_NFS=y
749CONFIG_LOCKD=y
750CONFIG_LOCKD_V4=y
751CONFIG_NFS_COMMON=y
752CONFIG_SUNRPC=y
753# CONFIG_RPCSEC_GSS_KRB5 is not set
754# CONFIG_RPCSEC_GSS_SPKM3 is not set
755# CONFIG_SMB_FS is not set
756# CONFIG_CIFS is not set
757# CONFIG_NCP_FS is not set
758# CONFIG_CODA_FS is not set
759# CONFIG_AFS_FS is not set
760# CONFIG_9P_FS is not set
761
762#
763# Partition Types
764#
765# CONFIG_PARTITION_ADVANCED is not set
766CONFIG_MSDOS_PARTITION=y
767
768#
769# Native Language Support
770#
771# CONFIG_NLS is not set
772
773#
774# Library routines
775#
776# CONFIG_CRC_CCITT is not set
777# CONFIG_CRC16 is not set
778# CONFIG_CRC32 is not set
779# CONFIG_LIBCRC32C is not set
780CONFIG_PLIST=y
781
782#
783# Instrumentation Support
784#
785# CONFIG_PROFILING is not set
786# CONFIG_KPROBES is not set
787
788#
789# Kernel hacking
790#
791# CONFIG_PRINTK_TIME is not set
792CONFIG_ENABLE_MUST_CHECK=y
793# CONFIG_MAGIC_SYSRQ is not set
794# CONFIG_UNUSED_SYMBOLS is not set
795CONFIG_DEBUG_KERNEL=y
796CONFIG_LOG_BUF_SHIFT=17
797CONFIG_DETECT_SOFTLOCKUP=y
798# CONFIG_SCHEDSTATS is not set
799# CONFIG_DEBUG_SLAB is not set
800# CONFIG_DEBUG_RT_MUTEXES is not set
801# CONFIG_RT_MUTEX_TESTER is not set
802CONFIG_DEBUG_SPINLOCK=y
803# CONFIG_DEBUG_MUTEXES is not set
804# CONFIG_DEBUG_RWSEMS is not set
805CONFIG_DEBUG_SPINLOCK_SLEEP=y
806# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
807# CONFIG_DEBUG_KOBJECT is not set
808CONFIG_DEBUG_INFO=y
809# CONFIG_DEBUG_FS is not set
810# CONFIG_DEBUG_VM is not set
811CONFIG_DEBUG_LIST=y
812CONFIG_FORCED_INLINING=y
813# CONFIG_HEADERS_CHECK is not set
814# CONFIG_RCU_TORTURE_TEST is not set
815# CONFIG_DEBUG_STACKOVERFLOW is not set
816# CONFIG_DEBUG_STACK_USAGE is not set
817# CONFIG_DEBUGGER is not set
818CONFIG_IRQSTACKS=y
819# CONFIG_BOOTX_TEXT is not set
820CONFIG_PPC_EARLY_DEBUG=y
821# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
822# CONFIG_PPC_EARLY_DEBUG_G5 is not set
823# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
824# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
825# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
826# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
827
828#
829# Security options
830#
831# CONFIG_KEYS is not set
832# CONFIG_SECURITY is not set
833
834#
835# Cryptographic options
836#
837# CONFIG_CRYPTO is not set
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 7af23c43fd4b..4fe53d08ab81 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -17,11 +17,11 @@ obj-y += vdso32/
17obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ 17obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
18 signal_64.o ptrace32.o \ 18 signal_64.o ptrace32.o \
19 paca.o cpu_setup_ppc970.o \ 19 paca.o cpu_setup_ppc970.o \
20 firmware.o sysfs.o 20 firmware.o sysfs.o nvram_64.o
21obj-$(CONFIG_PPC64) += vdso64/ 21obj-$(CONFIG_PPC64) += vdso64/
22obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o 22obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
23obj-$(CONFIG_PPC_970_NAP) += idle_power4.o 23obj-$(CONFIG_PPC_970_NAP) += idle_power4.o
24obj-$(CONFIG_PPC_OF) += of_device.o prom_parse.o 24obj-$(CONFIG_PPC_OF) += of_device.o of_platform.o prom_parse.o
25procfs-$(CONFIG_PPC64) := proc_ppc64.o 25procfs-$(CONFIG_PPC64) := proc_ppc64.o
26obj-$(CONFIG_PROC_FS) += $(procfs-y) 26obj-$(CONFIG_PROC_FS) += $(procfs-y)
27rtaspci-$(CONFIG_PPC64) := rtas_pci.o 27rtaspci-$(CONFIG_PPC64) := rtas_pci.o
@@ -32,7 +32,6 @@ obj-$(CONFIG_LPARCFG) += lparcfg.o
32obj-$(CONFIG_IBMVIO) += vio.o 32obj-$(CONFIG_IBMVIO) += vio.o
33obj-$(CONFIG_IBMEBUS) += ibmebus.o 33obj-$(CONFIG_IBMEBUS) += ibmebus.o
34obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o 34obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o
35obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o
36obj-$(CONFIG_CRASH_DUMP) += crash_dump.o 35obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
37obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o 36obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
38obj-$(CONFIG_TAU) += tau_6xx.o 37obj-$(CONFIG_TAU) += tau_6xx.o
@@ -59,11 +58,11 @@ obj-$(CONFIG_BOOTX_TEXT) += btext.o
59obj-$(CONFIG_SMP) += smp.o 58obj-$(CONFIG_SMP) += smp.o
60obj-$(CONFIG_KPROBES) += kprobes.o 59obj-$(CONFIG_KPROBES) += kprobes.o
61obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o 60obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o
61
62module-$(CONFIG_PPC64) += module_64.o 62module-$(CONFIG_PPC64) += module_64.o
63obj-$(CONFIG_MODULES) += $(module-y) 63obj-$(CONFIG_MODULES) += $(module-y)
64 64
65pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \ 65pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o
66 pci_direct_iommu.o iomap.o
67pci32-$(CONFIG_PPC32) := pci_32.o 66pci32-$(CONFIG_PPC32) := pci_32.o
68obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) 67obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y)
69kexec-$(CONFIG_PPC64) := machine_kexec_64.o 68kexec-$(CONFIG_PPC64) := machine_kexec_64.o
@@ -72,8 +71,12 @@ obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o $(kexec-y)
72obj-$(CONFIG_AUDIT) += audit.o 71obj-$(CONFIG_AUDIT) += audit.o
73obj64-$(CONFIG_AUDIT) += compat_audit.o 72obj64-$(CONFIG_AUDIT) += compat_audit.o
74 73
74ifneq ($(CONFIG_PPC_INDIRECT_IO),y)
75obj-y += iomap.o
76endif
77
75ifeq ($(CONFIG_PPC_ISERIES),y) 78ifeq ($(CONFIG_PPC_ISERIES),y)
76$(obj)/head_64.o: $(obj)/lparmap.s 79extra-y += lparmap.s
77AFLAGS_head_64.o += -I$(obj) 80AFLAGS_head_64.o += -I$(obj)
78endif 81endif
79 82
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index d06f378597bb..e96521530d21 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -118,7 +118,8 @@ int main(void)
118 DEFINE(PACASTABRR, offsetof(struct paca_struct, stab_rr)); 118 DEFINE(PACASTABRR, offsetof(struct paca_struct, stab_rr));
119 DEFINE(PACAR1, offsetof(struct paca_struct, saved_r1)); 119 DEFINE(PACAR1, offsetof(struct paca_struct, saved_r1));
120 DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc)); 120 DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc));
121 DEFINE(PACAPROCENABLED, offsetof(struct paca_struct, proc_enabled)); 121 DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled));
122 DEFINE(PACAHARDIRQEN, offsetof(struct paca_struct, hard_enabled));
122 DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); 123 DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache));
123 DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); 124 DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr));
124 DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); 125 DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
diff --git a/arch/powerpc/kernel/cpu_setup_ppc970.S b/arch/powerpc/kernel/cpu_setup_ppc970.S
index 652594891d58..bf118c385752 100644
--- a/arch/powerpc/kernel/cpu_setup_ppc970.S
+++ b/arch/powerpc/kernel/cpu_setup_ppc970.S
@@ -83,6 +83,22 @@ _GLOBAL(__setup_cpu_ppc970)
83 rldimi r0,r11,52,8 /* set NAP and DPM */ 83 rldimi r0,r11,52,8 /* set NAP and DPM */
84 li r11,0 84 li r11,0
85 rldimi r0,r11,32,31 /* clear EN_ATTN */ 85 rldimi r0,r11,32,31 /* clear EN_ATTN */
86 b load_hids /* Jump to shared code */
87
88
89_GLOBAL(__setup_cpu_ppc970MP)
90 /* Do nothing if not running in HV mode */
91 mfmsr r0
92 rldicl. r0,r0,4,63
93 beqlr
94
95 mfspr r0,SPRN_HID0
96 li r11,0x15 /* clear DOZE and SLEEP */
97 rldimi r0,r11,52,6 /* set DEEPNAP, NAP and DPM */
98 li r11,0
99 rldimi r0,r11,32,31 /* clear EN_ATTN */
100
101load_hids:
86 mtspr SPRN_HID0,r0 102 mtspr SPRN_HID0,r0
87 mfspr r0,SPRN_HID0 103 mfspr r0,SPRN_HID0
88 mfspr r0,SPRN_HID0 104 mfspr r0,SPRN_HID0
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index bfd499ee3753..9d1614c3ce67 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -42,6 +42,7 @@ extern void __setup_cpu_745x(unsigned long offset, struct cpu_spec* spec);
42#endif /* CONFIG_PPC32 */ 42#endif /* CONFIG_PPC32 */
43#ifdef CONFIG_PPC64 43#ifdef CONFIG_PPC64
44extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); 44extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
45extern void __setup_cpu_ppc970MP(unsigned long offset, struct cpu_spec* spec);
45extern void __restore_cpu_ppc970(void); 46extern void __restore_cpu_ppc970(void);
46#endif /* CONFIG_PPC64 */ 47#endif /* CONFIG_PPC64 */
47 48
@@ -222,9 +223,9 @@ static struct cpu_spec cpu_specs[] = {
222 .icache_bsize = 128, 223 .icache_bsize = 128,
223 .dcache_bsize = 128, 224 .dcache_bsize = 128,
224 .num_pmcs = 8, 225 .num_pmcs = 8,
225 .cpu_setup = __setup_cpu_ppc970, 226 .cpu_setup = __setup_cpu_ppc970MP,
226 .cpu_restore = __restore_cpu_ppc970, 227 .cpu_restore = __restore_cpu_ppc970,
227 .oprofile_cpu_type = "ppc64/970", 228 .oprofile_cpu_type = "ppc64/970MP",
228 .oprofile_type = PPC_OPROFILE_POWER4, 229 .oprofile_type = PPC_OPROFILE_POWER4,
229 .platform = "ppc970", 230 .platform = "ppc970",
230 }, 231 },
@@ -276,10 +277,45 @@ static struct cpu_spec cpu_specs[] = {
276 .oprofile_mmcra_sipr = MMCRA_SIPR, 277 .oprofile_mmcra_sipr = MMCRA_SIPR,
277 .platform = "power5+", 278 .platform = "power5+",
278 }, 279 },
280 { /* POWER6 in P5+ mode; 2.04-compliant processor */
281 .pvr_mask = 0xffffffff,
282 .pvr_value = 0x0f000001,
283 .cpu_name = "POWER5+",
284 .cpu_features = CPU_FTRS_POWER5,
285 .cpu_user_features = COMMON_USER_POWER5_PLUS,
286 .icache_bsize = 128,
287 .dcache_bsize = 128,
288 .num_pmcs = 6,
289 .oprofile_cpu_type = "ppc64/power6",
290 .oprofile_type = PPC_OPROFILE_POWER4,
291 .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV,
292 .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR,
293 .oprofile_mmcra_clear = POWER6_MMCRA_THRM |
294 POWER6_MMCRA_OTHER,
295 .platform = "power5+",
296 },
279 { /* Power6 */ 297 { /* Power6 */
280 .pvr_mask = 0xffff0000, 298 .pvr_mask = 0xffff0000,
281 .pvr_value = 0x003e0000, 299 .pvr_value = 0x003e0000,
282 .cpu_name = "POWER6", 300 .cpu_name = "POWER6 (raw)",
301 .cpu_features = CPU_FTRS_POWER6,
302 .cpu_user_features = COMMON_USER_POWER6 |
303 PPC_FEATURE_POWER6_EXT,
304 .icache_bsize = 128,
305 .dcache_bsize = 128,
306 .num_pmcs = 6,
307 .oprofile_cpu_type = "ppc64/power6",
308 .oprofile_type = PPC_OPROFILE_POWER4,
309 .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV,
310 .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR,
311 .oprofile_mmcra_clear = POWER6_MMCRA_THRM |
312 POWER6_MMCRA_OTHER,
313 .platform = "power6x",
314 },
315 { /* 2.05-compliant processor, i.e. Power6 "architected" mode */
316 .pvr_mask = 0xffffffff,
317 .pvr_value = 0x0f000002,
318 .cpu_name = "POWER6 (architected)",
283 .cpu_features = CPU_FTRS_POWER6, 319 .cpu_features = CPU_FTRS_POWER6,
284 .cpu_user_features = COMMON_USER_POWER6, 320 .cpu_user_features = COMMON_USER_POWER6,
285 .icache_bsize = 128, 321 .icache_bsize = 128,
@@ -303,6 +339,9 @@ static struct cpu_spec cpu_specs[] = {
303 PPC_FEATURE_SMT, 339 PPC_FEATURE_SMT,
304 .icache_bsize = 128, 340 .icache_bsize = 128,
305 .dcache_bsize = 128, 341 .dcache_bsize = 128,
342 .num_pmcs = 4,
343 .oprofile_cpu_type = "ppc64/cell-be",
344 .oprofile_type = PPC_OPROFILE_CELL,
306 .platform = "ppc-cell-be", 345 .platform = "ppc-cell-be",
307 }, 346 },
308 { /* PA Semi PA6T */ 347 { /* PA Semi PA6T */
@@ -801,6 +840,17 @@ static struct cpu_spec cpu_specs[] = {
801 .cpu_setup = __setup_cpu_603, 840 .cpu_setup = __setup_cpu_603,
802 .platform = "ppc603", 841 .platform = "ppc603",
803 }, 842 },
843 { /* e300c3 on 83xx */
844 .pvr_mask = 0x7fff0000,
845 .pvr_value = 0x00850000,
846 .cpu_name = "e300c3",
847 .cpu_features = CPU_FTRS_E300,
848 .cpu_user_features = COMMON_USER,
849 .icache_bsize = 32,
850 .dcache_bsize = 32,
851 .cpu_setup = __setup_cpu_603,
852 .platform = "ppc603",
853 },
804 { /* default match, we assume split I/D cache & TB (non-601)... */ 854 { /* default match, we assume split I/D cache & TB (non-601)... */
805 .pvr_mask = 0x00000000, 855 .pvr_mask = 0x00000000,
806 .pvr_value = 0x00000000, 856 .pvr_value = 0x00000000,
@@ -1169,19 +1219,15 @@ static struct cpu_spec cpu_specs[] = {
1169#endif /* CONFIG_PPC32 */ 1219#endif /* CONFIG_PPC32 */
1170}; 1220};
1171 1221
1172struct cpu_spec *identify_cpu(unsigned long offset) 1222struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr)
1173{ 1223{
1174 struct cpu_spec *s = cpu_specs; 1224 struct cpu_spec *s = cpu_specs;
1175 struct cpu_spec **cur = &cur_cpu_spec; 1225 struct cpu_spec **cur = &cur_cpu_spec;
1176 unsigned int pvr = mfspr(SPRN_PVR);
1177 int i; 1226 int i;
1178 1227
1179 s = PTRRELOC(s); 1228 s = PTRRELOC(s);
1180 cur = PTRRELOC(cur); 1229 cur = PTRRELOC(cur);
1181 1230
1182 if (*cur != NULL)
1183 return PTRRELOC(*cur);
1184
1185 for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++) 1231 for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++)
1186 if ((pvr & s->pvr_mask) == s->pvr_value) { 1232 if ((pvr & s->pvr_mask) == s->pvr_value) {
1187 *cur = cpu_specs + i; 1233 *cur = cpu_specs + i;
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
index 1af41f7616dc..89b03c8da9d2 100644
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -111,7 +111,7 @@ void crash_ipi_callback(struct pt_regs *regs)
111 if (!cpu_online(cpu)) 111 if (!cpu_online(cpu))
112 return; 112 return;
113 113
114 local_irq_disable(); 114 hard_irq_disable();
115 if (!cpu_isset(cpu, cpus_in_crash)) 115 if (!cpu_isset(cpu, cpus_in_crash))
116 crash_save_this_cpu(regs, cpu); 116 crash_save_this_cpu(regs, cpu);
117 cpu_set(cpu, cpus_in_crash); 117 cpu_set(cpu, cpus_in_crash);
@@ -289,7 +289,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
289 * an SMP system. 289 * an SMP system.
290 * The kernel is broken so disable interrupts. 290 * The kernel is broken so disable interrupts.
291 */ 291 */
292 local_irq_disable(); 292 hard_irq_disable();
293 293
294 for_each_irq(irq) { 294 for_each_irq(irq) {
295 struct irq_desc *desc = irq_desc + irq; 295 struct irq_desc *desc = irq_desc + irq;
diff --git a/arch/powerpc/kernel/dma_64.c b/arch/powerpc/kernel/dma_64.c
index 6c168f6ea142..7b0e754383cf 100644
--- a/arch/powerpc/kernel/dma_64.c
+++ b/arch/powerpc/kernel/dma_64.c
@@ -1,151 +1,194 @@
1/* 1/*
2 * Copyright (C) 2004 IBM Corporation 2 * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corporation
3 * 3 *
4 * Implements the generic device dma API for ppc64. Handles 4 * Provide default implementations of the DMA mapping callbacks for
5 * the pci and vio busses 5 * directly mapped busses and busses using the iommu infrastructure
6 */ 6 */
7 7
8#include <linux/device.h> 8#include <linux/device.h>
9#include <linux/dma-mapping.h> 9#include <linux/dma-mapping.h>
10/* Include the busses we support */
11#include <linux/pci.h>
12#include <asm/vio.h>
13#include <asm/ibmebus.h>
14#include <asm/scatterlist.h>
15#include <asm/bug.h> 10#include <asm/bug.h>
11#include <asm/iommu.h>
12#include <asm/abs_addr.h>
16 13
17static struct dma_mapping_ops *get_dma_ops(struct device *dev) 14/*
18{ 15 * Generic iommu implementation
19#ifdef CONFIG_PCI 16 */
20 if (dev->bus == &pci_bus_type)
21 return &pci_dma_ops;
22#endif
23#ifdef CONFIG_IBMVIO
24 if (dev->bus == &vio_bus_type)
25 return &vio_dma_ops;
26#endif
27#ifdef CONFIG_IBMEBUS
28 if (dev->bus == &ibmebus_bus_type)
29 return &ibmebus_dma_ops;
30#endif
31 return NULL;
32}
33 17
34int dma_supported(struct device *dev, u64 mask) 18static inline unsigned long device_to_mask(struct device *dev)
35{ 19{
36 struct dma_mapping_ops *dma_ops = get_dma_ops(dev); 20 if (dev->dma_mask && *dev->dma_mask)
21 return *dev->dma_mask;
22 /* Assume devices without mask can take 32 bit addresses */
23 return 0xfffffffful;
24}
37 25
38 BUG_ON(!dma_ops);
39 26
40 return dma_ops->dma_supported(dev, mask); 27/* Allocates a contiguous real buffer and creates mappings over it.
28 * Returns the virtual address of the buffer and sets dma_handle
29 * to the dma address (mapping) of the first page.
30 */
31static void *dma_iommu_alloc_coherent(struct device *dev, size_t size,
32 dma_addr_t *dma_handle, gfp_t flag)
33{
34 return iommu_alloc_coherent(dev->archdata.dma_data, size, dma_handle,
35 device_to_mask(dev), flag,
36 dev->archdata.numa_node);
41} 37}
42EXPORT_SYMBOL(dma_supported);
43 38
44int dma_set_mask(struct device *dev, u64 dma_mask) 39static void dma_iommu_free_coherent(struct device *dev, size_t size,
40 void *vaddr, dma_addr_t dma_handle)
45{ 41{
46#ifdef CONFIG_PCI 42 iommu_free_coherent(dev->archdata.dma_data, size, vaddr, dma_handle);
47 if (dev->bus == &pci_bus_type)
48 return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
49#endif
50#ifdef CONFIG_IBMVIO
51 if (dev->bus == &vio_bus_type)
52 return -EIO;
53#endif /* CONFIG_IBMVIO */
54#ifdef CONFIG_IBMEBUS
55 if (dev->bus == &ibmebus_bus_type)
56 return -EIO;
57#endif
58 BUG();
59 return 0;
60} 43}
61EXPORT_SYMBOL(dma_set_mask);
62 44
63void *dma_alloc_coherent(struct device *dev, size_t size, 45/* Creates TCEs for a user provided buffer. The user buffer must be
64 dma_addr_t *dma_handle, gfp_t flag) 46 * contiguous real kernel storage (not vmalloc). The address of the buffer
47 * passed here is the kernel (virtual) address of the buffer. The buffer
48 * need not be page aligned, the dma_addr_t returned will point to the same
49 * byte within the page as vaddr.
50 */
51static dma_addr_t dma_iommu_map_single(struct device *dev, void *vaddr,
52 size_t size,
53 enum dma_data_direction direction)
65{ 54{
66 struct dma_mapping_ops *dma_ops = get_dma_ops(dev); 55 return iommu_map_single(dev->archdata.dma_data, vaddr, size,
67 56 device_to_mask(dev), direction);
68 BUG_ON(!dma_ops);
69
70 return dma_ops->alloc_coherent(dev, size, dma_handle, flag);
71} 57}
72EXPORT_SYMBOL(dma_alloc_coherent);
73 58
74void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, 59
75 dma_addr_t dma_handle) 60static void dma_iommu_unmap_single(struct device *dev, dma_addr_t dma_handle,
61 size_t size,
62 enum dma_data_direction direction)
76{ 63{
77 struct dma_mapping_ops *dma_ops = get_dma_ops(dev); 64 iommu_unmap_single(dev->archdata.dma_data, dma_handle, size, direction);
65}
78 66
79 BUG_ON(!dma_ops);
80 67
81 dma_ops->free_coherent(dev, size, cpu_addr, dma_handle); 68static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
69 int nelems, enum dma_data_direction direction)
70{
71 return iommu_map_sg(dev->archdata.dma_data, sglist, nelems,
72 device_to_mask(dev), direction);
82} 73}
83EXPORT_SYMBOL(dma_free_coherent);
84 74
85dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, size_t size, 75static void dma_iommu_unmap_sg(struct device *dev, struct scatterlist *sglist,
86 enum dma_data_direction direction) 76 int nelems, enum dma_data_direction direction)
87{ 77{
88 struct dma_mapping_ops *dma_ops = get_dma_ops(dev); 78 iommu_unmap_sg(dev->archdata.dma_data, sglist, nelems, direction);
89
90 BUG_ON(!dma_ops);
91
92 return dma_ops->map_single(dev, cpu_addr, size, direction);
93} 79}
94EXPORT_SYMBOL(dma_map_single);
95 80
96void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, 81/* We support DMA to/from any memory page via the iommu */
97 enum dma_data_direction direction) 82static int dma_iommu_dma_supported(struct device *dev, u64 mask)
98{ 83{
99 struct dma_mapping_ops *dma_ops = get_dma_ops(dev); 84 struct iommu_table *tbl = dev->archdata.dma_data;
100 85
101 BUG_ON(!dma_ops); 86 if (!tbl || tbl->it_offset > mask) {
102 87 printk(KERN_INFO
103 dma_ops->unmap_single(dev, dma_addr, size, direction); 88 "Warning: IOMMU offset too big for device mask\n");
89 if (tbl)
90 printk(KERN_INFO
91 "mask: 0x%08lx, table offset: 0x%08lx\n",
92 mask, tbl->it_offset);
93 else
94 printk(KERN_INFO "mask: 0x%08lx, table unavailable\n",
95 mask);
96 return 0;
97 } else
98 return 1;
104} 99}
105EXPORT_SYMBOL(dma_unmap_single);
106 100
107dma_addr_t dma_map_page(struct device *dev, struct page *page, 101struct dma_mapping_ops dma_iommu_ops = {
108 unsigned long offset, size_t size, 102 .alloc_coherent = dma_iommu_alloc_coherent,
109 enum dma_data_direction direction) 103 .free_coherent = dma_iommu_free_coherent,
110{ 104 .map_single = dma_iommu_map_single,
111 struct dma_mapping_ops *dma_ops = get_dma_ops(dev); 105 .unmap_single = dma_iommu_unmap_single,
106 .map_sg = dma_iommu_map_sg,
107 .unmap_sg = dma_iommu_unmap_sg,
108 .dma_supported = dma_iommu_dma_supported,
109};
110EXPORT_SYMBOL(dma_iommu_ops);
112 111
113 BUG_ON(!dma_ops); 112/*
113 * Generic direct DMA implementation
114 *
115 * This implementation supports a global offset that can be applied if
116 * the address at which memory is visible to devices is not 0.
117 */
118unsigned long dma_direct_offset;
114 119
115 return dma_ops->map_single(dev, page_address(page) + offset, size, 120static void *dma_direct_alloc_coherent(struct device *dev, size_t size,
116 direction); 121 dma_addr_t *dma_handle, gfp_t flag)
122{
123 struct page *page;
124 void *ret;
125 int node = dev->archdata.numa_node;
126
127 /* TODO: Maybe use the numa node here too ? */
128 page = alloc_pages_node(node, flag, get_order(size));
129 if (page == NULL)
130 return NULL;
131 ret = page_address(page);
132 memset(ret, 0, size);
133 *dma_handle = virt_to_abs(ret) | dma_direct_offset;
134
135 return ret;
117} 136}
118EXPORT_SYMBOL(dma_map_page);
119 137
120void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, 138static void dma_direct_free_coherent(struct device *dev, size_t size,
121 enum dma_data_direction direction) 139 void *vaddr, dma_addr_t dma_handle)
122{ 140{
123 struct dma_mapping_ops *dma_ops = get_dma_ops(dev); 141 free_pages((unsigned long)vaddr, get_order(size));
142}
124 143
125 BUG_ON(!dma_ops); 144static dma_addr_t dma_direct_map_single(struct device *dev, void *ptr,
145 size_t size,
146 enum dma_data_direction direction)
147{
148 return virt_to_abs(ptr) | dma_direct_offset;
149}
126 150
127 dma_ops->unmap_single(dev, dma_address, size, direction); 151static void dma_direct_unmap_single(struct device *dev, dma_addr_t dma_addr,
152 size_t size,
153 enum dma_data_direction direction)
154{
128} 155}
129EXPORT_SYMBOL(dma_unmap_page);
130 156
131int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, 157static int dma_direct_map_sg(struct device *dev, struct scatterlist *sg,
132 enum dma_data_direction direction) 158 int nents, enum dma_data_direction direction)
133{ 159{
134 struct dma_mapping_ops *dma_ops = get_dma_ops(dev); 160 int i;
135 161
136 BUG_ON(!dma_ops); 162 for (i = 0; i < nents; i++, sg++) {
163 sg->dma_address = (page_to_phys(sg->page) + sg->offset) |
164 dma_direct_offset;
165 sg->dma_length = sg->length;
166 }
137 167
138 return dma_ops->map_sg(dev, sg, nents, direction); 168 return nents;
139} 169}
140EXPORT_SYMBOL(dma_map_sg);
141 170
142void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, 171static void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sg,
143 enum dma_data_direction direction) 172 int nents, enum dma_data_direction direction)
144{ 173{
145 struct dma_mapping_ops *dma_ops = get_dma_ops(dev); 174}
146
147 BUG_ON(!dma_ops);
148 175
149 dma_ops->unmap_sg(dev, sg, nhwentries, direction); 176static int dma_direct_dma_supported(struct device *dev, u64 mask)
177{
178 /* Could be improved to check for memory though it better be
179 * done via some global so platforms can set the limit in case
180 * they have limited DMA windows
181 */
182 return mask >= DMA_32BIT_MASK;
150} 183}
151EXPORT_SYMBOL(dma_unmap_sg); 184
185struct dma_mapping_ops dma_direct_ops = {
186 .alloc_coherent = dma_direct_alloc_coherent,
187 .free_coherent = dma_direct_free_coherent,
188 .map_single = dma_direct_map_single,
189 .unmap_single = dma_direct_unmap_single,
190 .map_sg = dma_direct_map_sg,
191 .unmap_sg = dma_direct_unmap_sg,
192 .dma_supported = dma_direct_dma_supported,
193};
194EXPORT_SYMBOL(dma_direct_ops);
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 748e74fcf541..1a3d4de197d2 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -87,15 +87,19 @@ system_call_common:
87 addi r9,r1,STACK_FRAME_OVERHEAD 87 addi r9,r1,STACK_FRAME_OVERHEAD
88 ld r11,exception_marker@toc(r2) 88 ld r11,exception_marker@toc(r2)
89 std r11,-16(r9) /* "regshere" marker */ 89 std r11,-16(r9) /* "regshere" marker */
90 li r10,1
91 stb r10,PACASOFTIRQEN(r13)
92 stb r10,PACAHARDIRQEN(r13)
93 std r10,SOFTE(r1)
90#ifdef CONFIG_PPC_ISERIES 94#ifdef CONFIG_PPC_ISERIES
91BEGIN_FW_FTR_SECTION 95BEGIN_FW_FTR_SECTION
92 /* Hack for handling interrupts when soft-enabling on iSeries */ 96 /* Hack for handling interrupts when soft-enabling on iSeries */
93 cmpdi cr1,r0,0x5555 /* syscall 0x5555 */ 97 cmpdi cr1,r0,0x5555 /* syscall 0x5555 */
94 andi. r10,r12,MSR_PR /* from kernel */ 98 andi. r10,r12,MSR_PR /* from kernel */
95 crand 4*cr0+eq,4*cr1+eq,4*cr0+eq 99 crand 4*cr0+eq,4*cr1+eq,4*cr0+eq
96 beq hardware_interrupt_entry 100 bne 2f
97 lbz r10,PACAPROCENABLED(r13) 101 b hardware_interrupt_entry
98 std r10,SOFTE(r1) 1022:
99END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) 103END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
100#endif 104#endif
101 mfmsr r11 105 mfmsr r11
@@ -460,9 +464,9 @@ _GLOBAL(ret_from_except_lite)
460#endif 464#endif
461 465
462restore: 466restore:
467 ld r5,SOFTE(r1)
463#ifdef CONFIG_PPC_ISERIES 468#ifdef CONFIG_PPC_ISERIES
464BEGIN_FW_FTR_SECTION 469BEGIN_FW_FTR_SECTION
465 ld r5,SOFTE(r1)
466 cmpdi 0,r5,0 470 cmpdi 0,r5,0
467 beq 4f 471 beq 4f
468 /* Check for pending interrupts (iSeries) */ 472 /* Check for pending interrupts (iSeries) */
@@ -472,21 +476,25 @@ BEGIN_FW_FTR_SECTION
472 beq+ 4f /* skip do_IRQ if no interrupts */ 476 beq+ 4f /* skip do_IRQ if no interrupts */
473 477
474 li r3,0 478 li r3,0
475 stb r3,PACAPROCENABLED(r13) /* ensure we are soft-disabled */ 479 stb r3,PACASOFTIRQEN(r13) /* ensure we are soft-disabled */
476 ori r10,r10,MSR_EE 480 ori r10,r10,MSR_EE
477 mtmsrd r10 /* hard-enable again */ 481 mtmsrd r10 /* hard-enable again */
478 addi r3,r1,STACK_FRAME_OVERHEAD 482 addi r3,r1,STACK_FRAME_OVERHEAD
479 bl .do_IRQ 483 bl .do_IRQ
480 b .ret_from_except_lite /* loop back and handle more */ 484 b .ret_from_except_lite /* loop back and handle more */
481 4854:
4824: stb r5,PACAPROCENABLED(r13)
483END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) 486END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
484#endif 487#endif
488 stb r5,PACASOFTIRQEN(r13)
485 489
486 ld r3,_MSR(r1) 490 ld r3,_MSR(r1)
487 andi. r0,r3,MSR_RI 491 andi. r0,r3,MSR_RI
488 beq- unrecov_restore 492 beq- unrecov_restore
489 493
494 /* extract EE bit and use it to restore paca->hard_enabled */
495 rldicl r4,r3,49,63 /* r0 = (r3 >> 15) & 1 */
496 stb r4,PACAHARDIRQEN(r13)
497
490 andi. r0,r3,MSR_PR 498 andi. r0,r3,MSR_PR
491 499
492 /* 500 /*
@@ -538,25 +546,15 @@ do_work:
538 /* Check that preempt_count() == 0 and interrupts are enabled */ 546 /* Check that preempt_count() == 0 and interrupts are enabled */
539 lwz r8,TI_PREEMPT(r9) 547 lwz r8,TI_PREEMPT(r9)
540 cmpwi cr1,r8,0 548 cmpwi cr1,r8,0
541#ifdef CONFIG_PPC_ISERIES
542BEGIN_FW_FTR_SECTION
543 ld r0,SOFTE(r1) 549 ld r0,SOFTE(r1)
544 cmpdi r0,0 550 cmpdi r0,0
545END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
546#endif
547BEGIN_FW_FTR_SECTION
548 andi. r0,r3,MSR_EE
549END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
550 crandc eq,cr1*4+eq,eq 551 crandc eq,cr1*4+eq,eq
551 bne restore 552 bne restore
552 /* here we are preempting the current task */ 553 /* here we are preempting the current task */
5531: 5541:
554#ifdef CONFIG_PPC_ISERIES
555BEGIN_FW_FTR_SECTION
556 li r0,1 555 li r0,1
557 stb r0,PACAPROCENABLED(r13) 556 stb r0,PACASOFTIRQEN(r13)
558END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) 557 stb r0,PACAHARDIRQEN(r13)
559#endif
560 ori r10,r10,MSR_EE 558 ori r10,r10,MSR_EE
561 mtmsrd r10,1 /* reenable interrupts */ 559 mtmsrd r10,1 /* reenable interrupts */
562 bl .preempt_schedule 560 bl .preempt_schedule
@@ -639,8 +637,7 @@ _GLOBAL(enter_rtas)
639 /* There is no way it is acceptable to get here with interrupts enabled, 637 /* There is no way it is acceptable to get here with interrupts enabled,
640 * check it with the asm equivalent of WARN_ON 638 * check it with the asm equivalent of WARN_ON
641 */ 639 */
642 mfmsr r6 640 lbz r0,PACASOFTIRQEN(r13)
643 andi. r0,r6,MSR_EE
6441: tdnei r0,0 6411: tdnei r0,0
645.section __bug_table,"a" 642.section __bug_table,"a"
646 .llong 1b,__LINE__ + 0x1000000, 1f, 2f 643 .llong 1b,__LINE__ + 0x1000000, 1f, 2f
@@ -649,7 +646,13 @@ _GLOBAL(enter_rtas)
6491: .asciz __FILE__ 6461: .asciz __FILE__
6502: .asciz "enter_rtas" 6472: .asciz "enter_rtas"
651.previous 648.previous
652 649
650 /* Hard-disable interrupts */
651 mfmsr r6
652 rldicl r7,r6,48,1
653 rotldi r7,r7,16
654 mtmsrd r7,1
655
653 /* Unfortunately, the stack pointer and the MSR are also clobbered, 656 /* Unfortunately, the stack pointer and the MSR are also clobbered,
654 * so they are saved in the PACA which allows us to restore 657 * so they are saved in the PACA which allows us to restore
655 * our original state after RTAS returns. 658 * our original state after RTAS returns.
@@ -735,8 +738,6 @@ _STATIC(rtas_restore_regs)
735 738
736#endif /* CONFIG_PPC_RTAS */ 739#endif /* CONFIG_PPC_RTAS */
737 740
738#ifdef CONFIG_PPC_MULTIPLATFORM
739
740_GLOBAL(enter_prom) 741_GLOBAL(enter_prom)
741 mflr r0 742 mflr r0
742 std r0,16(r1) 743 std r0,16(r1)
@@ -821,5 +822,3 @@ _GLOBAL(enter_prom)
821 ld r0,16(r1) 822 ld r0,16(r1)
822 mtlr r0 823 mtlr r0
823 blr 824 blr
824
825#endif /* CONFIG_PPC_MULTIPLATFORM */
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index e720729f3e55..71b1fe58e9e4 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -35,9 +35,7 @@
35#include <asm/thread_info.h> 35#include <asm/thread_info.h>
36#include <asm/firmware.h> 36#include <asm/firmware.h>
37 37
38#ifdef CONFIG_PPC_ISERIES
39#define DO_SOFT_DISABLE 38#define DO_SOFT_DISABLE
40#endif
41 39
42/* 40/*
43 * We layout physical memory as follows: 41 * We layout physical memory as follows:
@@ -74,13 +72,11 @@
74 .text 72 .text
75 .globl _stext 73 .globl _stext
76_stext: 74_stext:
77#ifdef CONFIG_PPC_MULTIPLATFORM
78_GLOBAL(__start) 75_GLOBAL(__start)
79 /* NOP this out unconditionally */ 76 /* NOP this out unconditionally */
80BEGIN_FTR_SECTION 77BEGIN_FTR_SECTION
81 b .__start_initialization_multiplatform 78 b .__start_initialization_multiplatform
82END_FTR_SECTION(0, 1) 79END_FTR_SECTION(0, 1)
83#endif /* CONFIG_PPC_MULTIPLATFORM */
84 80
85 /* Catch branch to 0 in real mode */ 81 /* Catch branch to 0 in real mode */
86 trap 82 trap
@@ -308,7 +304,9 @@ exception_marker:
308 std r9,_LINK(r1); \ 304 std r9,_LINK(r1); \
309 mfctr r10; /* save CTR in stackframe */ \ 305 mfctr r10; /* save CTR in stackframe */ \
310 std r10,_CTR(r1); \ 306 std r10,_CTR(r1); \
307 lbz r10,PACASOFTIRQEN(r13); \
311 mfspr r11,SPRN_XER; /* save XER in stackframe */ \ 308 mfspr r11,SPRN_XER; /* save XER in stackframe */ \
309 std r10,SOFTE(r1); \
312 std r11,_XER(r1); \ 310 std r11,_XER(r1); \
313 li r9,(n)+1; \ 311 li r9,(n)+1; \
314 std r9,_TRAP(r1); /* set trap number */ \ 312 std r9,_TRAP(r1); /* set trap number */ \
@@ -343,6 +341,34 @@ label##_pSeries: \
343 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) 341 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)
344 342
345 343
344#define MASKABLE_EXCEPTION_PSERIES(n, label) \
345 . = n; \
346 .globl label##_pSeries; \
347label##_pSeries: \
348 HMT_MEDIUM; \
349 mtspr SPRN_SPRG1,r13; /* save r13 */ \
350 mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \
351 std r9,PACA_EXGEN+EX_R9(r13); /* save r9, r10 */ \
352 std r10,PACA_EXGEN+EX_R10(r13); \
353 lbz r10,PACASOFTIRQEN(r13); \
354 mfcr r9; \
355 cmpwi r10,0; \
356 beq masked_interrupt; \
357 mfspr r10,SPRN_SPRG1; \
358 std r10,PACA_EXGEN+EX_R13(r13); \
359 std r11,PACA_EXGEN+EX_R11(r13); \
360 std r12,PACA_EXGEN+EX_R12(r13); \
361 clrrdi r12,r13,32; /* get high part of &label */ \
362 mfmsr r10; \
363 mfspr r11,SPRN_SRR0; /* save SRR0 */ \
364 LOAD_HANDLER(r12,label##_common) \
365 ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \
366 mtspr SPRN_SRR0,r12; \
367 mfspr r12,SPRN_SRR1; /* and SRR1 */ \
368 mtspr SPRN_SRR1,r10; \
369 rfid; \
370 b . /* prevent speculative execution */
371
346#define STD_EXCEPTION_ISERIES(n, label, area) \ 372#define STD_EXCEPTION_ISERIES(n, label, area) \
347 .globl label##_iSeries; \ 373 .globl label##_iSeries; \
348label##_iSeries: \ 374label##_iSeries: \
@@ -358,40 +384,32 @@ label##_iSeries: \
358 HMT_MEDIUM; \ 384 HMT_MEDIUM; \
359 mtspr SPRN_SPRG1,r13; /* save r13 */ \ 385 mtspr SPRN_SPRG1,r13; /* save r13 */ \
360 EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \ 386 EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \
361 lbz r10,PACAPROCENABLED(r13); \ 387 lbz r10,PACASOFTIRQEN(r13); \
362 cmpwi 0,r10,0; \ 388 cmpwi 0,r10,0; \
363 beq- label##_iSeries_masked; \ 389 beq- label##_iSeries_masked; \
364 EXCEPTION_PROLOG_ISERIES_2; \ 390 EXCEPTION_PROLOG_ISERIES_2; \
365 b label##_common; \ 391 b label##_common; \
366 392
367#ifdef DO_SOFT_DISABLE 393#ifdef CONFIG_PPC_ISERIES
368#define DISABLE_INTS \ 394#define DISABLE_INTS \
369BEGIN_FW_FTR_SECTION; \
370 lbz r10,PACAPROCENABLED(r13); \
371 li r11,0; \ 395 li r11,0; \
372 std r10,SOFTE(r1); \ 396 stb r11,PACASOFTIRQEN(r13); \
397BEGIN_FW_FTR_SECTION; \
398 stb r11,PACAHARDIRQEN(r13); \
399END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \
400BEGIN_FW_FTR_SECTION; \
373 mfmsr r10; \ 401 mfmsr r10; \
374 stb r11,PACAPROCENABLED(r13); \
375 ori r10,r10,MSR_EE; \ 402 ori r10,r10,MSR_EE; \
376 mtmsrd r10,1; \ 403 mtmsrd r10,1; \
377END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) 404END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
378 405
379#define ENABLE_INTS \ 406#else
380BEGIN_FW_FTR_SECTION; \ 407#define DISABLE_INTS \
381 lbz r10,PACAPROCENABLED(r13); \ 408 li r11,0; \
382 mfmsr r11; \ 409 stb r11,PACASOFTIRQEN(r13); \
383 std r10,SOFTE(r1); \ 410 stb r11,PACAHARDIRQEN(r13)
384 ori r11,r11,MSR_EE; \
385END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES); \
386BEGIN_FW_FTR_SECTION; \
387 ld r12,_MSR(r1); \
388 mfmsr r11; \
389 rlwimi r11,r12,0,MSR_EE; \
390END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \
391 mtmsrd r11,1
392 411
393#else /* hard enable/disable interrupts */ 412#endif /* CONFIG_PPC_ISERIES */
394#define DISABLE_INTS
395 413
396#define ENABLE_INTS \ 414#define ENABLE_INTS \
397 ld r12,_MSR(r1); \ 415 ld r12,_MSR(r1); \
@@ -399,8 +417,6 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \
399 rlwimi r11,r12,0,MSR_EE; \ 417 rlwimi r11,r12,0,MSR_EE; \
400 mtmsrd r11,1 418 mtmsrd r11,1
401 419
402#endif
403
404#define STD_EXCEPTION_COMMON(trap, label, hdlr) \ 420#define STD_EXCEPTION_COMMON(trap, label, hdlr) \
405 .align 7; \ 421 .align 7; \
406 .globl label##_common; \ 422 .globl label##_common; \
@@ -541,11 +557,11 @@ instruction_access_slb_pSeries:
541 mfspr r12,SPRN_SRR1 /* and SRR1 */ 557 mfspr r12,SPRN_SRR1 /* and SRR1 */
542 b .slb_miss_realmode /* Rel. branch works in real mode */ 558 b .slb_miss_realmode /* Rel. branch works in real mode */
543 559
544 STD_EXCEPTION_PSERIES(0x500, hardware_interrupt) 560 MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt)
545 STD_EXCEPTION_PSERIES(0x600, alignment) 561 STD_EXCEPTION_PSERIES(0x600, alignment)
546 STD_EXCEPTION_PSERIES(0x700, program_check) 562 STD_EXCEPTION_PSERIES(0x700, program_check)
547 STD_EXCEPTION_PSERIES(0x800, fp_unavailable) 563 STD_EXCEPTION_PSERIES(0x800, fp_unavailable)
548 STD_EXCEPTION_PSERIES(0x900, decrementer) 564 MASKABLE_EXCEPTION_PSERIES(0x900, decrementer)
549 STD_EXCEPTION_PSERIES(0xa00, trap_0a) 565 STD_EXCEPTION_PSERIES(0xa00, trap_0a)
550 STD_EXCEPTION_PSERIES(0xb00, trap_0b) 566 STD_EXCEPTION_PSERIES(0xb00, trap_0b)
551 567
@@ -597,7 +613,24 @@ system_call_pSeries:
597/*** pSeries interrupt support ***/ 613/*** pSeries interrupt support ***/
598 614
599 /* moved from 0xf00 */ 615 /* moved from 0xf00 */
600 STD_EXCEPTION_PSERIES(., performance_monitor) 616 MASKABLE_EXCEPTION_PSERIES(., performance_monitor)
617
618/*
619 * An interrupt came in while soft-disabled; clear EE in SRR1,
620 * clear paca->hard_enabled and return.
621 */
622masked_interrupt:
623 stb r10,PACAHARDIRQEN(r13)
624 mtcrf 0x80,r9
625 ld r9,PACA_EXGEN+EX_R9(r13)
626 mfspr r10,SPRN_SRR1
627 rldicl r10,r10,48,1 /* clear MSR_EE */
628 rotldi r10,r10,16
629 mtspr SPRN_SRR1,r10
630 ld r10,PACA_EXGEN+EX_R10(r13)
631 mfspr r13,SPRN_SPRG1
632 rfid
633 b .
601 634
602 .align 7 635 .align 7
603do_stab_bolted_pSeries: 636do_stab_bolted_pSeries:
@@ -792,7 +825,7 @@ system_reset_iSeries:
792 825
793 cmpwi 0,r23,0 826 cmpwi 0,r23,0
794 beq iSeries_secondary_smp_loop /* Loop until told to go */ 827 beq iSeries_secondary_smp_loop /* Loop until told to go */
795 bne .__secondary_start /* Loop until told to go */ 828 bne __secondary_start /* Loop until told to go */
796iSeries_secondary_smp_loop: 829iSeries_secondary_smp_loop:
797 /* Let the Hypervisor know we are alive */ 830 /* Let the Hypervisor know we are alive */
798 /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */ 831 /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
@@ -813,7 +846,6 @@ iSeries_secondary_smp_loop:
813 b 1b /* If SMP not configured, secondaries 846 b 1b /* If SMP not configured, secondaries
814 * loop forever */ 847 * loop forever */
815 848
816 .globl decrementer_iSeries_masked
817decrementer_iSeries_masked: 849decrementer_iSeries_masked:
818 /* We may not have a valid TOC pointer in here. */ 850 /* We may not have a valid TOC pointer in here. */
819 li r11,1 851 li r11,1
@@ -824,7 +856,6 @@ decrementer_iSeries_masked:
824 mtspr SPRN_DEC,r12 856 mtspr SPRN_DEC,r12
825 /* fall through */ 857 /* fall through */
826 858
827 .globl hardware_interrupt_iSeries_masked
828hardware_interrupt_iSeries_masked: 859hardware_interrupt_iSeries_masked:
829 mtcrf 0x80,r9 /* Restore regs */ 860 mtcrf 0x80,r9 /* Restore regs */
830 ld r12,PACALPPACAPTR(r13) 861 ld r12,PACALPPACAPTR(r13)
@@ -926,10 +957,18 @@ bad_stack:
926 * any task or sent any task a signal, you should use 957 * any task or sent any task a signal, you should use
927 * ret_from_except or ret_from_except_lite instead of this. 958 * ret_from_except or ret_from_except_lite instead of this.
928 */ 959 */
960fast_exc_return_irq: /* restores irq state too */
961 ld r3,SOFTE(r1)
962 ld r12,_MSR(r1)
963 stb r3,PACASOFTIRQEN(r13) /* restore paca->soft_enabled */
964 rldicl r4,r12,49,63 /* get MSR_EE to LSB */
965 stb r4,PACAHARDIRQEN(r13) /* restore paca->hard_enabled */
966 b 1f
967
929 .globl fast_exception_return 968 .globl fast_exception_return
930fast_exception_return: 969fast_exception_return:
931 ld r12,_MSR(r1) 970 ld r12,_MSR(r1)
932 ld r11,_NIP(r1) 9711: ld r11,_NIP(r1)
933 andi. r3,r12,MSR_RI /* check if RI is set */ 972 andi. r3,r12,MSR_RI /* check if RI is set */
934 beq- unrecov_fer 973 beq- unrecov_fer
935 974
@@ -952,7 +991,8 @@ fast_exception_return:
952 REST_8GPRS(2, r1) 991 REST_8GPRS(2, r1)
953 992
954 mfmsr r10 993 mfmsr r10
955 clrrdi r10,r10,2 /* clear RI (LE is 0 already) */ 994 rldicl r10,r10,48,1 /* clear EE */
995 rldicr r10,r10,16,61 /* clear RI (LE is 0 already) */
956 mtmsrd r10,1 996 mtmsrd r10,1
957 997
958 mtspr SPRN_SRR1,r12 998 mtspr SPRN_SRR1,r12
@@ -1326,6 +1366,16 @@ BEGIN_FW_FTR_SECTION
1326 * interrupts if necessary. 1366 * interrupts if necessary.
1327 */ 1367 */
1328 beq 13f 1368 beq 13f
1369END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
1370#endif
1371BEGIN_FW_FTR_SECTION
1372 /*
1373 * Here we have interrupts hard-disabled, so it is sufficient
1374 * to restore paca->{soft,hard}_enable and get out.
1375 */
1376 beq fast_exc_return_irq /* Return from exception on success */
1377END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
1378
1329 /* For a hash failure, we don't bother re-enabling interrupts */ 1379 /* For a hash failure, we don't bother re-enabling interrupts */
1330 ble- 12f 1380 ble- 12f
1331 1381
@@ -1337,14 +1387,6 @@ BEGIN_FW_FTR_SECTION
1337 ld r3,SOFTE(r1) 1387 ld r3,SOFTE(r1)
1338 bl .local_irq_restore 1388 bl .local_irq_restore
1339 b 11f 1389 b 11f
1340END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
1341#endif
1342BEGIN_FW_FTR_SECTION
1343 beq fast_exception_return /* Return from exception on success */
1344 ble- 12f /* Failure return from hash_page */
1345
1346 /* fall through */
1347END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
1348 1390
1349/* Here we have a page fault that hash_page can't handle. */ 1391/* Here we have a page fault that hash_page can't handle. */
1350handle_page_fault: 1392handle_page_fault:
@@ -1362,6 +1404,8 @@ handle_page_fault:
1362 bl .bad_page_fault 1404 bl .bad_page_fault
1363 b .ret_from_except 1405 b .ret_from_except
1364 1406
140713: b .ret_from_except_lite
1408
1365/* We have a page fault that hash_page could handle but HV refused 1409/* We have a page fault that hash_page could handle but HV refused
1366 * the PTE insertion 1410 * the PTE insertion
1367 */ 1411 */
@@ -1371,8 +1415,6 @@ handle_page_fault:
1371 bl .low_hash_fault 1415 bl .low_hash_fault
1372 b .ret_from_except 1416 b .ret_from_except
1373 1417
137413: b .ret_from_except_lite
1375
1376 /* here we have a segment miss */ 1418 /* here we have a segment miss */
1377do_ste_alloc: 1419do_ste_alloc:
1378 bl .ste_allocate /* try to insert stab entry */ 1420 bl .ste_allocate /* try to insert stab entry */
@@ -1560,7 +1602,7 @@ _GLOBAL(generic_secondary_smp_init)
1560 ld r1,PACAEMERGSP(r13) 1602 ld r1,PACAEMERGSP(r13)
1561 subi r1,r1,STACK_FRAME_OVERHEAD 1603 subi r1,r1,STACK_FRAME_OVERHEAD
1562 1604
1563 b .__secondary_start 1605 b __secondary_start
1564#endif 1606#endif
1565 1607
1566#ifdef CONFIG_PPC_ISERIES 1608#ifdef CONFIG_PPC_ISERIES
@@ -1595,7 +1637,6 @@ _STATIC(__start_initialization_iSeries)
1595 b .start_here_common 1637 b .start_here_common
1596#endif /* CONFIG_PPC_ISERIES */ 1638#endif /* CONFIG_PPC_ISERIES */
1597 1639
1598#ifdef CONFIG_PPC_MULTIPLATFORM
1599 1640
1600_STATIC(__mmu_off) 1641_STATIC(__mmu_off)
1601 mfmsr r3 1642 mfmsr r3
@@ -1621,13 +1662,11 @@ _STATIC(__mmu_off)
1621 * 1662 *
1622 */ 1663 */
1623_GLOBAL(__start_initialization_multiplatform) 1664_GLOBAL(__start_initialization_multiplatform)
1624#ifdef CONFIG_PPC_MULTIPLATFORM
1625 /* 1665 /*
1626 * Are we booted from a PROM Of-type client-interface ? 1666 * Are we booted from a PROM Of-type client-interface ?
1627 */ 1667 */
1628 cmpldi cr0,r5,0 1668 cmpldi cr0,r5,0
1629 bne .__boot_from_prom /* yes -> prom */ 1669 bne .__boot_from_prom /* yes -> prom */
1630#endif
1631 1670
1632 /* Save parameters */ 1671 /* Save parameters */
1633 mr r31,r3 1672 mr r31,r3
@@ -1656,7 +1695,6 @@ _GLOBAL(__start_initialization_multiplatform)
1656 bl .__mmu_off 1695 bl .__mmu_off
1657 b .__after_prom_start 1696 b .__after_prom_start
1658 1697
1659#ifdef CONFIG_PPC_MULTIPLATFORM
1660_STATIC(__boot_from_prom) 1698_STATIC(__boot_from_prom)
1661 /* Save parameters */ 1699 /* Save parameters */
1662 mr r31,r3 1700 mr r31,r3
@@ -1696,7 +1734,6 @@ _STATIC(__boot_from_prom)
1696 bl .prom_init 1734 bl .prom_init
1697 /* We never return */ 1735 /* We never return */
1698 trap 1736 trap
1699#endif
1700 1737
1701/* 1738/*
1702 * At this point, r3 contains the physical address we are running at, 1739 * At this point, r3 contains the physical address we are running at,
@@ -1752,8 +1789,6 @@ _STATIC(__after_prom_start)
1752 bl .copy_and_flush /* copy the rest */ 1789 bl .copy_and_flush /* copy the rest */
1753 b .start_here_multiplatform 1790 b .start_here_multiplatform
1754 1791
1755#endif /* CONFIG_PPC_MULTIPLATFORM */
1756
1757/* 1792/*
1758 * Copy routine used to copy the kernel to start at physical address 0 1793 * Copy routine used to copy the kernel to start at physical address 0
1759 * and flush and invalidate the caches as needed. 1794 * and flush and invalidate the caches as needed.
@@ -1836,7 +1871,7 @@ _GLOBAL(pmac_secondary_start)
1836 ld r1,PACAEMERGSP(r13) 1871 ld r1,PACAEMERGSP(r13)
1837 subi r1,r1,STACK_FRAME_OVERHEAD 1872 subi r1,r1,STACK_FRAME_OVERHEAD
1838 1873
1839 b .__secondary_start 1874 b __secondary_start
1840 1875
1841#endif /* CONFIG_PPC_PMAC */ 1876#endif /* CONFIG_PPC_PMAC */
1842 1877
@@ -1853,7 +1888,7 @@ _GLOBAL(pmac_secondary_start)
1853 * r13 = paca virtual address 1888 * r13 = paca virtual address
1854 * SPRG3 = paca virtual address 1889 * SPRG3 = paca virtual address
1855 */ 1890 */
1856_GLOBAL(__secondary_start) 1891__secondary_start:
1857 /* Set thread priority to MEDIUM */ 1892 /* Set thread priority to MEDIUM */
1858 HMT_MEDIUM 1893 HMT_MEDIUM
1859 1894
@@ -1877,11 +1912,16 @@ _GLOBAL(__secondary_start)
1877 /* enable MMU and jump to start_secondary */ 1912 /* enable MMU and jump to start_secondary */
1878 LOAD_REG_ADDR(r3, .start_secondary_prolog) 1913 LOAD_REG_ADDR(r3, .start_secondary_prolog)
1879 LOAD_REG_IMMEDIATE(r4, MSR_KERNEL) 1914 LOAD_REG_IMMEDIATE(r4, MSR_KERNEL)
1880#ifdef DO_SOFT_DISABLE 1915#ifdef CONFIG_PPC_ISERIES
1881BEGIN_FW_FTR_SECTION 1916BEGIN_FW_FTR_SECTION
1882 ori r4,r4,MSR_EE 1917 ori r4,r4,MSR_EE
1883END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) 1918END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
1884#endif 1919#endif
1920BEGIN_FW_FTR_SECTION
1921 stb r7,PACASOFTIRQEN(r13)
1922 stb r7,PACAHARDIRQEN(r13)
1923END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
1924
1885 mtspr SPRN_SRR0,r3 1925 mtspr SPRN_SRR0,r3
1886 mtspr SPRN_SRR1,r4 1926 mtspr SPRN_SRR1,r4
1887 rfid 1927 rfid
@@ -1913,7 +1953,6 @@ _GLOBAL(enable_64b_mode)
1913 isync 1953 isync
1914 blr 1954 blr
1915 1955
1916#ifdef CONFIG_PPC_MULTIPLATFORM
1917/* 1956/*
1918 * This is where the main kernel code starts. 1957 * This is where the main kernel code starts.
1919 */ 1958 */
@@ -1977,7 +2016,6 @@ _STATIC(start_here_multiplatform)
1977 mtspr SPRN_SRR1,r4 2016 mtspr SPRN_SRR1,r4
1978 rfid 2017 rfid
1979 b . /* prevent speculative execution */ 2018 b . /* prevent speculative execution */
1980#endif /* CONFIG_PPC_MULTIPLATFORM */
1981 2019
1982 /* This is where all platforms converge execution */ 2020 /* This is where all platforms converge execution */
1983_STATIC(start_here_common) 2021_STATIC(start_here_common)
@@ -2005,15 +2043,18 @@ _STATIC(start_here_common)
2005 2043
2006 /* Load up the kernel context */ 2044 /* Load up the kernel context */
20075: 20455:
2008#ifdef DO_SOFT_DISABLE
2009BEGIN_FW_FTR_SECTION
2010 li r5,0 2046 li r5,0
2011 stb r5,PACAPROCENABLED(r13) /* Soft Disabled */ 2047 stb r5,PACASOFTIRQEN(r13) /* Soft Disabled */
2048#ifdef CONFIG_PPC_ISERIES
2049BEGIN_FW_FTR_SECTION
2012 mfmsr r5 2050 mfmsr r5
2013 ori r5,r5,MSR_EE /* Hard Enabled */ 2051 ori r5,r5,MSR_EE /* Hard Enabled */
2014 mtmsrd r5 2052 mtmsrd r5
2015END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) 2053END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
2016#endif 2054#endif
2055BEGIN_FW_FTR_SECTION
2056 stb r5,PACAHARDIRQEN(r13)
2057END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
2017 2058
2018 bl .start_kernel 2059 bl .start_kernel
2019 2060
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index 39db7a3affe1..82bd2f10770f 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -112,7 +112,7 @@ static int ibmebus_dma_supported(struct device *dev, u64 mask)
112 return 1; 112 return 1;
113} 113}
114 114
115struct dma_mapping_ops ibmebus_dma_ops = { 115static struct dma_mapping_ops ibmebus_dma_ops = {
116 .alloc_coherent = ibmebus_alloc_coherent, 116 .alloc_coherent = ibmebus_alloc_coherent,
117 .free_coherent = ibmebus_free_coherent, 117 .free_coherent = ibmebus_free_coherent,
118 .map_single = ibmebus_map_single, 118 .map_single = ibmebus_map_single,
@@ -176,6 +176,10 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_common(
176 dev->ofdev.dev.bus = &ibmebus_bus_type; 176 dev->ofdev.dev.bus = &ibmebus_bus_type;
177 dev->ofdev.dev.release = ibmebus_dev_release; 177 dev->ofdev.dev.release = ibmebus_dev_release;
178 178
179 dev->ofdev.dev.archdata.of_node = dev->ofdev.node;
180 dev->ofdev.dev.archdata.dma_ops = &ibmebus_dma_ops;
181 dev->ofdev.dev.archdata.numa_node = of_node_to_nid(dev->ofdev.node);
182
179 /* An ibmebusdev is based on a of_device. We have to change the 183 /* An ibmebusdev is based on a of_device. We have to change the
180 * bus type to use our own DMA mapping operations. 184 * bus type to use our own DMA mapping operations.
181 */ 185 */
@@ -210,11 +214,10 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_node(
210 return NULL; 214 return NULL;
211 } 215 }
212 216
213 dev = kmalloc(sizeof(struct ibmebus_dev), GFP_KERNEL); 217 dev = kzalloc(sizeof(struct ibmebus_dev), GFP_KERNEL);
214 if (!dev) { 218 if (!dev) {
215 return NULL; 219 return NULL;
216 } 220 }
217 memset(dev, 0, sizeof(struct ibmebus_dev));
218 221
219 dev->ofdev.node = of_node_get(dn); 222 dev->ofdev.node = of_node_get(dn);
220 223
diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c
index 4180c3998b39..8994af327b47 100644
--- a/arch/powerpc/kernel/idle.c
+++ b/arch/powerpc/kernel/idle.c
@@ -39,6 +39,13 @@
39#define cpu_should_die() 0 39#define cpu_should_die() 0
40#endif 40#endif
41 41
42static int __init powersave_off(char *arg)
43{
44 ppc_md.power_save = NULL;
45 return 0;
46}
47__setup("powersave=off", powersave_off);
48
42/* 49/*
43 * The body of the idle task. 50 * The body of the idle task.
44 */ 51 */
diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S
index 30de81da7b40..ba3195478600 100644
--- a/arch/powerpc/kernel/idle_power4.S
+++ b/arch/powerpc/kernel/idle_power4.S
@@ -30,6 +30,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
30 beqlr 30 beqlr
31 31
32 /* Go to NAP now */ 32 /* Go to NAP now */
33 mfmsr r7
34 rldicl r0,r7,48,1
35 rotldi r0,r0,16
36 mtmsrd r0,1 /* hard-disable interrupts */
37 li r0,1
38 stb r0,PACASOFTIRQEN(r13) /* we'll hard-enable shortly */
39 stb r0,PACAHARDIRQEN(r13)
33BEGIN_FTR_SECTION 40BEGIN_FTR_SECTION
34 DSSALL 41 DSSALL
35 sync 42 sync
@@ -38,7 +45,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
38 ld r8,TI_LOCAL_FLAGS(r9) /* set napping bit */ 45 ld r8,TI_LOCAL_FLAGS(r9) /* set napping bit */
39 ori r8,r8,_TLF_NAPPING /* so when we take an exception */ 46 ori r8,r8,_TLF_NAPPING /* so when we take an exception */
40 std r8,TI_LOCAL_FLAGS(r9) /* it will return to our caller */ 47 std r8,TI_LOCAL_FLAGS(r9) /* it will return to our caller */
41 mfmsr r7
42 ori r7,r7,MSR_EE 48 ori r7,r7,MSR_EE
43 oris r7,r7,MSR_POW@h 49 oris r7,r7,MSR_POW@h
441: sync 501: sync
diff --git a/arch/powerpc/kernel/io.c b/arch/powerpc/kernel/io.c
index e98180686b35..34ae11494ddc 100644
--- a/arch/powerpc/kernel/io.c
+++ b/arch/powerpc/kernel/io.c
@@ -25,13 +25,11 @@
25#include <asm/firmware.h> 25#include <asm/firmware.h>
26#include <asm/bug.h> 26#include <asm/bug.h>
27 27
28void _insb(volatile u8 __iomem *port, void *buf, long count) 28void _insb(const volatile u8 __iomem *port, void *buf, long count)
29{ 29{
30 u8 *tbuf = buf; 30 u8 *tbuf = buf;
31 u8 tmp; 31 u8 tmp;
32 32
33 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
34
35 if (unlikely(count <= 0)) 33 if (unlikely(count <= 0))
36 return; 34 return;
37 asm volatile("sync"); 35 asm volatile("sync");
@@ -48,8 +46,6 @@ void _outsb(volatile u8 __iomem *port, const void *buf, long count)
48{ 46{
49 const u8 *tbuf = buf; 47 const u8 *tbuf = buf;
50 48
51 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
52
53 if (unlikely(count <= 0)) 49 if (unlikely(count <= 0))
54 return; 50 return;
55 asm volatile("sync"); 51 asm volatile("sync");
@@ -60,13 +56,11 @@ void _outsb(volatile u8 __iomem *port, const void *buf, long count)
60} 56}
61EXPORT_SYMBOL(_outsb); 57EXPORT_SYMBOL(_outsb);
62 58
63void _insw_ns(volatile u16 __iomem *port, void *buf, long count) 59void _insw_ns(const volatile u16 __iomem *port, void *buf, long count)
64{ 60{
65 u16 *tbuf = buf; 61 u16 *tbuf = buf;
66 u16 tmp; 62 u16 tmp;
67 63
68 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
69
70 if (unlikely(count <= 0)) 64 if (unlikely(count <= 0))
71 return; 65 return;
72 asm volatile("sync"); 66 asm volatile("sync");
@@ -83,8 +77,6 @@ void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count)
83{ 77{
84 const u16 *tbuf = buf; 78 const u16 *tbuf = buf;
85 79
86 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
87
88 if (unlikely(count <= 0)) 80 if (unlikely(count <= 0))
89 return; 81 return;
90 asm volatile("sync"); 82 asm volatile("sync");
@@ -95,13 +87,11 @@ void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count)
95} 87}
96EXPORT_SYMBOL(_outsw_ns); 88EXPORT_SYMBOL(_outsw_ns);
97 89
98void _insl_ns(volatile u32 __iomem *port, void *buf, long count) 90void _insl_ns(const volatile u32 __iomem *port, void *buf, long count)
99{ 91{
100 u32 *tbuf = buf; 92 u32 *tbuf = buf;
101 u32 tmp; 93 u32 tmp;
102 94
103 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
104
105 if (unlikely(count <= 0)) 95 if (unlikely(count <= 0))
106 return; 96 return;
107 asm volatile("sync"); 97 asm volatile("sync");
@@ -118,8 +108,6 @@ void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count)
118{ 108{
119 const u32 *tbuf = buf; 109 const u32 *tbuf = buf;
120 110
121 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
122
123 if (unlikely(count <= 0)) 111 if (unlikely(count <= 0))
124 return; 112 return;
125 asm volatile("sync"); 113 asm volatile("sync");
@@ -129,3 +117,90 @@ void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count)
129 asm volatile("sync"); 117 asm volatile("sync");
130} 118}
131EXPORT_SYMBOL(_outsl_ns); 119EXPORT_SYMBOL(_outsl_ns);
120
121#define IO_CHECK_ALIGN(v,a) ((((unsigned long)(v)) & ((a) - 1)) == 0)
122
123void _memset_io(volatile void __iomem *addr, int c, unsigned long n)
124{
125 void *p = (void __force *)addr;
126 u32 lc = c;
127 lc |= lc << 8;
128 lc |= lc << 16;
129
130 __asm__ __volatile__ ("sync" : : : "memory");
131 while(n && !IO_CHECK_ALIGN(p, 4)) {
132 *((volatile u8 *)p) = c;
133 p++;
134 n--;
135 }
136 while(n >= 4) {
137 *((volatile u32 *)p) = lc;
138 p += 4;
139 n -= 4;
140 }
141 while(n) {
142 *((volatile u8 *)p) = c;
143 p++;
144 n--;
145 }
146 __asm__ __volatile__ ("sync" : : : "memory");
147}
148EXPORT_SYMBOL(_memset_io);
149
150void _memcpy_fromio(void *dest, const volatile void __iomem *src,
151 unsigned long n)
152{
153 void *vsrc = (void __force *) src;
154
155 __asm__ __volatile__ ("sync" : : : "memory");
156 while(n && (!IO_CHECK_ALIGN(vsrc, 4) || !IO_CHECK_ALIGN(dest, 4))) {
157 *((u8 *)dest) = *((volatile u8 *)vsrc);
158 __asm__ __volatile__ ("eieio" : : : "memory");
159 vsrc++;
160 dest++;
161 n--;
162 }
163 while(n > 4) {
164 *((u32 *)dest) = *((volatile u32 *)vsrc);
165 __asm__ __volatile__ ("eieio" : : : "memory");
166 vsrc += 4;
167 dest += 4;
168 n -= 4;
169 }
170 while(n) {
171 *((u8 *)dest) = *((volatile u8 *)vsrc);
172 __asm__ __volatile__ ("eieio" : : : "memory");
173 vsrc++;
174 dest++;
175 n--;
176 }
177 __asm__ __volatile__ ("sync" : : : "memory");
178}
179EXPORT_SYMBOL(_memcpy_fromio);
180
181void _memcpy_toio(volatile void __iomem *dest, const void *src, unsigned long n)
182{
183 void *vdest = (void __force *) dest;
184
185 __asm__ __volatile__ ("sync" : : : "memory");
186 while(n && (!IO_CHECK_ALIGN(vdest, 4) || !IO_CHECK_ALIGN(src, 4))) {
187 *((volatile u8 *)vdest) = *((u8 *)src);
188 src++;
189 vdest++;
190 n--;
191 }
192 while(n > 4) {
193 *((volatile u32 *)vdest) = *((volatile u32 *)src);
194 src += 4;
195 vdest += 4;
196 n-=4;
197 }
198 while(n) {
199 *((volatile u8 *)vdest) = *((u8 *)src);
200 src++;
201 vdest++;
202 n--;
203 }
204 __asm__ __volatile__ ("sync" : : : "memory");
205}
206EXPORT_SYMBOL(_memcpy_toio);
diff --git a/arch/powerpc/kernel/iomap.c b/arch/powerpc/kernel/iomap.c
index a13a93dfc655..c68113371050 100644
--- a/arch/powerpc/kernel/iomap.c
+++ b/arch/powerpc/kernel/iomap.c
@@ -106,7 +106,7 @@ EXPORT_SYMBOL(iowrite32_rep);
106 106
107void __iomem *ioport_map(unsigned long port, unsigned int len) 107void __iomem *ioport_map(unsigned long port, unsigned int len)
108{ 108{
109 return (void __iomem *) (port+pci_io_base); 109 return (void __iomem *) (port + _IO_BASE);
110} 110}
111 111
112void ioport_unmap(void __iomem *addr) 112void ioport_unmap(void __iomem *addr)
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index ba6b7256084b..95edad4faf26 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -258,9 +258,9 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
258 spin_unlock_irqrestore(&(tbl->it_lock), flags); 258 spin_unlock_irqrestore(&(tbl->it_lock), flags);
259} 259}
260 260
261int iommu_map_sg(struct device *dev, struct iommu_table *tbl, 261int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
262 struct scatterlist *sglist, int nelems, 262 int nelems, unsigned long mask,
263 unsigned long mask, enum dma_data_direction direction) 263 enum dma_data_direction direction)
264{ 264{
265 dma_addr_t dma_next = 0, dma_addr; 265 dma_addr_t dma_next = 0, dma_addr;
266 unsigned long flags; 266 unsigned long flags;
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 5e37bf14ef2d..0bd8c7665834 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -64,8 +64,9 @@
64#include <asm/ptrace.h> 64#include <asm/ptrace.h>
65#include <asm/machdep.h> 65#include <asm/machdep.h>
66#include <asm/udbg.h> 66#include <asm/udbg.h>
67#ifdef CONFIG_PPC_ISERIES 67#ifdef CONFIG_PPC64
68#include <asm/paca.h> 68#include <asm/paca.h>
69#include <asm/firmware.h>
69#endif 70#endif
70 71
71int __irq_offset_value; 72int __irq_offset_value;
@@ -95,6 +96,74 @@ extern atomic_t ipi_sent;
95EXPORT_SYMBOL(irq_desc); 96EXPORT_SYMBOL(irq_desc);
96 97
97int distribute_irqs = 1; 98int distribute_irqs = 1;
99
100static inline unsigned long get_hard_enabled(void)
101{
102 unsigned long enabled;
103
104 __asm__ __volatile__("lbz %0,%1(13)"
105 : "=r" (enabled) : "i" (offsetof(struct paca_struct, hard_enabled)));
106
107 return enabled;
108}
109
110static inline void set_soft_enabled(unsigned long enable)
111{
112 __asm__ __volatile__("stb %0,%1(13)"
113 : : "r" (enable), "i" (offsetof(struct paca_struct, soft_enabled)));
114}
115
116void local_irq_restore(unsigned long en)
117{
118 /*
119 * get_paca()->soft_enabled = en;
120 * Is it ever valid to use local_irq_restore(0) when soft_enabled is 1?
121 * That was allowed before, and in such a case we do need to take care
122 * that gcc will set soft_enabled directly via r13, not choose to use
123 * an intermediate register, lest we're preempted to a different cpu.
124 */
125 set_soft_enabled(en);
126 if (!en)
127 return;
128
129 if (firmware_has_feature(FW_FEATURE_ISERIES)) {
130 /*
131 * Do we need to disable preemption here? Not really: in the
132 * unlikely event that we're preempted to a different cpu in
133 * between getting r13, loading its lppaca_ptr, and loading
134 * its any_int, we might call iseries_handle_interrupts without
135 * an interrupt pending on the new cpu, but that's no disaster,
136 * is it? And the business of preempting us off the old cpu
137 * would itself involve a local_irq_restore which handles the
138 * interrupt to that cpu.
139 *
140 * But use "local_paca->lppaca_ptr" instead of "get_lppaca()"
141 * to avoid any preemption checking added into get_paca().
142 */
143 if (local_paca->lppaca_ptr->int_dword.any_int)
144 iseries_handle_interrupts();
145 return;
146 }
147
148 /*
149 * if (get_paca()->hard_enabled) return;
150 * But again we need to take care that gcc gets hard_enabled directly
151 * via r13, not choose to use an intermediate register, lest we're
152 * preempted to a different cpu in between the two instructions.
153 */
154 if (get_hard_enabled())
155 return;
156
157 /*
158 * Need to hard-enable interrupts here. Since currently disabled,
159 * no need to take further asm precautions against preemption; but
160 * use local_paca instead of get_paca() to avoid preemption checking.
161 */
162 local_paca->hard_enabled = en;
163 if ((int)mfspr(SPRN_DEC) < 0)
164 mtspr(SPRN_DEC, 1);
165 hard_irq_enable();
166}
98#endif /* CONFIG_PPC64 */ 167#endif /* CONFIG_PPC64 */
99 168
100int show_interrupts(struct seq_file *p, void *v) 169int show_interrupts(struct seq_file *p, void *v)
@@ -246,7 +315,8 @@ void do_IRQ(struct pt_regs *regs)
246 set_irq_regs(old_regs); 315 set_irq_regs(old_regs);
247 316
248#ifdef CONFIG_PPC_ISERIES 317#ifdef CONFIG_PPC_ISERIES
249 if (get_lppaca()->int_dword.fields.decr_int) { 318 if (firmware_has_feature(FW_FEATURE_ISERIES) &&
319 get_lppaca()->int_dword.fields.decr_int) {
250 get_lppaca()->int_dword.fields.decr_int = 0; 320 get_lppaca()->int_dword.fields.decr_int = 0;
251 /* Signal a fake decrementer interrupt */ 321 /* Signal a fake decrementer interrupt */
252 timer_interrupt(regs); 322 timer_interrupt(regs);
@@ -626,10 +696,14 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
626 696
627void irq_dispose_mapping(unsigned int virq) 697void irq_dispose_mapping(unsigned int virq)
628{ 698{
629 struct irq_host *host = irq_map[virq].host; 699 struct irq_host *host;
630 irq_hw_number_t hwirq; 700 irq_hw_number_t hwirq;
631 unsigned long flags; 701 unsigned long flags;
632 702
703 if (virq == NO_IRQ)
704 return;
705
706 host = irq_map[virq].host;
633 WARN_ON (host == NULL); 707 WARN_ON (host == NULL);
634 if (host == NULL) 708 if (host == NULL)
635 return; 709 return;
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c
index 397c83eda20e..8a06724e029e 100644
--- a/arch/powerpc/kernel/of_device.c
+++ b/arch/powerpc/kernel/of_device.c
@@ -9,30 +9,26 @@
9#include <asm/of_device.h> 9#include <asm/of_device.h>
10 10
11/** 11/**
12 * of_match_device - Tell if an of_device structure has a matching 12 * of_match_node - Tell if an device_node has a matching of_match structure
13 * of_match structure
14 * @ids: array of of device match structures to search in 13 * @ids: array of of device match structures to search in
15 * @dev: the of device structure to match against 14 * @node: the of device structure to match against
16 * 15 *
17 * Used by a driver to check whether an of_device present in the 16 * Low level utility function used by device matching.
18 * system is in its list of supported devices.
19 */ 17 */
20const struct of_device_id *of_match_device(const struct of_device_id *matches, 18const struct of_device_id *of_match_node(const struct of_device_id *matches,
21 const struct of_device *dev) 19 const struct device_node *node)
22{ 20{
23 if (!dev->node)
24 return NULL;
25 while (matches->name[0] || matches->type[0] || matches->compatible[0]) { 21 while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
26 int match = 1; 22 int match = 1;
27 if (matches->name[0]) 23 if (matches->name[0])
28 match &= dev->node->name 24 match &= node->name
29 && !strcmp(matches->name, dev->node->name); 25 && !strcmp(matches->name, node->name);
30 if (matches->type[0]) 26 if (matches->type[0])
31 match &= dev->node->type 27 match &= node->type
32 && !strcmp(matches->type, dev->node->type); 28 && !strcmp(matches->type, node->type);
33 if (matches->compatible[0]) 29 if (matches->compatible[0])
34 match &= device_is_compatible(dev->node, 30 match &= device_is_compatible(node,
35 matches->compatible); 31 matches->compatible);
36 if (match) 32 if (match)
37 return matches; 33 return matches;
38 matches++; 34 matches++;
@@ -40,16 +36,21 @@ const struct of_device_id *of_match_device(const struct of_device_id *matches,
40 return NULL; 36 return NULL;
41} 37}
42 38
43static int of_platform_bus_match(struct device *dev, struct device_driver *drv) 39/**
40 * of_match_device - Tell if an of_device structure has a matching
41 * of_match structure
42 * @ids: array of of device match structures to search in
43 * @dev: the of device structure to match against
44 *
45 * Used by a driver to check whether an of_device present in the
46 * system is in its list of supported devices.
47 */
48const struct of_device_id *of_match_device(const struct of_device_id *matches,
49 const struct of_device *dev)
44{ 50{
45 struct of_device * of_dev = to_of_device(dev); 51 if (!dev->node)
46 struct of_platform_driver * of_drv = to_of_platform_driver(drv); 52 return NULL;
47 const struct of_device_id * matches = of_drv->match_table; 53 return of_match_node(matches, dev->node);
48
49 if (!matches)
50 return 0;
51
52 return of_match_device(matches, of_dev) != NULL;
53} 54}
54 55
55struct of_device *of_dev_get(struct of_device *dev) 56struct of_device *of_dev_get(struct of_device *dev)
@@ -71,96 +72,8 @@ void of_dev_put(struct of_device *dev)
71 put_device(&dev->dev); 72 put_device(&dev->dev);
72} 73}
73 74
74 75static ssize_t dev_show_devspec(struct device *dev,
75static int of_device_probe(struct device *dev) 76 struct device_attribute *attr, char *buf)
76{
77 int error = -ENODEV;
78 struct of_platform_driver *drv;
79 struct of_device *of_dev;
80 const struct of_device_id *match;
81
82 drv = to_of_platform_driver(dev->driver);
83 of_dev = to_of_device(dev);
84
85 if (!drv->probe)
86 return error;
87
88 of_dev_get(of_dev);
89
90 match = of_match_device(drv->match_table, of_dev);
91 if (match)
92 error = drv->probe(of_dev, match);
93 if (error)
94 of_dev_put(of_dev);
95
96 return error;
97}
98
99static int of_device_remove(struct device *dev)
100{
101 struct of_device * of_dev = to_of_device(dev);
102 struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
103
104 if (dev->driver && drv->remove)
105 drv->remove(of_dev);
106 return 0;
107}
108
109static int of_device_suspend(struct device *dev, pm_message_t state)
110{
111 struct of_device * of_dev = to_of_device(dev);
112 struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
113 int error = 0;
114
115 if (dev->driver && drv->suspend)
116 error = drv->suspend(of_dev, state);
117 return error;
118}
119
120static int of_device_resume(struct device * dev)
121{
122 struct of_device * of_dev = to_of_device(dev);
123 struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
124 int error = 0;
125
126 if (dev->driver && drv->resume)
127 error = drv->resume(of_dev);
128 return error;
129}
130
131struct bus_type of_platform_bus_type = {
132 .name = "of_platform",
133 .match = of_platform_bus_match,
134 .probe = of_device_probe,
135 .remove = of_device_remove,
136 .suspend = of_device_suspend,
137 .resume = of_device_resume,
138};
139
140static int __init of_bus_driver_init(void)
141{
142 return bus_register(&of_platform_bus_type);
143}
144
145postcore_initcall(of_bus_driver_init);
146
147int of_register_driver(struct of_platform_driver *drv)
148{
149 /* initialize common driver fields */
150 drv->driver.name = drv->name;
151 drv->driver.bus = &of_platform_bus_type;
152
153 /* register with core */
154 return driver_register(&drv->driver);
155}
156
157void of_unregister_driver(struct of_platform_driver *drv)
158{
159 driver_unregister(&drv->driver);
160}
161
162
163static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
164{ 77{
165 struct of_device *ofdev; 78 struct of_device *ofdev;
166 79
@@ -208,41 +121,11 @@ void of_device_unregister(struct of_device *ofdev)
208 device_unregister(&ofdev->dev); 121 device_unregister(&ofdev->dev);
209} 122}
210 123
211struct of_device* of_platform_device_create(struct device_node *np,
212 const char *bus_id,
213 struct device *parent)
214{
215 struct of_device *dev;
216
217 dev = kmalloc(sizeof(*dev), GFP_KERNEL);
218 if (!dev)
219 return NULL;
220 memset(dev, 0, sizeof(*dev));
221
222 dev->node = of_node_get(np);
223 dev->dma_mask = 0xffffffffUL;
224 dev->dev.dma_mask = &dev->dma_mask;
225 dev->dev.parent = parent;
226 dev->dev.bus = &of_platform_bus_type;
227 dev->dev.release = of_release_dev;
228
229 strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
230
231 if (of_device_register(dev) != 0) {
232 kfree(dev);
233 return NULL;
234 }
235
236 return dev;
237}
238 124
125EXPORT_SYMBOL(of_match_node);
239EXPORT_SYMBOL(of_match_device); 126EXPORT_SYMBOL(of_match_device);
240EXPORT_SYMBOL(of_platform_bus_type);
241EXPORT_SYMBOL(of_register_driver);
242EXPORT_SYMBOL(of_unregister_driver);
243EXPORT_SYMBOL(of_device_register); 127EXPORT_SYMBOL(of_device_register);
244EXPORT_SYMBOL(of_device_unregister); 128EXPORT_SYMBOL(of_device_unregister);
245EXPORT_SYMBOL(of_dev_get); 129EXPORT_SYMBOL(of_dev_get);
246EXPORT_SYMBOL(of_dev_put); 130EXPORT_SYMBOL(of_dev_put);
247EXPORT_SYMBOL(of_platform_device_create);
248EXPORT_SYMBOL(of_release_dev); 131EXPORT_SYMBOL(of_release_dev);
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
new file mode 100644
index 000000000000..b3189d0161b8
--- /dev/null
+++ b/arch/powerpc/kernel/of_platform.c
@@ -0,0 +1,489 @@
1/*
2 * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
3 * <benh@kernel.crashing.org>
4 * and Arnd Bergmann, IBM Corp.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#undef DEBUG
14
15#include <linux/string.h>
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <linux/module.h>
19#include <linux/mod_devicetable.h>
20#include <linux/slab.h>
21#include <linux/pci.h>
22
23#include <asm/errno.h>
24#include <asm/dcr.h>
25#include <asm/of_device.h>
26#include <asm/of_platform.h>
27#include <asm/topology.h>
28#include <asm/pci-bridge.h>
29#include <asm/ppc-pci.h>
30#include <asm/atomic.h>
31
32
33/*
34 * The list of OF IDs below is used for matching bus types in the
35 * system whose devices are to be exposed as of_platform_devices.
36 *
37 * This is the default list valid for most platforms. This file provides
38 * functions who can take an explicit list if necessary though
39 *
40 * The search is always performed recursively looking for children of
41 * the provided device_node and recursively if such a children matches
42 * a bus type in the list
43 */
44
45static struct of_device_id of_default_bus_ids[] = {
46 { .type = "soc", },
47 { .compatible = "soc", },
48 { .type = "spider", },
49 { .type = "axon", },
50 { .type = "plb5", },
51 { .type = "plb4", },
52 { .type = "opb", },
53 {},
54};
55
56static atomic_t bus_no_reg_magic;
57
58/*
59 *
60 * OF platform device type definition & base infrastructure
61 *
62 */
63
64static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
65{
66 struct of_device * of_dev = to_of_device(dev);
67 struct of_platform_driver * of_drv = to_of_platform_driver(drv);
68 const struct of_device_id * matches = of_drv->match_table;
69
70 if (!matches)
71 return 0;
72
73 return of_match_device(matches, of_dev) != NULL;
74}
75
76static int of_platform_device_probe(struct device *dev)
77{
78 int error = -ENODEV;
79 struct of_platform_driver *drv;
80 struct of_device *of_dev;
81 const struct of_device_id *match;
82
83 drv = to_of_platform_driver(dev->driver);
84 of_dev = to_of_device(dev);
85
86 if (!drv->probe)
87 return error;
88
89 of_dev_get(of_dev);
90
91 match = of_match_device(drv->match_table, of_dev);
92 if (match)
93 error = drv->probe(of_dev, match);
94 if (error)
95 of_dev_put(of_dev);
96
97 return error;
98}
99
100static int of_platform_device_remove(struct device *dev)
101{
102 struct of_device * of_dev = to_of_device(dev);
103 struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
104
105 if (dev->driver && drv->remove)
106 drv->remove(of_dev);
107 return 0;
108}
109
110static int of_platform_device_suspend(struct device *dev, pm_message_t state)
111{
112 struct of_device * of_dev = to_of_device(dev);
113 struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
114 int error = 0;
115
116 if (dev->driver && drv->suspend)
117 error = drv->suspend(of_dev, state);
118 return error;
119}
120
121static int of_platform_device_resume(struct device * dev)
122{
123 struct of_device * of_dev = to_of_device(dev);
124 struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
125 int error = 0;
126
127 if (dev->driver && drv->resume)
128 error = drv->resume(of_dev);
129 return error;
130}
131
132struct bus_type of_platform_bus_type = {
133 .name = "of_platform",
134 .match = of_platform_bus_match,
135 .probe = of_platform_device_probe,
136 .remove = of_platform_device_remove,
137 .suspend = of_platform_device_suspend,
138 .resume = of_platform_device_resume,
139};
140EXPORT_SYMBOL(of_platform_bus_type);
141
142static int __init of_bus_driver_init(void)
143{
144 return bus_register(&of_platform_bus_type);
145}
146
147postcore_initcall(of_bus_driver_init);
148
149int of_register_platform_driver(struct of_platform_driver *drv)
150{
151 /* initialize common driver fields */
152 drv->driver.name = drv->name;
153 drv->driver.bus = &of_platform_bus_type;
154
155 /* register with core */
156 return driver_register(&drv->driver);
157}
158EXPORT_SYMBOL(of_register_platform_driver);
159
160void of_unregister_platform_driver(struct of_platform_driver *drv)
161{
162 driver_unregister(&drv->driver);
163}
164EXPORT_SYMBOL(of_unregister_platform_driver);
165
166static void of_platform_make_bus_id(struct of_device *dev)
167{
168 struct device_node *node = dev->node;
169 char *name = dev->dev.bus_id;
170 const u32 *reg;
171 u64 addr;
172 long magic;
173
174 /*
175 * If it's a DCR based device, use 'd' for native DCRs
176 * and 'D' for MMIO DCRs.
177 */
178#ifdef CONFIG_PPC_DCR
179 reg = get_property(node, "dcr-reg", NULL);
180 if (reg) {
181#ifdef CONFIG_PPC_DCR_NATIVE
182 snprintf(name, BUS_ID_SIZE, "d%x.%s",
183 *reg, node->name);
184#else /* CONFIG_PPC_DCR_NATIVE */
185 addr = of_translate_dcr_address(node, *reg, NULL);
186 if (addr != OF_BAD_ADDR) {
187 snprintf(name, BUS_ID_SIZE,
188 "D%llx.%s", (unsigned long long)addr,
189 node->name);
190 return;
191 }
192#endif /* !CONFIG_PPC_DCR_NATIVE */
193 }
194#endif /* CONFIG_PPC_DCR */
195
196 /*
197 * For MMIO, get the physical address
198 */
199 reg = get_property(node, "reg", NULL);
200 if (reg) {
201 addr = of_translate_address(node, reg);
202 if (addr != OF_BAD_ADDR) {
203 snprintf(name, BUS_ID_SIZE,
204 "%llx.%s", (unsigned long long)addr,
205 node->name);
206 return;
207 }
208 }
209
210 /*
211 * No BusID, use the node name and add a globally incremented
212 * counter (and pray...)
213 */
214 magic = atomic_add_return(1, &bus_no_reg_magic);
215 snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1);
216}
217
218struct of_device* of_platform_device_create(struct device_node *np,
219 const char *bus_id,
220 struct device *parent)
221{
222 struct of_device *dev;
223
224 dev = kmalloc(sizeof(*dev), GFP_KERNEL);
225 if (!dev)
226 return NULL;
227 memset(dev, 0, sizeof(*dev));
228
229 dev->node = of_node_get(np);
230 dev->dma_mask = 0xffffffffUL;
231 dev->dev.dma_mask = &dev->dma_mask;
232 dev->dev.parent = parent;
233 dev->dev.bus = &of_platform_bus_type;
234 dev->dev.release = of_release_dev;
235 dev->dev.archdata.of_node = np;
236 dev->dev.archdata.numa_node = of_node_to_nid(np);
237
238 /* We do not fill the DMA ops for platform devices by default.
239 * This is currently the responsibility of the platform code
240 * to do such, possibly using a device notifier
241 */
242
243 if (bus_id)
244 strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
245 else
246 of_platform_make_bus_id(dev);
247
248 if (of_device_register(dev) != 0) {
249 kfree(dev);
250 return NULL;
251 }
252
253 return dev;
254}
255EXPORT_SYMBOL(of_platform_device_create);
256
257
258
259/**
260 * of_platform_bus_create - Create an OF device for a bus node and all its
261 * children. Optionally recursively instanciate matching busses.
262 * @bus: device node of the bus to instanciate
263 * @matches: match table, NULL to use the default, OF_NO_DEEP_PROBE to
264 * disallow recursive creation of child busses
265 */
266static int of_platform_bus_create(struct device_node *bus,
267 struct of_device_id *matches,
268 struct device *parent)
269{
270 struct device_node *child;
271 struct of_device *dev;
272 int rc = 0;
273
274 for (child = NULL; (child = of_get_next_child(bus, child)); ) {
275 pr_debug(" create child: %s\n", child->full_name);
276 dev = of_platform_device_create(child, NULL, parent);
277 if (dev == NULL)
278 rc = -ENOMEM;
279 else if (!of_match_node(matches, child))
280 continue;
281 if (rc == 0) {
282 pr_debug(" and sub busses\n");
283 rc = of_platform_bus_create(child, matches, &dev->dev);
284 } if (rc) {
285 of_node_put(child);
286 break;
287 }
288 }
289 return rc;
290}
291
292/**
293 * of_platform_bus_probe - Probe the device-tree for platform busses
294 * @root: parent of the first level to probe or NULL for the root of the tree
295 * @matches: match table, NULL to use the default
296 * @parent: parent to hook devices from, NULL for toplevel
297 *
298 * Note that children of the provided root are not instanciated as devices
299 * unless the specified root itself matches the bus list and is not NULL.
300 */
301
302int of_platform_bus_probe(struct device_node *root,
303 struct of_device_id *matches,
304 struct device *parent)
305{
306 struct device_node *child;
307 struct of_device *dev;
308 int rc = 0;
309
310 if (matches == NULL)
311 matches = of_default_bus_ids;
312 if (matches == OF_NO_DEEP_PROBE)
313 return -EINVAL;
314 if (root == NULL)
315 root = of_find_node_by_path("/");
316 else
317 of_node_get(root);
318
319 pr_debug("of_platform_bus_probe()\n");
320 pr_debug(" starting at: %s\n", root->full_name);
321
322 /* Do a self check of bus type, if there's a match, create
323 * children
324 */
325 if (of_match_node(matches, root)) {
326 pr_debug(" root match, create all sub devices\n");
327 dev = of_platform_device_create(root, NULL, parent);
328 if (dev == NULL) {
329 rc = -ENOMEM;
330 goto bail;
331 }
332 pr_debug(" create all sub busses\n");
333 rc = of_platform_bus_create(root, matches, &dev->dev);
334 goto bail;
335 }
336 for (child = NULL; (child = of_get_next_child(root, child)); ) {
337 if (!of_match_node(matches, child))
338 continue;
339
340 pr_debug(" match: %s\n", child->full_name);
341 dev = of_platform_device_create(child, NULL, parent);
342 if (dev == NULL)
343 rc = -ENOMEM;
344 else
345 rc = of_platform_bus_create(child, matches, &dev->dev);
346 if (rc) {
347 of_node_put(child);
348 break;
349 }
350 }
351 bail:
352 of_node_put(root);
353 return rc;
354}
355EXPORT_SYMBOL(of_platform_bus_probe);
356
357static int of_dev_node_match(struct device *dev, void *data)
358{
359 return to_of_device(dev)->node == data;
360}
361
362struct of_device *of_find_device_by_node(struct device_node *np)
363{
364 struct device *dev;
365
366 dev = bus_find_device(&of_platform_bus_type,
367 NULL, np, of_dev_node_match);
368 if (dev)
369 return to_of_device(dev);
370 return NULL;
371}
372EXPORT_SYMBOL(of_find_device_by_node);
373
374static int of_dev_phandle_match(struct device *dev, void *data)
375{
376 phandle *ph = data;
377 return to_of_device(dev)->node->linux_phandle == *ph;
378}
379
380struct of_device *of_find_device_by_phandle(phandle ph)
381{
382 struct device *dev;
383
384 dev = bus_find_device(&of_platform_bus_type,
385 NULL, &ph, of_dev_phandle_match);
386 if (dev)
387 return to_of_device(dev);
388 return NULL;
389}
390EXPORT_SYMBOL(of_find_device_by_phandle);
391
392
393#ifdef CONFIG_PPC_OF_PLATFORM_PCI
394
395/* The probing of PCI controllers from of_platform is currently
396 * 64 bits only, mostly due to gratuitous differences between
397 * the 32 and 64 bits PCI code on PowerPC and the 32 bits one
398 * lacking some bits needed here.
399 */
400
401static int __devinit of_pci_phb_probe(struct of_device *dev,
402 const struct of_device_id *match)
403{
404 struct pci_controller *phb;
405
406 /* Check if we can do that ... */
407 if (ppc_md.pci_setup_phb == NULL)
408 return -ENODEV;
409
410 printk(KERN_INFO "Setting up PCI bus %s\n", dev->node->full_name);
411
412 /* Alloc and setup PHB data structure */
413 phb = pcibios_alloc_controller(dev->node);
414 if (!phb)
415 return -ENODEV;
416
417 /* Setup parent in sysfs */
418 phb->parent = &dev->dev;
419
420 /* Setup the PHB using arch provided callback */
421 if (ppc_md.pci_setup_phb(phb)) {
422 pcibios_free_controller(phb);
423 return -ENODEV;
424 }
425
426 /* Process "ranges" property */
427 pci_process_bridge_OF_ranges(phb, dev->node, 0);
428
429 /* Setup IO space.
430 * This will not work properly for ISA IOs, something needs to be done
431 * about it if we ever generalize that way of probing PCI brigdes
432 */
433 pci_setup_phb_io_dynamic(phb, 0);
434
435 /* Init pci_dn data structures */
436 pci_devs_phb_init_dynamic(phb);
437
438 /* Register devices with EEH */
439#ifdef CONFIG_EEH
440 if (dev->node->child)
441 eeh_add_device_tree_early(dev->node);
442#endif /* CONFIG_EEH */
443
444 /* Scan the bus */
445 scan_phb(phb);
446
447 /* Claim resources. This might need some rework as well depending
448 * wether we are doing probe-only or not, like assigning unassigned
449 * resources etc...
450 */
451 pcibios_claim_one_bus(phb->bus);
452
453 /* Finish EEH setup */
454#ifdef CONFIG_EEH
455 eeh_add_device_tree_late(phb->bus);
456#endif
457
458 /* Add probed PCI devices to the device model */
459 pci_bus_add_devices(phb->bus);
460
461 return 0;
462}
463
464static struct of_device_id of_pci_phb_ids[] = {
465 { .type = "pci", },
466 { .type = "pcix", },
467 { .type = "pcie", },
468 { .type = "pciex", },
469 { .type = "ht", },
470 {}
471};
472
473static struct of_platform_driver of_pci_phb_driver = {
474 .name = "of-pci",
475 .match_table = of_pci_phb_ids,
476 .probe = of_pci_phb_probe,
477 .driver = {
478 .multithread_probe = 1,
479 },
480};
481
482static __init int of_pci_phb_init(void)
483{
484 return of_register_platform_driver(&of_pci_phb_driver);
485}
486
487device_initcall(of_pci_phb_init);
488
489#endif /* CONFIG_PPC_OF_PLATFORM_PCI */
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index 0d9ff72e2852..2f54cd81dea5 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -12,6 +12,7 @@
12#include <linux/errno.h> 12#include <linux/errno.h>
13#include <linux/bootmem.h> 13#include <linux/bootmem.h>
14#include <linux/irq.h> 14#include <linux/irq.h>
15#include <linux/list.h>
15 16
16#include <asm/processor.h> 17#include <asm/processor.h>
17#include <asm/io.h> 18#include <asm/io.h>
@@ -99,7 +100,7 @@ pcibios_fixup_resources(struct pci_dev *dev)
99 continue; 100 continue;
100 if (res->end == 0xffffffff) { 101 if (res->end == 0xffffffff) {
101 DBG("PCI:%s Resource %d [%016llx-%016llx] is unassigned\n", 102 DBG("PCI:%s Resource %d [%016llx-%016llx] is unassigned\n",
102 pci_name(dev), i, res->start, res->end); 103 pci_name(dev), i, (u64)res->start, (u64)res->end);
103 res->end -= res->start; 104 res->end -= res->start;
104 res->start = 0; 105 res->start = 0;
105 res->flags |= IORESOURCE_UNSET; 106 res->flags |= IORESOURCE_UNSET;
@@ -115,11 +116,9 @@ pcibios_fixup_resources(struct pci_dev *dev)
115 if (offset != 0) { 116 if (offset != 0) {
116 res->start += offset; 117 res->start += offset;
117 res->end += offset; 118 res->end += offset;
118#ifdef DEBUG 119 DBG("Fixup res %d (%lx) of dev %s: %llx -> %llx\n",
119 printk("Fixup res %d (%lx) of dev %s: %llx -> %llx\n", 120 i, res->flags, pci_name(dev),
120 i, res->flags, pci_name(dev), 121 (u64)res->start - offset, (u64)res->start);
121 res->start - offset, res->start);
122#endif
123 } 122 }
124 } 123 }
125 124
@@ -255,7 +254,7 @@ pcibios_allocate_bus_resources(struct list_head *bus_list)
255 } 254 }
256 255
257 DBG("PCI: bridge rsrc %llx..%llx (%lx), parent %p\n", 256 DBG("PCI: bridge rsrc %llx..%llx (%lx), parent %p\n",
258 res->start, res->end, res->flags, pr); 257 (u64)res->start, (u64)res->end, res->flags, pr);
259 if (pr) { 258 if (pr) {
260 if (request_resource(pr, res) == 0) 259 if (request_resource(pr, res) == 0)
261 continue; 260 continue;
@@ -306,7 +305,7 @@ reparent_resources(struct resource *parent, struct resource *res)
306 for (p = res->child; p != NULL; p = p->sibling) { 305 for (p = res->child; p != NULL; p = p->sibling) {
307 p->parent = res; 306 p->parent = res;
308 DBG(KERN_INFO "PCI: reparented %s [%llx..%llx] under %s\n", 307 DBG(KERN_INFO "PCI: reparented %s [%llx..%llx] under %s\n",
309 p->name, p->start, p->end, res->name); 308 p->name, (u64)p->start, (u64)p->end, res->name);
310 } 309 }
311 return 0; 310 return 0;
312} 311}
@@ -362,7 +361,7 @@ pci_relocate_bridge_resource(struct pci_bus *bus, int i)
362 } 361 }
363 if (request_resource(pr, res)) { 362 if (request_resource(pr, res)) {
364 DBG(KERN_ERR "PCI: huh? couldn't move to %llx..%llx\n", 363 DBG(KERN_ERR "PCI: huh? couldn't move to %llx..%llx\n",
365 res->start, res->end); 364 (u64)res->start, (u64)res->end);
366 return -1; /* "can't happen" */ 365 return -1; /* "can't happen" */
367 } 366 }
368 update_bridge_base(bus, i); 367 update_bridge_base(bus, i);
@@ -480,14 +479,14 @@ static inline void alloc_resource(struct pci_dev *dev, int idx)
480 struct resource *pr, *r = &dev->resource[idx]; 479 struct resource *pr, *r = &dev->resource[idx];
481 480
482 DBG("PCI:%s: Resource %d: %016llx-%016llx (f=%lx)\n", 481 DBG("PCI:%s: Resource %d: %016llx-%016llx (f=%lx)\n",
483 pci_name(dev), idx, r->start, r->end, r->flags); 482 pci_name(dev), idx, (u64)r->start, (u64)r->end, r->flags);
484 pr = pci_find_parent_resource(dev, r); 483 pr = pci_find_parent_resource(dev, r);
485 if (!pr || request_resource(pr, r) < 0) { 484 if (!pr || request_resource(pr, r) < 0) {
486 printk(KERN_ERR "PCI: Cannot allocate resource region %d" 485 printk(KERN_ERR "PCI: Cannot allocate resource region %d"
487 " of device %s\n", idx, pci_name(dev)); 486 " of device %s\n", idx, pci_name(dev));
488 if (pr) 487 if (pr)
489 DBG("PCI: parent is %p: %016llx-%016llx (f=%lx)\n", 488 DBG("PCI: parent is %p: %016llx-%016llx (f=%lx)\n",
490 pr, pr->start, pr->end, pr->flags); 489 pr, (u64)pr->start, (u64)pr->end, pr->flags);
491 /* We'll assign a new address later */ 490 /* We'll assign a new address later */
492 r->flags |= IORESOURCE_UNSET; 491 r->flags |= IORESOURCE_UNSET;
493 r->end -= r->start; 492 r->end -= r->start;
@@ -960,7 +959,7 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose,
960 res->flags = IORESOURCE_IO; 959 res->flags = IORESOURCE_IO;
961 res->start = ranges[2]; 960 res->start = ranges[2];
962 DBG("PCI: IO 0x%llx -> 0x%llx\n", 961 DBG("PCI: IO 0x%llx -> 0x%llx\n",
963 res->start, res->start + size - 1); 962 (u64)res->start, (u64)res->start + size - 1);
964 break; 963 break;
965 case 2: /* memory space */ 964 case 2: /* memory space */
966 memno = 0; 965 memno = 0;
@@ -982,7 +981,7 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose,
982 res->flags |= IORESOURCE_PREFETCH; 981 res->flags |= IORESOURCE_PREFETCH;
983 res->start = ranges[na+2]; 982 res->start = ranges[na+2];
984 DBG("PCI: MEM[%d] 0x%llx -> 0x%llx\n", memno, 983 DBG("PCI: MEM[%d] 0x%llx -> 0x%llx\n", memno,
985 res->start, res->start + size - 1); 984 (u64)res->start, (u64)res->start + size - 1);
986 } 985 }
987 break; 986 break;
988 } 987 }
@@ -1268,7 +1267,10 @@ pcibios_init(void)
1268 if (pci_assign_all_buses) 1267 if (pci_assign_all_buses)
1269 hose->first_busno = next_busno; 1268 hose->first_busno = next_busno;
1270 hose->last_busno = 0xff; 1269 hose->last_busno = 0xff;
1271 bus = pci_scan_bus(hose->first_busno, hose->ops, hose); 1270 bus = pci_scan_bus_parented(hose->parent, hose->first_busno,
1271 hose->ops, hose);
1272 if (bus)
1273 pci_bus_add_devices(bus);
1272 hose->last_busno = bus->subordinate; 1274 hose->last_busno = bus->subordinate;
1273 if (pci_assign_all_buses || next_busno <= hose->last_busno) 1275 if (pci_assign_all_buses || next_busno <= hose->last_busno)
1274 next_busno = hose->last_busno + pcibios_assign_bus_offset; 1276 next_busno = hose->last_busno + pcibios_assign_bus_offset;
@@ -1282,10 +1284,6 @@ pcibios_init(void)
1282 if (pci_assign_all_buses && have_of) 1284 if (pci_assign_all_buses && have_of)
1283 pcibios_make_OF_bus_map(); 1285 pcibios_make_OF_bus_map();
1284 1286
1285 /* Do machine dependent PCI interrupt routing */
1286 if (ppc_md.pci_swizzle && ppc_md.pci_map_irq)
1287 pci_fixup_irqs(ppc_md.pci_swizzle, ppc_md.pci_map_irq);
1288
1289 /* Call machine dependent fixup */ 1287 /* Call machine dependent fixup */
1290 if (ppc_md.pcibios_fixup) 1288 if (ppc_md.pcibios_fixup)
1291 ppc_md.pcibios_fixup(); 1289 ppc_md.pcibios_fixup();
@@ -1308,25 +1306,6 @@ pcibios_init(void)
1308 1306
1309subsys_initcall(pcibios_init); 1307subsys_initcall(pcibios_init);
1310 1308
1311unsigned char __init
1312common_swizzle(struct pci_dev *dev, unsigned char *pinp)
1313{
1314 struct pci_controller *hose = dev->sysdata;
1315
1316 if (dev->bus->number != hose->first_busno) {
1317 u8 pin = *pinp;
1318 do {
1319 pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
1320 /* Move up the chain of bridges. */
1321 dev = dev->bus->self;
1322 } while (dev->bus->self);
1323 *pinp = pin;
1324
1325 /* The slot is the idsel of the last bridge. */
1326 }
1327 return PCI_SLOT(dev->devfn);
1328}
1329
1330unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, 1309unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
1331 unsigned long start, unsigned long size) 1310 unsigned long start, unsigned long size)
1332{ 1311{
@@ -1338,6 +1317,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
1338 struct pci_controller *hose = (struct pci_controller *) bus->sysdata; 1317 struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
1339 unsigned long io_offset; 1318 unsigned long io_offset;
1340 struct resource *res; 1319 struct resource *res;
1320 struct pci_dev *dev;
1341 int i; 1321 int i;
1342 1322
1343 io_offset = (unsigned long)hose->io_base_virt - isa_io_base; 1323 io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
@@ -1390,8 +1370,16 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
1390 } 1370 }
1391 } 1371 }
1392 1372
1373 /* Platform specific bus fixups */
1393 if (ppc_md.pcibios_fixup_bus) 1374 if (ppc_md.pcibios_fixup_bus)
1394 ppc_md.pcibios_fixup_bus(bus); 1375 ppc_md.pcibios_fixup_bus(bus);
1376
1377 /* Read default IRQs and fixup if necessary */
1378 list_for_each_entry(dev, &bus->devices, bus_list) {
1379 pci_read_irq_line(dev);
1380 if (ppc_md.pci_irq_fixup)
1381 ppc_md.pci_irq_fixup(dev);
1382 }
1395} 1383}
1396 1384
1397char __init *pcibios_setup(char *str) 1385char __init *pcibios_setup(char *str)
@@ -1571,7 +1559,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
1571 *offset += hose->pci_mem_offset; 1559 *offset += hose->pci_mem_offset;
1572 res_bit = IORESOURCE_MEM; 1560 res_bit = IORESOURCE_MEM;
1573 } else { 1561 } else {
1574 io_offset = hose->io_base_virt - ___IO_BASE; 1562 io_offset = hose->io_base_virt - (void __iomem *)_IO_BASE;
1575 *offset += io_offset; 1563 *offset += io_offset;
1576 res_bit = IORESOURCE_IO; 1564 res_bit = IORESOURCE_IO;
1577 } 1565 }
@@ -1826,7 +1814,8 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
1826 return; 1814 return;
1827 1815
1828 if (rsrc->flags & IORESOURCE_IO) 1816 if (rsrc->flags & IORESOURCE_IO)
1829 offset = ___IO_BASE - hose->io_base_virt + hose->io_base_phys; 1817 offset = (void __iomem *)_IO_BASE - hose->io_base_virt
1818 + hose->io_base_phys;
1830 1819
1831 *start = rsrc->start + offset; 1820 *start = rsrc->start + offset;
1832 *end = rsrc->end + offset; 1821 *end = rsrc->end + offset;
@@ -1845,35 +1834,6 @@ pci_init_resource(struct resource *res, unsigned long start, unsigned long end,
1845 res->child = NULL; 1834 res->child = NULL;
1846} 1835}
1847 1836
1848void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
1849{
1850 unsigned long start = pci_resource_start(dev, bar);
1851 unsigned long len = pci_resource_len(dev, bar);
1852 unsigned long flags = pci_resource_flags(dev, bar);
1853
1854 if (!len)
1855 return NULL;
1856 if (max && len > max)
1857 len = max;
1858 if (flags & IORESOURCE_IO)
1859 return ioport_map(start, len);
1860 if (flags & IORESOURCE_MEM)
1861 /* Not checking IORESOURCE_CACHEABLE because PPC does
1862 * not currently distinguish between ioremap and
1863 * ioremap_nocache.
1864 */
1865 return ioremap(start, len);
1866 /* What? */
1867 return NULL;
1868}
1869
1870void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
1871{
1872 /* Nothing to do */
1873}
1874EXPORT_SYMBOL(pci_iomap);
1875EXPORT_SYMBOL(pci_iounmap);
1876
1877unsigned long pci_address_to_pio(phys_addr_t address) 1837unsigned long pci_address_to_pio(phys_addr_t address)
1878{ 1838{
1879 struct pci_controller* hose = hose_head; 1839 struct pci_controller* hose = hose_head;
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 9bae8a5bf671..6fa9a0a5c8db 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -42,11 +42,9 @@
42unsigned long pci_probe_only = 1; 42unsigned long pci_probe_only = 1;
43int pci_assign_all_buses = 0; 43int pci_assign_all_buses = 0;
44 44
45#ifdef CONFIG_PPC_MULTIPLATFORM
46static void fixup_resource(struct resource *res, struct pci_dev *dev); 45static void fixup_resource(struct resource *res, struct pci_dev *dev);
47static void do_bus_setup(struct pci_bus *bus); 46static void do_bus_setup(struct pci_bus *bus);
48static void phbs_remap_io(void); 47static void phbs_remap_io(void);
49#endif
50 48
51/* pci_io_base -- the base address from which io bars are offsets. 49/* pci_io_base -- the base address from which io bars are offsets.
52 * This is the lowest I/O base address (so bar values are always positive), 50 * This is the lowest I/O base address (so bar values are always positive),
@@ -63,7 +61,7 @@ void iSeries_pcibios_init(void);
63 61
64LIST_HEAD(hose_list); 62LIST_HEAD(hose_list);
65 63
66struct dma_mapping_ops pci_dma_ops; 64struct dma_mapping_ops *pci_dma_ops;
67EXPORT_SYMBOL(pci_dma_ops); 65EXPORT_SYMBOL(pci_dma_ops);
68 66
69int global_phb_number; /* Global phb counter */ 67int global_phb_number; /* Global phb counter */
@@ -212,6 +210,10 @@ struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
212 210
213void pcibios_free_controller(struct pci_controller *phb) 211void pcibios_free_controller(struct pci_controller *phb)
214{ 212{
213 spin_lock(&hose_spinlock);
214 list_del(&phb->list_node);
215 spin_unlock(&hose_spinlock);
216
215 if (phb->is_dynamic) 217 if (phb->is_dynamic)
216 kfree(phb); 218 kfree(phb);
217} 219}
@@ -251,7 +253,6 @@ static void __init pcibios_claim_of_setup(void)
251 pcibios_claim_one_bus(b); 253 pcibios_claim_one_bus(b);
252} 254}
253 255
254#ifdef CONFIG_PPC_MULTIPLATFORM
255static u32 get_int_prop(struct device_node *np, const char *name, u32 def) 256static u32 get_int_prop(struct device_node *np, const char *name, u32 def)
256{ 257{
257 const u32 *prop; 258 const u32 *prop;
@@ -329,7 +330,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
329 struct pci_dev *dev; 330 struct pci_dev *dev;
330 const char *type; 331 const char *type;
331 332
332 dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); 333 dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
333 if (!dev) 334 if (!dev)
334 return NULL; 335 return NULL;
335 type = get_property(node, "device_type", NULL); 336 type = get_property(node, "device_type", NULL);
@@ -338,7 +339,6 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
338 339
339 DBG(" create device, devfn: %x, type: %s\n", devfn, type); 340 DBG(" create device, devfn: %x, type: %s\n", devfn, type);
340 341
341 memset(dev, 0, sizeof(struct pci_dev));
342 dev->bus = bus; 342 dev->bus = bus;
343 dev->sysdata = node; 343 dev->sysdata = node;
344 dev->dev.parent = bus->bridge; 344 dev->dev.parent = bus->bridge;
@@ -506,7 +506,6 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
506 pci_scan_child_bus(bus); 506 pci_scan_child_bus(bus);
507} 507}
508EXPORT_SYMBOL(of_scan_pci_bridge); 508EXPORT_SYMBOL(of_scan_pci_bridge);
509#endif /* CONFIG_PPC_MULTIPLATFORM */
510 509
511void __devinit scan_phb(struct pci_controller *hose) 510void __devinit scan_phb(struct pci_controller *hose)
512{ 511{
@@ -517,7 +516,7 @@ void __devinit scan_phb(struct pci_controller *hose)
517 516
518 DBG("Scanning PHB %s\n", node ? node->full_name : "<NO NAME>"); 517 DBG("Scanning PHB %s\n", node ? node->full_name : "<NO NAME>");
519 518
520 bus = pci_create_bus(NULL, hose->first_busno, hose->ops, node); 519 bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, node);
521 if (bus == NULL) { 520 if (bus == NULL) {
522 printk(KERN_ERR "Failed to create bus for PCI domain %04x\n", 521 printk(KERN_ERR "Failed to create bus for PCI domain %04x\n",
523 hose->global_number); 522 hose->global_number);
@@ -540,7 +539,7 @@ void __devinit scan_phb(struct pci_controller *hose)
540 } 539 }
541 540
542 mode = PCI_PROBE_NORMAL; 541 mode = PCI_PROBE_NORMAL;
543#ifdef CONFIG_PPC_MULTIPLATFORM 542
544 if (node && ppc_md.pci_probe_mode) 543 if (node && ppc_md.pci_probe_mode)
545 mode = ppc_md.pci_probe_mode(bus); 544 mode = ppc_md.pci_probe_mode(bus);
546 DBG(" probe mode: %d\n", mode); 545 DBG(" probe mode: %d\n", mode);
@@ -548,7 +547,7 @@ void __devinit scan_phb(struct pci_controller *hose)
548 bus->subordinate = hose->last_busno; 547 bus->subordinate = hose->last_busno;
549 of_scan_bus(node, bus); 548 of_scan_bus(node, bus);
550 } 549 }
551#endif /* CONFIG_PPC_MULTIPLATFORM */ 550
552 if (mode == PCI_PROBE_NORMAL) 551 if (mode == PCI_PROBE_NORMAL)
553 hose->last_busno = bus->subordinate = pci_scan_child_bus(bus); 552 hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
554} 553}
@@ -592,11 +591,9 @@ static int __init pcibios_init(void)
592 if (ppc64_isabridge_dev != NULL) 591 if (ppc64_isabridge_dev != NULL)
593 printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); 592 printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
594 593
595#ifdef CONFIG_PPC_MULTIPLATFORM
596 if (!firmware_has_feature(FW_FEATURE_ISERIES)) 594 if (!firmware_has_feature(FW_FEATURE_ISERIES))
597 /* map in PCI I/O space */ 595 /* map in PCI I/O space */
598 phbs_remap_io(); 596 phbs_remap_io();
599#endif
600 597
601 printk(KERN_DEBUG "PCI: Probing PCI hardware done\n"); 598 printk(KERN_DEBUG "PCI: Probing PCI hardware done\n");
602 599
@@ -873,8 +870,6 @@ void pcibios_add_platform_entries(struct pci_dev *pdev)
873 device_create_file(&pdev->dev, &dev_attr_devspec); 870 device_create_file(&pdev->dev, &dev_attr_devspec);
874} 871}
875 872
876#ifdef CONFIG_PPC_MULTIPLATFORM
877
878#define ISA_SPACE_MASK 0x1 873#define ISA_SPACE_MASK 0x1
879#define ISA_SPACE_IO 0x1 874#define ISA_SPACE_IO 0x1
880 875
@@ -975,11 +970,7 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
975 res = NULL; 970 res = NULL;
976 pci_space = ranges[0]; 971 pci_space = ranges[0];
977 pci_addr = ((unsigned long)ranges[1] << 32) | ranges[2]; 972 pci_addr = ((unsigned long)ranges[1] << 32) | ranges[2];
978 973 cpu_phys_addr = of_translate_address(dev, &ranges[3]);
979 cpu_phys_addr = ranges[3];
980 if (na >= 2)
981 cpu_phys_addr = (cpu_phys_addr << 32) | ranges[4];
982
983 size = ((unsigned long)ranges[na+3] << 32) | ranges[na+4]; 974 size = ((unsigned long)ranges[na+3] << 32) | ranges[na+4];
984 ranges += np; 975 ranges += np;
985 if (size == 0) 976 if (size == 0)
@@ -1145,7 +1136,7 @@ int unmap_bus_range(struct pci_bus *bus)
1145 1136
1146 if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) 1137 if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
1147 return 1; 1138 return 1;
1148 if (iounmap_explicit((void __iomem *) start_virt, size)) 1139 if (__iounmap_explicit((void __iomem *) start_virt, size))
1149 return 1; 1140 return 1;
1150 1141
1151 return 0; 1142 return 0;
@@ -1213,23 +1204,52 @@ void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
1213} 1204}
1214EXPORT_SYMBOL(pcibios_fixup_device_resources); 1205EXPORT_SYMBOL(pcibios_fixup_device_resources);
1215 1206
1207void __devinit pcibios_setup_new_device(struct pci_dev *dev)
1208{
1209 struct dev_archdata *sd = &dev->dev.archdata;
1210
1211 sd->of_node = pci_device_to_OF_node(dev);
1212
1213 DBG("PCI device %s OF node: %s\n", pci_name(dev),
1214 sd->of_node ? sd->of_node->full_name : "<none>");
1215
1216 sd->dma_ops = pci_dma_ops;
1217#ifdef CONFIG_NUMA
1218 sd->numa_node = pcibus_to_node(dev->bus);
1219#else
1220 sd->numa_node = -1;
1221#endif
1222 if (ppc_md.pci_dma_dev_setup)
1223 ppc_md.pci_dma_dev_setup(dev);
1224}
1225EXPORT_SYMBOL(pcibios_setup_new_device);
1216 1226
1217static void __devinit do_bus_setup(struct pci_bus *bus) 1227static void __devinit do_bus_setup(struct pci_bus *bus)
1218{ 1228{
1219 struct pci_dev *dev; 1229 struct pci_dev *dev;
1220 1230
1221 ppc_md.iommu_bus_setup(bus); 1231 if (ppc_md.pci_dma_bus_setup)
1232 ppc_md.pci_dma_bus_setup(bus);
1222 1233
1223 list_for_each_entry(dev, &bus->devices, bus_list) 1234 list_for_each_entry(dev, &bus->devices, bus_list)
1224 ppc_md.iommu_dev_setup(dev); 1235 pcibios_setup_new_device(dev);
1225 1236
1226 if (ppc_md.irq_bus_setup) 1237 /* Read default IRQs and fixup if necessary */
1227 ppc_md.irq_bus_setup(bus); 1238 list_for_each_entry(dev, &bus->devices, bus_list) {
1239 pci_read_irq_line(dev);
1240 if (ppc_md.pci_irq_fixup)
1241 ppc_md.pci_irq_fixup(dev);
1242 }
1228} 1243}
1229 1244
1230void __devinit pcibios_fixup_bus(struct pci_bus *bus) 1245void __devinit pcibios_fixup_bus(struct pci_bus *bus)
1231{ 1246{
1232 struct pci_dev *dev = bus->self; 1247 struct pci_dev *dev = bus->self;
1248 struct device_node *np;
1249
1250 np = pci_bus_to_OF_node(bus);
1251
1252 DBG("pcibios_fixup_bus(%s)\n", np ? np->full_name : "<???>");
1233 1253
1234 if (dev && pci_probe_only && 1254 if (dev && pci_probe_only &&
1235 (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { 1255 (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
@@ -1343,8 +1363,6 @@ struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
1343 return NULL; 1363 return NULL;
1344} 1364}
1345 1365
1346#endif /* CONFIG_PPC_MULTIPLATFORM */
1347
1348unsigned long pci_address_to_pio(phys_addr_t address) 1366unsigned long pci_address_to_pio(phys_addr_t address)
1349{ 1367{
1350 struct pci_controller *hose, *tmp; 1368 struct pci_controller *hose, *tmp;
diff --git a/arch/powerpc/kernel/pci_direct_iommu.c b/arch/powerpc/kernel/pci_direct_iommu.c
deleted file mode 100644
index 72ce082ce738..000000000000
--- a/arch/powerpc/kernel/pci_direct_iommu.c
+++ /dev/null
@@ -1,98 +0,0 @@
1/*
2 * Support for DMA from PCI devices to main memory on
3 * machines without an iommu or with directly addressable
4 * RAM (typically a pmac with 2Gb of RAM or less)
5 *
6 * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13
14#include <linux/kernel.h>
15#include <linux/pci.h>
16#include <linux/delay.h>
17#include <linux/string.h>
18#include <linux/init.h>
19#include <linux/bootmem.h>
20#include <linux/mm.h>
21#include <linux/dma-mapping.h>
22
23#include <asm/sections.h>
24#include <asm/io.h>
25#include <asm/prom.h>
26#include <asm/pci-bridge.h>
27#include <asm/machdep.h>
28#include <asm/pmac_feature.h>
29#include <asm/abs_addr.h>
30#include <asm/ppc-pci.h>
31
32static void *pci_direct_alloc_coherent(struct device *hwdev, size_t size,
33 dma_addr_t *dma_handle, gfp_t flag)
34{
35 void *ret;
36
37 ret = (void *)__get_free_pages(flag, get_order(size));
38 if (ret != NULL) {
39 memset(ret, 0, size);
40 *dma_handle = virt_to_abs(ret);
41 }
42 return ret;
43}
44
45static void pci_direct_free_coherent(struct device *hwdev, size_t size,
46 void *vaddr, dma_addr_t dma_handle)
47{
48 free_pages((unsigned long)vaddr, get_order(size));
49}
50
51static dma_addr_t pci_direct_map_single(struct device *hwdev, void *ptr,
52 size_t size, enum dma_data_direction direction)
53{
54 return virt_to_abs(ptr);
55}
56
57static void pci_direct_unmap_single(struct device *hwdev, dma_addr_t dma_addr,
58 size_t size, enum dma_data_direction direction)
59{
60}
61
62static int pci_direct_map_sg(struct device *hwdev, struct scatterlist *sg,
63 int nents, enum dma_data_direction direction)
64{
65 int i;
66
67 for (i = 0; i < nents; i++, sg++) {
68 sg->dma_address = page_to_phys(sg->page) + sg->offset;
69 sg->dma_length = sg->length;
70 }
71
72 return nents;
73}
74
75static void pci_direct_unmap_sg(struct device *hwdev, struct scatterlist *sg,
76 int nents, enum dma_data_direction direction)
77{
78}
79
80static int pci_direct_dma_supported(struct device *dev, u64 mask)
81{
82 return mask < 0x100000000ull;
83}
84
85static struct dma_mapping_ops pci_direct_ops = {
86 .alloc_coherent = pci_direct_alloc_coherent,
87 .free_coherent = pci_direct_free_coherent,
88 .map_single = pci_direct_map_single,
89 .unmap_single = pci_direct_unmap_single,
90 .map_sg = pci_direct_map_sg,
91 .unmap_sg = pci_direct_unmap_sg,
92 .dma_supported = pci_direct_dma_supported,
93};
94
95void __init pci_direct_iommu_init(void)
96{
97 pci_dma_ops = pci_direct_ops;
98}
diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c
deleted file mode 100644
index 0688b2534acb..000000000000
--- a/arch/powerpc/kernel/pci_iommu.c
+++ /dev/null
@@ -1,164 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
3 *
4 * Rewrite, cleanup, new allocation schemes:
5 * Copyright (C) 2004 Olof Johansson, IBM Corporation
6 *
7 * Dynamic DMA mapping support, platform-independent parts.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24
25#include <linux/init.h>
26#include <linux/types.h>
27#include <linux/slab.h>
28#include <linux/mm.h>
29#include <linux/spinlock.h>
30#include <linux/string.h>
31#include <linux/pci.h>
32#include <linux/dma-mapping.h>
33#include <asm/io.h>
34#include <asm/prom.h>
35#include <asm/iommu.h>
36#include <asm/pci-bridge.h>
37#include <asm/machdep.h>
38#include <asm/ppc-pci.h>
39
40/*
41 * We can use ->sysdata directly and avoid the extra work in
42 * pci_device_to_OF_node since ->sysdata will have been initialised
43 * in the iommu init code for all devices.
44 */
45#define PCI_GET_DN(dev) ((struct device_node *)((dev)->sysdata))
46
47static inline struct iommu_table *device_to_table(struct device *hwdev)
48{
49 struct pci_dev *pdev;
50
51 if (!hwdev) {
52 pdev = ppc64_isabridge_dev;
53 if (!pdev)
54 return NULL;
55 } else
56 pdev = to_pci_dev(hwdev);
57
58 return PCI_DN(PCI_GET_DN(pdev))->iommu_table;
59}
60
61
62static inline unsigned long device_to_mask(struct device *hwdev)
63{
64 struct pci_dev *pdev;
65
66 if (!hwdev) {
67 pdev = ppc64_isabridge_dev;
68 if (!pdev) /* This is the best guess we can do */
69 return 0xfffffffful;
70 } else
71 pdev = to_pci_dev(hwdev);
72
73 if (pdev->dma_mask)
74 return pdev->dma_mask;
75
76 /* Assume devices without mask can take 32 bit addresses */
77 return 0xfffffffful;
78}
79
80
81/* Allocates a contiguous real buffer and creates mappings over it.
82 * Returns the virtual address of the buffer and sets dma_handle
83 * to the dma address (mapping) of the first page.
84 */
85static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size,
86 dma_addr_t *dma_handle, gfp_t flag)
87{
88 return iommu_alloc_coherent(device_to_table(hwdev), size, dma_handle,
89 device_to_mask(hwdev), flag,
90 pcibus_to_node(to_pci_dev(hwdev)->bus));
91}
92
93static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
94 void *vaddr, dma_addr_t dma_handle)
95{
96 iommu_free_coherent(device_to_table(hwdev), size, vaddr, dma_handle);
97}
98
99/* Creates TCEs for a user provided buffer. The user buffer must be
100 * contiguous real kernel storage (not vmalloc). The address of the buffer
101 * passed here is the kernel (virtual) address of the buffer. The buffer
102 * need not be page aligned, the dma_addr_t returned will point to the same
103 * byte within the page as vaddr.
104 */
105static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr,
106 size_t size, enum dma_data_direction direction)
107{
108 return iommu_map_single(device_to_table(hwdev), vaddr, size,
109 device_to_mask(hwdev), direction);
110}
111
112
113static void pci_iommu_unmap_single(struct device *hwdev, dma_addr_t dma_handle,
114 size_t size, enum dma_data_direction direction)
115{
116 iommu_unmap_single(device_to_table(hwdev), dma_handle, size, direction);
117}
118
119
120static int pci_iommu_map_sg(struct device *pdev, struct scatterlist *sglist,
121 int nelems, enum dma_data_direction direction)
122{
123 return iommu_map_sg(pdev, device_to_table(pdev), sglist,
124 nelems, device_to_mask(pdev), direction);
125}
126
127static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist,
128 int nelems, enum dma_data_direction direction)
129{
130 iommu_unmap_sg(device_to_table(pdev), sglist, nelems, direction);
131}
132
133/* We support DMA to/from any memory page via the iommu */
134static int pci_iommu_dma_supported(struct device *dev, u64 mask)
135{
136 struct iommu_table *tbl = device_to_table(dev);
137
138 if (!tbl || tbl->it_offset > mask) {
139 printk(KERN_INFO "Warning: IOMMU table offset too big for device mask\n");
140 if (tbl)
141 printk(KERN_INFO "mask: 0x%08lx, table offset: 0x%08lx\n",
142 mask, tbl->it_offset);
143 else
144 printk(KERN_INFO "mask: 0x%08lx, table unavailable\n",
145 mask);
146 return 0;
147 } else
148 return 1;
149}
150
151struct dma_mapping_ops pci_iommu_ops = {
152 .alloc_coherent = pci_iommu_alloc_coherent,
153 .free_coherent = pci_iommu_free_coherent,
154 .map_single = pci_iommu_map_single,
155 .unmap_single = pci_iommu_unmap_single,
156 .map_sg = pci_iommu_map_sg,
157 .unmap_sg = pci_iommu_unmap_sg,
158 .dma_supported = pci_iommu_dma_supported,
159};
160
161void pci_iommu_init(void)
162{
163 pci_dma_ops = pci_iommu_ops;
164}
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 807193a3c784..9179f0739ea2 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -49,6 +49,10 @@
49#include <asm/commproc.h> 49#include <asm/commproc.h>
50#endif 50#endif
51 51
52#ifdef CONFIG_PPC64
53EXPORT_SYMBOL(local_irq_restore);
54#endif
55
52#ifdef CONFIG_PPC32 56#ifdef CONFIG_PPC32
53extern void transfer_to_handler(void); 57extern void transfer_to_handler(void);
54extern void do_IRQ(struct pt_regs *regs); 58extern void do_IRQ(struct pt_regs *regs);
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index bdb412d4b748..c18dbe77fdc2 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -538,35 +538,31 @@ static struct ibm_pa_feature {
538 {CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0}, 538 {CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0},
539}; 539};
540 540
541static void __init check_cpu_pa_features(unsigned long node) 541static void __init scan_features(unsigned long node, unsigned char *ftrs,
542 unsigned long tablelen,
543 struct ibm_pa_feature *fp,
544 unsigned long ft_size)
542{ 545{
543 unsigned char *pa_ftrs; 546 unsigned long i, len, bit;
544 unsigned long len, tablelen, i, bit;
545
546 pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen);
547 if (pa_ftrs == NULL)
548 return;
549 547
550 /* find descriptor with type == 0 */ 548 /* find descriptor with type == 0 */
551 for (;;) { 549 for (;;) {
552 if (tablelen < 3) 550 if (tablelen < 3)
553 return; 551 return;
554 len = 2 + pa_ftrs[0]; 552 len = 2 + ftrs[0];
555 if (tablelen < len) 553 if (tablelen < len)
556 return; /* descriptor 0 not found */ 554 return; /* descriptor 0 not found */
557 if (pa_ftrs[1] == 0) 555 if (ftrs[1] == 0)
558 break; 556 break;
559 tablelen -= len; 557 tablelen -= len;
560 pa_ftrs += len; 558 ftrs += len;
561 } 559 }
562 560
563 /* loop over bits we know about */ 561 /* loop over bits we know about */
564 for (i = 0; i < ARRAY_SIZE(ibm_pa_features); ++i) { 562 for (i = 0; i < ft_size; ++i, ++fp) {
565 struct ibm_pa_feature *fp = &ibm_pa_features[i]; 563 if (fp->pabyte >= ftrs[0])
566
567 if (fp->pabyte >= pa_ftrs[0])
568 continue; 564 continue;
569 bit = (pa_ftrs[2 + fp->pabyte] >> (7 - fp->pabit)) & 1; 565 bit = (ftrs[2 + fp->pabyte] >> (7 - fp->pabit)) & 1;
570 if (bit ^ fp->invert) { 566 if (bit ^ fp->invert) {
571 cur_cpu_spec->cpu_features |= fp->cpu_features; 567 cur_cpu_spec->cpu_features |= fp->cpu_features;
572 cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftrs; 568 cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftrs;
@@ -577,16 +573,59 @@ static void __init check_cpu_pa_features(unsigned long node)
577 } 573 }
578} 574}
579 575
576static void __init check_cpu_pa_features(unsigned long node)
577{
578 unsigned char *pa_ftrs;
579 unsigned long tablelen;
580
581 pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen);
582 if (pa_ftrs == NULL)
583 return;
584
585 scan_features(node, pa_ftrs, tablelen,
586 ibm_pa_features, ARRAY_SIZE(ibm_pa_features));
587}
588
589static struct feature_property {
590 const char *name;
591 u32 min_value;
592 unsigned long cpu_feature;
593 unsigned long cpu_user_ftr;
594} feature_properties[] __initdata = {
595#ifdef CONFIG_ALTIVEC
596 {"altivec", 0, CPU_FTR_ALTIVEC, PPC_FEATURE_HAS_ALTIVEC},
597 {"ibm,vmx", 1, CPU_FTR_ALTIVEC, PPC_FEATURE_HAS_ALTIVEC},
598#endif /* CONFIG_ALTIVEC */
599#ifdef CONFIG_PPC64
600 {"ibm,dfp", 1, 0, PPC_FEATURE_HAS_DFP},
601 {"ibm,purr", 1, CPU_FTR_PURR, 0},
602 {"ibm,spurr", 1, CPU_FTR_SPURR, 0},
603#endif /* CONFIG_PPC64 */
604};
605
606static void __init check_cpu_feature_properties(unsigned long node)
607{
608 unsigned long i;
609 struct feature_property *fp = feature_properties;
610 const u32 *prop;
611
612 for (i = 0; i < ARRAY_SIZE(feature_properties); ++i, ++fp) {
613 prop = of_get_flat_dt_prop(node, fp->name, NULL);
614 if (prop && *prop >= fp->min_value) {
615 cur_cpu_spec->cpu_features |= fp->cpu_feature;
616 cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftr;
617 }
618 }
619}
620
580static int __init early_init_dt_scan_cpus(unsigned long node, 621static int __init early_init_dt_scan_cpus(unsigned long node,
581 const char *uname, int depth, 622 const char *uname, int depth,
582 void *data) 623 void *data)
583{ 624{
584 static int logical_cpuid = 0; 625 static int logical_cpuid = 0;
585 char *type = of_get_flat_dt_prop(node, "device_type", NULL); 626 char *type = of_get_flat_dt_prop(node, "device_type", NULL);
586#ifdef CONFIG_ALTIVEC 627 const u32 *prop;
587 u32 *prop; 628 const u32 *intserv;
588#endif
589 u32 *intserv;
590 int i, nthreads; 629 int i, nthreads;
591 unsigned long len; 630 unsigned long len;
592 int found = 0; 631 int found = 0;
@@ -643,24 +682,27 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
643 intserv[i]); 682 intserv[i]);
644 boot_cpuid = logical_cpuid; 683 boot_cpuid = logical_cpuid;
645 set_hard_smp_processor_id(boot_cpuid, intserv[i]); 684 set_hard_smp_processor_id(boot_cpuid, intserv[i]);
646 }
647 685
648#ifdef CONFIG_ALTIVEC 686 /*
649 /* Check if we have a VMX and eventually update CPU features */ 687 * PAPR defines "logical" PVR values for cpus that
650 prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", NULL); 688 * meet various levels of the architecture:
651 if (prop && (*prop) > 0) { 689 * 0x0f000001 Architecture version 2.04
652 cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; 690 * 0x0f000002 Architecture version 2.05
653 cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; 691 * If the cpu-version property in the cpu node contains
654 } 692 * such a value, we call identify_cpu again with the
655 693 * logical PVR value in order to use the cpu feature
656 /* Same goes for Apple's "altivec" property */ 694 * bits appropriate for the architecture level.
657 prop = (u32 *)of_get_flat_dt_prop(node, "altivec", NULL); 695 *
658 if (prop) { 696 * A POWER6 partition in "POWER6 architected" mode
659 cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; 697 * uses the 0x0f000002 PVR value; in POWER5+ mode
660 cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; 698 * it uses 0x0f000001.
699 */
700 prop = of_get_flat_dt_prop(node, "cpu-version", NULL);
701 if (prop && (*prop & 0xff000000) == 0x0f000000)
702 identify_cpu(0, *prop);
661 } 703 }
662#endif /* CONFIG_ALTIVEC */
663 704
705 check_cpu_feature_properties(node);
664 check_cpu_pa_features(node); 706 check_cpu_pa_features(node);
665 707
666#ifdef CONFIG_PPC_PSERIES 708#ifdef CONFIG_PPC_PSERIES
@@ -1674,6 +1716,7 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
1674 } 1716 }
1675 return NULL; 1717 return NULL;
1676} 1718}
1719EXPORT_SYMBOL(of_get_cpu_node);
1677 1720
1678#ifdef DEBUG 1721#ifdef DEBUG
1679static struct debugfs_blob_wrapper flat_dt_blob; 1722static struct debugfs_blob_wrapper flat_dt_blob;
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index b91761639d96..46cf32670ddb 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -173,8 +173,8 @@ static unsigned long __initdata dt_string_start, dt_string_end;
173static unsigned long __initdata prom_initrd_start, prom_initrd_end; 173static unsigned long __initdata prom_initrd_start, prom_initrd_end;
174 174
175#ifdef CONFIG_PPC64 175#ifdef CONFIG_PPC64
176static int __initdata iommu_force_on; 176static int __initdata prom_iommu_force_on;
177static int __initdata ppc64_iommu_off; 177static int __initdata prom_iommu_off;
178static unsigned long __initdata prom_tce_alloc_start; 178static unsigned long __initdata prom_tce_alloc_start;
179static unsigned long __initdata prom_tce_alloc_end; 179static unsigned long __initdata prom_tce_alloc_end;
180#endif 180#endif
@@ -582,9 +582,9 @@ static void __init early_cmdline_parse(void)
582 while (*opt && *opt == ' ') 582 while (*opt && *opt == ' ')
583 opt++; 583 opt++;
584 if (!strncmp(opt, RELOC("off"), 3)) 584 if (!strncmp(opt, RELOC("off"), 3))
585 RELOC(ppc64_iommu_off) = 1; 585 RELOC(prom_iommu_off) = 1;
586 else if (!strncmp(opt, RELOC("force"), 5)) 586 else if (!strncmp(opt, RELOC("force"), 5))
587 RELOC(iommu_force_on) = 1; 587 RELOC(prom_iommu_force_on) = 1;
588 } 588 }
589#endif 589#endif
590} 590}
@@ -627,6 +627,7 @@ static void __init early_cmdline_parse(void)
627/* Option vector 3: processor options supported */ 627/* Option vector 3: processor options supported */
628#define OV3_FP 0x80 /* floating point */ 628#define OV3_FP 0x80 /* floating point */
629#define OV3_VMX 0x40 /* VMX/Altivec */ 629#define OV3_VMX 0x40 /* VMX/Altivec */
630#define OV3_DFP 0x20 /* decimal FP */
630 631
631/* Option vector 5: PAPR/OF options supported */ 632/* Option vector 5: PAPR/OF options supported */
632#define OV5_LPAR 0x80 /* logical partitioning supported */ 633#define OV5_LPAR 0x80 /* logical partitioning supported */
@@ -642,6 +643,7 @@ static void __init early_cmdline_parse(void)
642static unsigned char ibm_architecture_vec[] = { 643static unsigned char ibm_architecture_vec[] = {
643 W(0xfffe0000), W(0x003a0000), /* POWER5/POWER5+ */ 644 W(0xfffe0000), W(0x003a0000), /* POWER5/POWER5+ */
644 W(0xffff0000), W(0x003e0000), /* POWER6 */ 645 W(0xffff0000), W(0x003e0000), /* POWER6 */
646 W(0xffffffff), W(0x0f000002), /* all 2.05-compliant */
645 W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */ 647 W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */
646 5 - 1, /* 5 option vectors */ 648 5 - 1, /* 5 option vectors */
647 649
@@ -668,7 +670,7 @@ static unsigned char ibm_architecture_vec[] = {
668 /* option vector 3: processor options supported */ 670 /* option vector 3: processor options supported */
669 3 - 2, /* length */ 671 3 - 2, /* length */
670 0, /* don't ignore, don't halt */ 672 0, /* don't ignore, don't halt */
671 OV3_FP | OV3_VMX, 673 OV3_FP | OV3_VMX | OV3_DFP,
672 674
673 /* option vector 4: IBM PAPR implementation */ 675 /* option vector 4: IBM PAPR implementation */
674 2 - 2, /* length */ 676 2 - 2, /* length */
@@ -1167,7 +1169,7 @@ static void __init prom_initialize_tce_table(void)
1167 u64 local_alloc_top, local_alloc_bottom; 1169 u64 local_alloc_top, local_alloc_bottom;
1168 u64 i; 1170 u64 i;
1169 1171
1170 if (RELOC(ppc64_iommu_off)) 1172 if (RELOC(prom_iommu_off))
1171 return; 1173 return;
1172 1174
1173 prom_debug("starting prom_initialize_tce_table\n"); 1175 prom_debug("starting prom_initialize_tce_table\n");
@@ -2283,11 +2285,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
2283 * Fill in some infos for use by the kernel later on 2285 * Fill in some infos for use by the kernel later on
2284 */ 2286 */
2285#ifdef CONFIG_PPC64 2287#ifdef CONFIG_PPC64
2286 if (RELOC(ppc64_iommu_off)) 2288 if (RELOC(prom_iommu_off))
2287 prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off", 2289 prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off",
2288 NULL, 0); 2290 NULL, 0);
2289 2291
2290 if (RELOC(iommu_force_on)) 2292 if (RELOC(prom_iommu_force_on))
2291 prom_setprop(_prom->chosen, "/chosen", "linux,iommu-force-on", 2293 prom_setprop(_prom->chosen, "/chosen", "linux,iommu-force-on",
2292 NULL, 0); 2294 NULL, 0);
2293 2295
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index 603dff3ad62a..0dfbe1cd28eb 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -25,6 +25,12 @@
25#define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \ 25#define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \
26 (ns) > 0) 26 (ns) > 0)
27 27
28static struct of_bus *of_match_bus(struct device_node *np);
29static int __of_address_to_resource(struct device_node *dev,
30 const u32 *addrp, u64 size, unsigned int flags,
31 struct resource *r);
32
33
28/* Debug utility */ 34/* Debug utility */
29#ifdef DEBUG 35#ifdef DEBUG
30static void of_dump_addr(const char *s, const u32 *addr, int na) 36static void of_dump_addr(const char *s, const u32 *addr, int na)
@@ -101,6 +107,7 @@ static unsigned int of_bus_default_get_flags(const u32 *addr)
101} 107}
102 108
103 109
110#ifdef CONFIG_PCI
104/* 111/*
105 * PCI bus specific translator 112 * PCI bus specific translator
106 */ 113 */
@@ -153,15 +160,156 @@ static unsigned int of_bus_pci_get_flags(const u32 *addr)
153 switch((w >> 24) & 0x03) { 160 switch((w >> 24) & 0x03) {
154 case 0x01: 161 case 0x01:
155 flags |= IORESOURCE_IO; 162 flags |= IORESOURCE_IO;
163 break;
156 case 0x02: /* 32 bits */ 164 case 0x02: /* 32 bits */
157 case 0x03: /* 64 bits */ 165 case 0x03: /* 64 bits */
158 flags |= IORESOURCE_MEM; 166 flags |= IORESOURCE_MEM;
167 break;
159 } 168 }
160 if (w & 0x40000000) 169 if (w & 0x40000000)
161 flags |= IORESOURCE_PREFETCH; 170 flags |= IORESOURCE_PREFETCH;
162 return flags; 171 return flags;
163} 172}
164 173
174const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
175 unsigned int *flags)
176{
177 const u32 *prop;
178 unsigned int psize;
179 struct device_node *parent;
180 struct of_bus *bus;
181 int onesize, i, na, ns;
182
183 /* Get parent & match bus type */
184 parent = of_get_parent(dev);
185 if (parent == NULL)
186 return NULL;
187 bus = of_match_bus(parent);
188 if (strcmp(bus->name, "pci")) {
189 of_node_put(parent);
190 return NULL;
191 }
192 bus->count_cells(dev, &na, &ns);
193 of_node_put(parent);
194 if (!OF_CHECK_COUNTS(na, ns))
195 return NULL;
196
197 /* Get "reg" or "assigned-addresses" property */
198 prop = get_property(dev, bus->addresses, &psize);
199 if (prop == NULL)
200 return NULL;
201 psize /= 4;
202
203 onesize = na + ns;
204 for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
205 if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) {
206 if (size)
207 *size = of_read_number(prop + na, ns);
208 if (flags)
209 *flags = bus->get_flags(prop);
210 return prop;
211 }
212 return NULL;
213}
214EXPORT_SYMBOL(of_get_pci_address);
215
216int of_pci_address_to_resource(struct device_node *dev, int bar,
217 struct resource *r)
218{
219 const u32 *addrp;
220 u64 size;
221 unsigned int flags;
222
223 addrp = of_get_pci_address(dev, bar, &size, &flags);
224 if (addrp == NULL)
225 return -EINVAL;
226 return __of_address_to_resource(dev, addrp, size, flags, r);
227}
228EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
229
230static u8 of_irq_pci_swizzle(u8 slot, u8 pin)
231{
232 return (((pin - 1) + slot) % 4) + 1;
233}
234
235int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
236{
237 struct device_node *dn, *ppnode;
238 struct pci_dev *ppdev;
239 u32 lspec;
240 u32 laddr[3];
241 u8 pin;
242 int rc;
243
244 /* Check if we have a device node, if yes, fallback to standard OF
245 * parsing
246 */
247 dn = pci_device_to_OF_node(pdev);
248 if (dn)
249 return of_irq_map_one(dn, 0, out_irq);
250
251 /* Ok, we don't, time to have fun. Let's start by building up an
252 * interrupt spec. we assume #interrupt-cells is 1, which is standard
253 * for PCI. If you do different, then don't use that routine.
254 */
255 rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
256 if (rc != 0)
257 return rc;
258 /* No pin, exit */
259 if (pin == 0)
260 return -ENODEV;
261
262 /* Now we walk up the PCI tree */
263 lspec = pin;
264 for (;;) {
265 /* Get the pci_dev of our parent */
266 ppdev = pdev->bus->self;
267
268 /* Ouch, it's a host bridge... */
269 if (ppdev == NULL) {
270#ifdef CONFIG_PPC64
271 ppnode = pci_bus_to_OF_node(pdev->bus);
272#else
273 struct pci_controller *host;
274 host = pci_bus_to_host(pdev->bus);
275 ppnode = host ? host->arch_data : NULL;
276#endif
277 /* No node for host bridge ? give up */
278 if (ppnode == NULL)
279 return -EINVAL;
280 } else
281 /* We found a P2P bridge, check if it has a node */
282 ppnode = pci_device_to_OF_node(ppdev);
283
284 /* Ok, we have found a parent with a device-node, hand over to
285 * the OF parsing code.
286 * We build a unit address from the linux device to be used for
287 * resolution. Note that we use the linux bus number which may
288 * not match your firmware bus numbering.
289 * Fortunately, in most cases, interrupt-map-mask doesn't include
290 * the bus number as part of the matching.
291 * You should still be careful about that though if you intend
292 * to rely on this function (you ship a firmware that doesn't
293 * create device nodes for all PCI devices).
294 */
295 if (ppnode)
296 break;
297
298 /* We can only get here if we hit a P2P bridge with no node,
299 * let's do standard swizzling and try again
300 */
301 lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec);
302 pdev = ppdev;
303 }
304
305 laddr[0] = (pdev->bus->number << 16)
306 | (pdev->devfn << 8);
307 laddr[1] = laddr[2] = 0;
308 return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
309}
310EXPORT_SYMBOL_GPL(of_irq_map_pci);
311#endif /* CONFIG_PCI */
312
165/* 313/*
166 * ISA bus specific translator 314 * ISA bus specific translator
167 */ 315 */
@@ -223,6 +371,7 @@ static unsigned int of_bus_isa_get_flags(const u32 *addr)
223 */ 371 */
224 372
225static struct of_bus of_busses[] = { 373static struct of_bus of_busses[] = {
374#ifdef CONFIG_PCI
226 /* PCI */ 375 /* PCI */
227 { 376 {
228 .name = "pci", 377 .name = "pci",
@@ -233,6 +382,7 @@ static struct of_bus of_busses[] = {
233 .translate = of_bus_pci_translate, 382 .translate = of_bus_pci_translate,
234 .get_flags = of_bus_pci_get_flags, 383 .get_flags = of_bus_pci_get_flags,
235 }, 384 },
385#endif /* CONFIG_PCI */
236 /* ISA */ 386 /* ISA */
237 { 387 {
238 .name = "isa", 388 .name = "isa",
@@ -445,48 +595,6 @@ const u32 *of_get_address(struct device_node *dev, int index, u64 *size,
445} 595}
446EXPORT_SYMBOL(of_get_address); 596EXPORT_SYMBOL(of_get_address);
447 597
448const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
449 unsigned int *flags)
450{
451 const u32 *prop;
452 unsigned int psize;
453 struct device_node *parent;
454 struct of_bus *bus;
455 int onesize, i, na, ns;
456
457 /* Get parent & match bus type */
458 parent = of_get_parent(dev);
459 if (parent == NULL)
460 return NULL;
461 bus = of_match_bus(parent);
462 if (strcmp(bus->name, "pci")) {
463 of_node_put(parent);
464 return NULL;
465 }
466 bus->count_cells(dev, &na, &ns);
467 of_node_put(parent);
468 if (!OF_CHECK_COUNTS(na, ns))
469 return NULL;
470
471 /* Get "reg" or "assigned-addresses" property */
472 prop = get_property(dev, bus->addresses, &psize);
473 if (prop == NULL)
474 return NULL;
475 psize /= 4;
476
477 onesize = na + ns;
478 for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
479 if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) {
480 if (size)
481 *size = of_read_number(prop + na, ns);
482 if (flags)
483 *flags = bus->get_flags(prop);
484 return prop;
485 }
486 return NULL;
487}
488EXPORT_SYMBOL(of_get_pci_address);
489
490static int __of_address_to_resource(struct device_node *dev, const u32 *addrp, 598static int __of_address_to_resource(struct device_node *dev, const u32 *addrp,
491 u64 size, unsigned int flags, 599 u64 size, unsigned int flags,
492 struct resource *r) 600 struct resource *r)
@@ -529,20 +637,6 @@ int of_address_to_resource(struct device_node *dev, int index,
529} 637}
530EXPORT_SYMBOL_GPL(of_address_to_resource); 638EXPORT_SYMBOL_GPL(of_address_to_resource);
531 639
532int of_pci_address_to_resource(struct device_node *dev, int bar,
533 struct resource *r)
534{
535 const u32 *addrp;
536 u64 size;
537 unsigned int flags;
538
539 addrp = of_get_pci_address(dev, bar, &size, &flags);
540 if (addrp == NULL)
541 return -EINVAL;
542 return __of_address_to_resource(dev, addrp, size, flags, r);
543}
544EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
545
546void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, 640void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
547 unsigned long *busno, unsigned long *phys, unsigned long *size) 641 unsigned long *busno, unsigned long *phys, unsigned long *size)
548{ 642{
@@ -898,87 +992,3 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
898 return res; 992 return res;
899} 993}
900EXPORT_SYMBOL_GPL(of_irq_map_one); 994EXPORT_SYMBOL_GPL(of_irq_map_one);
901
902#ifdef CONFIG_PCI
903static u8 of_irq_pci_swizzle(u8 slot, u8 pin)
904{
905 return (((pin - 1) + slot) % 4) + 1;
906}
907
908int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
909{
910 struct device_node *dn, *ppnode;
911 struct pci_dev *ppdev;
912 u32 lspec;
913 u32 laddr[3];
914 u8 pin;
915 int rc;
916
917 /* Check if we have a device node, if yes, fallback to standard OF
918 * parsing
919 */
920 dn = pci_device_to_OF_node(pdev);
921 if (dn)
922 return of_irq_map_one(dn, 0, out_irq);
923
924 /* Ok, we don't, time to have fun. Let's start by building up an
925 * interrupt spec. we assume #interrupt-cells is 1, which is standard
926 * for PCI. If you do different, then don't use that routine.
927 */
928 rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
929 if (rc != 0)
930 return rc;
931 /* No pin, exit */
932 if (pin == 0)
933 return -ENODEV;
934
935 /* Now we walk up the PCI tree */
936 lspec = pin;
937 for (;;) {
938 /* Get the pci_dev of our parent */
939 ppdev = pdev->bus->self;
940
941 /* Ouch, it's a host bridge... */
942 if (ppdev == NULL) {
943#ifdef CONFIG_PPC64
944 ppnode = pci_bus_to_OF_node(pdev->bus);
945#else
946 struct pci_controller *host;
947 host = pci_bus_to_host(pdev->bus);
948 ppnode = host ? host->arch_data : NULL;
949#endif
950 /* No node for host bridge ? give up */
951 if (ppnode == NULL)
952 return -EINVAL;
953 } else
954 /* We found a P2P bridge, check if it has a node */
955 ppnode = pci_device_to_OF_node(ppdev);
956
957 /* Ok, we have found a parent with a device-node, hand over to
958 * the OF parsing code.
959 * We build a unit address from the linux device to be used for
960 * resolution. Note that we use the linux bus number which may
961 * not match your firmware bus numbering.
962 * Fortunately, in most cases, interrupt-map-mask doesn't include
963 * the bus number as part of the matching.
964 * You should still be careful about that though if you intend
965 * to rely on this function (you ship a firmware that doesn't
966 * create device nodes for all PCI devices).
967 */
968 if (ppnode)
969 break;
970
971 /* We can only get here if we hit a P2P bridge with no node,
972 * let's do standard swizzling and try again
973 */
974 lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec);
975 pdev = ppdev;
976 }
977
978 laddr[0] = (pdev->bus->number << 16)
979 | (pdev->devfn << 8);
980 laddr[1] = laddr[2] = 0;
981 return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
982}
983EXPORT_SYMBOL_GPL(of_irq_map_pci);
984#endif /* CONFIG_PCI */
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 6ef80d4e38d3..387ed0d9ad61 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -810,9 +810,9 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
810 return 0; 810 return 0;
811} 811}
812 812
813#ifdef CONFIG_HOTPLUG_CPU
813/* This version can't take the spinlock, because it never returns */ 814/* This version can't take the spinlock, because it never returns */
814 815static struct rtas_args rtas_stop_self_args = {
815struct rtas_args rtas_stop_self_args = {
816 /* The token is initialized for real in setup_system() */ 816 /* The token is initialized for real in setup_system() */
817 .token = RTAS_UNKNOWN_SERVICE, 817 .token = RTAS_UNKNOWN_SERVICE,
818 .nargs = 0, 818 .nargs = 0,
@@ -834,6 +834,7 @@ void rtas_stop_self(void)
834 834
835 panic("Alas, I survived.\n"); 835 panic("Alas, I survived.\n");
836} 836}
837#endif
837 838
838/* 839/*
839 * Call early during boot, before mem init or bootmem, to retrieve the RTAS 840 * Call early during boot, before mem init or bootmem, to retrieve the RTAS
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index 6f6fc977cb39..b9561d300516 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -681,14 +681,12 @@ static int initialize_flash_pde_data(const char *rtas_call_name,
681 int *status; 681 int *status;
682 int token; 682 int token;
683 683
684 dp->data = kmalloc(buf_size, GFP_KERNEL); 684 dp->data = kzalloc(buf_size, GFP_KERNEL);
685 if (dp->data == NULL) { 685 if (dp->data == NULL) {
686 remove_flash_pde(dp); 686 remove_flash_pde(dp);
687 return -ENOMEM; 687 return -ENOMEM;
688 } 688 }
689 689
690 memset(dp->data, 0, buf_size);
691
692 /* 690 /*
693 * This code assumes that the status int is the first member of the 691 * This code assumes that the status int is the first member of the
694 * struct 692 * struct
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index b4a0de79c060..ace9f4c86e67 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -38,6 +38,7 @@
38#include <asm/rtas.h> 38#include <asm/rtas.h>
39#include <asm/mpic.h> 39#include <asm/mpic.h>
40#include <asm/ppc-pci.h> 40#include <asm/ppc-pci.h>
41#include <asm/eeh.h>
41 42
42/* RTAS tokens */ 43/* RTAS tokens */
43static int read_pci_config; 44static int read_pci_config;
@@ -231,32 +232,13 @@ void __init init_pci_config_tokens (void)
231 232
232unsigned long __devinit get_phb_buid (struct device_node *phb) 233unsigned long __devinit get_phb_buid (struct device_node *phb)
233{ 234{
234 int addr_cells; 235 struct resource r;
235 const unsigned int *buid_vals;
236 unsigned int len;
237 unsigned long buid;
238
239 if (ibm_read_pci_config == -1) return 0;
240 236
241 /* PHB's will always be children of the root node, 237 if (ibm_read_pci_config == -1)
242 * or so it is promised by the current firmware. */
243 if (phb->parent == NULL)
244 return 0; 238 return 0;
245 if (phb->parent->parent) 239 if (of_address_to_resource(phb, 0, &r))
246 return 0;
247
248 buid_vals = get_property(phb, "reg", &len);
249 if (buid_vals == NULL)
250 return 0; 240 return 0;
251 241 return r.start;
252 addr_cells = prom_n_addr_cells(phb);
253 if (addr_cells == 1) {
254 buid = (unsigned long) buid_vals[0];
255 } else {
256 buid = (((unsigned long)buid_vals[0]) << 32UL) |
257 (((unsigned long)buid_vals[1]) & 0xffffffff);
258 }
259 return buid;
260} 242}
261 243
262static int phb_set_bus_ranges(struct device_node *dev, 244static int phb_set_bus_ranges(struct device_node *dev,
@@ -276,8 +258,10 @@ static int phb_set_bus_ranges(struct device_node *dev,
276 return 0; 258 return 0;
277} 259}
278 260
279int __devinit setup_phb(struct device_node *dev, struct pci_controller *phb) 261int __devinit rtas_setup_phb(struct pci_controller *phb)
280{ 262{
263 struct device_node *dev = phb->arch_data;
264
281 if (is_python(dev)) 265 if (is_python(dev))
282 python_countermeasures(dev); 266 python_countermeasures(dev);
283 267
@@ -309,7 +293,7 @@ unsigned long __init find_and_init_phbs(void)
309 phb = pcibios_alloc_controller(node); 293 phb = pcibios_alloc_controller(node);
310 if (!phb) 294 if (!phb)
311 continue; 295 continue;
312 setup_phb(node, phb); 296 rtas_setup_phb(phb);
313 pci_process_bridge_OF_ranges(phb, node, 0); 297 pci_process_bridge_OF_ranges(phb, node, 0);
314 pci_setup_phb_io(phb, index == 0); 298 pci_setup_phb_io(phb, index == 0);
315 index++; 299 index++;
@@ -381,7 +365,6 @@ int pcibios_remove_root_bus(struct pci_controller *phb)
381 } 365 }
382 } 366 }
383 367
384 list_del(&phb->list_node);
385 pcibios_free_controller(phb); 368 pcibios_free_controller(phb);
386 369
387 return 0; 370 return 0;
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index a4c2964a3ca6..61c65d19ef06 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -63,10 +63,6 @@ unsigned int DMA_MODE_WRITE;
63 63
64int have_of = 1; 64int have_of = 1;
65 65
66#ifdef CONFIG_PPC_MULTIPLATFORM
67dev_t boot_dev;
68#endif /* CONFIG_PPC_MULTIPLATFORM */
69
70#ifdef CONFIG_VGA_CONSOLE 66#ifdef CONFIG_VGA_CONSOLE
71unsigned long vgacon_remap_base; 67unsigned long vgacon_remap_base;
72#endif 68#endif
@@ -101,7 +97,7 @@ unsigned long __init early_init(unsigned long dt_ptr)
101 * Identify the CPU type and fix up code sections 97 * Identify the CPU type and fix up code sections
102 * that depend on which cpu we have. 98 * that depend on which cpu we have.
103 */ 99 */
104 spec = identify_cpu(offset); 100 spec = identify_cpu(offset, mfspr(SPRN_PVR));
105 101
106 do_feature_fixups(spec->cpu_features, 102 do_feature_fixups(spec->cpu_features,
107 PTRRELOC(&__start___ftr_fixup), 103 PTRRELOC(&__start___ftr_fixup),
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 16278968dab6..3733de30e84d 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -33,6 +33,7 @@
33#include <linux/serial.h> 33#include <linux/serial.h>
34#include <linux/serial_8250.h> 34#include <linux/serial_8250.h>
35#include <linux/bootmem.h> 35#include <linux/bootmem.h>
36#include <linux/pci.h>
36#include <asm/io.h> 37#include <asm/io.h>
37#include <asm/kdump.h> 38#include <asm/kdump.h>
38#include <asm/prom.h> 39#include <asm/prom.h>
@@ -71,7 +72,6 @@
71 72
72int have_of = 1; 73int have_of = 1;
73int boot_cpuid = 0; 74int boot_cpuid = 0;
74dev_t boot_dev;
75u64 ppc64_pft_size; 75u64 ppc64_pft_size;
76 76
77/* Pick defaults since we might want to patch instructions 77/* Pick defaults since we might want to patch instructions
@@ -171,7 +171,7 @@ void __init setup_paca(int cpu)
171void __init early_setup(unsigned long dt_ptr) 171void __init early_setup(unsigned long dt_ptr)
172{ 172{
173 /* Identify CPU type */ 173 /* Identify CPU type */
174 identify_cpu(0); 174 identify_cpu(0, mfspr(SPRN_PVR));
175 175
176 /* Assume we're on cpu 0 for now. Don't write to the paca yet! */ 176 /* Assume we're on cpu 0 for now. Don't write to the paca yet! */
177 setup_paca(0); 177 setup_paca(0);
@@ -226,8 +226,8 @@ void early_setup_secondary(void)
226{ 226{
227 struct paca_struct *lpaca = get_paca(); 227 struct paca_struct *lpaca = get_paca();
228 228
229 /* Mark enabled in PACA */ 229 /* Mark interrupts enabled in PACA */
230 lpaca->proc_enabled = 0; 230 lpaca->soft_enabled = 0;
231 231
232 /* Initialize hash table for that CPU */ 232 /* Initialize hash table for that CPU */
233 htab_initialize_secondary(); 233 htab_initialize_secondary();
@@ -392,7 +392,8 @@ void __init setup_system(void)
392 * setting up the hash table pointers. It also sets up some interrupt-mapping 392 * setting up the hash table pointers. It also sets up some interrupt-mapping
393 * related options that will be used by finish_device_tree() 393 * related options that will be used by finish_device_tree()
394 */ 394 */
395 ppc_md.init_early(); 395 if (ppc_md.init_early)
396 ppc_md.init_early();
396 397
397 /* 398 /*
398 * We can discover serial ports now since the above did setup the 399 * We can discover serial ports now since the above did setup the
@@ -598,3 +599,10 @@ void __init setup_per_cpu_areas(void)
598 } 599 }
599} 600}
600#endif 601#endif
602
603
604#ifdef CONFIG_PPC_INDIRECT_IO
605struct ppc_pci_io ppc_pci_io;
606EXPORT_SYMBOL(ppc_pci_io);
607#endif /* CONFIG_PPC_INDIRECT_IO */
608
diff --git a/arch/powerpc/kernel/smp-tbsync.c b/arch/powerpc/kernel/smp-tbsync.c
index de59c6c31a5b..bc892e69b4f7 100644
--- a/arch/powerpc/kernel/smp-tbsync.c
+++ b/arch/powerpc/kernel/smp-tbsync.c
@@ -78,7 +78,7 @@ static int __devinit start_contest(int cmd, long offset, int num)
78{ 78{
79 int i, score=0; 79 int i, score=0;
80 u64 tb; 80 u64 tb;
81 long mark; 81 u64 mark;
82 82
83 tbsync->cmd = cmd; 83 tbsync->cmd = cmd;
84 84
@@ -116,8 +116,7 @@ void __devinit smp_generic_give_timebase(void)
116 printk("Synchronizing timebase\n"); 116 printk("Synchronizing timebase\n");
117 117
118 /* if this fails then this kernel won't work anyway... */ 118 /* if this fails then this kernel won't work anyway... */
119 tbsync = kmalloc( sizeof(*tbsync), GFP_KERNEL ); 119 tbsync = kzalloc( sizeof(*tbsync), GFP_KERNEL );
120 memset( tbsync, 0, sizeof(*tbsync) );
121 mb(); 120 mb();
122 running = 1; 121 running = 1;
123 122
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 35c6309bdb76..9b28c238b6c0 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -65,6 +65,7 @@ cpumask_t cpu_sibling_map[NR_CPUS] = { [0 ... NR_CPUS-1] = CPU_MASK_NONE };
65 65
66EXPORT_SYMBOL(cpu_online_map); 66EXPORT_SYMBOL(cpu_online_map);
67EXPORT_SYMBOL(cpu_possible_map); 67EXPORT_SYMBOL(cpu_possible_map);
68EXPORT_SYMBOL(cpu_sibling_map);
68 69
69/* SMP operations for this machine */ 70/* SMP operations for this machine */
70struct smp_ops_t *smp_ops; 71struct smp_ops_t *smp_ops;
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index d15c33e95959..03a2a2f30d66 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -51,6 +51,7 @@
51#include <asm/time.h> 51#include <asm/time.h>
52#include <asm/mmu_context.h> 52#include <asm/mmu_context.h>
53#include <asm/ppc-pci.h> 53#include <asm/ppc-pci.h>
54#include <asm/syscalls.h>
54 55
55/* readdir & getdents */ 56/* readdir & getdents */
56#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de))) 57#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index d45a168bdaca..22123a0d5416 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -200,10 +200,9 @@ static void register_cpu_online(unsigned int cpu)
200 struct cpu *c = &per_cpu(cpu_devices, cpu); 200 struct cpu *c = &per_cpu(cpu_devices, cpu);
201 struct sys_device *s = &c->sysdev; 201 struct sys_device *s = &c->sysdev;
202 202
203#ifndef CONFIG_PPC_ISERIES 203 if (!firmware_has_feature(FW_FEATURE_ISERIES) &&
204 if (cpu_has_feature(CPU_FTR_SMT)) 204 cpu_has_feature(CPU_FTR_SMT))
205 sysdev_create_file(s, &attr_smt_snooze_delay); 205 sysdev_create_file(s, &attr_smt_snooze_delay);
206#endif
207 206
208 /* PMC stuff */ 207 /* PMC stuff */
209 208
@@ -242,10 +241,9 @@ static void unregister_cpu_online(unsigned int cpu)
242 241
243 BUG_ON(c->no_control); 242 BUG_ON(c->no_control);
244 243
245#ifndef CONFIG_PPC_ISERIES 244 if (!firmware_has_feature(FW_FEATURE_ISERIES) &&
246 if (cpu_has_feature(CPU_FTR_SMT)) 245 cpu_has_feature(CPU_FTR_SMT))
247 sysdev_remove_file(s, &attr_smt_snooze_delay); 246 sysdev_remove_file(s, &attr_smt_snooze_delay);
248#endif
249 247
250 /* PMC stuff */ 248 /* PMC stuff */
251 249
@@ -299,6 +297,72 @@ static struct notifier_block __cpuinitdata sysfs_cpu_nb = {
299 .notifier_call = sysfs_cpu_notify, 297 .notifier_call = sysfs_cpu_notify,
300}; 298};
301 299
300static DEFINE_MUTEX(cpu_mutex);
301
302int cpu_add_sysdev_attr(struct sysdev_attribute *attr)
303{
304 int cpu;
305
306 mutex_lock(&cpu_mutex);
307
308 for_each_possible_cpu(cpu) {
309 sysdev_create_file(get_cpu_sysdev(cpu), attr);
310 }
311
312 mutex_unlock(&cpu_mutex);
313 return 0;
314}
315EXPORT_SYMBOL_GPL(cpu_add_sysdev_attr);
316
317int cpu_add_sysdev_attr_group(struct attribute_group *attrs)
318{
319 int cpu;
320 struct sys_device *sysdev;
321
322 mutex_lock(&cpu_mutex);
323
324 for_each_possible_cpu(cpu) {
325 sysdev = get_cpu_sysdev(cpu);
326 sysfs_create_group(&sysdev->kobj, attrs);
327 }
328
329 mutex_unlock(&cpu_mutex);
330 return 0;
331}
332EXPORT_SYMBOL_GPL(cpu_add_sysdev_attr_group);
333
334
335void cpu_remove_sysdev_attr(struct sysdev_attribute *attr)
336{
337 int cpu;
338
339 mutex_lock(&cpu_mutex);
340
341 for_each_possible_cpu(cpu) {
342 sysdev_remove_file(get_cpu_sysdev(cpu), attr);
343 }
344
345 mutex_unlock(&cpu_mutex);
346}
347EXPORT_SYMBOL_GPL(cpu_remove_sysdev_attr);
348
349void cpu_remove_sysdev_attr_group(struct attribute_group *attrs)
350{
351 int cpu;
352 struct sys_device *sysdev;
353
354 mutex_lock(&cpu_mutex);
355
356 for_each_possible_cpu(cpu) {
357 sysdev = get_cpu_sysdev(cpu);
358 sysfs_remove_group(&sysdev->kobj, attrs);
359 }
360
361 mutex_unlock(&cpu_mutex);
362}
363EXPORT_SYMBOL_GPL(cpu_remove_sysdev_attr_group);
364
365
302/* NUMA stuff */ 366/* NUMA stuff */
303 367
304#ifdef CONFIG_NUMA 368#ifdef CONFIG_NUMA
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 46a24de36fec..f6f0c6b07c4c 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -631,7 +631,8 @@ void timer_interrupt(struct pt_regs * regs)
631 calculate_steal_time(); 631 calculate_steal_time();
632 632
633#ifdef CONFIG_PPC_ISERIES 633#ifdef CONFIG_PPC_ISERIES
634 get_lppaca()->int_dword.fields.decr_int = 0; 634 if (firmware_has_feature(FW_FEATURE_ISERIES))
635 get_lppaca()->int_dword.fields.decr_int = 0;
635#endif 636#endif
636 637
637 while ((ticks = tb_ticks_since(per_cpu(last_jiffy, cpu))) 638 while ((ticks = tb_ticks_since(per_cpu(last_jiffy, cpu)))
@@ -674,7 +675,7 @@ void timer_interrupt(struct pt_regs * regs)
674 set_dec(next_dec); 675 set_dec(next_dec);
675 676
676#ifdef CONFIG_PPC_ISERIES 677#ifdef CONFIG_PPC_ISERIES
677 if (hvlpevent_is_pending()) 678 if (firmware_has_feature(FW_FEATURE_ISERIES) && hvlpevent_is_pending())
678 process_hvlpevents(); 679 process_hvlpevents();
679#endif 680#endif
680 681
@@ -774,7 +775,7 @@ int do_settimeofday(struct timespec *tv)
774 * settimeofday to perform this operation. 775 * settimeofday to perform this operation.
775 */ 776 */
776#ifdef CONFIG_PPC_ISERIES 777#ifdef CONFIG_PPC_ISERIES
777 if (first_settimeofday) { 778 if (firmware_has_feature(FW_FEATURE_ISERIES) && first_settimeofday) {
778 iSeries_tb_recal(); 779 iSeries_tb_recal();
779 first_settimeofday = 0; 780 first_settimeofday = 0;
780 } 781 }
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index c66b4771ef44..0d4e203fa7a0 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -53,10 +53,6 @@
53#endif 53#endif
54#include <asm/kexec.h> 54#include <asm/kexec.h>
55 55
56#ifdef CONFIG_PPC64 /* XXX */
57#define _IO_BASE pci_io_base
58#endif
59
60#ifdef CONFIG_DEBUGGER 56#ifdef CONFIG_DEBUGGER
61int (*__debugger)(struct pt_regs *regs); 57int (*__debugger)(struct pt_regs *regs);
62int (*__debugger_ipi)(struct pt_regs *regs); 58int (*__debugger_ipi)(struct pt_regs *regs);
@@ -241,7 +237,7 @@ void system_reset_exception(struct pt_regs *regs)
241 */ 237 */
242static inline int check_io_access(struct pt_regs *regs) 238static inline int check_io_access(struct pt_regs *regs)
243{ 239{
244#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) 240#ifdef CONFIG_PPC32
245 unsigned long msr = regs->msr; 241 unsigned long msr = regs->msr;
246 const struct exception_table_entry *entry; 242 const struct exception_table_entry *entry;
247 unsigned int *nip = (unsigned int *)regs->nip; 243 unsigned int *nip = (unsigned int *)regs->nip;
@@ -274,7 +270,7 @@ static inline int check_io_access(struct pt_regs *regs)
274 return 1; 270 return 1;
275 } 271 }
276 } 272 }
277#endif /* CONFIG_PPC_PMAC && CONFIG_PPC32 */ 273#endif /* CONFIG_PPC32 */
278 return 0; 274 return 0;
279} 275}
280 276
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index ed007878d1bf..a80f8f1d2e5d 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -81,15 +81,15 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
81 struct iommu_table *tbl; 81 struct iommu_table *tbl;
82 unsigned long offset, size; 82 unsigned long offset, size;
83 83
84 dma_window = get_property(dev->dev.platform_data, 84 dma_window = get_property(dev->dev.archdata.of_node,
85 "ibm,my-dma-window", NULL); 85 "ibm,my-dma-window", NULL);
86 if (!dma_window) 86 if (!dma_window)
87 return NULL; 87 return NULL;
88 88
89 tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); 89 tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
90 90
91 of_parse_dma_window(dev->dev.platform_data, dma_window, 91 of_parse_dma_window(dev->dev.archdata.of_node, dma_window,
92 &tbl->it_index, &offset, &size); 92 &tbl->it_index, &offset, &size);
93 93
94 /* TCE table size - measured in tce entries */ 94 /* TCE table size - measured in tce entries */
95 tbl->it_size = size >> IOMMU_PAGE_SHIFT; 95 tbl->it_size = size >> IOMMU_PAGE_SHIFT;
@@ -117,7 +117,8 @@ static const struct vio_device_id *vio_match_device(
117{ 117{
118 while (ids->type[0] != '\0') { 118 while (ids->type[0] != '\0') {
119 if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) && 119 if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) &&
120 device_is_compatible(dev->dev.platform_data, ids->compat)) 120 device_is_compatible(dev->dev.archdata.of_node,
121 ids->compat))
121 return ids; 122 return ids;
122 ids++; 123 ids++;
123 } 124 }
@@ -198,9 +199,9 @@ EXPORT_SYMBOL(vio_unregister_driver);
198/* vio_dev refcount hit 0 */ 199/* vio_dev refcount hit 0 */
199static void __devinit vio_dev_release(struct device *dev) 200static void __devinit vio_dev_release(struct device *dev)
200{ 201{
201 if (dev->platform_data) { 202 if (dev->archdata.of_node) {
202 /* XXX free TCE table */ 203 /* XXX should free TCE table */
203 of_node_put(dev->platform_data); 204 of_node_put(dev->archdata.of_node);
204 } 205 }
205 kfree(to_vio_dev(dev)); 206 kfree(to_vio_dev(dev));
206} 207}
@@ -210,7 +211,7 @@ static void __devinit vio_dev_release(struct device *dev)
210 * @of_node: The OF node for this device. 211 * @of_node: The OF node for this device.
211 * 212 *
212 * Creates and initializes a vio_dev structure from the data in 213 * Creates and initializes a vio_dev structure from the data in
213 * of_node (dev.platform_data) and adds it to the list of virtual devices. 214 * of_node and adds it to the list of virtual devices.
214 * Returns a pointer to the created vio_dev or NULL if node has 215 * Returns a pointer to the created vio_dev or NULL if node has
215 * NULL device_type or compatible fields. 216 * NULL device_type or compatible fields.
216 */ 217 */
@@ -240,8 +241,6 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
240 if (viodev == NULL) 241 if (viodev == NULL)
241 return NULL; 242 return NULL;
242 243
243 viodev->dev.platform_data = of_node_get(of_node);
244
245 viodev->irq = irq_of_parse_and_map(of_node, 0); 244 viodev->irq = irq_of_parse_and_map(of_node, 0);
246 245
247 snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address); 246 snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);
@@ -254,7 +253,10 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
254 if (unit_address != NULL) 253 if (unit_address != NULL)
255 viodev->unit_address = *unit_address; 254 viodev->unit_address = *unit_address;
256 } 255 }
257 viodev->iommu_table = vio_build_iommu_table(viodev); 256 viodev->dev.archdata.of_node = of_node_get(of_node);
257 viodev->dev.archdata.dma_ops = &dma_iommu_ops;
258 viodev->dev.archdata.dma_data = vio_build_iommu_table(viodev);
259 viodev->dev.archdata.numa_node = of_node_to_nid(of_node);
258 260
259 /* init generic 'struct device' fields: */ 261 /* init generic 'struct device' fields: */
260 viodev->dev.parent = &vio_bus_device.dev; 262 viodev->dev.parent = &vio_bus_device.dev;
@@ -285,10 +287,11 @@ static int __init vio_bus_init(void)
285#ifdef CONFIG_PPC_ISERIES 287#ifdef CONFIG_PPC_ISERIES
286 if (firmware_has_feature(FW_FEATURE_ISERIES)) { 288 if (firmware_has_feature(FW_FEATURE_ISERIES)) {
287 iommu_vio_init(); 289 iommu_vio_init();
288 vio_bus_device.iommu_table = &vio_iommu_table; 290 vio_bus_device.dev.archdata.dma_ops = &dma_iommu_ops;
291 vio_bus_device.dev.archdata.dma_data = &vio_iommu_table;
289 iSeries_vio_dev = &vio_bus_device.dev; 292 iSeries_vio_dev = &vio_bus_device.dev;
290 } 293 }
291#endif 294#endif /* CONFIG_PPC_ISERIES */
292 295
293 err = bus_register(&vio_bus_type); 296 err = bus_register(&vio_bus_type);
294 if (err) { 297 if (err) {
@@ -336,7 +339,7 @@ static ssize_t name_show(struct device *dev,
336static ssize_t devspec_show(struct device *dev, 339static ssize_t devspec_show(struct device *dev,
337 struct device_attribute *attr, char *buf) 340 struct device_attribute *attr, char *buf)
338{ 341{
339 struct device_node *of_node = dev->platform_data; 342 struct device_node *of_node = dev->archdata.of_node;
340 343
341 return sprintf(buf, "%s\n", of_node ? of_node->full_name : "none"); 344 return sprintf(buf, "%s\n", of_node ? of_node->full_name : "none");
342} 345}
@@ -353,62 +356,6 @@ void __devinit vio_unregister_device(struct vio_dev *viodev)
353} 356}
354EXPORT_SYMBOL(vio_unregister_device); 357EXPORT_SYMBOL(vio_unregister_device);
355 358
356static dma_addr_t vio_map_single(struct device *dev, void *vaddr,
357 size_t size, enum dma_data_direction direction)
358{
359 return iommu_map_single(to_vio_dev(dev)->iommu_table, vaddr, size,
360 ~0ul, direction);
361}
362
363static void vio_unmap_single(struct device *dev, dma_addr_t dma_handle,
364 size_t size, enum dma_data_direction direction)
365{
366 iommu_unmap_single(to_vio_dev(dev)->iommu_table, dma_handle, size,
367 direction);
368}
369
370static int vio_map_sg(struct device *dev, struct scatterlist *sglist,
371 int nelems, enum dma_data_direction direction)
372{
373 return iommu_map_sg(dev, to_vio_dev(dev)->iommu_table, sglist,
374 nelems, ~0ul, direction);
375}
376
377static void vio_unmap_sg(struct device *dev, struct scatterlist *sglist,
378 int nelems, enum dma_data_direction direction)
379{
380 iommu_unmap_sg(to_vio_dev(dev)->iommu_table, sglist, nelems, direction);
381}
382
383static void *vio_alloc_coherent(struct device *dev, size_t size,
384 dma_addr_t *dma_handle, gfp_t flag)
385{
386 return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size,
387 dma_handle, ~0ul, flag, -1);
388}
389
390static void vio_free_coherent(struct device *dev, size_t size,
391 void *vaddr, dma_addr_t dma_handle)
392{
393 iommu_free_coherent(to_vio_dev(dev)->iommu_table, size, vaddr,
394 dma_handle);
395}
396
397static int vio_dma_supported(struct device *dev, u64 mask)
398{
399 return 1;
400}
401
402struct dma_mapping_ops vio_dma_ops = {
403 .alloc_coherent = vio_alloc_coherent,
404 .free_coherent = vio_free_coherent,
405 .map_single = vio_map_single,
406 .unmap_single = vio_unmap_single,
407 .map_sg = vio_map_sg,
408 .unmap_sg = vio_unmap_sg,
409 .dma_supported = vio_dma_supported,
410};
411
412static int vio_bus_match(struct device *dev, struct device_driver *drv) 359static int vio_bus_match(struct device *dev, struct device_driver *drv)
413{ 360{
414 const struct vio_dev *vio_dev = to_vio_dev(dev); 361 const struct vio_dev *vio_dev = to_vio_dev(dev);
@@ -422,13 +369,14 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp,
422 char *buffer, int buffer_size) 369 char *buffer, int buffer_size)
423{ 370{
424 const struct vio_dev *vio_dev = to_vio_dev(dev); 371 const struct vio_dev *vio_dev = to_vio_dev(dev);
425 struct device_node *dn = dev->platform_data; 372 struct device_node *dn;
426 const char *cp; 373 const char *cp;
427 int length; 374 int length;
428 375
429 if (!num_envp) 376 if (!num_envp)
430 return -ENOMEM; 377 return -ENOMEM;
431 378
379 dn = dev->archdata.of_node;
432 if (!dn) 380 if (!dn)
433 return -ENODEV; 381 return -ENODEV;
434 cp = get_property(dn, "compatible", &length); 382 cp = get_property(dn, "compatible", &length);
@@ -465,7 +413,7 @@ struct bus_type vio_bus_type = {
465*/ 413*/
466const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length) 414const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length)
467{ 415{
468 return get_property(vdev->dev.platform_data, which, length); 416 return get_property(vdev->dev.archdata.of_node, which, length);
469} 417}
470EXPORT_SYMBOL(vio_get_attribute); 418EXPORT_SYMBOL(vio_get_attribute);
471 419
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile
index 93441e7a2921..38a81967ca07 100644
--- a/arch/powerpc/mm/Makefile
+++ b/arch/powerpc/mm/Makefile
@@ -8,7 +8,7 @@ endif
8 8
9obj-y := fault.o mem.o lmb.o 9obj-y := fault.o mem.o lmb.o
10obj-$(CONFIG_PPC32) += init_32.o pgtable_32.o mmu_context_32.o 10obj-$(CONFIG_PPC32) += init_32.o pgtable_32.o mmu_context_32.o
11hash-$(CONFIG_PPC_MULTIPLATFORM) := hash_native_64.o 11hash-$(CONFIG_PPC_NATIVE) := hash_native_64.o
12obj-$(CONFIG_PPC64) += init_64.o pgtable_64.o mmu_context_64.o \ 12obj-$(CONFIG_PPC64) += init_64.o pgtable_64.o mmu_context_64.o \
13 hash_utils_64.o hash_low_64.o tlb_64.o \ 13 hash_utils_64.o hash_low_64.o tlb_64.o \
14 slb_low.o slb.o stab.o mmap.o imalloc.o \ 14 slb_low.o slb.o stab.o mmap.o imalloc.o \
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index e8fa50624b70..03aeb3a46077 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -426,18 +426,21 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
426 426
427 /* kernel has accessed a bad area */ 427 /* kernel has accessed a bad area */
428 428
429 printk(KERN_ALERT "Unable to handle kernel paging request for ");
430 switch (regs->trap) { 429 switch (regs->trap) {
431 case 0x300: 430 case 0x300:
432 case 0x380: 431 case 0x380:
433 printk("data at address 0x%08lx\n", regs->dar); 432 printk(KERN_ALERT "Unable to handle kernel paging request for "
434 break; 433 "data at address 0x%08lx\n", regs->dar);
435 case 0x400: 434 break;
436 case 0x480: 435 case 0x400:
437 printk("instruction fetch\n"); 436 case 0x480:
438 break; 437 printk(KERN_ALERT "Unable to handle kernel paging request for "
439 default: 438 "instruction fetch\n");
440 printk("unknown fault\n"); 439 break;
440 default:
441 printk(KERN_ALERT "Unable to handle kernel paging request for "
442 "unknown fault\n");
443 break;
441 } 444 }
442 printk(KERN_ALERT "Faulting instruction address: 0x%08lx\n", 445 printk(KERN_ALERT "Faulting instruction address: 0x%08lx\n",
443 regs->nip); 446 regs->nip);
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index c90f124f3c71..6f1016acdbf6 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -123,7 +123,7 @@ static inline void native_unlock_hpte(hpte_t *hptep)
123 clear_bit(HPTE_LOCK_BIT, word); 123 clear_bit(HPTE_LOCK_BIT, word);
124} 124}
125 125
126long native_hpte_insert(unsigned long hpte_group, unsigned long va, 126static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
127 unsigned long pa, unsigned long rflags, 127 unsigned long pa, unsigned long rflags,
128 unsigned long vflags, int psize) 128 unsigned long vflags, int psize)
129{ 129{
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 1915661c2c81..c0d2a694fa30 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -277,7 +277,7 @@ static void __init htab_init_page_sizes(void)
277 * Not in the device-tree, let's fallback on known size 277 * Not in the device-tree, let's fallback on known size
278 * list for 16M capable GP & GR 278 * list for 16M capable GP & GR
279 */ 279 */
280 if (cpu_has_feature(CPU_FTR_16M_PAGE) && !machine_is(iseries)) 280 if (cpu_has_feature(CPU_FTR_16M_PAGE))
281 memcpy(mmu_psize_defs, mmu_psize_defaults_gp, 281 memcpy(mmu_psize_defs, mmu_psize_defaults_gp,
282 sizeof(mmu_psize_defaults_gp)); 282 sizeof(mmu_psize_defaults_gp));
283 found: 283 found:
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 3ff374697e34..9a178549cbcf 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -130,7 +130,7 @@ static int __init setup_kcore(void)
130 /* GFP_ATOMIC to avoid might_sleep warnings during boot */ 130 /* GFP_ATOMIC to avoid might_sleep warnings during boot */
131 kcore_mem = kmalloc(sizeof(struct kcore_list), GFP_ATOMIC); 131 kcore_mem = kmalloc(sizeof(struct kcore_list), GFP_ATOMIC);
132 if (!kcore_mem) 132 if (!kcore_mem)
133 panic("mem_init: kmalloc failed\n"); 133 panic("%s: kmalloc failed\n", __FUNCTION__);
134 134
135 kclist_add(kcore_mem, __va(base), size); 135 kclist_add(kcore_mem, __va(base), size);
136 } 136 }
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index 8fcacb0239da..1891dbeeb8e9 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -141,29 +141,19 @@ void pte_free(struct page *ptepage)
141 __free_page(ptepage); 141 __free_page(ptepage);
142} 142}
143 143
144#ifndef CONFIG_PHYS_64BIT
145void __iomem * 144void __iomem *
146ioremap(phys_addr_t addr, unsigned long size) 145ioremap(phys_addr_t addr, unsigned long size)
147{ 146{
148 return __ioremap(addr, size, _PAGE_NO_CACHE); 147 return __ioremap(addr, size, _PAGE_NO_CACHE);
149} 148}
150#else /* CONFIG_PHYS_64BIT */ 149EXPORT_SYMBOL(ioremap);
151void __iomem *
152ioremap64(unsigned long long addr, unsigned long size)
153{
154 return __ioremap(addr, size, _PAGE_NO_CACHE);
155}
156EXPORT_SYMBOL(ioremap64);
157 150
158void __iomem * 151void __iomem *
159ioremap(phys_addr_t addr, unsigned long size) 152ioremap_flags(phys_addr_t addr, unsigned long size, unsigned long flags)
160{ 153{
161 phys_addr_t addr64 = fixup_bigphys_addr(addr, size); 154 return __ioremap(addr, size, flags);
162
163 return ioremap64(addr64, size);
164} 155}
165#endif /* CONFIG_PHYS_64BIT */ 156EXPORT_SYMBOL(ioremap_flags);
166EXPORT_SYMBOL(ioremap);
167 157
168void __iomem * 158void __iomem *
169__ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) 159__ioremap(phys_addr_t addr, unsigned long size, unsigned long flags)
@@ -264,20 +254,7 @@ void iounmap(volatile void __iomem *addr)
264} 254}
265EXPORT_SYMBOL(iounmap); 255EXPORT_SYMBOL(iounmap);
266 256
267void __iomem *ioport_map(unsigned long port, unsigned int len) 257int map_page(unsigned long va, phys_addr_t pa, int flags)
268{
269 return (void __iomem *) (port + _IO_BASE);
270}
271
272void ioport_unmap(void __iomem *addr)
273{
274 /* Nothing to do */
275}
276EXPORT_SYMBOL(ioport_map);
277EXPORT_SYMBOL(ioport_unmap);
278
279int
280map_page(unsigned long va, phys_addr_t pa, int flags)
281{ 258{
282 pmd_t *pd; 259 pmd_t *pd;
283 pte_t *pg; 260 pte_t *pg;
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index ac64f4aaa509..16e4ee1c2318 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -113,7 +113,7 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags)
113} 113}
114 114
115 115
116static void __iomem * __ioremap_com(unsigned long addr, unsigned long pa, 116static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa,
117 unsigned long ea, unsigned long size, 117 unsigned long ea, unsigned long size,
118 unsigned long flags) 118 unsigned long flags)
119{ 119{
@@ -129,22 +129,12 @@ static void __iomem * __ioremap_com(unsigned long addr, unsigned long pa,
129 return (void __iomem *) (ea + (addr & ~PAGE_MASK)); 129 return (void __iomem *) (ea + (addr & ~PAGE_MASK));
130} 130}
131 131
132 132void __iomem * __ioremap(phys_addr_t addr, unsigned long size,
133void __iomem *
134ioremap(unsigned long addr, unsigned long size)
135{
136 return __ioremap(addr, size, _PAGE_NO_CACHE | _PAGE_GUARDED);
137}
138
139void __iomem * __ioremap(unsigned long addr, unsigned long size,
140 unsigned long flags) 133 unsigned long flags)
141{ 134{
142 unsigned long pa, ea; 135 unsigned long pa, ea;
143 void __iomem *ret; 136 void __iomem *ret;
144 137
145 if (firmware_has_feature(FW_FEATURE_ISERIES))
146 return (void __iomem *)addr;
147
148 /* 138 /*
149 * Choose an address to map it to. 139 * Choose an address to map it to.
150 * Once the imalloc system is running, we use it. 140 * Once the imalloc system is running, we use it.
@@ -178,9 +168,28 @@ void __iomem * __ioremap(unsigned long addr, unsigned long size,
178 return ret; 168 return ret;
179} 169}
180 170
171
172void __iomem * ioremap(phys_addr_t addr, unsigned long size)
173{
174 unsigned long flags = _PAGE_NO_CACHE | _PAGE_GUARDED;
175
176 if (ppc_md.ioremap)
177 return ppc_md.ioremap(addr, size, flags);
178 return __ioremap(addr, size, flags);
179}
180
181void __iomem * ioremap_flags(phys_addr_t addr, unsigned long size,
182 unsigned long flags)
183{
184 if (ppc_md.ioremap)
185 return ppc_md.ioremap(addr, size, flags);
186 return __ioremap(addr, size, flags);
187}
188
189
181#define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK)) 190#define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK))
182 191
183int __ioremap_explicit(unsigned long pa, unsigned long ea, 192int __ioremap_explicit(phys_addr_t pa, unsigned long ea,
184 unsigned long size, unsigned long flags) 193 unsigned long size, unsigned long flags)
185{ 194{
186 struct vm_struct *area; 195 struct vm_struct *area;
@@ -235,13 +244,10 @@ int __ioremap_explicit(unsigned long pa, unsigned long ea,
235 * 244 *
236 * XXX what about calls before mem_init_done (ie python_countermeasures()) 245 * XXX what about calls before mem_init_done (ie python_countermeasures())
237 */ 246 */
238void iounmap(volatile void __iomem *token) 247void __iounmap(volatile void __iomem *token)
239{ 248{
240 void *addr; 249 void *addr;
241 250
242 if (firmware_has_feature(FW_FEATURE_ISERIES))
243 return;
244
245 if (!mem_init_done) 251 if (!mem_init_done)
246 return; 252 return;
247 253
@@ -250,6 +256,14 @@ void iounmap(volatile void __iomem *token)
250 im_free(addr); 256 im_free(addr);
251} 257}
252 258
259void iounmap(volatile void __iomem *token)
260{
261 if (ppc_md.iounmap)
262 ppc_md.iounmap(token);
263 else
264 __iounmap(token);
265}
266
253static int iounmap_subset_regions(unsigned long addr, unsigned long size) 267static int iounmap_subset_regions(unsigned long addr, unsigned long size)
254{ 268{
255 struct vm_struct *area; 269 struct vm_struct *area;
@@ -268,7 +282,7 @@ static int iounmap_subset_regions(unsigned long addr, unsigned long size)
268 return 0; 282 return 0;
269} 283}
270 284
271int iounmap_explicit(volatile void __iomem *start, unsigned long size) 285int __iounmap_explicit(volatile void __iomem *start, unsigned long size)
272{ 286{
273 struct vm_struct *area; 287 struct vm_struct *area;
274 unsigned long addr; 288 unsigned long addr;
@@ -303,8 +317,10 @@ int iounmap_explicit(volatile void __iomem *start, unsigned long size)
303} 317}
304 318
305EXPORT_SYMBOL(ioremap); 319EXPORT_SYMBOL(ioremap);
320EXPORT_SYMBOL(ioremap_flags);
306EXPORT_SYMBOL(__ioremap); 321EXPORT_SYMBOL(__ioremap);
307EXPORT_SYMBOL(iounmap); 322EXPORT_SYMBOL(iounmap);
323EXPORT_SYMBOL(__iounmap);
308 324
309void __iomem * reserve_phb_iospace(unsigned long size) 325void __iomem * reserve_phb_iospace(unsigned long size)
310{ 326{
diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c
index d3733912adb4..224e960650a0 100644
--- a/arch/powerpc/mm/slb.c
+++ b/arch/powerpc/mm/slb.c
@@ -23,6 +23,7 @@
23#include <asm/cputable.h> 23#include <asm/cputable.h>
24#include <asm/cacheflush.h> 24#include <asm/cacheflush.h>
25#include <asm/smp.h> 25#include <asm/smp.h>
26#include <asm/firmware.h>
26#include <linux/compiler.h> 27#include <linux/compiler.h>
27 28
28#ifdef DEBUG 29#ifdef DEBUG
@@ -193,6 +194,7 @@ static inline void patch_slb_encoding(unsigned int *insn_addr,
193void slb_initialize(void) 194void slb_initialize(void)
194{ 195{
195 unsigned long linear_llp, vmalloc_llp, io_llp; 196 unsigned long linear_llp, vmalloc_llp, io_llp;
197 unsigned long lflags, vflags;
196 static int slb_encoding_inited; 198 static int slb_encoding_inited;
197 extern unsigned int *slb_miss_kernel_load_linear; 199 extern unsigned int *slb_miss_kernel_load_linear;
198 extern unsigned int *slb_miss_kernel_load_io; 200 extern unsigned int *slb_miss_kernel_load_io;
@@ -225,11 +227,12 @@ void slb_initialize(void)
225#endif 227#endif
226 } 228 }
227 229
230 get_paca()->stab_rr = SLB_NUM_BOLTED;
231
228 /* On iSeries the bolted entries have already been set up by 232 /* On iSeries the bolted entries have already been set up by
229 * the hypervisor from the lparMap data in head.S */ 233 * the hypervisor from the lparMap data in head.S */
230#ifndef CONFIG_PPC_ISERIES 234 if (firmware_has_feature(FW_FEATURE_ISERIES))
231 { 235 return;
232 unsigned long lflags, vflags;
233 236
234 lflags = SLB_VSID_KERNEL | linear_llp; 237 lflags = SLB_VSID_KERNEL | linear_llp;
235 vflags = SLB_VSID_KERNEL | vmalloc_llp; 238 vflags = SLB_VSID_KERNEL | vmalloc_llp;
@@ -247,8 +250,4 @@ void slb_initialize(void)
247 * elsewhere, we'll call _switch() which will bolt in the new 250 * elsewhere, we'll call _switch() which will bolt in the new
248 * one. */ 251 * one. */
249 asm volatile("isync":::"memory"); 252 asm volatile("isync":::"memory");
250 }
251#endif /* CONFIG_PPC_ISERIES */
252
253 get_paca()->stab_rr = SLB_NUM_BOLTED;
254} 253}
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile
index 0b5df9c96ae0..4ccef2d5530c 100644
--- a/arch/powerpc/oprofile/Makefile
+++ b/arch/powerpc/oprofile/Makefile
@@ -11,6 +11,7 @@ DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
11 timer_int.o ) 11 timer_int.o )
12 12
13oprofile-y := $(DRIVER_OBJS) common.o backtrace.o 13oprofile-y := $(DRIVER_OBJS) common.o backtrace.o
14oprofile-$(CONFIG_PPC_CELL_NATIVE) += op_model_cell.o
14oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o 15oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o
15oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o 16oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o
16oprofile-$(CONFIG_6xx) += op_model_7450.o 17oprofile-$(CONFIG_6xx) += op_model_7450.o
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c
index 63bbef3b63f1..b6d82390b6a6 100644
--- a/arch/powerpc/oprofile/common.c
+++ b/arch/powerpc/oprofile/common.c
@@ -69,7 +69,10 @@ static void op_powerpc_cpu_start(void *dummy)
69 69
70static int op_powerpc_start(void) 70static int op_powerpc_start(void)
71{ 71{
72 on_each_cpu(op_powerpc_cpu_start, NULL, 0, 1); 72 if (model->global_start)
73 model->global_start(ctr);
74 if (model->start)
75 on_each_cpu(op_powerpc_cpu_start, NULL, 0, 1);
73 return 0; 76 return 0;
74} 77}
75 78
@@ -80,7 +83,10 @@ static inline void op_powerpc_cpu_stop(void *dummy)
80 83
81static void op_powerpc_stop(void) 84static void op_powerpc_stop(void)
82{ 85{
83 on_each_cpu(op_powerpc_cpu_stop, NULL, 0, 1); 86 if (model->stop)
87 on_each_cpu(op_powerpc_cpu_stop, NULL, 0, 1);
88 if (model->global_stop)
89 model->global_stop();
84} 90}
85 91
86static int op_powerpc_create_files(struct super_block *sb, struct dentry *root) 92static int op_powerpc_create_files(struct super_block *sb, struct dentry *root)
@@ -141,6 +147,11 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
141 147
142 switch (cur_cpu_spec->oprofile_type) { 148 switch (cur_cpu_spec->oprofile_type) {
143#ifdef CONFIG_PPC64 149#ifdef CONFIG_PPC64
150#ifdef CONFIG_PPC_CELL_NATIVE
151 case PPC_OPROFILE_CELL:
152 model = &op_model_cell;
153 break;
154#endif
144 case PPC_OPROFILE_RS64: 155 case PPC_OPROFILE_RS64:
145 model = &op_model_rs64; 156 model = &op_model_rs64;
146 break; 157 break;
diff --git a/arch/powerpc/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c
new file mode 100644
index 000000000000..2eb15f388103
--- /dev/null
+++ b/arch/powerpc/oprofile/op_model_cell.c
@@ -0,0 +1,724 @@
1/*
2 * Cell Broadband Engine OProfile Support
3 *
4 * (C) Copyright IBM Corporation 2006
5 *
6 * Author: David Erb (djerb@us.ibm.com)
7 * Modifications:
8 * Carl Love <carll@us.ibm.com>
9 * Maynard Johnson <maynardj@us.ibm.com>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version
14 * 2 of the License, or (at your option) any later version.
15 */
16
17#include <linux/cpufreq.h>
18#include <linux/delay.h>
19#include <linux/init.h>
20#include <linux/jiffies.h>
21#include <linux/kthread.h>
22#include <linux/oprofile.h>
23#include <linux/percpu.h>
24#include <linux/smp.h>
25#include <linux/spinlock.h>
26#include <linux/timer.h>
27#include <asm/cell-pmu.h>
28#include <asm/cputable.h>
29#include <asm/firmware.h>
30#include <asm/io.h>
31#include <asm/oprofile_impl.h>
32#include <asm/processor.h>
33#include <asm/prom.h>
34#include <asm/ptrace.h>
35#include <asm/reg.h>
36#include <asm/rtas.h>
37#include <asm/system.h>
38
39#include "../platforms/cell/interrupt.h"
40
41#define PPU_CYCLES_EVENT_NUM 1 /* event number for CYCLES */
42#define CBE_COUNT_ALL_CYCLES 0x42800000 /* PPU cycle event specifier */
43
44#define NUM_THREADS 2
45#define VIRT_CNTR_SW_TIME_NS 100000000 // 0.5 seconds
46
47struct pmc_cntrl_data {
48 unsigned long vcntr;
49 unsigned long evnts;
50 unsigned long masks;
51 unsigned long enabled;
52};
53
54/*
55 * ibm,cbe-perftools rtas parameters
56 */
57
58struct pm_signal {
59 u16 cpu; /* Processor to modify */
60 u16 sub_unit; /* hw subunit this applies to (if applicable) */
61 u16 signal_group; /* Signal Group to Enable/Disable */
62 u8 bus_word; /* Enable/Disable on this Trace/Trigger/Event
63 * Bus Word(s) (bitmask)
64 */
65 u8 bit; /* Trigger/Event bit (if applicable) */
66};
67
68/*
69 * rtas call arguments
70 */
71enum {
72 SUBFUNC_RESET = 1,
73 SUBFUNC_ACTIVATE = 2,
74 SUBFUNC_DEACTIVATE = 3,
75
76 PASSTHRU_IGNORE = 0,
77 PASSTHRU_ENABLE = 1,
78 PASSTHRU_DISABLE = 2,
79};
80
81struct pm_cntrl {
82 u16 enable;
83 u16 stop_at_max;
84 u16 trace_mode;
85 u16 freeze;
86 u16 count_mode;
87};
88
89static struct {
90 u32 group_control;
91 u32 debug_bus_control;
92 struct pm_cntrl pm_cntrl;
93 u32 pm07_cntrl[NR_PHYS_CTRS];
94} pm_regs;
95
96
97#define GET_SUB_UNIT(x) ((x & 0x0000f000) >> 12)
98#define GET_BUS_WORD(x) ((x & 0x000000f0) >> 4)
99#define GET_BUS_TYPE(x) ((x & 0x00000300) >> 8)
100#define GET_POLARITY(x) ((x & 0x00000002) >> 1)
101#define GET_COUNT_CYCLES(x) (x & 0x00000001)
102#define GET_INPUT_CONTROL(x) ((x & 0x00000004) >> 2)
103
104
105static DEFINE_PER_CPU(unsigned long[NR_PHYS_CTRS], pmc_values);
106
107static struct pmc_cntrl_data pmc_cntrl[NUM_THREADS][NR_PHYS_CTRS];
108
109/* Interpetation of hdw_thread:
110 * 0 - even virtual cpus 0, 2, 4,...
111 * 1 - odd virtual cpus 1, 3, 5, ...
112 */
113static u32 hdw_thread;
114
115static u32 virt_cntr_inter_mask;
116static struct timer_list timer_virt_cntr;
117
118/* pm_signal needs to be global since it is initialized in
119 * cell_reg_setup at the time when the necessary information
120 * is available.
121 */
122static struct pm_signal pm_signal[NR_PHYS_CTRS];
123static int pm_rtas_token;
124
125static u32 reset_value[NR_PHYS_CTRS];
126static int num_counters;
127static int oprofile_running;
128static spinlock_t virt_cntr_lock = SPIN_LOCK_UNLOCKED;
129
130static u32 ctr_enabled;
131
132static unsigned char trace_bus[4];
133static unsigned char input_bus[2];
134
135/*
136 * Firmware interface functions
137 */
138static int
139rtas_ibm_cbe_perftools(int subfunc, int passthru,
140 void *address, unsigned long length)
141{
142 u64 paddr = __pa(address);
143
144 return rtas_call(pm_rtas_token, 5, 1, NULL, subfunc, passthru,
145 paddr >> 32, paddr & 0xffffffff, length);
146}
147
148static void pm_rtas_reset_signals(u32 node)
149{
150 int ret;
151 struct pm_signal pm_signal_local;
152
153 /* The debug bus is being set to the passthru disable state.
154 * However, the FW still expects atleast one legal signal routing
155 * entry or it will return an error on the arguments. If we don't
156 * supply a valid entry, we must ignore all return values. Ignoring
157 * all return values means we might miss an error we should be
158 * concerned about.
159 */
160
161 /* fw expects physical cpu #. */
162 pm_signal_local.cpu = node;
163 pm_signal_local.signal_group = 21;
164 pm_signal_local.bus_word = 1;
165 pm_signal_local.sub_unit = 0;
166 pm_signal_local.bit = 0;
167
168 ret = rtas_ibm_cbe_perftools(SUBFUNC_RESET, PASSTHRU_DISABLE,
169 &pm_signal_local,
170 sizeof(struct pm_signal));
171
172 if (ret)
173 printk(KERN_WARNING "%s: rtas returned: %d\n",
174 __FUNCTION__, ret);
175}
176
177static void pm_rtas_activate_signals(u32 node, u32 count)
178{
179 int ret;
180 int j;
181 struct pm_signal pm_signal_local[NR_PHYS_CTRS];
182
183 for (j = 0; j < count; j++) {
184 /* fw expects physical cpu # */
185 pm_signal_local[j].cpu = node;
186 pm_signal_local[j].signal_group = pm_signal[j].signal_group;
187 pm_signal_local[j].bus_word = pm_signal[j].bus_word;
188 pm_signal_local[j].sub_unit = pm_signal[j].sub_unit;
189 pm_signal_local[j].bit = pm_signal[j].bit;
190 }
191
192 ret = rtas_ibm_cbe_perftools(SUBFUNC_ACTIVATE, PASSTHRU_ENABLE,
193 pm_signal_local,
194 count * sizeof(struct pm_signal));
195
196 if (ret)
197 printk(KERN_WARNING "%s: rtas returned: %d\n",
198 __FUNCTION__, ret);
199}
200
201/*
202 * PM Signal functions
203 */
204static void set_pm_event(u32 ctr, int event, u32 unit_mask)
205{
206 struct pm_signal *p;
207 u32 signal_bit;
208 u32 bus_word, bus_type, count_cycles, polarity, input_control;
209 int j, i;
210
211 if (event == PPU_CYCLES_EVENT_NUM) {
212 /* Special Event: Count all cpu cycles */
213 pm_regs.pm07_cntrl[ctr] = CBE_COUNT_ALL_CYCLES;
214 p = &(pm_signal[ctr]);
215 p->signal_group = 21;
216 p->bus_word = 1;
217 p->sub_unit = 0;
218 p->bit = 0;
219 goto out;
220 } else {
221 pm_regs.pm07_cntrl[ctr] = 0;
222 }
223
224 bus_word = GET_BUS_WORD(unit_mask);
225 bus_type = GET_BUS_TYPE(unit_mask);
226 count_cycles = GET_COUNT_CYCLES(unit_mask);
227 polarity = GET_POLARITY(unit_mask);
228 input_control = GET_INPUT_CONTROL(unit_mask);
229 signal_bit = (event % 100);
230
231 p = &(pm_signal[ctr]);
232
233 p->signal_group = event / 100;
234 p->bus_word = bus_word;
235 p->sub_unit = unit_mask & 0x0000f000;
236
237 pm_regs.pm07_cntrl[ctr] = 0;
238 pm_regs.pm07_cntrl[ctr] |= PM07_CTR_COUNT_CYCLES(count_cycles);
239 pm_regs.pm07_cntrl[ctr] |= PM07_CTR_POLARITY(polarity);
240 pm_regs.pm07_cntrl[ctr] |= PM07_CTR_INPUT_CONTROL(input_control);
241
242 if (input_control == 0) {
243 if (signal_bit > 31) {
244 signal_bit -= 32;
245 if (bus_word == 0x3)
246 bus_word = 0x2;
247 else if (bus_word == 0xc)
248 bus_word = 0x8;
249 }
250
251 if ((bus_type == 0) && p->signal_group >= 60)
252 bus_type = 2;
253 if ((bus_type == 1) && p->signal_group >= 50)
254 bus_type = 0;
255
256 pm_regs.pm07_cntrl[ctr] |= PM07_CTR_INPUT_MUX(signal_bit);
257 } else {
258 pm_regs.pm07_cntrl[ctr] = 0;
259 p->bit = signal_bit;
260 }
261
262 for (i = 0; i < 4; i++) {
263 if (bus_word & (1 << i)) {
264 pm_regs.debug_bus_control |=
265 (bus_type << (31 - (2 * i) + 1));
266
267 for (j = 0; j < 2; j++) {
268 if (input_bus[j] == 0xff) {
269 input_bus[j] = i;
270 pm_regs.group_control |=
271 (i << (31 - i));
272 break;
273 }
274 }
275 }
276 }
277out:
278 ;
279}
280
281static void write_pm_cntrl(int cpu, struct pm_cntrl *pm_cntrl)
282{
283 /* Oprofile will use 32 bit counters, set bits 7:10 to 0 */
284 u32 val = 0;
285 if (pm_cntrl->enable == 1)
286 val |= CBE_PM_ENABLE_PERF_MON;
287
288 if (pm_cntrl->stop_at_max == 1)
289 val |= CBE_PM_STOP_AT_MAX;
290
291 if (pm_cntrl->trace_mode == 1)
292 val |= CBE_PM_TRACE_MODE_SET(pm_cntrl->trace_mode);
293
294 if (pm_cntrl->freeze == 1)
295 val |= CBE_PM_FREEZE_ALL_CTRS;
296
297 /* Routine set_count_mode must be called previously to set
298 * the count mode based on the user selection of user and kernel.
299 */
300 val |= CBE_PM_COUNT_MODE_SET(pm_cntrl->count_mode);
301 cbe_write_pm(cpu, pm_control, val);
302}
303
304static inline void
305set_count_mode(u32 kernel, u32 user, struct pm_cntrl *pm_cntrl)
306{
307 /* The user must specify user and kernel if they want them. If
308 * neither is specified, OProfile will count in hypervisor mode
309 */
310 if (kernel) {
311 if (user)
312 pm_cntrl->count_mode = CBE_COUNT_ALL_MODES;
313 else
314 pm_cntrl->count_mode = CBE_COUNT_SUPERVISOR_MODE;
315 } else {
316 if (user)
317 pm_cntrl->count_mode = CBE_COUNT_PROBLEM_MODE;
318 else
319 pm_cntrl->count_mode = CBE_COUNT_HYPERVISOR_MODE;
320 }
321}
322
323static inline void enable_ctr(u32 cpu, u32 ctr, u32 * pm07_cntrl)
324{
325
326 pm07_cntrl[ctr] |= PM07_CTR_ENABLE(1);
327 cbe_write_pm07_control(cpu, ctr, pm07_cntrl[ctr]);
328}
329
330/*
331 * Oprofile is expected to collect data on all CPUs simultaneously.
332 * However, there is one set of performance counters per node. There are
333 * two hardware threads or virtual CPUs on each node. Hence, OProfile must
334 * multiplex in time the performance counter collection on the two virtual
335 * CPUs. The multiplexing of the performance counters is done by this
336 * virtual counter routine.
337 *
338 * The pmc_values used below is defined as 'per-cpu' but its use is
339 * more akin to 'per-node'. We need to store two sets of counter
340 * values per node -- one for the previous run and one for the next.
341 * The per-cpu[NR_PHYS_CTRS] gives us the storage we need. Each odd/even
342 * pair of per-cpu arrays is used for storing the previous and next
343 * pmc values for a given node.
344 * NOTE: We use the per-cpu variable to improve cache performance.
345 */
346static void cell_virtual_cntr(unsigned long data)
347{
348 /* This routine will alternate loading the virtual counters for
349 * virtual CPUs
350 */
351 int i, prev_hdw_thread, next_hdw_thread;
352 u32 cpu;
353 unsigned long flags;
354
355 /* Make sure that the interrupt_hander and
356 * the virt counter are not both playing with
357 * the counters on the same node.
358 */
359
360 spin_lock_irqsave(&virt_cntr_lock, flags);
361
362 prev_hdw_thread = hdw_thread;
363
364 /* switch the cpu handling the interrupts */
365 hdw_thread = 1 ^ hdw_thread;
366 next_hdw_thread = hdw_thread;
367
368 /* The following is done only once per each node, but
369 * we need cpu #, not node #, to pass to the cbe_xxx functions.
370 */
371 for_each_online_cpu(cpu) {
372 if (cbe_get_hw_thread_id(cpu))
373 continue;
374
375 /* stop counters, save counter values, restore counts
376 * for previous thread
377 */
378 cbe_disable_pm(cpu);
379 cbe_disable_pm_interrupts(cpu);
380 for (i = 0; i < num_counters; i++) {
381 per_cpu(pmc_values, cpu + prev_hdw_thread)[i]
382 = cbe_read_ctr(cpu, i);
383
384 if (per_cpu(pmc_values, cpu + next_hdw_thread)[i]
385 == 0xFFFFFFFF)
386 /* If the cntr value is 0xffffffff, we must
387 * reset that to 0xfffffff0 when the current
388 * thread is restarted. This will generate a new
389 * interrupt and make sure that we never restore
390 * the counters to the max value. If the counters
391 * were restored to the max value, they do not
392 * increment and no interrupts are generated. Hence
393 * no more samples will be collected on that cpu.
394 */
395 cbe_write_ctr(cpu, i, 0xFFFFFFF0);
396 else
397 cbe_write_ctr(cpu, i,
398 per_cpu(pmc_values,
399 cpu +
400 next_hdw_thread)[i]);
401 }
402
403 /* Switch to the other thread. Change the interrupt
404 * and control regs to be scheduled on the CPU
405 * corresponding to the thread to execute.
406 */
407 for (i = 0; i < num_counters; i++) {
408 if (pmc_cntrl[next_hdw_thread][i].enabled) {
409 /* There are some per thread events.
410 * Must do the set event, enable_cntr
411 * for each cpu.
412 */
413 set_pm_event(i,
414 pmc_cntrl[next_hdw_thread][i].evnts,
415 pmc_cntrl[next_hdw_thread][i].masks);
416 enable_ctr(cpu, i,
417 pm_regs.pm07_cntrl);
418 } else {
419 cbe_write_pm07_control(cpu, i, 0);
420 }
421 }
422
423 /* Enable interrupts on the CPU thread that is starting */
424 cbe_enable_pm_interrupts(cpu, next_hdw_thread,
425 virt_cntr_inter_mask);
426 cbe_enable_pm(cpu);
427 }
428
429 spin_unlock_irqrestore(&virt_cntr_lock, flags);
430
431 mod_timer(&timer_virt_cntr, jiffies + HZ / 10);
432}
433
434static void start_virt_cntrs(void)
435{
436 init_timer(&timer_virt_cntr);
437 timer_virt_cntr.function = cell_virtual_cntr;
438 timer_virt_cntr.data = 0UL;
439 timer_virt_cntr.expires = jiffies + HZ / 10;
440 add_timer(&timer_virt_cntr);
441}
442
443/* This function is called once for all cpus combined */
444static void
445cell_reg_setup(struct op_counter_config *ctr,
446 struct op_system_config *sys, int num_ctrs)
447{
448 int i, j, cpu;
449
450 pm_rtas_token = rtas_token("ibm,cbe-perftools");
451 if (pm_rtas_token == RTAS_UNKNOWN_SERVICE) {
452 printk(KERN_WARNING "%s: RTAS_UNKNOWN_SERVICE\n",
453 __FUNCTION__);
454 goto out;
455 }
456
457 num_counters = num_ctrs;
458
459 pm_regs.group_control = 0;
460 pm_regs.debug_bus_control = 0;
461
462 /* setup the pm_control register */
463 memset(&pm_regs.pm_cntrl, 0, sizeof(struct pm_cntrl));
464 pm_regs.pm_cntrl.stop_at_max = 1;
465 pm_regs.pm_cntrl.trace_mode = 0;
466 pm_regs.pm_cntrl.freeze = 1;
467
468 set_count_mode(sys->enable_kernel, sys->enable_user,
469 &pm_regs.pm_cntrl);
470
471 /* Setup the thread 0 events */
472 for (i = 0; i < num_ctrs; ++i) {
473
474 pmc_cntrl[0][i].evnts = ctr[i].event;
475 pmc_cntrl[0][i].masks = ctr[i].unit_mask;
476 pmc_cntrl[0][i].enabled = ctr[i].enabled;
477 pmc_cntrl[0][i].vcntr = i;
478
479 for_each_possible_cpu(j)
480 per_cpu(pmc_values, j)[i] = 0;
481 }
482
483 /* Setup the thread 1 events, map the thread 0 event to the
484 * equivalent thread 1 event.
485 */
486 for (i = 0; i < num_ctrs; ++i) {
487 if ((ctr[i].event >= 2100) && (ctr[i].event <= 2111))
488 pmc_cntrl[1][i].evnts = ctr[i].event + 19;
489 else if (ctr[i].event == 2203)
490 pmc_cntrl[1][i].evnts = ctr[i].event;
491 else if ((ctr[i].event >= 2200) && (ctr[i].event <= 2215))
492 pmc_cntrl[1][i].evnts = ctr[i].event + 16;
493 else
494 pmc_cntrl[1][i].evnts = ctr[i].event;
495
496 pmc_cntrl[1][i].masks = ctr[i].unit_mask;
497 pmc_cntrl[1][i].enabled = ctr[i].enabled;
498 pmc_cntrl[1][i].vcntr = i;
499 }
500
501 for (i = 0; i < 4; i++)
502 trace_bus[i] = 0xff;
503
504 for (i = 0; i < 2; i++)
505 input_bus[i] = 0xff;
506
507 /* Our counters count up, and "count" refers to
508 * how much before the next interrupt, and we interrupt
509 * on overflow. So we calculate the starting value
510 * which will give us "count" until overflow.
511 * Then we set the events on the enabled counters.
512 */
513 for (i = 0; i < num_counters; ++i) {
514 /* start with virtual counter set 0 */
515 if (pmc_cntrl[0][i].enabled) {
516 /* Using 32bit counters, reset max - count */
517 reset_value[i] = 0xFFFFFFFF - ctr[i].count;
518 set_pm_event(i,
519 pmc_cntrl[0][i].evnts,
520 pmc_cntrl[0][i].masks);
521
522 /* global, used by cell_cpu_setup */
523 ctr_enabled |= (1 << i);
524 }
525 }
526
527 /* initialize the previous counts for the virtual cntrs */
528 for_each_online_cpu(cpu)
529 for (i = 0; i < num_counters; ++i) {
530 per_cpu(pmc_values, cpu)[i] = reset_value[i];
531 }
532out:
533 ;
534}
535
536/* This function is called once for each cpu */
537static void cell_cpu_setup(struct op_counter_config *cntr)
538{
539 u32 cpu = smp_processor_id();
540 u32 num_enabled = 0;
541 int i;
542
543 /* There is one performance monitor per processor chip (i.e. node),
544 * so we only need to perform this function once per node.
545 */
546 if (cbe_get_hw_thread_id(cpu))
547 goto out;
548
549 if (pm_rtas_token == RTAS_UNKNOWN_SERVICE) {
550 printk(KERN_WARNING "%s: RTAS_UNKNOWN_SERVICE\n",
551 __FUNCTION__);
552 goto out;
553 }
554
555 /* Stop all counters */
556 cbe_disable_pm(cpu);
557 cbe_disable_pm_interrupts(cpu);
558
559 cbe_write_pm(cpu, pm_interval, 0);
560 cbe_write_pm(cpu, pm_start_stop, 0);
561 cbe_write_pm(cpu, group_control, pm_regs.group_control);
562 cbe_write_pm(cpu, debug_bus_control, pm_regs.debug_bus_control);
563 write_pm_cntrl(cpu, &pm_regs.pm_cntrl);
564
565 for (i = 0; i < num_counters; ++i) {
566 if (ctr_enabled & (1 << i)) {
567 pm_signal[num_enabled].cpu = cbe_cpu_to_node(cpu);
568 num_enabled++;
569 }
570 }
571
572 pm_rtas_activate_signals(cbe_cpu_to_node(cpu), num_enabled);
573out:
574 ;
575}
576
577static void cell_global_start(struct op_counter_config *ctr)
578{
579 u32 cpu;
580 u32 interrupt_mask = 0;
581 u32 i;
582
583 /* This routine gets called once for the system.
584 * There is one performance monitor per node, so we
585 * only need to perform this function once per node.
586 */
587 for_each_online_cpu(cpu) {
588 if (cbe_get_hw_thread_id(cpu))
589 continue;
590
591 interrupt_mask = 0;
592
593 for (i = 0; i < num_counters; ++i) {
594 if (ctr_enabled & (1 << i)) {
595 cbe_write_ctr(cpu, i, reset_value[i]);
596 enable_ctr(cpu, i, pm_regs.pm07_cntrl);
597 interrupt_mask |=
598 CBE_PM_CTR_OVERFLOW_INTR(i);
599 } else {
600 /* Disable counter */
601 cbe_write_pm07_control(cpu, i, 0);
602 }
603 }
604
605 cbe_clear_pm_interrupts(cpu);
606 cbe_enable_pm_interrupts(cpu, hdw_thread, interrupt_mask);
607 cbe_enable_pm(cpu);
608 }
609
610 virt_cntr_inter_mask = interrupt_mask;
611 oprofile_running = 1;
612 smp_wmb();
613
614 /* NOTE: start_virt_cntrs will result in cell_virtual_cntr() being
615 * executed which manipulates the PMU. We start the "virtual counter"
616 * here so that we do not need to synchronize access to the PMU in
617 * the above for-loop.
618 */
619 start_virt_cntrs();
620}
621
622static void cell_global_stop(void)
623{
624 int cpu;
625
626 /* This routine will be called once for the system.
627 * There is one performance monitor per node, so we
628 * only need to perform this function once per node.
629 */
630 del_timer_sync(&timer_virt_cntr);
631 oprofile_running = 0;
632 smp_wmb();
633
634 for_each_online_cpu(cpu) {
635 if (cbe_get_hw_thread_id(cpu))
636 continue;
637
638 cbe_sync_irq(cbe_cpu_to_node(cpu));
639 /* Stop the counters */
640 cbe_disable_pm(cpu);
641
642 /* Deactivate the signals */
643 pm_rtas_reset_signals(cbe_cpu_to_node(cpu));
644
645 /* Deactivate interrupts */
646 cbe_disable_pm_interrupts(cpu);
647 }
648}
649
650static void
651cell_handle_interrupt(struct pt_regs *regs, struct op_counter_config *ctr)
652{
653 u32 cpu;
654 u64 pc;
655 int is_kernel;
656 unsigned long flags = 0;
657 u32 interrupt_mask;
658 int i;
659
660 cpu = smp_processor_id();
661
662 /* Need to make sure the interrupt handler and the virt counter
663 * routine are not running at the same time. See the
664 * cell_virtual_cntr() routine for additional comments.
665 */
666 spin_lock_irqsave(&virt_cntr_lock, flags);
667
668 /* Need to disable and reenable the performance counters
669 * to get the desired behavior from the hardware. This
670 * is hardware specific.
671 */
672
673 cbe_disable_pm(cpu);
674
675 interrupt_mask = cbe_clear_pm_interrupts(cpu);
676
677 /* If the interrupt mask has been cleared, then the virt cntr
678 * has cleared the interrupt. When the thread that generated
679 * the interrupt is restored, the data count will be restored to
680 * 0xffffff0 to cause the interrupt to be regenerated.
681 */
682
683 if ((oprofile_running == 1) && (interrupt_mask != 0)) {
684 pc = regs->nip;
685 is_kernel = is_kernel_addr(pc);
686
687 for (i = 0; i < num_counters; ++i) {
688 if ((interrupt_mask & CBE_PM_CTR_OVERFLOW_INTR(i))
689 && ctr[i].enabled) {
690 oprofile_add_pc(pc, is_kernel, i);
691 cbe_write_ctr(cpu, i, reset_value[i]);
692 }
693 }
694
695 /* The counters were frozen by the interrupt.
696 * Reenable the interrupt and restart the counters.
697 * If there was a race between the interrupt handler and
698 * the virtual counter routine. The virutal counter
699 * routine may have cleared the interrupts. Hence must
700 * use the virt_cntr_inter_mask to re-enable the interrupts.
701 */
702 cbe_enable_pm_interrupts(cpu, hdw_thread,
703 virt_cntr_inter_mask);
704
705 /* The writes to the various performance counters only writes
706 * to a latch. The new values (interrupt setting bits, reset
707 * counter value etc.) are not copied to the actual registers
708 * until the performance monitor is enabled. In order to get
709 * this to work as desired, the permormance monitor needs to
710 * be disabled while writting to the latches. This is a
711 * HW design issue.
712 */
713 cbe_enable_pm(cpu);
714 }
715 spin_unlock_irqrestore(&virt_cntr_lock, flags);
716}
717
718struct op_powerpc_model op_model_cell = {
719 .reg_setup = cell_reg_setup,
720 .cpu_setup = cell_cpu_setup,
721 .global_start = cell_global_start,
722 .global_stop = cell_global_stop,
723 .handle_interrupt = cell_handle_interrupt,
724};
diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile
new file mode 100644
index 000000000000..a46184a0c750
--- /dev/null
+++ b/arch/powerpc/platforms/52xx/Makefile
@@ -0,0 +1,9 @@
1#
2# Makefile for 52xx based boards
3#
4ifeq ($(CONFIG_PPC_MERGE),y)
5obj-y += mpc52xx_pic.o mpc52xx_common.o
6endif
7
8obj-$(CONFIG_PPC_EFIKA) += efika-setup.o efika-pci.o
9obj-$(CONFIG_PPC_LITE5200) += lite5200.o
diff --git a/arch/powerpc/platforms/52xx/efika-pci.c b/arch/powerpc/platforms/52xx/efika-pci.c
new file mode 100644
index 000000000000..62e05b2a9227
--- /dev/null
+++ b/arch/powerpc/platforms/52xx/efika-pci.c
@@ -0,0 +1,119 @@
1
2#include <linux/kernel.h>
3#include <linux/pci.h>
4#include <linux/string.h>
5#include <linux/init.h>
6
7#include <asm/io.h>
8#include <asm/irq.h>
9#include <asm/prom.h>
10#include <asm/machdep.h>
11#include <asm/sections.h>
12#include <asm/pci-bridge.h>
13#include <asm/rtas.h>
14
15#include "efika.h"
16
17#ifdef CONFIG_PCI
18/*
19 * Access functions for PCI config space using RTAS calls.
20 */
21static int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
22 int len, u32 * val)
23{
24 struct pci_controller *hose = bus->sysdata;
25 unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
26 | (((bus->number - hose->first_busno) & 0xff) << 16)
27 | (hose->index << 24);
28 int ret = -1;
29 int rval;
30
31 rval = rtas_call(rtas_token("read-pci-config"), 2, 2, &ret, addr, len);
32 *val = ret;
33 return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
34}
35
36static int rtas_write_config(struct pci_bus *bus, unsigned int devfn,
37 int offset, int len, u32 val)
38{
39 struct pci_controller *hose = bus->sysdata;
40 unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
41 | (((bus->number - hose->first_busno) & 0xff) << 16)
42 | (hose->index << 24);
43 int rval;
44
45 rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL,
46 addr, len, val);
47 return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
48}
49
50static struct pci_ops rtas_pci_ops = {
51 rtas_read_config,
52 rtas_write_config
53};
54
55void __init efika_pcisetup(void)
56{
57 const int *bus_range;
58 int len;
59 struct pci_controller *hose;
60 struct device_node *root;
61 struct device_node *pcictrl;
62
63 root = of_find_node_by_path("/");
64 if (root == NULL) {
65 printk(KERN_WARNING EFIKA_PLATFORM_NAME
66 ": Unable to find the root node\n");
67 return;
68 }
69
70 for (pcictrl = NULL;;) {
71 pcictrl = of_get_next_child(root, pcictrl);
72 if ((pcictrl == NULL) || (strcmp(pcictrl->name, "pci") == 0))
73 break;
74 }
75
76 of_node_put(root);
77
78 if (pcictrl == NULL) {
79 printk(KERN_WARNING EFIKA_PLATFORM_NAME
80 ": Unable to find the PCI bridge node\n");
81 return;
82 }
83
84 bus_range = get_property(pcictrl, "bus-range", &len);
85 if (bus_range == NULL || len < 2 * sizeof(int)) {
86 printk(KERN_WARNING EFIKA_PLATFORM_NAME
87 ": Can't get bus-range for %s\n", pcictrl->full_name);
88 return;
89 }
90
91 if (bus_range[1] == bus_range[0])
92 printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI bus %d",
93 bus_range[0]);
94 else
95 printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI buses %d..%d",
96 bus_range[0], bus_range[1]);
97 printk(" controlled by %s\n", pcictrl->full_name);
98 printk("\n");
99
100 hose = pcibios_alloc_controller();
101 if (!hose) {
102 printk(KERN_WARNING EFIKA_PLATFORM_NAME
103 ": Can't allocate PCI controller structure for %s\n",
104 pcictrl->full_name);
105 return;
106 }
107
108 hose->arch_data = of_node_get(pcictrl);
109 hose->first_busno = bus_range[0];
110 hose->last_busno = bus_range[1];
111 hose->ops = &rtas_pci_ops;
112
113 pci_process_bridge_OF_ranges(hose, pcictrl, 0);
114}
115
116#else
117void __init efika_pcisetup(void)
118{}
119#endif
diff --git a/arch/powerpc/platforms/52xx/efika-setup.c b/arch/powerpc/platforms/52xx/efika-setup.c
new file mode 100644
index 000000000000..110c980ed1e0
--- /dev/null
+++ b/arch/powerpc/platforms/52xx/efika-setup.c
@@ -0,0 +1,150 @@
1/*
2 *
3 * Efika 5K2 platform setup
4 * Some code really inspired from the lite5200b platform.
5 *
6 * Copyright (C) 2006 bplan GmbH
7 *
8 * This file is licensed under the terms of the GNU General Public License
9 * version 2. This program is licensed "as is" without any warranty of any
10 * kind, whether express or implied.
11 *
12 */
13
14#include <linux/errno.h>
15#include <linux/kernel.h>
16#include <linux/slab.h>
17#include <linux/reboot.h>
18#include <linux/init.h>
19#include <linux/utsrelease.h>
20#include <linux/seq_file.h>
21#include <linux/root_dev.h>
22#include <linux/initrd.h>
23#include <linux/timer.h>
24#include <linux/pci.h>
25
26#include <asm/pgtable.h>
27#include <asm/prom.h>
28#include <asm/time.h>
29#include <asm/machdep.h>
30#include <asm/rtas.h>
31#include <asm/of_device.h>
32#include <asm/of_platform.h>
33#include <asm/mpc52xx.h>
34
35#include "efika.h"
36
37static void efika_show_cpuinfo(struct seq_file *m)
38{
39 struct device_node *root;
40 const char *revision = NULL;
41 const char *codegendescription = NULL;
42 const char *codegenvendor = NULL;
43
44 root = of_find_node_by_path("/");
45 if (root) {
46 revision = get_property(root, "revision", NULL);
47 codegendescription =
48 get_property(root, "CODEGEN,description", NULL);
49 codegenvendor = get_property(root, "CODEGEN,vendor", NULL);
50
51 of_node_put(root);
52 }
53
54 if (codegendescription)
55 seq_printf(m, "machine\t\t: %s\n", codegendescription);
56 else
57 seq_printf(m, "machine\t\t: Efika\n");
58
59 if (revision)
60 seq_printf(m, "revision\t: %s\n", revision);
61
62 if (codegenvendor)
63 seq_printf(m, "vendor\t\t: %s\n", codegenvendor);
64
65 of_node_put(root);
66}
67
68static void __init efika_setup_arch(void)
69{
70 rtas_initialize();
71
72#ifdef CONFIG_BLK_DEV_INITRD
73 initrd_below_start_ok = 1;
74
75 if (initrd_start)
76 ROOT_DEV = Root_RAM0;
77 else
78#endif
79 ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */
80
81 efika_pcisetup();
82
83 if (ppc_md.progress)
84 ppc_md.progress("Linux/PPC " UTS_RELEASE " runnung on Efika ;-)\n", 0x0);
85}
86
87static void __init efika_init(void)
88{
89 struct device_node *np;
90 struct device_node *cnp = NULL;
91 const u32 *base;
92
93 /* Find every child of the SOC node and add it to of_platform */
94 np = of_find_node_by_name(NULL, "builtin");
95 if (np) {
96 char name[BUS_ID_SIZE];
97 while ((cnp = of_get_next_child(np, cnp))) {
98 strcpy(name, cnp->name);
99
100 base = get_property(cnp, "reg", NULL);
101 if (base == NULL)
102 continue;
103
104 snprintf(name+strlen(name), BUS_ID_SIZE, "@%x", *base);
105 of_platform_device_create(cnp, name, NULL);
106
107 printk(KERN_INFO EFIKA_PLATFORM_NAME" : Added %s (type '%s' at '%s') to the known devices\n", name, cnp->type, cnp->full_name);
108 }
109 }
110
111 if (ppc_md.progress)
112 ppc_md.progress(" Have fun with your Efika! ", 0x7777);
113}
114
115static int __init efika_probe(void)
116{
117 char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
118 "model", NULL);
119
120 if (model == NULL)
121 return 0;
122 if (strcmp(model, "EFIKA5K2"))
123 return 0;
124
125 ISA_DMA_THRESHOLD = ~0L;
126 DMA_MODE_READ = 0x44;
127 DMA_MODE_WRITE = 0x48;
128
129 return 1;
130}
131
132define_machine(efika)
133{
134 .name = EFIKA_PLATFORM_NAME,
135 .probe = efika_probe,
136 .setup_arch = efika_setup_arch,
137 .init = efika_init,
138 .show_cpuinfo = efika_show_cpuinfo,
139 .init_IRQ = mpc52xx_init_irq,
140 .get_irq = mpc52xx_get_irq,
141 .restart = rtas_restart,
142 .power_off = rtas_power_off,
143 .halt = rtas_halt,
144 .set_rtc_time = rtas_set_rtc_time,
145 .get_rtc_time = rtas_get_rtc_time,
146 .progress = rtas_progress,
147 .get_boot_time = rtas_get_boot_time,
148 .calibrate_decr = generic_calibrate_decr,
149 .phys_mem_access_prot = pci_phys_mem_access_prot,
150};
diff --git a/arch/powerpc/platforms/52xx/efika.h b/arch/powerpc/platforms/52xx/efika.h
new file mode 100644
index 000000000000..2f060fd097d7
--- /dev/null
+++ b/arch/powerpc/platforms/52xx/efika.h
@@ -0,0 +1,19 @@
1/*
2 * Efika 5K2 platform setup - Header file
3 *
4 * Copyright (C) 2006 bplan GmbH
5 *
6 * This file is licensed under the terms of the GNU General Public License
7 * version 2. This program is licensed "as is" without any warranty of any
8 * kind, whether express or implied.
9 *
10 */
11
12#ifndef __ARCH_POWERPC_EFIKA__
13#define __ARCH_POWERPC_EFIKA__
14
15#define EFIKA_PLATFORM_NAME "Efika"
16
17extern void __init efika_pcisetup(void);
18
19#endif
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
new file mode 100644
index 000000000000..a375c15b4315
--- /dev/null
+++ b/arch/powerpc/platforms/52xx/lite5200.c
@@ -0,0 +1,162 @@
1/*
2 * Freescale Lite5200 board support
3 *
4 * Written by: Grant Likely <grant.likely@secretlab.ca>
5 *
6 * Copyright (C) Secret Lab Technologies Ltd. 2006. All rights reserved.
7 * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
8 *
9 * Description:
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15
16#undef DEBUG
17
18#include <linux/stddef.h>
19#include <linux/kernel.h>
20#include <linux/init.h>
21#include <linux/errno.h>
22#include <linux/reboot.h>
23#include <linux/pci.h>
24#include <linux/kdev_t.h>
25#include <linux/major.h>
26#include <linux/console.h>
27#include <linux/delay.h>
28#include <linux/seq_file.h>
29#include <linux/root_dev.h>
30#include <linux/initrd.h>
31
32#include <asm/system.h>
33#include <asm/atomic.h>
34#include <asm/time.h>
35#include <asm/io.h>
36#include <asm/machdep.h>
37#include <asm/ipic.h>
38#include <asm/bootinfo.h>
39#include <asm/irq.h>
40#include <asm/prom.h>
41#include <asm/udbg.h>
42#include <sysdev/fsl_soc.h>
43#include <asm/qe.h>
44#include <asm/qe_ic.h>
45#include <asm/of_platform.h>
46
47#include <asm/mpc52xx.h>
48
49/* ************************************************************************
50 *
51 * Setup the architecture
52 *
53 */
54
55static void __init
56lite52xx_setup_cpu(void)
57{
58 struct mpc52xx_gpio __iomem *gpio;
59 u32 port_config;
60
61 /* Map zones */
62 gpio = mpc52xx_find_and_map("mpc52xx-gpio");
63 if (!gpio) {
64 printk(KERN_ERR __FILE__ ": "
65 "Error while mapping GPIO register for port config. "
66 "Expect some abnormal behavior\n");
67 goto error;
68 }
69
70 /* Set port config */
71 port_config = in_be32(&gpio->port_config);
72
73 port_config &= ~0x00800000; /* 48Mhz internal, pin is GPIO */
74
75 port_config &= ~0x00007000; /* USB port : Differential mode */
76 port_config |= 0x00001000; /* USB 1 only */
77
78 port_config &= ~0x03000000; /* ATA CS is on csb_4/5 */
79 port_config |= 0x01000000;
80
81 pr_debug("port_config: old:%x new:%x\n",
82 in_be32(&gpio->port_config), port_config);
83 out_be32(&gpio->port_config, port_config);
84
85 /* Unmap zone */
86error:
87 iounmap(gpio);
88}
89
90static void __init lite52xx_setup_arch(void)
91{
92 struct device_node *np;
93
94 if (ppc_md.progress)
95 ppc_md.progress("lite52xx_setup_arch()", 0);
96
97 np = of_find_node_by_type(NULL, "cpu");
98 if (np) {
99 unsigned int *fp =
100 (int *)get_property(np, "clock-frequency", NULL);
101 if (fp != 0)
102 loops_per_jiffy = *fp / HZ;
103 else
104 loops_per_jiffy = 50000000 / HZ;
105 of_node_put(np);
106 }
107
108 /* CPU & Port mux setup */
109 mpc52xx_setup_cpu(); /* Generic */
110 lite52xx_setup_cpu(); /* Platorm specific */
111
112#ifdef CONFIG_BLK_DEV_INITRD
113 if (initrd_start)
114 ROOT_DEV = Root_RAM0;
115 else
116#endif
117#ifdef CONFIG_ROOT_NFS
118 ROOT_DEV = Root_NFS;
119#else
120 ROOT_DEV = Root_HDA1;
121#endif
122
123}
124
125void lite52xx_show_cpuinfo(struct seq_file *m)
126{
127 struct device_node* np = of_find_all_nodes(NULL);
128 const char *model = NULL;
129
130 if (np)
131 model = get_property(np, "model", NULL);
132
133 seq_printf(m, "vendor\t\t: Freescale Semiconductor\n");
134 seq_printf(m, "machine\t\t: %s\n", model ? model : "unknown");
135
136 of_node_put(np);
137}
138
139/*
140 * Called very early, MMU is off, device-tree isn't unflattened
141 */
142static int __init lite52xx_probe(void)
143{
144 unsigned long node = of_get_flat_dt_root();
145 const char *model = of_get_flat_dt_prop(node, "model", NULL);
146
147 if (!of_flat_dt_is_compatible(node, "lite52xx"))
148 return 0;
149 pr_debug("%s board w/ mpc52xx found\n", model ? model : "unknown");
150
151 return 1;
152}
153
154define_machine(lite52xx) {
155 .name = "lite52xx",
156 .probe = lite52xx_probe,
157 .setup_arch = lite52xx_setup_arch,
158 .init_IRQ = mpc52xx_init_irq,
159 .get_irq = mpc52xx_get_irq,
160 .show_cpuinfo = lite52xx_show_cpuinfo,
161 .calibrate_decr = generic_calibrate_decr,
162};
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c
new file mode 100644
index 000000000000..8331ff457770
--- /dev/null
+++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c
@@ -0,0 +1,126 @@
1/*
2 *
3 * Utility functions for the Freescale MPC52xx.
4 *
5 * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
6 *
7 * This file is licensed under the terms of the GNU General Public License
8 * version 2. This program is licensed "as is" without any warranty of any
9 * kind, whether express or implied.
10 *
11 */
12
13#undef DEBUG
14
15#include <linux/kernel.h>
16
17#include <asm/io.h>
18#include <asm/prom.h>
19#include <asm/of_platform.h>
20#include <asm/mpc52xx.h>
21
22
23void __iomem *
24mpc52xx_find_and_map(const char *compatible)
25{
26 struct device_node *ofn;
27 const u32 *regaddr_p;
28 u64 regaddr64, size64;
29
30 ofn = of_find_compatible_node(NULL, NULL, compatible);
31 if (!ofn)
32 return NULL;
33
34 regaddr_p = of_get_address(ofn, 0, &size64, NULL);
35 if (!regaddr_p) {
36 of_node_put(ofn);
37 return NULL;
38 }
39
40 regaddr64 = of_translate_address(ofn, regaddr_p);
41
42 of_node_put(ofn);
43
44 return ioremap((u32)regaddr64, (u32)size64);
45}
46EXPORT_SYMBOL(mpc52xx_find_and_map);
47
48
49/**
50 * mpc52xx_find_ipb_freq - Find the IPB bus frequency for a device
51 * @node: device node
52 *
53 * Returns IPB bus frequency, or 0 if the bus frequency cannot be found.
54 */
55unsigned int
56mpc52xx_find_ipb_freq(struct device_node *node)
57{
58 struct device_node *np;
59 const unsigned int *p_ipb_freq = NULL;
60
61 of_node_get(node);
62 while (node) {
63 p_ipb_freq = get_property(node, "bus-frequency", NULL);
64 if (p_ipb_freq)
65 break;
66
67 np = of_get_parent(node);
68 of_node_put(node);
69 node = np;
70 }
71 if (node)
72 of_node_put(node);
73
74 return p_ipb_freq ? *p_ipb_freq : 0;
75}
76EXPORT_SYMBOL(mpc52xx_find_ipb_freq);
77
78
79void __init
80mpc52xx_setup_cpu(void)
81{
82 struct mpc52xx_cdm __iomem *cdm;
83 struct mpc52xx_xlb __iomem *xlb;
84
85 /* Map zones */
86 cdm = mpc52xx_find_and_map("mpc52xx-cdm");
87 xlb = mpc52xx_find_and_map("mpc52xx-xlb");
88
89 if (!cdm || !xlb) {
90 printk(KERN_ERR __FILE__ ": "
91 "Error while mapping CDM/XLB during mpc52xx_setup_cpu. "
92 "Expect some abnormal behavior\n");
93 goto unmap_regs;
94 }
95
96 /* Use internal 48 Mhz */
97 out_8(&cdm->ext_48mhz_en, 0x00);
98 out_8(&cdm->fd_enable, 0x01);
99 if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */
100 out_be16(&cdm->fd_counters, 0x0001);
101 else
102 out_be16(&cdm->fd_counters, 0x5555);
103
104 /* Configure the XLB Arbiter priorities */
105 out_be32(&xlb->master_pri_enable, 0xff);
106 out_be32(&xlb->master_priority, 0x11111111);
107
108 /* Disable XLB pipelining */
109 /* (cfr errate 292. We could do this only just before ATA PIO
110 transaction and re-enable it afterwards ...) */
111 out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS);
112
113 /* Unmap zones */
114unmap_regs:
115 if (cdm) iounmap(cdm);
116 if (xlb) iounmap(xlb);
117}
118
119static int __init
120mpc52xx_declare_of_platform_devices(void)
121{
122 /* Find every child of the SOC node and add it to of_platform */
123 return of_platform_bus_probe(NULL, NULL, NULL);
124}
125
126device_initcall(mpc52xx_declare_of_platform_devices);
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
new file mode 100644
index 000000000000..cd91a6c3aafa
--- /dev/null
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
@@ -0,0 +1,473 @@
1/*
2 *
3 * Programmable Interrupt Controller functions for the Freescale MPC52xx.
4 *
5 * Copyright (C) 2006 bplan GmbH
6 *
7 * Based on the code from the 2.4 kernel by
8 * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
9 *
10 * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
11 * Copyright (C) 2003 Montavista Software, Inc
12 *
13 * This file is licensed under the terms of the GNU General Public License
14 * version 2. This program is licensed "as is" without any warranty of any
15 * kind, whether express or implied.
16 *
17 */
18
19#undef DEBUG
20
21#include <linux/stddef.h>
22#include <linux/init.h>
23#include <linux/sched.h>
24#include <linux/signal.h>
25#include <linux/stddef.h>
26#include <linux/delay.h>
27#include <linux/irq.h>
28#include <linux/hardirq.h>
29
30#include <asm/io.h>
31#include <asm/processor.h>
32#include <asm/system.h>
33#include <asm/irq.h>
34#include <asm/prom.h>
35#include <asm/mpc52xx.h>
36#include "mpc52xx_pic.h"
37
38/*
39 *
40*/
41
42static struct mpc52xx_intr __iomem *intr;
43static struct mpc52xx_sdma __iomem *sdma;
44static struct irq_host *mpc52xx_irqhost = NULL;
45
46static unsigned char mpc52xx_map_senses[4] = {
47 IRQ_TYPE_LEVEL_HIGH,
48 IRQ_TYPE_EDGE_RISING,
49 IRQ_TYPE_EDGE_FALLING,
50 IRQ_TYPE_LEVEL_LOW,
51};
52
53/*
54 *
55*/
56
57static inline void io_be_setbit(u32 __iomem *addr, int bitno)
58{
59 out_be32(addr, in_be32(addr) | (1 << bitno));
60}
61
62static inline void io_be_clrbit(u32 __iomem *addr, int bitno)
63{
64 out_be32(addr, in_be32(addr) & ~(1 << bitno));
65}
66
67/*
68 * IRQ[0-3] interrupt irq_chip
69*/
70
71static void mpc52xx_extirq_mask(unsigned int virq)
72{
73 int irq;
74 int l2irq;
75
76 irq = irq_map[virq].hwirq;
77 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
78
79 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
80
81 io_be_clrbit(&intr->ctrl, 11 - l2irq);
82}
83
84static void mpc52xx_extirq_unmask(unsigned int virq)
85{
86 int irq;
87 int l2irq;
88
89 irq = irq_map[virq].hwirq;
90 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
91
92 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
93
94 io_be_setbit(&intr->ctrl, 11 - l2irq);
95}
96
97static void mpc52xx_extirq_ack(unsigned int virq)
98{
99 int irq;
100 int l2irq;
101
102 irq = irq_map[virq].hwirq;
103 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
104
105 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
106
107 io_be_setbit(&intr->ctrl, 27-l2irq);
108}
109
110static struct irq_chip mpc52xx_extirq_irqchip = {
111 .typename = " MPC52xx IRQ[0-3] ",
112 .mask = mpc52xx_extirq_mask,
113 .unmask = mpc52xx_extirq_unmask,
114 .ack = mpc52xx_extirq_ack,
115};
116
117/*
118 * Main interrupt irq_chip
119*/
120
121static void mpc52xx_main_mask(unsigned int virq)
122{
123 int irq;
124 int l2irq;
125
126 irq = irq_map[virq].hwirq;
127 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
128
129 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
130
131 io_be_setbit(&intr->main_mask, 15 - l2irq);
132}
133
134static void mpc52xx_main_unmask(unsigned int virq)
135{
136 int irq;
137 int l2irq;
138
139 irq = irq_map[virq].hwirq;
140 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
141
142 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
143
144 io_be_clrbit(&intr->main_mask, 15 - l2irq);
145}
146
147static struct irq_chip mpc52xx_main_irqchip = {
148 .typename = "MPC52xx Main",
149 .mask = mpc52xx_main_mask,
150 .mask_ack = mpc52xx_main_mask,
151 .unmask = mpc52xx_main_unmask,
152};
153
154/*
155 * Peripherals interrupt irq_chip
156*/
157
158static void mpc52xx_periph_mask(unsigned int virq)
159{
160 int irq;
161 int l2irq;
162
163 irq = irq_map[virq].hwirq;
164 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
165
166 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
167
168 io_be_setbit(&intr->per_mask, 31 - l2irq);
169}
170
171static void mpc52xx_periph_unmask(unsigned int virq)
172{
173 int irq;
174 int l2irq;
175
176 irq = irq_map[virq].hwirq;
177 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
178
179 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
180
181 io_be_clrbit(&intr->per_mask, 31 - l2irq);
182}
183
184static struct irq_chip mpc52xx_periph_irqchip = {
185 .typename = "MPC52xx Peripherals",
186 .mask = mpc52xx_periph_mask,
187 .mask_ack = mpc52xx_periph_mask,
188 .unmask = mpc52xx_periph_unmask,
189};
190
191/*
192 * SDMA interrupt irq_chip
193*/
194
195static void mpc52xx_sdma_mask(unsigned int virq)
196{
197 int irq;
198 int l2irq;
199
200 irq = irq_map[virq].hwirq;
201 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
202
203 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
204
205 io_be_setbit(&sdma->IntMask, l2irq);
206}
207
208static void mpc52xx_sdma_unmask(unsigned int virq)
209{
210 int irq;
211 int l2irq;
212
213 irq = irq_map[virq].hwirq;
214 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
215
216 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
217
218 io_be_clrbit(&sdma->IntMask, l2irq);
219}
220
221static void mpc52xx_sdma_ack(unsigned int virq)
222{
223 int irq;
224 int l2irq;
225
226 irq = irq_map[virq].hwirq;
227 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
228
229 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
230
231 out_be32(&sdma->IntPend, 1 << l2irq);
232}
233
234static struct irq_chip mpc52xx_sdma_irqchip = {
235 .typename = "MPC52xx SDMA",
236 .mask = mpc52xx_sdma_mask,
237 .unmask = mpc52xx_sdma_unmask,
238 .ack = mpc52xx_sdma_ack,
239};
240
241/*
242 * irq_host
243*/
244
245static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node)
246{
247 pr_debug("%s: node=%p\n", __func__, node);
248 return mpc52xx_irqhost->host_data == node;
249}
250
251static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct,
252 u32 * intspec, unsigned int intsize,
253 irq_hw_number_t * out_hwirq,
254 unsigned int *out_flags)
255{
256 int intrvect_l1;
257 int intrvect_l2;
258 int intrvect_type;
259 int intrvect_linux;
260
261 if (intsize != 3)
262 return -1;
263
264 intrvect_l1 = (int)intspec[0];
265 intrvect_l2 = (int)intspec[1];
266 intrvect_type = (int)intspec[2];
267
268 intrvect_linux =
269 (intrvect_l1 << MPC52xx_IRQ_L1_OFFSET) & MPC52xx_IRQ_L1_MASK;
270 intrvect_linux |=
271 (intrvect_l2 << MPC52xx_IRQ_L2_OFFSET) & MPC52xx_IRQ_L2_MASK;
272
273 pr_debug("return %x, l1=%d, l2=%d\n", intrvect_linux, intrvect_l1,
274 intrvect_l2);
275
276 *out_hwirq = intrvect_linux;
277 *out_flags = mpc52xx_map_senses[intrvect_type];
278
279 return 0;
280}
281
282/*
283 * this function retrieves the correct IRQ type out
284 * of the MPC regs
285 * Only externals IRQs needs this
286*/
287static int mpc52xx_irqx_gettype(int irq)
288{
289 int type;
290 u32 ctrl_reg;
291
292 ctrl_reg = in_be32(&intr->ctrl);
293 type = (ctrl_reg >> (22 - irq * 2)) & 0x3;
294
295 return mpc52xx_map_senses[type];
296}
297
298static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
299 irq_hw_number_t irq)
300{
301 int l1irq;
302 int l2irq;
303 struct irq_chip *good_irqchip;
304 void *good_handle;
305 int type;
306
307 l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
308 l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
309
310 /*
311 * Most of ours IRQs will be level low
312 * Only external IRQs on some platform may be others
313 */
314 type = IRQ_TYPE_LEVEL_LOW;
315
316 switch (l1irq) {
317 case MPC52xx_IRQ_L1_CRIT:
318 pr_debug("%s: Critical. l2=%x\n", __func__, l2irq);
319
320 BUG_ON(l2irq != 0);
321
322 type = mpc52xx_irqx_gettype(l2irq);
323 good_irqchip = &mpc52xx_extirq_irqchip;
324 break;
325
326 case MPC52xx_IRQ_L1_MAIN:
327 pr_debug("%s: Main IRQ[1-3] l2=%x\n", __func__, l2irq);
328
329 if ((l2irq >= 1) && (l2irq <= 3)) {
330 type = mpc52xx_irqx_gettype(l2irq);
331 good_irqchip = &mpc52xx_extirq_irqchip;
332 } else {
333 good_irqchip = &mpc52xx_main_irqchip;
334 }
335 break;
336
337 case MPC52xx_IRQ_L1_PERP:
338 pr_debug("%s: Peripherals. l2=%x\n", __func__, l2irq);
339 good_irqchip = &mpc52xx_periph_irqchip;
340 break;
341
342 case MPC52xx_IRQ_L1_SDMA:
343 pr_debug("%s: SDMA. l2=%x\n", __func__, l2irq);
344 good_irqchip = &mpc52xx_sdma_irqchip;
345 break;
346
347 default:
348 pr_debug("%s: Error, unknown L1 IRQ (0x%x)\n", __func__, l1irq);
349 printk(KERN_ERR "Unknow IRQ!\n");
350 return -EINVAL;
351 }
352
353 switch (type) {
354 case IRQ_TYPE_EDGE_FALLING:
355 case IRQ_TYPE_EDGE_RISING:
356 good_handle = handle_edge_irq;
357 break;
358 default:
359 good_handle = handle_level_irq;
360 }
361
362 set_irq_chip_and_handler(virq, good_irqchip, good_handle);
363
364 pr_debug("%s: virq=%x, hw=%x. type=%x\n", __func__, virq,
365 (int)irq, type);
366
367 return 0;
368}
369
370static struct irq_host_ops mpc52xx_irqhost_ops = {
371 .match = mpc52xx_irqhost_match,
372 .xlate = mpc52xx_irqhost_xlate,
373 .map = mpc52xx_irqhost_map,
374};
375
376/*
377 * init (public)
378*/
379
380void __init mpc52xx_init_irq(void)
381{
382 u32 intr_ctrl;
383 struct device_node *picnode;
384
385 /* Remap the necessary zones */
386 picnode = of_find_compatible_node(NULL, NULL, "mpc52xx-pic");
387
388 intr = mpc52xx_find_and_map("mpc52xx-pic");
389 if (!intr)
390 panic(__FILE__ ": find_and_map failed on 'mpc52xx-pic'. "
391 "Check node !");
392
393 sdma = mpc52xx_find_and_map("mpc52xx-bestcomm");
394 if (!sdma)
395 panic(__FILE__ ": find_and_map failed on 'mpc52xx-bestcomm'. "
396 "Check node !");
397
398 /* Disable all interrupt sources. */
399 out_be32(&sdma->IntPend, 0xffffffff); /* 1 means clear pending */
400 out_be32(&sdma->IntMask, 0xffffffff); /* 1 means disabled */
401 out_be32(&intr->per_mask, 0x7ffffc00); /* 1 means disabled */
402 out_be32(&intr->main_mask, 0x00010fff); /* 1 means disabled */
403 intr_ctrl = in_be32(&intr->ctrl);
404 intr_ctrl &= 0x00ff0000; /* Keeps IRQ[0-3] config */
405 intr_ctrl |= 0x0f000000 | /* clear IRQ 0-3 */
406 0x00001000 | /* MEE master external enable */
407 0x00000000 | /* 0 means disable IRQ 0-3 */
408 0x00000001; /* CEb route critical normally */
409 out_be32(&intr->ctrl, intr_ctrl);
410
411 /* Zero a bunch of the priority settings. */
412 out_be32(&intr->per_pri1, 0);
413 out_be32(&intr->per_pri2, 0);
414 out_be32(&intr->per_pri3, 0);
415 out_be32(&intr->main_pri1, 0);
416 out_be32(&intr->main_pri2, 0);
417
418 /*
419 * As last step, add an irq host to translate the real
420 * hw irq information provided by the ofw to linux virq
421 */
422
423 mpc52xx_irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
424 MPC52xx_IRQ_HIGHTESTHWIRQ,
425 &mpc52xx_irqhost_ops, -1);
426
427 if (!mpc52xx_irqhost)
428 panic(__FILE__ ": Cannot allocate the IRQ host\n");
429
430 mpc52xx_irqhost->host_data = picnode;
431 printk(KERN_INFO "MPC52xx PIC is up and running!\n");
432}
433
434/*
435 * get_irq (public)
436*/
437unsigned int mpc52xx_get_irq(void)
438{
439 u32 status;
440 int irq = NO_IRQ_IGNORE;
441
442 status = in_be32(&intr->enc_status);
443 if (status & 0x00000400) { /* critical */
444 irq = (status >> 8) & 0x3;
445 if (irq == 2) /* high priority peripheral */
446 goto peripheral;
447 irq |= (MPC52xx_IRQ_L1_CRIT << MPC52xx_IRQ_L1_OFFSET) &
448 MPC52xx_IRQ_L1_MASK;
449 } else if (status & 0x00200000) { /* main */
450 irq = (status >> 16) & 0x1f;
451 if (irq == 4) /* low priority peripheral */
452 goto peripheral;
453 irq |= (MPC52xx_IRQ_L1_MAIN << MPC52xx_IRQ_L1_OFFSET) &
454 MPC52xx_IRQ_L1_MASK;
455 } else if (status & 0x20000000) { /* peripheral */
456 peripheral:
457 irq = (status >> 24) & 0x1f;
458 if (irq == 0) { /* bestcomm */
459 status = in_be32(&sdma->IntPend);
460 irq = ffs(status) - 1;
461 irq |= (MPC52xx_IRQ_L1_SDMA << MPC52xx_IRQ_L1_OFFSET) &
462 MPC52xx_IRQ_L1_MASK;
463 } else {
464 irq |= (MPC52xx_IRQ_L1_PERP << MPC52xx_IRQ_L1_OFFSET) &
465 MPC52xx_IRQ_L1_MASK;
466 }
467 }
468
469 pr_debug("%s: irq=%x. virq=%d\n", __func__, irq,
470 irq_linear_revmap(mpc52xx_irqhost, irq));
471
472 return irq_linear_revmap(mpc52xx_irqhost, irq);
473}
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.h b/arch/powerpc/platforms/52xx/mpc52xx_pic.h
new file mode 100644
index 000000000000..1a26bcdb3049
--- /dev/null
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.h
@@ -0,0 +1,53 @@
1/*
2 * Header file for Freescale MPC52xx Interrupt controller
3 *
4 * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com>
5 * Copyright (C) 2003 MontaVista, Software, Inc.
6 *
7 * This file is licensed under the terms of the GNU General Public License
8 * version 2. This program is licensed "as is" without any warranty of any
9 * kind, whether express or implied.
10 */
11
12#ifndef __POWERPC_SYSDEV_MPC52xx_PIC_H__
13#define __POWERPC_SYSDEV_MPC52xx_PIC_H__
14
15#include <asm/types.h>
16
17
18/* HW IRQ mapping */
19#define MPC52xx_IRQ_L1_CRIT (0)
20#define MPC52xx_IRQ_L1_MAIN (1)
21#define MPC52xx_IRQ_L1_PERP (2)
22#define MPC52xx_IRQ_L1_SDMA (3)
23
24#define MPC52xx_IRQ_L1_OFFSET (6)
25#define MPC52xx_IRQ_L1_MASK (0x00c0)
26
27#define MPC52xx_IRQ_L2_OFFSET (0)
28#define MPC52xx_IRQ_L2_MASK (0x003f)
29
30#define MPC52xx_IRQ_HIGHTESTHWIRQ (0xd0)
31
32
33/* Interrupt controller Register set */
34struct mpc52xx_intr {
35 u32 per_mask; /* INTR + 0x00 */
36 u32 per_pri1; /* INTR + 0x04 */
37 u32 per_pri2; /* INTR + 0x08 */
38 u32 per_pri3; /* INTR + 0x0c */
39 u32 ctrl; /* INTR + 0x10 */
40 u32 main_mask; /* INTR + 0x14 */
41 u32 main_pri1; /* INTR + 0x18 */
42 u32 main_pri2; /* INTR + 0x1c */
43 u32 reserved1; /* INTR + 0x20 */
44 u32 enc_status; /* INTR + 0x24 */
45 u32 crit_status; /* INTR + 0x28 */
46 u32 main_status; /* INTR + 0x2c */
47 u32 per_status; /* INTR + 0x30 */
48 u32 reserved2; /* INTR + 0x34 */
49 u32 per_error; /* INTR + 0x38 */
50};
51
52#endif /* __POWERPC_SYSDEV_MPC52xx_PIC_H__ */
53
diff --git a/arch/powerpc/platforms/82xx/mpc82xx_ads.c b/arch/powerpc/platforms/82xx/mpc82xx_ads.c
index bb9acbb98176..ea880f1f0dcd 100644
--- a/arch/powerpc/platforms/82xx/mpc82xx_ads.c
+++ b/arch/powerpc/platforms/82xx/mpc82xx_ads.c
@@ -515,16 +515,6 @@ static int m82xx_pci_exclude_device(u_char bus, u_char devfn)
515 return PCIBIOS_SUCCESSFUL; 515 return PCIBIOS_SUCCESSFUL;
516} 516}
517 517
518static void
519__init mpc82xx_pcibios_fixup(void)
520{
521 struct pci_dev *dev = NULL;
522
523 for_each_pci_dev(dev) {
524 pci_read_irq_line(dev);
525 }
526}
527
528void __init add_bridge(struct device_node *np) 518void __init add_bridge(struct device_node *np)
529{ 519{
530 int len; 520 int len;
@@ -597,9 +587,6 @@ static void __init mpc82xx_ads_setup_arch(void)
597 add_bridge(np); 587 add_bridge(np);
598 588
599 of_node_put(np); 589 of_node_put(np);
600 ppc_md.pci_map_irq = NULL;
601 ppc_md.pcibios_fixup = mpc82xx_pcibios_fixup;
602 ppc_md.pcibios_fixup_bus = NULL;
603#endif 590#endif
604 591
605#ifdef CONFIG_ROOT_NFS 592#ifdef CONFIG_ROOT_NFS
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index a43ac71ab740..f58c9780b66f 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -97,8 +97,6 @@ static void __init mpc832x_sys_setup_arch(void)
97#ifdef CONFIG_PCI 97#ifdef CONFIG_PCI
98 for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) 98 for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
99 add_bridge(np); 99 add_bridge(np);
100
101 ppc_md.pci_swizzle = common_swizzle;
102 ppc_md.pci_exclude_device = mpc83xx_exclude_device; 100 ppc_md.pci_exclude_device = mpc83xx_exclude_device;
103#endif 101#endif
104 102
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index e2bcaaf6b329..314c42ac6048 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -118,7 +118,4 @@ define_machine(mpc834x_itx) {
118 .time_init = mpc83xx_time_init, 118 .time_init = mpc83xx_time_init,
119 .calibrate_decr = generic_calibrate_decr, 119 .calibrate_decr = generic_calibrate_decr,
120 .progress = udbg_progress, 120 .progress = udbg_progress,
121#ifdef CONFIG_PCI
122 .pcibios_fixup = mpc83xx_pcibios_fixup,
123#endif
124}; 121};
diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.c b/arch/powerpc/platforms/83xx/mpc834x_sys.c
index 677196187a4e..80b735a414d9 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_sys.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_sys.c
@@ -137,7 +137,4 @@ define_machine(mpc834x_sys) {
137 .time_init = mpc83xx_time_init, 137 .time_init = mpc83xx_time_init,
138 .calibrate_decr = generic_calibrate_decr, 138 .calibrate_decr = generic_calibrate_decr,
139 .progress = udbg_progress, 139 .progress = udbg_progress,
140#ifdef CONFIG_PCI
141 .pcibios_fixup = mpc83xx_pcibios_fixup,
142#endif
143}; 140};
diff --git a/arch/powerpc/platforms/83xx/mpc8360e_pb.c b/arch/powerpc/platforms/83xx/mpc8360e_pb.c
index 1a523c81c06e..7bfd47ad7233 100644
--- a/arch/powerpc/platforms/83xx/mpc8360e_pb.c
+++ b/arch/powerpc/platforms/83xx/mpc8360e_pb.c
@@ -102,8 +102,6 @@ static void __init mpc8360_sys_setup_arch(void)
102#ifdef CONFIG_PCI 102#ifdef CONFIG_PCI
103 for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) 103 for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
104 add_bridge(np); 104 add_bridge(np);
105
106 ppc_md.pci_swizzle = common_swizzle;
107 ppc_md.pci_exclude_device = mpc83xx_exclude_device; 105 ppc_md.pci_exclude_device = mpc83xx_exclude_device;
108#endif 106#endif
109 107
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h
index 2c82bca9bfbb..01cae106912b 100644
--- a/arch/powerpc/platforms/83xx/mpc83xx.h
+++ b/arch/powerpc/platforms/83xx/mpc83xx.h
@@ -11,7 +11,6 @@
11 11
12extern int add_bridge(struct device_node *dev); 12extern int add_bridge(struct device_node *dev);
13extern int mpc83xx_exclude_device(u_char bus, u_char devfn); 13extern int mpc83xx_exclude_device(u_char bus, u_char devfn);
14extern void mpc83xx_pcibios_fixup(void);
15extern void mpc83xx_restart(char *cmd); 14extern void mpc83xx_restart(char *cmd);
16extern long mpc83xx_time_init(void); 15extern long mpc83xx_time_init(void);
17 16
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c
index 4557ac5255c1..9c3650555144 100644
--- a/arch/powerpc/platforms/83xx/pci.c
+++ b/arch/powerpc/platforms/83xx/pci.c
@@ -45,15 +45,6 @@ int mpc83xx_exclude_device(u_char bus, u_char devfn)
45 return PCIBIOS_SUCCESSFUL; 45 return PCIBIOS_SUCCESSFUL;
46} 46}
47 47
48void __init mpc83xx_pcibios_fixup(void)
49{
50 struct pci_dev *dev = NULL;
51
52 /* map all the PCI irqs */
53 for_each_pci_dev(dev)
54 pci_read_irq_line(dev);
55}
56
57int __init add_bridge(struct device_node *dev) 48int __init add_bridge(struct device_node *dev)
58{ 49{
59 int len; 50 int len;
diff --git a/arch/powerpc/platforms/85xx/misc.c b/arch/powerpc/platforms/85xx/misc.c
index 26c5e822c7c8..3e62fcb04c1c 100644
--- a/arch/powerpc/platforms/85xx/misc.c
+++ b/arch/powerpc/platforms/85xx/misc.c
@@ -21,11 +21,3 @@ void mpc85xx_restart(char *cmd)
21 local_irq_disable(); 21 local_irq_disable();
22 abort(); 22 abort();
23} 23}
24
25/* For now this is a pass through */
26phys_addr_t fixup_bigphys_addr(phys_addr_t addr, phys_addr_t size)
27{
28 return addr;
29};
30
31EXPORT_SYMBOL(fixup_bigphys_addr);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index d3e669d69c73..bda2e55e6c4c 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -53,15 +53,6 @@ mpc85xx_exclude_device(u_char bus, u_char devfn)
53 else 53 else
54 return PCIBIOS_SUCCESSFUL; 54 return PCIBIOS_SUCCESSFUL;
55} 55}
56
57void __init
58mpc85xx_pcibios_fixup(void)
59{
60 struct pci_dev *dev = NULL;
61
62 for_each_pci_dev(dev)
63 pci_read_irq_line(dev);
64}
65#endif /* CONFIG_PCI */ 56#endif /* CONFIG_PCI */
66 57
67#ifdef CONFIG_CPM2 58#ifdef CONFIG_CPM2
@@ -253,8 +244,6 @@ static void __init mpc85xx_ads_setup_arch(void)
253#ifdef CONFIG_PCI 244#ifdef CONFIG_PCI
254 for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) 245 for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
255 add_bridge(np); 246 add_bridge(np);
256
257 ppc_md.pcibios_fixup = mpc85xx_pcibios_fixup;
258 ppc_md.pci_exclude_device = mpc85xx_exclude_device; 247 ppc_md.pci_exclude_device = mpc85xx_exclude_device;
259#endif 248#endif
260 249
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 1a1c226ad4d9..f4dd5f2f8a28 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -398,15 +398,6 @@ mpc86xx_hpcn_show_cpuinfo(struct seq_file *m)
398} 398}
399 399
400 400
401void __init mpc86xx_hpcn_pcibios_fixup(void)
402{
403 struct pci_dev *dev = NULL;
404
405 for_each_pci_dev(dev)
406 pci_read_irq_line(dev);
407}
408
409
410/* 401/*
411 * Called very early, device-tree isn't unflattened 402 * Called very early, device-tree isn't unflattened
412 */ 403 */
@@ -461,7 +452,6 @@ define_machine(mpc86xx_hpcn) {
461 .setup_arch = mpc86xx_hpcn_setup_arch, 452 .setup_arch = mpc86xx_hpcn_setup_arch,
462 .init_IRQ = mpc86xx_hpcn_init_irq, 453 .init_IRQ = mpc86xx_hpcn_init_irq,
463 .show_cpuinfo = mpc86xx_hpcn_show_cpuinfo, 454 .show_cpuinfo = mpc86xx_hpcn_show_cpuinfo,
464 .pcibios_fixup = mpc86xx_hpcn_pcibios_fixup,
465 .get_irq = mpic_get_irq, 455 .get_irq = mpic_get_irq,
466 .restart = mpc86xx_restart, 456 .restart = mpc86xx_restart,
467 .time_init = mpc86xx_time_init, 457 .time_init = mpc86xx_time_init,
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index e58fa953a50b..44d95eaf22e6 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -7,12 +7,14 @@ endif
7endif 7endif
8obj-$(CONFIG_PPC_CHRP) += chrp/ 8obj-$(CONFIG_PPC_CHRP) += chrp/
9obj-$(CONFIG_4xx) += 4xx/ 9obj-$(CONFIG_4xx) += 4xx/
10obj-$(CONFIG_PPC_MPC52xx) += 52xx/
10obj-$(CONFIG_PPC_83xx) += 83xx/ 11obj-$(CONFIG_PPC_83xx) += 83xx/
11obj-$(CONFIG_PPC_85xx) += 85xx/ 12obj-$(CONFIG_PPC_85xx) += 85xx/
12obj-$(CONFIG_PPC_86xx) += 86xx/ 13obj-$(CONFIG_PPC_86xx) += 86xx/
13obj-$(CONFIG_PPC_PSERIES) += pseries/ 14obj-$(CONFIG_PPC_PSERIES) += pseries/
14obj-$(CONFIG_PPC_ISERIES) += iseries/ 15obj-$(CONFIG_PPC_ISERIES) += iseries/
15obj-$(CONFIG_PPC_MAPLE) += maple/ 16obj-$(CONFIG_PPC_MAPLE) += maple/
16obj-$(CONFIG_PPC_PASEMI) += pasemi/ 17obj-$(CONFIG_PPC_PASEMI) += pasemi/
17obj-$(CONFIG_PPC_CELL) += cell/ 18obj-$(CONFIG_PPC_CELL) += cell/
19obj-$(CONFIG_PPC_PS3) += ps3/
18obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/ 20obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 3e430b489bb7..06a85b704331 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -20,4 +20,18 @@ config CBE_RAS
20 bool "RAS features for bare metal Cell BE" 20 bool "RAS features for bare metal Cell BE"
21 default y 21 default y
22 22
23config CBE_THERM
24 tristate "CBE thermal support"
25 default m
26 depends on CBE_RAS
27
28config CBE_CPUFREQ
29 tristate "CBE frequency scaling"
30 depends on CBE_RAS && CPU_FREQ
31 default m
32 help
33 This adds the cpufreq driver for Cell BE processors.
34 For details, take a look at <file:Documentation/cpu-freq/>.
35 If you don't have such processor, say N
36
23endmenu 37endmenu
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index c89cdd67383b..f90e8337796c 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -1,7 +1,11 @@
1obj-$(CONFIG_PPC_CELL_NATIVE) += interrupt.o iommu.o setup.o \ 1obj-$(CONFIG_PPC_CELL_NATIVE) += interrupt.o iommu.o setup.o \
2 cbe_regs.o spider-pic.o pervasive.o 2 cbe_regs.o spider-pic.o \
3 pervasive.o pmu.o io-workarounds.o
3obj-$(CONFIG_CBE_RAS) += ras.o 4obj-$(CONFIG_CBE_RAS) += ras.o
4 5
6obj-$(CONFIG_CBE_THERM) += cbe_thermal.o
7obj-$(CONFIG_CBE_CPUFREQ) += cbe_cpufreq.o
8
5ifeq ($(CONFIG_SMP),y) 9ifeq ($(CONFIG_SMP),y)
6obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o 10obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o
7endif 11endif
@@ -11,5 +15,6 @@ spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o
11spu-priv1-$(CONFIG_PPC_CELL_NATIVE) += spu_priv1_mmio.o 15spu-priv1-$(CONFIG_PPC_CELL_NATIVE) += spu_priv1_mmio.o
12 16
13obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \ 17obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \
18 spu_coredump.o \
14 $(spufs-modular-m) \ 19 $(spufs-modular-m) \
15 $(spu-priv1-y) spufs/ 20 $(spu-priv1-y) spufs/
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c
new file mode 100644
index 000000000000..a3850fd1e94c
--- /dev/null
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c
@@ -0,0 +1,248 @@
1/*
2 * cpufreq driver for the cell processor
3 *
4 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
5 *
6 * Author: Christian Krafft <krafft@de.ibm.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <linux/cpufreq.h>
24#include <linux/timer.h>
25
26#include <asm/hw_irq.h>
27#include <asm/io.h>
28#include <asm/processor.h>
29#include <asm/prom.h>
30#include <asm/time.h>
31
32#include "cbe_regs.h"
33
34static DEFINE_MUTEX(cbe_switch_mutex);
35
36
37/* the CBE supports an 8 step frequency scaling */
38static struct cpufreq_frequency_table cbe_freqs[] = {
39 {1, 0},
40 {2, 0},
41 {3, 0},
42 {4, 0},
43 {5, 0},
44 {6, 0},
45 {8, 0},
46 {10, 0},
47 {0, CPUFREQ_TABLE_END},
48};
49
50/* to write to MIC register */
51static u64 MIC_Slow_Fast_Timer_table[] = {
52 [0 ... 7] = 0x007fc00000000000ull,
53};
54
55/* more values for the MIC */
56static u64 MIC_Slow_Next_Timer_table[] = {
57 0x0000240000000000ull,
58 0x0000268000000000ull,
59 0x000029C000000000ull,
60 0x00002D0000000000ull,
61 0x0000300000000000ull,
62 0x0000334000000000ull,
63 0x000039C000000000ull,
64 0x00003FC000000000ull,
65};
66
67/*
68 * hardware specific functions
69 */
70
71static int get_pmode(int cpu)
72{
73 int ret;
74 struct cbe_pmd_regs __iomem *pmd_regs;
75
76 pmd_regs = cbe_get_cpu_pmd_regs(cpu);
77 ret = in_be64(&pmd_regs->pmsr) & 0x07;
78
79 return ret;
80}
81
82static int set_pmode(int cpu, unsigned int pmode)
83{
84 struct cbe_pmd_regs __iomem *pmd_regs;
85 struct cbe_mic_tm_regs __iomem *mic_tm_regs;
86 u64 flags;
87 u64 value;
88
89 local_irq_save(flags);
90
91 mic_tm_regs = cbe_get_cpu_mic_tm_regs(cpu);
92 pmd_regs = cbe_get_cpu_pmd_regs(cpu);
93
94 pr_debug("pm register is mapped at %p\n", &pmd_regs->pmcr);
95 pr_debug("mic register is mapped at %p\n", &mic_tm_regs->slow_fast_timer_0);
96
97 out_be64(&mic_tm_regs->slow_fast_timer_0, MIC_Slow_Fast_Timer_table[pmode]);
98 out_be64(&mic_tm_regs->slow_fast_timer_1, MIC_Slow_Fast_Timer_table[pmode]);
99
100 out_be64(&mic_tm_regs->slow_next_timer_0, MIC_Slow_Next_Timer_table[pmode]);
101 out_be64(&mic_tm_regs->slow_next_timer_1, MIC_Slow_Next_Timer_table[pmode]);
102
103 value = in_be64(&pmd_regs->pmcr);
104 /* set bits to zero */
105 value &= 0xFFFFFFFFFFFFFFF8ull;
106 /* set bits to next pmode */
107 value |= pmode;
108
109 out_be64(&pmd_regs->pmcr, value);
110
111 /* wait until new pmode appears in status register */
112 value = in_be64(&pmd_regs->pmsr) & 0x07;
113 while(value != pmode) {
114 cpu_relax();
115 value = in_be64(&pmd_regs->pmsr) & 0x07;
116 }
117
118 local_irq_restore(flags);
119
120 return 0;
121}
122
123/*
124 * cpufreq functions
125 */
126
127static int cbe_cpufreq_cpu_init (struct cpufreq_policy *policy)
128{
129 u32 *max_freq;
130 int i, cur_pmode;
131 struct device_node *cpu;
132
133 cpu = of_get_cpu_node(policy->cpu, NULL);
134
135 if(!cpu)
136 return -ENODEV;
137
138 pr_debug("init cpufreq on CPU %d\n", policy->cpu);
139
140 max_freq = (u32*) get_property(cpu, "clock-frequency", NULL);
141
142 if(!max_freq)
143 return -EINVAL;
144
145 // we need the freq in kHz
146 *max_freq /= 1000;
147
148 pr_debug("max clock-frequency is at %u kHz\n", *max_freq);
149 pr_debug("initializing frequency table\n");
150
151 // initialize frequency table
152 for (i=0; cbe_freqs[i].frequency!=CPUFREQ_TABLE_END; i++) {
153 cbe_freqs[i].frequency = *max_freq / cbe_freqs[i].index;
154 pr_debug("%d: %d\n", i, cbe_freqs[i].frequency);
155 }
156
157 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
158 /* if DEBUG is enabled set_pmode() measures the correct latency of a transition */
159 policy->cpuinfo.transition_latency = 25000;
160
161 cur_pmode = get_pmode(policy->cpu);
162 pr_debug("current pmode is at %d\n",cur_pmode);
163
164 policy->cur = cbe_freqs[cur_pmode].frequency;
165
166#ifdef CONFIG_SMP
167 policy->cpus = cpu_sibling_map[policy->cpu];
168#endif
169
170 cpufreq_frequency_table_get_attr (cbe_freqs, policy->cpu);
171
172 /* this ensures that policy->cpuinfo_min and policy->cpuinfo_max are set correctly */
173 return cpufreq_frequency_table_cpuinfo (policy, cbe_freqs);
174}
175
176static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy)
177{
178 cpufreq_frequency_table_put_attr(policy->cpu);
179 return 0;
180}
181
182static int cbe_cpufreq_verify(struct cpufreq_policy *policy)
183{
184 return cpufreq_frequency_table_verify(policy, cbe_freqs);
185}
186
187
188static int cbe_cpufreq_target(struct cpufreq_policy *policy, unsigned int target_freq,
189 unsigned int relation)
190{
191 int rc;
192 struct cpufreq_freqs freqs;
193 int cbe_pmode_new;
194
195 cpufreq_frequency_table_target(policy,
196 cbe_freqs,
197 target_freq,
198 relation,
199 &cbe_pmode_new);
200
201 freqs.old = policy->cur;
202 freqs.new = cbe_freqs[cbe_pmode_new].frequency;
203 freqs.cpu = policy->cpu;
204
205 mutex_lock (&cbe_switch_mutex);
206 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
207
208 pr_debug("setting frequency for cpu %d to %d kHz, 1/%d of max frequency\n",
209 policy->cpu,
210 cbe_freqs[cbe_pmode_new].frequency,
211 cbe_freqs[cbe_pmode_new].index);
212
213 rc = set_pmode(policy->cpu, cbe_pmode_new);
214 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
215 mutex_unlock(&cbe_switch_mutex);
216
217 return rc;
218}
219
220static struct cpufreq_driver cbe_cpufreq_driver = {
221 .verify = cbe_cpufreq_verify,
222 .target = cbe_cpufreq_target,
223 .init = cbe_cpufreq_cpu_init,
224 .exit = cbe_cpufreq_cpu_exit,
225 .name = "cbe-cpufreq",
226 .owner = THIS_MODULE,
227 .flags = CPUFREQ_CONST_LOOPS,
228};
229
230/*
231 * module init and destoy
232 */
233
234static int __init cbe_cpufreq_init(void)
235{
236 return cpufreq_register_driver(&cbe_cpufreq_driver);
237}
238
239static void __exit cbe_cpufreq_exit(void)
240{
241 cpufreq_unregister_driver(&cbe_cpufreq_driver);
242}
243
244module_init(cbe_cpufreq_init);
245module_exit(cbe_cpufreq_exit);
246
247MODULE_LICENSE("GPL");
248MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");
diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c
index 2f194ba29899..9a0ee62691d5 100644
--- a/arch/powerpc/platforms/cell/cbe_regs.c
+++ b/arch/powerpc/platforms/cell/cbe_regs.c
@@ -8,6 +8,7 @@
8 8
9#include <linux/percpu.h> 9#include <linux/percpu.h>
10#include <linux/types.h> 10#include <linux/types.h>
11#include <linux/module.h>
11 12
12#include <asm/io.h> 13#include <asm/io.h>
13#include <asm/pgtable.h> 14#include <asm/pgtable.h>
@@ -16,8 +17,6 @@
16 17
17#include "cbe_regs.h" 18#include "cbe_regs.h"
18 19
19#define MAX_CBE 2
20
21/* 20/*
22 * Current implementation uses "cpu" nodes. We build our own mapping 21 * Current implementation uses "cpu" nodes. We build our own mapping
23 * array of cpu numbers to cpu nodes locally for now to allow interrupt 22 * array of cpu numbers to cpu nodes locally for now to allow interrupt
@@ -30,6 +29,8 @@ static struct cbe_regs_map
30 struct device_node *cpu_node; 29 struct device_node *cpu_node;
31 struct cbe_pmd_regs __iomem *pmd_regs; 30 struct cbe_pmd_regs __iomem *pmd_regs;
32 struct cbe_iic_regs __iomem *iic_regs; 31 struct cbe_iic_regs __iomem *iic_regs;
32 struct cbe_mic_tm_regs __iomem *mic_tm_regs;
33 struct cbe_pmd_shadow_regs pmd_shadow_regs;
33} cbe_regs_maps[MAX_CBE]; 34} cbe_regs_maps[MAX_CBE];
34static int cbe_regs_map_count; 35static int cbe_regs_map_count;
35 36
@@ -42,6 +43,19 @@ static struct cbe_thread_map
42static struct cbe_regs_map *cbe_find_map(struct device_node *np) 43static struct cbe_regs_map *cbe_find_map(struct device_node *np)
43{ 44{
44 int i; 45 int i;
46 struct device_node *tmp_np;
47
48 if (strcasecmp(np->type, "spe") == 0) {
49 if (np->data == NULL) {
50 /* walk up path until cpu node was found */
51 tmp_np = np->parent;
52 while (tmp_np != NULL && strcasecmp(tmp_np->type, "cpu") != 0)
53 tmp_np = tmp_np->parent;
54
55 np->data = cbe_find_map(tmp_np);
56 }
57 return np->data;
58 }
45 59
46 for (i = 0; i < cbe_regs_map_count; i++) 60 for (i = 0; i < cbe_regs_map_count; i++)
47 if (cbe_regs_maps[i].cpu_node == np) 61 if (cbe_regs_maps[i].cpu_node == np)
@@ -56,6 +70,7 @@ struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np)
56 return NULL; 70 return NULL;
57 return map->pmd_regs; 71 return map->pmd_regs;
58} 72}
73EXPORT_SYMBOL_GPL(cbe_get_pmd_regs);
59 74
60struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu) 75struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu)
61{ 76{
@@ -64,7 +79,23 @@ struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu)
64 return NULL; 79 return NULL;
65 return map->pmd_regs; 80 return map->pmd_regs;
66} 81}
82EXPORT_SYMBOL_GPL(cbe_get_cpu_pmd_regs);
67 83
84struct cbe_pmd_shadow_regs *cbe_get_pmd_shadow_regs(struct device_node *np)
85{
86 struct cbe_regs_map *map = cbe_find_map(np);
87 if (map == NULL)
88 return NULL;
89 return &map->pmd_shadow_regs;
90}
91
92struct cbe_pmd_shadow_regs *cbe_get_cpu_pmd_shadow_regs(int cpu)
93{
94 struct cbe_regs_map *map = cbe_thread_map[cpu].regs;
95 if (map == NULL)
96 return NULL;
97 return &map->pmd_shadow_regs;
98}
68 99
69struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np) 100struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np)
70{ 101{
@@ -73,6 +104,7 @@ struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np)
73 return NULL; 104 return NULL;
74 return map->iic_regs; 105 return map->iic_regs;
75} 106}
107
76struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu) 108struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu)
77{ 109{
78 struct cbe_regs_map *map = cbe_thread_map[cpu].regs; 110 struct cbe_regs_map *map = cbe_thread_map[cpu].regs;
@@ -81,6 +113,36 @@ struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu)
81 return map->iic_regs; 113 return map->iic_regs;
82} 114}
83 115
116struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np)
117{
118 struct cbe_regs_map *map = cbe_find_map(np);
119 if (map == NULL)
120 return NULL;
121 return map->mic_tm_regs;
122}
123
124struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu)
125{
126 struct cbe_regs_map *map = cbe_thread_map[cpu].regs;
127 if (map == NULL)
128 return NULL;
129 return map->mic_tm_regs;
130}
131EXPORT_SYMBOL_GPL(cbe_get_cpu_mic_tm_regs);
132
133/* FIXME
134 * This is little more than a stub at the moment. It should be
135 * fleshed out so that it works for both SMT and non-SMT, no
136 * matter if the passed cpu is odd or even.
137 * For SMT enabled, returns 0 for even-numbered cpu; otherwise 1.
138 * For SMT disabled, returns 0 for all cpus.
139 */
140u32 cbe_get_hw_thread_id(int cpu)
141{
142 return (cpu & 1);
143}
144EXPORT_SYMBOL_GPL(cbe_get_hw_thread_id);
145
84void __init cbe_regs_init(void) 146void __init cbe_regs_init(void)
85{ 147{
86 int i; 148 int i;
@@ -119,6 +181,11 @@ void __init cbe_regs_init(void)
119 prop = get_property(cpu, "iic", NULL); 181 prop = get_property(cpu, "iic", NULL);
120 if (prop != NULL) 182 if (prop != NULL)
121 map->iic_regs = ioremap(prop->address, prop->len); 183 map->iic_regs = ioremap(prop->address, prop->len);
184
185 prop = (struct address_prop *)get_property(cpu, "mic-tm",
186 NULL);
187 if (prop != NULL)
188 map->mic_tm_regs = ioremap(prop->address, prop->len);
122 } 189 }
123} 190}
124 191
diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h
index e76e4a6af5bc..440a7ecc66ea 100644
--- a/arch/powerpc/platforms/cell/cbe_regs.h
+++ b/arch/powerpc/platforms/cell/cbe_regs.h
@@ -4,12 +4,19 @@
4 * This file is intended to hold the various register definitions for CBE 4 * This file is intended to hold the various register definitions for CBE
5 * on-chip system devices (memory controller, IO controller, etc...) 5 * on-chip system devices (memory controller, IO controller, etc...)
6 * 6 *
7 * (C) Copyright IBM Corporation 2001,2006
8 *
9 * Authors: Maximino Aguilar (maguilar@us.ibm.com)
10 * David J. Erb (djerb@us.ibm.com)
11 *
7 * (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp. 12 * (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
8 */ 13 */
9 14
10#ifndef CBE_REGS_H 15#ifndef CBE_REGS_H
11#define CBE_REGS_H 16#define CBE_REGS_H
12 17
18#include <asm/cell-pmu.h>
19
13/* 20/*
14 * 21 *
15 * Some HID register definitions 22 * Some HID register definitions
@@ -22,6 +29,7 @@
22#define HID0_CBE_THERM_INT_EN 0x0000000400000000ul 29#define HID0_CBE_THERM_INT_EN 0x0000000400000000ul
23#define HID0_CBE_SYSERR_INT_EN 0x0000000200000000ul 30#define HID0_CBE_SYSERR_INT_EN 0x0000000200000000ul
24 31
32#define MAX_CBE 2
25 33
26/* 34/*
27 * 35 *
@@ -29,51 +37,124 @@
29 * 37 *
30 */ 38 */
31 39
40union spe_reg {
41 u64 val;
42 u8 spe[8];
43};
44
45union ppe_spe_reg {
46 u64 val;
47 struct {
48 u32 ppe;
49 u32 spe;
50 };
51};
52
53
32struct cbe_pmd_regs { 54struct cbe_pmd_regs {
33 u8 pad_0x0000_0x0800[0x0800 - 0x0000]; /* 0x0000 */ 55 /* Debug Bus Control */
56 u64 pad_0x0000; /* 0x0000 */
57
58 u64 group_control; /* 0x0008 */
59
60 u8 pad_0x0010_0x00a8 [0x00a8 - 0x0010]; /* 0x0010 */
61
62 u64 debug_bus_control; /* 0x00a8 */
63
64 u8 pad_0x00b0_0x0100 [0x0100 - 0x00b0]; /* 0x00b0 */
65
66 u64 trace_aux_data; /* 0x0100 */
67 u64 trace_buffer_0_63; /* 0x0108 */
68 u64 trace_buffer_64_127; /* 0x0110 */
69 u64 trace_address; /* 0x0118 */
70 u64 ext_tr_timer; /* 0x0120 */
71
72 u8 pad_0x0128_0x0400 [0x0400 - 0x0128]; /* 0x0128 */
73
74 /* Performance Monitor */
75 u64 pm_status; /* 0x0400 */
76 u64 pm_control; /* 0x0408 */
77 u64 pm_interval; /* 0x0410 */
78 u64 pm_ctr[4]; /* 0x0418 */
79 u64 pm_start_stop; /* 0x0438 */
80 u64 pm07_control[8]; /* 0x0440 */
81
82 u8 pad_0x0480_0x0800 [0x0800 - 0x0480]; /* 0x0480 */
34 83
35 /* Thermal Sensor Registers */ 84 /* Thermal Sensor Registers */
36 u64 ts_ctsr1; /* 0x0800 */ 85 union spe_reg ts_ctsr1; /* 0x0800 */
37 u64 ts_ctsr2; /* 0x0808 */ 86 u64 ts_ctsr2; /* 0x0808 */
38 u64 ts_mtsr1; /* 0x0810 */ 87 union spe_reg ts_mtsr1; /* 0x0810 */
39 u64 ts_mtsr2; /* 0x0818 */ 88 u64 ts_mtsr2; /* 0x0818 */
40 u64 ts_itr1; /* 0x0820 */ 89 union spe_reg ts_itr1; /* 0x0820 */
41 u64 ts_itr2; /* 0x0828 */ 90 u64 ts_itr2; /* 0x0828 */
42 u64 ts_gitr; /* 0x0830 */ 91 u64 ts_gitr; /* 0x0830 */
43 u64 ts_isr; /* 0x0838 */ 92 u64 ts_isr; /* 0x0838 */
44 u64 ts_imr; /* 0x0840 */ 93 u64 ts_imr; /* 0x0840 */
45 u64 tm_cr1; /* 0x0848 */ 94 union spe_reg tm_cr1; /* 0x0848 */
46 u64 tm_cr2; /* 0x0850 */ 95 u64 tm_cr2; /* 0x0850 */
47 u64 tm_simr; /* 0x0858 */ 96 u64 tm_simr; /* 0x0858 */
48 u64 tm_tpr; /* 0x0860 */ 97 union ppe_spe_reg tm_tpr; /* 0x0860 */
49 u64 tm_str1; /* 0x0868 */ 98 union spe_reg tm_str1; /* 0x0868 */
50 u64 tm_str2; /* 0x0870 */ 99 u64 tm_str2; /* 0x0870 */
51 u64 tm_tsr; /* 0x0878 */ 100 union ppe_spe_reg tm_tsr; /* 0x0878 */
52 101
53 /* Power Management */ 102 /* Power Management */
54 u64 pm_control; /* 0x0880 */ 103 u64 pmcr; /* 0x0880 */
55#define CBE_PMD_PAUSE_ZERO_CONTROL 0x10000 104#define CBE_PMD_PAUSE_ZERO_CONTROL 0x10000
56 u64 pm_status; /* 0x0888 */ 105 u64 pmsr; /* 0x0888 */
57 106
58 /* Time Base Register */ 107 /* Time Base Register */
59 u64 tbr; /* 0x0890 */ 108 u64 tbr; /* 0x0890 */
60 109
61 u8 pad_0x0898_0x0c00 [0x0c00 - 0x0898]; /* 0x0898 */ 110 u8 pad_0x0898_0x0c00 [0x0c00 - 0x0898]; /* 0x0898 */
62 111
63 /* Fault Isolation Registers */ 112 /* Fault Isolation Registers */
64 u64 checkstop_fir; /* 0x0c00 */ 113 u64 checkstop_fir; /* 0x0c00 */
65 u64 recoverable_fir; 114 u64 recoverable_fir; /* 0x0c08 */
66 u64 spec_att_mchk_fir; 115 u64 spec_att_mchk_fir; /* 0x0c10 */
67 u64 fir_mode_reg; 116 u64 fir_mode_reg; /* 0x0c18 */
68 u64 fir_enable_mask; 117 u64 fir_enable_mask; /* 0x0c20 */
69 118
70 u8 pad_0x0c28_0x1000 [0x1000 - 0x0c28]; /* 0x0c28 */ 119 u8 pad_0x0c28_0x1000 [0x1000 - 0x0c28]; /* 0x0c28 */
71}; 120};
72 121
73extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np); 122extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np);
74extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu); 123extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu);
75 124
76/* 125/*
126 * PMU shadow registers
127 *
128 * Many of the registers in the performance monitoring unit are write-only,
129 * so we need to save a copy of what we write to those registers.
130 *
131 * The actual data counters are read/write. However, writing to the counters
132 * only takes effect if the PMU is enabled. Otherwise the value is stored in
133 * a hardware latch until the next time the PMU is enabled. So we save a copy
134 * of the counter values if we need to read them back while the PMU is
135 * disabled. The counter_value_in_latch field is a bitmap indicating which
136 * counters currently have a value waiting to be written.
137 */
138
139struct cbe_pmd_shadow_regs {
140 u32 group_control;
141 u32 debug_bus_control;
142 u32 trace_address;
143 u32 ext_tr_timer;
144 u32 pm_status;
145 u32 pm_control;
146 u32 pm_interval;
147 u32 pm_start_stop;
148 u32 pm07_control[NR_CTRS];
149
150 u32 pm_ctr[NR_PHYS_CTRS];
151 u32 counter_value_in_latch;
152};
153
154extern struct cbe_pmd_shadow_regs *cbe_get_pmd_shadow_regs(struct device_node *np);
155extern struct cbe_pmd_shadow_regs *cbe_get_cpu_pmd_shadow_regs(int cpu);
156
157/*
77 * 158 *
78 * IIC unit register definitions 159 * IIC unit register definitions
79 * 160 *
@@ -102,18 +183,28 @@ struct cbe_iic_regs {
102 183
103 /* IIC interrupt registers */ 184 /* IIC interrupt registers */
104 struct cbe_iic_thread_regs thread[2]; /* 0x0400 */ 185 struct cbe_iic_thread_regs thread[2]; /* 0x0400 */
105 u64 iic_ir; /* 0x0440 */ 186
106 u64 iic_is; /* 0x0448 */ 187 u64 iic_ir; /* 0x0440 */
188#define CBE_IIC_IR_PRIO(x) (((x) & 0xf) << 12)
189#define CBE_IIC_IR_DEST_NODE(x) (((x) & 0xf) << 4)
190#define CBE_IIC_IR_DEST_UNIT(x) ((x) & 0xf)
191#define CBE_IIC_IR_IOC_0 0x0
192#define CBE_IIC_IR_IOC_1S 0xb
193#define CBE_IIC_IR_PT_0 0xe
194#define CBE_IIC_IR_PT_1 0xf
195
196 u64 iic_is; /* 0x0448 */
197#define CBE_IIC_IS_PMI 0x2
107 198
108 u8 pad_0x0450_0x0500[0x0500 - 0x0450]; /* 0x0450 */ 199 u8 pad_0x0450_0x0500[0x0500 - 0x0450]; /* 0x0450 */
109 200
110 /* IOC FIR */ 201 /* IOC FIR */
111 u64 ioc_fir_reset; /* 0x0500 */ 202 u64 ioc_fir_reset; /* 0x0500 */
112 u64 ioc_fir_set; 203 u64 ioc_fir_set; /* 0x0508 */
113 u64 ioc_checkstop_enable; 204 u64 ioc_checkstop_enable; /* 0x0510 */
114 u64 ioc_fir_error_mask; 205 u64 ioc_fir_error_mask; /* 0x0518 */
115 u64 ioc_syserr_enable; 206 u64 ioc_syserr_enable; /* 0x0520 */
116 u64 ioc_fir; 207 u64 ioc_fir; /* 0x0528 */
117 208
118 u8 pad_0x0530_0x1000[0x1000 - 0x0530]; /* 0x0530 */ 209 u8 pad_0x0530_0x1000[0x1000 - 0x0530]; /* 0x0530 */
119}; 210};
@@ -122,6 +213,48 @@ extern struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np);
122extern struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu); 213extern struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu);
123 214
124 215
216struct cbe_mic_tm_regs {
217 u8 pad_0x0000_0x0040[0x0040 - 0x0000]; /* 0x0000 */
218
219 u64 mic_ctl_cnfg2; /* 0x0040 */
220#define CBE_MIC_ENABLE_AUX_TRC 0x8000000000000000LL
221#define CBE_MIC_DISABLE_PWR_SAV_2 0x0200000000000000LL
222#define CBE_MIC_DISABLE_AUX_TRC_WRAP 0x0100000000000000LL
223#define CBE_MIC_ENABLE_AUX_TRC_INT 0x0080000000000000LL
224
225 u64 pad_0x0048; /* 0x0048 */
226
227 u64 mic_aux_trc_base; /* 0x0050 */
228 u64 mic_aux_trc_max_addr; /* 0x0058 */
229 u64 mic_aux_trc_cur_addr; /* 0x0060 */
230 u64 mic_aux_trc_grf_addr; /* 0x0068 */
231 u64 mic_aux_trc_grf_data; /* 0x0070 */
232
233 u64 pad_0x0078; /* 0x0078 */
234
235 u64 mic_ctl_cnfg_0; /* 0x0080 */
236#define CBE_MIC_DISABLE_PWR_SAV_0 0x8000000000000000LL
237
238 u64 pad_0x0088; /* 0x0088 */
239
240 u64 slow_fast_timer_0; /* 0x0090 */
241 u64 slow_next_timer_0; /* 0x0098 */
242
243 u8 pad_0x00a0_0x01c0[0x01c0 - 0x0a0]; /* 0x00a0 */
244
245 u64 mic_ctl_cnfg_1; /* 0x01c0 */
246#define CBE_MIC_DISABLE_PWR_SAV_1 0x8000000000000000LL
247 u64 pad_0x01c8; /* 0x01c8 */
248
249 u64 slow_fast_timer_1; /* 0x01d0 */
250 u64 slow_next_timer_1; /* 0x01d8 */
251
252 u8 pad_0x01e0_0x1000[0x1000 - 0x01e0]; /* 0x01e0 */
253};
254
255extern struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np);
256extern struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu);
257
125/* Init this module early */ 258/* Init this module early */
126extern void cbe_regs_init(void); 259extern void cbe_regs_init(void);
127 260
diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c
new file mode 100644
index 000000000000..616a0a3fd0e2
--- /dev/null
+++ b/arch/powerpc/platforms/cell/cbe_thermal.c
@@ -0,0 +1,226 @@
1/*
2 * thermal support for the cell processor
3 *
4 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
5 *
6 * Author: Christian Krafft <krafft@de.ibm.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <linux/module.h>
24#include <linux/sysdev.h>
25#include <linux/kernel.h>
26#include <linux/cpu.h>
27#include <asm/spu.h>
28#include <asm/io.h>
29#include <asm/prom.h>
30
31#include "cbe_regs.h"
32#include "spu_priv1_mmio.h"
33
34static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev)
35{
36 struct spu *spu;
37
38 spu = container_of(sysdev, struct spu, sysdev);
39
40 return cbe_get_pmd_regs(spu_devnode(spu));
41}
42
43/* returns the value for a given spu in a given register */
44static u8 spu_read_register_value(struct sys_device *sysdev, union spe_reg __iomem *reg)
45{
46 unsigned int *id;
47 union spe_reg value;
48 struct spu *spu;
49
50 /* getting the id from the reg attribute will not work on future device-tree layouts
51 * in future we should store the id to the spu struct and use it here */
52 spu = container_of(sysdev, struct spu, sysdev);
53 id = (unsigned int *)get_property(spu_devnode(spu), "reg", NULL);
54 value.val = in_be64(&reg->val);
55
56 return value.spe[*id];
57}
58
59static ssize_t spu_show_temp(struct sys_device *sysdev, char *buf)
60{
61 int value;
62 struct cbe_pmd_regs __iomem *pmd_regs;
63
64 pmd_regs = get_pmd_regs(sysdev);
65
66 value = spu_read_register_value(sysdev, &pmd_regs->ts_ctsr1);
67 /* clear all other bits */
68 value &= 0x3F;
69 /* temp is stored in steps of 2 degrees */
70 value *= 2;
71 /* base temp is 65 degrees */
72 value += 65;
73
74 return sprintf(buf, "%d\n", (int) value);
75}
76
77static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos)
78{
79 struct cbe_pmd_regs __iomem *pmd_regs;
80 u64 value;
81
82 pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id);
83 value = in_be64(&pmd_regs->ts_ctsr2);
84
85 /* access the corresponding byte */
86 value >>= pos;
87 /* clear all other bits */
88 value &= 0x3F;
89 /* temp is stored in steps of 2 degrees */
90 value *= 2;
91 /* base temp is 65 degrees */
92 value += 65;
93
94 return sprintf(buf, "%d\n", (int) value);
95}
96
97
98/* shows the temperature of the DTS on the PPE,
99 * located near the linear thermal sensor */
100static ssize_t ppe_show_temp0(struct sys_device *sysdev, char *buf)
101{
102 return ppe_show_temp(sysdev, buf, 32);
103}
104
105/* shows the temperature of the second DTS on the PPE */
106static ssize_t ppe_show_temp1(struct sys_device *sysdev, char *buf)
107{
108 return ppe_show_temp(sysdev, buf, 0);
109}
110
111static struct sysdev_attribute attr_spu_temperature = {
112 .attr = {.name = "temperature", .mode = 0400 },
113 .show = spu_show_temp,
114};
115
116static struct attribute *spu_attributes[] = {
117 &attr_spu_temperature.attr,
118};
119
120static struct attribute_group spu_attribute_group = {
121 .name = "thermal",
122 .attrs = spu_attributes,
123};
124
125static struct sysdev_attribute attr_ppe_temperature0 = {
126 .attr = {.name = "temperature0", .mode = 0400 },
127 .show = ppe_show_temp0,
128};
129
130static struct sysdev_attribute attr_ppe_temperature1 = {
131 .attr = {.name = "temperature1", .mode = 0400 },
132 .show = ppe_show_temp1,
133};
134
135static struct attribute *ppe_attributes[] = {
136 &attr_ppe_temperature0.attr,
137 &attr_ppe_temperature1.attr,
138};
139
140static struct attribute_group ppe_attribute_group = {
141 .name = "thermal",
142 .attrs = ppe_attributes,
143};
144
145/*
146 * initialize throttling with default values
147 */
148static void __init init_default_values(void)
149{
150 int cpu;
151 struct cbe_pmd_regs __iomem *pmd_regs;
152 struct sys_device *sysdev;
153 union ppe_spe_reg tpr;
154 union spe_reg str1;
155 u64 str2;
156 union spe_reg cr1;
157 u64 cr2;
158
159 /* TPR defaults */
160 /* ppe
161 * 1F - no full stop
162 * 08 - dynamic throttling starts if over 80 degrees
163 * 03 - dynamic throttling ceases if below 70 degrees */
164 tpr.ppe = 0x1F0803;
165 /* spe
166 * 10 - full stopped when over 96 degrees
167 * 08 - dynamic throttling starts if over 80 degrees
168 * 03 - dynamic throttling ceases if below 70 degrees
169 */
170 tpr.spe = 0x100803;
171
172 /* STR defaults */
173 /* str1
174 * 10 - stop 16 of 32 cycles
175 */
176 str1.val = 0x1010101010101010ull;
177 /* str2
178 * 10 - stop 16 of 32 cycles
179 */
180 str2 = 0x10;
181
182 /* CR defaults */
183 /* cr1
184 * 4 - normal operation
185 */
186 cr1.val = 0x0404040404040404ull;
187 /* cr2
188 * 4 - normal operation
189 */
190 cr2 = 0x04;
191
192 for_each_possible_cpu (cpu) {
193 pr_debug("processing cpu %d\n", cpu);
194 sysdev = get_cpu_sysdev(cpu);
195 pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id);
196
197 out_be64(&pmd_regs->tm_str2, str2);
198 out_be64(&pmd_regs->tm_str1.val, str1.val);
199 out_be64(&pmd_regs->tm_tpr.val, tpr.val);
200 out_be64(&pmd_regs->tm_cr1.val, cr1.val);
201 out_be64(&pmd_regs->tm_cr2, cr2);
202 }
203}
204
205
206static int __init thermal_init(void)
207{
208 init_default_values();
209
210 spu_add_sysdev_attr_group(&spu_attribute_group);
211 cpu_add_sysdev_attr_group(&ppe_attribute_group);
212
213 return 0;
214}
215module_init(thermal_init);
216
217static void __exit thermal_exit(void)
218{
219 spu_remove_sysdev_attr_group(&spu_attribute_group);
220 cpu_remove_sysdev_attr_group(&ppe_attribute_group);
221}
222module_exit(thermal_exit);
223
224MODULE_LICENSE("GPL");
225MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");
226
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index a914c12b4060..6666d037eb44 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -396,3 +396,19 @@ void __init iic_init_IRQ(void)
396 /* Enable on current CPU */ 396 /* Enable on current CPU */
397 iic_setup_cpu(); 397 iic_setup_cpu();
398} 398}
399
400void iic_set_interrupt_routing(int cpu, int thread, int priority)
401{
402 struct cbe_iic_regs __iomem *iic_regs = cbe_get_cpu_iic_regs(cpu);
403 u64 iic_ir = 0;
404 int node = cpu >> 1;
405
406 /* Set which node and thread will handle the next interrupt */
407 iic_ir |= CBE_IIC_IR_PRIO(priority) |
408 CBE_IIC_IR_DEST_NODE(node);
409 if (thread == 0)
410 iic_ir |= CBE_IIC_IR_DEST_UNIT(CBE_IIC_IR_PT_0);
411 else
412 iic_ir |= CBE_IIC_IR_DEST_UNIT(CBE_IIC_IR_PT_1);
413 out_be64(&iic_regs->iic_ir, iic_ir);
414}
diff --git a/arch/powerpc/platforms/cell/interrupt.h b/arch/powerpc/platforms/cell/interrupt.h
index 9ba1d3c17b4b..942dc39d6045 100644
--- a/arch/powerpc/platforms/cell/interrupt.h
+++ b/arch/powerpc/platforms/cell/interrupt.h
@@ -83,5 +83,7 @@ extern u8 iic_get_target_id(int cpu);
83 83
84extern void spider_init_IRQ(void); 84extern void spider_init_IRQ(void);
85 85
86extern void iic_set_interrupt_routing(int cpu, int thread, int priority);
87
86#endif 88#endif
87#endif /* ASM_CELL_PIC_H */ 89#endif /* ASM_CELL_PIC_H */
diff --git a/arch/powerpc/platforms/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c
new file mode 100644
index 000000000000..580d42595912
--- /dev/null
+++ b/arch/powerpc/platforms/cell/io-workarounds.c
@@ -0,0 +1,346 @@
1/*
2 * Copyright (C) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>
3 * IBM, Corp.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9#undef DEBUG
10
11#include <linux/kernel.h>
12#include <linux/mm.h>
13#include <linux/pci.h>
14#include <asm/io.h>
15#include <asm/machdep.h>
16#include <asm/pci-bridge.h>
17#include <asm/ppc-pci.h>
18
19
20#define SPIDER_PCI_REG_BASE 0xd000
21#define SPIDER_PCI_VCI_CNTL_STAT 0x0110
22#define SPIDER_PCI_DUMMY_READ 0x0810
23#define SPIDER_PCI_DUMMY_READ_BASE 0x0814
24
25/* Undefine that to re-enable bogus prefetch
26 *
27 * Without that workaround, the chip will do bogus prefetch past
28 * page boundary from system memory. This setting will disable that,
29 * though the documentation is unclear as to the consequences of doing
30 * so, either purely performances, or possible misbehaviour... It's not
31 * clear wether the chip can handle unaligned accesses at all without
32 * prefetching enabled.
33 *
34 * For now, things appear to be behaving properly with that prefetching
35 * disabled and IDE, possibly because IDE isn't doing any unaligned
36 * access.
37 */
38#define SPIDER_DISABLE_PREFETCH
39
40#define MAX_SPIDERS 2
41
42static struct spider_pci_bus {
43 void __iomem *regs;
44 unsigned long mmio_start;
45 unsigned long mmio_end;
46 unsigned long pio_vstart;
47 unsigned long pio_vend;
48} spider_pci_busses[MAX_SPIDERS];
49static int spider_pci_count;
50
51static struct spider_pci_bus *spider_pci_find(unsigned long vaddr,
52 unsigned long paddr)
53{
54 int i;
55
56 for (i = 0; i < spider_pci_count; i++) {
57 struct spider_pci_bus *bus = &spider_pci_busses[i];
58 if (paddr && paddr >= bus->mmio_start && paddr < bus->mmio_end)
59 return bus;
60 if (vaddr && vaddr >= bus->pio_vstart && vaddr < bus->pio_vend)
61 return bus;
62 }
63 return NULL;
64}
65
66static void spider_io_flush(const volatile void __iomem *addr)
67{
68 struct spider_pci_bus *bus;
69 int token;
70
71 /* Get platform token (set by ioremap) from address */
72 token = PCI_GET_ADDR_TOKEN(addr);
73
74 /* Fast path if we have a non-0 token, it indicates which bus we
75 * are on.
76 *
77 * If the token is 0, that means either the the ioremap was done
78 * before we initialized this layer, or it's a PIO operation. We
79 * fallback to a low path in this case. Hopefully, internal devices
80 * which are ioremap'ed early should use in_XX/out_XX functions
81 * instead of the PCI ones and thus not suffer from the slowdown.
82 *
83 * Also note that currently, the workaround will not work for areas
84 * that are not mapped with PTEs (bolted in the hash table). This
85 * is the case for ioremaps done very early at boot (before
86 * mem_init_done) and includes the mapping of the ISA IO space.
87 *
88 * Fortunately, none of the affected devices is expected to do DMA
89 * and thus there should be no problem in practice.
90 *
91 * In order to improve performances, we only do the PTE search for
92 * addresses falling in the PHB IO space area. That means it will
93 * not work for hotplug'ed PHBs but those don't exist with Spider.
94 */
95 if (token && token <= spider_pci_count)
96 bus = &spider_pci_busses[token - 1];
97 else {
98 unsigned long vaddr, paddr;
99 pte_t *ptep;
100
101 /* Fixup physical address */
102 vaddr = (unsigned long)PCI_FIX_ADDR(addr);
103
104 /* Check if it's in allowed range for PIO */
105 if (vaddr < PHBS_IO_BASE || vaddr >= IMALLOC_BASE)
106 return;
107
108 /* Try to find a PTE. If not, clear the paddr, we'll do
109 * a vaddr only lookup (PIO only)
110 */
111 ptep = find_linux_pte(init_mm.pgd, vaddr);
112 if (ptep == NULL)
113 paddr = 0;
114 else
115 paddr = pte_pfn(*ptep) << PAGE_SHIFT;
116
117 bus = spider_pci_find(vaddr, paddr);
118 if (bus == NULL)
119 return;
120 }
121
122 /* Now do the workaround
123 */
124 (void)in_be32(bus->regs + SPIDER_PCI_DUMMY_READ);
125}
126
127static u8 spider_readb(const volatile void __iomem *addr)
128{
129 u8 val = __do_readb(addr);
130 spider_io_flush(addr);
131 return val;
132}
133
134static u16 spider_readw(const volatile void __iomem *addr)
135{
136 u16 val = __do_readw(addr);
137 spider_io_flush(addr);
138 return val;
139}
140
141static u32 spider_readl(const volatile void __iomem *addr)
142{
143 u32 val = __do_readl(addr);
144 spider_io_flush(addr);
145 return val;
146}
147
148static u64 spider_readq(const volatile void __iomem *addr)
149{
150 u64 val = __do_readq(addr);
151 spider_io_flush(addr);
152 return val;
153}
154
155static u16 spider_readw_be(const volatile void __iomem *addr)
156{
157 u16 val = __do_readw_be(addr);
158 spider_io_flush(addr);
159 return val;
160}
161
162static u32 spider_readl_be(const volatile void __iomem *addr)
163{
164 u32 val = __do_readl_be(addr);
165 spider_io_flush(addr);
166 return val;
167}
168
169static u64 spider_readq_be(const volatile void __iomem *addr)
170{
171 u64 val = __do_readq_be(addr);
172 spider_io_flush(addr);
173 return val;
174}
175
176static void spider_readsb(const volatile void __iomem *addr, void *buf,
177 unsigned long count)
178{
179 __do_readsb(addr, buf, count);
180 spider_io_flush(addr);
181}
182
183static void spider_readsw(const volatile void __iomem *addr, void *buf,
184 unsigned long count)
185{
186 __do_readsw(addr, buf, count);
187 spider_io_flush(addr);
188}
189
190static void spider_readsl(const volatile void __iomem *addr, void *buf,
191 unsigned long count)
192{
193 __do_readsl(addr, buf, count);
194 spider_io_flush(addr);
195}
196
197static void spider_memcpy_fromio(void *dest, const volatile void __iomem *src,
198 unsigned long n)
199{
200 __do_memcpy_fromio(dest, src, n);
201 spider_io_flush(src);
202}
203
204
205static void __iomem * spider_ioremap(unsigned long addr, unsigned long size,
206 unsigned long flags)
207{
208 struct spider_pci_bus *bus;
209 void __iomem *res = __ioremap(addr, size, flags);
210 int busno;
211
212 pr_debug("spider_ioremap(0x%lx, 0x%lx, 0x%lx) -> 0x%p\n",
213 addr, size, flags, res);
214
215 bus = spider_pci_find(0, addr);
216 if (bus != NULL) {
217 busno = bus - spider_pci_busses;
218 pr_debug(" found bus %d, setting token\n", busno);
219 PCI_SET_ADDR_TOKEN(res, busno + 1);
220 }
221 pr_debug(" result=0x%p\n", res);
222
223 return res;
224}
225
226static void __init spider_pci_setup_chip(struct spider_pci_bus *bus)
227{
228#ifdef SPIDER_DISABLE_PREFETCH
229 u32 val = in_be32(bus->regs + SPIDER_PCI_VCI_CNTL_STAT);
230 pr_debug(" PVCI_Control_Status was 0x%08x\n", val);
231 out_be32(bus->regs + SPIDER_PCI_VCI_CNTL_STAT, val | 0x8);
232#endif
233
234 /* Configure the dummy address for the workaround */
235 out_be32(bus->regs + SPIDER_PCI_DUMMY_READ_BASE, 0x80000000);
236}
237
238static void __init spider_pci_add_one(struct pci_controller *phb)
239{
240 struct spider_pci_bus *bus = &spider_pci_busses[spider_pci_count];
241 struct device_node *np = phb->arch_data;
242 struct resource rsrc;
243 void __iomem *regs;
244
245 if (spider_pci_count >= MAX_SPIDERS) {
246 printk(KERN_ERR "Too many spider bridges, workarounds"
247 " disabled for %s\n", np->full_name);
248 return;
249 }
250
251 /* Get the registers for the beast */
252 if (of_address_to_resource(np, 0, &rsrc)) {
253 printk(KERN_ERR "Failed to get registers for spider %s"
254 " workarounds disabled\n", np->full_name);
255 return;
256 }
257
258 /* Mask out some useless bits in there to get to the base of the
259 * spider chip
260 */
261 rsrc.start &= ~0xfffffffful;
262
263 /* Map them */
264 regs = ioremap(rsrc.start + SPIDER_PCI_REG_BASE, 0x1000);
265 if (regs == NULL) {
266 printk(KERN_ERR "Failed to map registers for spider %s"
267 " workarounds disabled\n", np->full_name);
268 return;
269 }
270
271 spider_pci_count++;
272
273 /* We assume spiders only have one MMIO resource */
274 bus->mmio_start = phb->mem_resources[0].start;
275 bus->mmio_end = phb->mem_resources[0].end + 1;
276
277 bus->pio_vstart = (unsigned long)phb->io_base_virt;
278 bus->pio_vend = bus->pio_vstart + phb->pci_io_size;
279
280 bus->regs = regs;
281
282 printk(KERN_INFO "PCI: Spider MMIO workaround for %s\n",np->full_name);
283
284 pr_debug(" mmio (P) = 0x%016lx..0x%016lx\n",
285 bus->mmio_start, bus->mmio_end);
286 pr_debug(" pio (V) = 0x%016lx..0x%016lx\n",
287 bus->pio_vstart, bus->pio_vend);
288 pr_debug(" regs (P) = 0x%016lx (V) = 0x%p\n",
289 rsrc.start + SPIDER_PCI_REG_BASE, bus->regs);
290
291 spider_pci_setup_chip(bus);
292}
293
294static struct ppc_pci_io __initdata spider_pci_io = {
295 .readb = spider_readb,
296 .readw = spider_readw,
297 .readl = spider_readl,
298 .readq = spider_readq,
299 .readw_be = spider_readw_be,
300 .readl_be = spider_readl_be,
301 .readq_be = spider_readq_be,
302 .readsb = spider_readsb,
303 .readsw = spider_readsw,
304 .readsl = spider_readsl,
305 .memcpy_fromio = spider_memcpy_fromio,
306};
307
308static int __init spider_pci_workaround_init(void)
309{
310 struct pci_controller *phb;
311
312 if (!machine_is(cell))
313 return 0;
314
315 /* Find spider bridges. We assume they have been all probed
316 * in setup_arch(). If that was to change, we would need to
317 * update this code to cope with dynamically added busses
318 */
319 list_for_each_entry(phb, &hose_list, list_node) {
320 struct device_node *np = phb->arch_data;
321 const char *model = get_property(np, "model", NULL);
322
323 /* If no model property or name isn't exactly "pci", skip */
324 if (model == NULL || strcmp(np->name, "pci"))
325 continue;
326 /* If model is not "Spider", skip */
327 if (strcmp(model, "Spider"))
328 continue;
329 spider_pci_add_one(phb);
330 }
331
332 /* No Spider PCI found, exit */
333 if (spider_pci_count == 0)
334 return 0;
335
336 /* Setup IO callbacks. We only setup MMIO reads. PIO reads will
337 * fallback to MMIO reads (though without a token, thus slower)
338 */
339 ppc_pci_io = spider_pci_io;
340
341 /* Setup ioremap callback */
342 ppc_md.ioremap = spider_ioremap;
343
344 return 0;
345}
346arch_initcall(spider_pci_workaround_init);
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index aca4c3db0dde..b43466ba8096 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -1,514 +1,747 @@
1/* 1/*
2 * IOMMU implementation for Cell Broadband Processor Architecture 2 * IOMMU implementation for Cell Broadband Processor Architecture
3 * We just establish a linear mapping at boot by setting all the
4 * IOPT cache entries in the CPU.
5 * The mapping functions should be identical to pci_direct_iommu,
6 * except for the handling of the high order bit that is required
7 * by the Spider bridge. These should be split into a separate
8 * file at the point where we get a different bridge chip.
9 * 3 *
10 * Copyright (C) 2005 IBM Deutschland Entwicklung GmbH, 4 * (C) Copyright IBM Corporation 2006
11 * Arnd Bergmann <arndb@de.ibm.com>
12 * 5 *
13 * Based on linear mapping 6 * Author: Jeremy Kerr <jk@ozlabs.org>
14 * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org)
15 * 7 *
16 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or modify
17 * modify it under the terms of the GNU General Public License 9 * it under the terms of the GNU General Public License as published by
18 * as published by the Free Software Foundation; either version 10 * the Free Software Foundation; either version 2, or (at your option)
19 * 2 of the License, or (at your option) any later version. 11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */ 21 */
21 22
22#undef DEBUG 23#undef DEBUG
23 24
24#include <linux/kernel.h> 25#include <linux/kernel.h>
25#include <linux/pci.h>
26#include <linux/delay.h>
27#include <linux/string.h>
28#include <linux/init.h> 26#include <linux/init.h>
29#include <linux/bootmem.h> 27#include <linux/interrupt.h>
30#include <linux/mm.h> 28#include <linux/notifier.h>
31#include <linux/dma-mapping.h>
32#include <linux/kernel.h>
33#include <linux/compiler.h>
34 29
35#include <asm/sections.h>
36#include <asm/iommu.h>
37#include <asm/io.h>
38#include <asm/prom.h> 30#include <asm/prom.h>
39#include <asm/pci-bridge.h> 31#include <asm/iommu.h>
40#include <asm/machdep.h> 32#include <asm/machdep.h>
41#include <asm/pmac_feature.h> 33#include <asm/pci-bridge.h>
42#include <asm/abs_addr.h>
43#include <asm/system.h>
44#include <asm/ppc-pci.h>
45#include <asm/udbg.h> 34#include <asm/udbg.h>
35#include <asm/of_platform.h>
36#include <asm/lmb.h>
46 37
47#include "iommu.h" 38#include "cbe_regs.h"
39#include "interrupt.h"
48 40
49static inline unsigned long 41/* Define CELL_IOMMU_REAL_UNMAP to actually unmap non-used pages
50get_iopt_entry(unsigned long real_address, unsigned long ioid, 42 * instead of leaving them mapped to some dummy page. This can be
51 unsigned long prot) 43 * enabled once the appropriate workarounds for spider bugs have
52{ 44 * been enabled
53 return (prot & IOPT_PROT_MASK) 45 */
54 | (IOPT_COHERENT) 46#define CELL_IOMMU_REAL_UNMAP
55 | (IOPT_ORDER_VC)
56 | (real_address & IOPT_RPN_MASK)
57 | (ioid & IOPT_IOID_MASK);
58}
59 47
60typedef struct { 48/* Define CELL_IOMMU_STRICT_PROTECTION to enforce protection of
61 unsigned long val; 49 * IO PTEs based on the transfer direction. That can be enabled
62} ioste; 50 * once spider-net has been fixed to pass the correct direction
51 * to the DMA mapping functions
52 */
53#define CELL_IOMMU_STRICT_PROTECTION
54
55
56#define NR_IOMMUS 2
57
58/* IOC mmap registers */
59#define IOC_Reg_Size 0x2000
60
61#define IOC_IOPT_CacheInvd 0x908
62#define IOC_IOPT_CacheInvd_NE_Mask 0xffe0000000000000ul
63#define IOC_IOPT_CacheInvd_IOPTE_Mask 0x000003fffffffff8ul
64#define IOC_IOPT_CacheInvd_Busy 0x0000000000000001ul
65
66#define IOC_IOST_Origin 0x918
67#define IOC_IOST_Origin_E 0x8000000000000000ul
68#define IOC_IOST_Origin_HW 0x0000000000000800ul
69#define IOC_IOST_Origin_HL 0x0000000000000400ul
70
71#define IOC_IO_ExcpStat 0x920
72#define IOC_IO_ExcpStat_V 0x8000000000000000ul
73#define IOC_IO_ExcpStat_SPF_Mask 0x6000000000000000ul
74#define IOC_IO_ExcpStat_SPF_S 0x6000000000000000ul
75#define IOC_IO_ExcpStat_SPF_P 0x4000000000000000ul
76#define IOC_IO_ExcpStat_ADDR_Mask 0x00000007fffff000ul
77#define IOC_IO_ExcpStat_RW_Mask 0x0000000000000800ul
78#define IOC_IO_ExcpStat_IOID_Mask 0x00000000000007fful
79
80#define IOC_IO_ExcpMask 0x928
81#define IOC_IO_ExcpMask_SFE 0x4000000000000000ul
82#define IOC_IO_ExcpMask_PFE 0x2000000000000000ul
83
84#define IOC_IOCmd_Offset 0x1000
85
86#define IOC_IOCmd_Cfg 0xc00
87#define IOC_IOCmd_Cfg_TE 0x0000800000000000ul
88
89
90/* Segment table entries */
91#define IOSTE_V 0x8000000000000000ul /* valid */
92#define IOSTE_H 0x4000000000000000ul /* cache hint */
93#define IOSTE_PT_Base_RPN_Mask 0x3ffffffffffff000ul /* base RPN of IOPT */
94#define IOSTE_NPPT_Mask 0x0000000000000fe0ul /* no. pages in IOPT */
95#define IOSTE_PS_Mask 0x0000000000000007ul /* page size */
96#define IOSTE_PS_4K 0x0000000000000001ul /* - 4kB */
97#define IOSTE_PS_64K 0x0000000000000003ul /* - 64kB */
98#define IOSTE_PS_1M 0x0000000000000005ul /* - 1MB */
99#define IOSTE_PS_16M 0x0000000000000007ul /* - 16MB */
100
101/* Page table entries */
102#define IOPTE_PP_W 0x8000000000000000ul /* protection: write */
103#define IOPTE_PP_R 0x4000000000000000ul /* protection: read */
104#define IOPTE_M 0x2000000000000000ul /* coherency required */
105#define IOPTE_SO_R 0x1000000000000000ul /* ordering: writes */
106#define IOPTE_SO_RW 0x1800000000000000ul /* ordering: r & w */
107#define IOPTE_RPN_Mask 0x07fffffffffff000ul /* RPN */
108#define IOPTE_H 0x0000000000000800ul /* cache hint */
109#define IOPTE_IOID_Mask 0x00000000000007fful /* ioid */
110
111
112/* IOMMU sizing */
113#define IO_SEGMENT_SHIFT 28
114#define IO_PAGENO_BITS (IO_SEGMENT_SHIFT - IOMMU_PAGE_SHIFT)
115
116/* The high bit needs to be set on every DMA address */
117#define SPIDER_DMA_OFFSET 0x80000000ul
118
119struct iommu_window {
120 struct list_head list;
121 struct cbe_iommu *iommu;
122 unsigned long offset;
123 unsigned long size;
124 unsigned long pte_offset;
125 unsigned int ioid;
126 struct iommu_table table;
127};
63 128
64static inline ioste 129#define NAMESIZE 8
65mk_ioste(unsigned long val) 130struct cbe_iommu {
66{ 131 int nid;
67 ioste ioste = { .val = val, }; 132 char name[NAMESIZE];
68 return ioste; 133 void __iomem *xlate_regs;
69} 134 void __iomem *cmd_regs;
135 unsigned long *stab;
136 unsigned long *ptab;
137 void *pad_page;
138 struct list_head windows;
139};
140
141/* Static array of iommus, one per node
142 * each contains a list of windows, keyed from dma_window property
143 * - on bus setup, look for a matching window, or create one
144 * - on dev setup, assign iommu_table ptr
145 */
146static struct cbe_iommu iommus[NR_IOMMUS];
147static int cbe_nr_iommus;
70 148
71static inline ioste 149static void invalidate_tce_cache(struct cbe_iommu *iommu, unsigned long *pte,
72get_iost_entry(unsigned long iopt_base, unsigned long io_address, unsigned page_size) 150 long n_ptes)
73{ 151{
74 unsigned long ps; 152 unsigned long *reg, val;
75 unsigned long iostep; 153 long n;
76 unsigned long nnpt;
77 unsigned long shift;
78
79 switch (page_size) {
80 case 0x1000000:
81 ps = IOST_PS_16M;
82 nnpt = 0; /* one page per segment */
83 shift = 5; /* segment has 16 iopt entries */
84 break;
85
86 case 0x100000:
87 ps = IOST_PS_1M;
88 nnpt = 0; /* one page per segment */
89 shift = 1; /* segment has 256 iopt entries */
90 break;
91
92 case 0x10000:
93 ps = IOST_PS_64K;
94 nnpt = 0x07; /* 8 pages per io page table */
95 shift = 0; /* all entries are used */
96 break;
97
98 case 0x1000:
99 ps = IOST_PS_4K;
100 nnpt = 0x7f; /* 128 pages per io page table */
101 shift = 0; /* all entries are used */
102 break;
103
104 default: /* not a known compile time constant */
105 {
106 /* BUILD_BUG_ON() is not usable here */
107 extern void __get_iost_entry_bad_page_size(void);
108 __get_iost_entry_bad_page_size();
109 }
110 break;
111 }
112 154
113 iostep = iopt_base + 155 reg = iommu->xlate_regs + IOC_IOPT_CacheInvd;
114 /* need 8 bytes per iopte */
115 (((io_address / page_size * 8)
116 /* align io page tables on 4k page boundaries */
117 << shift)
118 /* nnpt+1 pages go into each iopt */
119 & ~(nnpt << 12));
120
121 nnpt++; /* this seems to work, but the documentation is not clear
122 about wether we put nnpt or nnpt-1 into the ioste bits.
123 In theory, this can't work for 4k pages. */
124 return mk_ioste(IOST_VALID_MASK
125 | (iostep & IOST_PT_BASE_MASK)
126 | ((nnpt << 5) & IOST_NNPT_MASK)
127 | (ps & IOST_PS_MASK));
128}
129 156
130/* compute the address of an io pte */ 157 while (n_ptes > 0) {
131static inline unsigned long 158 /* we can invalidate up to 1 << 11 PTEs at once */
132get_ioptep(ioste iost_entry, unsigned long io_address) 159 n = min(n_ptes, 1l << 11);
133{ 160 val = (((n /*- 1*/) << 53) & IOC_IOPT_CacheInvd_NE_Mask)
134 unsigned long iopt_base; 161 | (__pa(pte) & IOC_IOPT_CacheInvd_IOPTE_Mask)
135 unsigned long page_size; 162 | IOC_IOPT_CacheInvd_Busy;
136 unsigned long page_number;
137 unsigned long iopt_offset;
138
139 iopt_base = iost_entry.val & IOST_PT_BASE_MASK;
140 page_size = iost_entry.val & IOST_PS_MASK;
141
142 /* decode page size to compute page number */
143 page_number = (io_address & 0x0fffffff) >> (10 + 2 * page_size);
144 /* page number is an offset into the io page table */
145 iopt_offset = (page_number << 3) & 0x7fff8ul;
146 return iopt_base + iopt_offset;
147}
148 163
149/* compute the tag field of the iopt cache entry */ 164 out_be64(reg, val);
150static inline unsigned long 165 while (in_be64(reg) & IOC_IOPT_CacheInvd_Busy)
151get_ioc_tag(ioste iost_entry, unsigned long io_address) 166 ;
152{
153 unsigned long iopte = get_ioptep(iost_entry, io_address);
154 167
155 return IOPT_VALID_MASK 168 n_ptes -= n;
156 | ((iopte & 0x00000000000000ff8ul) >> 3) 169 pte += n;
157 | ((iopte & 0x0000003fffffc0000ul) >> 9); 170 }
158} 171}
159 172
160/* compute the hashed 6 bit index for the 4-way associative pte cache */ 173static void tce_build_cell(struct iommu_table *tbl, long index, long npages,
161static inline unsigned long 174 unsigned long uaddr, enum dma_data_direction direction)
162get_ioc_hash(ioste iost_entry, unsigned long io_address)
163{ 175{
164 unsigned long iopte = get_ioptep(iost_entry, io_address); 176 int i;
165 177 unsigned long *io_pte, base_pte;
166 return ((iopte & 0x000000000000001f8ul) >> 3) 178 struct iommu_window *window =
167 ^ ((iopte & 0x00000000000020000ul) >> 17) 179 container_of(tbl, struct iommu_window, table);
168 ^ ((iopte & 0x00000000000010000ul) >> 15) 180
169 ^ ((iopte & 0x00000000000008000ul) >> 13) 181 /* implementing proper protection causes problems with the spidernet
170 ^ ((iopte & 0x00000000000004000ul) >> 11) 182 * driver - check mapping directions later, but allow read & write by
171 ^ ((iopte & 0x00000000000002000ul) >> 9) 183 * default for now.*/
172 ^ ((iopte & 0x00000000000001000ul) >> 7); 184#ifdef CELL_IOMMU_STRICT_PROTECTION
185 /* to avoid referencing a global, we use a trick here to setup the
186 * protection bit. "prot" is setup to be 3 fields of 4 bits apprended
187 * together for each of the 3 supported direction values. It is then
188 * shifted left so that the fields matching the desired direction
189 * lands on the appropriate bits, and other bits are masked out.
190 */
191 const unsigned long prot = 0xc48;
192 base_pte =
193 ((prot << (52 + 4 * direction)) & (IOPTE_PP_W | IOPTE_PP_R))
194 | IOPTE_M | IOPTE_SO_RW | (window->ioid & IOPTE_IOID_Mask);
195#else
196 base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW |
197 (window->ioid & IOPTE_IOID_Mask);
198#endif
199
200 io_pte = (unsigned long *)tbl->it_base + (index - window->pte_offset);
201
202 for (i = 0; i < npages; i++, uaddr += IOMMU_PAGE_SIZE)
203 io_pte[i] = base_pte | (__pa(uaddr) & IOPTE_RPN_Mask);
204
205 mb();
206
207 invalidate_tce_cache(window->iommu, io_pte, npages);
208
209 pr_debug("tce_build_cell(index=%lx,n=%lx,dir=%d,base_pte=%lx)\n",
210 index, npages, direction, base_pte);
173} 211}
174 212
175/* same as above, but pretend that we have a simpler 1-way associative 213static void tce_free_cell(struct iommu_table *tbl, long index, long npages)
176 pte cache with an 8 bit index */
177static inline unsigned long
178get_ioc_hash_1way(ioste iost_entry, unsigned long io_address)
179{ 214{
180 unsigned long iopte = get_ioptep(iost_entry, io_address);
181
182 return ((iopte & 0x000000000000001f8ul) >> 3)
183 ^ ((iopte & 0x00000000000020000ul) >> 17)
184 ^ ((iopte & 0x00000000000010000ul) >> 15)
185 ^ ((iopte & 0x00000000000008000ul) >> 13)
186 ^ ((iopte & 0x00000000000004000ul) >> 11)
187 ^ ((iopte & 0x00000000000002000ul) >> 9)
188 ^ ((iopte & 0x00000000000001000ul) >> 7)
189 ^ ((iopte & 0x0000000000000c000ul) >> 8);
190}
191 215
192static inline ioste 216 int i;
193get_iost_cache(void __iomem *base, unsigned long index) 217 unsigned long *io_pte, pte;
194{ 218 struct iommu_window *window =
195 unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR); 219 container_of(tbl, struct iommu_window, table);
196 return mk_ioste(in_be64(&p[index]));
197}
198 220
199static inline void 221 pr_debug("tce_free_cell(index=%lx,n=%lx)\n", index, npages);
200set_iost_cache(void __iomem *base, unsigned long index, ioste ste)
201{
202 unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR);
203 pr_debug("ioste %02lx was %016lx, store %016lx", index,
204 get_iost_cache(base, index).val, ste.val);
205 out_be64(&p[index], ste.val);
206 pr_debug(" now %016lx\n", get_iost_cache(base, index).val);
207}
208 222
209static inline unsigned long 223#ifdef CELL_IOMMU_REAL_UNMAP
210get_iopt_cache(void __iomem *base, unsigned long index, unsigned long *tag) 224 pte = 0;
211{ 225#else
212 unsigned long __iomem *tags = (void *)(base + IOC_PT_CACHE_DIR); 226 /* spider bridge does PCI reads after freeing - insert a mapping
213 unsigned long __iomem *p = (void *)(base + IOC_PT_CACHE_REG); 227 * to a scratch page instead of an invalid entry */
228 pte = IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW | __pa(window->iommu->pad_page)
229 | (window->ioid & IOPTE_IOID_Mask);
230#endif
214 231
215 *tag = tags[index]; 232 io_pte = (unsigned long *)tbl->it_base + (index - window->pte_offset);
216 rmb();
217 return *p;
218}
219 233
220static inline void 234 for (i = 0; i < npages; i++)
221set_iopt_cache(void __iomem *base, unsigned long index, 235 io_pte[i] = pte;
222 unsigned long tag, unsigned long val) 236
223{ 237 mb();
224 unsigned long __iomem *tags = base + IOC_PT_CACHE_DIR;
225 unsigned long __iomem *p = base + IOC_PT_CACHE_REG;
226 238
227 out_be64(p, val); 239 invalidate_tce_cache(window->iommu, io_pte, npages);
228 out_be64(&tags[index], tag);
229} 240}
230 241
231static inline void 242static irqreturn_t ioc_interrupt(int irq, void *data)
232set_iost_origin(void __iomem *base)
233{ 243{
234 unsigned long __iomem *p = base + IOC_ST_ORIGIN; 244 unsigned long stat;
235 unsigned long origin = IOSTO_ENABLE | IOSTO_SW; 245 struct cbe_iommu *iommu = data;
236 246
237 pr_debug("iost_origin %016lx, now %016lx\n", in_be64(p), origin); 247 stat = in_be64(iommu->xlate_regs + IOC_IO_ExcpStat);
238 out_be64(p, origin); 248
249 /* Might want to rate limit it */
250 printk(KERN_ERR "iommu: DMA exception 0x%016lx\n", stat);
251 printk(KERN_ERR " V=%d, SPF=[%c%c], RW=%s, IOID=0x%04x\n",
252 !!(stat & IOC_IO_ExcpStat_V),
253 (stat & IOC_IO_ExcpStat_SPF_S) ? 'S' : ' ',
254 (stat & IOC_IO_ExcpStat_SPF_P) ? 'P' : ' ',
255 (stat & IOC_IO_ExcpStat_RW_Mask) ? "Read" : "Write",
256 (unsigned int)(stat & IOC_IO_ExcpStat_IOID_Mask));
257 printk(KERN_ERR " page=0x%016lx\n",
258 stat & IOC_IO_ExcpStat_ADDR_Mask);
259
260 /* clear interrupt */
261 stat &= ~IOC_IO_ExcpStat_V;
262 out_be64(iommu->xlate_regs + IOC_IO_ExcpStat, stat);
263
264 return IRQ_HANDLED;
239} 265}
240 266
241static inline void 267static int cell_iommu_find_ioc(int nid, unsigned long *base)
242set_iocmd_config(void __iomem *base)
243{ 268{
244 unsigned long __iomem *p = base + 0xc00; 269 struct device_node *np;
245 unsigned long conf; 270 struct resource r;
271
272 *base = 0;
273
274 /* First look for new style /be nodes */
275 for_each_node_by_name(np, "ioc") {
276 if (of_node_to_nid(np) != nid)
277 continue;
278 if (of_address_to_resource(np, 0, &r)) {
279 printk(KERN_ERR "iommu: can't get address for %s\n",
280 np->full_name);
281 continue;
282 }
283 *base = r.start;
284 of_node_put(np);
285 return 0;
286 }
246 287
247 conf = in_be64(p); 288 /* Ok, let's try the old way */
248 pr_debug("iost_conf %016lx, now %016lx\n", conf, conf | IOCMD_CONF_TE); 289 for_each_node_by_type(np, "cpu") {
249 out_be64(p, conf | IOCMD_CONF_TE); 290 const unsigned int *nidp;
291 const unsigned long *tmp;
292
293 nidp = get_property(np, "node-id", NULL);
294 if (nidp && *nidp == nid) {
295 tmp = get_property(np, "ioc-translation", NULL);
296 if (tmp) {
297 *base = *tmp;
298 of_node_put(np);
299 return 0;
300 }
301 }
302 }
303
304 return -ENODEV;
250} 305}
251 306
252static void enable_mapping(void __iomem *base, void __iomem *mmio_base) 307static void cell_iommu_setup_hardware(struct cbe_iommu *iommu, unsigned long size)
253{ 308{
254 set_iocmd_config(base); 309 struct page *page;
255 set_iost_origin(mmio_base); 310 int ret, i;
256} 311 unsigned long reg, segments, pages_per_segment, ptab_size, n_pte_pages;
312 unsigned long xlate_base;
313 unsigned int virq;
314
315 if (cell_iommu_find_ioc(iommu->nid, &xlate_base))
316 panic("%s: missing IOC register mappings for node %d\n",
317 __FUNCTION__, iommu->nid);
318
319 iommu->xlate_regs = ioremap(xlate_base, IOC_Reg_Size);
320 iommu->cmd_regs = iommu->xlate_regs + IOC_IOCmd_Offset;
321
322 segments = size >> IO_SEGMENT_SHIFT;
323 pages_per_segment = 1ull << IO_PAGENO_BITS;
324
325 pr_debug("%s: iommu[%d]: segments: %lu, pages per segment: %lu\n",
326 __FUNCTION__, iommu->nid, segments, pages_per_segment);
327
328 /* set up the segment table */
329 page = alloc_pages_node(iommu->nid, GFP_KERNEL, 0);
330 BUG_ON(!page);
331 iommu->stab = page_address(page);
332 clear_page(iommu->stab);
333
334 /* ... and the page tables. Since these are contiguous, we can treat
335 * the page tables as one array of ptes, like pSeries does.
336 */
337 ptab_size = segments * pages_per_segment * sizeof(unsigned long);
338 pr_debug("%s: iommu[%d]: ptab_size: %lu, order: %d\n", __FUNCTION__,
339 iommu->nid, ptab_size, get_order(ptab_size));
340 page = alloc_pages_node(iommu->nid, GFP_KERNEL, get_order(ptab_size));
341 BUG_ON(!page);
342
343 iommu->ptab = page_address(page);
344 memset(iommu->ptab, 0, ptab_size);
345
346 /* allocate a bogus page for the end of each mapping */
347 page = alloc_pages_node(iommu->nid, GFP_KERNEL, 0);
348 BUG_ON(!page);
349 iommu->pad_page = page_address(page);
350 clear_page(iommu->pad_page);
351
352 /* number of pages needed for a page table */
353 n_pte_pages = (pages_per_segment *
354 sizeof(unsigned long)) >> IOMMU_PAGE_SHIFT;
355
356 pr_debug("%s: iommu[%d]: stab at %p, ptab at %p, n_pte_pages: %lu\n",
357 __FUNCTION__, iommu->nid, iommu->stab, iommu->ptab,
358 n_pte_pages);
359
360 /* initialise the STEs */
361 reg = IOSTE_V | ((n_pte_pages - 1) << 5);
362
363 if (IOMMU_PAGE_SIZE == 0x1000)
364 reg |= IOSTE_PS_4K;
365 else if (IOMMU_PAGE_SIZE == 0x10000)
366 reg |= IOSTE_PS_64K;
367 else {
368 extern void __unknown_page_size_error(void);
369 __unknown_page_size_error();
370 }
371
372 pr_debug("Setting up IOMMU stab:\n");
373 for (i = 0; i * (1ul << IO_SEGMENT_SHIFT) < size; i++) {
374 iommu->stab[i] = reg |
375 (__pa(iommu->ptab) + n_pte_pages * IOMMU_PAGE_SIZE * i);
376 pr_debug("\t[%d] 0x%016lx\n", i, iommu->stab[i]);
377 }
257 378
258static void iommu_dev_setup_null(struct pci_dev *d) { } 379 /* ensure that the STEs have updated */
259static void iommu_bus_setup_null(struct pci_bus *b) { } 380 mb();
260 381
261struct cell_iommu { 382 /* setup interrupts for the iommu. */
262 unsigned long base; 383 reg = in_be64(iommu->xlate_regs + IOC_IO_ExcpStat);
263 unsigned long mmio_base; 384 out_be64(iommu->xlate_regs + IOC_IO_ExcpStat,
264 void __iomem *mapped_base; 385 reg & ~IOC_IO_ExcpStat_V);
265 void __iomem *mapped_mmio_base; 386 out_be64(iommu->xlate_regs + IOC_IO_ExcpMask,
266}; 387 IOC_IO_ExcpMask_PFE | IOC_IO_ExcpMask_SFE);
267 388
268static struct cell_iommu cell_iommus[NR_CPUS]; 389 virq = irq_create_mapping(NULL,
390 IIC_IRQ_IOEX_ATI | (iommu->nid << IIC_IRQ_NODE_SHIFT));
391 BUG_ON(virq == NO_IRQ);
269 392
270/* initialize the iommu to support a simple linear mapping 393 ret = request_irq(virq, ioc_interrupt, IRQF_DISABLED,
271 * for each DMA window used by any device. For now, we 394 iommu->name, iommu);
272 * happen to know that there is only one DMA window in use, 395 BUG_ON(ret);
273 * starting at iopt_phys_offset. */
274static void cell_do_map_iommu(struct cell_iommu *iommu,
275 unsigned int ioid,
276 unsigned long map_start,
277 unsigned long map_size)
278{
279 unsigned long io_address, real_address;
280 void __iomem *ioc_base, *ioc_mmio_base;
281 ioste ioste;
282 unsigned long index;
283 396
284 /* we pretend the io page table was at a very high address */ 397 /* set the IOC segment table origin register (and turn on the iommu) */
285 const unsigned long fake_iopt = 0x10000000000ul; 398 reg = IOC_IOST_Origin_E | __pa(iommu->stab) | IOC_IOST_Origin_HW;
286 const unsigned long io_page_size = 0x1000000; /* use 16M pages */ 399 out_be64(iommu->xlate_regs + IOC_IOST_Origin, reg);
287 const unsigned long io_segment_size = 0x10000000; /* 256M */ 400 in_be64(iommu->xlate_regs + IOC_IOST_Origin);
288 401
289 ioc_base = iommu->mapped_base; 402 /* turn on IO translation */
290 ioc_mmio_base = iommu->mapped_mmio_base; 403 reg = in_be64(iommu->cmd_regs + IOC_IOCmd_Cfg) | IOC_IOCmd_Cfg_TE;
291 404 out_be64(iommu->cmd_regs + IOC_IOCmd_Cfg, reg);
292 for (real_address = 0, io_address = map_start;
293 io_address <= map_start + map_size;
294 real_address += io_page_size, io_address += io_page_size) {
295 ioste = get_iost_entry(fake_iopt, io_address, io_page_size);
296 if ((real_address % io_segment_size) == 0) /* segment start */
297 set_iost_cache(ioc_mmio_base,
298 io_address >> 28, ioste);
299 index = get_ioc_hash_1way(ioste, io_address);
300 pr_debug("addr %08lx, index %02lx, ioste %016lx\n",
301 io_address, index, ioste.val);
302 set_iopt_cache(ioc_mmio_base,
303 get_ioc_hash_1way(ioste, io_address),
304 get_ioc_tag(ioste, io_address),
305 get_iopt_entry(real_address, ioid, IOPT_PROT_RW));
306 }
307} 405}
308 406
309static void iommu_devnode_setup(struct device_node *d) 407#if 0/* Unused for now */
408static struct iommu_window *find_window(struct cbe_iommu *iommu,
409 unsigned long offset, unsigned long size)
310{ 410{
311 const unsigned int *ioid; 411 struct iommu_window *window;
312 unsigned long map_start, map_size, token;
313 const unsigned long *dma_window;
314 struct cell_iommu *iommu;
315 412
316 ioid = get_property(d, "ioid", NULL); 413 /* todo: check for overlapping (but not equal) windows) */
317 if (!ioid)
318 pr_debug("No ioid entry found !\n");
319 414
320 dma_window = get_property(d, "ibm,dma-window", NULL); 415 list_for_each_entry(window, &(iommu->windows), list) {
321 if (!dma_window) 416 if (window->offset == offset && window->size == size)
322 pr_debug("No ibm,dma-window entry found !\n"); 417 return window;
418 }
323 419
324 map_start = dma_window[1]; 420 return NULL;
325 map_size = dma_window[2]; 421}
326 token = dma_window[0] >> 32; 422#endif
327 423
328 iommu = &cell_iommus[token]; 424static struct iommu_window * __init
425cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np,
426 unsigned long offset, unsigned long size,
427 unsigned long pte_offset)
428{
429 struct iommu_window *window;
430 const unsigned int *ioid;
329 431
330 cell_do_map_iommu(iommu, *ioid, map_start, map_size); 432 ioid = get_property(np, "ioid", NULL);
433 if (ioid == NULL)
434 printk(KERN_WARNING "iommu: missing ioid for %s using 0\n",
435 np->full_name);
436
437 window = kmalloc_node(sizeof(*window), GFP_KERNEL, iommu->nid);
438 BUG_ON(window == NULL);
439
440 window->offset = offset;
441 window->size = size;
442 window->ioid = ioid ? *ioid : 0;
443 window->iommu = iommu;
444 window->pte_offset = pte_offset;
445
446 window->table.it_blocksize = 16;
447 window->table.it_base = (unsigned long)iommu->ptab;
448 window->table.it_index = iommu->nid;
449 window->table.it_offset = (offset >> IOMMU_PAGE_SHIFT) +
450 window->pte_offset;
451 window->table.it_size = size >> IOMMU_PAGE_SHIFT;
452
453 iommu_init_table(&window->table, iommu->nid);
454
455 pr_debug("\tioid %d\n", window->ioid);
456 pr_debug("\tblocksize %ld\n", window->table.it_blocksize);
457 pr_debug("\tbase 0x%016lx\n", window->table.it_base);
458 pr_debug("\toffset 0x%lx\n", window->table.it_offset);
459 pr_debug("\tsize %ld\n", window->table.it_size);
460
461 list_add(&window->list, &iommu->windows);
462
463 if (offset != 0)
464 return window;
465
466 /* We need to map and reserve the first IOMMU page since it's used
467 * by the spider workaround. In theory, we only need to do that when
468 * running on spider but it doesn't really matter.
469 *
470 * This code also assumes that we have a window that starts at 0,
471 * which is the case on all spider based blades.
472 */
473 __set_bit(0, window->table.it_map);
474 tce_build_cell(&window->table, window->table.it_offset, 1,
475 (unsigned long)iommu->pad_page, DMA_TO_DEVICE);
476 window->table.it_hint = window->table.it_blocksize;
477
478 return window;
331} 479}
332 480
333static void iommu_bus_setup(struct pci_bus *b) 481static struct cbe_iommu *cell_iommu_for_node(int nid)
334{ 482{
335 struct device_node *d = (struct device_node *)b->sysdata; 483 int i;
336 iommu_devnode_setup(d);
337}
338 484
485 for (i = 0; i < cbe_nr_iommus; i++)
486 if (iommus[i].nid == nid)
487 return &iommus[i];
488 return NULL;
489}
339 490
340static int cell_map_iommu_hardcoded(int num_nodes) 491static void cell_dma_dev_setup(struct device *dev)
341{ 492{
342 struct cell_iommu *iommu = NULL; 493 struct iommu_window *window;
343 494 struct cbe_iommu *iommu;
344 pr_debug("%s(%d): Using hardcoded defaults\n", __FUNCTION__, __LINE__); 495 struct dev_archdata *archdata = &dev->archdata;
496
497 /* If we run without iommu, no need to do anything */
498 if (pci_dma_ops == &dma_direct_ops)
499 return;
500
501 /* Current implementation uses the first window available in that
502 * node's iommu. We -might- do something smarter later though it may
503 * never be necessary
504 */
505 iommu = cell_iommu_for_node(archdata->numa_node);
506 if (iommu == NULL || list_empty(&iommu->windows)) {
507 printk(KERN_ERR "iommu: missing iommu for %s (node %d)\n",
508 archdata->of_node ? archdata->of_node->full_name : "?",
509 archdata->numa_node);
510 return;
511 }
512 window = list_entry(iommu->windows.next, struct iommu_window, list);
345 513
346 /* node 0 */ 514 archdata->dma_data = &window->table;
347 iommu = &cell_iommus[0]; 515}
348 iommu->mapped_base = ioremap(0x20000511000ul, 0x1000);
349 iommu->mapped_mmio_base = ioremap(0x20000510000ul, 0x1000);
350 516
351 enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base); 517static void cell_pci_dma_dev_setup(struct pci_dev *dev)
518{
519 cell_dma_dev_setup(&dev->dev);
520}
352 521
353 cell_do_map_iommu(iommu, 0x048a, 522static int cell_of_bus_notify(struct notifier_block *nb, unsigned long action,
354 0x20000000ul,0x20000000ul); 523 void *data)
524{
525 struct device *dev = data;
355 526
356 if (num_nodes < 2) 527 /* We are only intereted in device addition */
528 if (action != BUS_NOTIFY_ADD_DEVICE)
357 return 0; 529 return 0;
358 530
359 /* node 1 */ 531 /* We use the PCI DMA ops */
360 iommu = &cell_iommus[1]; 532 dev->archdata.dma_ops = pci_dma_ops;
361 iommu->mapped_base = ioremap(0x30000511000ul, 0x1000);
362 iommu->mapped_mmio_base = ioremap(0x30000510000ul, 0x1000);
363
364 enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base);
365 533
366 cell_do_map_iommu(iommu, 0x048a, 534 cell_dma_dev_setup(dev);
367 0x20000000,0x20000000ul);
368 535
369 return 0; 536 return 0;
370} 537}
371 538
539static struct notifier_block cell_of_bus_notifier = {
540 .notifier_call = cell_of_bus_notify
541};
372 542
373static int cell_map_iommu(void) 543static int __init cell_iommu_get_window(struct device_node *np,
544 unsigned long *base,
545 unsigned long *size)
374{ 546{
375 unsigned int num_nodes = 0; 547 const void *dma_window;
376 const unsigned int *node_id; 548 unsigned long index;
377 const unsigned long *base, *mmio_base;
378 struct device_node *dn;
379 struct cell_iommu *iommu = NULL;
380
381 /* determine number of nodes (=iommus) */
382 pr_debug("%s(%d): determining number of nodes...", __FUNCTION__, __LINE__);
383 for(dn = of_find_node_by_type(NULL, "cpu");
384 dn;
385 dn = of_find_node_by_type(dn, "cpu")) {
386 node_id = get_property(dn, "node-id", NULL);
387
388 if (num_nodes < *node_id)
389 num_nodes = *node_id;
390 }
391
392 num_nodes++;
393 pr_debug("%i found.\n", num_nodes);
394 549
395 /* map the iommu registers for each node */ 550 /* Use ibm,dma-window if available, else, hard code ! */
396 pr_debug("%s(%d): Looping through nodes\n", __FUNCTION__, __LINE__); 551 dma_window = get_property(np, "ibm,dma-window", NULL);
397 for(dn = of_find_node_by_type(NULL, "cpu"); 552 if (dma_window == NULL) {
398 dn; 553 *base = 0;
399 dn = of_find_node_by_type(dn, "cpu")) { 554 *size = 0x80000000u;
555 return -ENODEV;
556 }
400 557
401 node_id = get_property(dn, "node-id", NULL); 558 of_parse_dma_window(np, dma_window, &index, base, size);
402 base = get_property(dn, "ioc-cache", NULL); 559 return 0;
403 mmio_base = get_property(dn, "ioc-translation", NULL); 560}
404 561
405 if (!base || !mmio_base || !node_id) 562static void __init cell_iommu_init_one(struct device_node *np, unsigned long offset)
406 return cell_map_iommu_hardcoded(num_nodes); 563{
564 struct cbe_iommu *iommu;
565 unsigned long base, size;
566 int nid, i;
567
568 /* Get node ID */
569 nid = of_node_to_nid(np);
570 if (nid < 0) {
571 printk(KERN_ERR "iommu: failed to get node for %s\n",
572 np->full_name);
573 return;
574 }
575 pr_debug("iommu: setting up iommu for node %d (%s)\n",
576 nid, np->full_name);
577
578 /* XXX todo: If we can have multiple windows on the same IOMMU, which
579 * isn't the case today, we probably want here to check wether the
580 * iommu for that node is already setup.
581 * However, there might be issue with getting the size right so let's
582 * ignore that for now. We might want to completely get rid of the
583 * multiple window support since the cell iommu supports per-page ioids
584 */
585
586 if (cbe_nr_iommus >= NR_IOMMUS) {
587 printk(KERN_ERR "iommu: too many IOMMUs detected ! (%s)\n",
588 np->full_name);
589 return;
590 }
407 591
408 iommu = &cell_iommus[*node_id]; 592 /* Init base fields */
409 iommu->base = *base; 593 i = cbe_nr_iommus++;
410 iommu->mmio_base = *mmio_base; 594 iommu = &iommus[i];
595 iommu->stab = 0;
596 iommu->nid = nid;
597 snprintf(iommu->name, sizeof(iommu->name), "iommu%d", i);
598 INIT_LIST_HEAD(&iommu->windows);
411 599
412 iommu->mapped_base = ioremap(*base, 0x1000); 600 /* Obtain a window for it */
413 iommu->mapped_mmio_base = ioremap(*mmio_base, 0x1000); 601 cell_iommu_get_window(np, &base, &size);
414 602
415 enable_mapping(iommu->mapped_base, 603 pr_debug("\ttranslating window 0x%lx...0x%lx\n",
416 iommu->mapped_mmio_base); 604 base, base + size - 1);
417 605
418 /* everything else will be done in iommu_bus_setup */ 606 /* Initialize the hardware */
419 } 607 cell_iommu_setup_hardware(iommu, size);
420 608
421 return 1; 609 /* Setup the iommu_table */
610 cell_iommu_setup_window(iommu, np, base, size,
611 offset >> IOMMU_PAGE_SHIFT);
422} 612}
423 613
424static void *cell_alloc_coherent(struct device *hwdev, size_t size, 614static void __init cell_disable_iommus(void)
425 dma_addr_t *dma_handle, gfp_t flag)
426{ 615{
427 void *ret; 616 int node;
428 617 unsigned long base, val;
429 ret = (void *)__get_free_pages(flag, get_order(size)); 618 void __iomem *xregs, *cregs;
430 if (ret != NULL) { 619
431 memset(ret, 0, size); 620 /* Make sure IOC translation is disabled on all nodes */
432 *dma_handle = virt_to_abs(ret) | CELL_DMA_VALID; 621 for_each_online_node(node) {
622 if (cell_iommu_find_ioc(node, &base))
623 continue;
624 xregs = ioremap(base, IOC_Reg_Size);
625 if (xregs == NULL)
626 continue;
627 cregs = xregs + IOC_IOCmd_Offset;
628
629 pr_debug("iommu: cleaning up iommu on node %d\n", node);
630
631 out_be64(xregs + IOC_IOST_Origin, 0);
632 (void)in_be64(xregs + IOC_IOST_Origin);
633 val = in_be64(cregs + IOC_IOCmd_Cfg);
634 val &= ~IOC_IOCmd_Cfg_TE;
635 out_be64(cregs + IOC_IOCmd_Cfg, val);
636 (void)in_be64(cregs + IOC_IOCmd_Cfg);
637
638 iounmap(xregs);
433 } 639 }
434 return ret;
435} 640}
436 641
437static void cell_free_coherent(struct device *hwdev, size_t size, 642static int __init cell_iommu_init_disabled(void)
438 void *vaddr, dma_addr_t dma_handle)
439{ 643{
440 free_pages((unsigned long)vaddr, get_order(size)); 644 struct device_node *np = NULL;
441} 645 unsigned long base = 0, size;
646
647 /* When no iommu is present, we use direct DMA ops */
648 pci_dma_ops = &dma_direct_ops;
649
650 /* First make sure all IOC translation is turned off */
651 cell_disable_iommus();
652
653 /* If we have no Axon, we set up the spider DMA magic offset */
654 if (of_find_node_by_name(NULL, "axon") == NULL)
655 dma_direct_offset = SPIDER_DMA_OFFSET;
656
657 /* Now we need to check to see where the memory is mapped
658 * in PCI space. We assume that all busses use the same dma
659 * window which is always the case so far on Cell, thus we
660 * pick up the first pci-internal node we can find and check
661 * the DMA window from there.
662 */
663 for_each_node_by_name(np, "axon") {
664 if (np->parent == NULL || np->parent->parent != NULL)
665 continue;
666 if (cell_iommu_get_window(np, &base, &size) == 0)
667 break;
668 }
669 if (np == NULL) {
670 for_each_node_by_name(np, "pci-internal") {
671 if (np->parent == NULL || np->parent->parent != NULL)
672 continue;
673 if (cell_iommu_get_window(np, &base, &size) == 0)
674 break;
675 }
676 }
677 of_node_put(np);
678
679 /* If we found a DMA window, we check if it's big enough to enclose
680 * all of physical memory. If not, we force enable IOMMU
681 */
682 if (np && size < lmb_end_of_DRAM()) {
683 printk(KERN_WARNING "iommu: force-enabled, dma window"
684 " (%ldMB) smaller than total memory (%ldMB)\n",
685 size >> 20, lmb_end_of_DRAM() >> 20);
686 return -ENODEV;
687 }
442 688
443static dma_addr_t cell_map_single(struct device *hwdev, void *ptr, 689 dma_direct_offset += base;
444 size_t size, enum dma_data_direction direction)
445{
446 return virt_to_abs(ptr) | CELL_DMA_VALID;
447}
448 690
449static void cell_unmap_single(struct device *hwdev, dma_addr_t dma_addr, 691 printk("iommu: disabled, direct DMA offset is 0x%lx\n",
450 size_t size, enum dma_data_direction direction) 692 dma_direct_offset);
451{ 693
694 return 0;
452} 695}
453 696
454static int cell_map_sg(struct device *hwdev, struct scatterlist *sg, 697static int __init cell_iommu_init(void)
455 int nents, enum dma_data_direction direction)
456{ 698{
457 int i; 699 struct device_node *np;
700
701 if (!machine_is(cell))
702 return -ENODEV;
703
704 /* If IOMMU is disabled or we have little enough RAM to not need
705 * to enable it, we setup a direct mapping.
706 *
707 * Note: should we make sure we have the IOMMU actually disabled ?
708 */
709 if (iommu_is_off ||
710 (!iommu_force_on && lmb_end_of_DRAM() <= 0x80000000ull))
711 if (cell_iommu_init_disabled() == 0)
712 goto bail;
713
714 /* Setup various ppc_md. callbacks */
715 ppc_md.pci_dma_dev_setup = cell_pci_dma_dev_setup;
716 ppc_md.tce_build = tce_build_cell;
717 ppc_md.tce_free = tce_free_cell;
718
719 /* Create an iommu for each /axon node. */
720 for_each_node_by_name(np, "axon") {
721 if (np->parent == NULL || np->parent->parent != NULL)
722 continue;
723 cell_iommu_init_one(np, 0);
724 }
458 725
459 for (i = 0; i < nents; i++, sg++) { 726 /* Create an iommu for each toplevel /pci-internal node for
460 sg->dma_address = (page_to_phys(sg->page) + sg->offset) 727 * old hardware/firmware
461 | CELL_DMA_VALID; 728 */
462 sg->dma_length = sg->length; 729 for_each_node_by_name(np, "pci-internal") {
730 if (np->parent == NULL || np->parent->parent != NULL)
731 continue;
732 cell_iommu_init_one(np, SPIDER_DMA_OFFSET);
463 } 733 }
464 734
465 return nents; 735 /* Setup default PCI iommu ops */
466} 736 pci_dma_ops = &dma_iommu_ops;
467 737
468static void cell_unmap_sg(struct device *hwdev, struct scatterlist *sg, 738 bail:
469 int nents, enum dma_data_direction direction) 739 /* Register callbacks on OF platform device addition/removal
470{ 740 * to handle linking them to the right DMA operations
471} 741 */
742 bus_register_notifier(&of_platform_bus_type, &cell_of_bus_notifier);
472 743
473static int cell_dma_supported(struct device *dev, u64 mask) 744 return 0;
474{
475 return mask < 0x100000000ull;
476} 745}
746arch_initcall(cell_iommu_init);
477 747
478static struct dma_mapping_ops cell_iommu_ops = {
479 .alloc_coherent = cell_alloc_coherent,
480 .free_coherent = cell_free_coherent,
481 .map_single = cell_map_single,
482 .unmap_single = cell_unmap_single,
483 .map_sg = cell_map_sg,
484 .unmap_sg = cell_unmap_sg,
485 .dma_supported = cell_dma_supported,
486};
487
488void cell_init_iommu(void)
489{
490 int setup_bus = 0;
491
492 if (of_find_node_by_path("/mambo")) {
493 pr_info("Not using iommu on systemsim\n");
494 } else {
495
496 if (!(of_chosen &&
497 get_property(of_chosen, "linux,iommu-off", NULL)))
498 setup_bus = cell_map_iommu();
499
500 if (setup_bus) {
501 pr_debug("%s: IOMMU mapping activated\n", __FUNCTION__);
502 ppc_md.iommu_dev_setup = iommu_dev_setup_null;
503 ppc_md.iommu_bus_setup = iommu_bus_setup;
504 } else {
505 pr_debug("%s: IOMMU mapping activated, "
506 "no device action necessary\n", __FUNCTION__);
507 /* Direct I/O, IOMMU off */
508 ppc_md.iommu_dev_setup = iommu_dev_setup_null;
509 ppc_md.iommu_bus_setup = iommu_bus_setup_null;
510 }
511 }
512
513 pci_dma_ops = cell_iommu_ops;
514}
diff --git a/arch/powerpc/platforms/cell/iommu.h b/arch/powerpc/platforms/cell/iommu.h
deleted file mode 100644
index 490d77abfe85..000000000000
--- a/arch/powerpc/platforms/cell/iommu.h
+++ /dev/null
@@ -1,65 +0,0 @@
1#ifndef CELL_IOMMU_H
2#define CELL_IOMMU_H
3
4/* some constants */
5enum {
6 /* segment table entries */
7 IOST_VALID_MASK = 0x8000000000000000ul,
8 IOST_TAG_MASK = 0x3000000000000000ul,
9 IOST_PT_BASE_MASK = 0x000003fffffff000ul,
10 IOST_NNPT_MASK = 0x0000000000000fe0ul,
11 IOST_PS_MASK = 0x000000000000000ful,
12
13 IOST_PS_4K = 0x1,
14 IOST_PS_64K = 0x3,
15 IOST_PS_1M = 0x5,
16 IOST_PS_16M = 0x7,
17
18 /* iopt tag register */
19 IOPT_VALID_MASK = 0x0000000200000000ul,
20 IOPT_TAG_MASK = 0x00000001fffffffful,
21
22 /* iopt cache register */
23 IOPT_PROT_MASK = 0xc000000000000000ul,
24 IOPT_PROT_NONE = 0x0000000000000000ul,
25 IOPT_PROT_READ = 0x4000000000000000ul,
26 IOPT_PROT_WRITE = 0x8000000000000000ul,
27 IOPT_PROT_RW = 0xc000000000000000ul,
28 IOPT_COHERENT = 0x2000000000000000ul,
29
30 IOPT_ORDER_MASK = 0x1800000000000000ul,
31 /* order access to same IOID/VC on same address */
32 IOPT_ORDER_ADDR = 0x0800000000000000ul,
33 /* similar, but only after a write access */
34 IOPT_ORDER_WRITES = 0x1000000000000000ul,
35 /* Order all accesses to same IOID/VC */
36 IOPT_ORDER_VC = 0x1800000000000000ul,
37
38 IOPT_RPN_MASK = 0x000003fffffff000ul,
39 IOPT_HINT_MASK = 0x0000000000000800ul,
40 IOPT_IOID_MASK = 0x00000000000007fful,
41
42 IOSTO_ENABLE = 0x8000000000000000ul,
43 IOSTO_ORIGIN = 0x000003fffffff000ul,
44 IOSTO_HW = 0x0000000000000800ul,
45 IOSTO_SW = 0x0000000000000400ul,
46
47 IOCMD_CONF_TE = 0x0000800000000000ul,
48
49 /* memory mapped registers */
50 IOC_PT_CACHE_DIR = 0x000,
51 IOC_ST_CACHE_DIR = 0x800,
52 IOC_PT_CACHE_REG = 0x910,
53 IOC_ST_ORIGIN = 0x918,
54 IOC_CONF = 0x930,
55
56 /* The high bit needs to be set on every DMA address,
57 only 2GB are addressable */
58 CELL_DMA_VALID = 0x80000000,
59 CELL_DMA_MASK = 0x7fffffff,
60};
61
62
63void cell_init_iommu(void);
64
65#endif
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
index 9f2e4ed20a57..8c20f0fb8651 100644
--- a/arch/powerpc/platforms/cell/pervasive.c
+++ b/arch/powerpc/platforms/cell/pervasive.c
@@ -38,32 +38,25 @@
38#include "pervasive.h" 38#include "pervasive.h"
39#include "cbe_regs.h" 39#include "cbe_regs.h"
40 40
41static DEFINE_SPINLOCK(cbe_pervasive_lock); 41static void cbe_power_save(void)
42
43static void __init cbe_enable_pause_zero(void)
44{ 42{
45 unsigned long thread_switch_control; 43 unsigned long ctrl, thread_switch_control;
46 unsigned long temp_register;
47 struct cbe_pmd_regs __iomem *pregs;
48
49 spin_lock_irq(&cbe_pervasive_lock);
50 pregs = cbe_get_cpu_pmd_regs(smp_processor_id());
51 if (pregs == NULL)
52 goto out;
53 44
54 pr_debug("Power Management: CPU %d\n", smp_processor_id()); 45 /*
55 46 * We need to hard disable interrupts, but we also need to mark them
56 /* Enable Pause(0) control bit */ 47 * hard disabled in the PACA so that the local_irq_enable() done by
57 temp_register = in_be64(&pregs->pm_control); 48 * our caller upon return propertly hard enables.
49 */
50 hard_irq_disable();
51 get_paca()->hard_enabled = 0;
58 52
59 out_be64(&pregs->pm_control, 53 ctrl = mfspr(SPRN_CTRLF);
60 temp_register | CBE_PMD_PAUSE_ZERO_CONTROL);
61 54
62 /* Enable DEC and EE interrupt request */ 55 /* Enable DEC and EE interrupt request */
63 thread_switch_control = mfspr(SPRN_TSC_CELL); 56 thread_switch_control = mfspr(SPRN_TSC_CELL);
64 thread_switch_control |= TSC_CELL_EE_ENABLE | TSC_CELL_EE_BOOST; 57 thread_switch_control |= TSC_CELL_EE_ENABLE | TSC_CELL_EE_BOOST;
65 58
66 switch ((mfspr(SPRN_CTRLF) & CTRL_CT)) { 59 switch (ctrl & CTRL_CT) {
67 case CTRL_CT0: 60 case CTRL_CT0:
68 thread_switch_control |= TSC_CELL_DEC_ENABLE_0; 61 thread_switch_control |= TSC_CELL_DEC_ENABLE_0;
69 break; 62 break;
@@ -75,58 +68,21 @@ static void __init cbe_enable_pause_zero(void)
75 __FUNCTION__); 68 __FUNCTION__);
76 break; 69 break;
77 } 70 }
78
79 mtspr(SPRN_TSC_CELL, thread_switch_control); 71 mtspr(SPRN_TSC_CELL, thread_switch_control);
80 72
81out: 73 /*
82 spin_unlock_irq(&cbe_pervasive_lock); 74 * go into low thread priority, medium priority will be
83} 75 * restored for us after wake-up.
84 76 */
85static void cbe_idle(void) 77 HMT_low();
86{
87 unsigned long ctrl;
88 78
89 /* Why do we do that on every idle ? Couldn't that be done once for 79 /*
90 * all or do we lose the state some way ? Also, the pm_control 80 * atomically disable thread execution and runlatch.
91 * register setting, that can't be set once at boot ? We really want 81 * External and Decrementer exceptions are still handled when the
92 * to move that away in order to implement a simple powersave 82 * thread is disabled but now enter in cbe_system_reset_exception()
93 */ 83 */
94 cbe_enable_pause_zero(); 84 ctrl &= ~(CTRL_RUNLATCH | CTRL_TE);
95 85 mtspr(SPRN_CTRLT, ctrl);
96 while (1) {
97 if (!need_resched()) {
98 local_irq_disable();
99 while (!need_resched()) {
100 /* go into low thread priority */
101 HMT_low();
102
103 /*
104 * atomically disable thread execution
105 * and runlatch.
106 * External and Decrementer exceptions
107 * are still handled when the thread
108 * is disabled but now enter in
109 * cbe_system_reset_exception()
110 */
111 ctrl = mfspr(SPRN_CTRLF);
112 ctrl &= ~(CTRL_RUNLATCH | CTRL_TE);
113 mtspr(SPRN_CTRLT, ctrl);
114 }
115 /* restore thread prio */
116 HMT_medium();
117 local_irq_enable();
118 }
119
120 /*
121 * turn runlatch on again before scheduling the
122 * process we just woke up
123 */
124 ppc64_runlatch_on();
125
126 preempt_enable_no_resched();
127 schedule();
128 preempt_disable();
129 }
130} 86}
131 87
132static int cbe_system_reset_exception(struct pt_regs *regs) 88static int cbe_system_reset_exception(struct pt_regs *regs)
@@ -158,9 +114,20 @@ static int cbe_system_reset_exception(struct pt_regs *regs)
158 114
159void __init cbe_pervasive_init(void) 115void __init cbe_pervasive_init(void)
160{ 116{
117 int cpu;
161 if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO)) 118 if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO))
162 return; 119 return;
163 120
164 ppc_md.idle_loop = cbe_idle; 121 for_each_possible_cpu(cpu) {
122 struct cbe_pmd_regs __iomem *regs = cbe_get_cpu_pmd_regs(cpu);
123 if (!regs)
124 continue;
125
126 /* Enable Pause(0) control bit */
127 out_be64(&regs->pmcr, in_be64(&regs->pmcr) |
128 CBE_PMD_PAUSE_ZERO_CONTROL);
129 }
130
131 ppc_md.power_save = cbe_power_save;
165 ppc_md.system_reset_exception = cbe_system_reset_exception; 132 ppc_md.system_reset_exception = cbe_system_reset_exception;
166} 133}
diff --git a/arch/powerpc/platforms/cell/pmu.c b/arch/powerpc/platforms/cell/pmu.c
new file mode 100644
index 000000000000..99c612025e8f
--- /dev/null
+++ b/arch/powerpc/platforms/cell/pmu.c
@@ -0,0 +1,429 @@
1/*
2 * Cell Broadband Engine Performance Monitor
3 *
4 * (C) Copyright IBM Corporation 2001,2006
5 *
6 * Author:
7 * David Erb (djerb@us.ibm.com)
8 * Kevin Corry (kevcorry@us.ibm.com)
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25#include <linux/interrupt.h>
26#include <linux/types.h>
27#include <asm/io.h>
28#include <asm/irq_regs.h>
29#include <asm/machdep.h>
30#include <asm/pmc.h>
31#include <asm/reg.h>
32#include <asm/spu.h>
33
34#include "cbe_regs.h"
35#include "interrupt.h"
36
37/*
38 * When writing to write-only mmio addresses, save a shadow copy. All of the
39 * registers are 32-bit, but stored in the upper-half of a 64-bit field in
40 * pmd_regs.
41 */
42
43#define WRITE_WO_MMIO(reg, x) \
44 do { \
45 u32 _x = (x); \
46 struct cbe_pmd_regs __iomem *pmd_regs; \
47 struct cbe_pmd_shadow_regs *shadow_regs; \
48 pmd_regs = cbe_get_cpu_pmd_regs(cpu); \
49 shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu); \
50 out_be64(&(pmd_regs->reg), (((u64)_x) << 32)); \
51 shadow_regs->reg = _x; \
52 } while (0)
53
54#define READ_SHADOW_REG(val, reg) \
55 do { \
56 struct cbe_pmd_shadow_regs *shadow_regs; \
57 shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu); \
58 (val) = shadow_regs->reg; \
59 } while (0)
60
61#define READ_MMIO_UPPER32(val, reg) \
62 do { \
63 struct cbe_pmd_regs __iomem *pmd_regs; \
64 pmd_regs = cbe_get_cpu_pmd_regs(cpu); \
65 (val) = (u32)(in_be64(&pmd_regs->reg) >> 32); \
66 } while (0)
67
68/*
69 * Physical counter registers.
70 * Each physical counter can act as one 32-bit counter or two 16-bit counters.
71 */
72
73u32 cbe_read_phys_ctr(u32 cpu, u32 phys_ctr)
74{
75 u32 val_in_latch, val = 0;
76
77 if (phys_ctr < NR_PHYS_CTRS) {
78 READ_SHADOW_REG(val_in_latch, counter_value_in_latch);
79
80 /* Read the latch or the actual counter, whichever is newer. */
81 if (val_in_latch & (1 << phys_ctr)) {
82 READ_SHADOW_REG(val, pm_ctr[phys_ctr]);
83 } else {
84 READ_MMIO_UPPER32(val, pm_ctr[phys_ctr]);
85 }
86 }
87
88 return val;
89}
90EXPORT_SYMBOL_GPL(cbe_read_phys_ctr);
91
92void cbe_write_phys_ctr(u32 cpu, u32 phys_ctr, u32 val)
93{
94 struct cbe_pmd_shadow_regs *shadow_regs;
95 u32 pm_ctrl;
96
97 if (phys_ctr < NR_PHYS_CTRS) {
98 /* Writing to a counter only writes to a hardware latch.
99 * The new value is not propagated to the actual counter
100 * until the performance monitor is enabled.
101 */
102 WRITE_WO_MMIO(pm_ctr[phys_ctr], val);
103
104 pm_ctrl = cbe_read_pm(cpu, pm_control);
105 if (pm_ctrl & CBE_PM_ENABLE_PERF_MON) {
106 /* The counters are already active, so we need to
107 * rewrite the pm_control register to "re-enable"
108 * the PMU.
109 */
110 cbe_write_pm(cpu, pm_control, pm_ctrl);
111 } else {
112 shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu);
113 shadow_regs->counter_value_in_latch |= (1 << phys_ctr);
114 }
115 }
116}
117EXPORT_SYMBOL_GPL(cbe_write_phys_ctr);
118
119/*
120 * "Logical" counter registers.
121 * These will read/write 16-bits or 32-bits depending on the
122 * current size of the counter. Counters 4 - 7 are always 16-bit.
123 */
124
125u32 cbe_read_ctr(u32 cpu, u32 ctr)
126{
127 u32 val;
128 u32 phys_ctr = ctr & (NR_PHYS_CTRS - 1);
129
130 val = cbe_read_phys_ctr(cpu, phys_ctr);
131
132 if (cbe_get_ctr_size(cpu, phys_ctr) == 16)
133 val = (ctr < NR_PHYS_CTRS) ? (val >> 16) : (val & 0xffff);
134
135 return val;
136}
137EXPORT_SYMBOL_GPL(cbe_read_ctr);
138
139void cbe_write_ctr(u32 cpu, u32 ctr, u32 val)
140{
141 u32 phys_ctr;
142 u32 phys_val;
143
144 phys_ctr = ctr & (NR_PHYS_CTRS - 1);
145
146 if (cbe_get_ctr_size(cpu, phys_ctr) == 16) {
147 phys_val = cbe_read_phys_ctr(cpu, phys_ctr);
148
149 if (ctr < NR_PHYS_CTRS)
150 val = (val << 16) | (phys_val & 0xffff);
151 else
152 val = (val & 0xffff) | (phys_val & 0xffff0000);
153 }
154
155 cbe_write_phys_ctr(cpu, phys_ctr, val);
156}
157EXPORT_SYMBOL_GPL(cbe_write_ctr);
158
159/*
160 * Counter-control registers.
161 * Each "logical" counter has a corresponding control register.
162 */
163
164u32 cbe_read_pm07_control(u32 cpu, u32 ctr)
165{
166 u32 pm07_control = 0;
167
168 if (ctr < NR_CTRS)
169 READ_SHADOW_REG(pm07_control, pm07_control[ctr]);
170
171 return pm07_control;
172}
173EXPORT_SYMBOL_GPL(cbe_read_pm07_control);
174
175void cbe_write_pm07_control(u32 cpu, u32 ctr, u32 val)
176{
177 if (ctr < NR_CTRS)
178 WRITE_WO_MMIO(pm07_control[ctr], val);
179}
180EXPORT_SYMBOL_GPL(cbe_write_pm07_control);
181
182/*
183 * Other PMU control registers. Most of these are write-only.
184 */
185
186u32 cbe_read_pm(u32 cpu, enum pm_reg_name reg)
187{
188 u32 val = 0;
189
190 switch (reg) {
191 case group_control:
192 READ_SHADOW_REG(val, group_control);
193 break;
194
195 case debug_bus_control:
196 READ_SHADOW_REG(val, debug_bus_control);
197 break;
198
199 case trace_address:
200 READ_MMIO_UPPER32(val, trace_address);
201 break;
202
203 case ext_tr_timer:
204 READ_SHADOW_REG(val, ext_tr_timer);
205 break;
206
207 case pm_status:
208 READ_MMIO_UPPER32(val, pm_status);
209 break;
210
211 case pm_control:
212 READ_SHADOW_REG(val, pm_control);
213 break;
214
215 case pm_interval:
216 READ_SHADOW_REG(val, pm_interval);
217 break;
218
219 case pm_start_stop:
220 READ_SHADOW_REG(val, pm_start_stop);
221 break;
222 }
223
224 return val;
225}
226EXPORT_SYMBOL_GPL(cbe_read_pm);
227
228void cbe_write_pm(u32 cpu, enum pm_reg_name reg, u32 val)
229{
230 switch (reg) {
231 case group_control:
232 WRITE_WO_MMIO(group_control, val);
233 break;
234
235 case debug_bus_control:
236 WRITE_WO_MMIO(debug_bus_control, val);
237 break;
238
239 case trace_address:
240 WRITE_WO_MMIO(trace_address, val);
241 break;
242
243 case ext_tr_timer:
244 WRITE_WO_MMIO(ext_tr_timer, val);
245 break;
246
247 case pm_status:
248 WRITE_WO_MMIO(pm_status, val);
249 break;
250
251 case pm_control:
252 WRITE_WO_MMIO(pm_control, val);
253 break;
254
255 case pm_interval:
256 WRITE_WO_MMIO(pm_interval, val);
257 break;
258
259 case pm_start_stop:
260 WRITE_WO_MMIO(pm_start_stop, val);
261 break;
262 }
263}
264EXPORT_SYMBOL_GPL(cbe_write_pm);
265
266/*
267 * Get/set the size of a physical counter to either 16 or 32 bits.
268 */
269
270u32 cbe_get_ctr_size(u32 cpu, u32 phys_ctr)
271{
272 u32 pm_ctrl, size = 0;
273
274 if (phys_ctr < NR_PHYS_CTRS) {
275 pm_ctrl = cbe_read_pm(cpu, pm_control);
276 size = (pm_ctrl & CBE_PM_16BIT_CTR(phys_ctr)) ? 16 : 32;
277 }
278
279 return size;
280}
281EXPORT_SYMBOL_GPL(cbe_get_ctr_size);
282
283void cbe_set_ctr_size(u32 cpu, u32 phys_ctr, u32 ctr_size)
284{
285 u32 pm_ctrl;
286
287 if (phys_ctr < NR_PHYS_CTRS) {
288 pm_ctrl = cbe_read_pm(cpu, pm_control);
289 switch (ctr_size) {
290 case 16:
291 pm_ctrl |= CBE_PM_16BIT_CTR(phys_ctr);
292 break;
293
294 case 32:
295 pm_ctrl &= ~CBE_PM_16BIT_CTR(phys_ctr);
296 break;
297 }
298 cbe_write_pm(cpu, pm_control, pm_ctrl);
299 }
300}
301EXPORT_SYMBOL_GPL(cbe_set_ctr_size);
302
303/*
304 * Enable/disable the entire performance monitoring unit.
305 * When we enable the PMU, all pending writes to counters get committed.
306 */
307
308void cbe_enable_pm(u32 cpu)
309{
310 struct cbe_pmd_shadow_regs *shadow_regs;
311 u32 pm_ctrl;
312
313 shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu);
314 shadow_regs->counter_value_in_latch = 0;
315
316 pm_ctrl = cbe_read_pm(cpu, pm_control) | CBE_PM_ENABLE_PERF_MON;
317 cbe_write_pm(cpu, pm_control, pm_ctrl);
318}
319EXPORT_SYMBOL_GPL(cbe_enable_pm);
320
321void cbe_disable_pm(u32 cpu)
322{
323 u32 pm_ctrl;
324 pm_ctrl = cbe_read_pm(cpu, pm_control) & ~CBE_PM_ENABLE_PERF_MON;
325 cbe_write_pm(cpu, pm_control, pm_ctrl);
326}
327EXPORT_SYMBOL_GPL(cbe_disable_pm);
328
329/*
330 * Reading from the trace_buffer.
331 * The trace buffer is two 64-bit registers. Reading from
332 * the second half automatically increments the trace_address.
333 */
334
335void cbe_read_trace_buffer(u32 cpu, u64 *buf)
336{
337 struct cbe_pmd_regs __iomem *pmd_regs = cbe_get_cpu_pmd_regs(cpu);
338
339 *buf++ = in_be64(&pmd_regs->trace_buffer_0_63);
340 *buf++ = in_be64(&pmd_regs->trace_buffer_64_127);
341}
342EXPORT_SYMBOL_GPL(cbe_read_trace_buffer);
343
344/*
345 * Enabling/disabling interrupts for the entire performance monitoring unit.
346 */
347
348u32 cbe_query_pm_interrupts(u32 cpu)
349{
350 return cbe_read_pm(cpu, pm_status);
351}
352EXPORT_SYMBOL_GPL(cbe_query_pm_interrupts);
353
354u32 cbe_clear_pm_interrupts(u32 cpu)
355{
356 /* Reading pm_status clears the interrupt bits. */
357 return cbe_query_pm_interrupts(cpu);
358}
359EXPORT_SYMBOL_GPL(cbe_clear_pm_interrupts);
360
361void cbe_enable_pm_interrupts(u32 cpu, u32 thread, u32 mask)
362{
363 /* Set which node and thread will handle the next interrupt. */
364 iic_set_interrupt_routing(cpu, thread, 0);
365
366 /* Enable the interrupt bits in the pm_status register. */
367 if (mask)
368 cbe_write_pm(cpu, pm_status, mask);
369}
370EXPORT_SYMBOL_GPL(cbe_enable_pm_interrupts);
371
372void cbe_disable_pm_interrupts(u32 cpu)
373{
374 cbe_clear_pm_interrupts(cpu);
375 cbe_write_pm(cpu, pm_status, 0);
376}
377EXPORT_SYMBOL_GPL(cbe_disable_pm_interrupts);
378
379static irqreturn_t cbe_pm_irq(int irq, void *dev_id)
380{
381 perf_irq(get_irq_regs());
382 return IRQ_HANDLED;
383}
384
385int __init cbe_init_pm_irq(void)
386{
387 unsigned int irq;
388 int rc, node;
389
390 for_each_node(node) {
391 irq = irq_create_mapping(NULL, IIC_IRQ_IOEX_PMI |
392 (node << IIC_IRQ_NODE_SHIFT));
393 if (irq == NO_IRQ) {
394 printk("ERROR: Unable to allocate irq for node %d\n",
395 node);
396 return -EINVAL;
397 }
398
399 rc = request_irq(irq, cbe_pm_irq,
400 IRQF_DISABLED, "cbe-pmu-0", NULL);
401 if (rc) {
402 printk("ERROR: Request for irq on node %d failed\n",
403 node);
404 return rc;
405 }
406 }
407
408 return 0;
409}
410arch_initcall(cbe_init_pm_irq);
411
412void cbe_sync_irq(int node)
413{
414 unsigned int irq;
415
416 irq = irq_find_mapping(NULL,
417 IIC_IRQ_IOEX_PMI
418 | (node << IIC_IRQ_NODE_SHIFT));
419
420 if (irq == NO_IRQ) {
421 printk(KERN_WARNING "ERROR, unable to get existing irq %d " \
422 "for node %d\n", irq, node);
423 return;
424 }
425
426 synchronize_irq(irq);
427}
428EXPORT_SYMBOL_GPL(cbe_sync_irq);
429
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index 22c228a49c33..36989c2eee66 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -50,9 +50,10 @@
50#include <asm/spu.h> 50#include <asm/spu.h>
51#include <asm/spu_priv1.h> 51#include <asm/spu_priv1.h>
52#include <asm/udbg.h> 52#include <asm/udbg.h>
53#include <asm/mpic.h>
54#include <asm/of_platform.h>
53 55
54#include "interrupt.h" 56#include "interrupt.h"
55#include "iommu.h"
56#include "cbe_regs.h" 57#include "cbe_regs.h"
57#include "pervasive.h" 58#include "pervasive.h"
58#include "ras.h" 59#include "ras.h"
@@ -80,24 +81,72 @@ static void cell_progress(char *s, unsigned short hex)
80 printk("*** %04x : %s\n", hex, s ? s : ""); 81 printk("*** %04x : %s\n", hex, s ? s : "");
81} 82}
82 83
83static void __init cell_pcibios_fixup(void) 84static int __init cell_publish_devices(void)
84{ 85{
85 struct pci_dev *dev = NULL; 86 if (!machine_is(cell))
87 return 0;
88
89 /* Publish OF platform devices for southbridge IOs */
90 of_platform_bus_probe(NULL, NULL, NULL);
91
92 return 0;
93}
94device_initcall(cell_publish_devices);
95
96static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc)
97{
98 struct mpic *mpic = desc->handler_data;
99 unsigned int virq;
100
101 virq = mpic_get_one_irq(mpic);
102 if (virq != NO_IRQ)
103 generic_handle_irq(virq);
104 desc->chip->eoi(irq);
105}
86 106
87 for_each_pci_dev(dev) 107static void __init mpic_init_IRQ(void)
88 pci_read_irq_line(dev); 108{
109 struct device_node *dn;
110 struct mpic *mpic;
111 unsigned int virq;
112
113 for (dn = NULL;
114 (dn = of_find_node_by_name(dn, "interrupt-controller"));) {
115 if (!device_is_compatible(dn, "CBEA,platform-open-pic"))
116 continue;
117
118 /* The MPIC driver will get everything it needs from the
119 * device-tree, just pass 0 to all arguments
120 */
121 mpic = mpic_alloc(dn, 0, 0, 0, 0, " MPIC ");
122 if (mpic == NULL)
123 continue;
124 mpic_init(mpic);
125
126 virq = irq_of_parse_and_map(dn, 0);
127 if (virq == NO_IRQ)
128 continue;
129
130 printk(KERN_INFO "%s : hooking up to IRQ %d\n",
131 dn->full_name, virq);
132 set_irq_data(virq, mpic);
133 set_irq_chained_handler(virq, cell_mpic_cascade);
134 }
89} 135}
90 136
137
91static void __init cell_init_irq(void) 138static void __init cell_init_irq(void)
92{ 139{
93 iic_init_IRQ(); 140 iic_init_IRQ();
94 spider_init_IRQ(); 141 spider_init_IRQ();
142 mpic_init_IRQ();
95} 143}
96 144
97static void __init cell_setup_arch(void) 145static void __init cell_setup_arch(void)
98{ 146{
99#ifdef CONFIG_SPU_BASE 147#ifdef CONFIG_SPU_BASE
100 spu_priv1_ops = &spu_priv1_mmio_ops; 148 spu_priv1_ops = &spu_priv1_mmio_ops;
149 spu_management_ops = &spu_management_of_ops;
101#endif 150#endif
102 151
103 cbe_regs_init(); 152 cbe_regs_init();
@@ -109,7 +158,6 @@ static void __init cell_setup_arch(void)
109#ifdef CONFIG_SMP 158#ifdef CONFIG_SMP
110 smp_init_cell(); 159 smp_init_cell();
111#endif 160#endif
112
113 /* init to some ~sane value until calibrate_delay() runs */ 161 /* init to some ~sane value until calibrate_delay() runs */
114 loops_per_jiffy = 50000000; 162 loops_per_jiffy = 50000000;
115 163
@@ -129,19 +177,6 @@ static void __init cell_setup_arch(void)
129 mmio_nvram_init(); 177 mmio_nvram_init();
130} 178}
131 179
132/*
133 * Early initialization. Relocation is on but do not reference unbolted pages
134 */
135static void __init cell_init_early(void)
136{
137 DBG(" -> cell_init_early()\n");
138
139 cell_init_iommu();
140
141 DBG(" <- cell_init_early()\n");
142}
143
144
145static int __init cell_probe(void) 180static int __init cell_probe(void)
146{ 181{
147 unsigned long root = of_get_flat_dt_root(); 182 unsigned long root = of_get_flat_dt_root();
@@ -168,7 +203,6 @@ define_machine(cell) {
168 .name = "Cell", 203 .name = "Cell",
169 .probe = cell_probe, 204 .probe = cell_probe,
170 .setup_arch = cell_setup_arch, 205 .setup_arch = cell_setup_arch,
171 .init_early = cell_init_early,
172 .show_cpuinfo = cell_show_cpuinfo, 206 .show_cpuinfo = cell_show_cpuinfo,
173 .restart = rtas_restart, 207 .restart = rtas_restart,
174 .power_off = rtas_power_off, 208 .power_off = rtas_power_off,
@@ -180,7 +214,7 @@ define_machine(cell) {
180 .check_legacy_ioport = cell_check_legacy_ioport, 214 .check_legacy_ioport = cell_check_legacy_ioport,
181 .progress = cell_progress, 215 .progress = cell_progress,
182 .init_IRQ = cell_init_irq, 216 .init_IRQ = cell_init_irq,
183 .pcibios_fixup = cell_pcibios_fixup, 217 .pci_setup_phb = rtas_setup_phb,
184#ifdef CONFIG_KEXEC 218#ifdef CONFIG_KEXEC
185 .machine_kexec = default_machine_kexec, 219 .machine_kexec = default_machine_kexec,
186 .machine_kexec_prepare = default_machine_kexec_prepare, 220 .machine_kexec_prepare = default_machine_kexec_prepare,
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index 7aa809d5a244..bd7bffc3ddd0 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -25,22 +25,17 @@
25#include <linux/interrupt.h> 25#include <linux/interrupt.h>
26#include <linux/list.h> 26#include <linux/list.h>
27#include <linux/module.h> 27#include <linux/module.h>
28#include <linux/pci.h>
29#include <linux/poll.h>
30#include <linux/ptrace.h> 28#include <linux/ptrace.h>
31#include <linux/slab.h> 29#include <linux/slab.h>
32#include <linux/wait.h> 30#include <linux/wait.h>
33 31#include <linux/mm.h>
34#include <asm/firmware.h> 32#include <linux/io.h>
35#include <asm/io.h>
36#include <asm/prom.h>
37#include <linux/mutex.h> 33#include <linux/mutex.h>
38#include <asm/spu.h> 34#include <asm/spu.h>
39#include <asm/spu_priv1.h> 35#include <asm/spu_priv1.h>
40#include <asm/mmu_context.h> 36#include <asm/xmon.h>
41
42#include "interrupt.h"
43 37
38const struct spu_management_ops *spu_management_ops;
44const struct spu_priv1_ops *spu_priv1_ops; 39const struct spu_priv1_ops *spu_priv1_ops;
45 40
46EXPORT_SYMBOL_GPL(spu_priv1_ops); 41EXPORT_SYMBOL_GPL(spu_priv1_ops);
@@ -89,7 +84,30 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
89 printk("%s: invalid access during switch!\n", __func__); 84 printk("%s: invalid access during switch!\n", __func__);
90 return 1; 85 return 1;
91 } 86 }
92 if (!mm || (REGION_ID(ea) != USER_REGION_ID)) { 87 esid = (ea & ESID_MASK) | SLB_ESID_V;
88
89 switch(REGION_ID(ea)) {
90 case USER_REGION_ID:
91#ifdef CONFIG_HUGETLB_PAGE
92 if (in_hugepage_area(mm->context, ea))
93 llp = mmu_psize_defs[mmu_huge_psize].sllp;
94 else
95#endif
96 llp = mmu_psize_defs[mmu_virtual_psize].sllp;
97 vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) |
98 SLB_VSID_USER | llp;
99 break;
100 case VMALLOC_REGION_ID:
101 llp = mmu_psize_defs[mmu_virtual_psize].sllp;
102 vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) |
103 SLB_VSID_KERNEL | llp;
104 break;
105 case KERNEL_REGION_ID:
106 llp = mmu_psize_defs[mmu_linear_psize].sllp;
107 vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) |
108 SLB_VSID_KERNEL | llp;
109 break;
110 default:
93 /* Future: support kernel segments so that drivers 111 /* Future: support kernel segments so that drivers
94 * can use SPUs. 112 * can use SPUs.
95 */ 113 */
@@ -97,16 +115,6 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
97 return 1; 115 return 1;
98 } 116 }
99 117
100 esid = (ea & ESID_MASK) | SLB_ESID_V;
101#ifdef CONFIG_HUGETLB_PAGE
102 if (in_hugepage_area(mm->context, ea))
103 llp = mmu_psize_defs[mmu_huge_psize].sllp;
104 else
105#endif
106 llp = mmu_psize_defs[mmu_virtual_psize].sllp;
107 vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) |
108 SLB_VSID_USER | llp;
109
110 out_be64(&priv2->slb_index_W, spu->slb_replace); 118 out_be64(&priv2->slb_index_W, spu->slb_replace);
111 out_be64(&priv2->slb_vsid_RW, vsid); 119 out_be64(&priv2->slb_vsid_RW, vsid);
112 out_be64(&priv2->slb_esid_RW, esid); 120 out_be64(&priv2->slb_esid_RW, esid);
@@ -320,6 +328,7 @@ static void spu_free_irqs(struct spu *spu)
320} 328}
321 329
322static struct list_head spu_list[MAX_NUMNODES]; 330static struct list_head spu_list[MAX_NUMNODES];
331static LIST_HEAD(spu_full_list);
323static DEFINE_MUTEX(spu_mutex); 332static DEFINE_MUTEX(spu_mutex);
324 333
325static void spu_init_channels(struct spu *spu) 334static void spu_init_channels(struct spu *spu)
@@ -364,8 +373,7 @@ struct spu *spu_alloc_node(int node)
364 if (!list_empty(&spu_list[node])) { 373 if (!list_empty(&spu_list[node])) {
365 spu = list_entry(spu_list[node].next, struct spu, list); 374 spu = list_entry(spu_list[node].next, struct spu, list);
366 list_del_init(&spu->list); 375 list_del_init(&spu->list);
367 pr_debug("Got SPU %x %d %d\n", 376 pr_debug("Got SPU %d %d\n", spu->number, spu->node);
368 spu->isrc, spu->number, spu->node);
369 spu_init_channels(spu); 377 spu_init_channels(spu);
370 } 378 }
371 mutex_unlock(&spu_mutex); 379 mutex_unlock(&spu_mutex);
@@ -493,280 +501,65 @@ int spu_irq_class_1_bottom(struct spu *spu)
493 if (!error) { 501 if (!error) {
494 spu_restart_dma(spu); 502 spu_restart_dma(spu);
495 } else { 503 } else {
496 __spu_trap_invalid_dma(spu); 504 spu->dma_callback(spu, SPE_EVENT_SPE_DATA_STORAGE);
497 } 505 }
498 return ret; 506 return ret;
499} 507}
500 508
501static int __init find_spu_node_id(struct device_node *spe) 509struct sysdev_class spu_sysdev_class = {
502{ 510 set_kset_name("spu")
503 const unsigned int *id; 511};
504 struct device_node *cpu;
505 cpu = spe->parent->parent;
506 id = get_property(cpu, "node-id", NULL);
507 return id ? *id : 0;
508}
509
510static int __init cell_spuprop_present(struct spu *spu, struct device_node *spe,
511 const char *prop)
512{
513 static DEFINE_MUTEX(add_spumem_mutex);
514
515 const struct address_prop {
516 unsigned long address;
517 unsigned int len;
518 } __attribute__((packed)) *p;
519 int proplen;
520
521 unsigned long start_pfn, nr_pages;
522 struct pglist_data *pgdata;
523 struct zone *zone;
524 int ret;
525
526 p = get_property(spe, prop, &proplen);
527 WARN_ON(proplen != sizeof (*p));
528
529 start_pfn = p->address >> PAGE_SHIFT;
530 nr_pages = ((unsigned long)p->len + PAGE_SIZE - 1) >> PAGE_SHIFT;
531
532 pgdata = NODE_DATA(spu->nid);
533 zone = pgdata->node_zones;
534
535 /* XXX rethink locking here */
536 mutex_lock(&add_spumem_mutex);
537 ret = __add_pages(zone, start_pfn, nr_pages);
538 mutex_unlock(&add_spumem_mutex);
539
540 return ret;
541}
542 512
543static void __iomem * __init map_spe_prop(struct spu *spu, 513int spu_add_sysdev_attr(struct sysdev_attribute *attr)
544 struct device_node *n, const char *name)
545{ 514{
546 const struct address_prop { 515 struct spu *spu;
547 unsigned long address; 516 mutex_lock(&spu_mutex);
548 unsigned int len;
549 } __attribute__((packed)) *prop;
550
551 const void *p;
552 int proplen;
553 void __iomem *ret = NULL;
554 int err = 0;
555
556 p = get_property(n, name, &proplen);
557 if (proplen != sizeof (struct address_prop))
558 return NULL;
559
560 prop = p;
561
562 err = cell_spuprop_present(spu, n, name);
563 if (err && (err != -EEXIST))
564 goto out;
565
566 ret = ioremap(prop->address, prop->len);
567
568 out:
569 return ret;
570}
571 517
572static void spu_unmap(struct spu *spu) 518 list_for_each_entry(spu, &spu_full_list, full_list)
573{ 519 sysdev_create_file(&spu->sysdev, attr);
574 iounmap(spu->priv2);
575 iounmap(spu->priv1);
576 iounmap(spu->problem);
577 iounmap((__force u8 __iomem *)spu->local_store);
578}
579 520
580/* This function shall be abstracted for HV platforms */ 521 mutex_unlock(&spu_mutex);
581static int __init spu_map_interrupts_old(struct spu *spu, struct device_node *np) 522 return 0;
582{
583 unsigned int isrc;
584 const u32 *tmp;
585
586 /* Get the interrupt source unit from the device-tree */
587 tmp = get_property(np, "isrc", NULL);
588 if (!tmp)
589 return -ENODEV;
590 isrc = tmp[0];
591
592 /* Add the node number */
593 isrc |= spu->node << IIC_IRQ_NODE_SHIFT;
594 spu->isrc = isrc;
595
596 /* Now map interrupts of all 3 classes */
597 spu->irqs[0] = irq_create_mapping(NULL, IIC_IRQ_CLASS_0 | isrc);
598 spu->irqs[1] = irq_create_mapping(NULL, IIC_IRQ_CLASS_1 | isrc);
599 spu->irqs[2] = irq_create_mapping(NULL, IIC_IRQ_CLASS_2 | isrc);
600
601 /* Right now, we only fail if class 2 failed */
602 return spu->irqs[2] == NO_IRQ ? -EINVAL : 0;
603} 523}
524EXPORT_SYMBOL_GPL(spu_add_sysdev_attr);
604 525
605static int __init spu_map_device_old(struct spu *spu, struct device_node *node) 526int spu_add_sysdev_attr_group(struct attribute_group *attrs)
606{ 527{
607 const char *prop; 528 struct spu *spu;
608 int ret; 529 mutex_lock(&spu_mutex);
609
610 ret = -ENODEV;
611 spu->name = get_property(node, "name", NULL);
612 if (!spu->name)
613 goto out;
614
615 prop = get_property(node, "local-store", NULL);
616 if (!prop)
617 goto out;
618 spu->local_store_phys = *(unsigned long *)prop;
619
620 /* we use local store as ram, not io memory */
621 spu->local_store = (void __force *)
622 map_spe_prop(spu, node, "local-store");
623 if (!spu->local_store)
624 goto out;
625
626 prop = get_property(node, "problem", NULL);
627 if (!prop)
628 goto out_unmap;
629 spu->problem_phys = *(unsigned long *)prop;
630
631 spu->problem= map_spe_prop(spu, node, "problem");
632 if (!spu->problem)
633 goto out_unmap;
634
635 spu->priv1= map_spe_prop(spu, node, "priv1");
636 /* priv1 is not available on a hypervisor */
637
638 spu->priv2= map_spe_prop(spu, node, "priv2");
639 if (!spu->priv2)
640 goto out_unmap;
641 ret = 0;
642 goto out;
643
644out_unmap:
645 spu_unmap(spu);
646out:
647 return ret;
648}
649 530
650static int __init spu_map_interrupts(struct spu *spu, struct device_node *np) 531 list_for_each_entry(spu, &spu_full_list, full_list)
651{ 532 sysfs_create_group(&spu->sysdev.kobj, attrs);
652 struct of_irq oirq;
653 int ret;
654 int i;
655 533
656 for (i=0; i < 3; i++) { 534 mutex_unlock(&spu_mutex);
657 ret = of_irq_map_one(np, i, &oirq);
658 if (ret) {
659 pr_debug("spu_new: failed to get irq %d\n", i);
660 goto err;
661 }
662 ret = -EINVAL;
663 pr_debug(" irq %d no 0x%x on %s\n", i, oirq.specifier[0],
664 oirq.controller->full_name);
665 spu->irqs[i] = irq_create_of_mapping(oirq.controller,
666 oirq.specifier, oirq.size);
667 if (spu->irqs[i] == NO_IRQ) {
668 pr_debug("spu_new: failed to map it !\n");
669 goto err;
670 }
671 }
672 return 0; 535 return 0;
673
674err:
675 pr_debug("failed to map irq %x for spu %s\n", *oirq.specifier, spu->name);
676 for (; i >= 0; i--) {
677 if (spu->irqs[i] != NO_IRQ)
678 irq_dispose_mapping(spu->irqs[i]);
679 }
680 return ret;
681} 536}
537EXPORT_SYMBOL_GPL(spu_add_sysdev_attr_group);
682 538
683static int spu_map_resource(struct device_node *node, int nr,
684 void __iomem** virt, unsigned long *phys)
685{
686 struct resource resource = { };
687 int ret;
688
689 ret = of_address_to_resource(node, nr, &resource);
690 if (ret)
691 goto out;
692 539
693 if (phys) 540void spu_remove_sysdev_attr(struct sysdev_attribute *attr)
694 *phys = resource.start;
695 *virt = ioremap(resource.start, resource.end - resource.start);
696 if (!*virt)
697 ret = -EINVAL;
698
699out:
700 return ret;
701}
702
703static int __init spu_map_device(struct spu *spu, struct device_node *node)
704{ 541{
705 int ret = -ENODEV; 542 struct spu *spu;
706 spu->name = get_property(node, "name", NULL); 543 mutex_lock(&spu_mutex);
707 if (!spu->name)
708 goto out;
709
710 ret = spu_map_resource(node, 0, (void __iomem**)&spu->local_store,
711 &spu->local_store_phys);
712 if (ret) {
713 pr_debug("spu_new: failed to map %s resource 0\n",
714 node->full_name);
715 goto out;
716 }
717 ret = spu_map_resource(node, 1, (void __iomem**)&spu->problem,
718 &spu->problem_phys);
719 if (ret) {
720 pr_debug("spu_new: failed to map %s resource 1\n",
721 node->full_name);
722 goto out_unmap;
723 }
724 ret = spu_map_resource(node, 2, (void __iomem**)&spu->priv2,
725 NULL);
726 if (ret) {
727 pr_debug("spu_new: failed to map %s resource 2\n",
728 node->full_name);
729 goto out_unmap;
730 }
731
732 if (!firmware_has_feature(FW_FEATURE_LPAR))
733 ret = spu_map_resource(node, 3, (void __iomem**)&spu->priv1,
734 NULL);
735 if (ret) {
736 pr_debug("spu_new: failed to map %s resource 3\n",
737 node->full_name);
738 goto out_unmap;
739 }
740 pr_debug("spu_new: %s maps:\n", node->full_name);
741 pr_debug(" local store : 0x%016lx -> 0x%p\n",
742 spu->local_store_phys, spu->local_store);
743 pr_debug(" problem state : 0x%016lx -> 0x%p\n",
744 spu->problem_phys, spu->problem);
745 pr_debug(" priv2 : 0x%p\n", spu->priv2);
746 pr_debug(" priv1 : 0x%p\n", spu->priv1);
747 544
748 return 0; 545 list_for_each_entry(spu, &spu_full_list, full_list)
546 sysdev_remove_file(&spu->sysdev, attr);
749 547
750out_unmap: 548 mutex_unlock(&spu_mutex);
751 spu_unmap(spu);
752out:
753 pr_debug("failed to map spe %s: %d\n", spu->name, ret);
754 return ret;
755} 549}
550EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr);
756 551
757struct sysdev_class spu_sysdev_class = { 552void spu_remove_sysdev_attr_group(struct attribute_group *attrs)
758 set_kset_name("spu")
759};
760
761static ssize_t spu_show_isrc(struct sys_device *sysdev, char *buf)
762{ 553{
763 struct spu *spu = container_of(sysdev, struct spu, sysdev); 554 struct spu *spu;
764 return sprintf(buf, "%d\n", spu->isrc); 555 mutex_lock(&spu_mutex);
765 556
766} 557 list_for_each_entry(spu, &spu_full_list, full_list)
767static SYSDEV_ATTR(isrc, 0400, spu_show_isrc, NULL); 558 sysfs_remove_group(&spu->sysdev.kobj, attrs);
768 559
769extern int attach_sysdev_to_node(struct sys_device *dev, int nid); 560 mutex_unlock(&spu_mutex);
561}
562EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr_group);
770 563
771static int spu_create_sysdev(struct spu *spu) 564static int spu_create_sysdev(struct spu *spu)
772{ 565{
@@ -781,21 +574,18 @@ static int spu_create_sysdev(struct spu *spu)
781 return ret; 574 return ret;
782 } 575 }
783 576
784 if (spu->isrc != 0) 577 sysfs_add_device_to_node(&spu->sysdev, spu->node);
785 sysdev_create_file(&spu->sysdev, &attr_isrc);
786 sysfs_add_device_to_node(&spu->sysdev, spu->nid);
787 578
788 return 0; 579 return 0;
789} 580}
790 581
791static void spu_destroy_sysdev(struct spu *spu) 582static void spu_destroy_sysdev(struct spu *spu)
792{ 583{
793 sysdev_remove_file(&spu->sysdev, &attr_isrc); 584 sysfs_remove_device_from_node(&spu->sysdev, spu->node);
794 sysfs_remove_device_from_node(&spu->sysdev, spu->nid);
795 sysdev_unregister(&spu->sysdev); 585 sysdev_unregister(&spu->sysdev);
796} 586}
797 587
798static int __init create_spu(struct device_node *spe) 588static int __init create_spu(void *data)
799{ 589{
800 struct spu *spu; 590 struct spu *spu;
801 int ret; 591 int ret;
@@ -806,57 +596,37 @@ static int __init create_spu(struct device_node *spe)
806 if (!spu) 596 if (!spu)
807 goto out; 597 goto out;
808 598
809 spu->node = find_spu_node_id(spe); 599 spin_lock_init(&spu->register_lock);
810 if (spu->node >= MAX_NUMNODES) { 600 mutex_lock(&spu_mutex);
811 printk(KERN_WARNING "SPE %s on node %d ignored," 601 spu->number = number++;
812 " node number too big\n", spe->full_name, spu->node); 602 mutex_unlock(&spu_mutex);
813 printk(KERN_WARNING "Check if CONFIG_NUMA is enabled.\n"); 603
814 return -ENODEV; 604 ret = spu_create_spu(spu, data);
815 }
816 spu->nid = of_node_to_nid(spe);
817 if (spu->nid == -1)
818 spu->nid = 0;
819 605
820 ret = spu_map_device(spu, spe);
821 /* try old method */
822 if (ret)
823 ret = spu_map_device_old(spu, spe);
824 if (ret) 606 if (ret)
825 goto out_free; 607 goto out_free;
826 608
827 ret = spu_map_interrupts(spu, spe); 609 spu_mfc_sdr_setup(spu);
828 if (ret)
829 ret = spu_map_interrupts_old(spu, spe);
830 if (ret)
831 goto out_unmap;
832 spin_lock_init(&spu->register_lock);
833 spu_mfc_sdr_set(spu, mfspr(SPRN_SDR1));
834 spu_mfc_sr1_set(spu, 0x33); 610 spu_mfc_sr1_set(spu, 0x33);
835 mutex_lock(&spu_mutex);
836
837 spu->number = number++;
838 ret = spu_request_irqs(spu); 611 ret = spu_request_irqs(spu);
839 if (ret) 612 if (ret)
840 goto out_unlock; 613 goto out_destroy;
841 614
842 ret = spu_create_sysdev(spu); 615 ret = spu_create_sysdev(spu);
843 if (ret) 616 if (ret)
844 goto out_free_irqs; 617 goto out_free_irqs;
845 618
619 mutex_lock(&spu_mutex);
846 list_add(&spu->list, &spu_list[spu->node]); 620 list_add(&spu->list, &spu_list[spu->node]);
621 list_add(&spu->full_list, &spu_full_list);
847 mutex_unlock(&spu_mutex); 622 mutex_unlock(&spu_mutex);
848 623
849 pr_debug(KERN_DEBUG "Using SPE %s %02x %p %p %p %p %d\n",
850 spu->name, spu->isrc, spu->local_store,
851 spu->problem, spu->priv1, spu->priv2, spu->number);
852 goto out; 624 goto out;
853 625
854out_free_irqs: 626out_free_irqs:
855 spu_free_irqs(spu); 627 spu_free_irqs(spu);
856out_unlock: 628out_destroy:
857 mutex_unlock(&spu_mutex); 629 spu_destroy_spu(spu);
858out_unmap:
859 spu_unmap(spu);
860out_free: 630out_free:
861 kfree(spu); 631 kfree(spu);
862out: 632out:
@@ -866,10 +636,11 @@ out:
866static void destroy_spu(struct spu *spu) 636static void destroy_spu(struct spu *spu)
867{ 637{
868 list_del_init(&spu->list); 638 list_del_init(&spu->list);
639 list_del_init(&spu->full_list);
869 640
870 spu_destroy_sysdev(spu); 641 spu_destroy_sysdev(spu);
871 spu_free_irqs(spu); 642 spu_free_irqs(spu);
872 spu_unmap(spu); 643 spu_destroy_spu(spu);
873 kfree(spu); 644 kfree(spu);
874} 645}
875 646
@@ -890,9 +661,11 @@ module_exit(cleanup_spu_base);
890 661
891static int __init init_spu_base(void) 662static int __init init_spu_base(void)
892{ 663{
893 struct device_node *node;
894 int i, ret; 664 int i, ret;
895 665
666 if (!spu_management_ops)
667 return 0;
668
896 /* create sysdev class for spus */ 669 /* create sysdev class for spus */
897 ret = sysdev_class_register(&spu_sysdev_class); 670 ret = sysdev_class_register(&spu_sysdev_class);
898 if (ret) 671 if (ret)
@@ -901,17 +674,17 @@ static int __init init_spu_base(void)
901 for (i = 0; i < MAX_NUMNODES; i++) 674 for (i = 0; i < MAX_NUMNODES; i++)
902 INIT_LIST_HEAD(&spu_list[i]); 675 INIT_LIST_HEAD(&spu_list[i]);
903 676
904 ret = -ENODEV; 677 ret = spu_enumerate_spus(create_spu);
905 for (node = of_find_node_by_type(NULL, "spe"); 678
906 node; node = of_find_node_by_type(node, "spe")) { 679 if (ret) {
907 ret = create_spu(node); 680 printk(KERN_WARNING "%s: Error initializing spus\n",
908 if (ret) { 681 __FUNCTION__);
909 printk(KERN_WARNING "%s: Error initializing %s\n", 682 cleanup_spu_base();
910 __FUNCTION__, node->name); 683 return ret;
911 cleanup_spu_base();
912 break;
913 }
914 } 684 }
685
686 xmon_register_spus(&spu_full_list);
687
915 return ret; 688 return ret;
916} 689}
917module_init(init_spu_base); 690module_init(init_spu_base);
diff --git a/arch/powerpc/platforms/cell/spu_coredump.c b/arch/powerpc/platforms/cell/spu_coredump.c
new file mode 100644
index 000000000000..6915b418ee73
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spu_coredump.c
@@ -0,0 +1,81 @@
1/*
2 * SPU core dump code
3 *
4 * (C) Copyright 2006 IBM Corp.
5 *
6 * Author: Dwayne Grant McConnell <decimal@us.ibm.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <linux/file.h>
24#include <linux/module.h>
25#include <linux/syscalls.h>
26
27#include <asm/spu.h>
28
29static struct spu_coredump_calls spu_coredump_calls;
30static DEFINE_MUTEX(spu_coredump_mutex);
31
32int arch_notes_size(void)
33{
34 long ret;
35 struct module *owner = spu_coredump_calls.owner;
36
37 ret = -ENOSYS;
38 mutex_lock(&spu_coredump_mutex);
39 if (owner && try_module_get(owner)) {
40 ret = spu_coredump_calls.arch_notes_size();
41 module_put(owner);
42 }
43 mutex_unlock(&spu_coredump_mutex);
44 return ret;
45}
46
47void arch_write_notes(struct file *file)
48{
49 struct module *owner = spu_coredump_calls.owner;
50
51 mutex_lock(&spu_coredump_mutex);
52 if (owner && try_module_get(owner)) {
53 spu_coredump_calls.arch_write_notes(file);
54 module_put(owner);
55 }
56 mutex_unlock(&spu_coredump_mutex);
57}
58
59int register_arch_coredump_calls(struct spu_coredump_calls *calls)
60{
61 if (spu_coredump_calls.owner)
62 return -EBUSY;
63
64 mutex_lock(&spu_coredump_mutex);
65 spu_coredump_calls.arch_notes_size = calls->arch_notes_size;
66 spu_coredump_calls.arch_write_notes = calls->arch_write_notes;
67 spu_coredump_calls.owner = calls->owner;
68 mutex_unlock(&spu_coredump_mutex);
69 return 0;
70}
71EXPORT_SYMBOL_GPL(register_arch_coredump_calls);
72
73void unregister_arch_coredump_calls(struct spu_coredump_calls *calls)
74{
75 BUG_ON(spu_coredump_calls.owner != calls->owner);
76
77 mutex_lock(&spu_coredump_mutex);
78 spu_coredump_calls.owner = NULL;
79 mutex_unlock(&spu_coredump_mutex);
80}
81EXPORT_SYMBOL_GPL(unregister_arch_coredump_calls);
diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c
index 71b69f0a1a48..a5de0430c56d 100644
--- a/arch/powerpc/platforms/cell/spu_priv1_mmio.c
+++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c
@@ -18,120 +18,498 @@
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */ 19 */
20 20
21#include <linux/interrupt.h>
22#include <linux/list.h>
21#include <linux/module.h> 23#include <linux/module.h>
24#include <linux/ptrace.h>
25#include <linux/slab.h>
26#include <linux/wait.h>
27#include <linux/mm.h>
28#include <linux/io.h>
29#include <linux/mutex.h>
30#include <linux/device.h>
22 31
23#include <asm/io.h>
24#include <asm/spu.h> 32#include <asm/spu.h>
25#include <asm/spu_priv1.h> 33#include <asm/spu_priv1.h>
34#include <asm/firmware.h>
35#include <asm/prom.h>
26 36
27#include "interrupt.h" 37#include "interrupt.h"
38#include "spu_priv1_mmio.h"
39
40struct spu_pdata {
41 int nid;
42 struct device_node *devnode;
43 struct spu_priv1 __iomem *priv1;
44};
45
46static struct spu_pdata *spu_get_pdata(struct spu *spu)
47{
48 BUG_ON(!spu->pdata);
49 return spu->pdata;
50}
51
52struct device_node *spu_devnode(struct spu *spu)
53{
54 return spu_get_pdata(spu)->devnode;
55}
56
57EXPORT_SYMBOL_GPL(spu_devnode);
58
59static int __init find_spu_node_id(struct device_node *spe)
60{
61 const unsigned int *id;
62 struct device_node *cpu;
63 cpu = spe->parent->parent;
64 id = get_property(cpu, "node-id", NULL);
65 return id ? *id : 0;
66}
67
68static int __init cell_spuprop_present(struct spu *spu, struct device_node *spe,
69 const char *prop)
70{
71 static DEFINE_MUTEX(add_spumem_mutex);
72
73 const struct address_prop {
74 unsigned long address;
75 unsigned int len;
76 } __attribute__((packed)) *p;
77 int proplen;
78
79 unsigned long start_pfn, nr_pages;
80 struct pglist_data *pgdata;
81 struct zone *zone;
82 int ret;
83
84 p = get_property(spe, prop, &proplen);
85 WARN_ON(proplen != sizeof (*p));
86
87 start_pfn = p->address >> PAGE_SHIFT;
88 nr_pages = ((unsigned long)p->len + PAGE_SIZE - 1) >> PAGE_SHIFT;
89
90 pgdata = NODE_DATA(spu_get_pdata(spu)->nid);
91 zone = pgdata->node_zones;
92
93 /* XXX rethink locking here */
94 mutex_lock(&add_spumem_mutex);
95 ret = __add_pages(zone, start_pfn, nr_pages);
96 mutex_unlock(&add_spumem_mutex);
97
98 return ret;
99}
100
101static void __iomem * __init map_spe_prop(struct spu *spu,
102 struct device_node *n, const char *name)
103{
104 const struct address_prop {
105 unsigned long address;
106 unsigned int len;
107 } __attribute__((packed)) *prop;
108
109 const void *p;
110 int proplen;
111 void __iomem *ret = NULL;
112 int err = 0;
113
114 p = get_property(n, name, &proplen);
115 if (proplen != sizeof (struct address_prop))
116 return NULL;
117
118 prop = p;
119
120 err = cell_spuprop_present(spu, n, name);
121 if (err && (err != -EEXIST))
122 goto out;
123
124 ret = ioremap(prop->address, prop->len);
125
126 out:
127 return ret;
128}
129
130static void spu_unmap(struct spu *spu)
131{
132 iounmap(spu->priv2);
133 iounmap(spu_get_pdata(spu)->priv1);
134 iounmap(spu->problem);
135 iounmap((__force u8 __iomem *)spu->local_store);
136}
137
138static int __init spu_map_interrupts_old(struct spu *spu,
139 struct device_node *np)
140{
141 unsigned int isrc;
142 const u32 *tmp;
143
144 /* Get the interrupt source unit from the device-tree */
145 tmp = get_property(np, "isrc", NULL);
146 if (!tmp)
147 return -ENODEV;
148 isrc = tmp[0];
149
150 /* Add the node number */
151 isrc |= spu->node << IIC_IRQ_NODE_SHIFT;
152
153 /* Now map interrupts of all 3 classes */
154 spu->irqs[0] = irq_create_mapping(NULL, IIC_IRQ_CLASS_0 | isrc);
155 spu->irqs[1] = irq_create_mapping(NULL, IIC_IRQ_CLASS_1 | isrc);
156 spu->irqs[2] = irq_create_mapping(NULL, IIC_IRQ_CLASS_2 | isrc);
157
158 /* Right now, we only fail if class 2 failed */
159 return spu->irqs[2] == NO_IRQ ? -EINVAL : 0;
160}
161
162static int __init spu_map_device_old(struct spu *spu, struct device_node *node)
163{
164 const char *prop;
165 int ret;
166
167 ret = -ENODEV;
168 spu->name = get_property(node, "name", NULL);
169 if (!spu->name)
170 goto out;
171
172 prop = get_property(node, "local-store", NULL);
173 if (!prop)
174 goto out;
175 spu->local_store_phys = *(unsigned long *)prop;
176
177 /* we use local store as ram, not io memory */
178 spu->local_store = (void __force *)
179 map_spe_prop(spu, node, "local-store");
180 if (!spu->local_store)
181 goto out;
182
183 prop = get_property(node, "problem", NULL);
184 if (!prop)
185 goto out_unmap;
186 spu->problem_phys = *(unsigned long *)prop;
187
188 spu->problem= map_spe_prop(spu, node, "problem");
189 if (!spu->problem)
190 goto out_unmap;
191
192 spu_get_pdata(spu)->priv1= map_spe_prop(spu, node, "priv1");
193
194 spu->priv2= map_spe_prop(spu, node, "priv2");
195 if (!spu->priv2)
196 goto out_unmap;
197 ret = 0;
198 goto out;
199
200out_unmap:
201 spu_unmap(spu);
202out:
203 return ret;
204}
205
206static int __init spu_map_interrupts(struct spu *spu, struct device_node *np)
207{
208 struct of_irq oirq;
209 int ret;
210 int i;
211
212 for (i=0; i < 3; i++) {
213 ret = of_irq_map_one(np, i, &oirq);
214 if (ret) {
215 pr_debug("spu_new: failed to get irq %d\n", i);
216 goto err;
217 }
218 ret = -EINVAL;
219 pr_debug(" irq %d no 0x%x on %s\n", i, oirq.specifier[0],
220 oirq.controller->full_name);
221 spu->irqs[i] = irq_create_of_mapping(oirq.controller,
222 oirq.specifier, oirq.size);
223 if (spu->irqs[i] == NO_IRQ) {
224 pr_debug("spu_new: failed to map it !\n");
225 goto err;
226 }
227 }
228 return 0;
229
230err:
231 pr_debug("failed to map irq %x for spu %s\n", *oirq.specifier,
232 spu->name);
233 for (; i >= 0; i--) {
234 if (spu->irqs[i] != NO_IRQ)
235 irq_dispose_mapping(spu->irqs[i]);
236 }
237 return ret;
238}
239
240static int spu_map_resource(struct device_node *node, int nr,
241 void __iomem** virt, unsigned long *phys)
242{
243 struct resource resource = { };
244 int ret;
245
246 ret = of_address_to_resource(node, nr, &resource);
247 if (ret)
248 goto out;
249
250 if (phys)
251 *phys = resource.start;
252 *virt = ioremap(resource.start, resource.end - resource.start);
253 if (!*virt)
254 ret = -EINVAL;
255
256out:
257 return ret;
258}
259
260static int __init spu_map_device(struct spu *spu, struct device_node *node)
261{
262 int ret = -ENODEV;
263 spu->name = get_property(node, "name", NULL);
264 if (!spu->name)
265 goto out;
266
267 ret = spu_map_resource(node, 0, (void __iomem**)&spu->local_store,
268 &spu->local_store_phys);
269 if (ret) {
270 pr_debug("spu_new: failed to map %s resource 0\n",
271 node->full_name);
272 goto out;
273 }
274 ret = spu_map_resource(node, 1, (void __iomem**)&spu->problem,
275 &spu->problem_phys);
276 if (ret) {
277 pr_debug("spu_new: failed to map %s resource 1\n",
278 node->full_name);
279 goto out_unmap;
280 }
281 ret = spu_map_resource(node, 2, (void __iomem**)&spu->priv2,
282 NULL);
283 if (ret) {
284 pr_debug("spu_new: failed to map %s resource 2\n",
285 node->full_name);
286 goto out_unmap;
287 }
288 if (!firmware_has_feature(FW_FEATURE_LPAR))
289 ret = spu_map_resource(node, 3,
290 (void __iomem**)&spu_get_pdata(spu)->priv1, NULL);
291 if (ret) {
292 pr_debug("spu_new: failed to map %s resource 3\n",
293 node->full_name);
294 goto out_unmap;
295 }
296 pr_debug("spu_new: %s maps:\n", node->full_name);
297 pr_debug(" local store : 0x%016lx -> 0x%p\n",
298 spu->local_store_phys, spu->local_store);
299 pr_debug(" problem state : 0x%016lx -> 0x%p\n",
300 spu->problem_phys, spu->problem);
301 pr_debug(" priv2 : 0x%p\n", spu->priv2);
302 pr_debug(" priv1 : 0x%p\n",
303 spu_get_pdata(spu)->priv1);
304
305 return 0;
306
307out_unmap:
308 spu_unmap(spu);
309out:
310 pr_debug("failed to map spe %s: %d\n", spu->name, ret);
311 return ret;
312}
313
314static int __init of_enumerate_spus(int (*fn)(void *data))
315{
316 int ret;
317 struct device_node *node;
318
319 ret = -ENODEV;
320 for (node = of_find_node_by_type(NULL, "spe");
321 node; node = of_find_node_by_type(node, "spe")) {
322 ret = fn(node);
323 if (ret) {
324 printk(KERN_WARNING "%s: Error initializing %s\n",
325 __FUNCTION__, node->name);
326 break;
327 }
328 }
329 return ret;
330}
331
332static int __init of_create_spu(struct spu *spu, void *data)
333{
334 int ret;
335 struct device_node *spe = (struct device_node *)data;
336
337 spu->pdata = kzalloc(sizeof(struct spu_pdata),
338 GFP_KERNEL);
339 if (!spu->pdata) {
340 ret = -ENOMEM;
341 goto out;
342 }
343
344 spu->node = find_spu_node_id(spe);
345 if (spu->node >= MAX_NUMNODES) {
346 printk(KERN_WARNING "SPE %s on node %d ignored,"
347 " node number too big\n", spe->full_name, spu->node);
348 printk(KERN_WARNING "Check if CONFIG_NUMA is enabled.\n");
349 ret = -ENODEV;
350 goto out_free;
351 }
352
353 spu_get_pdata(spu)->nid = of_node_to_nid(spe);
354 if (spu_get_pdata(spu)->nid == -1)
355 spu_get_pdata(spu)->nid = 0;
356
357 ret = spu_map_device(spu, spe);
358 /* try old method */
359 if (ret)
360 ret = spu_map_device_old(spu, spe);
361 if (ret)
362 goto out_free;
363
364 ret = spu_map_interrupts(spu, spe);
365 if (ret)
366 ret = spu_map_interrupts_old(spu, spe);
367 if (ret)
368 goto out_unmap;
369
370 spu_get_pdata(spu)->devnode = of_node_get(spe);
371
372 pr_debug(KERN_DEBUG "Using SPE %s %p %p %p %p %d\n", spu->name,
373 spu->local_store, spu->problem, spu_get_pdata(spu)->priv1,
374 spu->priv2, spu->number);
375 goto out;
376
377out_unmap:
378 spu_unmap(spu);
379out_free:
380 kfree(spu->pdata);
381 spu->pdata = NULL;
382out:
383 return ret;
384}
385
386static int of_destroy_spu(struct spu *spu)
387{
388 spu_unmap(spu);
389 of_node_put(spu_get_pdata(spu)->devnode);
390 kfree(spu->pdata);
391 spu->pdata = NULL;
392 return 0;
393}
394
395const struct spu_management_ops spu_management_of_ops = {
396 .enumerate_spus = of_enumerate_spus,
397 .create_spu = of_create_spu,
398 .destroy_spu = of_destroy_spu,
399};
28 400
29static void int_mask_and(struct spu *spu, int class, u64 mask) 401static void int_mask_and(struct spu *spu, int class, u64 mask)
30{ 402{
31 u64 old_mask; 403 u64 old_mask;
32 404
33 old_mask = in_be64(&spu->priv1->int_mask_RW[class]); 405 old_mask = in_be64(&spu_get_pdata(spu)->priv1->int_mask_RW[class]);
34 out_be64(&spu->priv1->int_mask_RW[class], old_mask & mask); 406 out_be64(&spu_get_pdata(spu)->priv1->int_mask_RW[class],
407 old_mask & mask);
35} 408}
36 409
37static void int_mask_or(struct spu *spu, int class, u64 mask) 410static void int_mask_or(struct spu *spu, int class, u64 mask)
38{ 411{
39 u64 old_mask; 412 u64 old_mask;
40 413
41 old_mask = in_be64(&spu->priv1->int_mask_RW[class]); 414 old_mask = in_be64(&spu_get_pdata(spu)->priv1->int_mask_RW[class]);
42 out_be64(&spu->priv1->int_mask_RW[class], old_mask | mask); 415 out_be64(&spu_get_pdata(spu)->priv1->int_mask_RW[class],
416 old_mask | mask);
43} 417}
44 418
45static void int_mask_set(struct spu *spu, int class, u64 mask) 419static void int_mask_set(struct spu *spu, int class, u64 mask)
46{ 420{
47 out_be64(&spu->priv1->int_mask_RW[class], mask); 421 out_be64(&spu_get_pdata(spu)->priv1->int_mask_RW[class], mask);
48} 422}
49 423
50static u64 int_mask_get(struct spu *spu, int class) 424static u64 int_mask_get(struct spu *spu, int class)
51{ 425{
52 return in_be64(&spu->priv1->int_mask_RW[class]); 426 return in_be64(&spu_get_pdata(spu)->priv1->int_mask_RW[class]);
53} 427}
54 428
55static void int_stat_clear(struct spu *spu, int class, u64 stat) 429static void int_stat_clear(struct spu *spu, int class, u64 stat)
56{ 430{
57 out_be64(&spu->priv1->int_stat_RW[class], stat); 431 out_be64(&spu_get_pdata(spu)->priv1->int_stat_RW[class], stat);
58} 432}
59 433
60static u64 int_stat_get(struct spu *spu, int class) 434static u64 int_stat_get(struct spu *spu, int class)
61{ 435{
62 return in_be64(&spu->priv1->int_stat_RW[class]); 436 return in_be64(&spu_get_pdata(spu)->priv1->int_stat_RW[class]);
63} 437}
64 438
65static void cpu_affinity_set(struct spu *spu, int cpu) 439static void cpu_affinity_set(struct spu *spu, int cpu)
66{ 440{
67 u64 target = iic_get_target_id(cpu); 441 u64 target = iic_get_target_id(cpu);
68 u64 route = target << 48 | target << 32 | target << 16; 442 u64 route = target << 48 | target << 32 | target << 16;
69 out_be64(&spu->priv1->int_route_RW, route); 443 out_be64(&spu_get_pdata(spu)->priv1->int_route_RW, route);
70} 444}
71 445
72static u64 mfc_dar_get(struct spu *spu) 446static u64 mfc_dar_get(struct spu *spu)
73{ 447{
74 return in_be64(&spu->priv1->mfc_dar_RW); 448 return in_be64(&spu_get_pdata(spu)->priv1->mfc_dar_RW);
75} 449}
76 450
77static u64 mfc_dsisr_get(struct spu *spu) 451static u64 mfc_dsisr_get(struct spu *spu)
78{ 452{
79 return in_be64(&spu->priv1->mfc_dsisr_RW); 453 return in_be64(&spu_get_pdata(spu)->priv1->mfc_dsisr_RW);
80} 454}
81 455
82static void mfc_dsisr_set(struct spu *spu, u64 dsisr) 456static void mfc_dsisr_set(struct spu *spu, u64 dsisr)
83{ 457{
84 out_be64(&spu->priv1->mfc_dsisr_RW, dsisr); 458 out_be64(&spu_get_pdata(spu)->priv1->mfc_dsisr_RW, dsisr);
85} 459}
86 460
87static void mfc_sdr_set(struct spu *spu, u64 sdr) 461static void mfc_sdr_setup(struct spu *spu)
88{ 462{
89 out_be64(&spu->priv1->mfc_sdr_RW, sdr); 463 out_be64(&spu_get_pdata(spu)->priv1->mfc_sdr_RW, mfspr(SPRN_SDR1));
90} 464}
91 465
92static void mfc_sr1_set(struct spu *spu, u64 sr1) 466static void mfc_sr1_set(struct spu *spu, u64 sr1)
93{ 467{
94 out_be64(&spu->priv1->mfc_sr1_RW, sr1); 468 out_be64(&spu_get_pdata(spu)->priv1->mfc_sr1_RW, sr1);
95} 469}
96 470
97static u64 mfc_sr1_get(struct spu *spu) 471static u64 mfc_sr1_get(struct spu *spu)
98{ 472{
99 return in_be64(&spu->priv1->mfc_sr1_RW); 473 return in_be64(&spu_get_pdata(spu)->priv1->mfc_sr1_RW);
100} 474}
101 475
102static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id) 476static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id)
103{ 477{
104 out_be64(&spu->priv1->mfc_tclass_id_RW, tclass_id); 478 out_be64(&spu_get_pdata(spu)->priv1->mfc_tclass_id_RW, tclass_id);
105} 479}
106 480
107static u64 mfc_tclass_id_get(struct spu *spu) 481static u64 mfc_tclass_id_get(struct spu *spu)
108{ 482{
109 return in_be64(&spu->priv1->mfc_tclass_id_RW); 483 return in_be64(&spu_get_pdata(spu)->priv1->mfc_tclass_id_RW);
110} 484}
111 485
112static void tlb_invalidate(struct spu *spu) 486static void tlb_invalidate(struct spu *spu)
113{ 487{
114 out_be64(&spu->priv1->tlb_invalidate_entry_W, 0ul); 488 out_be64(&spu_get_pdata(spu)->priv1->tlb_invalidate_entry_W, 0ul);
115} 489}
116 490
117static void resource_allocation_groupID_set(struct spu *spu, u64 id) 491static void resource_allocation_groupID_set(struct spu *spu, u64 id)
118{ 492{
119 out_be64(&spu->priv1->resource_allocation_groupID_RW, id); 493 out_be64(&spu_get_pdata(spu)->priv1->resource_allocation_groupID_RW,
494 id);
120} 495}
121 496
122static u64 resource_allocation_groupID_get(struct spu *spu) 497static u64 resource_allocation_groupID_get(struct spu *spu)
123{ 498{
124 return in_be64(&spu->priv1->resource_allocation_groupID_RW); 499 return in_be64(
500 &spu_get_pdata(spu)->priv1->resource_allocation_groupID_RW);
125} 501}
126 502
127static void resource_allocation_enable_set(struct spu *spu, u64 enable) 503static void resource_allocation_enable_set(struct spu *spu, u64 enable)
128{ 504{
129 out_be64(&spu->priv1->resource_allocation_enable_RW, enable); 505 out_be64(&spu_get_pdata(spu)->priv1->resource_allocation_enable_RW,
506 enable);
130} 507}
131 508
132static u64 resource_allocation_enable_get(struct spu *spu) 509static u64 resource_allocation_enable_get(struct spu *spu)
133{ 510{
134 return in_be64(&spu->priv1->resource_allocation_enable_RW); 511 return in_be64(
512 &spu_get_pdata(spu)->priv1->resource_allocation_enable_RW);
135} 513}
136 514
137const struct spu_priv1_ops spu_priv1_mmio_ops = 515const struct spu_priv1_ops spu_priv1_mmio_ops =
@@ -146,7 +524,7 @@ const struct spu_priv1_ops spu_priv1_mmio_ops =
146 .mfc_dar_get = mfc_dar_get, 524 .mfc_dar_get = mfc_dar_get,
147 .mfc_dsisr_get = mfc_dsisr_get, 525 .mfc_dsisr_get = mfc_dsisr_get,
148 .mfc_dsisr_set = mfc_dsisr_set, 526 .mfc_dsisr_set = mfc_dsisr_set,
149 .mfc_sdr_set = mfc_sdr_set, 527 .mfc_sdr_setup = mfc_sdr_setup,
150 .mfc_sr1_set = mfc_sr1_set, 528 .mfc_sr1_set = mfc_sr1_set,
151 .mfc_sr1_get = mfc_sr1_get, 529 .mfc_sr1_get = mfc_sr1_get,
152 .mfc_tclass_id_set = mfc_tclass_id_set, 530 .mfc_tclass_id_set = mfc_tclass_id_set,
diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.h b/arch/powerpc/platforms/cell/spu_priv1_mmio.h
new file mode 100644
index 000000000000..7b62bd1cc256
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.h
@@ -0,0 +1,26 @@
1/*
2 * spu hypervisor abstraction for direct hardware access.
3 *
4 * Copyright (C) 2006 Sony Computer Entertainment Inc.
5 * Copyright 2006 Sony Corp.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#ifndef SPU_PRIV1_MMIO_H
22#define SPU_PRIV1_MMIO_H
23
24struct device_node *spu_devnode(struct spu *spu);
25
26#endif /* SPU_PRIV1_MMIO_H */
diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile
index ecdfbb35f82e..472217d19faf 100644
--- a/arch/powerpc/platforms/cell/spufs/Makefile
+++ b/arch/powerpc/platforms/cell/spufs/Makefile
@@ -1,7 +1,7 @@
1obj-y += switch.o 1obj-y += switch.o
2 2
3obj-$(CONFIG_SPU_FS) += spufs.o 3obj-$(CONFIG_SPU_FS) += spufs.o
4spufs-y += inode.o file.o context.o syscalls.o 4spufs-y += inode.o file.o context.o syscalls.o coredump.o
5spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o 5spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o
6 6
7# Rules to build switch.o with the help of SPU tool chain 7# Rules to build switch.o with the help of SPU tool chain
diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c
index 2d22cd59d6fc..1898f0d3a8b8 100644
--- a/arch/powerpc/platforms/cell/spufs/backing_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c
@@ -36,6 +36,7 @@
36#include <asm/io.h> 36#include <asm/io.h>
37#include <asm/spu.h> 37#include <asm/spu.h>
38#include <asm/spu_csa.h> 38#include <asm/spu_csa.h>
39#include <asm/spu_info.h>
39#include <asm/mmu_context.h> 40#include <asm/mmu_context.h>
40#include "spufs.h" 41#include "spufs.h"
41 42
@@ -267,6 +268,11 @@ static char *spu_backing_get_ls(struct spu_context *ctx)
267 return ctx->csa.lscsa->ls; 268 return ctx->csa.lscsa->ls;
268} 269}
269 270
271static u32 spu_backing_runcntl_read(struct spu_context *ctx)
272{
273 return ctx->csa.prob.spu_runcntl_RW;
274}
275
270static void spu_backing_runcntl_write(struct spu_context *ctx, u32 val) 276static void spu_backing_runcntl_write(struct spu_context *ctx, u32 val)
271{ 277{
272 spin_lock(&ctx->csa.register_lock); 278 spin_lock(&ctx->csa.register_lock);
@@ -279,9 +285,26 @@ static void spu_backing_runcntl_write(struct spu_context *ctx, u32 val)
279 spin_unlock(&ctx->csa.register_lock); 285 spin_unlock(&ctx->csa.register_lock);
280} 286}
281 287
282static void spu_backing_runcntl_stop(struct spu_context *ctx) 288static void spu_backing_master_start(struct spu_context *ctx)
289{
290 struct spu_state *csa = &ctx->csa;
291 u64 sr1;
292
293 spin_lock(&csa->register_lock);
294 sr1 = csa->priv1.mfc_sr1_RW | MFC_STATE1_MASTER_RUN_CONTROL_MASK;
295 csa->priv1.mfc_sr1_RW = sr1;
296 spin_unlock(&csa->register_lock);
297}
298
299static void spu_backing_master_stop(struct spu_context *ctx)
283{ 300{
284 spu_backing_runcntl_write(ctx, SPU_RUNCNTL_STOP); 301 struct spu_state *csa = &ctx->csa;
302 u64 sr1;
303
304 spin_lock(&csa->register_lock);
305 sr1 = csa->priv1.mfc_sr1_RW & ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
306 csa->priv1.mfc_sr1_RW = sr1;
307 spin_unlock(&csa->register_lock);
285} 308}
286 309
287static int spu_backing_set_mfc_query(struct spu_context * ctx, u32 mask, 310static int spu_backing_set_mfc_query(struct spu_context * ctx, u32 mask,
@@ -345,8 +368,10 @@ struct spu_context_ops spu_backing_ops = {
345 .npc_write = spu_backing_npc_write, 368 .npc_write = spu_backing_npc_write,
346 .status_read = spu_backing_status_read, 369 .status_read = spu_backing_status_read,
347 .get_ls = spu_backing_get_ls, 370 .get_ls = spu_backing_get_ls,
371 .runcntl_read = spu_backing_runcntl_read,
348 .runcntl_write = spu_backing_runcntl_write, 372 .runcntl_write = spu_backing_runcntl_write,
349 .runcntl_stop = spu_backing_runcntl_stop, 373 .master_start = spu_backing_master_start,
374 .master_stop = spu_backing_master_stop,
350 .set_mfc_query = spu_backing_set_mfc_query, 375 .set_mfc_query = spu_backing_set_mfc_query,
351 .read_mfc_tagstatus = spu_backing_read_mfc_tagstatus, 376 .read_mfc_tagstatus = spu_backing_read_mfc_tagstatus,
352 .get_mfc_free_elements = spu_backing_get_mfc_free_elements, 377 .get_mfc_free_elements = spu_backing_get_mfc_free_elements,
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 034cf6af53a2..0870009f56db 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -120,6 +120,33 @@ void spu_unmap_mappings(struct spu_context *ctx)
120 unmap_mapping_range(ctx->signal2, 0, 0x4000, 1); 120 unmap_mapping_range(ctx->signal2, 0, 0x4000, 1);
121} 121}
122 122
123int spu_acquire_exclusive(struct spu_context *ctx)
124{
125 int ret = 0;
126
127 down_write(&ctx->state_sema);
128 /* ctx is about to be freed, can't acquire any more */
129 if (!ctx->owner) {
130 ret = -EINVAL;
131 goto out;
132 }
133
134 if (ctx->state == SPU_STATE_SAVED) {
135 ret = spu_activate(ctx, 0);
136 if (ret)
137 goto out;
138 ctx->state = SPU_STATE_RUNNABLE;
139 } else {
140 /* We need to exclude userspace access to the context. */
141 spu_unmap_mappings(ctx);
142 }
143
144out:
145 if (ret)
146 up_write(&ctx->state_sema);
147 return ret;
148}
149
123int spu_acquire_runnable(struct spu_context *ctx) 150int spu_acquire_runnable(struct spu_context *ctx)
124{ 151{
125 int ret = 0; 152 int ret = 0;
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
new file mode 100644
index 000000000000..26945c491f6b
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -0,0 +1,238 @@
1/*
2 * SPU core dump code
3 *
4 * (C) Copyright 2006 IBM Corp.
5 *
6 * Author: Dwayne Grant McConnell <decimal@us.ibm.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <linux/elf.h>
24#include <linux/file.h>
25#include <linux/fs.h>
26#include <linux/list.h>
27#include <linux/module.h>
28#include <linux/syscalls.h>
29
30#include <asm/uaccess.h>
31
32#include "spufs.h"
33
34struct spufs_ctx_info {
35 struct list_head list;
36 int dfd;
37 int memsize; /* in bytes */
38 struct spu_context *ctx;
39};
40
41static LIST_HEAD(ctx_info_list);
42
43static ssize_t do_coredump_read(int num, struct spu_context *ctx, void __user *buffer,
44 size_t size, loff_t *off)
45{
46 u64 data;
47 int ret;
48
49 if (spufs_coredump_read[num].read)
50 return spufs_coredump_read[num].read(ctx, buffer, size, off);
51
52 data = spufs_coredump_read[num].get(ctx);
53 ret = copy_to_user(buffer, &data, 8);
54 return ret ? -EFAULT : 8;
55}
56
57/*
58 * These are the only things you should do on a core-file: use only these
59 * functions to write out all the necessary info.
60 */
61static int spufs_dump_write(struct file *file, const void *addr, int nr)
62{
63 return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
64}
65
66static int spufs_dump_seek(struct file *file, loff_t off)
67{
68 if (file->f_op->llseek) {
69 if (file->f_op->llseek(file, off, 0) != off)
70 return 0;
71 } else
72 file->f_pos = off;
73 return 1;
74}
75
76static void spufs_fill_memsize(struct spufs_ctx_info *ctx_info)
77{
78 struct spu_context *ctx;
79 unsigned long long lslr;
80
81 ctx = ctx_info->ctx;
82 lslr = ctx->csa.priv2.spu_lslr_RW;
83 ctx_info->memsize = lslr + 1;
84}
85
86static int spufs_ctx_note_size(struct spufs_ctx_info *ctx_info)
87{
88 int dfd, memsize, i, sz, total = 0;
89 char *name;
90 char fullname[80];
91
92 dfd = ctx_info->dfd;
93 memsize = ctx_info->memsize;
94
95 for (i = 0; spufs_coredump_read[i].name; i++) {
96 name = spufs_coredump_read[i].name;
97 sz = spufs_coredump_read[i].size;
98
99 sprintf(fullname, "SPU/%d/%s", dfd, name);
100
101 total += sizeof(struct elf_note);
102 total += roundup(strlen(fullname) + 1, 4);
103 if (!strcmp(name, "mem"))
104 total += roundup(memsize, 4);
105 else
106 total += roundup(sz, 4);
107 }
108
109 return total;
110}
111
112static int spufs_add_one_context(struct file *file, int dfd)
113{
114 struct spu_context *ctx;
115 struct spufs_ctx_info *ctx_info;
116 int size;
117
118 ctx = SPUFS_I(file->f_dentry->d_inode)->i_ctx;
119 if (ctx->flags & SPU_CREATE_NOSCHED)
120 return 0;
121
122 ctx_info = kzalloc(sizeof(*ctx_info), GFP_KERNEL);
123 if (unlikely(!ctx_info))
124 return -ENOMEM;
125
126 ctx_info->dfd = dfd;
127 ctx_info->ctx = ctx;
128
129 spufs_fill_memsize(ctx_info);
130
131 size = spufs_ctx_note_size(ctx_info);
132 list_add(&ctx_info->list, &ctx_info_list);
133 return size;
134}
135
136/*
137 * The additional architecture-specific notes for Cell are various
138 * context files in the spu context.
139 *
140 * This function iterates over all open file descriptors and sees
141 * if they are a directory in spufs. In that case we use spufs
142 * internal functionality to dump them without needing to actually
143 * open the files.
144 */
145static int spufs_arch_notes_size(void)
146{
147 struct fdtable *fdt = files_fdtable(current->files);
148 int size = 0, fd;
149
150 for (fd = 0; fd < fdt->max_fdset && fd < fdt->max_fds; fd++) {
151 if (FD_ISSET(fd, fdt->open_fds)) {
152 struct file *file = fcheck(fd);
153
154 if (file && file->f_op == &spufs_context_fops) {
155 int rval = spufs_add_one_context(file, fd);
156 if (rval < 0)
157 break;
158 size += rval;
159 }
160 }
161 }
162
163 return size;
164}
165
166static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i,
167 struct file *file)
168{
169 struct spu_context *ctx;
170 loff_t pos = 0;
171 int sz, dfd, rc, total = 0;
172 const int bufsz = 4096;
173 char *name;
174 char fullname[80], *buf;
175 struct elf_note en;
176
177 buf = kmalloc(bufsz, GFP_KERNEL);
178 if (!buf)
179 return;
180
181 dfd = ctx_info->dfd;
182 name = spufs_coredump_read[i].name;
183
184 if (!strcmp(name, "mem"))
185 sz = ctx_info->memsize;
186 else
187 sz = spufs_coredump_read[i].size;
188
189 ctx = ctx_info->ctx;
190 if (!ctx) {
191 return;
192 }
193
194 sprintf(fullname, "SPU/%d/%s", dfd, name);
195 en.n_namesz = strlen(fullname) + 1;
196 en.n_descsz = sz;
197 en.n_type = NT_SPU;
198
199 if (!spufs_dump_write(file, &en, sizeof(en)))
200 return;
201 if (!spufs_dump_write(file, fullname, en.n_namesz))
202 return;
203 if (!spufs_dump_seek(file, roundup((unsigned long)file->f_pos, 4)))
204 return;
205
206 do {
207 rc = do_coredump_read(i, ctx, buf, bufsz, &pos);
208 if (rc > 0) {
209 if (!spufs_dump_write(file, buf, rc))
210 return;
211 total += rc;
212 }
213 } while (rc == bufsz && total < sz);
214
215 spufs_dump_seek(file, roundup((unsigned long)file->f_pos
216 - total + sz, 4));
217}
218
219static void spufs_arch_write_notes(struct file *file)
220{
221 int j;
222 struct spufs_ctx_info *ctx_info, *next;
223
224 list_for_each_entry_safe(ctx_info, next, &ctx_info_list, list) {
225 spu_acquire_saved(ctx_info->ctx);
226 for (j = 0; j < spufs_coredump_num_notes; j++)
227 spufs_arch_write_note(ctx_info, j, file);
228 spu_release(ctx_info->ctx);
229 list_del(&ctx_info->list);
230 kfree(ctx_info);
231 }
232}
233
234struct spu_coredump_calls spufs_coredump_calls = {
235 .arch_notes_size = spufs_arch_notes_size,
236 .arch_write_notes = spufs_arch_write_notes,
237 .owner = THIS_MODULE,
238};
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 533e2723e184..347eff56fcbd 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -32,13 +32,13 @@
32#include <asm/io.h> 32#include <asm/io.h>
33#include <asm/semaphore.h> 33#include <asm/semaphore.h>
34#include <asm/spu.h> 34#include <asm/spu.h>
35#include <asm/spu_info.h>
35#include <asm/uaccess.h> 36#include <asm/uaccess.h>
36 37
37#include "spufs.h" 38#include "spufs.h"
38 39
39#define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000) 40#define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000)
40 41
41
42static int 42static int
43spufs_mem_open(struct inode *inode, struct file *file) 43spufs_mem_open(struct inode *inode, struct file *file)
44{ 44{
@@ -51,18 +51,23 @@ spufs_mem_open(struct inode *inode, struct file *file)
51} 51}
52 52
53static ssize_t 53static ssize_t
54__spufs_mem_read(struct spu_context *ctx, char __user *buffer,
55 size_t size, loff_t *pos)
56{
57 char *local_store = ctx->ops->get_ls(ctx);
58 return simple_read_from_buffer(buffer, size, pos, local_store,
59 LS_SIZE);
60}
61
62static ssize_t
54spufs_mem_read(struct file *file, char __user *buffer, 63spufs_mem_read(struct file *file, char __user *buffer,
55 size_t size, loff_t *pos) 64 size_t size, loff_t *pos)
56{ 65{
57 struct spu_context *ctx = file->private_data;
58 char *local_store;
59 int ret; 66 int ret;
67 struct spu_context *ctx = file->private_data;
60 68
61 spu_acquire(ctx); 69 spu_acquire(ctx);
62 70 ret = __spufs_mem_read(ctx, buffer, size, pos);
63 local_store = ctx->ops->get_ls(ctx);
64 ret = simple_read_from_buffer(buffer, size, pos, local_store, LS_SIZE);
65
66 spu_release(ctx); 71 spu_release(ctx);
67 return ret; 72 return ret;
68} 73}
@@ -104,11 +109,11 @@ spufs_mem_mmap_nopage(struct vm_area_struct *vma,
104 109
105 if (ctx->state == SPU_STATE_SAVED) { 110 if (ctx->state == SPU_STATE_SAVED) {
106 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 111 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
107 & ~(_PAGE_NO_CACHE | _PAGE_GUARDED)); 112 & ~_PAGE_NO_CACHE);
108 page = vmalloc_to_page(ctx->csa.lscsa->ls + offset); 113 page = vmalloc_to_page(ctx->csa.lscsa->ls + offset);
109 } else { 114 } else {
110 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 115 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
111 | _PAGE_NO_CACHE | _PAGE_GUARDED); 116 | _PAGE_NO_CACHE);
112 page = pfn_to_page((ctx->spu->local_store_phys + offset) 117 page = pfn_to_page((ctx->spu->local_store_phys + offset)
113 >> PAGE_SHIFT); 118 >> PAGE_SHIFT);
114 } 119 }
@@ -131,7 +136,7 @@ spufs_mem_mmap(struct file *file, struct vm_area_struct *vma)
131 if (!(vma->vm_flags & VM_SHARED)) 136 if (!(vma->vm_flags & VM_SHARED))
132 return -EINVAL; 137 return -EINVAL;
133 138
134 /* FIXME: */ 139 vma->vm_flags |= VM_IO;
135 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 140 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
136 | _PAGE_NO_CACHE); 141 | _PAGE_NO_CACHE);
137 142
@@ -200,7 +205,7 @@ static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma)
200 if (!(vma->vm_flags & VM_SHARED)) 205 if (!(vma->vm_flags & VM_SHARED))
201 return -EINVAL; 206 return -EINVAL;
202 207
203 vma->vm_flags |= VM_RESERVED; 208 vma->vm_flags |= VM_IO;
204 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 209 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
205 | _PAGE_NO_CACHE | _PAGE_GUARDED); 210 | _PAGE_NO_CACHE | _PAGE_GUARDED);
206 211
@@ -261,18 +266,23 @@ spufs_regs_open(struct inode *inode, struct file *file)
261} 266}
262 267
263static ssize_t 268static ssize_t
269__spufs_regs_read(struct spu_context *ctx, char __user *buffer,
270 size_t size, loff_t *pos)
271{
272 struct spu_lscsa *lscsa = ctx->csa.lscsa;
273 return simple_read_from_buffer(buffer, size, pos,
274 lscsa->gprs, sizeof lscsa->gprs);
275}
276
277static ssize_t
264spufs_regs_read(struct file *file, char __user *buffer, 278spufs_regs_read(struct file *file, char __user *buffer,
265 size_t size, loff_t *pos) 279 size_t size, loff_t *pos)
266{ 280{
267 struct spu_context *ctx = file->private_data;
268 struct spu_lscsa *lscsa = ctx->csa.lscsa;
269 int ret; 281 int ret;
282 struct spu_context *ctx = file->private_data;
270 283
271 spu_acquire_saved(ctx); 284 spu_acquire_saved(ctx);
272 285 ret = __spufs_regs_read(ctx, buffer, size, pos);
273 ret = simple_read_from_buffer(buffer, size, pos,
274 lscsa->gprs, sizeof lscsa->gprs);
275
276 spu_release(ctx); 286 spu_release(ctx);
277 return ret; 287 return ret;
278} 288}
@@ -307,18 +317,23 @@ static struct file_operations spufs_regs_fops = {
307}; 317};
308 318
309static ssize_t 319static ssize_t
320__spufs_fpcr_read(struct spu_context *ctx, char __user * buffer,
321 size_t size, loff_t * pos)
322{
323 struct spu_lscsa *lscsa = ctx->csa.lscsa;
324 return simple_read_from_buffer(buffer, size, pos,
325 &lscsa->fpcr, sizeof(lscsa->fpcr));
326}
327
328static ssize_t
310spufs_fpcr_read(struct file *file, char __user * buffer, 329spufs_fpcr_read(struct file *file, char __user * buffer,
311 size_t size, loff_t * pos) 330 size_t size, loff_t * pos)
312{ 331{
313 struct spu_context *ctx = file->private_data;
314 struct spu_lscsa *lscsa = ctx->csa.lscsa;
315 int ret; 332 int ret;
333 struct spu_context *ctx = file->private_data;
316 334
317 spu_acquire_saved(ctx); 335 spu_acquire_saved(ctx);
318 336 ret = __spufs_fpcr_read(ctx, buffer, size, pos);
319 ret = simple_read_from_buffer(buffer, size, pos,
320 &lscsa->fpcr, sizeof(lscsa->fpcr));
321
322 spu_release(ctx); 337 spu_release(ctx);
323 return ret; 338 return ret;
324} 339}
@@ -718,23 +733,41 @@ static int spufs_signal1_open(struct inode *inode, struct file *file)
718 return nonseekable_open(inode, file); 733 return nonseekable_open(inode, file);
719} 734}
720 735
721static ssize_t spufs_signal1_read(struct file *file, char __user *buf, 736static ssize_t __spufs_signal1_read(struct spu_context *ctx, char __user *buf,
722 size_t len, loff_t *pos) 737 size_t len, loff_t *pos)
723{ 738{
724 struct spu_context *ctx = file->private_data; 739 int ret = 0;
725 u32 data; 740 u32 data;
726 741
727 if (len < 4) 742 if (len < 4)
728 return -EINVAL; 743 return -EINVAL;
729 744
730 spu_acquire(ctx); 745 if (ctx->csa.spu_chnlcnt_RW[3]) {
731 data = ctx->ops->signal1_read(ctx); 746 data = ctx->csa.spu_chnldata_RW[3];
732 spu_release(ctx); 747 ret = 4;
748 }
749
750 if (!ret)
751 goto out;
733 752
734 if (copy_to_user(buf, &data, 4)) 753 if (copy_to_user(buf, &data, 4))
735 return -EFAULT; 754 return -EFAULT;
736 755
737 return 4; 756out:
757 return ret;
758}
759
760static ssize_t spufs_signal1_read(struct file *file, char __user *buf,
761 size_t len, loff_t *pos)
762{
763 int ret;
764 struct spu_context *ctx = file->private_data;
765
766 spu_acquire_saved(ctx);
767 ret = __spufs_signal1_read(ctx, buf, len, pos);
768 spu_release(ctx);
769
770 return ret;
738} 771}
739 772
740static ssize_t spufs_signal1_write(struct file *file, const char __user *buf, 773static ssize_t spufs_signal1_write(struct file *file, const char __user *buf,
@@ -782,7 +815,7 @@ static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma)
782 if (!(vma->vm_flags & VM_SHARED)) 815 if (!(vma->vm_flags & VM_SHARED))
783 return -EINVAL; 816 return -EINVAL;
784 817
785 vma->vm_flags |= VM_RESERVED; 818 vma->vm_flags |= VM_IO;
786 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 819 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
787 | _PAGE_NO_CACHE | _PAGE_GUARDED); 820 | _PAGE_NO_CACHE | _PAGE_GUARDED);
788 821
@@ -807,25 +840,41 @@ static int spufs_signal2_open(struct inode *inode, struct file *file)
807 return nonseekable_open(inode, file); 840 return nonseekable_open(inode, file);
808} 841}
809 842
810static ssize_t spufs_signal2_read(struct file *file, char __user *buf, 843static ssize_t __spufs_signal2_read(struct spu_context *ctx, char __user *buf,
811 size_t len, loff_t *pos) 844 size_t len, loff_t *pos)
812{ 845{
813 struct spu_context *ctx; 846 int ret = 0;
814 u32 data; 847 u32 data;
815 848
816 ctx = file->private_data;
817
818 if (len < 4) 849 if (len < 4)
819 return -EINVAL; 850 return -EINVAL;
820 851
821 spu_acquire(ctx); 852 if (ctx->csa.spu_chnlcnt_RW[4]) {
822 data = ctx->ops->signal2_read(ctx); 853 data = ctx->csa.spu_chnldata_RW[4];
823 spu_release(ctx); 854 ret = 4;
855 }
856
857 if (!ret)
858 goto out;
824 859
825 if (copy_to_user(buf, &data, 4)) 860 if (copy_to_user(buf, &data, 4))
826 return -EFAULT; 861 return -EFAULT;
827 862
828 return 4; 863out:
864 return ret;
865}
866
867static ssize_t spufs_signal2_read(struct file *file, char __user *buf,
868 size_t len, loff_t *pos)
869{
870 struct spu_context *ctx = file->private_data;
871 int ret;
872
873 spu_acquire_saved(ctx);
874 ret = __spufs_signal2_read(ctx, buf, len, pos);
875 spu_release(ctx);
876
877 return ret;
829} 878}
830 879
831static ssize_t spufs_signal2_write(struct file *file, const char __user *buf, 880static ssize_t spufs_signal2_write(struct file *file, const char __user *buf,
@@ -874,8 +923,7 @@ static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma)
874 if (!(vma->vm_flags & VM_SHARED)) 923 if (!(vma->vm_flags & VM_SHARED))
875 return -EINVAL; 924 return -EINVAL;
876 925
877 /* FIXME: */ 926 vma->vm_flags |= VM_IO;
878 vma->vm_flags |= VM_RESERVED;
879 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 927 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
880 | _PAGE_NO_CACHE | _PAGE_GUARDED); 928 | _PAGE_NO_CACHE | _PAGE_GUARDED);
881 929
@@ -902,13 +950,19 @@ static void spufs_signal1_type_set(void *data, u64 val)
902 spu_release(ctx); 950 spu_release(ctx);
903} 951}
904 952
953static u64 __spufs_signal1_type_get(void *data)
954{
955 struct spu_context *ctx = data;
956 return ctx->ops->signal1_type_get(ctx);
957}
958
905static u64 spufs_signal1_type_get(void *data) 959static u64 spufs_signal1_type_get(void *data)
906{ 960{
907 struct spu_context *ctx = data; 961 struct spu_context *ctx = data;
908 u64 ret; 962 u64 ret;
909 963
910 spu_acquire(ctx); 964 spu_acquire(ctx);
911 ret = ctx->ops->signal1_type_get(ctx); 965 ret = __spufs_signal1_type_get(data);
912 spu_release(ctx); 966 spu_release(ctx);
913 967
914 return ret; 968 return ret;
@@ -925,13 +979,19 @@ static void spufs_signal2_type_set(void *data, u64 val)
925 spu_release(ctx); 979 spu_release(ctx);
926} 980}
927 981
982static u64 __spufs_signal2_type_get(void *data)
983{
984 struct spu_context *ctx = data;
985 return ctx->ops->signal2_type_get(ctx);
986}
987
928static u64 spufs_signal2_type_get(void *data) 988static u64 spufs_signal2_type_get(void *data)
929{ 989{
930 struct spu_context *ctx = data; 990 struct spu_context *ctx = data;
931 u64 ret; 991 u64 ret;
932 992
933 spu_acquire(ctx); 993 spu_acquire(ctx);
934 ret = ctx->ops->signal2_type_get(ctx); 994 ret = __spufs_signal2_type_get(data);
935 spu_release(ctx); 995 spu_release(ctx);
936 996
937 return ret; 997 return ret;
@@ -958,7 +1018,7 @@ static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma)
958 if (!(vma->vm_flags & VM_SHARED)) 1018 if (!(vma->vm_flags & VM_SHARED))
959 return -EINVAL; 1019 return -EINVAL;
960 1020
961 vma->vm_flags |= VM_RESERVED; 1021 vma->vm_flags |= VM_IO;
962 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 1022 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
963 | _PAGE_NO_CACHE | _PAGE_GUARDED); 1023 | _PAGE_NO_CACHE | _PAGE_GUARDED);
964 1024
@@ -1000,7 +1060,7 @@ static int spufs_psmap_mmap(struct file *file, struct vm_area_struct *vma)
1000 if (!(vma->vm_flags & VM_SHARED)) 1060 if (!(vma->vm_flags & VM_SHARED))
1001 return -EINVAL; 1061 return -EINVAL;
1002 1062
1003 vma->vm_flags |= VM_RESERVED; 1063 vma->vm_flags |= VM_IO;
1004 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 1064 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
1005 | _PAGE_NO_CACHE | _PAGE_GUARDED); 1065 | _PAGE_NO_CACHE | _PAGE_GUARDED);
1006 1066
@@ -1041,7 +1101,7 @@ static int spufs_mfc_mmap(struct file *file, struct vm_area_struct *vma)
1041 if (!(vma->vm_flags & VM_SHARED)) 1101 if (!(vma->vm_flags & VM_SHARED))
1042 return -EINVAL; 1102 return -EINVAL;
1043 1103
1044 vma->vm_flags |= VM_RESERVED; 1104 vma->vm_flags |= VM_IO;
1045 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) 1105 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
1046 | _PAGE_NO_CACHE | _PAGE_GUARDED); 1106 | _PAGE_NO_CACHE | _PAGE_GUARDED);
1047 1107
@@ -1265,6 +1325,7 @@ static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer,
1265 goto out; 1325 goto out;
1266 1326
1267 ctx->tagwait |= 1 << cmd.tag; 1327 ctx->tagwait |= 1 << cmd.tag;
1328 ret = size;
1268 1329
1269out: 1330out:
1270 return ret; 1331 return ret;
@@ -1360,7 +1421,8 @@ static u64 spufs_npc_get(void *data)
1360 spu_release(ctx); 1421 spu_release(ctx);
1361 return ret; 1422 return ret;
1362} 1423}
1363DEFINE_SIMPLE_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set, "%llx\n") 1424DEFINE_SIMPLE_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set,
1425 "0x%llx\n")
1364 1426
1365static void spufs_decr_set(void *data, u64 val) 1427static void spufs_decr_set(void *data, u64 val)
1366{ 1428{
@@ -1371,18 +1433,24 @@ static void spufs_decr_set(void *data, u64 val)
1371 spu_release(ctx); 1433 spu_release(ctx);
1372} 1434}
1373 1435
1374static u64 spufs_decr_get(void *data) 1436static u64 __spufs_decr_get(void *data)
1375{ 1437{
1376 struct spu_context *ctx = data; 1438 struct spu_context *ctx = data;
1377 struct spu_lscsa *lscsa = ctx->csa.lscsa; 1439 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1440 return lscsa->decr.slot[0];
1441}
1442
1443static u64 spufs_decr_get(void *data)
1444{
1445 struct spu_context *ctx = data;
1378 u64 ret; 1446 u64 ret;
1379 spu_acquire_saved(ctx); 1447 spu_acquire_saved(ctx);
1380 ret = lscsa->decr.slot[0]; 1448 ret = __spufs_decr_get(data);
1381 spu_release(ctx); 1449 spu_release(ctx);
1382 return ret; 1450 return ret;
1383} 1451}
1384DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set, 1452DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set,
1385 "%llx\n") 1453 "0x%llx\n")
1386 1454
1387static void spufs_decr_status_set(void *data, u64 val) 1455static void spufs_decr_status_set(void *data, u64 val)
1388{ 1456{
@@ -1393,62 +1461,76 @@ static void spufs_decr_status_set(void *data, u64 val)
1393 spu_release(ctx); 1461 spu_release(ctx);
1394} 1462}
1395 1463
1396static u64 spufs_decr_status_get(void *data) 1464static u64 __spufs_decr_status_get(void *data)
1397{ 1465{
1398 struct spu_context *ctx = data; 1466 struct spu_context *ctx = data;
1399 struct spu_lscsa *lscsa = ctx->csa.lscsa; 1467 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1468 return lscsa->decr_status.slot[0];
1469}
1470
1471static u64 spufs_decr_status_get(void *data)
1472{
1473 struct spu_context *ctx = data;
1400 u64 ret; 1474 u64 ret;
1401 spu_acquire_saved(ctx); 1475 spu_acquire_saved(ctx);
1402 ret = lscsa->decr_status.slot[0]; 1476 ret = __spufs_decr_status_get(data);
1403 spu_release(ctx); 1477 spu_release(ctx);
1404 return ret; 1478 return ret;
1405} 1479}
1406DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get, 1480DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get,
1407 spufs_decr_status_set, "%llx\n") 1481 spufs_decr_status_set, "0x%llx\n")
1408 1482
1409static void spufs_spu_tag_mask_set(void *data, u64 val) 1483static void spufs_event_mask_set(void *data, u64 val)
1410{ 1484{
1411 struct spu_context *ctx = data; 1485 struct spu_context *ctx = data;
1412 struct spu_lscsa *lscsa = ctx->csa.lscsa; 1486 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1413 spu_acquire_saved(ctx); 1487 spu_acquire_saved(ctx);
1414 lscsa->tag_mask.slot[0] = (u32) val; 1488 lscsa->event_mask.slot[0] = (u32) val;
1415 spu_release(ctx); 1489 spu_release(ctx);
1416} 1490}
1417 1491
1418static u64 spufs_spu_tag_mask_get(void *data) 1492static u64 __spufs_event_mask_get(void *data)
1419{ 1493{
1420 struct spu_context *ctx = data; 1494 struct spu_context *ctx = data;
1421 struct spu_lscsa *lscsa = ctx->csa.lscsa; 1495 struct spu_lscsa *lscsa = ctx->csa.lscsa;
1496 return lscsa->event_mask.slot[0];
1497}
1498
1499static u64 spufs_event_mask_get(void *data)
1500{
1501 struct spu_context *ctx = data;
1422 u64 ret; 1502 u64 ret;
1423 spu_acquire_saved(ctx); 1503 spu_acquire_saved(ctx);
1424 ret = lscsa->tag_mask.slot[0]; 1504 ret = __spufs_event_mask_get(data);
1425 spu_release(ctx); 1505 spu_release(ctx);
1426 return ret; 1506 return ret;
1427} 1507}
1428DEFINE_SIMPLE_ATTRIBUTE(spufs_spu_tag_mask_ops, spufs_spu_tag_mask_get, 1508DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get,
1429 spufs_spu_tag_mask_set, "%llx\n") 1509 spufs_event_mask_set, "0x%llx\n")
1430 1510
1431static void spufs_event_mask_set(void *data, u64 val) 1511static u64 __spufs_event_status_get(void *data)
1432{ 1512{
1433 struct spu_context *ctx = data; 1513 struct spu_context *ctx = data;
1434 struct spu_lscsa *lscsa = ctx->csa.lscsa; 1514 struct spu_state *state = &ctx->csa;
1435 spu_acquire_saved(ctx); 1515 u64 stat;
1436 lscsa->event_mask.slot[0] = (u32) val; 1516 stat = state->spu_chnlcnt_RW[0];
1437 spu_release(ctx); 1517 if (stat)
1518 return state->spu_chnldata_RW[0];
1519 return 0;
1438} 1520}
1439 1521
1440static u64 spufs_event_mask_get(void *data) 1522static u64 spufs_event_status_get(void *data)
1441{ 1523{
1442 struct spu_context *ctx = data; 1524 struct spu_context *ctx = data;
1443 struct spu_lscsa *lscsa = ctx->csa.lscsa; 1525 u64 ret = 0;
1444 u64 ret; 1526
1445 spu_acquire_saved(ctx); 1527 spu_acquire_saved(ctx);
1446 ret = lscsa->event_mask.slot[0]; 1528 ret = __spufs_event_status_get(data);
1447 spu_release(ctx); 1529 spu_release(ctx);
1448 return ret; 1530 return ret;
1449} 1531}
1450DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get, 1532DEFINE_SIMPLE_ATTRIBUTE(spufs_event_status_ops, spufs_event_status_get,
1451 spufs_event_mask_set, "%llx\n") 1533 NULL, "0x%llx\n")
1452 1534
1453static void spufs_srr0_set(void *data, u64 val) 1535static void spufs_srr0_set(void *data, u64 val)
1454{ 1536{
@@ -1470,7 +1552,7 @@ static u64 spufs_srr0_get(void *data)
1470 return ret; 1552 return ret;
1471} 1553}
1472DEFINE_SIMPLE_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set, 1554DEFINE_SIMPLE_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set,
1473 "%llx\n") 1555 "0x%llx\n")
1474 1556
1475static u64 spufs_id_get(void *data) 1557static u64 spufs_id_get(void *data)
1476{ 1558{
@@ -1488,12 +1570,18 @@ static u64 spufs_id_get(void *data)
1488} 1570}
1489DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n") 1571DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n")
1490 1572
1491static u64 spufs_object_id_get(void *data) 1573static u64 __spufs_object_id_get(void *data)
1492{ 1574{
1493 struct spu_context *ctx = data; 1575 struct spu_context *ctx = data;
1494 return ctx->object_id; 1576 return ctx->object_id;
1495} 1577}
1496 1578
1579static u64 spufs_object_id_get(void *data)
1580{
1581 /* FIXME: Should there really be no locking here? */
1582 return __spufs_object_id_get(data);
1583}
1584
1497static void spufs_object_id_set(void *data, u64 id) 1585static void spufs_object_id_set(void *data, u64 id)
1498{ 1586{
1499 struct spu_context *ctx = data; 1587 struct spu_context *ctx = data;
@@ -1503,6 +1591,250 @@ static void spufs_object_id_set(void *data, u64 id)
1503DEFINE_SIMPLE_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get, 1591DEFINE_SIMPLE_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get,
1504 spufs_object_id_set, "0x%llx\n"); 1592 spufs_object_id_set, "0x%llx\n");
1505 1593
1594static u64 __spufs_lslr_get(void *data)
1595{
1596 struct spu_context *ctx = data;
1597 return ctx->csa.priv2.spu_lslr_RW;
1598}
1599
1600static u64 spufs_lslr_get(void *data)
1601{
1602 struct spu_context *ctx = data;
1603 u64 ret;
1604
1605 spu_acquire_saved(ctx);
1606 ret = __spufs_lslr_get(data);
1607 spu_release(ctx);
1608
1609 return ret;
1610}
1611DEFINE_SIMPLE_ATTRIBUTE(spufs_lslr_ops, spufs_lslr_get, NULL, "0x%llx\n")
1612
1613static int spufs_info_open(struct inode *inode, struct file *file)
1614{
1615 struct spufs_inode_info *i = SPUFS_I(inode);
1616 struct spu_context *ctx = i->i_ctx;
1617 file->private_data = ctx;
1618 return 0;
1619}
1620
1621static ssize_t __spufs_mbox_info_read(struct spu_context *ctx,
1622 char __user *buf, size_t len, loff_t *pos)
1623{
1624 u32 mbox_stat;
1625 u32 data;
1626
1627 mbox_stat = ctx->csa.prob.mb_stat_R;
1628 if (mbox_stat & 0x0000ff) {
1629 data = ctx->csa.prob.pu_mb_R;
1630 }
1631
1632 return simple_read_from_buffer(buf, len, pos, &data, sizeof data);
1633}
1634
1635static ssize_t spufs_mbox_info_read(struct file *file, char __user *buf,
1636 size_t len, loff_t *pos)
1637{
1638 int ret;
1639 struct spu_context *ctx = file->private_data;
1640
1641 if (!access_ok(VERIFY_WRITE, buf, len))
1642 return -EFAULT;
1643
1644 spu_acquire_saved(ctx);
1645 spin_lock(&ctx->csa.register_lock);
1646 ret = __spufs_mbox_info_read(ctx, buf, len, pos);
1647 spin_unlock(&ctx->csa.register_lock);
1648 spu_release(ctx);
1649
1650 return ret;
1651}
1652
1653static struct file_operations spufs_mbox_info_fops = {
1654 .open = spufs_info_open,
1655 .read = spufs_mbox_info_read,
1656 .llseek = generic_file_llseek,
1657};
1658
1659static ssize_t __spufs_ibox_info_read(struct spu_context *ctx,
1660 char __user *buf, size_t len, loff_t *pos)
1661{
1662 u32 ibox_stat;
1663 u32 data;
1664
1665 ibox_stat = ctx->csa.prob.mb_stat_R;
1666 if (ibox_stat & 0xff0000) {
1667 data = ctx->csa.priv2.puint_mb_R;
1668 }
1669
1670 return simple_read_from_buffer(buf, len, pos, &data, sizeof data);
1671}
1672
1673static ssize_t spufs_ibox_info_read(struct file *file, char __user *buf,
1674 size_t len, loff_t *pos)
1675{
1676 struct spu_context *ctx = file->private_data;
1677 int ret;
1678
1679 if (!access_ok(VERIFY_WRITE, buf, len))
1680 return -EFAULT;
1681
1682 spu_acquire_saved(ctx);
1683 spin_lock(&ctx->csa.register_lock);
1684 ret = __spufs_ibox_info_read(ctx, buf, len, pos);
1685 spin_unlock(&ctx->csa.register_lock);
1686 spu_release(ctx);
1687
1688 return ret;
1689}
1690
1691static struct file_operations spufs_ibox_info_fops = {
1692 .open = spufs_info_open,
1693 .read = spufs_ibox_info_read,
1694 .llseek = generic_file_llseek,
1695};
1696
1697static ssize_t __spufs_wbox_info_read(struct spu_context *ctx,
1698 char __user *buf, size_t len, loff_t *pos)
1699{
1700 int i, cnt;
1701 u32 data[4];
1702 u32 wbox_stat;
1703
1704 wbox_stat = ctx->csa.prob.mb_stat_R;
1705 cnt = 4 - ((wbox_stat & 0x00ff00) >> 8);
1706 for (i = 0; i < cnt; i++) {
1707 data[i] = ctx->csa.spu_mailbox_data[i];
1708 }
1709
1710 return simple_read_from_buffer(buf, len, pos, &data,
1711 cnt * sizeof(u32));
1712}
1713
1714static ssize_t spufs_wbox_info_read(struct file *file, char __user *buf,
1715 size_t len, loff_t *pos)
1716{
1717 struct spu_context *ctx = file->private_data;
1718 int ret;
1719
1720 if (!access_ok(VERIFY_WRITE, buf, len))
1721 return -EFAULT;
1722
1723 spu_acquire_saved(ctx);
1724 spin_lock(&ctx->csa.register_lock);
1725 ret = __spufs_wbox_info_read(ctx, buf, len, pos);
1726 spin_unlock(&ctx->csa.register_lock);
1727 spu_release(ctx);
1728
1729 return ret;
1730}
1731
1732static struct file_operations spufs_wbox_info_fops = {
1733 .open = spufs_info_open,
1734 .read = spufs_wbox_info_read,
1735 .llseek = generic_file_llseek,
1736};
1737
1738static ssize_t __spufs_dma_info_read(struct spu_context *ctx,
1739 char __user *buf, size_t len, loff_t *pos)
1740{
1741 struct spu_dma_info info;
1742 struct mfc_cq_sr *qp, *spuqp;
1743 int i;
1744
1745 info.dma_info_type = ctx->csa.priv2.spu_tag_status_query_RW;
1746 info.dma_info_mask = ctx->csa.lscsa->tag_mask.slot[0];
1747 info.dma_info_status = ctx->csa.spu_chnldata_RW[24];
1748 info.dma_info_stall_and_notify = ctx->csa.spu_chnldata_RW[25];
1749 info.dma_info_atomic_command_status = ctx->csa.spu_chnldata_RW[27];
1750 for (i = 0; i < 16; i++) {
1751 qp = &info.dma_info_command_data[i];
1752 spuqp = &ctx->csa.priv2.spuq[i];
1753
1754 qp->mfc_cq_data0_RW = spuqp->mfc_cq_data0_RW;
1755 qp->mfc_cq_data1_RW = spuqp->mfc_cq_data1_RW;
1756 qp->mfc_cq_data2_RW = spuqp->mfc_cq_data2_RW;
1757 qp->mfc_cq_data3_RW = spuqp->mfc_cq_data3_RW;
1758 }
1759
1760 return simple_read_from_buffer(buf, len, pos, &info,
1761 sizeof info);
1762}
1763
1764static ssize_t spufs_dma_info_read(struct file *file, char __user *buf,
1765 size_t len, loff_t *pos)
1766{
1767 struct spu_context *ctx = file->private_data;
1768 int ret;
1769
1770 if (!access_ok(VERIFY_WRITE, buf, len))
1771 return -EFAULT;
1772
1773 spu_acquire_saved(ctx);
1774 spin_lock(&ctx->csa.register_lock);
1775 ret = __spufs_dma_info_read(ctx, buf, len, pos);
1776 spin_unlock(&ctx->csa.register_lock);
1777 spu_release(ctx);
1778
1779 return ret;
1780}
1781
1782static struct file_operations spufs_dma_info_fops = {
1783 .open = spufs_info_open,
1784 .read = spufs_dma_info_read,
1785};
1786
1787static ssize_t __spufs_proxydma_info_read(struct spu_context *ctx,
1788 char __user *buf, size_t len, loff_t *pos)
1789{
1790 struct spu_proxydma_info info;
1791 struct mfc_cq_sr *qp, *puqp;
1792 int ret = sizeof info;
1793 int i;
1794
1795 if (len < ret)
1796 return -EINVAL;
1797
1798 if (!access_ok(VERIFY_WRITE, buf, len))
1799 return -EFAULT;
1800
1801 info.proxydma_info_type = ctx->csa.prob.dma_querytype_RW;
1802 info.proxydma_info_mask = ctx->csa.prob.dma_querymask_RW;
1803 info.proxydma_info_status = ctx->csa.prob.dma_tagstatus_R;
1804 for (i = 0; i < 8; i++) {
1805 qp = &info.proxydma_info_command_data[i];
1806 puqp = &ctx->csa.priv2.puq[i];
1807
1808 qp->mfc_cq_data0_RW = puqp->mfc_cq_data0_RW;
1809 qp->mfc_cq_data1_RW = puqp->mfc_cq_data1_RW;
1810 qp->mfc_cq_data2_RW = puqp->mfc_cq_data2_RW;
1811 qp->mfc_cq_data3_RW = puqp->mfc_cq_data3_RW;
1812 }
1813
1814 return simple_read_from_buffer(buf, len, pos, &info,
1815 sizeof info);
1816}
1817
1818static ssize_t spufs_proxydma_info_read(struct file *file, char __user *buf,
1819 size_t len, loff_t *pos)
1820{
1821 struct spu_context *ctx = file->private_data;
1822 int ret;
1823
1824 spu_acquire_saved(ctx);
1825 spin_lock(&ctx->csa.register_lock);
1826 ret = __spufs_proxydma_info_read(ctx, buf, len, pos);
1827 spin_unlock(&ctx->csa.register_lock);
1828 spu_release(ctx);
1829
1830 return ret;
1831}
1832
1833static struct file_operations spufs_proxydma_info_fops = {
1834 .open = spufs_info_open,
1835 .read = spufs_proxydma_info_read,
1836};
1837
1506struct tree_descr spufs_dir_contents[] = { 1838struct tree_descr spufs_dir_contents[] = {
1507 { "mem", &spufs_mem_fops, 0666, }, 1839 { "mem", &spufs_mem_fops, 0666, },
1508 { "regs", &spufs_regs_fops, 0666, }, 1840 { "regs", &spufs_regs_fops, 0666, },
@@ -1516,18 +1848,70 @@ struct tree_descr spufs_dir_contents[] = {
1516 { "signal2", &spufs_signal2_fops, 0666, }, 1848 { "signal2", &spufs_signal2_fops, 0666, },
1517 { "signal1_type", &spufs_signal1_type, 0666, }, 1849 { "signal1_type", &spufs_signal1_type, 0666, },
1518 { "signal2_type", &spufs_signal2_type, 0666, }, 1850 { "signal2_type", &spufs_signal2_type, 0666, },
1519 { "mss", &spufs_mss_fops, 0666, },
1520 { "mfc", &spufs_mfc_fops, 0666, },
1521 { "cntl", &spufs_cntl_fops, 0666, }, 1851 { "cntl", &spufs_cntl_fops, 0666, },
1522 { "npc", &spufs_npc_ops, 0666, },
1523 { "fpcr", &spufs_fpcr_fops, 0666, }, 1852 { "fpcr", &spufs_fpcr_fops, 0666, },
1853 { "lslr", &spufs_lslr_ops, 0444, },
1854 { "mfc", &spufs_mfc_fops, 0666, },
1855 { "mss", &spufs_mss_fops, 0666, },
1856 { "npc", &spufs_npc_ops, 0666, },
1857 { "srr0", &spufs_srr0_ops, 0666, },
1524 { "decr", &spufs_decr_ops, 0666, }, 1858 { "decr", &spufs_decr_ops, 0666, },
1525 { "decr_status", &spufs_decr_status_ops, 0666, }, 1859 { "decr_status", &spufs_decr_status_ops, 0666, },
1526 { "spu_tag_mask", &spufs_spu_tag_mask_ops, 0666, },
1527 { "event_mask", &spufs_event_mask_ops, 0666, }, 1860 { "event_mask", &spufs_event_mask_ops, 0666, },
1528 { "srr0", &spufs_srr0_ops, 0666, }, 1861 { "event_status", &spufs_event_status_ops, 0444, },
1862 { "psmap", &spufs_psmap_fops, 0666, },
1863 { "phys-id", &spufs_id_ops, 0666, },
1864 { "object-id", &spufs_object_id_ops, 0666, },
1865 { "mbox_info", &spufs_mbox_info_fops, 0444, },
1866 { "ibox_info", &spufs_ibox_info_fops, 0444, },
1867 { "wbox_info", &spufs_wbox_info_fops, 0444, },
1868 { "dma_info", &spufs_dma_info_fops, 0444, },
1869 { "proxydma_info", &spufs_proxydma_info_fops, 0444, },
1870 {},
1871};
1872
1873struct tree_descr spufs_dir_nosched_contents[] = {
1874 { "mem", &spufs_mem_fops, 0666, },
1875 { "mbox", &spufs_mbox_fops, 0444, },
1876 { "ibox", &spufs_ibox_fops, 0444, },
1877 { "wbox", &spufs_wbox_fops, 0222, },
1878 { "mbox_stat", &spufs_mbox_stat_fops, 0444, },
1879 { "ibox_stat", &spufs_ibox_stat_fops, 0444, },
1880 { "wbox_stat", &spufs_wbox_stat_fops, 0444, },
1881 { "signal1", &spufs_signal1_fops, 0666, },
1882 { "signal2", &spufs_signal2_fops, 0666, },
1883 { "signal1_type", &spufs_signal1_type, 0666, },
1884 { "signal2_type", &spufs_signal2_type, 0666, },
1885 { "mss", &spufs_mss_fops, 0666, },
1886 { "mfc", &spufs_mfc_fops, 0666, },
1887 { "cntl", &spufs_cntl_fops, 0666, },
1888 { "npc", &spufs_npc_ops, 0666, },
1529 { "psmap", &spufs_psmap_fops, 0666, }, 1889 { "psmap", &spufs_psmap_fops, 0666, },
1530 { "phys-id", &spufs_id_ops, 0666, }, 1890 { "phys-id", &spufs_id_ops, 0666, },
1531 { "object-id", &spufs_object_id_ops, 0666, }, 1891 { "object-id", &spufs_object_id_ops, 0666, },
1532 {}, 1892 {},
1533}; 1893};
1894
1895struct spufs_coredump_reader spufs_coredump_read[] = {
1896 { "regs", __spufs_regs_read, NULL, 128 * 16 },
1897 { "fpcr", __spufs_fpcr_read, NULL, 16 },
1898 { "lslr", NULL, __spufs_lslr_get, 11 },
1899 { "decr", NULL, __spufs_decr_get, 11 },
1900 { "decr_status", NULL, __spufs_decr_status_get, 11 },
1901 { "mem", __spufs_mem_read, NULL, 256 * 1024, },
1902 { "signal1", __spufs_signal1_read, NULL, 4 },
1903 { "signal1_type", NULL, __spufs_signal1_type_get, 2 },
1904 { "signal2", __spufs_signal2_read, NULL, 4 },
1905 { "signal2_type", NULL, __spufs_signal2_type_get, 2 },
1906 { "event_mask", NULL, __spufs_event_mask_get, 8 },
1907 { "event_status", NULL, __spufs_event_status_get, 8 },
1908 { "mbox_info", __spufs_mbox_info_read, NULL, 4 },
1909 { "ibox_info", __spufs_ibox_info_read, NULL, 4 },
1910 { "wbox_info", __spufs_wbox_info_read, NULL, 16 },
1911 { "dma_info", __spufs_dma_info_read, NULL, 69 * 8 },
1912 { "proxydma_info", __spufs_proxydma_info_read, NULL, 35 * 8 },
1913 { "object-id", NULL, __spufs_object_id_get, 19 },
1914 { },
1915};
1916int spufs_coredump_num_notes = ARRAY_SIZE(spufs_coredump_read) - 1;
1917
diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c
index d805ffed892d..ae42e03b8c86 100644
--- a/arch/powerpc/platforms/cell/spufs/hw_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c
@@ -135,21 +135,11 @@ static int spu_hw_wbox_write(struct spu_context *ctx, u32 data)
135 return ret; 135 return ret;
136} 136}
137 137
138static u32 spu_hw_signal1_read(struct spu_context *ctx)
139{
140 return in_be32(&ctx->spu->problem->signal_notify1);
141}
142
143static void spu_hw_signal1_write(struct spu_context *ctx, u32 data) 138static void spu_hw_signal1_write(struct spu_context *ctx, u32 data)
144{ 139{
145 out_be32(&ctx->spu->problem->signal_notify1, data); 140 out_be32(&ctx->spu->problem->signal_notify1, data);
146} 141}
147 142
148static u32 spu_hw_signal2_read(struct spu_context *ctx)
149{
150 return in_be32(&ctx->spu->problem->signal_notify2);
151}
152
153static void spu_hw_signal2_write(struct spu_context *ctx, u32 data) 143static void spu_hw_signal2_write(struct spu_context *ctx, u32 data)
154{ 144{
155 out_be32(&ctx->spu->problem->signal_notify2, data); 145 out_be32(&ctx->spu->problem->signal_notify2, data);
@@ -217,21 +207,42 @@ static char *spu_hw_get_ls(struct spu_context *ctx)
217 return ctx->spu->local_store; 207 return ctx->spu->local_store;
218} 208}
219 209
220static void spu_hw_runcntl_write(struct spu_context *ctx, u32 val) 210static u32 spu_hw_runcntl_read(struct spu_context *ctx)
221{ 211{
222 eieio(); 212 return in_be32(&ctx->spu->problem->spu_runcntl_RW);
223 out_be32(&ctx->spu->problem->spu_runcntl_RW, val);
224} 213}
225 214
226static void spu_hw_runcntl_stop(struct spu_context *ctx) 215static void spu_hw_runcntl_write(struct spu_context *ctx, u32 val)
227{ 216{
228 spin_lock_irq(&ctx->spu->register_lock); 217 spin_lock_irq(&ctx->spu->register_lock);
229 out_be32(&ctx->spu->problem->spu_runcntl_RW, SPU_RUNCNTL_STOP); 218 if (val & SPU_RUNCNTL_ISOLATE)
230 while (in_be32(&ctx->spu->problem->spu_status_R) & SPU_STATUS_RUNNING) 219 out_be64(&ctx->spu->priv2->spu_privcntl_RW, 4LL);
231 cpu_relax(); 220 out_be32(&ctx->spu->problem->spu_runcntl_RW, val);
232 spin_unlock_irq(&ctx->spu->register_lock); 221 spin_unlock_irq(&ctx->spu->register_lock);
233} 222}
234 223
224static void spu_hw_master_start(struct spu_context *ctx)
225{
226 struct spu *spu = ctx->spu;
227 u64 sr1;
228
229 spin_lock_irq(&spu->register_lock);
230 sr1 = spu_mfc_sr1_get(spu) | MFC_STATE1_MASTER_RUN_CONTROL_MASK;
231 spu_mfc_sr1_set(spu, sr1);
232 spin_unlock_irq(&spu->register_lock);
233}
234
235static void spu_hw_master_stop(struct spu_context *ctx)
236{
237 struct spu *spu = ctx->spu;
238 u64 sr1;
239
240 spin_lock_irq(&spu->register_lock);
241 sr1 = spu_mfc_sr1_get(spu) & ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
242 spu_mfc_sr1_set(spu, sr1);
243 spin_unlock_irq(&spu->register_lock);
244}
245
235static int spu_hw_set_mfc_query(struct spu_context * ctx, u32 mask, u32 mode) 246static int spu_hw_set_mfc_query(struct spu_context * ctx, u32 mask, u32 mode)
236{ 247{
237 struct spu_problem __iomem *prob = ctx->spu->problem; 248 struct spu_problem __iomem *prob = ctx->spu->problem;
@@ -291,9 +302,7 @@ struct spu_context_ops spu_hw_ops = {
291 .mbox_stat_poll = spu_hw_mbox_stat_poll, 302 .mbox_stat_poll = spu_hw_mbox_stat_poll,
292 .ibox_read = spu_hw_ibox_read, 303 .ibox_read = spu_hw_ibox_read,
293 .wbox_write = spu_hw_wbox_write, 304 .wbox_write = spu_hw_wbox_write,
294 .signal1_read = spu_hw_signal1_read,
295 .signal1_write = spu_hw_signal1_write, 305 .signal1_write = spu_hw_signal1_write,
296 .signal2_read = spu_hw_signal2_read,
297 .signal2_write = spu_hw_signal2_write, 306 .signal2_write = spu_hw_signal2_write,
298 .signal1_type_set = spu_hw_signal1_type_set, 307 .signal1_type_set = spu_hw_signal1_type_set,
299 .signal1_type_get = spu_hw_signal1_type_get, 308 .signal1_type_get = spu_hw_signal1_type_get,
@@ -303,8 +312,10 @@ struct spu_context_ops spu_hw_ops = {
303 .npc_write = spu_hw_npc_write, 312 .npc_write = spu_hw_npc_write,
304 .status_read = spu_hw_status_read, 313 .status_read = spu_hw_status_read,
305 .get_ls = spu_hw_get_ls, 314 .get_ls = spu_hw_get_ls,
315 .runcntl_read = spu_hw_runcntl_read,
306 .runcntl_write = spu_hw_runcntl_write, 316 .runcntl_write = spu_hw_runcntl_write,
307 .runcntl_stop = spu_hw_runcntl_stop, 317 .master_start = spu_hw_master_start,
318 .master_stop = spu_hw_master_stop,
308 .set_mfc_query = spu_hw_set_mfc_query, 319 .set_mfc_query = spu_hw_set_mfc_query,
309 .read_mfc_tagstatus = spu_hw_read_mfc_tagstatus, 320 .read_mfc_tagstatus = spu_hw_read_mfc_tagstatus,
310 .get_mfc_free_elements = spu_hw_get_mfc_free_elements, 321 .get_mfc_free_elements = spu_hw_get_mfc_free_elements,
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 427d00a4f6a0..c7d010749a18 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -33,7 +33,7 @@
33#include <linux/slab.h> 33#include <linux/slab.h>
34#include <linux/parser.h> 34#include <linux/parser.h>
35 35
36#include <asm/io.h> 36#include <asm/prom.h>
37#include <asm/semaphore.h> 37#include <asm/semaphore.h>
38#include <asm/spu.h> 38#include <asm/spu.h>
39#include <asm/uaccess.h> 39#include <asm/uaccess.h>
@@ -41,6 +41,7 @@
41#include "spufs.h" 41#include "spufs.h"
42 42
43static kmem_cache_t *spufs_inode_cache; 43static kmem_cache_t *spufs_inode_cache;
44char *isolated_loader;
44 45
45static struct inode * 46static struct inode *
46spufs_alloc_inode(struct super_block *sb) 47spufs_alloc_inode(struct super_block *sb)
@@ -231,6 +232,7 @@ struct file_operations spufs_context_fops = {
231 .readdir = dcache_readdir, 232 .readdir = dcache_readdir,
232 .fsync = simple_sync_file, 233 .fsync = simple_sync_file,
233}; 234};
235EXPORT_SYMBOL_GPL(spufs_context_fops);
234 236
235static int 237static int
236spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, 238spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
@@ -255,10 +257,14 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
255 goto out_iput; 257 goto out_iput;
256 258
257 ctx->flags = flags; 259 ctx->flags = flags;
258
259 inode->i_op = &spufs_dir_inode_operations; 260 inode->i_op = &spufs_dir_inode_operations;
260 inode->i_fop = &simple_dir_operations; 261 inode->i_fop = &simple_dir_operations;
261 ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx); 262 if (flags & SPU_CREATE_NOSCHED)
263 ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents,
264 mode, ctx);
265 else
266 ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx);
267
262 if (ret) 268 if (ret)
263 goto out_free_ctx; 269 goto out_free_ctx;
264 270
@@ -307,6 +313,20 @@ static int spufs_create_context(struct inode *inode,
307{ 313{
308 int ret; 314 int ret;
309 315
316 ret = -EPERM;
317 if ((flags & SPU_CREATE_NOSCHED) &&
318 !capable(CAP_SYS_NICE))
319 goto out_unlock;
320
321 ret = -EINVAL;
322 if ((flags & (SPU_CREATE_NOSCHED | SPU_CREATE_ISOLATE))
323 == SPU_CREATE_ISOLATE)
324 goto out_unlock;
325
326 ret = -ENODEV;
327 if ((flags & SPU_CREATE_ISOLATE) && !isolated_loader)
328 goto out_unlock;
329
310 ret = spufs_mkdir(inode, dentry, flags, mode & S_IRWXUGO); 330 ret = spufs_mkdir(inode, dentry, flags, mode & S_IRWXUGO);
311 if (ret) 331 if (ret)
312 goto out_unlock; 332 goto out_unlock;
@@ -540,6 +560,30 @@ spufs_parse_options(char *options, struct inode *root)
540 return 1; 560 return 1;
541} 561}
542 562
563static void
564spufs_init_isolated_loader(void)
565{
566 struct device_node *dn;
567 const char *loader;
568 int size;
569
570 dn = of_find_node_by_path("/spu-isolation");
571 if (!dn)
572 return;
573
574 loader = get_property(dn, "loader", &size);
575 if (!loader)
576 return;
577
578 /* kmalloc should align on a 16 byte boundary..* */
579 isolated_loader = kmalloc(size, GFP_KERNEL);
580 if (!isolated_loader)
581 return;
582
583 memcpy(isolated_loader, loader, size);
584 printk(KERN_INFO "spufs: SPU isolation mode enabled\n");
585}
586
543static int 587static int
544spufs_create_root(struct super_block *sb, void *data) 588spufs_create_root(struct super_block *sb, void *data)
545{ 589{
@@ -608,6 +652,7 @@ static struct file_system_type spufs_type = {
608static int __init spufs_init(void) 652static int __init spufs_init(void)
609{ 653{
610 int ret; 654 int ret;
655
611 ret = -ENOMEM; 656 ret = -ENOMEM;
612 spufs_inode_cache = kmem_cache_create("spufs_inode_cache", 657 spufs_inode_cache = kmem_cache_create("spufs_inode_cache",
613 sizeof(struct spufs_inode_info), 0, 658 sizeof(struct spufs_inode_info), 0,
@@ -625,6 +670,12 @@ static int __init spufs_init(void)
625 ret = register_spu_syscalls(&spufs_calls); 670 ret = register_spu_syscalls(&spufs_calls);
626 if (ret) 671 if (ret)
627 goto out_fs; 672 goto out_fs;
673 ret = register_arch_coredump_calls(&spufs_coredump_calls);
674 if (ret)
675 goto out_fs;
676
677 spufs_init_isolated_loader();
678
628 return 0; 679 return 0;
629out_fs: 680out_fs:
630 unregister_filesystem(&spufs_type); 681 unregister_filesystem(&spufs_type);
@@ -638,6 +689,7 @@ module_init(spufs_init);
638static void __exit spufs_exit(void) 689static void __exit spufs_exit(void)
639{ 690{
640 spu_sched_exit(); 691 spu_sched_exit();
692 unregister_arch_coredump_calls(&spufs_coredump_calls);
641 unregister_spu_syscalls(&spufs_calls); 693 unregister_spu_syscalls(&spufs_calls);
642 unregister_filesystem(&spufs_type); 694 unregister_filesystem(&spufs_type);
643 kmem_cache_destroy(spufs_inode_cache); 695 kmem_cache_destroy(spufs_inode_cache);
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index 63df8cf4ba16..1acc2ffef8c8 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -1,7 +1,11 @@
1#define DEBUG
2
1#include <linux/wait.h> 3#include <linux/wait.h>
2#include <linux/ptrace.h> 4#include <linux/ptrace.h>
3 5
4#include <asm/spu.h> 6#include <asm/spu.h>
7#include <asm/spu_priv1.h>
8#include <asm/io.h>
5#include <asm/unistd.h> 9#include <asm/unistd.h>
6 10
7#include "spufs.h" 11#include "spufs.h"
@@ -24,6 +28,7 @@ void spufs_dma_callback(struct spu *spu, int type)
24 } else { 28 } else {
25 switch (type) { 29 switch (type) {
26 case SPE_EVENT_DMA_ALIGNMENT: 30 case SPE_EVENT_DMA_ALIGNMENT:
31 case SPE_EVENT_SPE_DATA_STORAGE:
27 case SPE_EVENT_INVALID_DMA: 32 case SPE_EVENT_INVALID_DMA:
28 force_sig(SIGBUS, /* info, */ current); 33 force_sig(SIGBUS, /* info, */ current);
29 break; 34 break;
@@ -48,15 +53,122 @@ static inline int spu_stopped(struct spu_context *ctx, u32 * stat)
48 return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0; 53 return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0;
49} 54}
50 55
56static int spu_setup_isolated(struct spu_context *ctx)
57{
58 int ret;
59 u64 __iomem *mfc_cntl;
60 u64 sr1;
61 u32 status;
62 unsigned long timeout;
63 const u32 status_loading = SPU_STATUS_RUNNING
64 | SPU_STATUS_ISOLATED_STATE | SPU_STATUS_ISOLATED_LOAD_STATUS;
65
66 if (!isolated_loader)
67 return -ENODEV;
68
69 ret = spu_acquire_exclusive(ctx);
70 if (ret)
71 goto out;
72
73 mfc_cntl = &ctx->spu->priv2->mfc_control_RW;
74
75 /* purge the MFC DMA queue to ensure no spurious accesses before we
76 * enter kernel mode */
77 timeout = jiffies + HZ;
78 out_be64(mfc_cntl, MFC_CNTL_PURGE_DMA_REQUEST);
79 while ((in_be64(mfc_cntl) & MFC_CNTL_PURGE_DMA_STATUS_MASK)
80 != MFC_CNTL_PURGE_DMA_COMPLETE) {
81 if (time_after(jiffies, timeout)) {
82 printk(KERN_ERR "%s: timeout flushing MFC DMA queue\n",
83 __FUNCTION__);
84 ret = -EIO;
85 goto out_unlock;
86 }
87 cond_resched();
88 }
89
90 /* put the SPE in kernel mode to allow access to the loader */
91 sr1 = spu_mfc_sr1_get(ctx->spu);
92 sr1 &= ~MFC_STATE1_PROBLEM_STATE_MASK;
93 spu_mfc_sr1_set(ctx->spu, sr1);
94
95 /* start the loader */
96 ctx->ops->signal1_write(ctx, (unsigned long)isolated_loader >> 32);
97 ctx->ops->signal2_write(ctx,
98 (unsigned long)isolated_loader & 0xffffffff);
99
100 ctx->ops->runcntl_write(ctx,
101 SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE);
102
103 ret = 0;
104 timeout = jiffies + HZ;
105 while (((status = ctx->ops->status_read(ctx)) & status_loading) ==
106 status_loading) {
107 if (time_after(jiffies, timeout)) {
108 printk(KERN_ERR "%s: timeout waiting for loader\n",
109 __FUNCTION__);
110 ret = -EIO;
111 goto out_drop_priv;
112 }
113 cond_resched();
114 }
115
116 if (!(status & SPU_STATUS_RUNNING)) {
117 /* If isolated LOAD has failed: run SPU, we will get a stop-and
118 * signal later. */
119 pr_debug("%s: isolated LOAD failed\n", __FUNCTION__);
120 ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
121 ret = -EACCES;
122
123 } else if (!(status & SPU_STATUS_ISOLATED_STATE)) {
124 /* This isn't allowed by the CBEA, but check anyway */
125 pr_debug("%s: SPU fell out of isolated mode?\n", __FUNCTION__);
126 ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_STOP);
127 ret = -EINVAL;
128 }
129
130out_drop_priv:
131 /* Finished accessing the loader. Drop kernel mode */
132 sr1 |= MFC_STATE1_PROBLEM_STATE_MASK;
133 spu_mfc_sr1_set(ctx->spu, sr1);
134
135out_unlock:
136 spu_release_exclusive(ctx);
137out:
138 return ret;
139}
140
51static inline int spu_run_init(struct spu_context *ctx, u32 * npc) 141static inline int spu_run_init(struct spu_context *ctx, u32 * npc)
52{ 142{
53 int ret; 143 int ret;
144 unsigned long runcntl = SPU_RUNCNTL_RUNNABLE;
54 145
55 if ((ret = spu_acquire_runnable(ctx)) != 0) 146 ret = spu_acquire_runnable(ctx);
147 if (ret)
56 return ret; 148 return ret;
57 ctx->ops->npc_write(ctx, *npc); 149
58 ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); 150 if (ctx->flags & SPU_CREATE_ISOLATE) {
59 return 0; 151 if (!(ctx->ops->status_read(ctx) & SPU_STATUS_ISOLATED_STATE)) {
152 /* Need to release ctx, because spu_setup_isolated will
153 * acquire it exclusively.
154 */
155 spu_release(ctx);
156 ret = spu_setup_isolated(ctx);
157 if (!ret)
158 ret = spu_acquire_runnable(ctx);
159 }
160
161 /* if userspace has set the runcntrl register (eg, to issue an
162 * isolated exit), we need to re-set it here */
163 runcntl = ctx->ops->runcntl_read(ctx) &
164 (SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE);
165 if (runcntl == 0)
166 runcntl = SPU_RUNCNTL_RUNNABLE;
167 } else
168 ctx->ops->npc_write(ctx, *npc);
169
170 ctx->ops->runcntl_write(ctx, runcntl);
171 return ret;
60} 172}
61 173
62static inline int spu_run_fini(struct spu_context *ctx, u32 * npc, 174static inline int spu_run_fini(struct spu_context *ctx, u32 * npc,
@@ -70,13 +182,7 @@ static inline int spu_run_fini(struct spu_context *ctx, u32 * npc,
70 182
71 if (signal_pending(current)) 183 if (signal_pending(current))
72 ret = -ERESTARTSYS; 184 ret = -ERESTARTSYS;
73 if (unlikely(current->ptrace & PT_PTRACED)) { 185
74 if ((*status & SPU_STATUS_STOPPED_BY_STOP)
75 && (*status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) {
76 force_sig(SIGTRAP, current);
77 ret = -ERESTARTSYS;
78 }
79 }
80 return ret; 186 return ret;
81} 187}
82 188
@@ -204,6 +310,7 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
204 if (down_interruptible(&ctx->run_sema)) 310 if (down_interruptible(&ctx->run_sema))
205 return -ERESTARTSYS; 311 return -ERESTARTSYS;
206 312
313 ctx->ops->master_start(ctx);
207 ctx->event_return = 0; 314 ctx->event_return = 0;
208 ret = spu_run_init(ctx, npc); 315 ret = spu_run_init(ctx, npc);
209 if (ret) 316 if (ret)
@@ -223,7 +330,7 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
223 if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { 330 if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
224 ret = spu_reacquire_runnable(ctx, npc, &status); 331 ret = spu_reacquire_runnable(ctx, npc, &status);
225 if (ret) 332 if (ret)
226 goto out; 333 goto out2;
227 continue; 334 continue;
228 } 335 }
229 ret = spu_process_events(ctx); 336 ret = spu_process_events(ctx);
@@ -231,12 +338,24 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
231 } while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP | 338 } while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP |
232 SPU_STATUS_STOPPED_BY_HALT))); 339 SPU_STATUS_STOPPED_BY_HALT)));
233 340
234 ctx->ops->runcntl_stop(ctx); 341 ctx->ops->master_stop(ctx);
235 ret = spu_run_fini(ctx, npc, &status); 342 ret = spu_run_fini(ctx, npc, &status);
236 if (!ret)
237 ret = status;
238 spu_yield(ctx); 343 spu_yield(ctx);
239 344
345out2:
346 if ((ret == 0) ||
347 ((ret == -ERESTARTSYS) &&
348 ((status & SPU_STATUS_STOPPED_BY_HALT) ||
349 ((status & SPU_STATUS_STOPPED_BY_STOP) &&
350 (status >> SPU_STOP_STATUS_SHIFT != 0x2104)))))
351 ret = status;
352
353 if ((status & SPU_STATUS_STOPPED_BY_STOP)
354 && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) {
355 force_sig(SIGTRAP, current);
356 ret = -ERESTARTSYS;
357 }
358
240out: 359out:
241 *event = ctx->event_return; 360 *event = ctx->event_return;
242 up(&ctx->run_sema); 361 up(&ctx->run_sema);
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index a0f55ca2d488..70fb13395c04 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -29,6 +29,7 @@
29 29
30#include <asm/spu.h> 30#include <asm/spu.h>
31#include <asm/spu_csa.h> 31#include <asm/spu_csa.h>
32#include <asm/spu_info.h>
32 33
33/* The magic number for our file system */ 34/* The magic number for our file system */
34enum { 35enum {
@@ -114,13 +115,19 @@ struct spu_context_ops {
114 void (*npc_write) (struct spu_context * ctx, u32 data); 115 void (*npc_write) (struct spu_context * ctx, u32 data);
115 u32(*status_read) (struct spu_context * ctx); 116 u32(*status_read) (struct spu_context * ctx);
116 char*(*get_ls) (struct spu_context * ctx); 117 char*(*get_ls) (struct spu_context * ctx);
118 u32 (*runcntl_read) (struct spu_context * ctx);
117 void (*runcntl_write) (struct spu_context * ctx, u32 data); 119 void (*runcntl_write) (struct spu_context * ctx, u32 data);
118 void (*runcntl_stop) (struct spu_context * ctx); 120 void (*master_start) (struct spu_context * ctx);
121 void (*master_stop) (struct spu_context * ctx);
119 int (*set_mfc_query)(struct spu_context * ctx, u32 mask, u32 mode); 122 int (*set_mfc_query)(struct spu_context * ctx, u32 mask, u32 mode);
120 u32 (*read_mfc_tagstatus)(struct spu_context * ctx); 123 u32 (*read_mfc_tagstatus)(struct spu_context * ctx);
121 u32 (*get_mfc_free_elements)(struct spu_context *ctx); 124 u32 (*get_mfc_free_elements)(struct spu_context *ctx);
122 int (*send_mfc_command)(struct spu_context *ctx, 125 int (*send_mfc_command)(struct spu_context * ctx,
123 struct mfc_dma_command *cmd); 126 struct mfc_dma_command * cmd);
127 void (*dma_info_read) (struct spu_context * ctx,
128 struct spu_dma_info * info);
129 void (*proxydma_info_read) (struct spu_context * ctx,
130 struct spu_proxydma_info * info);
124}; 131};
125 132
126extern struct spu_context_ops spu_hw_ops; 133extern struct spu_context_ops spu_hw_ops;
@@ -135,6 +142,7 @@ struct spufs_inode_info {
135 container_of(inode, struct spufs_inode_info, vfs_inode) 142 container_of(inode, struct spufs_inode_info, vfs_inode)
136 143
137extern struct tree_descr spufs_dir_contents[]; 144extern struct tree_descr spufs_dir_contents[];
145extern struct tree_descr spufs_dir_nosched_contents[];
138 146
139/* system call implementation */ 147/* system call implementation */
140long spufs_run_spu(struct file *file, 148long spufs_run_spu(struct file *file,
@@ -162,6 +170,12 @@ void spu_acquire(struct spu_context *ctx);
162void spu_release(struct spu_context *ctx); 170void spu_release(struct spu_context *ctx);
163int spu_acquire_runnable(struct spu_context *ctx); 171int spu_acquire_runnable(struct spu_context *ctx);
164void spu_acquire_saved(struct spu_context *ctx); 172void spu_acquire_saved(struct spu_context *ctx);
173int spu_acquire_exclusive(struct spu_context *ctx);
174
175static inline void spu_release_exclusive(struct spu_context *ctx)
176{
177 up_write(&ctx->state_sema);
178}
165 179
166int spu_activate(struct spu_context *ctx, u64 flags); 180int spu_activate(struct spu_context *ctx, u64 flags);
167void spu_deactivate(struct spu_context *ctx); 181void spu_deactivate(struct spu_context *ctx);
@@ -169,6 +183,8 @@ void spu_yield(struct spu_context *ctx);
169int __init spu_sched_init(void); 183int __init spu_sched_init(void);
170void __exit spu_sched_exit(void); 184void __exit spu_sched_exit(void);
171 185
186extern char *isolated_loader;
187
172/* 188/*
173 * spufs_wait 189 * spufs_wait
174 * Same as wait_event_interruptible(), except that here 190 * Same as wait_event_interruptible(), except that here
@@ -207,4 +223,15 @@ void spufs_stop_callback(struct spu *spu);
207void spufs_mfc_callback(struct spu *spu); 223void spufs_mfc_callback(struct spu *spu);
208void spufs_dma_callback(struct spu *spu, int type); 224void spufs_dma_callback(struct spu *spu, int type);
209 225
226extern struct spu_coredump_calls spufs_coredump_calls;
227struct spufs_coredump_reader {
228 char *name;
229 ssize_t (*read)(struct spu_context *ctx,
230 char __user *buffer, size_t size, loff_t *pos);
231 u64 (*get)(void *data);
232 size_t size;
233};
234extern struct spufs_coredump_reader spufs_coredump_read[];
235extern int spufs_coredump_num_notes;
236
210#endif 237#endif
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index 0f782ca662ba..c08981ff7fc6 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -102,7 +102,7 @@ static inline int check_spu_isolate(struct spu_state *csa, struct spu *spu)
102 * saved at this time. 102 * saved at this time.
103 */ 103 */
104 isolate_state = SPU_STATUS_ISOLATED_STATE | 104 isolate_state = SPU_STATUS_ISOLATED_STATE |
105 SPU_STATUS_ISOLATED_LOAD_STAUTUS | SPU_STATUS_ISOLATED_EXIT_STAUTUS; 105 SPU_STATUS_ISOLATED_LOAD_STATUS | SPU_STATUS_ISOLATED_EXIT_STATUS;
106 return (in_be32(&prob->spu_status_R) & isolate_state) ? 1 : 0; 106 return (in_be32(&prob->spu_status_R) & isolate_state) ? 1 : 0;
107} 107}
108 108
@@ -1046,12 +1046,12 @@ static inline int suspend_spe(struct spu_state *csa, struct spu *spu)
1046 */ 1046 */
1047 if (in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING) { 1047 if (in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING) {
1048 if (in_be32(&prob->spu_status_R) & 1048 if (in_be32(&prob->spu_status_R) &
1049 SPU_STATUS_ISOLATED_EXIT_STAUTUS) { 1049 SPU_STATUS_ISOLATED_EXIT_STATUS) {
1050 POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & 1050 POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) &
1051 SPU_STATUS_RUNNING); 1051 SPU_STATUS_RUNNING);
1052 } 1052 }
1053 if ((in_be32(&prob->spu_status_R) & 1053 if ((in_be32(&prob->spu_status_R) &
1054 SPU_STATUS_ISOLATED_LOAD_STAUTUS) 1054 SPU_STATUS_ISOLATED_LOAD_STATUS)
1055 || (in_be32(&prob->spu_status_R) & 1055 || (in_be32(&prob->spu_status_R) &
1056 SPU_STATUS_ISOLATED_STATE)) { 1056 SPU_STATUS_ISOLATED_STATE)) {
1057 out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP); 1057 out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP);
@@ -1085,7 +1085,7 @@ static inline void clear_spu_status(struct spu_state *csa, struct spu *spu)
1085 */ 1085 */
1086 if (!(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING)) { 1086 if (!(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING)) {
1087 if (in_be32(&prob->spu_status_R) & 1087 if (in_be32(&prob->spu_status_R) &
1088 SPU_STATUS_ISOLATED_EXIT_STAUTUS) { 1088 SPU_STATUS_ISOLATED_EXIT_STATUS) {
1089 spu_mfc_sr1_set(spu, 1089 spu_mfc_sr1_set(spu,
1090 MFC_STATE1_MASTER_RUN_CONTROL_MASK); 1090 MFC_STATE1_MASTER_RUN_CONTROL_MASK);
1091 eieio(); 1091 eieio();
@@ -1095,7 +1095,7 @@ static inline void clear_spu_status(struct spu_state *csa, struct spu *spu)
1095 SPU_STATUS_RUNNING); 1095 SPU_STATUS_RUNNING);
1096 } 1096 }
1097 if ((in_be32(&prob->spu_status_R) & 1097 if ((in_be32(&prob->spu_status_R) &
1098 SPU_STATUS_ISOLATED_LOAD_STAUTUS) 1098 SPU_STATUS_ISOLATED_LOAD_STATUS)
1099 || (in_be32(&prob->spu_status_R) & 1099 || (in_be32(&prob->spu_status_R) &
1100 SPU_STATUS_ISOLATED_STATE)) { 1100 SPU_STATUS_ISOLATED_STATE)) {
1101 spu_mfc_sr1_set(spu, 1101 spu_mfc_sr1_set(spu,
@@ -1916,6 +1916,51 @@ static void save_lscsa(struct spu_state *prev, struct spu *spu)
1916 wait_spu_stopped(prev, spu); /* Step 57. */ 1916 wait_spu_stopped(prev, spu); /* Step 57. */
1917} 1917}
1918 1918
1919static void force_spu_isolate_exit(struct spu *spu)
1920{
1921 struct spu_problem __iomem *prob = spu->problem;
1922 struct spu_priv2 __iomem *priv2 = spu->priv2;
1923
1924 /* Stop SPE execution and wait for completion. */
1925 out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP);
1926 iobarrier_rw();
1927 POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING);
1928
1929 /* Restart SPE master runcntl. */
1930 spu_mfc_sr1_set(spu, MFC_STATE1_MASTER_RUN_CONTROL_MASK);
1931 iobarrier_w();
1932
1933 /* Initiate isolate exit request and wait for completion. */
1934 out_be64(&priv2->spu_privcntl_RW, 4LL);
1935 iobarrier_w();
1936 out_be32(&prob->spu_runcntl_RW, 2);
1937 iobarrier_rw();
1938 POLL_WHILE_FALSE((in_be32(&prob->spu_status_R)
1939 & SPU_STATUS_STOPPED_BY_STOP));
1940
1941 /* Reset load request to normal. */
1942 out_be64(&priv2->spu_privcntl_RW, SPU_PRIVCNT_LOAD_REQUEST_NORMAL);
1943 iobarrier_w();
1944}
1945
1946/**
1947 * stop_spu_isolate
1948 * Check SPU run-control state and force isolated
1949 * exit function as necessary.
1950 */
1951static void stop_spu_isolate(struct spu *spu)
1952{
1953 struct spu_problem __iomem *prob = spu->problem;
1954
1955 if (in_be32(&prob->spu_status_R) & SPU_STATUS_ISOLATED_STATE) {
1956 /* The SPU is in isolated state; the only way
1957 * to get it out is to perform an isolated
1958 * exit (clean) operation.
1959 */
1960 force_spu_isolate_exit(spu);
1961 }
1962}
1963
1919static void harvest(struct spu_state *prev, struct spu *spu) 1964static void harvest(struct spu_state *prev, struct spu *spu)
1920{ 1965{
1921 /* 1966 /*
@@ -1928,6 +1973,7 @@ static void harvest(struct spu_state *prev, struct spu *spu)
1928 inhibit_user_access(prev, spu); /* Step 3. */ 1973 inhibit_user_access(prev, spu); /* Step 3. */
1929 terminate_spu_app(prev, spu); /* Step 4. */ 1974 terminate_spu_app(prev, spu); /* Step 4. */
1930 set_switch_pending(prev, spu); /* Step 5. */ 1975 set_switch_pending(prev, spu); /* Step 5. */
1976 stop_spu_isolate(spu); /* NEW. */
1931 remove_other_spu_access(prev, spu); /* Step 6. */ 1977 remove_other_spu_access(prev, spu); /* Step 6. */
1932 suspend_mfc(prev, spu); /* Step 7. */ 1978 suspend_mfc(prev, spu); /* Step 7. */
1933 wait_suspend_mfc_complete(prev, spu); /* Step 8. */ 1979 wait_suspend_mfc_complete(prev, spu); /* Step 8. */
@@ -2096,11 +2142,11 @@ int spu_save(struct spu_state *prev, struct spu *spu)
2096 acquire_spu_lock(spu); /* Step 1. */ 2142 acquire_spu_lock(spu); /* Step 1. */
2097 rc = __do_spu_save(prev, spu); /* Steps 2-53. */ 2143 rc = __do_spu_save(prev, spu); /* Steps 2-53. */
2098 release_spu_lock(spu); 2144 release_spu_lock(spu);
2099 if (rc) { 2145 if (rc != 0 && rc != 2 && rc != 6) {
2100 panic("%s failed on SPU[%d], rc=%d.\n", 2146 panic("%s failed on SPU[%d], rc=%d.\n",
2101 __func__, spu->number, rc); 2147 __func__, spu->number, rc);
2102 } 2148 }
2103 return rc; 2149 return 0;
2104} 2150}
2105EXPORT_SYMBOL_GPL(spu_save); 2151EXPORT_SYMBOL_GPL(spu_save);
2106 2152
@@ -2165,9 +2211,6 @@ static void init_priv1(struct spu_state *csa)
2165 MFC_STATE1_PROBLEM_STATE_MASK | 2211 MFC_STATE1_PROBLEM_STATE_MASK |
2166 MFC_STATE1_RELOCATE_MASK | MFC_STATE1_BUS_TLBIE_MASK; 2212 MFC_STATE1_RELOCATE_MASK | MFC_STATE1_BUS_TLBIE_MASK;
2167 2213
2168 /* Set storage description. */
2169 csa->priv1.mfc_sdr_RW = mfspr(SPRN_SDR1);
2170
2171 /* Enable OS-specific set of interrupts. */ 2214 /* Enable OS-specific set of interrupts. */
2172 csa->priv1.int_mask_class0_RW = CLASS0_ENABLE_DMA_ALIGNMENT_INTR | 2215 csa->priv1.int_mask_class0_RW = CLASS0_ENABLE_DMA_ALIGNMENT_INTR |
2173 CLASS0_ENABLE_INVALID_DMA_COMMAND_INTR | 2216 CLASS0_ENABLE_INVALID_DMA_COMMAND_INTR |
diff --git a/arch/powerpc/platforms/chrp/chrp.h b/arch/powerpc/platforms/chrp/chrp.h
index 996c28744e96..63f0aee4c158 100644
--- a/arch/powerpc/platforms/chrp/chrp.h
+++ b/arch/powerpc/platforms/chrp/chrp.h
@@ -9,4 +9,3 @@ extern long chrp_time_init(void);
9 9
10extern void chrp_find_bridges(void); 10extern void chrp_find_bridges(void);
11extern void chrp_event_scan(unsigned long); 11extern void chrp_event_scan(unsigned long);
12extern void chrp_pcibios_fixup(void);
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index 0f4340506c75..ddb4a116ea89 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -156,15 +156,6 @@ hydra_init(void)
156 return 1; 156 return 1;
157} 157}
158 158
159void __init
160chrp_pcibios_fixup(void)
161{
162 struct pci_dev *dev = NULL;
163
164 for_each_pci_dev(dev)
165 pci_read_irq_line(dev);
166}
167
168#define PRG_CL_RESET_VALID 0x00010000 159#define PRG_CL_RESET_VALID 0x00010000
169 160
170static void __init 161static void __init
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 49b8dabcbc99..e1f51d455984 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -588,7 +588,6 @@ static int __init chrp_probe(void)
588 ISA_DMA_THRESHOLD = ~0L; 588 ISA_DMA_THRESHOLD = ~0L;
589 DMA_MODE_READ = 0x44; 589 DMA_MODE_READ = 0x44;
590 DMA_MODE_WRITE = 0x48; 590 DMA_MODE_WRITE = 0x48;
591 isa_io_base = CHRP_ISA_IO_BASE; /* default value */
592 591
593 return 1; 592 return 1;
594} 593}
@@ -600,7 +599,6 @@ define_machine(chrp) {
600 .init = chrp_init2, 599 .init = chrp_init2,
601 .show_cpuinfo = chrp_show_cpuinfo, 600 .show_cpuinfo = chrp_show_cpuinfo,
602 .init_IRQ = chrp_init_IRQ, 601 .init_IRQ = chrp_init_IRQ,
603 .pcibios_fixup = chrp_pcibios_fixup,
604 .restart = rtas_restart, 602 .restart = rtas_restart,
605 .power_off = rtas_power_off, 603 .power_off = rtas_power_off,
606 .halt = rtas_halt, 604 .halt = rtas_halt,
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index 234a861870a8..ddbe398fbd48 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -74,6 +74,18 @@ config SANDPOINT
74 Select SANDPOINT if configuring for a Motorola Sandpoint X3 74 Select SANDPOINT if configuring for a Motorola Sandpoint X3
75 (any flavor). 75 (any flavor).
76 76
77config LINKSTATION
78 bool "Linkstation / Kurobox(HG) from Buffalo"
79 select MPIC
80 select FSL_SOC
81 select PPC_UDBG_16550 if SERIAL_8250
82 help
83 Select LINKSTATION if configuring for one of PPC- (MPC8241)
84 based NAS systems from Buffalo Technology. So far only
85 KuroboxHG has been tested. In the future classical Kurobox,
86 Linkstation-I HD-HLAN and HD-HGLAN versions, and PPC-based
87 Terastation systems should be supported too.
88
77config MPC7448HPC2 89config MPC7448HPC2
78 bool "Freescale MPC7448HPC2(Taiga)" 90 bool "Freescale MPC7448HPC2(Taiga)"
79 select TSI108_BRIDGE 91 select TSI108_BRIDGE
@@ -146,15 +158,6 @@ config PQ2FADS
146 Select PQ2FADS if you wish to configure for a Freescale 158 Select PQ2FADS if you wish to configure for a Freescale
147 PQ2FADS board (-VR or -ZU). 159 PQ2FADS board (-VR or -ZU).
148 160
149config LITE5200
150 bool "Freescale LITE5200 / (IceCube)"
151 select PPC_MPC52xx
152 help
153 Support for the LITE5200 dev board for the MPC5200 from Freescale.
154 This is for the LITE5200 version 2.0 board. Don't know if it changes
155 much but it's only been tested on this board version. I think this
156 board is also known as IceCube.
157
158config EV64360 161config EV64360
159 bool "Marvell-EV64360BP" 162 bool "Marvell-EV64360BP"
160 help 163 help
@@ -172,9 +175,6 @@ config TQM8xxL
172 depends on 8xx && (TQM823L || TQM850L || FPS850L || TQM855L || TQM860L) 175 depends on 8xx && (TQM823L || TQM850L || FPS850L || TQM855L || TQM860L)
173 default y 176 default y
174 177
175config PPC_MPC52xx
176 bool
177
178config 8260 178config 8260
179 bool "CPM2 Support" if WILLOW 179 bool "CPM2 Support" if WILLOW
180 depends on 6xx 180 depends on 6xx
@@ -208,7 +208,7 @@ config PPC_GEN550
208 depends on SANDPOINT || SPRUCE || PPLUS || \ 208 depends on SANDPOINT || SPRUCE || PPLUS || \
209 PRPMC750 || PRPMC800 || LOPEC || \ 209 PRPMC750 || PRPMC800 || LOPEC || \
210 (EV64260 && !SERIAL_MPSC) || CHESTNUT || RADSTONE_PPC7D || \ 210 (EV64260 && !SERIAL_MPSC) || CHESTNUT || RADSTONE_PPC7D || \
211 83xx 211 83xx || LINKSTATION
212 default y 212 default y
213 213
214config FORCE 214config FORCE
@@ -282,13 +282,13 @@ config EPIC_SERIAL_MODE
282 282
283config MPC10X_BRIDGE 283config MPC10X_BRIDGE
284 bool 284 bool
285 depends on POWERPMC250 || LOPEC || SANDPOINT 285 depends on POWERPMC250 || LOPEC || SANDPOINT || LINKSTATION
286 select PPC_INDIRECT_PCI 286 select PPC_INDIRECT_PCI
287 default y 287 default y
288 288
289config MPC10X_OPENPIC 289config MPC10X_OPENPIC
290 bool 290 bool
291 depends on POWERPMC250 || LOPEC || SANDPOINT 291 depends on POWERPMC250 || LOPEC || SANDPOINT || LINKSTATION
292 default y 292 default y
293 293
294config MPC10X_STORE_GATHERING 294config MPC10X_STORE_GATHERING
diff --git a/arch/powerpc/platforms/embedded6xx/Makefile b/arch/powerpc/platforms/embedded6xx/Makefile
index fa499fe59291..d3d11a3cd656 100644
--- a/arch/powerpc/platforms/embedded6xx/Makefile
+++ b/arch/powerpc/platforms/embedded6xx/Makefile
@@ -2,3 +2,4 @@
2# Makefile for the 6xx/7xx/7xxxx linux kernel. 2# Makefile for the 6xx/7xx/7xxxx linux kernel.
3# 3#
4obj-$(CONFIG_MPC7448HPC2) += mpc7448_hpc2.o 4obj-$(CONFIG_MPC7448HPC2) += mpc7448_hpc2.o
5obj-$(CONFIG_LINKSTATION) += linkstation.o ls_uart.o
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c
new file mode 100644
index 000000000000..61599d919ea8
--- /dev/null
+++ b/arch/powerpc/platforms/embedded6xx/linkstation.c
@@ -0,0 +1,211 @@
1/*
2 * Board setup routines for the Buffalo Linkstation / Kurobox Platform.
3 *
4 * Copyright (C) 2006 G. Liakhovetski (g.liakhovetski@gmx.de)
5 *
6 * Based on sandpoint.c by Mark A. Greer
7 *
8 * This file is licensed under the terms of the GNU General Public License
9 * version 2. This program is licensed "as is" without any warranty of
10 * any kind, whether express or implied.
11 */
12
13#include <linux/kernel.h>
14#include <linux/pci.h>
15#include <linux/initrd.h>
16#include <linux/root_dev.h>
17#include <linux/mtd/physmap.h>
18
19#include <asm/time.h>
20#include <asm/prom.h>
21#include <asm/mpic.h>
22#include <asm/mpc10x.h>
23#include <asm/pci-bridge.h>
24
25static struct mtd_partition linkstation_physmap_partitions[] = {
26 {
27 .name = "mtd_firmimg",
28 .offset = 0x000000,
29 .size = 0x300000,
30 },
31 {
32 .name = "mtd_bootcode",
33 .offset = 0x300000,
34 .size = 0x070000,
35 },
36 {
37 .name = "mtd_status",
38 .offset = 0x370000,
39 .size = 0x010000,
40 },
41 {
42 .name = "mtd_conf",
43 .offset = 0x380000,
44 .size = 0x080000,
45 },
46 {
47 .name = "mtd_allflash",
48 .offset = 0x000000,
49 .size = 0x400000,
50 },
51 {
52 .name = "mtd_data",
53 .offset = 0x310000,
54 .size = 0x0f0000,
55 },
56};
57
58static int __init add_bridge(struct device_node *dev)
59{
60 int len;
61 struct pci_controller *hose;
62 int *bus_range;
63
64 printk("Adding PCI host bridge %s\n", dev->full_name);
65
66 bus_range = (int *) get_property(dev, "bus-range", &len);
67 if (bus_range == NULL || len < 2 * sizeof(int))
68 printk(KERN_WARNING "Can't get bus-range for %s, assume"
69 " bus 0\n", dev->full_name);
70
71 hose = pcibios_alloc_controller();
72 if (hose == NULL)
73 return -ENOMEM;
74 hose->first_busno = bus_range ? bus_range[0] : 0;
75 hose->last_busno = bus_range ? bus_range[1] : 0xff;
76 hose->arch_data = dev;
77 setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
78
79 /* Interpret the "ranges" property */
80 /* This also maps the I/O region and sets isa_io/mem_base */
81 pci_process_bridge_OF_ranges(hose, dev, 1);
82
83 return 0;
84}
85
86static void __init linkstation_setup_arch(void)
87{
88 struct device_node *np;
89#ifdef CONFIG_MTD_PHYSMAP
90 physmap_set_partitions(linkstation_physmap_partitions,
91 ARRAY_SIZE(linkstation_physmap_partitions));
92#endif
93
94#ifdef CONFIG_BLK_DEV_INITRD
95 if (initrd_start)
96 ROOT_DEV = Root_RAM0;
97 else
98#endif
99#ifdef CONFIG_ROOT_NFS
100 ROOT_DEV = Root_NFS;
101#else
102 ROOT_DEV = Root_HDA1;
103#endif
104
105 /* Lookup PCI host bridges */
106 for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
107 add_bridge(np);
108
109 printk(KERN_INFO "BUFFALO Network Attached Storage Series\n");
110 printk(KERN_INFO "(C) 2002-2005 BUFFALO INC.\n");
111}
112
113/*
114 * Interrupt setup and service. Interrrupts on the linkstation come
115 * from the four PCI slots plus onboard 8241 devices: I2C, DUART.
116 */
117static void __init linkstation_init_IRQ(void)
118{
119 struct mpic *mpic;
120 struct device_node *dnp;
121 void *prop;
122 int size;
123 phys_addr_t paddr;
124
125 dnp = of_find_node_by_type(NULL, "open-pic");
126 if (dnp == NULL)
127 return;
128
129 prop = (struct device_node *)get_property(dnp, "reg", &size);
130 paddr = (phys_addr_t)of_translate_address(dnp, prop);
131
132 mpic = mpic_alloc(dnp, paddr, MPIC_PRIMARY | MPIC_WANTS_RESET, 4, 32, " EPIC ");
133 BUG_ON(mpic == NULL);
134
135 /* PCI IRQs */
136 mpic_assign_isu(mpic, 0, paddr + 0x10200);
137
138 /* I2C */
139 mpic_assign_isu(mpic, 1, paddr + 0x11000);
140
141 /* ttyS0, ttyS1 */
142 mpic_assign_isu(mpic, 2, paddr + 0x11100);
143
144 mpic_init(mpic);
145}
146
147extern void avr_uart_configure(void);
148extern void avr_uart_send(const char);
149
150static void linkstation_restart(char *cmd)
151{
152 local_irq_disable();
153
154 /* Reset system via AVR */
155 avr_uart_configure();
156 /* Send reboot command */
157 avr_uart_send('C');
158
159 for(;;) /* Spin until reset happens */
160 avr_uart_send('G'); /* "kick" */
161}
162
163static void linkstation_power_off(void)
164{
165 local_irq_disable();
166
167 /* Power down system via AVR */
168 avr_uart_configure();
169 /* send shutdown command */
170 avr_uart_send('E');
171
172 for(;;) /* Spin until power-off happens */
173 avr_uart_send('G'); /* "kick" */
174 /* NOTREACHED */
175}
176
177static void linkstation_halt(void)
178{
179 linkstation_power_off();
180 /* NOTREACHED */
181}
182
183static void linkstation_show_cpuinfo(struct seq_file *m)
184{
185 seq_printf(m, "vendor\t\t: Buffalo Technology\n");
186 seq_printf(m, "machine\t\t: Linkstation I/Kurobox(HG)\n");
187}
188
189static int __init linkstation_probe(void)
190{
191 unsigned long root;
192
193 root = of_get_flat_dt_root();
194
195 if (!of_flat_dt_is_compatible(root, "linkstation"))
196 return 0;
197 return 1;
198}
199
200define_machine(linkstation){
201 .name = "Buffalo Linkstation",
202 .probe = linkstation_probe,
203 .setup_arch = linkstation_setup_arch,
204 .init_IRQ = linkstation_init_IRQ,
205 .show_cpuinfo = linkstation_show_cpuinfo,
206 .get_irq = mpic_get_irq,
207 .restart = linkstation_restart,
208 .power_off = linkstation_power_off,
209 .halt = linkstation_halt,
210 .calibrate_decr = generic_calibrate_decr,
211};
diff --git a/arch/powerpc/platforms/embedded6xx/ls_uart.c b/arch/powerpc/platforms/embedded6xx/ls_uart.c
new file mode 100644
index 000000000000..31bcdae84823
--- /dev/null
+++ b/arch/powerpc/platforms/embedded6xx/ls_uart.c
@@ -0,0 +1,131 @@
1#include <linux/workqueue.h>
2#include <linux/string.h>
3#include <linux/delay.h>
4#include <linux/serial_reg.h>
5#include <linux/serial_8250.h>
6#include <asm/io.h>
7#include <asm/mpc10x.h>
8#include <asm/ppc_sys.h>
9#include <asm/prom.h>
10#include <asm/termbits.h>
11
12static void __iomem *avr_addr;
13static unsigned long avr_clock;
14
15static struct work_struct wd_work;
16
17static void wd_stop(void *unused)
18{
19 const char string[] = "AAAAFFFFJJJJ>>>>VVVV>>>>ZZZZVVVVKKKK";
20 int i = 0, rescue = 8;
21 int len = strlen(string);
22
23 while (rescue--) {
24 int j;
25 char lsr = in_8(avr_addr + UART_LSR);
26
27 if (lsr & (UART_LSR_THRE | UART_LSR_TEMT)) {
28 for (j = 0; j < 16 && i < len; j++, i++)
29 out_8(avr_addr + UART_TX, string[i]);
30 if (i == len) {
31 /* Read "OK" back: 4ms for the last "KKKK"
32 plus a couple bytes back */
33 msleep(7);
34 printk("linkstation: disarming the AVR watchdog: ");
35 while (in_8(avr_addr + UART_LSR) & UART_LSR_DR)
36 printk("%c", in_8(avr_addr + UART_RX));
37 break;
38 }
39 }
40 msleep(17);
41 }
42 printk("\n");
43}
44
45#define AVR_QUOT(clock) ((clock) + 8 * 9600) / (16 * 9600)
46
47void avr_uart_configure(void)
48{
49 unsigned char cval = UART_LCR_WLEN8;
50 unsigned int quot = AVR_QUOT(avr_clock);
51
52 if (!avr_addr || !avr_clock)
53 return;
54
55 out_8(avr_addr + UART_LCR, cval); /* initialise UART */
56 out_8(avr_addr + UART_MCR, 0);
57 out_8(avr_addr + UART_IER, 0);
58
59 cval |= UART_LCR_STOP | UART_LCR_PARITY | UART_LCR_EPAR;
60
61 out_8(avr_addr + UART_LCR, cval); /* Set character format */
62
63 out_8(avr_addr + UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */
64 out_8(avr_addr + UART_DLL, quot & 0xff); /* LS of divisor */
65 out_8(avr_addr + UART_DLM, quot >> 8); /* MS of divisor */
66 out_8(avr_addr + UART_LCR, cval); /* reset DLAB */
67 out_8(avr_addr + UART_FCR, UART_FCR_ENABLE_FIFO); /* enable FIFO */
68}
69
70void avr_uart_send(const char c)
71{
72 if (!avr_addr || !avr_clock)
73 return;
74
75 out_8(avr_addr + UART_TX, c);
76 out_8(avr_addr + UART_TX, c);
77 out_8(avr_addr + UART_TX, c);
78 out_8(avr_addr + UART_TX, c);
79}
80
81static void __init ls_uart_init(void)
82{
83 local_irq_disable();
84
85#ifndef CONFIG_SERIAL_8250
86 out_8(avr_addr + UART_FCR, UART_FCR_ENABLE_FIFO); /* enable FIFO */
87 out_8(avr_addr + UART_FCR, UART_FCR_ENABLE_FIFO |
88 UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); /* clear FIFOs */
89 out_8(avr_addr + UART_FCR, 0);
90 out_8(avr_addr + UART_IER, 0);
91
92 /* Clear up interrupts */
93 (void) in_8(avr_addr + UART_LSR);
94 (void) in_8(avr_addr + UART_RX);
95 (void) in_8(avr_addr + UART_IIR);
96 (void) in_8(avr_addr + UART_MSR);
97#endif
98 avr_uart_configure();
99
100 local_irq_enable();
101}
102
103static int __init ls_uarts_init(void)
104{
105 struct device_node *avr;
106 phys_addr_t phys_addr;
107 int len;
108
109 avr = of_find_node_by_path("/soc10x/serial@80004500");
110 if (!avr)
111 return -EINVAL;
112
113 avr_clock = *(u32*)get_property(avr, "clock-frequency", &len);
114 phys_addr = ((u32*)get_property(avr, "reg", &len))[0];
115
116 if (!avr_clock || !phys_addr)
117 return -EINVAL;
118
119 avr_addr = ioremap(phys_addr, 32);
120 if (!avr_addr)
121 return -EFAULT;
122
123 ls_uart_init();
124
125 INIT_WORK(&wd_work, wd_stop, NULL);
126 schedule_work(&wd_work);
127
128 return 0;
129}
130
131late_initcall(ls_uarts_init);
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
index bdb475c65cba..3fcc85f60fbf 100644
--- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
+++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
@@ -60,7 +60,7 @@ pci_dram_offset = MPC7448_HPC2_PCI_MEM_OFFSET;
60 60
61extern int tsi108_setup_pci(struct device_node *dev); 61extern int tsi108_setup_pci(struct device_node *dev);
62extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val); 62extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
63extern void tsi108_pci_int_init(void); 63extern void tsi108_pci_int_init(struct device_node *node);
64extern void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc); 64extern void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc);
65 65
66int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn) 66int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn)
@@ -71,65 +71,6 @@ int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn)
71 return PCIBIOS_SUCCESSFUL; 71 return PCIBIOS_SUCCESSFUL;
72} 72}
73 73
74/*
75 * find pci slot by devfn in interrupt map of OF tree
76 */
77u8 find_slot_by_devfn(unsigned int *interrupt_map, unsigned int devfn)
78{
79 int i;
80 unsigned int tmp;
81 for (i = 0; i < 4; i++){
82 tmp = interrupt_map[i*4*7];
83 if ((tmp >> 11) == (devfn >> 3))
84 return i;
85 }
86 return i;
87}
88
89/*
90 * Scans the interrupt map for pci device
91 */
92void mpc7448_hpc2_fixup_irq(struct pci_dev *dev)
93{
94 struct pci_controller *hose;
95 struct device_node *node;
96 const unsigned int *interrupt;
97 int busnr;
98 int len;
99 u8 slot;
100 u8 pin;
101
102 /* Lookup the hose */
103 busnr = dev->bus->number;
104 hose = pci_bus_to_hose(busnr);
105 if (!hose)
106 printk(KERN_ERR "No pci hose found\n");
107
108 /* Check it has an OF node associated */
109 node = (struct device_node *) hose->arch_data;
110 if (!node)
111 printk(KERN_ERR "No pci node found\n");
112
113 interrupt = get_property(node, "interrupt-map", &len);
114 slot = find_slot_by_devfn(interrupt, dev->devfn);
115 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
116 if (pin == 0 || pin > 4)
117 pin = 1;
118 pin--;
119 dev->irq = interrupt[slot*4*7 + pin*7 + 5];
120 DBG("TSI_PCI: dev->irq = 0x%x\n", dev->irq);
121}
122/* temporary pci irq map fixup*/
123
124void __init mpc7448_hpc2_pcibios_fixup(void)
125{
126 struct pci_dev *dev = NULL;
127 for_each_pci_dev(dev) {
128 mpc7448_hpc2_fixup_irq(dev);
129 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
130 }
131}
132
133static void __init mpc7448_hpc2_setup_arch(void) 74static void __init mpc7448_hpc2_setup_arch(void)
134{ 75{
135 struct device_node *cpu; 76 struct device_node *cpu;
@@ -192,9 +133,12 @@ static void __init mpc7448_hpc2_init_IRQ(void)
192{ 133{
193 struct mpic *mpic; 134 struct mpic *mpic;
194 phys_addr_t mpic_paddr = 0; 135 phys_addr_t mpic_paddr = 0;
136 struct device_node *tsi_pic;
137#ifdef CONFIG_PCI
195 unsigned int cascade_pci_irq; 138 unsigned int cascade_pci_irq;
196 struct device_node *tsi_pci; 139 struct device_node *tsi_pci;
197 struct device_node *tsi_pic; 140 struct device_node *cascade_node = NULL;
141#endif
198 142
199 tsi_pic = of_find_node_by_type(NULL, "open-pic"); 143 tsi_pic = of_find_node_by_type(NULL, "open-pic");
200 if (tsi_pic) { 144 if (tsi_pic) {
@@ -208,31 +152,41 @@ static void __init mpc7448_hpc2_init_IRQ(void)
208 return; 152 return;
209 } 153 }
210 154
211 DBG("%s: tsi108pic phys_addr = 0x%x\n", __FUNCTION__, 155 DBG("%s: tsi108 pic phys_addr = 0x%x\n", __FUNCTION__,
212 (u32) mpic_paddr); 156 (u32) mpic_paddr);
213 157
214 mpic = mpic_alloc(tsi_pic, mpic_paddr, 158 mpic = mpic_alloc(tsi_pic, mpic_paddr,
215 MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET | 159 MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET |
216 MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108, 160 MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108,
217 0, /* num_sources used */ 161 24,
218 0, /* num_sources used */ 162 NR_IRQS-4, /* num_sources used */
219 "Tsi108_PIC"); 163 "Tsi108_PIC");
220 164
221 BUG_ON(mpic == NULL); /* XXXX */ 165 BUG_ON(mpic == NULL);
166
167 mpic_assign_isu(mpic, 0, mpic_paddr + 0x100);
168
222 mpic_init(mpic); 169 mpic_init(mpic);
223 170
171#ifdef CONFIG_PCI
224 tsi_pci = of_find_node_by_type(NULL, "pci"); 172 tsi_pci = of_find_node_by_type(NULL, "pci");
225 if (tsi_pci == 0) { 173 if (tsi_pci == NULL) {
226 printk("%s: No tsi108 pci node found !\n", __FUNCTION__); 174 printk("%s: No tsi108 pci node found !\n", __FUNCTION__);
227 return; 175 return;
228 } 176 }
177 cascade_node = of_find_node_by_type(NULL, "pic-router");
178 if (cascade_node == NULL) {
179 printk("%s: No tsi108 pci cascade node found !\n", __FUNCTION__);
180 return;
181 }
229 182
230 cascade_pci_irq = irq_of_parse_and_map(tsi_pci, 0); 183 cascade_pci_irq = irq_of_parse_and_map(tsi_pci, 0);
184 DBG("%s: tsi108 cascade_pci_irq = 0x%x\n", __FUNCTION__,
185 (u32) cascade_pci_irq);
186 tsi108_pci_int_init(cascade_node);
231 set_irq_data(cascade_pci_irq, mpic); 187 set_irq_data(cascade_pci_irq, mpic);
232 set_irq_chained_handler(cascade_pci_irq, tsi108_irq_cascade); 188 set_irq_chained_handler(cascade_pci_irq, tsi108_irq_cascade);
233 189#endif
234 tsi108_pci_int_init();
235
236 /* Configure MPIC outputs to CPU0 */ 190 /* Configure MPIC outputs to CPU0 */
237 tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0); 191 tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0);
238 of_node_put(tsi_pic); 192 of_node_put(tsi_pic);
@@ -290,7 +244,6 @@ static int mpc7448_machine_check_exception(struct pt_regs *regs)
290 return 1; 244 return 1;
291 } 245 }
292 return 0; 246 return 0;
293
294} 247}
295 248
296define_machine(mpc7448_hpc2){ 249define_machine(mpc7448_hpc2){
@@ -300,7 +253,6 @@ define_machine(mpc7448_hpc2){
300 .init_IRQ = mpc7448_hpc2_init_IRQ, 253 .init_IRQ = mpc7448_hpc2_init_IRQ,
301 .show_cpuinfo = mpc7448_hpc2_show_cpuinfo, 254 .show_cpuinfo = mpc7448_hpc2_show_cpuinfo,
302 .get_irq = mpic_get_irq, 255 .get_irq = mpic_get_irq,
303 .pcibios_fixup = mpc7448_hpc2_pcibios_fixup,
304 .restart = mpc7448_hpc2_restart, 256 .restart = mpc7448_hpc2_restart,
305 .calibrate_decr = generic_calibrate_decr, 257 .calibrate_decr = generic_calibrate_decr,
306 .machine_check_exception= mpc7448_machine_check_exception, 258 .machine_check_exception= mpc7448_machine_check_exception,
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile
index dee4eb4d8bec..13ac3015d91c 100644
--- a/arch/powerpc/platforms/iseries/Makefile
+++ b/arch/powerpc/platforms/iseries/Makefile
@@ -1,5 +1,7 @@
1EXTRA_CFLAGS += -mno-minimal-toc 1EXTRA_CFLAGS += -mno-minimal-toc
2 2
3extra-y += dt.o
4
3obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \ 5obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \
4 hvcall.o proc.o htab.o iommu.o misc.o irq.o 6 hvcall.o proc.o htab.o iommu.o misc.o irq.o
5obj-$(CONFIG_PCI) += pci.o vpdinfo.o 7obj-$(CONFIG_PCI) += pci.o vpdinfo.o
@@ -7,5 +9,9 @@ obj-$(CONFIG_SMP) += smp.o
7obj-$(CONFIG_VIOPATH) += viopath.o 9obj-$(CONFIG_VIOPATH) += viopath.o
8obj-$(CONFIG_MODULES) += ksyms.o 10obj-$(CONFIG_MODULES) += ksyms.o
9 11
12quiet_cmd_dt_strings = DT_STR $@
13 cmd_dt_strings = $(OBJCOPY) --rename-section .rodata.str1.8=.dt_strings \
14 $< $@
15
10$(obj)/dt_mod.o: $(obj)/dt.o 16$(obj)/dt_mod.o: $(obj)/dt.o
11 @$(OBJCOPY) --rename-section .rodata.str1.8=.dt_strings $(obj)/dt.o $(obj)/dt_mod.o 17 $(call if_changed,dt_strings)
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index e305deee7f44..9e8a334a518a 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -41,6 +41,7 @@
41#include "call_pci.h" 41#include "call_pci.h"
42#include "pci.h" 42#include "pci.h"
43#include "it_exp_vpd_panel.h" 43#include "it_exp_vpd_panel.h"
44#include "naca.h"
44 45
45#ifdef DEBUG 46#ifdef DEBUG
46#define DBG(fmt...) udbg_printf(fmt) 47#define DBG(fmt...) udbg_printf(fmt)
@@ -205,13 +206,11 @@ static void __init dt_prop_u32(struct iseries_flat_dt *dt, const char *name,
205 dt_prop(dt, name, &data, sizeof(u32)); 206 dt_prop(dt, name, &data, sizeof(u32));
206} 207}
207 208
208#ifdef notyet
209static void __init dt_prop_u64(struct iseries_flat_dt *dt, const char *name, 209static void __init dt_prop_u64(struct iseries_flat_dt *dt, const char *name,
210 u64 data) 210 u64 data)
211{ 211{
212 dt_prop(dt, name, &data, sizeof(u64)); 212 dt_prop(dt, name, &data, sizeof(u64));
213} 213}
214#endif
215 214
216static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, 215static void __init dt_prop_u64_list(struct iseries_flat_dt *dt,
217 const char *name, u64 *data, int n) 216 const char *name, u64 *data, int n)
@@ -306,6 +305,17 @@ static void __init dt_model(struct iseries_flat_dt *dt)
306 dt_prop_u32(dt, "ibm,partition-no", HvLpConfig_getLpIndex()); 305 dt_prop_u32(dt, "ibm,partition-no", HvLpConfig_getLpIndex());
307} 306}
308 307
308static void __init dt_initrd(struct iseries_flat_dt *dt)
309{
310#ifdef CONFIG_BLK_DEV_INITRD
311 if (naca.xRamDisk) {
312 dt_prop_u64(dt, "linux,initrd-start", (u64)naca.xRamDisk);
313 dt_prop_u64(dt, "linux,initrd-end",
314 (u64)naca.xRamDisk + naca.xRamDiskSize * HW_PAGE_SIZE);
315 }
316#endif
317}
318
309static void __init dt_do_vdevice(struct iseries_flat_dt *dt, 319static void __init dt_do_vdevice(struct iseries_flat_dt *dt,
310 const char *name, u32 reg, int unit, 320 const char *name, u32 reg, int unit,
311 const char *type, const char *compat, int end) 321 const char *type, const char *compat, int end)
@@ -641,6 +651,7 @@ void * __init build_flat_dt(unsigned long phys_mem_size)
641 /* /chosen */ 651 /* /chosen */
642 dt_start_node(iseries_dt, "chosen"); 652 dt_start_node(iseries_dt, "chosen");
643 dt_prop_str(iseries_dt, "bootargs", cmd_line); 653 dt_prop_str(iseries_dt, "bootargs", cmd_line);
654 dt_initrd(iseries_dt);
644 dt_end_node(iseries_dt); 655 dt_end_node(iseries_dt);
645 656
646 dt_cpus(iseries_dt); 657 dt_cpus(iseries_dt);
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index 218817d13c5c..d7a756d5135c 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -27,6 +27,7 @@
27#include <linux/types.h> 27#include <linux/types.h>
28#include <linux/dma-mapping.h> 28#include <linux/dma-mapping.h>
29#include <linux/list.h> 29#include <linux/list.h>
30#include <linux/pci.h>
30 31
31#include <asm/iommu.h> 32#include <asm/iommu.h>
32#include <asm/tce.h> 33#include <asm/tce.h>
@@ -114,12 +115,10 @@ void iommu_table_getparms_iSeries(unsigned long busno,
114{ 115{
115 struct iommu_table_cb *parms; 116 struct iommu_table_cb *parms;
116 117
117 parms = kmalloc(sizeof(*parms), GFP_KERNEL); 118 parms = kzalloc(sizeof(*parms), GFP_KERNEL);
118 if (parms == NULL) 119 if (parms == NULL)
119 panic("PCI_DMA: TCE Table Allocation failed."); 120 panic("PCI_DMA: TCE Table Allocation failed.");
120 121
121 memset(parms, 0, sizeof(*parms));
122
123 parms->itc_busno = busno; 122 parms->itc_busno = busno;
124 parms->itc_slotno = slotno; 123 parms->itc_slotno = slotno;
125 parms->itc_virtbus = virtbus; 124 parms->itc_virtbus = virtbus;
@@ -168,7 +167,7 @@ static struct iommu_table *iommu_table_find(struct iommu_table * tbl)
168} 167}
169 168
170 169
171void iommu_devnode_init_iSeries(struct device_node *dn) 170void iommu_devnode_init_iSeries(struct pci_dev *pdev, struct device_node *dn)
172{ 171{
173 struct iommu_table *tbl; 172 struct iommu_table *tbl;
174 struct pci_dn *pdn = PCI_DN(dn); 173 struct pci_dn *pdn = PCI_DN(dn);
@@ -186,19 +185,14 @@ void iommu_devnode_init_iSeries(struct device_node *dn)
186 pdn->iommu_table = iommu_init_table(tbl, -1); 185 pdn->iommu_table = iommu_init_table(tbl, -1);
187 else 186 else
188 kfree(tbl); 187 kfree(tbl);
188 pdev->dev.archdata.dma_data = pdn->iommu_table;
189} 189}
190#endif 190#endif
191 191
192static void iommu_dev_setup_iSeries(struct pci_dev *dev) { }
193static void iommu_bus_setup_iSeries(struct pci_bus *bus) { }
194
195void iommu_init_early_iSeries(void) 192void iommu_init_early_iSeries(void)
196{ 193{
197 ppc_md.tce_build = tce_build_iSeries; 194 ppc_md.tce_build = tce_build_iSeries;
198 ppc_md.tce_free = tce_free_iSeries; 195 ppc_md.tce_free = tce_free_iSeries;
199 196
200 ppc_md.iommu_dev_setup = iommu_dev_setup_iSeries; 197 pci_dma_ops = &dma_iommu_ops;
201 ppc_md.iommu_bus_setup = iommu_bus_setup_iSeries;
202
203 pci_iommu_init();
204} 198}
diff --git a/arch/powerpc/platforms/iseries/ksyms.c b/arch/powerpc/platforms/iseries/ksyms.c
index a2200842f4e5..2430848b98e7 100644
--- a/arch/powerpc/platforms/iseries/ksyms.c
+++ b/arch/powerpc/platforms/iseries/ksyms.c
@@ -19,9 +19,3 @@ EXPORT_SYMBOL(HvCall4);
19EXPORT_SYMBOL(HvCall5); 19EXPORT_SYMBOL(HvCall5);
20EXPORT_SYMBOL(HvCall6); 20EXPORT_SYMBOL(HvCall6);
21EXPORT_SYMBOL(HvCall7); 21EXPORT_SYMBOL(HvCall7);
22
23#ifdef CONFIG_SMP
24EXPORT_SYMBOL(local_get_flags);
25EXPORT_SYMBOL(local_irq_disable);
26EXPORT_SYMBOL(local_irq_restore);
27#endif
diff --git a/arch/powerpc/platforms/iseries/misc.S b/arch/powerpc/platforms/iseries/misc.S
index 7641fc7e550a..2c6ff0fdac98 100644
--- a/arch/powerpc/platforms/iseries/misc.S
+++ b/arch/powerpc/platforms/iseries/misc.S
@@ -19,39 +19,8 @@
19 19
20 .text 20 .text
21 21
22/* unsigned long local_save_flags(void) */ 22/* Handle pending interrupts in interrupt context */
23_GLOBAL(local_get_flags) 23_GLOBAL(iseries_handle_interrupts)
24 lbz r3,PACAPROCENABLED(r13)
25 blr
26
27/* unsigned long local_irq_disable(void) */
28_GLOBAL(local_irq_disable)
29 lbz r3,PACAPROCENABLED(r13)
30 li r4,0
31 stb r4,PACAPROCENABLED(r13)
32 blr /* Done */
33
34/* void local_irq_restore(unsigned long flags) */
35_GLOBAL(local_irq_restore)
36 lbz r5,PACAPROCENABLED(r13)
37 /* Check if things are setup the way we want _already_. */
38 cmpw 0,r3,r5
39 beqlr
40 /* are we enabling interrupts? */
41 cmpdi 0,r3,0
42 stb r3,PACAPROCENABLED(r13)
43 beqlr
44 /* Check pending interrupts */
45 /* A decrementer, IPI or PMC interrupt may have occurred
46 * while we were in the hypervisor (which enables) */
47 ld r4,PACALPPACAPTR(r13)
48 ld r4,LPPACAANYINT(r4)
49 cmpdi r4,0
50 beqlr
51
52 /*
53 * Handle pending interrupts in interrupt context
54 */
55 li r0,0x5555 24 li r0,0x5555
56 sc 25 sc
57 blr 26 blr
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index 4aa165e010d9..4a06d9c34986 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -156,53 +156,6 @@ static void pci_Log_Error(char *Error_Text, int Bus, int SubBus,
156} 156}
157 157
158/* 158/*
159 * iSeries_pcibios_init
160 *
161 * Description:
162 * This function checks for all possible system PCI host bridges that connect
163 * PCI buses. The system hypervisor is queried as to the guest partition
164 * ownership status. A pci_controller is built for any bus which is partially
165 * owned or fully owned by this guest partition.
166 */
167void iSeries_pcibios_init(void)
168{
169 struct pci_controller *phb;
170 struct device_node *root = of_find_node_by_path("/");
171 struct device_node *node = NULL;
172
173 if (root == NULL) {
174 printk(KERN_CRIT "iSeries_pcibios_init: can't find root "
175 "of device tree\n");
176 return;
177 }
178 while ((node = of_get_next_child(root, node)) != NULL) {
179 HvBusNumber bus;
180 const u32 *busp;
181
182 if ((node->type == NULL) || (strcmp(node->type, "pci") != 0))
183 continue;
184
185 busp = get_property(node, "bus-range", NULL);
186 if (busp == NULL)
187 continue;
188 bus = *busp;
189 printk("bus %d appears to exist\n", bus);
190 phb = pcibios_alloc_controller(node);
191 if (phb == NULL)
192 continue;
193
194 phb->pci_mem_offset = phb->local_number = bus;
195 phb->first_busno = bus;
196 phb->last_busno = bus;
197 phb->ops = &iSeries_pci_ops;
198 }
199
200 of_node_put(root);
201
202 pci_devs_phb_init();
203}
204
205/*
206 * iSeries_pci_final_fixup(void) 159 * iSeries_pci_final_fixup(void)
207 */ 160 */
208void __init iSeries_pci_final_fixup(void) 161void __init iSeries_pci_final_fixup(void)
@@ -253,7 +206,7 @@ void __init iSeries_pci_final_fixup(void)
253 PCI_DN(node)->pcidev = pdev; 206 PCI_DN(node)->pcidev = pdev;
254 allocate_device_bars(pdev); 207 allocate_device_bars(pdev);
255 iSeries_Device_Information(pdev, DeviceCount); 208 iSeries_Device_Information(pdev, DeviceCount);
256 iommu_devnode_init_iSeries(node); 209 iommu_devnode_init_iSeries(pdev, node);
257 } else 210 } else
258 printk("PCI: Device Tree not found for 0x%016lX\n", 211 printk("PCI: Device Tree not found for 0x%016lX\n",
259 (unsigned long)pdev); 212 (unsigned long)pdev);
@@ -438,11 +391,7 @@ static inline struct device_node *xlate_iomm_address(
438/* 391/*
439 * Read MM I/O Instructions for the iSeries 392 * Read MM I/O Instructions for the iSeries
440 * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal 393 * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal
441 * else, data is returned in big Endian format. 394 * else, data is returned in Big Endian format.
442 *
443 * iSeries_Read_Byte = Read Byte ( 8 bit)
444 * iSeries_Read_Word = Read Word (16 bit)
445 * iSeries_Read_Long = Read Long (32 bit)
446 */ 395 */
447static u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress) 396static u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
448{ 397{
@@ -462,14 +411,15 @@ static u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
462 num_printed = 0; 411 num_printed = 0;
463 } 412 }
464 if (num_printed++ < 10) 413 if (num_printed++ < 10)
465 printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n", IoAddress); 414 printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n",
415 IoAddress);
466 return 0xff; 416 return 0xff;
467 } 417 }
468 do { 418 do {
469 HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0); 419 HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0);
470 } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0); 420 } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0);
471 421
472 return (u8)ret.value; 422 return ret.value;
473} 423}
474 424
475static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress) 425static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
@@ -490,7 +440,8 @@ static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
490 num_printed = 0; 440 num_printed = 0;
491 } 441 }
492 if (num_printed++ < 10) 442 if (num_printed++ < 10)
493 printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n", IoAddress); 443 printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n",
444 IoAddress);
494 return 0xffff; 445 return 0xffff;
495 } 446 }
496 do { 447 do {
@@ -498,7 +449,7 @@ static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
498 BarOffset, 0); 449 BarOffset, 0);
499 } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0); 450 } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0);
500 451
501 return swab16((u16)ret.value); 452 return ret.value;
502} 453}
503 454
504static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress) 455static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
@@ -519,7 +470,8 @@ static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
519 num_printed = 0; 470 num_printed = 0;
520 } 471 }
521 if (num_printed++ < 10) 472 if (num_printed++ < 10)
522 printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n", IoAddress); 473 printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n",
474 IoAddress);
523 return 0xffffffff; 475 return 0xffffffff;
524 } 476 }
525 do { 477 do {
@@ -527,15 +479,12 @@ static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
527 BarOffset, 0); 479 BarOffset, 0);
528 } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0); 480 } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0);
529 481
530 return swab32((u32)ret.value); 482 return ret.value;
531} 483}
532 484
533/* 485/*
534 * Write MM I/O Instructions for the iSeries 486 * Write MM I/O Instructions for the iSeries
535 * 487 *
536 * iSeries_Write_Byte = Write Byte (8 bit)
537 * iSeries_Write_Word = Write Word(16 bit)
538 * iSeries_Write_Long = Write Long(32 bit)
539 */ 488 */
540static void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress) 489static void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress)
541{ 490{
@@ -581,11 +530,12 @@ static void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress)
581 num_printed = 0; 530 num_printed = 0;
582 } 531 }
583 if (num_printed++ < 10) 532 if (num_printed++ < 10)
584 printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n", IoAddress); 533 printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n",
534 IoAddress);
585 return; 535 return;
586 } 536 }
587 do { 537 do {
588 rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0); 538 rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, data, 0);
589 } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0); 539 } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0);
590} 540}
591 541
@@ -607,231 +557,221 @@ static void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress)
607 num_printed = 0; 557 num_printed = 0;
608 } 558 }
609 if (num_printed++ < 10) 559 if (num_printed++ < 10)
610 printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n", IoAddress); 560 printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n",
561 IoAddress);
611 return; 562 return;
612 } 563 }
613 do { 564 do {
614 rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0); 565 rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, data, 0);
615 } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0); 566 } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0);
616} 567}
617 568
618extern unsigned char __raw_readb(const volatile void __iomem *addr) 569static u8 iseries_readb(const volatile void __iomem *addr)
619{ 570{
620 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 571 return iSeries_Read_Byte(addr);
621
622 return *(volatile unsigned char __force *)addr;
623} 572}
624EXPORT_SYMBOL(__raw_readb);
625 573
626extern unsigned short __raw_readw(const volatile void __iomem *addr) 574static u16 iseries_readw(const volatile void __iomem *addr)
627{ 575{
628 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 576 return le16_to_cpu(iSeries_Read_Word(addr));
629
630 return *(volatile unsigned short __force *)addr;
631} 577}
632EXPORT_SYMBOL(__raw_readw);
633 578
634extern unsigned int __raw_readl(const volatile void __iomem *addr) 579static u32 iseries_readl(const volatile void __iomem *addr)
635{ 580{
636 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 581 return le32_to_cpu(iSeries_Read_Long(addr));
637
638 return *(volatile unsigned int __force *)addr;
639} 582}
640EXPORT_SYMBOL(__raw_readl);
641 583
642extern unsigned long __raw_readq(const volatile void __iomem *addr) 584static u16 iseries_readw_be(const volatile void __iomem *addr)
643{ 585{
644 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 586 return iSeries_Read_Word(addr);
645
646 return *(volatile unsigned long __force *)addr;
647} 587}
648EXPORT_SYMBOL(__raw_readq);
649 588
650extern void __raw_writeb(unsigned char v, volatile void __iomem *addr) 589static u32 iseries_readl_be(const volatile void __iomem *addr)
651{ 590{
652 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 591 return iSeries_Read_Long(addr);
653
654 *(volatile unsigned char __force *)addr = v;
655} 592}
656EXPORT_SYMBOL(__raw_writeb);
657 593
658extern void __raw_writew(unsigned short v, volatile void __iomem *addr) 594static void iseries_writeb(u8 data, volatile void __iomem *addr)
659{ 595{
660 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 596 iSeries_Write_Byte(data, addr);
661
662 *(volatile unsigned short __force *)addr = v;
663} 597}
664EXPORT_SYMBOL(__raw_writew);
665 598
666extern void __raw_writel(unsigned int v, volatile void __iomem *addr) 599static void iseries_writew(u16 data, volatile void __iomem *addr)
667{ 600{
668 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 601 iSeries_Write_Word(cpu_to_le16(data), addr);
669
670 *(volatile unsigned int __force *)addr = v;
671} 602}
672EXPORT_SYMBOL(__raw_writel);
673 603
674extern void __raw_writeq(unsigned long v, volatile void __iomem *addr) 604static void iseries_writel(u32 data, volatile void __iomem *addr)
675{ 605{
676 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 606 iSeries_Write_Long(cpu_to_le32(data), addr);
677
678 *(volatile unsigned long __force *)addr = v;
679} 607}
680EXPORT_SYMBOL(__raw_writeq);
681 608
682int in_8(const volatile unsigned char __iomem *addr) 609static void iseries_writew_be(u16 data, volatile void __iomem *addr)
683{ 610{
684 if (firmware_has_feature(FW_FEATURE_ISERIES)) 611 iSeries_Write_Word(data, addr);
685 return iSeries_Read_Byte(addr);
686 return __in_8(addr);
687} 612}
688EXPORT_SYMBOL(in_8);
689 613
690void out_8(volatile unsigned char __iomem *addr, int val) 614static void iseries_writel_be(u32 data, volatile void __iomem *addr)
691{ 615{
692 if (firmware_has_feature(FW_FEATURE_ISERIES)) 616 iSeries_Write_Long(data, addr);
693 iSeries_Write_Byte(val, addr);
694 else
695 __out_8(addr, val);
696} 617}
697EXPORT_SYMBOL(out_8);
698 618
699int in_le16(const volatile unsigned short __iomem *addr) 619static void iseries_readsb(const volatile void __iomem *addr, void *buf,
620 unsigned long count)
700{ 621{
701 if (firmware_has_feature(FW_FEATURE_ISERIES)) 622 u8 *dst = buf;
702 return iSeries_Read_Word(addr); 623 while(count-- > 0)
703 return __in_le16(addr); 624 *(dst++) = iSeries_Read_Byte(addr);
704} 625}
705EXPORT_SYMBOL(in_le16);
706 626
707int in_be16(const volatile unsigned short __iomem *addr) 627static void iseries_readsw(const volatile void __iomem *addr, void *buf,
628 unsigned long count)
708{ 629{
709 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 630 u16 *dst = buf;
710 631 while(count-- > 0)
711 return __in_be16(addr); 632 *(dst++) = iSeries_Read_Word(addr);
712} 633}
713EXPORT_SYMBOL(in_be16);
714 634
715void out_le16(volatile unsigned short __iomem *addr, int val) 635static void iseries_readsl(const volatile void __iomem *addr, void *buf,
636 unsigned long count)
716{ 637{
717 if (firmware_has_feature(FW_FEATURE_ISERIES)) 638 u32 *dst = buf;
718 iSeries_Write_Word(val, addr); 639 while(count-- > 0)
719 else 640 *(dst++) = iSeries_Read_Long(addr);
720 __out_le16(addr, val);
721} 641}
722EXPORT_SYMBOL(out_le16);
723 642
724void out_be16(volatile unsigned short __iomem *addr, int val) 643static void iseries_writesb(volatile void __iomem *addr, const void *buf,
644 unsigned long count)
725{ 645{
726 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 646 const u8 *src = buf;
727 647 while(count-- > 0)
728 __out_be16(addr, val); 648 iSeries_Write_Byte(*(src++), addr);
729} 649}
730EXPORT_SYMBOL(out_be16);
731 650
732unsigned in_le32(const volatile unsigned __iomem *addr) 651static void iseries_writesw(volatile void __iomem *addr, const void *buf,
652 unsigned long count)
733{ 653{
734 if (firmware_has_feature(FW_FEATURE_ISERIES)) 654 const u16 *src = buf;
735 return iSeries_Read_Long(addr); 655 while(count-- > 0)
736 return __in_le32(addr); 656 iSeries_Write_Word(*(src++), addr);
737} 657}
738EXPORT_SYMBOL(in_le32);
739 658
740unsigned in_be32(const volatile unsigned __iomem *addr) 659static void iseries_writesl(volatile void __iomem *addr, const void *buf,
660 unsigned long count)
741{ 661{
742 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 662 const u32 *src = buf;
743 663 while(count-- > 0)
744 return __in_be32(addr); 664 iSeries_Write_Long(*(src++), addr);
745} 665}
746EXPORT_SYMBOL(in_be32);
747 666
748void out_le32(volatile unsigned __iomem *addr, int val) 667static void iseries_memset_io(volatile void __iomem *addr, int c,
668 unsigned long n)
749{ 669{
750 if (firmware_has_feature(FW_FEATURE_ISERIES)) 670 volatile char __iomem *d = addr;
751 iSeries_Write_Long(val, addr);
752 else
753 __out_le32(addr, val);
754}
755EXPORT_SYMBOL(out_le32);
756 671
757void out_be32(volatile unsigned __iomem *addr, int val) 672 while (n-- > 0)
758{ 673 iSeries_Write_Byte(c, d++);
759 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
760
761 __out_be32(addr, val);
762} 674}
763EXPORT_SYMBOL(out_be32);
764 675
765unsigned long in_le64(const volatile unsigned long __iomem *addr) 676static void iseries_memcpy_fromio(void *dest, const volatile void __iomem *src,
677 unsigned long n)
766{ 678{
767 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 679 char *d = dest;
680 const volatile char __iomem *s = src;
768 681
769 return __in_le64(addr); 682 while (n-- > 0)
683 *d++ = iSeries_Read_Byte(s++);
770} 684}
771EXPORT_SYMBOL(in_le64);
772 685
773unsigned long in_be64(const volatile unsigned long __iomem *addr) 686static void iseries_memcpy_toio(volatile void __iomem *dest, const void *src,
687 unsigned long n)
774{ 688{
775 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 689 const char *s = src;
690 volatile char __iomem *d = dest;
776 691
777 return __in_be64(addr); 692 while (n-- > 0)
693 iSeries_Write_Byte(*s++, d++);
778} 694}
779EXPORT_SYMBOL(in_be64);
780
781void out_le64(volatile unsigned long __iomem *addr, unsigned long val)
782{
783 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
784 695
785 __out_le64(addr, val); 696/* We only set MMIO ops. The default PIO ops will be default
786} 697 * to the MMIO ops + pci_io_base which is 0 on iSeries as
787EXPORT_SYMBOL(out_le64); 698 * expected so both should work.
699 *
700 * Note that we don't implement the readq/writeq versions as
701 * I don't know of an HV call for doing so. Thus, the default
702 * operation will be used instead, which will fault a the value
703 * return by iSeries for MMIO addresses always hits a non mapped
704 * area. This is as good as the BUG() we used to have there.
705 */
706static struct ppc_pci_io __initdata iseries_pci_io = {
707 .readb = iseries_readb,
708 .readw = iseries_readw,
709 .readl = iseries_readl,
710 .readw_be = iseries_readw_be,
711 .readl_be = iseries_readl_be,
712 .writeb = iseries_writeb,
713 .writew = iseries_writew,
714 .writel = iseries_writel,
715 .writew_be = iseries_writew_be,
716 .writel_be = iseries_writel_be,
717 .readsb = iseries_readsb,
718 .readsw = iseries_readsw,
719 .readsl = iseries_readsl,
720 .writesb = iseries_writesb,
721 .writesw = iseries_writesw,
722 .writesl = iseries_writesl,
723 .memset_io = iseries_memset_io,
724 .memcpy_fromio = iseries_memcpy_fromio,
725 .memcpy_toio = iseries_memcpy_toio,
726};
788 727
789void out_be64(volatile unsigned long __iomem *addr, unsigned long val) 728/*
729 * iSeries_pcibios_init
730 *
731 * Description:
732 * This function checks for all possible system PCI host bridges that connect
733 * PCI buses. The system hypervisor is queried as to the guest partition
734 * ownership status. A pci_controller is built for any bus which is partially
735 * owned or fully owned by this guest partition.
736 */
737void __init iSeries_pcibios_init(void)
790{ 738{
791 BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); 739 struct pci_controller *phb;
740 struct device_node *root = of_find_node_by_path("/");
741 struct device_node *node = NULL;
792 742
793 __out_be64(addr, val); 743 /* Install IO hooks */
794} 744 ppc_pci_io = iseries_pci_io;
795EXPORT_SYMBOL(out_be64);
796 745
797void memset_io(volatile void __iomem *addr, int c, unsigned long n) 746 if (root == NULL) {
798{ 747 printk(KERN_CRIT "iSeries_pcibios_init: can't find root "
799 if (firmware_has_feature(FW_FEATURE_ISERIES)) { 748 "of device tree\n");
800 volatile char __iomem *d = addr; 749 return;
750 }
751 while ((node = of_get_next_child(root, node)) != NULL) {
752 HvBusNumber bus;
753 const u32 *busp;
801 754
802 while (n-- > 0) { 755 if ((node->type == NULL) || (strcmp(node->type, "pci") != 0))
803 iSeries_Write_Byte(c, d++); 756 continue;
804 }
805 } else
806 eeh_memset_io(addr, c, n);
807}
808EXPORT_SYMBOL(memset_io);
809 757
810void memcpy_fromio(void *dest, const volatile void __iomem *src, 758 busp = get_property(node, "bus-range", NULL);
811 unsigned long n) 759 if (busp == NULL)
812{ 760 continue;
813 if (firmware_has_feature(FW_FEATURE_ISERIES)) { 761 bus = *busp;
814 char *d = dest; 762 printk("bus %d appears to exist\n", bus);
815 const volatile char __iomem *s = src; 763 phb = pcibios_alloc_controller(node);
764 if (phb == NULL)
765 continue;
816 766
817 while (n-- > 0) { 767 phb->pci_mem_offset = phb->local_number = bus;
818 *d++ = iSeries_Read_Byte(s++); 768 phb->first_busno = bus;
819 } 769 phb->last_busno = bus;
820 } else 770 phb->ops = &iSeries_pci_ops;
821 eeh_memcpy_fromio(dest, src, n); 771 }
822}
823EXPORT_SYMBOL(memcpy_fromio);
824 772
825void memcpy_toio(volatile void __iomem *dest, const void *src, unsigned long n) 773 of_node_put(root);
826{
827 if (firmware_has_feature(FW_FEATURE_ISERIES)) {
828 const char *s = src;
829 volatile char __iomem *d = dest;
830 774
831 while (n-- > 0) { 775 pci_devs_phb_init();
832 iSeries_Write_Byte(*s++, d++);
833 }
834 } else
835 eeh_memcpy_toio(dest, src, n);
836} 776}
837EXPORT_SYMBOL(memcpy_toio); 777
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 6f73469fd3b0..bdf2afbb60c1 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -21,7 +21,6 @@
21#include <linux/smp.h> 21#include <linux/smp.h>
22#include <linux/param.h> 22#include <linux/param.h>
23#include <linux/string.h> 23#include <linux/string.h>
24#include <linux/initrd.h>
25#include <linux/seq_file.h> 24#include <linux/seq_file.h>
26#include <linux/kdev_t.h> 25#include <linux/kdev_t.h>
27#include <linux/major.h> 26#include <linux/major.h>
@@ -80,8 +79,6 @@ extern void iSeries_pci_final_fixup(void);
80static void iSeries_pci_final_fixup(void) { } 79static void iSeries_pci_final_fixup(void) { }
81#endif 80#endif
82 81
83extern int rd_size; /* Defined in drivers/block/rd.c */
84
85extern unsigned long iSeries_recal_tb; 82extern unsigned long iSeries_recal_tb;
86extern unsigned long iSeries_recal_titan; 83extern unsigned long iSeries_recal_titan;
87 84
@@ -295,24 +292,6 @@ static void __init iSeries_init_early(void)
295{ 292{
296 DBG(" -> iSeries_init_early()\n"); 293 DBG(" -> iSeries_init_early()\n");
297 294
298#if defined(CONFIG_BLK_DEV_INITRD)
299 /*
300 * If the init RAM disk has been configured and there is
301 * a non-zero starting address for it, set it up
302 */
303 if (naca.xRamDisk) {
304 initrd_start = (unsigned long)__va(naca.xRamDisk);
305 initrd_end = initrd_start + naca.xRamDiskSize * HW_PAGE_SIZE;
306 initrd_below_start_ok = 1; // ramdisk in kernel space
307 ROOT_DEV = Root_RAM0;
308 if (((rd_size * 1024) / HW_PAGE_SIZE) < naca.xRamDiskSize)
309 rd_size = (naca.xRamDiskSize * HW_PAGE_SIZE) / 1024;
310 } else
311#endif /* CONFIG_BLK_DEV_INITRD */
312 {
313 /* ROOT_DEV = MKDEV(VIODASD_MAJOR, 1); */
314 }
315
316 iSeries_recal_tb = get_tb(); 295 iSeries_recal_tb = get_tb();
317 iSeries_recal_titan = HvCallXm_loadTod(); 296 iSeries_recal_titan = HvCallXm_loadTod();
318 297
@@ -331,17 +310,6 @@ static void __init iSeries_init_early(void)
331 310
332 mf_init(); 311 mf_init();
333 312
334 /* If we were passed an initrd, set the ROOT_DEV properly if the values
335 * look sensible. If not, clear initrd reference.
336 */
337#ifdef CONFIG_BLK_DEV_INITRD
338 if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
339 initrd_end > initrd_start)
340 ROOT_DEV = Root_RAM0;
341 else
342 initrd_start = initrd_end = 0;
343#endif /* CONFIG_BLK_DEV_INITRD */
344
345 DBG(" <- iSeries_init_early()\n"); 313 DBG(" <- iSeries_init_early()\n");
346} 314}
347 315
@@ -649,6 +617,16 @@ static void iseries_dedicated_idle(void)
649void __init iSeries_init_IRQ(void) { } 617void __init iSeries_init_IRQ(void) { }
650#endif 618#endif
651 619
620static void __iomem *iseries_ioremap(phys_addr_t address, unsigned long size,
621 unsigned long flags)
622{
623 return (void __iomem *)address;
624}
625
626static void iseries_iounmap(volatile void __iomem *token)
627{
628}
629
652/* 630/*
653 * iSeries has no legacy IO, anything calling this function has to 631 * iSeries has no legacy IO, anything calling this function has to
654 * fail or bad things will happen 632 * fail or bad things will happen
@@ -665,6 +643,8 @@ static int __init iseries_probe(void)
665 return 0; 643 return 0;
666 644
667 hpte_init_iSeries(); 645 hpte_init_iSeries();
646 /* iSeries does not support 16M pages */
647 cur_cpu_spec->cpu_features &= ~CPU_FTR_16M_PAGE;
668 648
669 return 1; 649 return 1;
670} 650}
@@ -687,6 +667,8 @@ define_machine(iseries) {
687 .progress = iSeries_progress, 667 .progress = iSeries_progress,
688 .probe = iseries_probe, 668 .probe = iseries_probe,
689 .check_legacy_ioport = iseries_check_legacy_ioport, 669 .check_legacy_ioport = iseries_check_legacy_ioport,
670 .ioremap = iseries_ioremap,
671 .iounmap = iseries_iounmap,
690 /* XXX Implement enable_pmcs for iSeries */ 672 /* XXX Implement enable_pmcs for iSeries */
691}; 673};
692 674
@@ -697,7 +679,7 @@ void * __init iSeries_early_setup(void)
697 /* Identify CPU type. This is done again by the common code later 679 /* Identify CPU type. This is done again by the common code later
698 * on but calling this function multiple times is fine. 680 * on but calling this function multiple times is fine.
699 */ 681 */
700 identify_cpu(0); 682 identify_cpu(0, mfspr(SPRN_PVR));
701 683
702 powerpc_firmware_features |= FW_FEATURE_ISERIES; 684 powerpc_firmware_features |= FW_FEATURE_ISERIES;
703 powerpc_firmware_features |= FW_FEATURE_LPAR; 685 powerpc_firmware_features |= FW_FEATURE_LPAR;
diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c
index 04e07e5da0c1..84e7ee2c086f 100644
--- a/arch/powerpc/platforms/iseries/viopath.c
+++ b/arch/powerpc/platforms/iseries/viopath.c
@@ -119,10 +119,9 @@ static int proc_viopath_show(struct seq_file *m, void *v)
119 struct device_node *node; 119 struct device_node *node;
120 const char *sysid; 120 const char *sysid;
121 121
122 buf = kmalloc(HW_PAGE_SIZE, GFP_KERNEL); 122 buf = kzalloc(HW_PAGE_SIZE, GFP_KERNEL);
123 if (!buf) 123 if (!buf)
124 return 0; 124 return 0;
125 memset(buf, 0, HW_PAGE_SIZE);
126 125
127 handle = dma_map_single(iSeries_vio_dev, buf, HW_PAGE_SIZE, 126 handle = dma_map_single(iSeries_vio_dev, buf, HW_PAGE_SIZE,
128 DMA_FROM_DEVICE); 127 DMA_FROM_DEVICE);
diff --git a/arch/powerpc/platforms/maple/maple.h b/arch/powerpc/platforms/maple/maple.h
index 0657c579b840..c6911ddc479f 100644
--- a/arch/powerpc/platforms/maple/maple.h
+++ b/arch/powerpc/platforms/maple/maple.h
@@ -8,5 +8,5 @@ extern void maple_get_rtc_time(struct rtc_time *tm);
8extern unsigned long maple_get_boot_time(void); 8extern unsigned long maple_get_boot_time(void);
9extern void maple_calibrate_decr(void); 9extern void maple_calibrate_decr(void);
10extern void maple_pci_init(void); 10extern void maple_pci_init(void);
11extern void maple_pcibios_fixup(void); 11extern void maple_pci_irq_fixup(struct pci_dev *dev);
12extern int maple_pci_get_legacy_ide_irq(struct pci_dev *dev, int channel); 12extern int maple_pci_get_legacy_ide_irq(struct pci_dev *dev, int channel);
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index 63b4d1bff359..3a32deda765d 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -502,38 +502,29 @@ static int __init add_bridge(struct device_node *dev)
502} 502}
503 503
504 504
505void __init maple_pcibios_fixup(void) 505void __devinit maple_pci_irq_fixup(struct pci_dev *dev)
506{ 506{
507 struct pci_dev *dev = NULL; 507 DBG(" -> maple_pci_irq_fixup\n");
508 508
509 DBG(" -> maple_pcibios_fixup\n"); 509 /* Fixup IRQ for PCIe host */
510 510 if (u4_pcie != NULL && dev->bus->number == 0 &&
511 for_each_pci_dev(dev) { 511 pci_bus_to_host(dev->bus) == u4_pcie) {
512 /* Fixup IRQ for PCIe host */ 512 printk(KERN_DEBUG "Fixup U4 PCIe IRQ\n");
513 if (u4_pcie != NULL && dev->bus->number == 0 && 513 dev->irq = irq_create_mapping(NULL, 1);
514 pci_bus_to_host(dev->bus) == u4_pcie) { 514 if (dev->irq != NO_IRQ)
515 printk(KERN_DEBUG "Fixup U4 PCIe IRQ\n"); 515 set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW);
516 dev->irq = irq_create_mapping(NULL, 1); 516 }
517 if (dev->irq != NO_IRQ)
518 set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW);
519 continue;
520 }
521
522 /* Hide AMD8111 IDE interrupt when in legacy mode so
523 * the driver calls pci_get_legacy_ide_irq()
524 */
525 if (dev->vendor == PCI_VENDOR_ID_AMD &&
526 dev->device == PCI_DEVICE_ID_AMD_8111_IDE &&
527 (dev->class & 5) != 5) {
528 dev->irq = NO_IRQ;
529 continue;
530 }
531 517
532 /* For all others, map the interrupt from the device-tree */ 518 /* Hide AMD8111 IDE interrupt when in legacy mode so
533 pci_read_irq_line(dev); 519 * the driver calls pci_get_legacy_ide_irq()
520 */
521 if (dev->vendor == PCI_VENDOR_ID_AMD &&
522 dev->device == PCI_DEVICE_ID_AMD_8111_IDE &&
523 (dev->class & 5) != 5) {
524 dev->irq = NO_IRQ;
534 } 525 }
535 526
536 DBG(" <- maple_pcibios_fixup\n"); 527 DBG(" <- maple_pci_irq_fixup\n");
537} 528}
538 529
539static void __init maple_fixup_phb_resources(void) 530static void __init maple_fixup_phb_resources(void)
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index fe6b9bff61b9..094989d50bab 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -312,7 +312,7 @@ define_machine(maple_md) {
312 .setup_arch = maple_setup_arch, 312 .setup_arch = maple_setup_arch,
313 .init_early = maple_init_early, 313 .init_early = maple_init_early,
314 .init_IRQ = maple_init_IRQ, 314 .init_IRQ = maple_init_IRQ,
315 .pcibios_fixup = maple_pcibios_fixup, 315 .pci_irq_fixup = maple_pci_irq_fixup,
316 .pci_get_legacy_ide_irq = maple_pci_get_legacy_ide_irq, 316 .pci_get_legacy_ide_irq = maple_pci_get_legacy_ide_irq,
317 .restart = maple_restart, 317 .restart = maple_restart,
318 .power_off = maple_power_off, 318 .power_off = maple_power_off,
diff --git a/arch/powerpc/platforms/pasemi/pasemi.h b/arch/powerpc/platforms/pasemi/pasemi.h
index fd71d72736b2..51c2a2397ecf 100644
--- a/arch/powerpc/platforms/pasemi/pasemi.h
+++ b/arch/powerpc/platforms/pasemi/pasemi.h
@@ -3,6 +3,5 @@
3 3
4extern unsigned long pas_get_boot_time(void); 4extern unsigned long pas_get_boot_time(void);
5extern void pas_pci_init(void); 5extern void pas_pci_init(void);
6extern void pas_pcibios_fixup(void);
7 6
8#endif /* _PASEMI_PASEMI_H */ 7#endif /* _PASEMI_PASEMI_H */
diff --git a/arch/powerpc/platforms/pasemi/pci.c b/arch/powerpc/platforms/pasemi/pci.c
index 39020c1fa13d..faa618e04047 100644
--- a/arch/powerpc/platforms/pasemi/pci.c
+++ b/arch/powerpc/platforms/pasemi/pci.c
@@ -148,14 +148,6 @@ static int __init add_bridge(struct device_node *dev)
148} 148}
149 149
150 150
151void __init pas_pcibios_fixup(void)
152{
153 struct pci_dev *dev = NULL;
154
155 for_each_pci_dev(dev)
156 pci_read_irq_line(dev);
157}
158
159static void __init pas_fixup_phb_resources(void) 151static void __init pas_fixup_phb_resources(void)
160{ 152{
161 struct pci_controller *hose, *tmp; 153 struct pci_controller *hose, *tmp;
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
index 106896c3b60a..89d6e295dbf7 100644
--- a/arch/powerpc/platforms/pasemi/setup.c
+++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -26,6 +26,7 @@
26#include <linux/kernel.h> 26#include <linux/kernel.h>
27#include <linux/delay.h> 27#include <linux/delay.h>
28#include <linux/console.h> 28#include <linux/console.h>
29#include <linux/pci.h>
29 30
30#include <asm/prom.h> 31#include <asm/prom.h>
31#include <asm/system.h> 32#include <asm/system.h>
@@ -71,6 +72,9 @@ void __init pas_setup_arch(void)
71 /* Setup SMP callback */ 72 /* Setup SMP callback */
72 smp_ops = &pas_smp_ops; 73 smp_ops = &pas_smp_ops;
73#endif 74#endif
75 /* no iommu yet */
76 pci_dma_ops = &dma_direct_ops;
77
74 /* Lookup PCI hosts */ 78 /* Lookup PCI hosts */
75 pas_pci_init(); 79 pas_pci_init();
76 80
@@ -81,17 +85,6 @@ void __init pas_setup_arch(void)
81 printk(KERN_DEBUG "Using default idle loop\n"); 85 printk(KERN_DEBUG "Using default idle loop\n");
82} 86}
83 87
84static void iommu_dev_setup_null(struct pci_dev *dev) { }
85static void iommu_bus_setup_null(struct pci_bus *bus) { }
86
87static void __init pas_init_early(void)
88{
89 /* No iommu code yet */
90 ppc_md.iommu_dev_setup = iommu_dev_setup_null;
91 ppc_md.iommu_bus_setup = iommu_bus_setup_null;
92 pci_direct_iommu_init();
93}
94
95/* No legacy IO on our parts */ 88/* No legacy IO on our parts */
96static int pas_check_legacy_ioport(unsigned int baseport) 89static int pas_check_legacy_ioport(unsigned int baseport)
97{ 90{
@@ -173,10 +166,8 @@ define_machine(pas) {
173 .name = "PA Semi PA6T-1682M", 166 .name = "PA Semi PA6T-1682M",
174 .probe = pas_probe, 167 .probe = pas_probe,
175 .setup_arch = pas_setup_arch, 168 .setup_arch = pas_setup_arch,
176 .init_early = pas_init_early,
177 .init_IRQ = pas_init_IRQ, 169 .init_IRQ = pas_init_IRQ,
178 .get_irq = mpic_get_irq, 170 .get_irq = mpic_get_irq,
179 .pcibios_fixup = pas_pcibios_fixup,
180 .restart = pas_restart, 171 .restart = pas_restart,
181 .power_off = pas_power_off, 172 .power_off = pas_power_off,
182 .halt = pas_halt, 173 .halt = pas_halt,
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index e49621be6640..c29a6a064d22 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -486,10 +486,6 @@ static long heathrow_sound_enable(struct device_node *node, long param,
486 486
487static u32 save_fcr[6]; 487static u32 save_fcr[6];
488static u32 save_mbcr; 488static u32 save_mbcr;
489static u32 save_gpio_levels[2];
490static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT];
491static u8 save_gpio_normal[KEYLARGO_GPIO_CNT];
492static u32 save_unin_clock_ctl;
493static struct dbdma_regs save_dbdma[13]; 489static struct dbdma_regs save_dbdma[13];
494static struct dbdma_regs save_alt_dbdma[13]; 490static struct dbdma_regs save_alt_dbdma[13];
495 491
@@ -1548,6 +1544,10 @@ void g5_phy_disable_cpu1(void)
1548 1544
1549 1545
1550#ifdef CONFIG_PM 1546#ifdef CONFIG_PM
1547static u32 save_gpio_levels[2];
1548static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT];
1549static u8 save_gpio_normal[KEYLARGO_GPIO_CNT];
1550static u32 save_unin_clock_ctl;
1551 1551
1552static void keylargo_shutdown(struct macio_chip *macio, int sleep_mode) 1552static void keylargo_shutdown(struct macio_chip *macio, int sleep_mode)
1553{ 1553{
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index 257dc9068468..f42475b27c15 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -984,30 +984,23 @@ static int __init add_bridge(struct device_node *dev)
984 return 0; 984 return 0;
985} 985}
986 986
987void __init pmac_pcibios_fixup(void) 987void __devinit pmac_pci_irq_fixup(struct pci_dev *dev)
988{ 988{
989 struct pci_dev* dev = NULL;
990
991 for_each_pci_dev(dev) {
992 /* Read interrupt from the device-tree */
993 pci_read_irq_line(dev);
994
995#ifdef CONFIG_PPC32 989#ifdef CONFIG_PPC32
996 /* Fixup interrupt for the modem/ethernet combo controller. 990 /* Fixup interrupt for the modem/ethernet combo controller.
997 * on machines with a second ohare chip. 991 * on machines with a second ohare chip.
998 * The number in the device tree (27) is bogus (correct for 992 * The number in the device tree (27) is bogus (correct for
999 * the ethernet-only board but not the combo ethernet/modem 993 * the ethernet-only board but not the combo ethernet/modem
1000 * board). The real interrupt is 28 on the second controller 994 * board). The real interrupt is 28 on the second controller
1001 * -> 28+32 = 60. 995 * -> 28+32 = 60.
1002 */ 996 */
1003 if (has_second_ohare && 997 if (has_second_ohare &&
1004 dev->vendor == PCI_VENDOR_ID_DEC && 998 dev->vendor == PCI_VENDOR_ID_DEC &&
1005 dev->device == PCI_DEVICE_ID_DEC_TULIP_PLUS) { 999 dev->device == PCI_DEVICE_ID_DEC_TULIP_PLUS) {
1006 dev->irq = irq_create_mapping(NULL, 60); 1000 dev->irq = irq_create_mapping(NULL, 60);
1007 set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW); 1001 set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW);
1008 }
1009#endif /* CONFIG_PPC32 */
1010 } 1002 }
1003#endif /* CONFIG_PPC32 */
1011} 1004}
1012 1005
1013#ifdef CONFIG_PPC64 1006#ifdef CONFIG_PPC64
diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h
index 94e7b24b840b..6e090a7dea83 100644
--- a/arch/powerpc/platforms/powermac/pmac.h
+++ b/arch/powerpc/platforms/powermac/pmac.h
@@ -20,7 +20,7 @@ extern void pmac_get_rtc_time(struct rtc_time *);
20extern int pmac_set_rtc_time(struct rtc_time *); 20extern int pmac_set_rtc_time(struct rtc_time *);
21extern void pmac_read_rtc_time(void); 21extern void pmac_read_rtc_time(void);
22extern void pmac_calibrate_decr(void); 22extern void pmac_calibrate_decr(void);
23extern void pmac_pcibios_fixup(void); 23extern void pmac_pci_irq_fixup(struct pci_dev *);
24extern void pmac_pci_init(void); 24extern void pmac_pci_init(void);
25extern unsigned long pmac_ide_get_base(int index); 25extern unsigned long pmac_ide_get_base(int index);
26extern void pmac_ide_init_hwif_ports(hw_regs_t *hw, 26extern void pmac_ide_init_hwif_ports(hw_regs_t *hw,
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 824a618396ab..d949e9df41ef 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -70,6 +70,7 @@
70#include <asm/pmac_feature.h> 70#include <asm/pmac_feature.h>
71#include <asm/time.h> 71#include <asm/time.h>
72#include <asm/of_device.h> 72#include <asm/of_device.h>
73#include <asm/of_platform.h>
73#include <asm/mmu_context.h> 74#include <asm/mmu_context.h>
74#include <asm/iommu.h> 75#include <asm/iommu.h>
75#include <asm/smu.h> 76#include <asm/smu.h>
@@ -361,7 +362,7 @@ char *bootdevice;
361void *boot_host; 362void *boot_host;
362int boot_target; 363int boot_target;
363int boot_part; 364int boot_part;
364extern dev_t boot_dev; 365static dev_t boot_dev;
365 366
366#ifdef CONFIG_SCSI 367#ifdef CONFIG_SCSI
367void __init note_scsi_host(struct device_node *node, void *host) 368void __init note_scsi_host(struct device_node *node, void *host)
@@ -676,8 +677,6 @@ static int __init pmac_probe(void)
676 677
677#ifdef CONFIG_PPC32 678#ifdef CONFIG_PPC32
678 /* isa_io_base gets set in pmac_pci_init */ 679 /* isa_io_base gets set in pmac_pci_init */
679 isa_mem_base = PMAC_ISA_MEM_BASE;
680 pci_dram_offset = PMAC_PCI_DRAM_OFFSET;
681 ISA_DMA_THRESHOLD = ~0L; 680 ISA_DMA_THRESHOLD = ~0L;
682 DMA_MODE_READ = 1; 681 DMA_MODE_READ = 1;
683 DMA_MODE_WRITE = 2; 682 DMA_MODE_WRITE = 2;
@@ -727,7 +726,7 @@ define_machine(powermac) {
727 .show_cpuinfo = pmac_show_cpuinfo, 726 .show_cpuinfo = pmac_show_cpuinfo,
728 .init_IRQ = pmac_pic_init, 727 .init_IRQ = pmac_pic_init,
729 .get_irq = NULL, /* changed later */ 728 .get_irq = NULL, /* changed later */
730 .pcibios_fixup = pmac_pcibios_fixup, 729 .pci_irq_fixup = pmac_pci_irq_fixup,
731 .restart = pmac_restart, 730 .restart = pmac_restart,
732 .power_off = pmac_power_off, 731 .power_off = pmac_power_off,
733 .halt = pmac_halt, 732 .halt = pmac_halt,
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
new file mode 100644
index 000000000000..451bfcd5502e
--- /dev/null
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -0,0 +1,43 @@
1menu "PS3 Platform Options"
2 depends on PPC_PS3
3
4config PS3_HTAB_SIZE
5 depends on PPC_PS3
6 int "PS3 Platform pagetable size"
7 range 18 20
8 default 20
9 help
10 This option is only for experts who may have the desire to fine
11 tune the pagetable size on their system. The value here is
12 expressed as the log2 of the page table size. Valid values are
13 18, 19, and 20, corresponding to 256KB, 512KB and 1MB respectively.
14
15 If unsure, choose the default (20) with the confidence that your
16 system will have optimal runtime performance.
17
18config PS3_DYNAMIC_DMA
19 depends on PPC_PS3 && EXPERIMENTAL
20 bool "PS3 Platform dynamic DMA page table management"
21 default n
22 help
23 This option will enable kernel support to take advantage of the
24 per device dynamic DMA page table management provided by the Cell
25 processor's IO Controller. This support incurs some runtime
26 overhead and also slightly increases kernel memory usage. The
27 current implementation should be considered experimental.
28
29 This support is mainly for Linux kernel development. If unsure,
30 say N.
31
32config PS3_USE_LPAR_ADDR
33 depends on PPC_PS3 && EXPERIMENTAL
34 bool "PS3 use lpar address space"
35 default y
36 help
37 This option is solely for experimentation by experts. Disables
38 translation of lpar addresses. SPE support currently won't work
39 without this set to y.
40
41 If you have any doubt, choose the default y.
42
43endmenu
diff --git a/arch/powerpc/platforms/ps3/Makefile b/arch/powerpc/platforms/ps3/Makefile
new file mode 100644
index 000000000000..3757cfabc8ce
--- /dev/null
+++ b/arch/powerpc/platforms/ps3/Makefile
@@ -0,0 +1,4 @@
1obj-y += setup.o mm.o smp.o time.o hvcall.o htab.o repository.o
2obj-y += interrupt.o exports.o os-area.o
3
4obj-$(CONFIG_SPU_BASE) += spu.o
diff --git a/arch/powerpc/platforms/ps3/exports.c b/arch/powerpc/platforms/ps3/exports.c
new file mode 100644
index 000000000000..a7e8ffd24a65
--- /dev/null
+++ b/arch/powerpc/platforms/ps3/exports.c
@@ -0,0 +1,27 @@
1/*
2 * PS3 hvcall exports for modules.
3 *
4 * Copyright (C) 2006 Sony Computer Entertainment Inc.
5 * Copyright 2006 Sony Corp.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/module.h>
22
23#define LV1_CALL(name, in, out, num) \
24 extern s64 _lv1_##name(LV1_##in##_IN_##out##_OUT_ARG_DECL); \
25 EXPORT_SYMBOL(_lv1_##name);
26
27#include <asm/lv1call.h>
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
new file mode 100644
index 000000000000..8fe1769655a3
--- /dev/null
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -0,0 +1,277 @@
1/*
2 * PS3 pagetable management routines.
3 *
4 * Copyright (C) 2006 Sony Computer Entertainment Inc.
5 * Copyright 2006 Sony Corp.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/kernel.h>
22
23#include <asm/machdep.h>
24#include <asm/lmb.h>
25#include <asm/udbg.h>
26#include <asm/ps3.h>
27#include <asm/lv1call.h>
28
29#include "platform.h"
30
31#if defined(DEBUG)
32#define DBG(fmt...) udbg_printf(fmt)
33#else
34#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
35#endif
36
37static hpte_t *htab;
38static unsigned long htab_addr;
39static unsigned char *bolttab;
40static unsigned char *inusetab;
41
42static spinlock_t ps3_bolttab_lock = SPIN_LOCK_UNLOCKED;
43
44#define debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g) \
45 _debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__)
46static void _debug_dump_hpte(unsigned long pa, unsigned long va,
47 unsigned long group, unsigned long bitmap, hpte_t lhpte, int psize,
48 unsigned long slot, const char* func, int line)
49{
50 DBG("%s:%d: pa = %lxh\n", func, line, pa);
51 DBG("%s:%d: lpar = %lxh\n", func, line,
52 ps3_mm_phys_to_lpar(pa));
53 DBG("%s:%d: va = %lxh\n", func, line, va);
54 DBG("%s:%d: group = %lxh\n", func, line, group);
55 DBG("%s:%d: bitmap = %lxh\n", func, line, bitmap);
56 DBG("%s:%d: hpte.v = %lxh\n", func, line, lhpte.v);
57 DBG("%s:%d: hpte.r = %lxh\n", func, line, lhpte.r);
58 DBG("%s:%d: psize = %xh\n", func, line, psize);
59 DBG("%s:%d: slot = %lxh\n", func, line, slot);
60}
61
62static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va,
63 unsigned long pa, unsigned long rflags, unsigned long vflags, int psize)
64{
65 unsigned long slot;
66 hpte_t lhpte;
67 int secondary = 0;
68 unsigned long result;
69 unsigned long bitmap;
70 unsigned long flags;
71 unsigned long p_pteg, s_pteg, b_index, b_mask, cb, ci;
72
73 vflags &= ~HPTE_V_SECONDARY; /* this bit is ignored */
74
75 lhpte.v = hpte_encode_v(va, psize) | vflags | HPTE_V_VALID;
76 lhpte.r = hpte_encode_r(ps3_mm_phys_to_lpar(pa), psize) | rflags;
77
78 p_pteg = hpte_group / HPTES_PER_GROUP;
79 s_pteg = ~p_pteg & htab_hash_mask;
80
81 spin_lock_irqsave(&ps3_bolttab_lock, flags);
82
83 BUG_ON(bolttab[p_pteg] == 0xff && bolttab[s_pteg] == 0xff);
84
85 bitmap = (inusetab[p_pteg] << 8) | inusetab[s_pteg];
86
87 if (bitmap == 0xffff) {
88 /*
89 * PTEG is full. Search for victim.
90 */
91 bitmap &= ~((bolttab[p_pteg] << 8) | bolttab[s_pteg]);
92 do {
93 ci = mftb() & 15;
94 cb = 0x8000UL >> ci;
95 } while ((cb & bitmap) == 0);
96 } else {
97 /*
98 * search free slot in hardware order
99 * [primary] 0, 2, 4, 6, 1, 3, 5, 7
100 * [secondary] 0, 2, 4, 6, 1, 3, 5, 7
101 */
102 for (ci = 0; ci < HPTES_PER_GROUP; ci += 2) {
103 cb = 0x8000UL >> ci;
104 if ((cb & bitmap) == 0)
105 goto found;
106 }
107 for (ci = 1; ci < HPTES_PER_GROUP; ci += 2) {
108 cb = 0x8000UL >> ci;
109 if ((cb & bitmap) == 0)
110 goto found;
111 }
112 for (ci = HPTES_PER_GROUP; ci < HPTES_PER_GROUP*2; ci += 2) {
113 cb = 0x8000UL >> ci;
114 if ((cb & bitmap) == 0)
115 goto found;
116 }
117 for (ci = HPTES_PER_GROUP+1; ci < HPTES_PER_GROUP*2; ci += 2) {
118 cb = 0x8000UL >> ci;
119 if ((cb & bitmap) == 0)
120 goto found;
121 }
122 }
123
124found:
125 if (ci < HPTES_PER_GROUP) {
126 slot = p_pteg * HPTES_PER_GROUP + ci;
127 } else {
128 slot = s_pteg * HPTES_PER_GROUP + (ci & 7);
129 /* lhpte.dw0.dw0.h = 1; */
130 vflags |= HPTE_V_SECONDARY;
131 lhpte.v |= HPTE_V_SECONDARY;
132 }
133
134 result = lv1_write_htab_entry(0, slot, lhpte.v, lhpte.r);
135
136 if (result) {
137 debug_dump_hpte(pa, va, hpte_group, bitmap, lhpte, psize, slot);
138 BUG();
139 }
140
141 /*
142 * If used slot is not in primary HPTE group,
143 * the slot should be in secondary HPTE group.
144 */
145
146 if ((hpte_group ^ slot) & ~(HPTES_PER_GROUP - 1)) {
147 secondary = 1;
148 b_index = s_pteg;
149 } else {
150 secondary = 0;
151 b_index = p_pteg;
152 }
153
154 b_mask = (lhpte.v & HPTE_V_BOLTED) ? 1 << 7 : 0 << 7;
155 bolttab[b_index] |= b_mask >> (slot & 7);
156 b_mask = 1 << 7;
157 inusetab[b_index] |= b_mask >> (slot & 7);
158 spin_unlock_irqrestore(&ps3_bolttab_lock, flags);
159
160 return (slot & 7) | (secondary << 3);
161}
162
163static long ps3_hpte_remove(unsigned long hpte_group)
164{
165 panic("ps3_hpte_remove() not implemented");
166 return 0;
167}
168
169static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp,
170 unsigned long va, int psize, int local)
171{
172 unsigned long flags;
173 unsigned long result;
174 unsigned long pteg, bit;
175 unsigned long hpte_v, want_v;
176
177 want_v = hpte_encode_v(va, psize);
178
179 spin_lock_irqsave(&ps3_bolttab_lock, flags);
180
181 hpte_v = htab[slot].v;
182 if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) {
183 spin_unlock_irqrestore(&ps3_bolttab_lock, flags);
184
185 /* ps3_hpte_insert() will be used to update PTE */
186 return -1;
187 }
188
189 result = lv1_write_htab_entry(0, slot, 0, 0);
190
191 if (result) {
192 DBG("%s: va=%lx slot=%lx psize=%d result = %ld (0x%lx)\n",
193 __func__, va, slot, psize, result, result);
194 BUG();
195 }
196
197 pteg = slot / HPTES_PER_GROUP;
198 bit = slot % HPTES_PER_GROUP;
199 inusetab[pteg] &= ~(0x80 >> bit);
200
201 spin_unlock_irqrestore(&ps3_bolttab_lock, flags);
202
203 /* ps3_hpte_insert() will be used to update PTE */
204 return -1;
205}
206
207static void ps3_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
208 int psize)
209{
210 panic("ps3_hpte_updateboltedpp() not implemented");
211}
212
213static void ps3_hpte_invalidate(unsigned long slot, unsigned long va,
214 int psize, int local)
215{
216 unsigned long flags;
217 unsigned long result;
218 unsigned long pteg, bit;
219
220 spin_lock_irqsave(&ps3_bolttab_lock, flags);
221 result = lv1_write_htab_entry(0, slot, 0, 0);
222
223 if (result) {
224 DBG("%s: va=%lx slot=%lx psize=%d result = %ld (0x%lx)\n",
225 __func__, va, slot, psize, result, result);
226 BUG();
227 }
228
229 pteg = slot / HPTES_PER_GROUP;
230 bit = slot % HPTES_PER_GROUP;
231 inusetab[pteg] &= ~(0x80 >> bit);
232 spin_unlock_irqrestore(&ps3_bolttab_lock, flags);
233}
234
235static void ps3_hpte_clear(void)
236{
237 lv1_unmap_htab(htab_addr);
238}
239
240void __init ps3_hpte_init(unsigned long htab_size)
241{
242 long bitmap_size;
243
244 DBG(" -> %s:%d\n", __func__, __LINE__);
245
246 ppc_md.hpte_invalidate = ps3_hpte_invalidate;
247 ppc_md.hpte_updatepp = ps3_hpte_updatepp;
248 ppc_md.hpte_updateboltedpp = ps3_hpte_updateboltedpp;
249 ppc_md.hpte_insert = ps3_hpte_insert;
250 ppc_md.hpte_remove = ps3_hpte_remove;
251 ppc_md.hpte_clear_all = ps3_hpte_clear;
252
253 ppc64_pft_size = __ilog2(htab_size);
254
255 bitmap_size = htab_size / sizeof(hpte_t) / 8;
256
257 bolttab = __va(lmb_alloc(bitmap_size, 1));
258 inusetab = __va(lmb_alloc(bitmap_size, 1));
259
260 memset(bolttab, 0, bitmap_size);
261 memset(inusetab, 0, bitmap_size);
262
263 DBG(" <- %s:%d\n", __func__, __LINE__);
264}
265
266void __init ps3_map_htab(void)
267{
268 long result;
269 unsigned long htab_size = (1UL << ppc64_pft_size);
270
271 result = lv1_map_htab(0, &htab_addr);
272
273 htab = (hpte_t *)__ioremap(htab_addr, htab_size, PAGE_READONLY_X);
274
275 DBG("%s:%d: lpar %016lxh, virt %016lxh\n", __func__, __LINE__,
276 htab_addr, (unsigned long)htab);
277}
diff --git a/arch/powerpc/platforms/ps3/hvcall.S b/arch/powerpc/platforms/ps3/hvcall.S
new file mode 100644
index 000000000000..54be6523a0e8
--- /dev/null
+++ b/arch/powerpc/platforms/ps3/hvcall.S
@@ -0,0 +1,804 @@
1/*
2 * PS3 hvcall interface.
3 *
4 * Copyright (C) 2006 Sony Computer Entertainment Inc.
5 * Copyright 2006 Sony Corp.
6 * Copyright 2003, 2004 (c) MontaVista Software, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include <asm/processor.h>
23#include <asm/ppc_asm.h>
24
25#define lv1call .long 0x44000022; extsw r3, r3
26
27#define LV1_N_IN_0_OUT(API_NAME, API_NUMBER) \
28_GLOBAL(_##API_NAME) \
29 \
30 mflr r0; \
31 std r0, 16(r1); \
32 \
33 li r11, API_NUMBER; \
34 lv1call; \
35 \
36 ld r0, 16(r1); \
37 mtlr r0; \
38 blr
39
40#define LV1_0_IN_0_OUT LV1_N_IN_0_OUT
41#define LV1_1_IN_0_OUT LV1_N_IN_0_OUT
42#define LV1_2_IN_0_OUT LV1_N_IN_0_OUT
43#define LV1_3_IN_0_OUT LV1_N_IN_0_OUT
44#define LV1_4_IN_0_OUT LV1_N_IN_0_OUT
45#define LV1_5_IN_0_OUT LV1_N_IN_0_OUT
46#define LV1_6_IN_0_OUT LV1_N_IN_0_OUT
47#define LV1_7_IN_0_OUT LV1_N_IN_0_OUT
48
49#define LV1_0_IN_1_OUT(API_NAME, API_NUMBER) \
50_GLOBAL(_##API_NAME) \
51 \
52 mflr r0; \
53 std r0, 16(r1); \
54 \
55 stdu r3, -8(r1); \
56 \
57 li r11, API_NUMBER; \
58 lv1call; \
59 \
60 addi r1, r1, 8; \
61 ld r11, -8(r1); \
62 std r4, 0(r11); \
63 \
64 ld r0, 16(r1); \
65 mtlr r0; \
66 blr
67
68#define LV1_0_IN_2_OUT(API_NAME, API_NUMBER) \
69_GLOBAL(_##API_NAME) \
70 \
71 mflr r0; \
72 std r0, 16(r1); \
73 \
74 std r3, -8(r1); \
75 stdu r4, -16(r1); \
76 \
77 li r11, API_NUMBER; \
78 lv1call; \
79 \
80 addi r1, r1, 16; \
81 ld r11, -8(r1); \
82 std r4, 0(r11); \
83 ld r11, -16(r1); \
84 std r5, 0(r11); \
85 \
86 ld r0, 16(r1); \
87 mtlr r0; \
88 blr
89
90#define LV1_0_IN_3_OUT(API_NAME, API_NUMBER) \
91_GLOBAL(_##API_NAME) \
92 \
93 mflr r0; \
94 std r0, 16(r1); \
95 \
96 std r3, -8(r1); \
97 std r4, -16(r1); \
98 stdu r5, -24(r1); \
99 \
100 li r11, API_NUMBER; \
101 lv1call; \
102 \
103 addi r1, r1, 24; \
104 ld r11, -8(r1); \
105 std r4, 0(r11); \
106 ld r11, -16(r1); \
107 std r5, 0(r11); \
108 ld r11, -24(r1); \
109 std r6, 0(r11); \
110 \
111 ld r0, 16(r1); \
112 mtlr r0; \
113 blr
114
115#define LV1_0_IN_7_OUT(API_NAME, API_NUMBER) \
116_GLOBAL(_##API_NAME) \
117 \
118 mflr r0; \
119 std r0, 16(r1); \
120 \
121 std r3, -8(r1); \
122 std r4, -16(r1); \
123 std r5, -24(r1); \
124 std r6, -32(r1); \
125 std r7, -40(r1); \
126 std r8, -48(r1); \
127 stdu r9, -56(r1); \
128 \
129 li r11, API_NUMBER; \
130 lv1call; \
131 \
132 addi r1, r1, 56; \
133 ld r11, -8(r1); \
134 std r4, 0(r11); \
135 ld r11, -16(r1); \
136 std r5, 0(r11); \
137 ld r11, -24(r1); \
138 std r6, 0(r11); \
139 ld r11, -32(r1); \
140 std r7, 0(r11); \
141 ld r11, -40(r1); \
142 std r8, 0(r11); \
143 ld r11, -48(r1); \
144 std r9, 0(r11); \
145 ld r11, -56(r1); \
146 std r10, 0(r11); \
147 \
148 ld r0, 16(r1); \
149 mtlr r0; \
150 blr
151
152#define LV1_1_IN_1_OUT(API_NAME, API_NUMBER) \
153_GLOBAL(_##API_NAME) \
154 \
155 mflr r0; \
156 std r0, 16(r1); \
157 \
158 stdu r4, -8(r1); \
159 \
160 li r11, API_NUMBER; \
161 lv1call; \
162 \
163 addi r1, r1, 8; \
164 ld r11, -8(r1); \
165 std r4, 0(r11); \
166 \
167 ld r0, 16(r1); \
168 mtlr r0; \
169 blr
170
171#define LV1_1_IN_2_OUT(API_NAME, API_NUMBER) \
172_GLOBAL(_##API_NAME) \
173 \
174 mflr r0; \
175 std r0, 16(r1); \
176 \
177 std r4, -8(r1); \
178 stdu r5, -16(r1); \
179 \
180 li r11, API_NUMBER; \
181 lv1call; \
182 \
183 addi r1, r1, 16; \
184 ld r11, -8(r1); \
185 std r4, 0(r11); \
186 ld r11, -16(r1); \
187 std r5, 0(r11); \
188 \
189 ld r0, 16(r1); \
190 mtlr r0; \
191 blr
192
193#define LV1_1_IN_3_OUT(API_NAME, API_NUMBER) \
194_GLOBAL(_##API_NAME) \
195 \
196 mflr r0; \
197 std r0, 16(r1); \
198 \
199 std r4, -8(r1); \
200 std r5, -16(r1); \
201 stdu r6, -24(r1); \
202 \
203 li r11, API_NUMBER; \
204 lv1call; \
205 \
206 addi r1, r1, 24; \
207 ld r11, -8(r1); \
208 std r4, 0(r11); \
209 ld r11, -16(r1); \
210 std r5, 0(r11); \
211 ld r11, -24(r1); \
212 std r6, 0(r11); \
213 \
214 ld r0, 16(r1); \
215 mtlr r0; \
216 blr
217
218#define LV1_1_IN_4_OUT(API_NAME, API_NUMBER) \
219_GLOBAL(_##API_NAME) \
220 \
221 mflr r0; \
222 std r0, 16(r1); \
223 \
224 std r4, -8(r1); \
225 std r5, -16(r1); \
226 std r6, -24(r1); \
227 stdu r7, -32(r1); \
228 \
229 li r11, API_NUMBER; \
230 lv1call; \
231 \
232 addi r1, r1, 32; \
233 ld r11, -8(r1); \
234 std r4, 0(r11); \
235 ld r11, -16(r1); \
236 std r5, 0(r11); \
237 ld r11, -24(r1); \
238 std r6, 0(r11); \
239 ld r11, -32(r1); \
240 std r7, 0(r11); \
241 \
242 ld r0, 16(r1); \
243 mtlr r0; \
244 blr
245
246#define LV1_1_IN_5_OUT(API_NAME, API_NUMBER) \
247_GLOBAL(_##API_NAME) \
248 \
249 mflr r0; \
250 std r0, 16(r1); \
251 \
252 std r4, -8(r1); \
253 std r5, -16(r1); \
254 std r6, -24(r1); \
255 std r7, -32(r1); \
256 stdu r8, -40(r1); \
257 \
258 li r11, API_NUMBER; \
259 lv1call; \
260 \
261 addi r1, r1, 40; \
262 ld r11, -8(r1); \
263 std r4, 0(r11); \
264 ld r11, -16(r1); \
265 std r5, 0(r11); \
266 ld r11, -24(r1); \
267 std r6, 0(r11); \
268 ld r11, -32(r1); \
269 std r7, 0(r11); \
270 ld r11, -40(r1); \
271 std r8, 0(r11); \
272 \
273 ld r0, 16(r1); \
274 mtlr r0; \
275 blr
276
277#define LV1_1_IN_6_OUT(API_NAME, API_NUMBER) \
278_GLOBAL(_##API_NAME) \
279 \
280 mflr r0; \
281 std r0, 16(r1); \
282 \
283 std r4, -8(r1); \
284 std r5, -16(r1); \
285 std r6, -24(r1); \
286 std r7, -32(r1); \
287 std r8, -40(r1); \
288 stdu r9, -48(r1); \
289 \
290 li r11, API_NUMBER; \
291 lv1call; \
292 \
293 addi r1, r1, 48; \
294 ld r11, -8(r1); \
295 std r4, 0(r11); \
296 ld r11, -16(r1); \
297 std r5, 0(r11); \
298 ld r11, -24(r1); \
299 std r6, 0(r11); \
300 ld r11, -32(r1); \
301 std r7, 0(r11); \
302 ld r11, -40(r1); \
303 std r8, 0(r11); \
304 ld r11, -48(r1); \
305 std r9, 0(r11); \
306 \
307 ld r0, 16(r1); \
308 mtlr r0; \
309 blr
310
311#define LV1_1_IN_7_OUT(API_NAME, API_NUMBER) \
312_GLOBAL(_##API_NAME) \
313 \
314 mflr r0; \
315 std r0, 16(r1); \
316 \
317 std r4, -8(r1); \
318 std r5, -16(r1); \
319 std r6, -24(r1); \
320 std r7, -32(r1); \
321 std r8, -40(r1); \
322 std r9, -48(r1); \
323 stdu r10, -56(r1); \
324 \
325 li r11, API_NUMBER; \
326 lv1call; \
327 \
328 addi r1, r1, 56; \
329 ld r11, -8(r1); \
330 std r4, 0(r11); \
331 ld r11, -16(r1); \
332 std r5, 0(r11); \
333 ld r11, -24(r1); \
334 std r6, 0(r11); \
335 ld r11, -32(r1); \
336 std r7, 0(r11); \
337 ld r11, -40(r1); \
338 std r8, 0(r11); \
339 ld r11, -48(r1); \
340 std r9, 0(r11); \
341 ld r11, -56(r1); \
342 std r10, 0(r11); \
343 \
344 ld r0, 16(r1); \
345 mtlr r0; \
346 blr
347
348#define LV1_2_IN_1_OUT(API_NAME, API_NUMBER) \
349_GLOBAL(_##API_NAME) \
350 \
351 mflr r0; \
352 std r0, 16(r1); \
353 \
354 stdu r5, -8(r1); \
355 \
356 li r11, API_NUMBER; \
357 lv1call; \
358 \
359 addi r1, r1, 8; \
360 ld r11, -8(r1); \
361 std r4, 0(r11); \
362 \
363 ld r0, 16(r1); \
364 mtlr r0; \
365 blr
366
367#define LV1_2_IN_2_OUT(API_NAME, API_NUMBER) \
368_GLOBAL(_##API_NAME) \
369 \
370 mflr r0; \
371 std r0, 16(r1); \
372 \
373 std r5, -8(r1); \
374 stdu r6, -16(r1); \
375 \
376 li r11, API_NUMBER; \
377 lv1call; \
378 \
379 addi r1, r1, 16; \
380 ld r11, -8(r1); \
381 std r4, 0(r11); \
382 ld r11, -16(r1); \
383 std r5, 0(r11); \
384 \
385 ld r0, 16(r1); \
386 mtlr r0; \
387 blr
388
389#define LV1_2_IN_3_OUT(API_NAME, API_NUMBER) \
390_GLOBAL(_##API_NAME) \
391 \
392 mflr r0; \
393 std r0, 16(r1); \
394 \
395 std r5, -8(r1); \
396 std r6, -16(r1); \
397 stdu r7, -24(r1); \
398 \
399 li r11, API_NUMBER; \
400 lv1call; \
401 \
402 addi r1, r1, 24; \
403 ld r11, -8(r1); \
404 std r4, 0(r11); \
405 ld r11, -16(r1); \
406 std r5, 0(r11); \
407 ld r11, -24(r1); \
408 std r6, 0(r11); \
409 \
410 ld r0, 16(r1); \
411 mtlr r0; \
412 blr
413
414#define LV1_2_IN_4_OUT(API_NAME, API_NUMBER) \
415_GLOBAL(_##API_NAME) \
416 \
417 mflr r0; \
418 std r0, 16(r1); \
419 \
420 std r5, -8(r1); \
421 std r6, -16(r1); \
422 std r7, -24(r1); \
423 stdu r8, -32(r1); \
424 \
425 li r11, API_NUMBER; \
426 lv1call; \
427 \
428 addi r1, r1, 32; \
429 ld r11, -8(r1); \
430 std r4, 0(r11); \
431 ld r11, -16(r1); \
432 std r5, 0(r11); \
433 ld r11, -24(r1); \
434 std r6, 0(r11); \
435 ld r11, -32(r1); \
436 std r7, 0(r11); \
437 \
438 ld r0, 16(r1); \
439 mtlr r0; \
440 blr
441
442#define LV1_2_IN_5_OUT(API_NAME, API_NUMBER) \
443_GLOBAL(_##API_NAME) \
444 \
445 mflr r0; \
446 std r0, 16(r1); \
447 \
448 std r5, -8(r1); \
449 std r6, -16(r1); \
450 std r7, -24(r1); \
451 std r8, -32(r1); \
452 stdu r9, -40(r1); \
453 \
454 li r11, API_NUMBER; \
455 lv1call; \
456 \
457 addi r1, r1, 40; \
458 ld r11, -8(r1); \
459 std r4, 0(r11); \
460 ld r11, -16(r1); \
461 std r5, 0(r11); \
462 ld r11, -24(r1); \
463 std r6, 0(r11); \
464 ld r11, -32(r1); \
465 std r7, 0(r11); \
466 ld r11, -40(r1); \
467 std r8, 0(r11); \
468 \
469 ld r0, 16(r1); \
470 mtlr r0; \
471 blr
472
473#define LV1_3_IN_1_OUT(API_NAME, API_NUMBER) \
474_GLOBAL(_##API_NAME) \
475 \
476 mflr r0; \
477 std r0, 16(r1); \
478 \
479 stdu r6, -8(r1); \
480 \
481 li r11, API_NUMBER; \
482 lv1call; \
483 \
484 addi r1, r1, 8; \
485 ld r11, -8(r1); \
486 std r4, 0(r11); \
487 \
488 ld r0, 16(r1); \
489 mtlr r0; \
490 blr
491
492#define LV1_3_IN_2_OUT(API_NAME, API_NUMBER) \
493_GLOBAL(_##API_NAME) \
494 \
495 mflr r0; \
496 std r0, 16(r1); \
497 \
498 std r6, -8(r1); \
499 stdu r7, -16(r1); \
500 \
501 li r11, API_NUMBER; \
502 lv1call; \
503 \
504 addi r1, r1, 16; \
505 ld r11, -8(r1); \
506 std r4, 0(r11); \
507 ld r11, -16(r1); \
508 std r5, 0(r11); \
509 \
510 ld r0, 16(r1); \
511 mtlr r0; \
512 blr
513
514#define LV1_3_IN_3_OUT(API_NAME, API_NUMBER) \
515_GLOBAL(_##API_NAME) \
516 \
517 mflr r0; \
518 std r0, 16(r1); \
519 \
520 std r6, -8(r1); \
521 std r7, -16(r1); \
522 stdu r8, -24(r1); \
523 \
524 li r11, API_NUMBER; \
525 lv1call; \
526 \
527 addi r1, r1, 24; \
528 ld r11, -8(r1); \
529 std r4, 0(r11); \
530 ld r11, -16(r1); \
531 std r5, 0(r11); \
532 ld r11, -24(r1); \
533 std r6, 0(r11); \
534 \
535 ld r0, 16(r1); \
536 mtlr r0; \
537 blr
538
539#define LV1_4_IN_1_OUT(API_NAME, API_NUMBER) \
540_GLOBAL(_##API_NAME) \
541 \
542 mflr r0; \
543 std r0, 16(r1); \
544 \
545 stdu r7, -8(r1); \
546 \
547 li r11, API_NUMBER; \
548 lv1call; \
549 \
550 addi r1, r1, 8; \
551 ld r11, -8(r1); \
552 std r4, 0(r11); \
553 \
554 ld r0, 16(r1); \
555 mtlr r0; \
556 blr
557
558#define LV1_4_IN_2_OUT(API_NAME, API_NUMBER) \
559_GLOBAL(_##API_NAME) \
560 \
561 mflr r0; \
562 std r0, 16(r1); \
563 \
564 std r7, -8(r1); \
565 stdu r8, -16(r1); \
566 \
567 li r11, API_NUMBER; \
568 lv1call; \
569 \
570 addi r1, r1, 16; \
571 ld r11, -8(r1); \
572 std r4, 0(r11); \
573 ld r11, -16(r1); \
574 std r5, 0(r11); \
575 \
576 ld r0, 16(r1); \
577 mtlr r0; \
578 blr
579
580#define LV1_4_IN_3_OUT(API_NAME, API_NUMBER) \
581_GLOBAL(_##API_NAME) \
582 \
583 mflr r0; \
584 std r0, 16(r1); \
585 \
586 std r7, -8(r1); \
587 std r8, -16(r1); \
588 stdu r9, -24(r1); \
589 \
590 li r11, API_NUMBER; \
591 lv1call; \
592 \
593 addi r1, r1, 24; \
594 ld r11, -8(r1); \
595 std r4, 0(r11); \
596 ld r11, -16(r1); \
597 std r5, 0(r11); \
598 ld r11, -24(r1); \
599 std r6, 0(r11); \
600 \
601 ld r0, 16(r1); \
602 mtlr r0; \
603 blr
604
605#define LV1_5_IN_1_OUT(API_NAME, API_NUMBER) \
606_GLOBAL(_##API_NAME) \
607 \
608 mflr r0; \
609 std r0, 16(r1); \
610 \
611 stdu r8, -8(r1); \
612 \
613 li r11, API_NUMBER; \
614 lv1call; \
615 \
616 addi r1, r1, 8; \
617 ld r11, -8(r1); \
618 std r4, 0(r11); \
619 \
620 ld r0, 16(r1); \
621 mtlr r0; \
622 blr
623
624#define LV1_5_IN_2_OUT(API_NAME, API_NUMBER) \
625_GLOBAL(_##API_NAME) \
626 \
627 mflr r0; \
628 std r0, 16(r1); \
629 \
630 std r8, -8(r1); \
631 stdu r9, -16(r1); \
632 \
633 li r11, API_NUMBER; \
634 lv1call; \
635 \
636 addi r1, r1, 16; \
637 ld r11, -8(r1); \
638 std r4, 0(r11); \
639 ld r11, -16(r1); \
640 std r5, 0(r11); \
641 \
642 ld r0, 16(r1); \
643 mtlr r0; \
644 blr
645
646#define LV1_5_IN_3_OUT(API_NAME, API_NUMBER) \
647_GLOBAL(_##API_NAME) \
648 \
649 mflr r0; \
650 std r0, 16(r1); \
651 \
652 std r8, -8(r1); \
653 std r9, -16(r1); \
654 stdu r10, -24(r1); \
655 \
656 li r11, API_NUMBER; \
657 lv1call; \
658 \
659 addi r1, r1, 24; \
660 ld r11, -8(r1); \
661 std r4, 0(r11); \
662 ld r11, -16(r1); \
663 std r5, 0(r11); \
664 ld r11, -24(r1); \
665 std r6, 0(r11); \
666 \
667 ld r0, 16(r1); \
668 mtlr r0; \
669 blr
670
671#define LV1_6_IN_1_OUT(API_NAME, API_NUMBER) \
672_GLOBAL(_##API_NAME) \
673 \
674 mflr r0; \
675 std r0, 16(r1); \
676 \
677 stdu r9, -8(r1); \
678 \
679 li r11, API_NUMBER; \
680 lv1call; \
681 \
682 addi r1, r1, 8; \
683 ld r11, -8(r1); \
684 std r4, 0(r11); \
685 \
686 ld r0, 16(r1); \
687 mtlr r0; \
688 blr
689
690#define LV1_6_IN_2_OUT(API_NAME, API_NUMBER) \
691_GLOBAL(_##API_NAME) \
692 \
693 mflr r0; \
694 std r0, 16(r1); \
695 \
696 std r9, -8(r1); \
697 stdu r10, -16(r1); \
698 \
699 li r11, API_NUMBER; \
700 lv1call; \
701 \
702 addi r1, r1, 16; \
703 ld r11, -8(r1); \
704 std r4, 0(r11); \
705 ld r11, -16(r1); \
706 std r5, 0(r11); \
707 \
708 ld r0, 16(r1); \
709 mtlr r0; \
710 blr
711
712#define LV1_6_IN_3_OUT(API_NAME, API_NUMBER) \
713_GLOBAL(_##API_NAME) \
714 \
715 mflr r0; \
716 std r0, 16(r1); \
717 \
718 std r9, -8(r1); \
719 stdu r10, -16(r1); \
720 \
721 li r11, API_NUMBER; \
722 lv1call; \
723 \
724 addi r1, r1, 16; \
725 ld r11, -8(r1); \
726 std r4, 0(r11); \
727 ld r11, -16(r1); \
728 std r5, 0(r11); \
729 ld r11, 48+8*8(r1); \
730 std r6, 0(r11); \
731 \
732 ld r0, 16(r1); \
733 mtlr r0; \
734 blr
735
736#define LV1_7_IN_1_OUT(API_NAME, API_NUMBER) \
737_GLOBAL(_##API_NAME) \
738 \
739 mflr r0; \
740 std r0, 16(r1); \
741 \
742 stdu r10, -8(r1); \
743 \
744 li r11, API_NUMBER; \
745 lv1call; \
746 \
747 addi r1, r1, 8; \
748 ld r11, -8(r1); \
749 std r4, 0(r11); \
750 \
751 ld r0, 16(r1); \
752 mtlr r0; \
753 blr
754
755#define LV1_7_IN_6_OUT(API_NAME, API_NUMBER) \
756_GLOBAL(_##API_NAME) \
757 \
758 mflr r0; \
759 std r0, 16(r1); \
760 \
761 std r10, 48+8*7(r1); \
762 \
763 li r11, API_NUMBER; \
764 lv1call; \
765 \
766 ld r11, 48+8*7(r1); \
767 std r4, 0(r11); \
768 ld r11, 48+8*8(r1); \
769 std r5, 0(r11); \
770 ld r11, 48+8*9(r1); \
771 std r6, 0(r11); \
772 ld r11, 48+8*10(r1); \
773 std r7, 0(r11); \
774 ld r11, 48+8*11(r1); \
775 std r8, 0(r11); \
776 ld r11, 48+8*12(r1); \
777 std r9, 0(r11); \
778 \
779 ld r0, 16(r1); \
780 mtlr r0; \
781 blr
782
783#define LV1_8_IN_1_OUT(API_NAME, API_NUMBER) \
784_GLOBAL(_##API_NAME) \
785 \
786 mflr r0; \
787 std r0, 16(r1); \
788 \
789 li r11, API_NUMBER; \
790 lv1call; \
791 \
792 ld r11, 48+8*8(r1); \
793 std r4, 0(r11); \
794 \
795 ld r0, 16(r1); \
796 mtlr r0; \
797 blr
798
799 .text
800
801/* the lv1 underscored call definitions expand here */
802
803#define LV1_CALL(name, in, out, num) LV1_##in##_IN_##out##_OUT(lv1_##name, num)
804#include <asm/lv1call.h>
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
new file mode 100644
index 000000000000..056c1e4141ba
--- /dev/null
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -0,0 +1,575 @@
1/*
2 * PS3 interrupt routines.
3 *
4 * Copyright (C) 2006 Sony Computer Entertainment Inc.
5 * Copyright 2006 Sony Corp.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/irq.h>
24
25#include <asm/machdep.h>
26#include <asm/udbg.h>
27#include <asm/ps3.h>
28#include <asm/lv1call.h>
29
30#include "platform.h"
31
32#if defined(DEBUG)
33#define DBG(fmt...) udbg_printf(fmt)
34#else
35#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
36#endif
37
38/**
39 * ps3_alloc_io_irq - Assign a virq to a system bus device.
40 * interrupt_id: The device interrupt id read from the system repository.
41 * @virq: The assigned Linux virq.
42 *
43 * An io irq represents a non-virtualized device interrupt. interrupt_id
44 * coresponds to the interrupt number of the interrupt controller.
45 */
46
47int ps3_alloc_io_irq(unsigned int interrupt_id, unsigned int *virq)
48{
49 int result;
50 unsigned long outlet;
51
52 result = lv1_construct_io_irq_outlet(interrupt_id, &outlet);
53
54 if (result) {
55 pr_debug("%s:%d: lv1_construct_io_irq_outlet failed: %s\n",
56 __func__, __LINE__, ps3_result(result));
57 return result;
58 }
59
60 *virq = irq_create_mapping(NULL, outlet);
61
62 pr_debug("%s:%d: interrupt_id %u => outlet %lu, virq %u\n",
63 __func__, __LINE__, interrupt_id, outlet, *virq);
64
65 return 0;
66}
67
68int ps3_free_io_irq(unsigned int virq)
69{
70 int result;
71
72 result = lv1_destruct_io_irq_outlet(virq_to_hw(virq));
73
74 if (!result)
75 pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
76 __func__, __LINE__, ps3_result(result));
77
78 irq_dispose_mapping(virq);
79
80 return result;
81}
82
83/**
84 * ps3_alloc_event_irq - Allocate a virq for use with a system event.
85 * @virq: The assigned Linux virq.
86 *
87 * The virq can be used with lv1_connect_interrupt_event_receive_port() to
88 * arrange to receive events, or with ps3_send_event_locally() to signal
89 * events.
90 */
91
92int ps3_alloc_event_irq(unsigned int *virq)
93{
94 int result;
95 unsigned long outlet;
96
97 result = lv1_construct_event_receive_port(&outlet);
98
99 if (result) {
100 pr_debug("%s:%d: lv1_construct_event_receive_port failed: %s\n",
101 __func__, __LINE__, ps3_result(result));
102 *virq = NO_IRQ;
103 return result;
104 }
105
106 *virq = irq_create_mapping(NULL, outlet);
107
108 pr_debug("%s:%d: outlet %lu, virq %u\n", __func__, __LINE__, outlet,
109 *virq);
110
111 return 0;
112}
113
114int ps3_free_event_irq(unsigned int virq)
115{
116 int result;
117
118 pr_debug(" -> %s:%d\n", __func__, __LINE__);
119
120 result = lv1_destruct_event_receive_port(virq_to_hw(virq));
121
122 if (result)
123 pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n",
124 __func__, __LINE__, ps3_result(result));
125
126 irq_dispose_mapping(virq);
127
128 pr_debug(" <- %s:%d\n", __func__, __LINE__);
129 return result;
130}
131
132int ps3_send_event_locally(unsigned int virq)
133{
134 return lv1_send_event_locally(virq_to_hw(virq));
135}
136
137/**
138 * ps3_connect_event_irq - Assign a virq to a system bus device.
139 * @did: The HV device identifier read from the system repository.
140 * @interrupt_id: The device interrupt id read from the system repository.
141 * @virq: The assigned Linux virq.
142 *
143 * An event irq represents a virtual device interrupt. The interrupt_id
144 * coresponds to the software interrupt number.
145 */
146
147int ps3_connect_event_irq(const struct ps3_device_id *did,
148 unsigned int interrupt_id, unsigned int *virq)
149{
150 int result;
151
152 result = ps3_alloc_event_irq(virq);
153
154 if (result)
155 return result;
156
157 result = lv1_connect_interrupt_event_receive_port(did->bus_id,
158 did->dev_id, virq_to_hw(*virq), interrupt_id);
159
160 if (result) {
161 pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port"
162 " failed: %s\n", __func__, __LINE__,
163 ps3_result(result));
164 ps3_free_event_irq(*virq);
165 *virq = NO_IRQ;
166 return result;
167 }
168
169 pr_debug("%s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
170 interrupt_id, *virq);
171
172 return 0;
173}
174
175int ps3_disconnect_event_irq(const struct ps3_device_id *did,
176 unsigned int interrupt_id, unsigned int virq)
177{
178 int result;
179
180 pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
181 interrupt_id, virq);
182
183 result = lv1_disconnect_interrupt_event_receive_port(did->bus_id,
184 did->dev_id, virq_to_hw(virq), interrupt_id);
185
186 if (result)
187 pr_debug("%s:%d: lv1_disconnect_interrupt_event_receive_port"
188 " failed: %s\n", __func__, __LINE__,
189 ps3_result(result));
190
191 ps3_free_event_irq(virq);
192
193 pr_debug(" <- %s:%d\n", __func__, __LINE__);
194 return result;
195}
196
197/**
198 * ps3_alloc_vuart_irq - Configure the system virtual uart virq.
199 * @virt_addr_bmp: The caller supplied virtual uart interrupt bitmap.
200 * @virq: The assigned Linux virq.
201 *
202 * The system supports only a single virtual uart, so multiple calls without
203 * freeing the interrupt will return a wrong state error.
204 */
205
206int ps3_alloc_vuart_irq(void* virt_addr_bmp, unsigned int *virq)
207{
208 int result;
209 unsigned long outlet;
210 unsigned long lpar_addr;
211
212 BUG_ON(!is_kernel_addr((unsigned long)virt_addr_bmp));
213
214 lpar_addr = ps3_mm_phys_to_lpar(__pa(virt_addr_bmp));
215
216 result = lv1_configure_virtual_uart_irq(lpar_addr, &outlet);
217
218 if (result) {
219 pr_debug("%s:%d: lv1_configure_virtual_uart_irq failed: %s\n",
220 __func__, __LINE__, ps3_result(result));
221 return result;
222 }
223
224 *virq = irq_create_mapping(NULL, outlet);
225
226 pr_debug("%s:%d: outlet %lu, virq %u\n", __func__, __LINE__,
227 outlet, *virq);
228
229 return 0;
230}
231
232int ps3_free_vuart_irq(unsigned int virq)
233{
234 int result;
235
236 result = lv1_deconfigure_virtual_uart_irq();
237
238 if (result) {
239 pr_debug("%s:%d: lv1_configure_virtual_uart_irq failed: %s\n",
240 __func__, __LINE__, ps3_result(result));
241 return result;
242 }
243
244 irq_dispose_mapping(virq);
245
246 return result;
247}
248
249/**
250 * ps3_alloc_spe_irq - Configure an spe virq.
251 * @spe_id: The spe_id returned from lv1_construct_logical_spe().
252 * @class: The spe interrupt class {0,1,2}.
253 * @virq: The assigned Linux virq.
254 *
255 */
256
257int ps3_alloc_spe_irq(unsigned long spe_id, unsigned int class,
258 unsigned int *virq)
259{
260 int result;
261 unsigned long outlet;
262
263 BUG_ON(class > 2);
264
265 result = lv1_get_spe_irq_outlet(spe_id, class, &outlet);
266
267 if (result) {
268 pr_debug("%s:%d: lv1_get_spe_irq_outlet failed: %s\n",
269 __func__, __LINE__, ps3_result(result));
270 return result;
271 }
272
273 *virq = irq_create_mapping(NULL, outlet);
274
275 pr_debug("%s:%d: spe_id %lu, class %u, outlet %lu, virq %u\n",
276 __func__, __LINE__, spe_id, class, outlet, *virq);
277
278 return 0;
279}
280
281int ps3_free_spe_irq(unsigned int virq)
282{
283 irq_dispose_mapping(virq);
284 return 0;
285}
286
287#define PS3_INVALID_OUTLET ((irq_hw_number_t)-1)
288#define PS3_PLUG_MAX 63
289
290/**
291 * struct bmp - a per cpu irq status and mask bitmap structure
292 * @status: 256 bit status bitmap indexed by plug
293 * @unused_1:
294 * @mask: 256 bit mask bitmap indexed by plug
295 * @unused_2:
296 * @lock:
297 * @ipi_debug_brk_mask:
298 *
299 * The HV mantains per SMT thread mappings of HV outlet to HV plug on
300 * behalf of the guest. These mappings are implemented as 256 bit guest
301 * supplied bitmaps indexed by plug number. The address of the bitmaps are
302 * registered with the HV through lv1_configure_irq_state_bitmap().
303 *
304 * The HV supports 256 plugs per thread, assigned as {0..255}, for a total
305 * of 512 plugs supported on a processor. To simplify the logic this
306 * implementation equates HV plug value to linux virq value, constrains each
307 * interrupt to have a system wide unique plug number, and limits the range
308 * of the plug values to map into the first dword of the bitmaps. This
309 * gives a usable range of plug values of {NUM_ISA_INTERRUPTS..63}. Note
310 * that there is no constraint on how many in this set an individual thread
311 * can aquire.
312 */
313
314struct bmp {
315 struct {
316 unsigned long status;
317 unsigned long unused_1[3];
318 unsigned long mask;
319 unsigned long unused_2[3];
320 } __attribute__ ((packed));
321 spinlock_t lock;
322 unsigned long ipi_debug_brk_mask;
323};
324
325/**
326 * struct private - a per cpu data structure
327 * @node: HV node id
328 * @cpu: HV thread id
329 * @bmp: an HV bmp structure
330 */
331
332struct private {
333 unsigned long node;
334 unsigned int cpu;
335 struct bmp bmp;
336};
337
338#if defined(DEBUG)
339static void _dump_64_bmp(const char *header, const unsigned long *p, unsigned cpu,
340 const char* func, int line)
341{
342 pr_debug("%s:%d: %s %u {%04lx_%04lx_%04lx_%04lx}\n",
343 func, line, header, cpu,
344 *p >> 48, (*p >> 32) & 0xffff, (*p >> 16) & 0xffff,
345 *p & 0xffff);
346}
347
348static void __attribute__ ((unused)) _dump_256_bmp(const char *header,
349 const unsigned long *p, unsigned cpu, const char* func, int line)
350{
351 pr_debug("%s:%d: %s %u {%016lx:%016lx:%016lx:%016lx}\n",
352 func, line, header, cpu, p[0], p[1], p[2], p[3]);
353}
354
355#define dump_bmp(_x) _dump_bmp(_x, __func__, __LINE__)
356static void _dump_bmp(struct private* pd, const char* func, int line)
357{
358 unsigned long flags;
359
360 spin_lock_irqsave(&pd->bmp.lock, flags);
361 _dump_64_bmp("stat", &pd->bmp.status, pd->cpu, func, line);
362 _dump_64_bmp("mask", &pd->bmp.mask, pd->cpu, func, line);
363 spin_unlock_irqrestore(&pd->bmp.lock, flags);
364}
365
366#define dump_mask(_x) _dump_mask(_x, __func__, __LINE__)
367static void __attribute__ ((unused)) _dump_mask(struct private* pd,
368 const char* func, int line)
369{
370 unsigned long flags;
371
372 spin_lock_irqsave(&pd->bmp.lock, flags);
373 _dump_64_bmp("mask", &pd->bmp.mask, pd->cpu, func, line);
374 spin_unlock_irqrestore(&pd->bmp.lock, flags);
375}
376#else
377static void dump_bmp(struct private* pd) {};
378#endif /* defined(DEBUG) */
379
380static void chip_mask(unsigned int virq)
381{
382 unsigned long flags;
383 struct private *pd = get_irq_chip_data(virq);
384
385 pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq);
386
387 BUG_ON(virq < NUM_ISA_INTERRUPTS);
388 BUG_ON(virq > PS3_PLUG_MAX);
389
390 spin_lock_irqsave(&pd->bmp.lock, flags);
391 pd->bmp.mask &= ~(0x8000000000000000UL >> virq);
392 spin_unlock_irqrestore(&pd->bmp.lock, flags);
393
394 lv1_did_update_interrupt_mask(pd->node, pd->cpu);
395}
396
397static void chip_unmask(unsigned int virq)
398{
399 unsigned long flags;
400 struct private *pd = get_irq_chip_data(virq);
401
402 pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq);
403
404 BUG_ON(virq < NUM_ISA_INTERRUPTS);
405 BUG_ON(virq > PS3_PLUG_MAX);
406
407 spin_lock_irqsave(&pd->bmp.lock, flags);
408 pd->bmp.mask |= (0x8000000000000000UL >> virq);
409 spin_unlock_irqrestore(&pd->bmp.lock, flags);
410
411 lv1_did_update_interrupt_mask(pd->node, pd->cpu);
412}
413
414static void chip_eoi(unsigned int virq)
415{
416 lv1_end_of_interrupt(virq);
417}
418
419static struct irq_chip irq_chip = {
420 .typename = "ps3",
421 .mask = chip_mask,
422 .unmask = chip_unmask,
423 .eoi = chip_eoi,
424};
425
426static void host_unmap(struct irq_host *h, unsigned int virq)
427{
428 int result;
429
430 pr_debug("%s:%d: virq %d\n", __func__, __LINE__, virq);
431
432 lv1_disconnect_irq_plug(virq);
433
434 result = set_irq_chip_data(virq, NULL);
435 BUG_ON(result);
436}
437
438static DEFINE_PER_CPU(struct private, private);
439
440static int host_map(struct irq_host *h, unsigned int virq,
441 irq_hw_number_t hwirq)
442{
443 int result;
444 unsigned int cpu;
445
446 pr_debug(" -> %s:%d\n", __func__, __LINE__);
447 pr_debug("%s:%d: hwirq %lu => virq %u\n", __func__, __LINE__, hwirq,
448 virq);
449
450 /* bind this virq to a cpu */
451
452 preempt_disable();
453 cpu = smp_processor_id();
454 result = lv1_connect_irq_plug(virq, hwirq);
455 preempt_enable();
456
457 if (result) {
458 pr_info("%s:%d: lv1_connect_irq_plug failed:"
459 " %s\n", __func__, __LINE__, ps3_result(result));
460 return -EPERM;
461 }
462
463 result = set_irq_chip_data(virq, &per_cpu(private, cpu));
464 BUG_ON(result);
465
466 set_irq_chip_and_handler(virq, &irq_chip, handle_fasteoi_irq);
467
468 pr_debug(" <- %s:%d\n", __func__, __LINE__);
469 return result;
470}
471
472static struct irq_host_ops host_ops = {
473 .map = host_map,
474 .unmap = host_unmap,
475};
476
477void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq)
478{
479 struct private *pd = &per_cpu(private, cpu);
480
481 pd->bmp.ipi_debug_brk_mask = 0x8000000000000000UL >> virq;
482
483 pr_debug("%s:%d: cpu %u, virq %u, mask %lxh\n", __func__, __LINE__,
484 cpu, virq, pd->bmp.ipi_debug_brk_mask);
485}
486
487static int bmp_get_and_clear_status_bit(struct bmp *m)
488{
489 unsigned long flags;
490 unsigned int bit;
491 unsigned long x;
492
493 spin_lock_irqsave(&m->lock, flags);
494
495 /* check for ipi break first to stop this cpu ASAP */
496
497 if (m->status & m->ipi_debug_brk_mask) {
498 m->status &= ~m->ipi_debug_brk_mask;
499 spin_unlock_irqrestore(&m->lock, flags);
500 return __ilog2(m->ipi_debug_brk_mask);
501 }
502
503 x = (m->status & m->mask);
504
505 for (bit = NUM_ISA_INTERRUPTS, x <<= bit; x; bit++, x <<= 1)
506 if (x & 0x8000000000000000UL) {
507 m->status &= ~(0x8000000000000000UL >> bit);
508 spin_unlock_irqrestore(&m->lock, flags);
509 return bit;
510 }
511
512 spin_unlock_irqrestore(&m->lock, flags);
513
514 pr_debug("%s:%d: not found\n", __func__, __LINE__);
515 return -1;
516}
517
518unsigned int ps3_get_irq(void)
519{
520 int plug;
521
522 struct private *pd = &__get_cpu_var(private);
523
524 plug = bmp_get_and_clear_status_bit(&pd->bmp);
525
526 if (plug < 1) {
527 pr_debug("%s:%d: no plug found: cpu %u\n", __func__, __LINE__,
528 pd->cpu);
529 dump_bmp(&per_cpu(private, 0));
530 dump_bmp(&per_cpu(private, 1));
531 return NO_IRQ;
532 }
533
534#if defined(DEBUG)
535 if (plug < NUM_ISA_INTERRUPTS || plug > PS3_PLUG_MAX) {
536 dump_bmp(&per_cpu(private, 0));
537 dump_bmp(&per_cpu(private, 1));
538 BUG();
539 }
540#endif
541 return plug;
542}
543
544void __init ps3_init_IRQ(void)
545{
546 int result;
547 unsigned long node;
548 unsigned cpu;
549 struct irq_host *host;
550
551 lv1_get_logical_ppe_id(&node);
552
553 host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, &host_ops,
554 PS3_INVALID_OUTLET);
555 irq_set_default_host(host);
556 irq_set_virq_count(PS3_PLUG_MAX + 1);
557
558 for_each_possible_cpu(cpu) {
559 struct private *pd = &per_cpu(private, cpu);
560
561 pd->node = node;
562 pd->cpu = cpu;
563 spin_lock_init(&pd->bmp.lock);
564
565 result = lv1_configure_irq_state_bitmap(node, cpu,
566 ps3_mm_phys_to_lpar(__pa(&pd->bmp.status)));
567
568 if (result)
569 pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:"
570 " %s\n", __func__, __LINE__,
571 ps3_result(result));
572 }
573
574 ppc_md.get_irq = ps3_get_irq;
575}
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c
new file mode 100644
index 000000000000..49c0d010d491
--- /dev/null
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -0,0 +1,831 @@
1/*
2 * PS3 address space management.
3 *
4 * Copyright (C) 2006 Sony Computer Entertainment Inc.
5 * Copyright 2006 Sony Corp.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/memory_hotplug.h>
24
25#include <asm/firmware.h>
26#include <asm/lmb.h>
27#include <asm/udbg.h>
28#include <asm/ps3.h>
29#include <asm/lv1call.h>
30
31#include "platform.h"
32
33#if defined(DEBUG)
34#define DBG(fmt...) udbg_printf(fmt)
35#else
36#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
37#endif
38
39enum {
40#if defined(CONFIG_PS3_USE_LPAR_ADDR)
41 USE_LPAR_ADDR = 1,
42#else
43 USE_LPAR_ADDR = 0,
44#endif
45#if defined(CONFIG_PS3_DYNAMIC_DMA)
46 USE_DYNAMIC_DMA = 1,
47#else
48 USE_DYNAMIC_DMA = 0,
49#endif
50};
51
52enum {
53 PAGE_SHIFT_4K = 12U,
54 PAGE_SHIFT_64K = 16U,
55 PAGE_SHIFT_16M = 24U,
56};
57
58static unsigned long make_page_sizes(unsigned long a, unsigned long b)
59{
60 return (a << 56) | (b << 48);
61}
62
63enum {
64 ALLOCATE_MEMORY_TRY_ALT_UNIT = 0X04,
65 ALLOCATE_MEMORY_ADDR_ZERO = 0X08,
66};
67
68/* valid htab sizes are {18,19,20} = 256K, 512K, 1M */
69
70enum {
71 HTAB_SIZE_MAX = 20U, /* HV limit of 1MB */
72 HTAB_SIZE_MIN = 18U, /* CPU limit of 256KB */
73};
74
75/*============================================================================*/
76/* virtual address space routines */
77/*============================================================================*/
78
79/**
80 * struct mem_region - memory region structure
81 * @base: base address
82 * @size: size in bytes
83 * @offset: difference between base and rm.size
84 */
85
86struct mem_region {
87 unsigned long base;
88 unsigned long size;
89 unsigned long offset;
90};
91
92/**
93 * struct map - address space state variables holder
94 * @total: total memory available as reported by HV
95 * @vas_id - HV virtual address space id
96 * @htab_size: htab size in bytes
97 *
98 * The HV virtual address space (vas) allows for hotplug memory regions.
99 * Memory regions can be created and destroyed in the vas at runtime.
100 * @rm: real mode (bootmem) region
101 * @r1: hotplug memory region(s)
102 *
103 * ps3 addresses
104 * virt_addr: a cpu 'translated' effective address
105 * phys_addr: an address in what Linux thinks is the physical address space
106 * lpar_addr: an address in the HV virtual address space
107 * bus_addr: an io controller 'translated' address on a device bus
108 */
109
110struct map {
111 unsigned long total;
112 unsigned long vas_id;
113 unsigned long htab_size;
114 struct mem_region rm;
115 struct mem_region r1;
116};
117
118#define debug_dump_map(x) _debug_dump_map(x, __func__, __LINE__)
119static void _debug_dump_map(const struct map* m, const char* func, int line)
120{
121 DBG("%s:%d: map.total = %lxh\n", func, line, m->total);
122 DBG("%s:%d: map.rm.size = %lxh\n", func, line, m->rm.size);
123 DBG("%s:%d: map.vas_id = %lu\n", func, line, m->vas_id);
124 DBG("%s:%d: map.htab_size = %lxh\n", func, line, m->htab_size);
125 DBG("%s:%d: map.r1.base = %lxh\n", func, line, m->r1.base);
126 DBG("%s:%d: map.r1.offset = %lxh\n", func, line, m->r1.offset);
127 DBG("%s:%d: map.r1.size = %lxh\n", func, line, m->r1.size);
128}
129
130static struct map map;
131
132/**
133 * ps3_mm_phys_to_lpar - translate a linux physical address to lpar address
134 * @phys_addr: linux physical address
135 */
136
137unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr)
138{
139 BUG_ON(is_kernel_addr(phys_addr));
140 if (USE_LPAR_ADDR)
141 return phys_addr;
142 else
143 return (phys_addr < map.rm.size || phys_addr >= map.total)
144 ? phys_addr : phys_addr + map.r1.offset;
145}
146
147EXPORT_SYMBOL(ps3_mm_phys_to_lpar);
148
149/**
150 * ps3_mm_vas_create - create the virtual address space
151 */
152
153void __init ps3_mm_vas_create(unsigned long* htab_size)
154{
155 int result;
156 unsigned long start_address;
157 unsigned long size;
158 unsigned long access_right;
159 unsigned long max_page_size;
160 unsigned long flags;
161
162 result = lv1_query_logical_partition_address_region_info(0,
163 &start_address, &size, &access_right, &max_page_size,
164 &flags);
165
166 if (result) {
167 DBG("%s:%d: lv1_query_logical_partition_address_region_info "
168 "failed: %s\n", __func__, __LINE__,
169 ps3_result(result));
170 goto fail;
171 }
172
173 if (max_page_size < PAGE_SHIFT_16M) {
174 DBG("%s:%d: bad max_page_size %lxh\n", __func__, __LINE__,
175 max_page_size);
176 goto fail;
177 }
178
179 BUILD_BUG_ON(CONFIG_PS3_HTAB_SIZE > HTAB_SIZE_MAX);
180 BUILD_BUG_ON(CONFIG_PS3_HTAB_SIZE < HTAB_SIZE_MIN);
181
182 result = lv1_construct_virtual_address_space(CONFIG_PS3_HTAB_SIZE,
183 2, make_page_sizes(PAGE_SHIFT_16M, PAGE_SHIFT_64K),
184 &map.vas_id, &map.htab_size);
185
186 if (result) {
187 DBG("%s:%d: lv1_construct_virtual_address_space failed: %s\n",
188 __func__, __LINE__, ps3_result(result));
189 goto fail;
190 }
191
192 result = lv1_select_virtual_address_space(map.vas_id);
193
194 if (result) {
195 DBG("%s:%d: lv1_select_virtual_address_space failed: %s\n",
196 __func__, __LINE__, ps3_result(result));
197 goto fail;
198 }
199
200 *htab_size = map.htab_size;
201
202 debug_dump_map(&map);
203
204 return;
205
206fail:
207 panic("ps3_mm_vas_create failed");
208}
209
210/**
211 * ps3_mm_vas_destroy -
212 */
213
214void ps3_mm_vas_destroy(void)
215{
216 if (map.vas_id) {
217 lv1_select_virtual_address_space(0);
218 lv1_destruct_virtual_address_space(map.vas_id);
219 map.vas_id = 0;
220 }
221}
222
223/*============================================================================*/
224/* memory hotplug routines */
225/*============================================================================*/
226
227/**
228 * ps3_mm_region_create - create a memory region in the vas
229 * @r: pointer to a struct mem_region to accept initialized values
230 * @size: requested region size
231 *
232 * This implementation creates the region with the vas large page size.
233 * @size is rounded down to a multiple of the vas large page size.
234 */
235
236int ps3_mm_region_create(struct mem_region *r, unsigned long size)
237{
238 int result;
239 unsigned long muid;
240
241 r->size = _ALIGN_DOWN(size, 1 << PAGE_SHIFT_16M);
242
243 DBG("%s:%d requested %lxh\n", __func__, __LINE__, size);
244 DBG("%s:%d actual %lxh\n", __func__, __LINE__, r->size);
245 DBG("%s:%d difference %lxh (%luMB)\n", __func__, __LINE__,
246 (unsigned long)(size - r->size),
247 (size - r->size) / 1024 / 1024);
248
249 if (r->size == 0) {
250 DBG("%s:%d: size == 0\n", __func__, __LINE__);
251 result = -1;
252 goto zero_region;
253 }
254
255 result = lv1_allocate_memory(r->size, PAGE_SHIFT_16M, 0,
256 ALLOCATE_MEMORY_TRY_ALT_UNIT, &r->base, &muid);
257
258 if (result || r->base < map.rm.size) {
259 DBG("%s:%d: lv1_allocate_memory failed: %s\n",
260 __func__, __LINE__, ps3_result(result));
261 goto zero_region;
262 }
263
264 r->offset = r->base - map.rm.size;
265 return result;
266
267zero_region:
268 r->size = r->base = r->offset = 0;
269 return result;
270}
271
272/**
273 * ps3_mm_region_destroy - destroy a memory region
274 * @r: pointer to struct mem_region
275 */
276
277void ps3_mm_region_destroy(struct mem_region *r)
278{
279 if (r->base) {
280 lv1_release_memory(r->base);
281 r->size = r->base = r->offset = 0;
282 map.total = map.rm.size;
283 }
284}
285
286/**
287 * ps3_mm_add_memory - hot add memory
288 */
289
290static int __init ps3_mm_add_memory(void)
291{
292 int result;
293 unsigned long start_addr;
294 unsigned long start_pfn;
295 unsigned long nr_pages;
296
297 if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
298 return 0;
299
300 BUG_ON(!mem_init_done);
301
302 start_addr = USE_LPAR_ADDR ? map.r1.base : map.rm.size;
303 start_pfn = start_addr >> PAGE_SHIFT;
304 nr_pages = (map.r1.size + PAGE_SIZE - 1) >> PAGE_SHIFT;
305
306 DBG("%s:%d: start_addr %lxh, start_pfn %lxh, nr_pages %lxh\n",
307 __func__, __LINE__, start_addr, start_pfn, nr_pages);
308
309 result = add_memory(0, start_addr, map.r1.size);
310
311 if (result) {
312 DBG("%s:%d: add_memory failed: (%d)\n",
313 __func__, __LINE__, result);
314 return result;
315 }
316
317 result = online_pages(start_pfn, nr_pages);
318
319 if (result)
320 DBG("%s:%d: online_pages failed: (%d)\n",
321 __func__, __LINE__, result);
322
323 return result;
324}
325
326core_initcall(ps3_mm_add_memory);
327
328/*============================================================================*/
329/* dma routines */
330/*============================================================================*/
331
332/**
333 * dma_lpar_to_bus - Translate an lpar address to ioc mapped bus address.
334 * @r: pointer to dma region structure
335 * @lpar_addr: HV lpar address
336 */
337
338static unsigned long dma_lpar_to_bus(struct ps3_dma_region *r,
339 unsigned long lpar_addr)
340{
341 BUG_ON(lpar_addr >= map.r1.base + map.r1.size);
342 return r->bus_addr + (lpar_addr <= map.rm.size ? lpar_addr
343 : lpar_addr - map.r1.offset);
344}
345
346#define dma_dump_region(_a) _dma_dump_region(_a, __func__, __LINE__)
347static void _dma_dump_region(const struct ps3_dma_region *r, const char* func,
348 int line)
349{
350 DBG("%s:%d: dev %u:%u\n", func, line, r->did.bus_id,
351 r->did.dev_id);
352 DBG("%s:%d: page_size %u\n", func, line, r->page_size);
353 DBG("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr);
354 DBG("%s:%d: len %lxh\n", func, line, r->len);
355}
356
357/**
358 * dma_chunk - A chunk of dma pages mapped by the io controller.
359 * @region - The dma region that owns this chunk.
360 * @lpar_addr: Starting lpar address of the area to map.
361 * @bus_addr: Starting ioc bus address of the area to map.
362 * @len: Length in bytes of the area to map.
363 * @link: A struct list_head used with struct ps3_dma_region.chunk_list, the
364 * list of all chuncks owned by the region.
365 *
366 * This implementation uses a very simple dma page manager
367 * based on the dma_chunk structure. This scheme assumes
368 * that all drivers use very well behaved dma ops.
369 */
370
371struct dma_chunk {
372 struct ps3_dma_region *region;
373 unsigned long lpar_addr;
374 unsigned long bus_addr;
375 unsigned long len;
376 struct list_head link;
377 unsigned int usage_count;
378};
379
380#define dma_dump_chunk(_a) _dma_dump_chunk(_a, __func__, __LINE__)
381static void _dma_dump_chunk (const struct dma_chunk* c, const char* func,
382 int line)
383{
384 DBG("%s:%d: r.dev %u:%u\n", func, line,
385 c->region->did.bus_id, c->region->did.dev_id);
386 DBG("%s:%d: r.bus_addr %lxh\n", func, line, c->region->bus_addr);
387 DBG("%s:%d: r.page_size %u\n", func, line, c->region->page_size);
388 DBG("%s:%d: r.len %lxh\n", func, line, c->region->len);
389 DBG("%s:%d: c.lpar_addr %lxh\n", func, line, c->lpar_addr);
390 DBG("%s:%d: c.bus_addr %lxh\n", func, line, c->bus_addr);
391 DBG("%s:%d: c.len %lxh\n", func, line, c->len);
392}
393
394static struct dma_chunk * dma_find_chunk(struct ps3_dma_region *r,
395 unsigned long bus_addr, unsigned long len)
396{
397 struct dma_chunk *c;
398 unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, 1 << r->page_size);
399 unsigned long aligned_len = _ALIGN_UP(len, 1 << r->page_size);
400
401 list_for_each_entry(c, &r->chunk_list.head, link) {
402 /* intersection */
403 if (aligned_bus >= c->bus_addr
404 && aligned_bus < c->bus_addr + c->len
405 && aligned_bus + aligned_len <= c->bus_addr + c->len) {
406 return c;
407 }
408 /* below */
409 if (aligned_bus + aligned_len <= c->bus_addr) {
410 continue;
411 }
412 /* above */
413 if (aligned_bus >= c->bus_addr + c->len) {
414 continue;
415 }
416
417 /* we don't handle the multi-chunk case for now */
418
419 dma_dump_chunk(c);
420 BUG();
421 }
422 return NULL;
423}
424
425static int dma_free_chunk(struct dma_chunk *c)
426{
427 int result = 0;
428
429 if (c->bus_addr) {
430 result = lv1_unmap_device_dma_region(c->region->did.bus_id,
431 c->region->did.dev_id, c->bus_addr, c->len);
432 BUG_ON(result);
433 }
434
435 kfree(c);
436 return result;
437}
438
439/**
440 * dma_map_pages - Maps dma pages into the io controller bus address space.
441 * @r: Pointer to a struct ps3_dma_region.
442 * @phys_addr: Starting physical address of the area to map.
443 * @len: Length in bytes of the area to map.
444 * c_out: A pointer to receive an allocated struct dma_chunk for this area.
445 *
446 * This is the lowest level dma mapping routine, and is the one that will
447 * make the HV call to add the pages into the io controller address space.
448 */
449
450static int dma_map_pages(struct ps3_dma_region *r, unsigned long phys_addr,
451 unsigned long len, struct dma_chunk **c_out)
452{
453 int result;
454 struct dma_chunk *c;
455
456 c = kzalloc(sizeof(struct dma_chunk), GFP_ATOMIC);
457
458 if (!c) {
459 result = -ENOMEM;
460 goto fail_alloc;
461 }
462
463 c->region = r;
464 c->lpar_addr = ps3_mm_phys_to_lpar(phys_addr);
465 c->bus_addr = dma_lpar_to_bus(r, c->lpar_addr);
466 c->len = len;
467
468 result = lv1_map_device_dma_region(c->region->did.bus_id,
469 c->region->did.dev_id, c->lpar_addr, c->bus_addr, c->len,
470 0xf800000000000000UL);
471
472 if (result) {
473 DBG("%s:%d: lv1_map_device_dma_region failed: %s\n",
474 __func__, __LINE__, ps3_result(result));
475 goto fail_map;
476 }
477
478 list_add(&c->link, &r->chunk_list.head);
479
480 *c_out = c;
481 return 0;
482
483fail_map:
484 kfree(c);
485fail_alloc:
486 *c_out = NULL;
487 DBG(" <- %s:%d\n", __func__, __LINE__);
488 return result;
489}
490
491/**
492 * dma_region_create - Create a device dma region.
493 * @r: Pointer to a struct ps3_dma_region.
494 *
495 * This is the lowest level dma region create routine, and is the one that
496 * will make the HV call to create the region.
497 */
498
499static int dma_region_create(struct ps3_dma_region* r)
500{
501 int result;
502
503 r->len = _ALIGN_UP(map.total, 1 << r->page_size);
504 INIT_LIST_HEAD(&r->chunk_list.head);
505 spin_lock_init(&r->chunk_list.lock);
506
507 result = lv1_allocate_device_dma_region(r->did.bus_id, r->did.dev_id,
508 r->len, r->page_size, r->region_type, &r->bus_addr);
509
510 dma_dump_region(r);
511
512 if (result) {
513 DBG("%s:%d: lv1_allocate_device_dma_region failed: %s\n",
514 __func__, __LINE__, ps3_result(result));
515 r->len = r->bus_addr = 0;
516 }
517
518 return result;
519}
520
521/**
522 * dma_region_free - Free a device dma region.
523 * @r: Pointer to a struct ps3_dma_region.
524 *
525 * This is the lowest level dma region free routine, and is the one that
526 * will make the HV call to free the region.
527 */
528
529static int dma_region_free(struct ps3_dma_region* r)
530{
531 int result;
532 struct dma_chunk *c;
533 struct dma_chunk *tmp;
534
535 list_for_each_entry_safe(c, tmp, &r->chunk_list.head, link) {
536 list_del(&c->link);
537 dma_free_chunk(c);
538 }
539
540 result = lv1_free_device_dma_region(r->did.bus_id, r->did.dev_id,
541 r->bus_addr);
542
543 if (result)
544 DBG("%s:%d: lv1_free_device_dma_region failed: %s\n",
545 __func__, __LINE__, ps3_result(result));
546
547 r->len = r->bus_addr = 0;
548
549 return result;
550}
551
552/**
553 * dma_map_area - Map an area of memory into a device dma region.
554 * @r: Pointer to a struct ps3_dma_region.
555 * @virt_addr: Starting virtual address of the area to map.
556 * @len: Length in bytes of the area to map.
557 * @bus_addr: A pointer to return the starting ioc bus address of the area to
558 * map.
559 *
560 * This is the common dma mapping routine.
561 */
562
563static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
564 unsigned long len, unsigned long *bus_addr)
565{
566 int result;
567 unsigned long flags;
568 struct dma_chunk *c;
569 unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr)
570 : virt_addr;
571
572 *bus_addr = dma_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr));
573
574 if (!USE_DYNAMIC_DMA) {
575 unsigned long lpar_addr = ps3_mm_phys_to_lpar(phys_addr);
576 DBG(" -> %s:%d\n", __func__, __LINE__);
577 DBG("%s:%d virt_addr %lxh\n", __func__, __LINE__,
578 virt_addr);
579 DBG("%s:%d phys_addr %lxh\n", __func__, __LINE__,
580 phys_addr);
581 DBG("%s:%d lpar_addr %lxh\n", __func__, __LINE__,
582 lpar_addr);
583 DBG("%s:%d len %lxh\n", __func__, __LINE__, len);
584 DBG("%s:%d bus_addr %lxh (%lxh)\n", __func__, __LINE__,
585 *bus_addr, len);
586 }
587
588 spin_lock_irqsave(&r->chunk_list.lock, flags);
589 c = dma_find_chunk(r, *bus_addr, len);
590
591 if (c) {
592 c->usage_count++;
593 spin_unlock_irqrestore(&r->chunk_list.lock, flags);
594 return 0;
595 }
596
597 result = dma_map_pages(r, _ALIGN_DOWN(phys_addr, 1 << r->page_size),
598 _ALIGN_UP(len, 1 << r->page_size), &c);
599
600 if (result) {
601 *bus_addr = 0;
602 DBG("%s:%d: dma_map_pages failed (%d)\n",
603 __func__, __LINE__, result);
604 spin_unlock_irqrestore(&r->chunk_list.lock, flags);
605 return result;
606 }
607
608 c->usage_count = 1;
609
610 spin_unlock_irqrestore(&r->chunk_list.lock, flags);
611 return result;
612}
613
614/**
615 * dma_unmap_area - Unmap an area of memory from a device dma region.
616 * @r: Pointer to a struct ps3_dma_region.
617 * @bus_addr: The starting ioc bus address of the area to unmap.
618 * @len: Length in bytes of the area to unmap.
619 *
620 * This is the common dma unmap routine.
621 */
622
623int dma_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr,
624 unsigned long len)
625{
626 unsigned long flags;
627 struct dma_chunk *c;
628
629 spin_lock_irqsave(&r->chunk_list.lock, flags);
630 c = dma_find_chunk(r, bus_addr, len);
631
632 if (!c) {
633 unsigned long aligned_bus = _ALIGN_DOWN(bus_addr,
634 1 << r->page_size);
635 unsigned long aligned_len = _ALIGN_UP(len, 1 << r->page_size);
636 DBG("%s:%d: not found: bus_addr %lxh\n",
637 __func__, __LINE__, bus_addr);
638 DBG("%s:%d: not found: len %lxh\n",
639 __func__, __LINE__, len);
640 DBG("%s:%d: not found: aligned_bus %lxh\n",
641 __func__, __LINE__, aligned_bus);
642 DBG("%s:%d: not found: aligned_len %lxh\n",
643 __func__, __LINE__, aligned_len);
644 BUG();
645 }
646
647 c->usage_count--;
648
649 if (!c->usage_count) {
650 list_del(&c->link);
651 dma_free_chunk(c);
652 }
653
654 spin_unlock_irqrestore(&r->chunk_list.lock, flags);
655 return 0;
656}
657
658/**
659 * dma_region_create_linear - Setup a linear dma maping for a device.
660 * @r: Pointer to a struct ps3_dma_region.
661 *
662 * This routine creates an HV dma region for the device and maps all available
663 * ram into the io controller bus address space.
664 */
665
666static int dma_region_create_linear(struct ps3_dma_region *r)
667{
668 int result;
669 unsigned long tmp;
670
671 /* force 16M dma pages for linear mapping */
672
673 if (r->page_size != PS3_DMA_16M) {
674 pr_info("%s:%d: forcing 16M pages for linear map\n",
675 __func__, __LINE__);
676 r->page_size = PS3_DMA_16M;
677 }
678
679 result = dma_region_create(r);
680 BUG_ON(result);
681
682 result = dma_map_area(r, map.rm.base, map.rm.size, &tmp);
683 BUG_ON(result);
684
685 if (USE_LPAR_ADDR)
686 result = dma_map_area(r, map.r1.base, map.r1.size,
687 &tmp);
688 else
689 result = dma_map_area(r, map.rm.size, map.r1.size,
690 &tmp);
691
692 BUG_ON(result);
693
694 return result;
695}
696
697/**
698 * dma_region_free_linear - Free a linear dma mapping for a device.
699 * @r: Pointer to a struct ps3_dma_region.
700 *
701 * This routine will unmap all mapped areas and free the HV dma region.
702 */
703
704static int dma_region_free_linear(struct ps3_dma_region *r)
705{
706 int result;
707
708 result = dma_unmap_area(r, dma_lpar_to_bus(r, 0), map.rm.size);
709 BUG_ON(result);
710
711 result = dma_unmap_area(r, dma_lpar_to_bus(r, map.r1.base),
712 map.r1.size);
713 BUG_ON(result);
714
715 result = dma_region_free(r);
716 BUG_ON(result);
717
718 return result;
719}
720
721/**
722 * dma_map_area_linear - Map an area of memory into a device dma region.
723 * @r: Pointer to a struct ps3_dma_region.
724 * @virt_addr: Starting virtual address of the area to map.
725 * @len: Length in bytes of the area to map.
726 * @bus_addr: A pointer to return the starting ioc bus address of the area to
727 * map.
728 *
729 * This routine just returns the coresponding bus address. Actual mapping
730 * occurs in dma_region_create_linear().
731 */
732
733static int dma_map_area_linear(struct ps3_dma_region *r,
734 unsigned long virt_addr, unsigned long len, unsigned long *bus_addr)
735{
736 unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr)
737 : virt_addr;
738 *bus_addr = dma_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr));
739 return 0;
740}
741
742/**
743 * dma_unmap_area_linear - Unmap an area of memory from a device dma region.
744 * @r: Pointer to a struct ps3_dma_region.
745 * @bus_addr: The starting ioc bus address of the area to unmap.
746 * @len: Length in bytes of the area to unmap.
747 *
748 * This routine does nothing. Unmapping occurs in dma_region_free_linear().
749 */
750
751static int dma_unmap_area_linear(struct ps3_dma_region *r,
752 unsigned long bus_addr, unsigned long len)
753{
754 return 0;
755}
756
757int ps3_dma_region_create(struct ps3_dma_region *r)
758{
759 return (USE_DYNAMIC_DMA)
760 ? dma_region_create(r)
761 : dma_region_create_linear(r);
762}
763
764int ps3_dma_region_free(struct ps3_dma_region *r)
765{
766 return (USE_DYNAMIC_DMA)
767 ? dma_region_free(r)
768 : dma_region_free_linear(r);
769}
770
771int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr,
772 unsigned long len, unsigned long *bus_addr)
773{
774 return (USE_DYNAMIC_DMA)
775 ? dma_map_area(r, virt_addr, len, bus_addr)
776 : dma_map_area_linear(r, virt_addr, len, bus_addr);
777}
778
779int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr,
780 unsigned long len)
781{
782 return (USE_DYNAMIC_DMA) ? dma_unmap_area(r, bus_addr, len)
783 : dma_unmap_area_linear(r, bus_addr, len);
784}
785
786/*============================================================================*/
787/* system startup routines */
788/*============================================================================*/
789
790/**
791 * ps3_mm_init - initialize the address space state variables
792 */
793
794void __init ps3_mm_init(void)
795{
796 int result;
797
798 DBG(" -> %s:%d\n", __func__, __LINE__);
799
800 result = ps3_repository_read_mm_info(&map.rm.base, &map.rm.size,
801 &map.total);
802
803 if (result)
804 panic("ps3_repository_read_mm_info() failed");
805
806 map.rm.offset = map.rm.base;
807 map.vas_id = map.htab_size = 0;
808
809 /* this implementation assumes map.rm.base is zero */
810
811 BUG_ON(map.rm.base);
812 BUG_ON(!map.rm.size);
813
814 lmb_add(map.rm.base, map.rm.size);
815 lmb_analyze();
816
817 /* arrange to do this in ps3_mm_add_memory */
818 ps3_mm_region_create(&map.r1, map.total - map.rm.size);
819
820 DBG(" <- %s:%d\n", __func__, __LINE__);
821}
822
823/**
824 * ps3_mm_shutdown - final cleanup of address space
825 */
826
827void ps3_mm_shutdown(void)
828{
829 ps3_mm_region_destroy(&map.r1);
830 map.total = map.rm.size;
831}
diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c
new file mode 100644
index 000000000000..58358305dc10
--- /dev/null
+++ b/arch/powerpc/platforms/ps3/os-area.c
@@ -0,0 +1,259 @@
1/*
2 * PS3 'Other OS' area data.
3 *
4 * Copyright (C) 2006 Sony Computer Entertainment Inc.
5 * Copyright 2006 Sony Corp.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/kernel.h>
22#include <linux/io.h>
23
24#include <asm/lmb.h>
25#include <asm/ps3.h>
26
27#include "platform.h"
28
29enum {
30 OS_AREA_SEGMENT_SIZE = 0X200,
31};
32
33enum {
34 HEADER_LDR_FORMAT_RAW = 0,
35 HEADER_LDR_FORMAT_GZIP = 1,
36};
37
38/**
39 * struct os_area_header - os area header segment.
40 * @magic_num: Always 'cell_ext_os_area'.
41 * @hdr_version: Header format version number.
42 * @os_area_offset: Starting segment number of os image area.
43 * @ldr_area_offset: Starting segment number of bootloader image area.
44 * @ldr_format: HEADER_LDR_FORMAT flag.
45 * @ldr_size: Size of bootloader image in bytes.
46 *
47 * Note that the docs refer to area offsets. These are offsets in units of
48 * segments from the start of the os area (top of the header). These are
49 * better thought of as segment numbers. The os area of the os area is
50 * reserved for the os image.
51 */
52
53struct os_area_header {
54 s8 magic_num[16];
55 u32 hdr_version;
56 u32 os_area_offset;
57 u32 ldr_area_offset;
58 u32 _reserved_1;
59 u32 ldr_format;
60 u32 ldr_size;
61 u32 _reserved_2[6];
62} __attribute__ ((packed));
63
64enum {
65 PARAM_BOOT_FLAG_GAME_OS = 0,
66 PARAM_BOOT_FLAG_OTHER_OS = 1,
67};
68
69enum {
70 PARAM_AV_MULTI_OUT_NTSC = 0,
71 PARAM_AV_MULTI_OUT_PAL_RGB = 1,
72 PARAM_AV_MULTI_OUT_PAL_YCBCR = 2,
73 PARAM_AV_MULTI_OUT_SECAM = 3,
74};
75
76enum {
77 PARAM_CTRL_BUTTON_O_IS_YES = 0,
78 PARAM_CTRL_BUTTON_X_IS_YES = 1,
79};
80
81/**
82 * struct os_area_params - os area params segment.
83 * @boot_flag: User preference of operating system, PARAM_BOOT_FLAG flag.
84 * @num_params: Number of params in this (params) segment.
85 * @rtc_diff: Difference in seconds between 1970 and the ps3 rtc value.
86 * @av_multi_out: User preference of AV output, PARAM_AV_MULTI_OUT flag.
87 * @ctrl_button: User preference of controller button config, PARAM_CTRL_BUTTON
88 * flag.
89 * @static_ip_addr: User preference of static IP address.
90 * @network_mask: User preference of static network mask.
91 * @default_gateway: User preference of static default gateway.
92 * @dns_primary: User preference of static primary dns server.
93 * @dns_secondary: User preference of static secondary dns server.
94 *
95 * User preference of zero for static_ip_addr means use dhcp.
96 */
97
98struct os_area_params {
99 u32 boot_flag;
100 u32 _reserved_1[3];
101 u32 num_params;
102 u32 _reserved_2[3];
103 /* param 0 */
104 s64 rtc_diff;
105 u8 av_multi_out;
106 u8 ctrl_button;
107 u8 _reserved_3[6];
108 /* param 1 */
109 u8 static_ip_addr[4];
110 u8 network_mask[4];
111 u8 default_gateway[4];
112 u8 _reserved_4[4];
113 /* param 2 */
114 u8 dns_primary[4];
115 u8 dns_secondary[4];
116 u8 _reserved_5[8];
117} __attribute__ ((packed));
118
119/**
120 * struct saved_params - Static working copies of data from the 'Other OS' area.
121 *
122 * For the convinience of the guest, the HV makes a copy of the 'Other OS' area
123 * in flash to a high address in the boot memory region and then puts that RAM
124 * address and the byte count into the repository for retreval by the guest.
125 * We copy the data we want into a static variable and allow the memory setup
126 * by the HV to be claimed by the lmb manager.
127 */
128
129struct saved_params {
130 /* param 0 */
131 s64 rtc_diff;
132 unsigned int av_multi_out;
133 unsigned int ctrl_button;
134 /* param 1 */
135 u8 static_ip_addr[4];
136 u8 network_mask[4];
137 u8 default_gateway[4];
138 /* param 2 */
139 u8 dns_primary[4];
140 u8 dns_secondary[4];
141} static saved_params;
142
143#define dump_header(_a) _dump_header(_a, __func__, __LINE__)
144static void _dump_header(const struct os_area_header __iomem *h, const char* func,
145 int line)
146{
147 pr_debug("%s:%d: h.magic_num: '%s'\n", func, line,
148 h->magic_num);
149 pr_debug("%s:%d: h.hdr_version: %u\n", func, line,
150 h->hdr_version);
151 pr_debug("%s:%d: h.os_area_offset: %u\n", func, line,
152 h->os_area_offset);
153 pr_debug("%s:%d: h.ldr_area_offset: %u\n", func, line,
154 h->ldr_area_offset);
155 pr_debug("%s:%d: h.ldr_format: %u\n", func, line,
156 h->ldr_format);
157 pr_debug("%s:%d: h.ldr_size: %xh\n", func, line,
158 h->ldr_size);
159}
160
161#define dump_params(_a) _dump_params(_a, __func__, __LINE__)
162static void _dump_params(const struct os_area_params __iomem *p, const char* func,
163 int line)
164{
165 pr_debug("%s:%d: p.boot_flag: %u\n", func, line, p->boot_flag);
166 pr_debug("%s:%d: p.num_params: %u\n", func, line, p->num_params);
167 pr_debug("%s:%d: p.rtc_diff %ld\n", func, line, p->rtc_diff);
168 pr_debug("%s:%d: p.av_multi_out %u\n", func, line, p->av_multi_out);
169 pr_debug("%s:%d: p.ctrl_button: %u\n", func, line, p->ctrl_button);
170 pr_debug("%s:%d: p.static_ip_addr: %u.%u.%u.%u\n", func, line,
171 p->static_ip_addr[0], p->static_ip_addr[1],
172 p->static_ip_addr[2], p->static_ip_addr[3]);
173 pr_debug("%s:%d: p.network_mask: %u.%u.%u.%u\n", func, line,
174 p->network_mask[0], p->network_mask[1],
175 p->network_mask[2], p->network_mask[3]);
176 pr_debug("%s:%d: p.default_gateway: %u.%u.%u.%u\n", func, line,
177 p->default_gateway[0], p->default_gateway[1],
178 p->default_gateway[2], p->default_gateway[3]);
179 pr_debug("%s:%d: p.dns_primary: %u.%u.%u.%u\n", func, line,
180 p->dns_primary[0], p->dns_primary[1],
181 p->dns_primary[2], p->dns_primary[3]);
182 pr_debug("%s:%d: p.dns_secondary: %u.%u.%u.%u\n", func, line,
183 p->dns_secondary[0], p->dns_secondary[1],
184 p->dns_secondary[2], p->dns_secondary[3]);
185}
186
187static int __init verify_header(const struct os_area_header *header)
188{
189 if (memcmp(header->magic_num, "cell_ext_os_area", 16)) {
190 pr_debug("%s:%d magic_num failed\n", __func__, __LINE__);
191 return -1;
192 }
193
194 if (header->hdr_version < 1) {
195 pr_debug("%s:%d hdr_version failed\n", __func__, __LINE__);
196 return -1;
197 }
198
199 if (header->os_area_offset > header->ldr_area_offset) {
200 pr_debug("%s:%d offsets failed\n", __func__, __LINE__);
201 return -1;
202 }
203
204 return 0;
205}
206
207int __init ps3_os_area_init(void)
208{
209 int result;
210 u64 lpar_addr;
211 unsigned int size;
212 struct os_area_header *header;
213 struct os_area_params *params;
214
215 result = ps3_repository_read_boot_dat_info(&lpar_addr, &size);
216
217 if (result) {
218 pr_debug("%s:%d ps3_repository_read_boot_dat_info failed\n",
219 __func__, __LINE__);
220 return result;
221 }
222
223 header = (struct os_area_header *)__va(lpar_addr);
224 params = (struct os_area_params *)__va(lpar_addr + OS_AREA_SEGMENT_SIZE);
225
226 result = verify_header(header);
227
228 if (result) {
229 pr_debug("%s:%d verify_header failed\n", __func__, __LINE__);
230 dump_header(header);
231 return -EIO;
232 }
233
234 dump_header(header);
235 dump_params(params);
236
237 saved_params.rtc_diff = params->rtc_diff;
238 saved_params.av_multi_out = params->av_multi_out;
239 saved_params.ctrl_button = params->ctrl_button;
240 memcpy(saved_params.static_ip_addr, params->static_ip_addr, 4);
241 memcpy(saved_params.network_mask, params->network_mask, 4);
242 memcpy(saved_params.default_gateway, params->default_gateway, 4);
243 memcpy(saved_params.dns_secondary, params->dns_secondary, 4);
244
245 return result;
246}
247
248/**
249 * ps3_os_area_rtc_diff - Returns the ps3 rtc diff value.
250 *
251 * The ps3 rtc maintains a value that approximates seconds since
252 * 2000-01-01 00:00:00 UTC. Returns the exact number of seconds from 1970 to
253 * 2000 when saved_params.rtc_diff has not been properly set up.
254 */
255
256u64 ps3_os_area_rtc_diff(void)
257{
258 return saved_params.rtc_diff ? saved_params.rtc_diff : 946684800UL;
259}
diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h
new file mode 100644
index 000000000000..23b111bea9d0
--- /dev/null
+++ b/arch/powerpc/platforms/ps3/platform.h
@@ -0,0 +1,68 @@
1/*
2 * PS3 platform declarations.
3 *
4 * Copyright (C) 2006 Sony Computer Entertainment Inc.
5 * Copyright 2006 Sony Corp.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#if !defined(_PS3_PLATFORM_H)
22#define _PS3_PLATFORM_H
23
24#include <linux/rtc.h>
25
26/* htab */
27
28void __init ps3_hpte_init(unsigned long htab_size);
29void __init ps3_map_htab(void);
30
31/* mm */
32
33void __init ps3_mm_init(void);
34void __init ps3_mm_vas_create(unsigned long* htab_size);
35void ps3_mm_vas_destroy(void);
36void ps3_mm_shutdown(void);
37
38/* irq */
39
40void ps3_init_IRQ(void);
41void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq);
42
43/* smp */
44
45void smp_init_ps3(void);
46void ps3_smp_cleanup_cpu(int cpu);
47
48/* time */
49
50void __init ps3_calibrate_decr(void);
51unsigned long __init ps3_get_boot_time(void);
52void ps3_get_rtc_time(struct rtc_time *time);
53int ps3_set_rtc_time(struct rtc_time *time);
54
55/* os area */
56
57int __init ps3_os_area_init(void);
58u64 ps3_os_area_rtc_diff(void);
59
60/* spu */
61
62#if defined(CONFIG_SPU_BASE)
63void ps3_spu_set_platform (void);
64#else
65static inline void ps3_spu_set_platform (void) {}
66#endif
67
68#endif
diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c
new file mode 100644
index 000000000000..273a0d621bdd
--- /dev/null
+++ b/arch/powerpc/platforms/ps3/repository.c
@@ -0,0 +1,840 @@
1/*
2 * PS3 repository routines.
3 *
4 * Copyright (C) 2006 Sony Computer Entertainment Inc.
5 * Copyright 2006 Sony Corp.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <asm/ps3.h>
22#include <asm/lv1call.h>
23
24enum ps3_vendor_id {
25 PS3_VENDOR_ID_NONE = 0,
26 PS3_VENDOR_ID_SONY = 0x8000000000000000UL,
27};
28
29enum ps3_lpar_id {
30 PS3_LPAR_ID_CURRENT = 0,
31 PS3_LPAR_ID_PME = 1,
32};
33
34#define dump_field(_a, _b) _dump_field(_a, _b, __func__, __LINE__)
35static void _dump_field(const char *hdr, u64 n, const char* func, int line)
36{
37#if defined(DEBUG)
38 char s[16];
39 const char *const in = (const char *)&n;
40 unsigned int i;
41
42 for (i = 0; i < 8; i++)
43 s[i] = (in[i] <= 126 && in[i] >= 32) ? in[i] : '.';
44 s[i] = 0;
45
46 pr_debug("%s:%d: %s%016lx : %s\n", func, line, hdr, n, s);
47#endif
48}
49
50#define dump_node_name(_a, _b, _c, _d, _e) \
51 _dump_node_name(_a, _b, _c, _d, _e, __func__, __LINE__)
52static void _dump_node_name (unsigned int lpar_id, u64 n1, u64 n2, u64 n3,
53 u64 n4, const char* func, int line)
54{
55 pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id);
56 _dump_field("n1: ", n1, func, line);
57 _dump_field("n2: ", n2, func, line);
58 _dump_field("n3: ", n3, func, line);
59 _dump_field("n4: ", n4, func, line);
60}
61
62#define dump_node(_a, _b, _c, _d, _e, _f, _g) \
63 _dump_node(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__)
64static void _dump_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
65 u64 v1, u64 v2, const char* func, int line)
66{
67 pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id);
68 _dump_field("n1: ", n1, func, line);
69 _dump_field("n2: ", n2, func, line);
70 _dump_field("n3: ", n3, func, line);
71 _dump_field("n4: ", n4, func, line);
72 pr_debug("%s:%d: v1: %016lx\n", func, line, v1);
73 pr_debug("%s:%d: v2: %016lx\n", func, line, v2);
74}
75
76/**
77 * make_first_field - Make the first field of a repository node name.
78 * @text: Text portion of the field.
79 * @index: Numeric index portion of the field. Use zero for 'don't care'.
80 *
81 * This routine sets the vendor id to zero (non-vendor specific).
82 * Returns field value.
83 */
84
85static u64 make_first_field(const char *text, u64 index)
86{
87 u64 n;
88
89 strncpy((char *)&n, text, 8);
90 return PS3_VENDOR_ID_NONE + (n >> 32) + index;
91}
92
93/**
94 * make_field - Make subsequent fields of a repository node name.
95 * @text: Text portion of the field. Use "" for 'don't care'.
96 * @index: Numeric index portion of the field. Use zero for 'don't care'.
97 *
98 * Returns field value.
99 */
100
101static u64 make_field(const char *text, u64 index)
102{
103 u64 n;
104
105 strncpy((char *)&n, text, 8);
106 return n + index;
107}
108
109/**
110 * read_node - Read a repository node from raw fields.
111 * @n1: First field of node name.
112 * @n2: Second field of node name. Use zero for 'don't care'.
113 * @n3: Third field of node name. Use zero for 'don't care'.
114 * @n4: Fourth field of node name. Use zero for 'don't care'.
115 * @v1: First repository value (high word).
116 * @v2: Second repository value (low word). Optional parameter, use zero
117 * for 'don't care'.
118 */
119
120static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
121 u64 *_v1, u64 *_v2)
122{
123 int result;
124 u64 v1;
125 u64 v2;
126
127 if (lpar_id == PS3_LPAR_ID_CURRENT) {
128 u64 id;
129 lv1_get_logical_partition_id(&id);
130 lpar_id = id;
131 }
132
133 result = lv1_get_repository_node_value(lpar_id, n1, n2, n3, n4, &v1,
134 &v2);
135
136 if (result) {
137 pr_debug("%s:%d: lv1_get_repository_node_value failed: %s\n",
138 __func__, __LINE__, ps3_result(result));
139 dump_node_name(lpar_id, n1, n2, n3, n4);
140 return result;
141 }
142
143 dump_node(lpar_id, n1, n2, n3, n4, v1, v2);
144
145 if (_v1)
146 *_v1 = v1;
147 if (_v2)
148 *_v2 = v2;
149
150 if (v1 && !_v1)
151 pr_debug("%s:%d: warning: discarding non-zero v1: %016lx\n",
152 __func__, __LINE__, v1);
153 if (v2 && !_v2)
154 pr_debug("%s:%d: warning: discarding non-zero v2: %016lx\n",
155 __func__, __LINE__, v2);
156
157 return result;
158}
159
160int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
161 u64 *value)
162{
163 return read_node(PS3_LPAR_ID_PME,
164 make_first_field("bus", bus_index),
165 make_field(bus_str, 0),
166 0, 0,
167 value, 0);
168}
169
170int ps3_repository_read_bus_id(unsigned int bus_index, unsigned int *bus_id)
171{
172 int result;
173 u64 v1;
174 u64 v2; /* unused */
175
176 result = read_node(PS3_LPAR_ID_PME,
177 make_first_field("bus", bus_index),
178 make_field("id", 0),
179 0, 0,
180 &v1, &v2);
181 *bus_id = v1;
182 return result;
183}
184
185int ps3_repository_read_bus_type(unsigned int bus_index,
186 enum ps3_bus_type *bus_type)
187{
188 int result;
189 u64 v1;
190
191 result = read_node(PS3_LPAR_ID_PME,
192 make_first_field("bus", bus_index),
193 make_field("type", 0),
194 0, 0,
195 &v1, 0);
196 *bus_type = v1;
197 return result;
198}
199
200int ps3_repository_read_bus_num_dev(unsigned int bus_index,
201 unsigned int *num_dev)
202{
203 int result;
204 u64 v1;
205
206 result = read_node(PS3_LPAR_ID_PME,
207 make_first_field("bus", bus_index),
208 make_field("num_dev", 0),
209 0, 0,
210 &v1, 0);
211 *num_dev = v1;
212 return result;
213}
214
215int ps3_repository_read_dev_str(unsigned int bus_index,
216 unsigned int dev_index, const char *dev_str, u64 *value)
217{
218 return read_node(PS3_LPAR_ID_PME,
219 make_first_field("bus", bus_index),
220 make_field("dev", dev_index),
221 make_field(dev_str, 0),
222 0,
223 value, 0);
224}
225
226int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index,
227 unsigned int *dev_id)
228{
229 int result;
230 u64 v1;
231
232 result = read_node(PS3_LPAR_ID_PME,
233 make_first_field("bus", bus_index),
234 make_field("dev", dev_index),
235 make_field("id", 0),
236 0,
237 &v1, 0);
238 *dev_id = v1;
239 return result;
240}
241
242int ps3_repository_read_dev_type(unsigned int bus_index,
243 unsigned int dev_index, enum ps3_dev_type *dev_type)
244{
245 int result;
246 u64 v1;
247
248 result = read_node(PS3_LPAR_ID_PME,
249 make_first_field("bus", bus_index),
250 make_field("dev", dev_index),
251 make_field("type", 0),
252 0,
253 &v1, 0);
254 *dev_type = v1;
255 return result;
256}
257
258int ps3_repository_read_dev_intr(unsigned int bus_index,
259 unsigned int dev_index, unsigned int intr_index,
260 unsigned int *intr_type, unsigned int* interrupt_id)
261{
262 int result;
263 u64 v1;
264 u64 v2;
265
266 result = read_node(PS3_LPAR_ID_PME,
267 make_first_field("bus", bus_index),
268 make_field("dev", dev_index),
269 make_field("intr", intr_index),
270 0,
271 &v1, &v2);
272 *intr_type = v1;
273 *interrupt_id = v2;
274 return result;
275}
276
277int ps3_repository_read_dev_reg_type(unsigned int bus_index,
278 unsigned int dev_index, unsigned int reg_index, unsigned int *reg_type)
279{
280 int result;
281 u64 v1;
282
283 result = read_node(PS3_LPAR_ID_PME,
284 make_first_field("bus", bus_index),
285 make_field("dev", dev_index),
286 make_field("reg", reg_index),
287 make_field("type", 0),
288 &v1, 0);
289 *reg_type = v1;
290 return result;
291}
292
293int ps3_repository_read_dev_reg_addr(unsigned int bus_index,
294 unsigned int dev_index, unsigned int reg_index, u64 *bus_addr, u64 *len)
295{
296 return read_node(PS3_LPAR_ID_PME,
297 make_first_field("bus", bus_index),
298 make_field("dev", dev_index),
299 make_field("reg", reg_index),
300 make_field("data", 0),
301 bus_addr, len);
302}
303
304int ps3_repository_read_dev_reg(unsigned int bus_index,
305 unsigned int dev_index, unsigned int reg_index, unsigned int *reg_type,
306 u64 *bus_addr, u64 *len)
307{
308 int result = ps3_repository_read_dev_reg_type(bus_index, dev_index,
309 reg_index, reg_type);
310 return result ? result
311 : ps3_repository_read_dev_reg_addr(bus_index, dev_index,
312 reg_index, bus_addr, len);
313}
314
315#if defined(DEBUG)
316int ps3_repository_dump_resource_info(unsigned int bus_index,
317 unsigned int dev_index)
318{
319 int result = 0;
320 unsigned int res_index;
321
322 pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
323 bus_index, dev_index);
324
325 for (res_index = 0; res_index < 10; res_index++) {
326 enum ps3_interrupt_type intr_type;
327 unsigned int interrupt_id;
328
329 result = ps3_repository_read_dev_intr(bus_index, dev_index,
330 res_index, &intr_type, &interrupt_id);
331
332 if (result) {
333 if (result != LV1_NO_ENTRY)
334 pr_debug("%s:%d ps3_repository_read_dev_intr"
335 " (%u:%u) failed\n", __func__, __LINE__,
336 bus_index, dev_index);
337 break;
338 }
339
340 pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n",
341 __func__, __LINE__, bus_index, dev_index, intr_type,
342 interrupt_id);
343 }
344
345 for (res_index = 0; res_index < 10; res_index++) {
346 enum ps3_region_type reg_type;
347 u64 bus_addr;
348 u64 len;
349
350 result = ps3_repository_read_dev_reg(bus_index, dev_index,
351 res_index, &reg_type, &bus_addr, &len);
352
353 if (result) {
354 if (result != LV1_NO_ENTRY)
355 pr_debug("%s:%d ps3_repository_read_dev_reg"
356 " (%u:%u) failed\n", __func__, __LINE__,
357 bus_index, dev_index);
358 break;
359 }
360
361 pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n",
362 __func__, __LINE__, bus_index, dev_index, reg_type,
363 bus_addr, len);
364 }
365
366 pr_debug(" <- %s:%d\n", __func__, __LINE__);
367 return result;
368}
369
370static int dump_device_info(unsigned int bus_index, unsigned int num_dev)
371{
372 int result = 0;
373 unsigned int dev_index;
374
375 pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, bus_index);
376
377 for (dev_index = 0; dev_index < num_dev; dev_index++) {
378 enum ps3_dev_type dev_type;
379 unsigned int dev_id;
380
381 result = ps3_repository_read_dev_type(bus_index, dev_index,
382 &dev_type);
383
384 if (result) {
385 pr_debug("%s:%d ps3_repository_read_dev_type"
386 " (%u:%u) failed\n", __func__, __LINE__,
387 bus_index, dev_index);
388 break;
389 }
390
391 result = ps3_repository_read_dev_id(bus_index, dev_index,
392 &dev_id);
393
394 if (result) {
395 pr_debug("%s:%d ps3_repository_read_dev_id"
396 " (%u:%u) failed\n", __func__, __LINE__,
397 bus_index, dev_index);
398 continue;
399 }
400
401 pr_debug("%s:%d (%u:%u): dev_type %u, dev_id %u\n", __func__,
402 __LINE__, bus_index, dev_index, dev_type, dev_id);
403
404 ps3_repository_dump_resource_info(bus_index, dev_index);
405 }
406
407 pr_debug(" <- %s:%d\n", __func__, __LINE__);
408 return result;
409}
410
411int ps3_repository_dump_bus_info(void)
412{
413 int result = 0;
414 unsigned int bus_index;
415
416 pr_debug(" -> %s:%d\n", __func__, __LINE__);
417
418 for (bus_index = 0; bus_index < 10; bus_index++) {
419 enum ps3_bus_type bus_type;
420 unsigned int bus_id;
421 unsigned int num_dev;
422
423 result = ps3_repository_read_bus_type(bus_index, &bus_type);
424
425 if (result) {
426 pr_debug("%s:%d read_bus_type(%u) failed\n",
427 __func__, __LINE__, bus_index);
428 break;
429 }
430
431 result = ps3_repository_read_bus_id(bus_index, &bus_id);
432
433 if (result) {
434 pr_debug("%s:%d read_bus_id(%u) failed\n",
435 __func__, __LINE__, bus_index);
436 continue;
437 }
438
439 if (bus_index != bus_id)
440 pr_debug("%s:%d bus_index != bus_id\n",
441 __func__, __LINE__);
442
443 result = ps3_repository_read_bus_num_dev(bus_index, &num_dev);
444
445 if (result) {
446 pr_debug("%s:%d read_bus_num_dev(%u) failed\n",
447 __func__, __LINE__, bus_index);
448 continue;
449 }
450
451 pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n",
452 __func__, __LINE__, bus_index, bus_type, bus_id,
453 num_dev);
454
455 dump_device_info(bus_index, num_dev);
456 }
457
458 pr_debug(" <- %s:%d\n", __func__, __LINE__);
459 return result;
460}
461#endif /* defined(DEBUG) */
462
463static int find_device(unsigned int bus_index, unsigned int num_dev,
464 unsigned int start_dev_index, enum ps3_dev_type dev_type,
465 struct ps3_repository_device *dev)
466{
467 int result = 0;
468 unsigned int dev_index;
469
470 pr_debug("%s:%d: find dev_type %u\n", __func__, __LINE__, dev_type);
471
472 dev->dev_index = UINT_MAX;
473
474 for (dev_index = start_dev_index; dev_index < num_dev; dev_index++) {
475 enum ps3_dev_type x;
476
477 result = ps3_repository_read_dev_type(bus_index, dev_index,
478 &x);
479
480 if (result) {
481 pr_debug("%s:%d read_dev_type failed\n",
482 __func__, __LINE__);
483 return result;
484 }
485
486 if (x == dev_type)
487 break;
488 }
489
490 BUG_ON(dev_index == num_dev);
491
492 pr_debug("%s:%d: found dev_type %u at dev_index %u\n",
493 __func__, __LINE__, dev_type, dev_index);
494
495 result = ps3_repository_read_dev_id(bus_index, dev_index,
496 &dev->did.dev_id);
497
498 if (result) {
499 pr_debug("%s:%d read_dev_id failed\n",
500 __func__, __LINE__);
501 return result;
502 }
503
504 dev->dev_index = dev_index;
505
506 pr_debug("%s:%d found: dev_id %u\n", __func__, __LINE__,
507 dev->did.dev_id);
508
509 return result;
510}
511
512int ps3_repository_find_device (enum ps3_bus_type bus_type,
513 enum ps3_dev_type dev_type,
514 const struct ps3_repository_device *start_dev,
515 struct ps3_repository_device *dev)
516{
517 int result = 0;
518 unsigned int bus_index;
519 unsigned int num_dev;
520
521 pr_debug("%s:%d: find bus_type %u, dev_type %u\n", __func__, __LINE__,
522 bus_type, dev_type);
523
524 dev->bus_index = UINT_MAX;
525
526 for (bus_index = start_dev ? start_dev->bus_index : 0; bus_index < 10;
527 bus_index++) {
528 enum ps3_bus_type x;
529
530 result = ps3_repository_read_bus_type(bus_index, &x);
531
532 if (result) {
533 pr_debug("%s:%d read_bus_type failed\n",
534 __func__, __LINE__);
535 return result;
536 }
537 if (x == bus_type)
538 break;
539 }
540
541 BUG_ON(bus_index == 10);
542
543 pr_debug("%s:%d: found bus_type %u at bus_index %u\n",
544 __func__, __LINE__, bus_type, bus_index);
545
546 result = ps3_repository_read_bus_num_dev(bus_index, &num_dev);
547
548 if (result) {
549 pr_debug("%s:%d read_bus_num_dev failed\n",
550 __func__, __LINE__);
551 return result;
552 }
553
554 result = find_device(bus_index, num_dev, start_dev
555 ? start_dev->dev_index + 1 : 0, dev_type, dev);
556
557 if (result) {
558 pr_debug("%s:%d get_did failed\n", __func__, __LINE__);
559 return result;
560 }
561
562 result = ps3_repository_read_bus_id(bus_index, &dev->did.bus_id);
563
564 if (result) {
565 pr_debug("%s:%d read_bus_id failed\n",
566 __func__, __LINE__);
567 return result;
568 }
569
570 dev->bus_index = bus_index;
571
572 pr_debug("%s:%d found: bus_id %u, dev_id %u\n",
573 __func__, __LINE__, dev->did.bus_id, dev->did.dev_id);
574
575 return result;
576}
577
578int ps3_repository_find_interrupt(const struct ps3_repository_device *dev,
579 enum ps3_interrupt_type intr_type, unsigned int *interrupt_id)
580{
581 int result = 0;
582 unsigned int res_index;
583
584 pr_debug("%s:%d: find intr_type %u\n", __func__, __LINE__, intr_type);
585
586 *interrupt_id = UINT_MAX;
587
588 for (res_index = 0; res_index < 10; res_index++) {
589 enum ps3_interrupt_type t;
590 unsigned int id;
591
592 result = ps3_repository_read_dev_intr(dev->bus_index,
593 dev->dev_index, res_index, &t, &id);
594
595 if (result) {
596 pr_debug("%s:%d read_dev_intr failed\n",
597 __func__, __LINE__);
598 return result;
599 }
600
601 if (t == intr_type) {
602 *interrupt_id = id;
603 break;
604 }
605 }
606
607 BUG_ON(res_index == 10);
608
609 pr_debug("%s:%d: found intr_type %u at res_index %u\n",
610 __func__, __LINE__, intr_type, res_index);
611
612 return result;
613}
614
615int ps3_repository_find_region(const struct ps3_repository_device *dev,
616 enum ps3_region_type reg_type, u64 *bus_addr, u64 *len)
617{
618 int result = 0;
619 unsigned int res_index;
620
621 pr_debug("%s:%d: find reg_type %u\n", __func__, __LINE__, reg_type);
622
623 *bus_addr = *len = 0;
624
625 for (res_index = 0; res_index < 10; res_index++) {
626 enum ps3_region_type t;
627 u64 a;
628 u64 l;
629
630 result = ps3_repository_read_dev_reg(dev->bus_index,
631 dev->dev_index, res_index, &t, &a, &l);
632
633 if (result) {
634 pr_debug("%s:%d read_dev_reg failed\n",
635 __func__, __LINE__);
636 return result;
637 }
638
639 if (t == reg_type) {
640 *bus_addr = a;
641 *len = l;
642 break;
643 }
644 }
645
646 BUG_ON(res_index == 10);
647
648 pr_debug("%s:%d: found reg_type %u at res_index %u\n",
649 __func__, __LINE__, reg_type, res_index);
650
651 return result;
652}
653
654int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size)
655{
656 return read_node(PS3_LPAR_ID_CURRENT,
657 make_first_field("bi", 0),
658 make_field("pu", 0),
659 ppe_id,
660 make_field("rm_size", 0),
661 rm_size, 0);
662}
663
664int ps3_repository_read_region_total(u64 *region_total)
665{
666 return read_node(PS3_LPAR_ID_CURRENT,
667 make_first_field("bi", 0),
668 make_field("rgntotal", 0),
669 0, 0,
670 region_total, 0);
671}
672
673/**
674 * ps3_repository_read_mm_info - Read mm info for single pu system.
675 * @rm_base: Real mode memory base address.
676 * @rm_size: Real mode memory size.
677 * @region_total: Maximum memory region size.
678 */
679
680int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total)
681{
682 int result;
683 u64 ppe_id;
684
685 lv1_get_logical_ppe_id(&ppe_id);
686 *rm_base = 0;
687 result = ps3_repository_read_rm_size(ppe_id, rm_size);
688 return result ? result
689 : ps3_repository_read_region_total(region_total);
690}
691
692/**
693 * ps3_repository_read_num_spu_reserved - Number of physical spus reserved.
694 * @num_spu: Number of physical spus.
695 */
696
697int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved)
698{
699 int result;
700 u64 v1;
701
702 result = read_node(PS3_LPAR_ID_CURRENT,
703 make_first_field("bi", 0),
704 make_field("spun", 0),
705 0, 0,
706 &v1, 0);
707 *num_spu_reserved = v1;
708 return result;
709}
710
711/**
712 * ps3_repository_read_num_spu_resource_id - Number of spu resource reservations.
713 * @num_resource_id: Number of spu resource ids.
714 */
715
716int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id)
717{
718 int result;
719 u64 v1;
720
721 result = read_node(PS3_LPAR_ID_CURRENT,
722 make_first_field("bi", 0),
723 make_field("spursvn", 0),
724 0, 0,
725 &v1, 0);
726 *num_resource_id = v1;
727 return result;
728}
729
730/**
731 * ps3_repository_read_spu_resource_id - spu resource reservation id value.
732 * @res_index: Resource reservation index.
733 * @resource_type: Resource reservation type.
734 * @resource_id: Resource reservation id.
735 */
736
737int ps3_repository_read_spu_resource_id(unsigned int res_index,
738 enum ps3_spu_resource_type* resource_type, unsigned int *resource_id)
739{
740 int result;
741 u64 v1;
742 u64 v2;
743
744 result = read_node(PS3_LPAR_ID_CURRENT,
745 make_first_field("bi", 0),
746 make_field("spursv", 0),
747 res_index,
748 0,
749 &v1, &v2);
750 *resource_type = v1;
751 *resource_id = v2;
752 return result;
753}
754
755int ps3_repository_read_boot_dat_address(u64 *address)
756{
757 return read_node(PS3_LPAR_ID_CURRENT,
758 make_first_field("bi", 0),
759 make_field("boot_dat", 0),
760 make_field("address", 0),
761 0,
762 address, 0);
763}
764
765int ps3_repository_read_boot_dat_size(unsigned int *size)
766{
767 int result;
768 u64 v1;
769
770 result = read_node(PS3_LPAR_ID_CURRENT,
771 make_first_field("bi", 0),
772 make_field("boot_dat", 0),
773 make_field("size", 0),
774 0,
775 &v1, 0);
776 *size = v1;
777 return result;
778}
779
780/**
781 * ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area.
782 * address: lpar address of cell_ext_os_area
783 * @size: size of cell_ext_os_area
784 */
785
786int ps3_repository_read_boot_dat_info(u64 *lpar_addr, unsigned int *size)
787{
788 int result;
789
790 *size = 0;
791 result = ps3_repository_read_boot_dat_address(lpar_addr);
792 return result ? result
793 : ps3_repository_read_boot_dat_size(size);
794}
795
796int ps3_repository_read_num_be(unsigned int *num_be)
797{
798 int result;
799 u64 v1;
800
801 result = read_node(PS3_LPAR_ID_PME,
802 make_first_field("ben", 0),
803 0,
804 0,
805 0,
806 &v1, 0);
807 *num_be = v1;
808 return result;
809}
810
811int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id)
812{
813 return read_node(PS3_LPAR_ID_PME,
814 make_first_field("be", be_index),
815 0,
816 0,
817 0,
818 node_id, 0);
819}
820
821int ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq)
822{
823 return read_node(PS3_LPAR_ID_PME,
824 make_first_field("be", 0),
825 node_id,
826 make_field("clock", 0),
827 0,
828 tb_freq, 0);
829}
830
831int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq)
832{
833 int result;
834 u64 node_id;
835
836 *tb_freq = 0;
837 result = ps3_repository_read_be_node_id(0, &node_id);
838 return result ? result
839 : ps3_repository_read_tb_freq(node_id, tb_freq);
840}
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
new file mode 100644
index 000000000000..d8b5cadbe80e
--- /dev/null
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -0,0 +1,173 @@
1/*
2 * PS3 platform setup routines.
3 *
4 * Copyright (C) 2006 Sony Computer Entertainment Inc.
5 * Copyright 2006 Sony Corp.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/kernel.h>
22#include <linux/delay.h>
23#include <linux/fs.h>
24#include <linux/root_dev.h>
25#include <linux/console.h>
26#include <linux/kexec.h>
27
28#include <asm/machdep.h>
29#include <asm/firmware.h>
30#include <asm/time.h>
31#include <asm/iommu.h>
32#include <asm/udbg.h>
33#include <asm/prom.h>
34#include <asm/lv1call.h>
35
36#include "platform.h"
37
38#if defined(DEBUG)
39#define DBG(fmt...) udbg_printf(fmt)
40#else
41#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
42#endif
43
44static void ps3_show_cpuinfo(struct seq_file *m)
45{
46 seq_printf(m, "machine\t\t: %s\n", ppc_md.name);
47}
48
49static void ps3_power_save(void)
50{
51 /*
52 * lv1_pause() puts the PPE thread into inactive state until an
53 * irq on an unmasked plug exists. MSR[EE] has no effect.
54 * flags: 0 = wake on DEC interrupt, 1 = ignore DEC interrupt.
55 */
56
57 lv1_pause(0);
58}
59
60static void ps3_panic(char *str)
61{
62 DBG("%s:%d %s\n", __func__, __LINE__, str);
63
64#ifdef CONFIG_SMP
65 smp_send_stop();
66#endif
67 printk("\n");
68 printk(" System does not reboot automatically.\n");
69 printk(" Please press POWER button.\n");
70 printk("\n");
71
72 for (;;) ;
73}
74
75static void __init ps3_setup_arch(void)
76{
77 DBG(" -> %s:%d\n", __func__, __LINE__);
78
79 ps3_spu_set_platform();
80 ps3_map_htab();
81
82#ifdef CONFIG_SMP
83 smp_init_ps3();
84#endif
85
86#ifdef CONFIG_DUMMY_CONSOLE
87 conswitchp = &dummy_con;
88#endif
89
90 ppc_md.power_save = ps3_power_save;
91
92 DBG(" <- %s:%d\n", __func__, __LINE__);
93}
94
95static void __init ps3_progress(char *s, unsigned short hex)
96{
97 printk("*** %04x : %s\n", hex, s ? s : "");
98}
99
100static int __init ps3_probe(void)
101{
102 unsigned long htab_size;
103 unsigned long dt_root;
104
105 DBG(" -> %s:%d\n", __func__, __LINE__);
106
107 dt_root = of_get_flat_dt_root();
108 if (!of_flat_dt_is_compatible(dt_root, "PS3"))
109 return 0;
110
111 powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE;
112
113 ps3_os_area_init();
114 ps3_mm_init();
115 ps3_mm_vas_create(&htab_size);
116 ps3_hpte_init(htab_size);
117
118 DBG(" <- %s:%d\n", __func__, __LINE__);
119 return 1;
120}
121
122#if defined(CONFIG_KEXEC)
123static void ps3_kexec_cpu_down(int crash_shutdown, int secondary)
124{
125 DBG(" -> %s:%d\n", __func__, __LINE__);
126
127 if (secondary) {
128 int cpu;
129 for_each_online_cpu(cpu)
130 if (cpu)
131 ps3_smp_cleanup_cpu(cpu);
132 } else
133 ps3_smp_cleanup_cpu(0);
134
135 DBG(" <- %s:%d\n", __func__, __LINE__);
136}
137
138static void ps3_machine_kexec(struct kimage *image)
139{
140 unsigned long ppe_id;
141
142 DBG(" -> %s:%d\n", __func__, __LINE__);
143
144 lv1_get_logical_ppe_id(&ppe_id);
145 lv1_configure_irq_state_bitmap(ppe_id, 0, 0);
146 ps3_mm_shutdown();
147 ps3_mm_vas_destroy();
148
149 default_machine_kexec(image);
150
151 DBG(" <- %s:%d\n", __func__, __LINE__);
152}
153#endif
154
155define_machine(ps3) {
156 .name = "PS3",
157 .probe = ps3_probe,
158 .setup_arch = ps3_setup_arch,
159 .show_cpuinfo = ps3_show_cpuinfo,
160 .init_IRQ = ps3_init_IRQ,
161 .panic = ps3_panic,
162 .get_boot_time = ps3_get_boot_time,
163 .set_rtc_time = ps3_set_rtc_time,
164 .get_rtc_time = ps3_get_rtc_time,
165 .calibrate_decr = ps3_calibrate_decr,
166 .progress = ps3_progress,
167#if defined(CONFIG_KEXEC)
168 .kexec_cpu_down = ps3_kexec_cpu_down,
169 .machine_kexec = ps3_machine_kexec,
170 .machine_kexec_prepare = default_machine_kexec_prepare,
171 .machine_crash_shutdown = default_machine_crash_shutdown,
172#endif
173};
diff --git a/arch/powerpc/platforms/ps3/smp.c b/arch/powerpc/platforms/ps3/smp.c
new file mode 100644
index 000000000000..11d2080607ed
--- /dev/null
+++ b/arch/powerpc/platforms/ps3/smp.c
@@ -0,0 +1,158 @@
1/*
2 * PS3 SMP routines.
3 *
4 * Copyright (C) 2006 Sony Computer Entertainment Inc.
5 * Copyright 2006 Sony Corp.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/kernel.h>
22#include <linux/smp.h>
23
24#include <asm/machdep.h>
25#include <asm/udbg.h>
26#include <asm/ps3.h>
27
28#include "platform.h"
29
30#if defined(DEBUG)
31#define DBG(fmt...) udbg_printf(fmt)
32#else
33#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
34#endif
35
36static irqreturn_t ipi_function_handler(int irq, void *msg)
37{
38 smp_message_recv((int)(long)msg);
39 return IRQ_HANDLED;
40}
41
42/**
43 * virqs - a per cpu array of virqs for ipi use
44 */
45
46#define MSG_COUNT 4
47static DEFINE_PER_CPU(unsigned int, virqs[MSG_COUNT]);
48
49static const char *names[MSG_COUNT] = {
50 "ipi call",
51 "ipi reschedule",
52 "ipi migrate",
53 "ipi debug brk"
54};
55
56static void do_message_pass(int target, int msg)
57{
58 int result;
59 unsigned int virq;
60
61 if (msg >= MSG_COUNT) {
62 DBG("%s:%d: bad msg: %d\n", __func__, __LINE__, msg);
63 return;
64 }
65
66 virq = per_cpu(virqs, target)[msg];
67 result = ps3_send_event_locally(virq);
68
69 if (result)
70 DBG("%s:%d: ps3_send_event_locally(%d, %d) failed"
71 " (%d)\n", __func__, __LINE__, target, msg, result);
72}
73
74static void ps3_smp_message_pass(int target, int msg)
75{
76 int cpu;
77
78 if (target < NR_CPUS)
79 do_message_pass(target, msg);
80 else if (target == MSG_ALL_BUT_SELF) {
81 for_each_online_cpu(cpu)
82 if (cpu != smp_processor_id())
83 do_message_pass(cpu, msg);
84 } else {
85 for_each_online_cpu(cpu)
86 do_message_pass(cpu, msg);
87 }
88}
89
90static int ps3_smp_probe(void)
91{
92 return 2;
93}
94
95static void __init ps3_smp_setup_cpu(int cpu)
96{
97 int result;
98 unsigned int *virqs = per_cpu(virqs, cpu);
99 int i;
100
101 DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
102
103 /*
104 * Check assumptions on virqs[] indexing. If this
105 * check fails, then a different mapping of PPC_MSG_
106 * to index needs to be setup.
107 */
108
109 BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION != 0);
110 BUILD_BUG_ON(PPC_MSG_RESCHEDULE != 1);
111 BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3);
112
113 for (i = 0; i < MSG_COUNT; i++) {
114 result = ps3_alloc_event_irq(&virqs[i]);
115
116 if (result)
117 continue;
118
119 DBG("%s:%d: (%d, %d) => virq %u\n",
120 __func__, __LINE__, cpu, i, virqs[i]);
121
122
123 request_irq(virqs[i], ipi_function_handler, IRQF_DISABLED,
124 names[i], (void*)(long)i);
125 }
126
127 ps3_register_ipi_debug_brk(cpu, virqs[PPC_MSG_DEBUGGER_BREAK]);
128
129 DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu);
130}
131
132void ps3_smp_cleanup_cpu(int cpu)
133{
134 unsigned int *virqs = per_cpu(virqs, cpu);
135 int i;
136
137 DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
138 for (i = 0; i < MSG_COUNT; i++) {
139 ps3_free_event_irq(virqs[i]);
140 free_irq(virqs[i], (void*)(long)i);
141 virqs[i] = NO_IRQ;
142 }
143 DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu);
144}
145
146static struct smp_ops_t ps3_smp_ops = {
147 .probe = ps3_smp_probe,
148 .message_pass = ps3_smp_message_pass,
149 .kick_cpu = smp_generic_kick_cpu,
150 .setup_cpu = ps3_smp_setup_cpu,
151};
152
153void smp_init_ps3(void)
154{
155 DBG(" -> %s\n", __func__);
156 smp_ops = &ps3_smp_ops;
157 DBG(" <- %s\n", __func__);
158}
diff --git a/arch/powerpc/platforms/ps3/spu.c b/arch/powerpc/platforms/ps3/spu.c
new file mode 100644
index 000000000000..644532c3b7c4
--- /dev/null
+++ b/arch/powerpc/platforms/ps3/spu.c
@@ -0,0 +1,613 @@
1/*
2 * PS3 Platform spu routines.
3 *
4 * Copyright (C) 2006 Sony Computer Entertainment Inc.
5 * Copyright 2006 Sony Corp.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/kernel.h>
22#include <linux/init.h>
23#include <linux/mmzone.h>
24#include <linux/io.h>
25#include <linux/mm.h>
26
27#include <asm/spu.h>
28#include <asm/spu_priv1.h>
29#include <asm/ps3.h>
30#include <asm/lv1call.h>
31
32/* spu_management_ops */
33
34/**
35 * enum spe_type - Type of spe to create.
36 * @spe_type_logical: Standard logical spe.
37 *
38 * For use with lv1_construct_logical_spe(). The current HV does not support
39 * any types other than those listed.
40 */
41
42enum spe_type {
43 SPE_TYPE_LOGICAL = 0,
44};
45
46/**
47 * struct spe_shadow - logical spe shadow register area.
48 *
49 * Read-only shadow of spe registers.
50 */
51
52struct spe_shadow {
53 u8 padding_0000[0x0140];
54 u64 int_status_class0_RW; /* 0x0140 */
55 u64 int_status_class1_RW; /* 0x0148 */
56 u64 int_status_class2_RW; /* 0x0150 */
57 u8 padding_0158[0x0610-0x0158];
58 u64 mfc_dsisr_RW; /* 0x0610 */
59 u8 padding_0618[0x0620-0x0618];
60 u64 mfc_dar_RW; /* 0x0620 */
61 u8 padding_0628[0x0800-0x0628];
62 u64 mfc_dsipr_R; /* 0x0800 */
63 u8 padding_0808[0x0810-0x0808];
64 u64 mfc_lscrr_R; /* 0x0810 */
65 u8 padding_0818[0x0c00-0x0818];
66 u64 mfc_cer_R; /* 0x0c00 */
67 u8 padding_0c08[0x0f00-0x0c08];
68 u64 spe_execution_status; /* 0x0f00 */
69 u8 padding_0f08[0x1000-0x0f08];
70} __attribute__ ((packed));
71
72
73/**
74 * enum spe_ex_state - Logical spe execution state.
75 * @spe_ex_state_unexecutable: Uninitialized.
76 * @spe_ex_state_executable: Enabled, not ready.
77 * @spe_ex_state_executed: Ready for use.
78 *
79 * The execution state (status) of the logical spe as reported in
80 * struct spe_shadow:spe_execution_status.
81 */
82
83enum spe_ex_state {
84 SPE_EX_STATE_UNEXECUTABLE = 0,
85 SPE_EX_STATE_EXECUTABLE = 2,
86 SPE_EX_STATE_EXECUTED = 3,
87};
88
89/**
90 * struct priv1_cache - Cached values of priv1 registers.
91 * @masks[]: Array of cached spe interrupt masks, indexed by class.
92 * @sr1: Cached mfc_sr1 register.
93 * @tclass_id: Cached mfc_tclass_id register.
94 */
95
96struct priv1_cache {
97 u64 masks[3];
98 u64 sr1;
99 u64 tclass_id;
100};
101
102/**
103 * struct spu_pdata - Platform state variables.
104 * @spe_id: HV spe id returned by lv1_construct_logical_spe().
105 * @resource_id: HV spe resource id returned by
106 * ps3_repository_read_spe_resource_id().
107 * @priv2_addr: lpar address of spe priv2 area returned by
108 * lv1_construct_logical_spe().
109 * @shadow_addr: lpar address of spe register shadow area returned by
110 * lv1_construct_logical_spe().
111 * @shadow: Virtual (ioremap) address of spe register shadow area.
112 * @cache: Cached values of priv1 registers.
113 */
114
115struct spu_pdata {
116 u64 spe_id;
117 u64 resource_id;
118 u64 priv2_addr;
119 u64 shadow_addr;
120 struct spe_shadow __iomem *shadow;
121 struct priv1_cache cache;
122};
123
124static struct spu_pdata *spu_pdata(struct spu *spu)
125{
126 return spu->pdata;
127}
128
129#define dump_areas(_a, _b, _c, _d, _e) \
130 _dump_areas(_a, _b, _c, _d, _e, __func__, __LINE__)
131static void _dump_areas(unsigned int spe_id, unsigned long priv2,
132 unsigned long problem, unsigned long ls, unsigned long shadow,
133 const char* func, int line)
134{
135 pr_debug("%s:%d: spe_id: %xh (%u)\n", func, line, spe_id, spe_id);
136 pr_debug("%s:%d: priv2: %lxh\n", func, line, priv2);
137 pr_debug("%s:%d: problem: %lxh\n", func, line, problem);
138 pr_debug("%s:%d: ls: %lxh\n", func, line, ls);
139 pr_debug("%s:%d: shadow: %lxh\n", func, line, shadow);
140}
141
142static unsigned long get_vas_id(void)
143{
144 unsigned long id;
145
146 lv1_get_logical_ppe_id(&id);
147 lv1_get_virtual_address_space_id_of_ppe(id, &id);
148
149 return id;
150}
151
152static int __init construct_spu(struct spu *spu)
153{
154 int result;
155 unsigned long unused;
156
157 result = lv1_construct_logical_spe(PAGE_SHIFT, PAGE_SHIFT, PAGE_SHIFT,
158 PAGE_SHIFT, PAGE_SHIFT, get_vas_id(), SPE_TYPE_LOGICAL,
159 &spu_pdata(spu)->priv2_addr, &spu->problem_phys,
160 &spu->local_store_phys, &unused,
161 &spu_pdata(spu)->shadow_addr,
162 &spu_pdata(spu)->spe_id);
163
164 if (result) {
165 pr_debug("%s:%d: lv1_construct_logical_spe failed: %s\n",
166 __func__, __LINE__, ps3_result(result));
167 return result;
168 }
169
170 return result;
171}
172
173static int __init add_spu_pages(unsigned long start_addr, unsigned long size)
174{
175 int result;
176 unsigned long start_pfn;
177 unsigned long nr_pages;
178 struct pglist_data *pgdata;
179 struct zone *zone;
180
181 BUG_ON(!mem_init_done);
182
183 start_pfn = start_addr >> PAGE_SHIFT;
184 nr_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
185
186 pgdata = NODE_DATA(0);
187 zone = pgdata->node_zones;
188
189 result = __add_pages(zone, start_pfn, nr_pages);
190
191 if (result)
192 pr_debug("%s:%d: __add_pages failed: (%d)\n",
193 __func__, __LINE__, result);
194
195 return result;
196}
197
198static void spu_unmap(struct spu *spu)
199{
200 iounmap(spu->priv2);
201 iounmap(spu->problem);
202 iounmap((__force u8 __iomem *)spu->local_store);
203 iounmap(spu_pdata(spu)->shadow);
204}
205
206static int __init setup_areas(struct spu *spu)
207{
208 struct table {char* name; unsigned long addr; unsigned long size;};
209 int result;
210
211 /* setup pages */
212
213 result = add_spu_pages(spu->local_store_phys, LS_SIZE);
214 if (result)
215 goto fail_add;
216
217 result = add_spu_pages(spu->problem_phys, sizeof(struct spu_problem));
218 if (result)
219 goto fail_add;
220
221 /* ioremap */
222
223 spu_pdata(spu)->shadow = __ioremap(
224 spu_pdata(spu)->shadow_addr, sizeof(struct spe_shadow),
225 PAGE_READONLY | _PAGE_NO_CACHE | _PAGE_GUARDED);
226 if (!spu_pdata(spu)->shadow) {
227 pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__);
228 goto fail_ioremap;
229 }
230
231 spu->local_store = ioremap(spu->local_store_phys, LS_SIZE);
232 if (!spu->local_store) {
233 pr_debug("%s:%d: ioremap local_store failed\n",
234 __func__, __LINE__);
235 goto fail_ioremap;
236 }
237
238 spu->problem = ioremap(spu->problem_phys,
239 sizeof(struct spu_problem));
240 if (!spu->problem) {
241 pr_debug("%s:%d: ioremap problem failed\n", __func__, __LINE__);
242 goto fail_ioremap;
243 }
244
245 spu->priv2 = ioremap(spu_pdata(spu)->priv2_addr,
246 sizeof(struct spu_priv2));
247 if (!spu->priv2) {
248 pr_debug("%s:%d: ioremap priv2 failed\n", __func__, __LINE__);
249 goto fail_ioremap;
250 }
251
252 dump_areas(spu_pdata(spu)->spe_id, spu_pdata(spu)->priv2_addr,
253 spu->problem_phys, spu->local_store_phys,
254 spu_pdata(spu)->shadow_addr);
255 dump_areas(spu_pdata(spu)->spe_id, (unsigned long)spu->priv2,
256 (unsigned long)spu->problem, (unsigned long)spu->local_store,
257 (unsigned long)spu_pdata(spu)->shadow);
258
259 return 0;
260
261fail_ioremap:
262 spu_unmap(spu);
263fail_add:
264 return result;
265}
266
267static int __init setup_interrupts(struct spu *spu)
268{
269 int result;
270
271 result = ps3_alloc_spe_irq(spu_pdata(spu)->spe_id, 0,
272 &spu->irqs[0]);
273
274 if (result)
275 goto fail_alloc_0;
276
277 result = ps3_alloc_spe_irq(spu_pdata(spu)->spe_id, 1,
278 &spu->irqs[1]);
279
280 if (result)
281 goto fail_alloc_1;
282
283 result = ps3_alloc_spe_irq(spu_pdata(spu)->spe_id, 2,
284 &spu->irqs[2]);
285
286 if (result)
287 goto fail_alloc_2;
288
289 return result;
290
291fail_alloc_2:
292 ps3_free_spe_irq(spu->irqs[1]);
293fail_alloc_1:
294 ps3_free_spe_irq(spu->irqs[0]);
295fail_alloc_0:
296 spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ;
297 return result;
298}
299
300static int __init enable_spu(struct spu *spu)
301{
302 int result;
303
304 result = lv1_enable_logical_spe(spu_pdata(spu)->spe_id,
305 spu_pdata(spu)->resource_id);
306
307 if (result) {
308 pr_debug("%s:%d: lv1_enable_logical_spe failed: %s\n",
309 __func__, __LINE__, ps3_result(result));
310 goto fail_enable;
311 }
312
313 result = setup_areas(spu);
314
315 if (result)
316 goto fail_areas;
317
318 result = setup_interrupts(spu);
319
320 if (result)
321 goto fail_interrupts;
322
323 return 0;
324
325fail_interrupts:
326 spu_unmap(spu);
327fail_areas:
328 lv1_disable_logical_spe(spu_pdata(spu)->spe_id, 0);
329fail_enable:
330 return result;
331}
332
333static int ps3_destroy_spu(struct spu *spu)
334{
335 int result;
336
337 pr_debug("%s:%d spu_%d\n", __func__, __LINE__, spu->number);
338
339 result = lv1_disable_logical_spe(spu_pdata(spu)->spe_id, 0);
340 BUG_ON(result);
341
342 ps3_free_spe_irq(spu->irqs[2]);
343 ps3_free_spe_irq(spu->irqs[1]);
344 ps3_free_spe_irq(spu->irqs[0]);
345
346 spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ;
347
348 spu_unmap(spu);
349
350 result = lv1_destruct_logical_spe(spu_pdata(spu)->spe_id);
351 BUG_ON(result);
352
353 kfree(spu->pdata);
354 spu->pdata = NULL;
355
356 return 0;
357}
358
359static int __init ps3_create_spu(struct spu *spu, void *data)
360{
361 int result;
362
363 pr_debug("%s:%d spu_%d\n", __func__, __LINE__, spu->number);
364
365 spu->pdata = kzalloc(sizeof(struct spu_pdata),
366 GFP_KERNEL);
367
368 if (!spu->pdata) {
369 result = -ENOMEM;
370 goto fail_malloc;
371 }
372
373 spu_pdata(spu)->resource_id = (unsigned long)data;
374
375 /* Init cached reg values to HV defaults. */
376
377 spu_pdata(spu)->cache.sr1 = 0x33;
378
379 result = construct_spu(spu);
380
381 if (result)
382 goto fail_construct;
383
384 /* For now, just go ahead and enable it. */
385
386 result = enable_spu(spu);
387
388 if (result)
389 goto fail_enable;
390
391 /* Make sure the spu is in SPE_EX_STATE_EXECUTED. */
392
393 /* need something better here!!! */
394 while (in_be64(&spu_pdata(spu)->shadow->spe_execution_status)
395 != SPE_EX_STATE_EXECUTED)
396 (void)0;
397
398 return result;
399
400fail_enable:
401fail_construct:
402 ps3_destroy_spu(spu);
403fail_malloc:
404 return result;
405}
406
407static int __init ps3_enumerate_spus(int (*fn)(void *data))
408{
409 int result;
410 unsigned int num_resource_id;
411 unsigned int i;
412
413 result = ps3_repository_read_num_spu_resource_id(&num_resource_id);
414
415 pr_debug("%s:%d: num_resource_id %u\n", __func__, __LINE__,
416 num_resource_id);
417
418 /*
419 * For now, just create logical spus equal to the number
420 * of physical spus reserved for the partition.
421 */
422
423 for (i = 0; i < num_resource_id; i++) {
424 enum ps3_spu_resource_type resource_type;
425 unsigned int resource_id;
426
427 result = ps3_repository_read_spu_resource_id(i,
428 &resource_type, &resource_id);
429
430 if (result)
431 break;
432
433 if (resource_type == PS3_SPU_RESOURCE_TYPE_EXCLUSIVE) {
434 result = fn((void*)(unsigned long)resource_id);
435
436 if (result)
437 break;
438 }
439 }
440
441 if (result)
442 printk(KERN_WARNING "%s:%d: Error initializing spus\n",
443 __func__, __LINE__);
444
445 return result;
446}
447
448const struct spu_management_ops spu_management_ps3_ops = {
449 .enumerate_spus = ps3_enumerate_spus,
450 .create_spu = ps3_create_spu,
451 .destroy_spu = ps3_destroy_spu,
452};
453
454/* spu_priv1_ops */
455
456static void int_mask_and(struct spu *spu, int class, u64 mask)
457{
458 u64 old_mask;
459
460 /* are these serialized by caller??? */
461 old_mask = spu_int_mask_get(spu, class);
462 spu_int_mask_set(spu, class, old_mask & mask);
463}
464
465static void int_mask_or(struct spu *spu, int class, u64 mask)
466{
467 u64 old_mask;
468
469 old_mask = spu_int_mask_get(spu, class);
470 spu_int_mask_set(spu, class, old_mask | mask);
471}
472
473static void int_mask_set(struct spu *spu, int class, u64 mask)
474{
475 spu_pdata(spu)->cache.masks[class] = mask;
476 lv1_set_spe_interrupt_mask(spu_pdata(spu)->spe_id, class,
477 spu_pdata(spu)->cache.masks[class]);
478}
479
480static u64 int_mask_get(struct spu *spu, int class)
481{
482 return spu_pdata(spu)->cache.masks[class];
483}
484
485static void int_stat_clear(struct spu *spu, int class, u64 stat)
486{
487 /* Note that MFC_DSISR will be cleared when class1[MF] is set. */
488
489 lv1_clear_spe_interrupt_status(spu_pdata(spu)->spe_id, class,
490 stat, 0);
491}
492
493static u64 int_stat_get(struct spu *spu, int class)
494{
495 u64 stat;
496
497 lv1_get_spe_interrupt_status(spu_pdata(spu)->spe_id, class, &stat);
498 return stat;
499}
500
501static void cpu_affinity_set(struct spu *spu, int cpu)
502{
503 /* No support. */
504}
505
506static u64 mfc_dar_get(struct spu *spu)
507{
508 return in_be64(&spu_pdata(spu)->shadow->mfc_dar_RW);
509}
510
511static void mfc_dsisr_set(struct spu *spu, u64 dsisr)
512{
513 /* Nothing to do, cleared in int_stat_clear(). */
514}
515
516static u64 mfc_dsisr_get(struct spu *spu)
517{
518 return in_be64(&spu_pdata(spu)->shadow->mfc_dsisr_RW);
519}
520
521static void mfc_sdr_setup(struct spu *spu)
522{
523 /* Nothing to do. */
524}
525
526static void mfc_sr1_set(struct spu *spu, u64 sr1)
527{
528 /* Check bits allowed by HV. */
529
530 static const u64 allowed = ~(MFC_STATE1_LOCAL_STORAGE_DECODE_MASK
531 | MFC_STATE1_PROBLEM_STATE_MASK);
532
533 BUG_ON((sr1 & allowed) != (spu_pdata(spu)->cache.sr1 & allowed));
534
535 spu_pdata(spu)->cache.sr1 = sr1;
536 lv1_set_spe_privilege_state_area_1_register(
537 spu_pdata(spu)->spe_id,
538 offsetof(struct spu_priv1, mfc_sr1_RW),
539 spu_pdata(spu)->cache.sr1);
540}
541
542static u64 mfc_sr1_get(struct spu *spu)
543{
544 return spu_pdata(spu)->cache.sr1;
545}
546
547static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id)
548{
549 spu_pdata(spu)->cache.tclass_id = tclass_id;
550 lv1_set_spe_privilege_state_area_1_register(
551 spu_pdata(spu)->spe_id,
552 offsetof(struct spu_priv1, mfc_tclass_id_RW),
553 spu_pdata(spu)->cache.tclass_id);
554}
555
556static u64 mfc_tclass_id_get(struct spu *spu)
557{
558 return spu_pdata(spu)->cache.tclass_id;
559}
560
561static void tlb_invalidate(struct spu *spu)
562{
563 /* Nothing to do. */
564}
565
566static void resource_allocation_groupID_set(struct spu *spu, u64 id)
567{
568 /* No support. */
569}
570
571static u64 resource_allocation_groupID_get(struct spu *spu)
572{
573 return 0; /* No support. */
574}
575
576static void resource_allocation_enable_set(struct spu *spu, u64 enable)
577{
578 /* No support. */
579}
580
581static u64 resource_allocation_enable_get(struct spu *spu)
582{
583 return 0; /* No support. */
584}
585
586const struct spu_priv1_ops spu_priv1_ps3_ops = {
587 .int_mask_and = int_mask_and,
588 .int_mask_or = int_mask_or,
589 .int_mask_set = int_mask_set,
590 .int_mask_get = int_mask_get,
591 .int_stat_clear = int_stat_clear,
592 .int_stat_get = int_stat_get,
593 .cpu_affinity_set = cpu_affinity_set,
594 .mfc_dar_get = mfc_dar_get,
595 .mfc_dsisr_set = mfc_dsisr_set,
596 .mfc_dsisr_get = mfc_dsisr_get,
597 .mfc_sdr_setup = mfc_sdr_setup,
598 .mfc_sr1_set = mfc_sr1_set,
599 .mfc_sr1_get = mfc_sr1_get,
600 .mfc_tclass_id_set = mfc_tclass_id_set,
601 .mfc_tclass_id_get = mfc_tclass_id_get,
602 .tlb_invalidate = tlb_invalidate,
603 .resource_allocation_groupID_set = resource_allocation_groupID_set,
604 .resource_allocation_groupID_get = resource_allocation_groupID_get,
605 .resource_allocation_enable_set = resource_allocation_enable_set,
606 .resource_allocation_enable_get = resource_allocation_enable_get,
607};
608
609void ps3_spu_set_platform(void)
610{
611 spu_priv1_ops = &spu_priv1_ps3_ops;
612 spu_management_ops = &spu_management_ps3_ops;
613}
diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c
new file mode 100644
index 000000000000..1bae8b19b363
--- /dev/null
+++ b/arch/powerpc/platforms/ps3/time.c
@@ -0,0 +1,104 @@
1/*
2 * PS3 time and rtc routines.
3 *
4 * Copyright (C) 2006 Sony Computer Entertainment Inc.
5 * Copyright 2006 Sony Corp.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/kernel.h>
22
23#include <asm/rtc.h>
24#include <asm/lv1call.h>
25#include <asm/ps3.h>
26
27#include "platform.h"
28
29#define dump_tm(_a) _dump_tm(_a, __func__, __LINE__)
30static void _dump_tm(const struct rtc_time *tm, const char* func, int line)
31{
32 pr_debug("%s:%d tm_sec %d\n", func, line, tm->tm_sec);
33 pr_debug("%s:%d tm_min %d\n", func, line, tm->tm_min);
34 pr_debug("%s:%d tm_hour %d\n", func, line, tm->tm_hour);
35 pr_debug("%s:%d tm_mday %d\n", func, line, tm->tm_mday);
36 pr_debug("%s:%d tm_mon %d\n", func, line, tm->tm_mon);
37 pr_debug("%s:%d tm_year %d\n", func, line, tm->tm_year);
38 pr_debug("%s:%d tm_wday %d\n", func, line, tm->tm_wday);
39}
40
41#define dump_time(_a) _dump_time(_a, __func__, __LINE__)
42static void __attribute__ ((unused)) _dump_time(int time, const char* func,
43 int line)
44{
45 struct rtc_time tm;
46
47 to_tm(time, &tm);
48
49 pr_debug("%s:%d time %d\n", func, line, time);
50 _dump_tm(&tm, func, line);
51}
52
53/**
54 * rtc_shift - Difference in seconds between 1970 and the ps3 rtc value.
55 */
56
57static s64 rtc_shift;
58
59void __init ps3_calibrate_decr(void)
60{
61 int result;
62 u64 tmp;
63
64 result = ps3_repository_read_be_tb_freq(0, &tmp);
65 BUG_ON(result);
66
67 ppc_tb_freq = tmp;
68 ppc_proc_freq = ppc_tb_freq * 40;
69
70 rtc_shift = ps3_os_area_rtc_diff();
71}
72
73static u64 read_rtc(void)
74{
75 int result;
76 u64 rtc_val;
77 u64 tb_val;
78
79 result = lv1_get_rtc(&rtc_val, &tb_val);
80 BUG_ON(result);
81
82 return rtc_val;
83}
84
85int ps3_set_rtc_time(struct rtc_time *tm)
86{
87 u64 now = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
88 tm->tm_hour, tm->tm_min, tm->tm_sec);
89
90 rtc_shift = now - read_rtc();
91 return 0;
92}
93
94void ps3_get_rtc_time(struct rtc_time *tm)
95{
96 to_tm(read_rtc() + rtc_shift, tm);
97 tm->tm_year -= 1900;
98 tm->tm_mon -= 1;
99}
100
101unsigned long __init ps3_get_boot_time(void)
102{
103 return read_rtc() + rtc_shift;
104}
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 556c279a789d..3c95392f4f41 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -309,7 +309,7 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb,
309 tbl->it_size = size >> IOMMU_PAGE_SHIFT; 309 tbl->it_size = size >> IOMMU_PAGE_SHIFT;
310} 310}
311 311
312static void iommu_bus_setup_pSeries(struct pci_bus *bus) 312static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
313{ 313{
314 struct device_node *dn; 314 struct device_node *dn;
315 struct iommu_table *tbl; 315 struct iommu_table *tbl;
@@ -318,10 +318,9 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus)
318 struct pci_dn *pci; 318 struct pci_dn *pci;
319 int children; 319 int children;
320 320
321 DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self);
322
323 dn = pci_bus_to_OF_node(bus); 321 dn = pci_bus_to_OF_node(bus);
324 pci = PCI_DN(dn); 322
323 DBG("pci_dma_bus_setup_pSeries: setting up bus %s\n", dn->full_name);
325 324
326 if (bus->self) { 325 if (bus->self) {
327 /* This is not a root bus, any setup will be done for the 326 /* This is not a root bus, any setup will be done for the
@@ -329,6 +328,7 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus)
329 */ 328 */
330 return; 329 return;
331 } 330 }
331 pci = PCI_DN(dn);
332 332
333 /* Check if the ISA bus on the system is under 333 /* Check if the ISA bus on the system is under
334 * this PHB. 334 * this PHB.
@@ -390,17 +390,17 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus)
390} 390}
391 391
392 392
393static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) 393static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
394{ 394{
395 struct iommu_table *tbl; 395 struct iommu_table *tbl;
396 struct device_node *dn, *pdn; 396 struct device_node *dn, *pdn;
397 struct pci_dn *ppci; 397 struct pci_dn *ppci;
398 const void *dma_window = NULL; 398 const void *dma_window = NULL;
399 399
400 DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self);
401
402 dn = pci_bus_to_OF_node(bus); 400 dn = pci_bus_to_OF_node(bus);
403 401
402 DBG("pci_dma_bus_setup_pSeriesLP: setting up bus %s\n", dn->full_name);
403
404 /* Find nearest ibm,dma-window, walking up the device tree */ 404 /* Find nearest ibm,dma-window, walking up the device tree */
405 for (pdn = dn; pdn != NULL; pdn = pdn->parent) { 405 for (pdn = dn; pdn != NULL; pdn = pdn->parent) {
406 dma_window = get_property(pdn, "ibm,dma-window", NULL); 406 dma_window = get_property(pdn, "ibm,dma-window", NULL);
@@ -409,11 +409,15 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
409 } 409 }
410 410
411 if (dma_window == NULL) { 411 if (dma_window == NULL) {
412 DBG("iommu_bus_setup_pSeriesLP: bus %s seems to have no ibm,dma-window property\n", dn->full_name); 412 DBG(" no ibm,dma-window property !\n");
413 return; 413 return;
414 } 414 }
415 415
416 ppci = PCI_DN(pdn); 416 ppci = PCI_DN(pdn);
417
418 DBG(" parent is %s, iommu_table: 0x%p\n",
419 pdn->full_name, ppci->iommu_table);
420
417 if (!ppci->iommu_table) { 421 if (!ppci->iommu_table) {
418 /* Bussubno hasn't been copied yet. 422 /* Bussubno hasn't been copied yet.
419 * Do it now because iommu_table_setparms_lpar needs it. 423 * Do it now because iommu_table_setparms_lpar needs it.
@@ -427,6 +431,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
427 iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window); 431 iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window);
428 432
429 ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node); 433 ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node);
434 DBG(" created table: %p\n", ppci->iommu_table);
430 } 435 }
431 436
432 if (pdn != dn) 437 if (pdn != dn)
@@ -434,27 +439,27 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
434} 439}
435 440
436 441
437static void iommu_dev_setup_pSeries(struct pci_dev *dev) 442static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
438{ 443{
439 struct device_node *dn, *mydn; 444 struct device_node *dn;
440 struct iommu_table *tbl; 445 struct iommu_table *tbl;
441 446
442 DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, pci_name(dev)); 447 DBG("pci_dma_dev_setup_pSeries: %s\n", pci_name(dev));
443 448
444 mydn = dn = pci_device_to_OF_node(dev); 449 dn = dev->dev.archdata.of_node;
445 450
446 /* If we're the direct child of a root bus, then we need to allocate 451 /* If we're the direct child of a root bus, then we need to allocate
447 * an iommu table ourselves. The bus setup code should have setup 452 * an iommu table ourselves. The bus setup code should have setup
448 * the window sizes already. 453 * the window sizes already.
449 */ 454 */
450 if (!dev->bus->self) { 455 if (!dev->bus->self) {
456 struct pci_controller *phb = PCI_DN(dn)->phb;
457
451 DBG(" --> first child, no bridge. Allocating iommu table.\n"); 458 DBG(" --> first child, no bridge. Allocating iommu table.\n");
452 tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, 459 tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
453 PCI_DN(dn)->phb->node); 460 phb->node);
454 iommu_table_setparms(PCI_DN(dn)->phb, dn, tbl); 461 iommu_table_setparms(phb, dn, tbl);
455 PCI_DN(dn)->iommu_table = iommu_init_table(tbl, 462 dev->dev.archdata.dma_data = iommu_init_table(tbl, phb->node);
456 PCI_DN(dn)->phb->node);
457
458 return; 463 return;
459 } 464 }
460 465
@@ -465,11 +470,11 @@ static void iommu_dev_setup_pSeries(struct pci_dev *dev)
465 while (dn && PCI_DN(dn) && PCI_DN(dn)->iommu_table == NULL) 470 while (dn && PCI_DN(dn) && PCI_DN(dn)->iommu_table == NULL)
466 dn = dn->parent; 471 dn = dn->parent;
467 472
468 if (dn && PCI_DN(dn)) { 473 if (dn && PCI_DN(dn))
469 PCI_DN(mydn)->iommu_table = PCI_DN(dn)->iommu_table; 474 dev->dev.archdata.dma_data = PCI_DN(dn)->iommu_table;
470 } else { 475 else
471 DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu table\n", dev, pci_name(dev)); 476 printk(KERN_WARNING "iommu: Device %s has no iommu table\n",
472 } 477 pci_name(dev));
473} 478}
474 479
475static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) 480static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node)
@@ -495,13 +500,15 @@ static struct notifier_block iommu_reconfig_nb = {
495 .notifier_call = iommu_reconfig_notifier, 500 .notifier_call = iommu_reconfig_notifier,
496}; 501};
497 502
498static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) 503static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
499{ 504{
500 struct device_node *pdn, *dn; 505 struct device_node *pdn, *dn;
501 struct iommu_table *tbl; 506 struct iommu_table *tbl;
502 const void *dma_window = NULL; 507 const void *dma_window = NULL;
503 struct pci_dn *pci; 508 struct pci_dn *pci;
504 509
510 DBG("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev));
511
505 /* dev setup for LPAR is a little tricky, since the device tree might 512 /* dev setup for LPAR is a little tricky, since the device tree might
506 * contain the dma-window properties per-device and not neccesarily 513 * contain the dma-window properties per-device and not neccesarily
507 * for the bus. So we need to search upwards in the tree until we 514 * for the bus. So we need to search upwards in the tree until we
@@ -509,9 +516,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
509 * already allocated. 516 * already allocated.
510 */ 517 */
511 dn = pci_device_to_OF_node(dev); 518 dn = pci_device_to_OF_node(dev);
512 519 DBG(" node is %s\n", dn->full_name);
513 DBG("iommu_dev_setup_pSeriesLP, dev %p (%s) %s\n",
514 dev, pci_name(dev), dn->full_name);
515 520
516 for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table; 521 for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table;
517 pdn = pdn->parent) { 522 pdn = pdn->parent) {
@@ -520,16 +525,17 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
520 break; 525 break;
521 } 526 }
522 527
528 DBG(" parent is %s\n", pdn->full_name);
529
523 /* Check for parent == NULL so we don't try to setup the empty EADS 530 /* Check for parent == NULL so we don't try to setup the empty EADS
524 * slots on POWER4 machines. 531 * slots on POWER4 machines.
525 */ 532 */
526 if (dma_window == NULL || pdn->parent == NULL) { 533 if (dma_window == NULL || pdn->parent == NULL) {
527 DBG("No dma window for device, linking to parent\n"); 534 DBG(" no dma window for device, linking to parent\n");
528 PCI_DN(dn)->iommu_table = PCI_DN(pdn)->iommu_table; 535 dev->dev.archdata.dma_data = PCI_DN(pdn)->iommu_table;
529 return; 536 return;
530 } else {
531 DBG("Found DMA window, allocating table\n");
532 } 537 }
538 DBG(" found DMA window, table: %p\n", pci->iommu_table);
533 539
534 pci = PCI_DN(pdn); 540 pci = PCI_DN(pdn);
535 if (!pci->iommu_table) { 541 if (!pci->iommu_table) {
@@ -542,24 +548,20 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
542 iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window); 548 iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window);
543 549
544 pci->iommu_table = iommu_init_table(tbl, pci->phb->node); 550 pci->iommu_table = iommu_init_table(tbl, pci->phb->node);
551 DBG(" created table: %p\n", pci->iommu_table);
545 } 552 }
546 553
547 if (pdn != dn) 554 dev->dev.archdata.dma_data = pci->iommu_table;
548 PCI_DN(dn)->iommu_table = pci->iommu_table;
549} 555}
550 556
551static void iommu_bus_setup_null(struct pci_bus *b) { }
552static void iommu_dev_setup_null(struct pci_dev *d) { }
553
554/* These are called very early. */ 557/* These are called very early. */
555void iommu_init_early_pSeries(void) 558void iommu_init_early_pSeries(void)
556{ 559{
557 if (of_chosen && get_property(of_chosen, "linux,iommu-off", NULL)) { 560 if (of_chosen && get_property(of_chosen, "linux,iommu-off", NULL)) {
558 /* Direct I/O, IOMMU off */ 561 /* Direct I/O, IOMMU off */
559 ppc_md.iommu_dev_setup = iommu_dev_setup_null; 562 ppc_md.pci_dma_dev_setup = NULL;
560 ppc_md.iommu_bus_setup = iommu_bus_setup_null; 563 ppc_md.pci_dma_bus_setup = NULL;
561 pci_direct_iommu_init(); 564 pci_dma_ops = &dma_direct_ops;
562
563 return; 565 return;
564 } 566 }
565 567
@@ -572,19 +574,19 @@ void iommu_init_early_pSeries(void)
572 ppc_md.tce_free = tce_free_pSeriesLP; 574 ppc_md.tce_free = tce_free_pSeriesLP;
573 } 575 }
574 ppc_md.tce_get = tce_get_pSeriesLP; 576 ppc_md.tce_get = tce_get_pSeriesLP;
575 ppc_md.iommu_bus_setup = iommu_bus_setup_pSeriesLP; 577 ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP;
576 ppc_md.iommu_dev_setup = iommu_dev_setup_pSeriesLP; 578 ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP;
577 } else { 579 } else {
578 ppc_md.tce_build = tce_build_pSeries; 580 ppc_md.tce_build = tce_build_pSeries;
579 ppc_md.tce_free = tce_free_pSeries; 581 ppc_md.tce_free = tce_free_pSeries;
580 ppc_md.tce_get = tce_get_pseries; 582 ppc_md.tce_get = tce_get_pseries;
581 ppc_md.iommu_bus_setup = iommu_bus_setup_pSeries; 583 ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeries;
582 ppc_md.iommu_dev_setup = iommu_dev_setup_pSeries; 584 ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeries;
583 } 585 }
584 586
585 587
586 pSeries_reconfig_notifier_register(&iommu_reconfig_nb); 588 pSeries_reconfig_notifier_register(&iommu_reconfig_nb);
587 589
588 pci_iommu_init(); 590 pci_dma_ops = &dma_iommu_ops;
589} 591}
590 592
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 1820a0b0a8c6..721436db3ef0 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -282,7 +282,7 @@ void vpa_init(int cpu)
282 } 282 }
283} 283}
284 284
285long pSeries_lpar_hpte_insert(unsigned long hpte_group, 285static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
286 unsigned long va, unsigned long pa, 286 unsigned long va, unsigned long pa,
287 unsigned long rflags, unsigned long vflags, 287 unsigned long rflags, unsigned long vflags,
288 int psize) 288 int psize)
@@ -506,7 +506,7 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
506 * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie 506 * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie
507 * lock. 507 * lock.
508 */ 508 */
509void pSeries_lpar_flush_hash_range(unsigned long number, int local) 509static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
510{ 510{
511 int i; 511 int i;
512 unsigned long flags = 0; 512 unsigned long flags = 0;
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c
index 410a6bcc4ca0..715db5c89908 100644
--- a/arch/powerpc/platforms/pseries/pci.c
+++ b/arch/powerpc/platforms/pseries/pci.c
@@ -29,8 +29,6 @@
29#include <asm/prom.h> 29#include <asm/prom.h>
30#include <asm/ppc-pci.h> 30#include <asm/ppc-pci.h>
31 31
32static int __devinitdata s7a_workaround = -1;
33
34#if 0 32#if 0
35void pcibios_name_device(struct pci_dev *dev) 33void pcibios_name_device(struct pci_dev *dev)
36{ 34{
@@ -57,39 +55,6 @@ void pcibios_name_device(struct pci_dev *dev)
57DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device); 55DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device);
58#endif 56#endif
59 57
60static void __devinit check_s7a(void)
61{
62 struct device_node *root;
63 const char *model;
64
65 s7a_workaround = 0;
66 root = of_find_node_by_path("/");
67 if (root) {
68 model = get_property(root, "model", NULL);
69 if (model && !strcmp(model, "IBM,7013-S7A"))
70 s7a_workaround = 1;
71 of_node_put(root);
72 }
73}
74
75void __devinit pSeries_irq_bus_setup(struct pci_bus *bus)
76{
77 struct pci_dev *dev;
78
79 if (s7a_workaround < 0)
80 check_s7a();
81 list_for_each_entry(dev, &bus->devices, bus_list) {
82 pci_read_irq_line(dev);
83 if (s7a_workaround) {
84 if (dev->irq > 16) {
85 dev->irq -= 3;
86 pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
87 dev->irq);
88 }
89 }
90 }
91}
92
93static void __init pSeries_request_regions(void) 58static void __init pSeries_request_regions(void)
94{ 59{
95 if (!isa_io_base) 60 if (!isa_io_base)
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index 6bfacc217085..ac56b868913a 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -93,8 +93,8 @@ pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
93 if (list_empty(&dev->global_list)) { 93 if (list_empty(&dev->global_list)) {
94 int i; 94 int i;
95 95
96 /* Need to setup IOMMU tables */ 96 /* Fill device archdata and setup iommu table */
97 ppc_md.iommu_dev_setup(dev); 97 pcibios_setup_new_device(dev);
98 98
99 if(fix_bus) 99 if(fix_bus)
100 pcibios_fixup_device_resources(dev, bus); 100 pcibios_fixup_device_resources(dev, bus);
@@ -195,7 +195,7 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
195 phb = pcibios_alloc_controller(dn); 195 phb = pcibios_alloc_controller(dn);
196 if (!phb) 196 if (!phb)
197 return NULL; 197 return NULL;
198 setup_phb(dn, phb); 198 rtas_setup_phb(phb);
199 pci_process_bridge_OF_ranges(phb, dn, 0); 199 pci_process_bridge_OF_ranges(phb, dn, 0);
200 200
201 pci_setup_phb_io_dynamic(phb, primary); 201 pci_setup_phb_io_dynamic(phb, primary);
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 1773103354be..4ad33e41b008 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -268,11 +268,10 @@ static char * parse_next_property(char *buf, char *end, char **name, int *length
268static struct property *new_property(const char *name, const int length, 268static struct property *new_property(const char *name, const int length,
269 const unsigned char *value, struct property *last) 269 const unsigned char *value, struct property *last)
270{ 270{
271 struct property *new = kmalloc(sizeof(*new), GFP_KERNEL); 271 struct property *new = kzalloc(sizeof(*new), GFP_KERNEL);
272 272
273 if (!new) 273 if (!new)
274 return NULL; 274 return NULL;
275 memset(new, 0, sizeof(*new));
276 275
277 if (!(new->name = kmalloc(strlen(name) + 1, GFP_KERNEL))) 276 if (!(new->name = kmalloc(strlen(name) + 1, GFP_KERNEL)))
278 goto cleanup; 277 goto cleanup;
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 89a8119f988d..0dc2548ca9bc 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -347,6 +347,7 @@ static int __init pSeries_init_panel(void)
347} 347}
348arch_initcall(pSeries_init_panel); 348arch_initcall(pSeries_init_panel);
349 349
350#ifdef CONFIG_HOTPLUG_CPU
350static void pSeries_mach_cpu_die(void) 351static void pSeries_mach_cpu_die(void)
351{ 352{
352 local_irq_disable(); 353 local_irq_disable();
@@ -357,6 +358,9 @@ static void pSeries_mach_cpu_die(void)
357 BUG(); 358 BUG();
358 for(;;); 359 for(;;);
359} 360}
361#else
362#define pSeries_mach_cpu_die NULL
363#endif
360 364
361static int pseries_set_dabr(unsigned long dabr) 365static int pseries_set_dabr(unsigned long dabr)
362{ 366{
@@ -553,7 +557,6 @@ define_machine(pseries) {
553 .log_error = pSeries_log_error, 557 .log_error = pSeries_log_error,
554 .pcibios_fixup = pSeries_final_fixup, 558 .pcibios_fixup = pSeries_final_fixup,
555 .pci_probe_mode = pSeries_pci_probe_mode, 559 .pci_probe_mode = pSeries_pci_probe_mode,
556 .irq_bus_setup = pSeries_irq_bus_setup,
557 .restart = rtas_restart, 560 .restart = rtas_restart,
558 .power_off = rtas_power_off, 561 .power_off = rtas_power_off,
559 .halt = rtas_halt, 562 .halt = rtas_halt,
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index d071abe78ab1..b5b2b1103de8 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -656,13 +656,38 @@ static void __init xics_setup_8259_cascade(void)
656 set_irq_chained_handler(cascade, pseries_8259_cascade); 656 set_irq_chained_handler(cascade, pseries_8259_cascade);
657} 657}
658 658
659static struct device_node *cpuid_to_of_node(int cpu)
660{
661 struct device_node *np;
662 u32 hcpuid = get_hard_smp_processor_id(cpu);
663
664 for_each_node_by_type(np, "cpu") {
665 int i, len;
666 const u32 *intserv;
667
668 intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len);
669
670 if (!intserv)
671 intserv = get_property(np, "reg", &len);
672
673 i = len / sizeof(u32);
674
675 while (i--)
676 if (intserv[i] == hcpuid)
677 return np;
678 }
679
680 return NULL;
681}
682
659void __init xics_init_IRQ(void) 683void __init xics_init_IRQ(void)
660{ 684{
661 int i; 685 int i, j;
662 struct device_node *np; 686 struct device_node *np;
663 u32 ilen, indx = 0; 687 u32 ilen, indx = 0;
664 const u32 *ireg; 688 const u32 *ireg, *isize;
665 int found = 0; 689 int found = 0;
690 u32 hcpuid;
666 691
667 ppc64_boot_msg(0x20, "XICS Init"); 692 ppc64_boot_msg(0x20, "XICS Init");
668 693
@@ -683,26 +708,31 @@ void __init xics_init_IRQ(void)
683 xics_init_host(); 708 xics_init_host();
684 709
685 /* Find the server numbers for the boot cpu. */ 710 /* Find the server numbers for the boot cpu. */
686 for (np = of_find_node_by_type(NULL, "cpu"); 711 np = cpuid_to_of_node(boot_cpuid);
687 np; 712 BUG_ON(!np);
688 np = of_find_node_by_type(np, "cpu")) { 713 ireg = get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
689 ireg = get_property(np, "reg", &ilen); 714 if (!ireg)
690 if (ireg && ireg[0] == get_hard_smp_processor_id(boot_cpuid)) { 715 goto skip_gserver_check;
691 ireg = get_property(np, 716 i = ilen / sizeof(int);
692 "ibm,ppc-interrupt-gserver#s", &ilen); 717 hcpuid = get_hard_smp_processor_id(boot_cpuid);
693 i = ilen / sizeof(int); 718
694 if (ireg && i > 0) { 719 /* Global interrupt distribution server is specified in the last
695 default_server = ireg[0]; 720 * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last
696 /* take last element */ 721 * entry fom this property for current boot cpu id and use it as
697 default_distrib_server = ireg[i-1]; 722 * default distribution server
698 } 723 */
699 ireg = get_property(np, 724 for (j = 0; j < i; j += 2) {
725 if (ireg[j] == hcpuid) {
726 default_server = hcpuid;
727 default_distrib_server = ireg[j+1];
728
729 isize = get_property(np,
700 "ibm,interrupt-server#-size", NULL); 730 "ibm,interrupt-server#-size", NULL);
701 if (ireg) 731 if (isize)
702 interrupt_server_size = *ireg; 732 interrupt_server_size = *isize;
703 break;
704 } 733 }
705 } 734 }
735skip_gserver_check:
706 of_node_put(np); 736 of_node_put(np);
707 737
708 if (firmware_has_feature(FW_FEATURE_LPAR)) 738 if (firmware_has_feature(FW_FEATURE_LPAR))
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 91f052d8cce0..6cc34597a620 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -5,14 +5,13 @@ endif
5obj-$(CONFIG_MPIC) += mpic.o 5obj-$(CONFIG_MPIC) += mpic.o
6obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o 6obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
7obj-$(CONFIG_PPC_MPC106) += grackle.o 7obj-$(CONFIG_PPC_MPC106) += grackle.o
8obj-$(CONFIG_BOOKE) += dcr.o 8obj-$(CONFIG_PPC_DCR) += dcr.o dcr-low.o
9obj-$(CONFIG_40x) += dcr.o
10obj-$(CONFIG_U3_DART) += dart_iommu.o 9obj-$(CONFIG_U3_DART) += dart_iommu.o
11obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o 10obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
12obj-$(CONFIG_FSL_SOC) += fsl_soc.o 11obj-$(CONFIG_FSL_SOC) += fsl_soc.o
13obj-$(CONFIG_PPC_TODC) += todc.o
14obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o 12obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
15obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ 13obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
14obj-$(CONFIG_MTD) += rom.o
16 15
17ifeq ($(CONFIG_PPC_MERGE),y) 16ifeq ($(CONFIG_PPC_MERGE),y)
18obj-$(CONFIG_PPC_I8259) += i8259.o 17obj-$(CONFIG_PPC_I8259) += i8259.o
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 572b7846cc77..1488535b0e13 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -48,9 +48,6 @@
48 48
49#include "dart.h" 49#include "dart.h"
50 50
51extern int iommu_is_off;
52extern int iommu_force_on;
53
54/* Physical base address and size of the DART table */ 51/* Physical base address and size of the DART table */
55unsigned long dart_tablebase; /* exported to htab_initialize */ 52unsigned long dart_tablebase; /* exported to htab_initialize */
56static unsigned long dart_tablesize; 53static unsigned long dart_tablesize;
@@ -289,24 +286,15 @@ static void iommu_table_dart_setup(void)
289 set_bit(iommu_table_dart.it_size - 1, iommu_table_dart.it_map); 286 set_bit(iommu_table_dart.it_size - 1, iommu_table_dart.it_map);
290} 287}
291 288
292static void iommu_dev_setup_dart(struct pci_dev *dev) 289static void pci_dma_dev_setup_dart(struct pci_dev *dev)
293{ 290{
294 struct device_node *dn;
295
296 /* We only have one iommu table on the mac for now, which makes 291 /* We only have one iommu table on the mac for now, which makes
297 * things simple. Setup all PCI devices to point to this table 292 * things simple. Setup all PCI devices to point to this table
298 *
299 * We must use pci_device_to_OF_node() to make sure that
300 * we get the real "final" pointer to the device in the
301 * pci_dev sysdata and not the temporary PHB one
302 */ 293 */
303 dn = pci_device_to_OF_node(dev); 294 dev->dev.archdata.dma_data = &iommu_table_dart;
304
305 if (dn)
306 PCI_DN(dn)->iommu_table = &iommu_table_dart;
307} 295}
308 296
309static void iommu_bus_setup_dart(struct pci_bus *bus) 297static void pci_dma_bus_setup_dart(struct pci_bus *bus)
310{ 298{
311 struct device_node *dn; 299 struct device_node *dn;
312 300
@@ -321,9 +309,6 @@ static void iommu_bus_setup_dart(struct pci_bus *bus)
321 PCI_DN(dn)->iommu_table = &iommu_table_dart; 309 PCI_DN(dn)->iommu_table = &iommu_table_dart;
322} 310}
323 311
324static void iommu_dev_setup_null(struct pci_dev *dev) { }
325static void iommu_bus_setup_null(struct pci_bus *bus) { }
326
327void iommu_init_early_dart(void) 312void iommu_init_early_dart(void)
328{ 313{
329 struct device_node *dn; 314 struct device_node *dn;
@@ -344,22 +329,21 @@ void iommu_init_early_dart(void)
344 329
345 /* Initialize the DART HW */ 330 /* Initialize the DART HW */
346 if (dart_init(dn) == 0) { 331 if (dart_init(dn) == 0) {
347 ppc_md.iommu_dev_setup = iommu_dev_setup_dart; 332 ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_dart;
348 ppc_md.iommu_bus_setup = iommu_bus_setup_dart; 333 ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart;
349 334
350 /* Setup pci_dma ops */ 335 /* Setup pci_dma ops */
351 pci_iommu_init(); 336 pci_dma_ops = &dma_iommu_ops;
352
353 return; 337 return;
354 } 338 }
355 339
356 bail: 340 bail:
357 /* If init failed, use direct iommu and null setup functions */ 341 /* If init failed, use direct iommu and null setup functions */
358 ppc_md.iommu_dev_setup = iommu_dev_setup_null; 342 ppc_md.pci_dma_dev_setup = NULL;
359 ppc_md.iommu_bus_setup = iommu_bus_setup_null; 343 ppc_md.pci_dma_bus_setup = NULL;
360 344
361 /* Setup pci_dma ops */ 345 /* Setup pci_dma ops */
362 pci_direct_iommu_init(); 346 pci_dma_ops = &dma_direct_ops;
363} 347}
364 348
365 349
diff --git a/arch/powerpc/sysdev/dcr-low.S b/arch/powerpc/sysdev/dcr-low.S
new file mode 100644
index 000000000000..2078f39e2f17
--- /dev/null
+++ b/arch/powerpc/sysdev/dcr-low.S
@@ -0,0 +1,39 @@
1/*
2 * "Indirect" DCR access
3 *
4 * Copyright (c) 2004 Eugene Surovegin <ebs@ebshome.net>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#include <asm/ppc_asm.h>
13#include <asm/processor.h>
14
15#define DCR_ACCESS_PROLOG(table) \
16 rlwinm r3,r3,4,18,27; \
17 lis r5,table@h; \
18 ori r5,r5,table@l; \
19 add r3,r3,r5; \
20 mtctr r3; \
21 bctr
22
23_GLOBAL(__mfdcr)
24 DCR_ACCESS_PROLOG(__mfdcr_table)
25
26_GLOBAL(__mtdcr)
27 DCR_ACCESS_PROLOG(__mtdcr_table)
28
29__mfdcr_table:
30 mfdcr r3,0; blr
31__mtdcr_table:
32 mtdcr 0,r4; blr
33
34dcr = 1
35 .rept 1023
36 mfdcr r3,dcr; blr
37 mtdcr dcr,r4; blr
38 dcr = dcr + 1
39 .endr
diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c
new file mode 100644
index 000000000000..dffeeaeca1d9
--- /dev/null
+++ b/arch/powerpc/sysdev/dcr.c
@@ -0,0 +1,137 @@
1/*
2 * (c) Copyright 2006 Benjamin Herrenschmidt, IBM Corp.
3 * <benh@kernel.crashing.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#undef DEBUG
21
22#include <linux/kernel.h>
23#include <asm/prom.h>
24#include <asm/dcr.h>
25
26unsigned int dcr_resource_start(struct device_node *np, unsigned int index)
27{
28 unsigned int ds;
29 const u32 *dr = get_property(np, "dcr-reg", &ds);
30
31 if (dr == NULL || ds & 1 || index >= (ds / 8))
32 return 0;
33
34 return dr[index * 2];
35}
36
37unsigned int dcr_resource_len(struct device_node *np, unsigned int index)
38{
39 unsigned int ds;
40 const u32 *dr = get_property(np, "dcr-reg", &ds);
41
42 if (dr == NULL || ds & 1 || index >= (ds / 8))
43 return 0;
44
45 return dr[index * 2 + 1];
46}
47
48#ifndef CONFIG_PPC_DCR_NATIVE
49
50static struct device_node * find_dcr_parent(struct device_node * node)
51{
52 struct device_node *par, *tmp;
53 const u32 *p;
54
55 for (par = of_node_get(node); par;) {
56 if (get_property(par, "dcr-controller", NULL))
57 break;
58 p = get_property(par, "dcr-parent", NULL);
59 tmp = par;
60 if (p == NULL)
61 par = of_get_parent(par);
62 else
63 par = of_find_node_by_phandle(*p);
64 of_node_put(tmp);
65 }
66 return par;
67}
68
69u64 of_translate_dcr_address(struct device_node *dev,
70 unsigned int dcr_n,
71 unsigned int *out_stride)
72{
73 struct device_node *dp;
74 const u32 *p;
75 unsigned int stride;
76 u64 ret;
77
78 dp = find_dcr_parent(dev);
79 if (dp == NULL)
80 return OF_BAD_ADDR;
81
82 /* Stride is not properly defined yet, default to 0x10 for Axon */
83 p = get_property(dp, "dcr-mmio-stride", NULL);
84 stride = (p == NULL) ? 0x10 : *p;
85
86 /* XXX FIXME: Which property name is to use of the 2 following ? */
87 p = get_property(dp, "dcr-mmio-range", NULL);
88 if (p == NULL)
89 p = get_property(dp, "dcr-mmio-space", NULL);
90 if (p == NULL)
91 return OF_BAD_ADDR;
92
93 /* Maybe could do some better range checking here */
94 ret = of_translate_address(dp, p);
95 if (ret != OF_BAD_ADDR)
96 ret += (u64)(stride) * (u64)dcr_n;
97 if (out_stride)
98 *out_stride = stride;
99 return ret;
100}
101
102dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n,
103 unsigned int dcr_c)
104{
105 dcr_host_t ret = { .token = NULL, .stride = 0 };
106 u64 addr;
107
108 pr_debug("dcr_map(%s, 0x%x, 0x%x)\n",
109 dev->full_name, dcr_n, dcr_c);
110
111 addr = of_translate_dcr_address(dev, dcr_n, &ret.stride);
112 pr_debug("translates to addr: 0x%lx, stride: 0x%x\n",
113 addr, ret.stride);
114 if (addr == OF_BAD_ADDR)
115 return ret;
116 pr_debug("mapping 0x%x bytes\n", dcr_c * ret.stride);
117 ret.token = ioremap(addr, dcr_c * ret.stride);
118 if (ret.token == NULL)
119 return ret;
120 pr_debug("mapped at 0x%p -> base is 0x%p\n",
121 ret.token, ret.token - dcr_n * ret.stride);
122 ret.token -= dcr_n * ret.stride;
123 return ret;
124}
125
126void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c)
127{
128 dcr_host_t h = host;
129
130 if (h.token == NULL)
131 return;
132 h.token -= dcr_n * h.stride;
133 iounmap(h.token);
134 h.token = NULL;
135}
136
137#endif /* !defined(CONFIG_PPC_DCR_NATIVE) */
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index dbe92ae20333..ad31e56e892b 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -22,6 +22,7 @@
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/device.h> 23#include <linux/device.h>
24#include <linux/platform_device.h> 24#include <linux/platform_device.h>
25#include <linux/phy.h>
25#include <linux/fsl_devices.h> 26#include <linux/fsl_devices.h>
26#include <linux/fs_enet_pd.h> 27#include <linux/fs_enet_pd.h>
27#include <linux/fs_uart_pd.h> 28#include <linux/fs_uart_pd.h>
@@ -146,7 +147,7 @@ static int __init gfar_mdio_of_init(void)
146 } 147 }
147 148
148 for (k = 0; k < 32; k++) 149 for (k = 0; k < 32; k++)
149 mdio_data.irq[k] = -1; 150 mdio_data.irq[k] = PHY_POLL;
150 151
151 while ((child = of_get_next_child(np, child)) != NULL) { 152 while ((child = of_get_next_child(np, child)) != NULL) {
152 int irq = irq_of_parse_and_map(child, 0); 153 int irq = irq_of_parse_and_map(child, 0);
@@ -177,6 +178,7 @@ static const char *gfar_tx_intr = "tx";
177static const char *gfar_rx_intr = "rx"; 178static const char *gfar_rx_intr = "rx";
178static const char *gfar_err_intr = "error"; 179static const char *gfar_err_intr = "error";
179 180
181
180static int __init gfar_of_init(void) 182static int __init gfar_of_init(void)
181{ 183{
182 struct device_node *np; 184 struct device_node *np;
@@ -204,8 +206,7 @@ static int __init gfar_of_init(void)
204 if (ret) 206 if (ret)
205 goto err; 207 goto err;
206 208
207 r[1].start = r[1].end = irq_of_parse_and_map(np, 0); 209 of_irq_to_resource(np, 0, &r[1]);
208 r[1].flags = IORESOURCE_IRQ;
209 210
210 model = get_property(np, "model", NULL); 211 model = get_property(np, "model", NULL);
211 212
@@ -214,12 +215,10 @@ static int __init gfar_of_init(void)
214 r[1].name = gfar_tx_intr; 215 r[1].name = gfar_tx_intr;
215 216
216 r[2].name = gfar_rx_intr; 217 r[2].name = gfar_rx_intr;
217 r[2].start = r[2].end = irq_of_parse_and_map(np, 1); 218 of_irq_to_resource(np, 1, &r[2]);
218 r[2].flags = IORESOURCE_IRQ;
219 219
220 r[3].name = gfar_err_intr; 220 r[3].name = gfar_err_intr;
221 r[3].start = r[3].end = irq_of_parse_and_map(np, 2); 221 of_irq_to_resource(np, 2, &r[3]);
222 r[3].flags = IORESOURCE_IRQ;
223 222
224 n_res += 2; 223 n_res += 2;
225 } 224 }
@@ -323,8 +322,7 @@ static int __init fsl_i2c_of_init(void)
323 if (ret) 322 if (ret)
324 goto err; 323 goto err;
325 324
326 r[1].start = r[1].end = irq_of_parse_and_map(np, 0); 325 of_irq_to_resource(np, 0, &r[1]);
327 r[1].flags = IORESOURCE_IRQ;
328 326
329 i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2); 327 i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2);
330 if (IS_ERR(i2c_dev)) { 328 if (IS_ERR(i2c_dev)) {
@@ -459,8 +457,7 @@ static int __init fsl_usb_of_init(void)
459 if (ret) 457 if (ret)
460 goto err; 458 goto err;
461 459
462 r[1].start = r[1].end = irq_of_parse_and_map(np, 0); 460 of_irq_to_resource(np, 0, &r[1]);
463 r[1].flags = IORESOURCE_IRQ;
464 461
465 usb_dev_mph = 462 usb_dev_mph =
466 platform_device_register_simple("fsl-ehci", i, r, 2); 463 platform_device_register_simple("fsl-ehci", i, r, 2);
@@ -507,8 +504,7 @@ static int __init fsl_usb_of_init(void)
507 if (ret) 504 if (ret)
508 goto unreg_mph; 505 goto unreg_mph;
509 506
510 r[1].start = r[1].end = irq_of_parse_and_map(np, 0); 507 of_irq_to_resource(np, 0, &r[1]);
511 r[1].flags = IORESOURCE_IRQ;
512 508
513 usb_dev_dr = 509 usb_dev_dr =
514 platform_device_register_simple("fsl-ehci", i, r, 2); 510 platform_device_register_simple("fsl-ehci", i, r, 2);
@@ -591,8 +587,7 @@ static int __init fs_enet_of_init(void)
591 r[2].name = fcc_regs_c; 587 r[2].name = fcc_regs_c;
592 fs_enet_data.fcc_regs_c = r[2].start; 588 fs_enet_data.fcc_regs_c = r[2].start;
593 589
594 r[3].start = r[3].end = irq_of_parse_and_map(np, 0); 590 of_irq_to_resource(np, 0, &r[3]);
595 r[3].flags = IORESOURCE_IRQ;
596 591
597 fs_enet_dev = 592 fs_enet_dev =
598 platform_device_register_simple("fsl-cpm-fcc", i, &r[0], 4); 593 platform_device_register_simple("fsl-cpm-fcc", i, &r[0], 4);
@@ -754,8 +749,7 @@ static int __init cpm_uart_of_init(void)
754 goto err; 749 goto err;
755 r[1].name = scc_pram; 750 r[1].name = scc_pram;
756 751
757 r[2].start = r[2].end = irq_of_parse_and_map(np, 0); 752 of_irq_to_resource(np, 0, &r[2]);
758 r[2].flags = IORESOURCE_IRQ;
759 753
760 cpm_uart_dev = 754 cpm_uart_dev =
761 platform_device_register_simple("fsl-cpm-scc:uart", i, &r[0], 3); 755 platform_device_register_simple("fsl-cpm-scc:uart", i, &r[0], 3);
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index ba4833f57d47..411480d5c626 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -147,33 +147,51 @@ static u32 mpic_infos[][MPIC_IDX_END] = {
147 */ 147 */
148 148
149 149
150static inline u32 _mpic_read(unsigned int be, volatile u32 __iomem *base, 150static inline u32 _mpic_read(enum mpic_reg_type type,
151 unsigned int reg) 151 struct mpic_reg_bank *rb,
152 unsigned int reg)
152{ 153{
153 if (be) 154 switch(type) {
154 return in_be32(base + (reg >> 2)); 155#ifdef CONFIG_PPC_DCR
155 else 156 case mpic_access_dcr:
156 return in_le32(base + (reg >> 2)); 157 return dcr_read(rb->dhost,
158 rb->dbase + reg + rb->doff);
159#endif
160 case mpic_access_mmio_be:
161 return in_be32(rb->base + (reg >> 2));
162 case mpic_access_mmio_le:
163 default:
164 return in_le32(rb->base + (reg >> 2));
165 }
157} 166}
158 167
159static inline void _mpic_write(unsigned int be, volatile u32 __iomem *base, 168static inline void _mpic_write(enum mpic_reg_type type,
160 unsigned int reg, u32 value) 169 struct mpic_reg_bank *rb,
170 unsigned int reg, u32 value)
161{ 171{
162 if (be) 172 switch(type) {
163 out_be32(base + (reg >> 2), value); 173#ifdef CONFIG_PPC_DCR
164 else 174 case mpic_access_dcr:
165 out_le32(base + (reg >> 2), value); 175 return dcr_write(rb->dhost,
176 rb->dbase + reg + rb->doff, value);
177#endif
178 case mpic_access_mmio_be:
179 return out_be32(rb->base + (reg >> 2), value);
180 case mpic_access_mmio_le:
181 default:
182 return out_le32(rb->base + (reg >> 2), value);
183 }
166} 184}
167 185
168static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi) 186static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi)
169{ 187{
170 unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0; 188 enum mpic_reg_type type = mpic->reg_type;
171 unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) + 189 unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) +
172 (ipi * MPIC_INFO(GREG_IPI_STRIDE)); 190 (ipi * MPIC_INFO(GREG_IPI_STRIDE));
173 191
174 if (mpic->flags & MPIC_BROKEN_IPI) 192 if ((mpic->flags & MPIC_BROKEN_IPI) && type == mpic_access_mmio_le)
175 be = !be; 193 type = mpic_access_mmio_be;
176 return _mpic_read(be, mpic->gregs, offset); 194 return _mpic_read(type, &mpic->gregs, offset);
177} 195}
178 196
179static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value) 197static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value)
@@ -181,7 +199,7 @@ static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 valu
181 unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) + 199 unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) +
182 (ipi * MPIC_INFO(GREG_IPI_STRIDE)); 200 (ipi * MPIC_INFO(GREG_IPI_STRIDE));
183 201
184 _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value); 202 _mpic_write(mpic->reg_type, &mpic->gregs, offset, value);
185} 203}
186 204
187static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg) 205static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg)
@@ -190,8 +208,7 @@ static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg)
190 208
191 if (mpic->flags & MPIC_PRIMARY) 209 if (mpic->flags & MPIC_PRIMARY)
192 cpu = hard_smp_processor_id(); 210 cpu = hard_smp_processor_id();
193 return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, 211 return _mpic_read(mpic->reg_type, &mpic->cpuregs[cpu], reg);
194 mpic->cpuregs[cpu], reg);
195} 212}
196 213
197static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value) 214static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value)
@@ -201,7 +218,7 @@ static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 valu
201 if (mpic->flags & MPIC_PRIMARY) 218 if (mpic->flags & MPIC_PRIMARY)
202 cpu = hard_smp_processor_id(); 219 cpu = hard_smp_processor_id();
203 220
204 _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg, value); 221 _mpic_write(mpic->reg_type, &mpic->cpuregs[cpu], reg, value);
205} 222}
206 223
207static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigned int reg) 224static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigned int reg)
@@ -209,7 +226,7 @@ static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigne
209 unsigned int isu = src_no >> mpic->isu_shift; 226 unsigned int isu = src_no >> mpic->isu_shift;
210 unsigned int idx = src_no & mpic->isu_mask; 227 unsigned int idx = src_no & mpic->isu_mask;
211 228
212 return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu], 229 return _mpic_read(mpic->reg_type, &mpic->isus[isu],
213 reg + (idx * MPIC_INFO(IRQ_STRIDE))); 230 reg + (idx * MPIC_INFO(IRQ_STRIDE)));
214} 231}
215 232
@@ -219,12 +236,12 @@ static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
219 unsigned int isu = src_no >> mpic->isu_shift; 236 unsigned int isu = src_no >> mpic->isu_shift;
220 unsigned int idx = src_no & mpic->isu_mask; 237 unsigned int idx = src_no & mpic->isu_mask;
221 238
222 _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu], 239 _mpic_write(mpic->reg_type, &mpic->isus[isu],
223 reg + (idx * MPIC_INFO(IRQ_STRIDE)), value); 240 reg + (idx * MPIC_INFO(IRQ_STRIDE)), value);
224} 241}
225 242
226#define mpic_read(b,r) _mpic_read(mpic->flags & MPIC_BIG_ENDIAN,(b),(r)) 243#define mpic_read(b,r) _mpic_read(mpic->reg_type,&(b),(r))
227#define mpic_write(b,r,v) _mpic_write(mpic->flags & MPIC_BIG_ENDIAN,(b),(r),(v)) 244#define mpic_write(b,r,v) _mpic_write(mpic->reg_type,&(b),(r),(v))
228#define mpic_ipi_read(i) _mpic_ipi_read(mpic,(i)) 245#define mpic_ipi_read(i) _mpic_ipi_read(mpic,(i))
229#define mpic_ipi_write(i,v) _mpic_ipi_write(mpic,(i),(v)) 246#define mpic_ipi_write(i,v) _mpic_ipi_write(mpic,(i),(v))
230#define mpic_cpu_read(i) _mpic_cpu_read(mpic,(i)) 247#define mpic_cpu_read(i) _mpic_cpu_read(mpic,(i))
@@ -238,6 +255,38 @@ static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
238 */ 255 */
239 256
240 257
258static void _mpic_map_mmio(struct mpic *mpic, unsigned long phys_addr,
259 struct mpic_reg_bank *rb, unsigned int offset,
260 unsigned int size)
261{
262 rb->base = ioremap(phys_addr + offset, size);
263 BUG_ON(rb->base == NULL);
264}
265
266#ifdef CONFIG_PPC_DCR
267static void _mpic_map_dcr(struct mpic *mpic, struct mpic_reg_bank *rb,
268 unsigned int offset, unsigned int size)
269{
270 rb->dbase = mpic->dcr_base;
271 rb->doff = offset;
272 rb->dhost = dcr_map(mpic->of_node, rb->dbase + rb->doff, size);
273 BUG_ON(!DCR_MAP_OK(rb->dhost));
274}
275
276static inline void mpic_map(struct mpic *mpic, unsigned long phys_addr,
277 struct mpic_reg_bank *rb, unsigned int offset,
278 unsigned int size)
279{
280 if (mpic->flags & MPIC_USES_DCR)
281 _mpic_map_dcr(mpic, rb, offset, size);
282 else
283 _mpic_map_mmio(mpic, phys_addr, rb, offset, size);
284}
285#else /* CONFIG_PPC_DCR */
286#define mpic_map(m,p,b,o,s) _mpic_map_mmio(m,p,b,o,s)
287#endif /* !CONFIG_PPC_DCR */
288
289
241 290
242/* Check if we have one of those nice broken MPICs with a flipped endian on 291/* Check if we have one of those nice broken MPICs with a flipped endian on
243 * reads from IPI registers 292 * reads from IPI registers
@@ -845,7 +894,7 @@ static struct irq_host_ops mpic_host_ops = {
845 */ 894 */
846 895
847struct mpic * __init mpic_alloc(struct device_node *node, 896struct mpic * __init mpic_alloc(struct device_node *node,
848 unsigned long phys_addr, 897 phys_addr_t phys_addr,
849 unsigned int flags, 898 unsigned int flags,
850 unsigned int isu_size, 899 unsigned int isu_size,
851 unsigned int irq_count, 900 unsigned int irq_count,
@@ -855,6 +904,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
855 u32 reg; 904 u32 reg;
856 const char *vers; 905 const char *vers;
857 int i; 906 int i;
907 u64 paddr = phys_addr;
858 908
859 mpic = alloc_bootmem(sizeof(struct mpic)); 909 mpic = alloc_bootmem(sizeof(struct mpic));
860 if (mpic == NULL) 910 if (mpic == NULL)
@@ -883,6 +933,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
883 if (flags & MPIC_PRIMARY) 933 if (flags & MPIC_PRIMARY)
884 mpic->hc_ht_irq.set_affinity = mpic_set_affinity; 934 mpic->hc_ht_irq.set_affinity = mpic_set_affinity;
885#endif /* CONFIG_MPIC_BROKEN_U3 */ 935#endif /* CONFIG_MPIC_BROKEN_U3 */
936
886#ifdef CONFIG_SMP 937#ifdef CONFIG_SMP
887 mpic->hc_ipi = mpic_ipi_chip; 938 mpic->hc_ipi = mpic_ipi_chip;
888 mpic->hc_ipi.typename = name; 939 mpic->hc_ipi.typename = name;
@@ -893,15 +944,52 @@ struct mpic * __init mpic_alloc(struct device_node *node,
893 mpic->irq_count = irq_count; 944 mpic->irq_count = irq_count;
894 mpic->num_sources = 0; /* so far */ 945 mpic->num_sources = 0; /* so far */
895 946
947 /* Check for "big-endian" in device-tree */
948 if (node && get_property(node, "big-endian", NULL) != NULL)
949 mpic->flags |= MPIC_BIG_ENDIAN;
950
951
896#ifdef CONFIG_MPIC_WEIRD 952#ifdef CONFIG_MPIC_WEIRD
897 mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; 953 mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)];
898#endif 954#endif
899 955
956 /* default register type */
957 mpic->reg_type = (flags & MPIC_BIG_ENDIAN) ?
958 mpic_access_mmio_be : mpic_access_mmio_le;
959
960 /* If no physical address is passed in, a device-node is mandatory */
961 BUG_ON(paddr == 0 && node == NULL);
962
963 /* If no physical address passed in, check if it's dcr based */
964 if (paddr == 0 && get_property(node, "dcr-reg", NULL) != NULL)
965 mpic->flags |= MPIC_USES_DCR;
966
967#ifdef CONFIG_PPC_DCR
968 if (mpic->flags & MPIC_USES_DCR) {
969 const u32 *dbasep;
970 dbasep = get_property(node, "dcr-reg", NULL);
971 BUG_ON(dbasep == NULL);
972 mpic->dcr_base = *dbasep;
973 mpic->reg_type = mpic_access_dcr;
974 }
975#else
976 BUG_ON (mpic->flags & MPIC_USES_DCR);
977#endif /* CONFIG_PPC_DCR */
978
979 /* If the MPIC is not DCR based, and no physical address was passed
980 * in, try to obtain one
981 */
982 if (paddr == 0 && !(mpic->flags & MPIC_USES_DCR)) {
983 const u32 *reg;
984 reg = get_property(node, "reg", NULL);
985 BUG_ON(reg == NULL);
986 paddr = of_translate_address(node, reg);
987 BUG_ON(paddr == OF_BAD_ADDR);
988 }
989
900 /* Map the global registers */ 990 /* Map the global registers */
901 mpic->gregs = ioremap(phys_addr + MPIC_INFO(GREG_BASE), 0x1000); 991 mpic_map(mpic, paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000);
902 mpic->tmregs = mpic->gregs + 992 mpic_map(mpic, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
903 ((MPIC_INFO(TIMER_BASE) - MPIC_INFO(GREG_BASE)) >> 2);
904 BUG_ON(mpic->gregs == NULL);
905 993
906 /* Reset */ 994 /* Reset */
907 if (flags & MPIC_WANTS_RESET) { 995 if (flags & MPIC_WANTS_RESET) {
@@ -926,17 +1014,16 @@ struct mpic * __init mpic_alloc(struct device_node *node,
926 1014
927 /* Map the per-CPU registers */ 1015 /* Map the per-CPU registers */
928 for (i = 0; i < mpic->num_cpus; i++) { 1016 for (i = 0; i < mpic->num_cpus; i++) {
929 mpic->cpuregs[i] = ioremap(phys_addr + MPIC_INFO(CPU_BASE) + 1017 mpic_map(mpic, paddr, &mpic->cpuregs[i],
930 i * MPIC_INFO(CPU_STRIDE), 0x1000); 1018 MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE),
931 BUG_ON(mpic->cpuregs[i] == NULL); 1019 0x1000);
932 } 1020 }
933 1021
934 /* Initialize main ISU if none provided */ 1022 /* Initialize main ISU if none provided */
935 if (mpic->isu_size == 0) { 1023 if (mpic->isu_size == 0) {
936 mpic->isu_size = mpic->num_sources; 1024 mpic->isu_size = mpic->num_sources;
937 mpic->isus[0] = ioremap(phys_addr + MPIC_INFO(IRQ_BASE), 1025 mpic_map(mpic, paddr, &mpic->isus[0],
938 MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); 1026 MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
939 BUG_ON(mpic->isus[0] == NULL);
940 } 1027 }
941 mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); 1028 mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
942 mpic->isu_mask = (1 << mpic->isu_shift) - 1; 1029 mpic->isu_mask = (1 << mpic->isu_shift) - 1;
@@ -956,10 +1043,11 @@ struct mpic * __init mpic_alloc(struct device_node *node,
956 vers = "<unknown>"; 1043 vers = "<unknown>";
957 break; 1044 break;
958 } 1045 }
959 printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %lx, max %d CPUs\n", 1046 printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %llx,"
960 name, vers, phys_addr, mpic->num_cpus); 1047 " max %d CPUs\n",
961 printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n", mpic->isu_size, 1048 name, vers, (unsigned long long)paddr, mpic->num_cpus);
962 mpic->isu_shift, mpic->isu_mask); 1049 printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n",
1050 mpic->isu_size, mpic->isu_shift, mpic->isu_mask);
963 1051
964 mpic->next = mpics; 1052 mpic->next = mpics;
965 mpics = mpic; 1053 mpics = mpic;
@@ -973,14 +1061,14 @@ struct mpic * __init mpic_alloc(struct device_node *node,
973} 1061}
974 1062
975void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, 1063void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
976 unsigned long phys_addr) 1064 phys_addr_t paddr)
977{ 1065{
978 unsigned int isu_first = isu_num * mpic->isu_size; 1066 unsigned int isu_first = isu_num * mpic->isu_size;
979 1067
980 BUG_ON(isu_num >= MPIC_MAX_ISU); 1068 BUG_ON(isu_num >= MPIC_MAX_ISU);
981 1069
982 mpic->isus[isu_num] = ioremap(phys_addr, 1070 mpic_map(mpic, paddr, &mpic->isus[isu_num], 0,
983 MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); 1071 MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
984 if ((isu_first + mpic->isu_size) > mpic->num_sources) 1072 if ((isu_first + mpic->isu_size) > mpic->num_sources)
985 mpic->num_sources = isu_first + mpic->isu_size; 1073 mpic->num_sources = isu_first + mpic->isu_size;
986} 1074}
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index e4223226a7a8..e3d71e083f35 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -174,8 +174,7 @@ void qe_setbrg(u32 brg, u32 rate)
174 u32 divisor, tempval; 174 u32 divisor, tempval;
175 int div16 = 0; 175 int div16 = 0;
176 176
177 bp = &qe_immr->brg.brgc1; 177 bp = &qe_immr->brg.brgc[brg];
178 bp += brg;
179 178
180 divisor = (get_brg_clk() / rate); 179 divisor = (get_brg_clk() / rate);
181 if (divisor > QE_BRGC_DIVISOR_MAX + 1) { 180 if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
index 75fa3104a43a..e657559bea93 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
@@ -216,14 +216,12 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
216 return -EINVAL; 216 return -EINVAL;
217 } 217 }
218 218
219 uccf = (struct ucc_fast_private *) 219 uccf = kzalloc(sizeof(struct ucc_fast_private), GFP_KERNEL);
220 kmalloc(sizeof(struct ucc_fast_private), GFP_KERNEL);
221 if (!uccf) { 220 if (!uccf) {
222 uccf_err 221 uccf_err
223 ("ucc_fast_init: No memory for UCC slow data structure!"); 222 ("ucc_fast_init: No memory for UCC slow data structure!");
224 return -ENOMEM; 223 return -ENOMEM;
225 } 224 }
226 memset(uccf, 0, sizeof(struct ucc_fast_private));
227 225
228 /* Fill fast UCC structure */ 226 /* Fill fast UCC structure */
229 uccf->uf_info = uf_info; 227 uccf->uf_info = uf_info;
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
index a49da6b73ecf..47b56203f47e 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_slow.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
@@ -168,14 +168,12 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
168 return -EINVAL; 168 return -EINVAL;
169 } 169 }
170 170
171 uccs = (struct ucc_slow_private *) 171 uccs = kzalloc(sizeof(struct ucc_slow_private), GFP_KERNEL);
172 kmalloc(sizeof(struct ucc_slow_private), GFP_KERNEL);
173 if (!uccs) { 172 if (!uccs) {
174 uccs_err 173 uccs_err
175 ("ucc_slow_init: No memory for UCC slow data structure!"); 174 ("ucc_slow_init: No memory for UCC slow data structure!");
176 return -ENOMEM; 175 return -ENOMEM;
177 } 176 }
178 memset(uccs, 0, sizeof(struct ucc_slow_private));
179 177
180 /* Fill slow UCC structure */ 178 /* Fill slow UCC structure */
181 uccs->us_info = us_info; 179 uccs->us_info = us_info;
diff --git a/arch/powerpc/sysdev/rom.c b/arch/powerpc/sysdev/rom.c
new file mode 100644
index 000000000000..bf5b3f10e6c6
--- /dev/null
+++ b/arch/powerpc/sysdev/rom.c
@@ -0,0 +1,31 @@
1/*
2 * ROM device registration
3 *
4 * (C) 2006 MontaVista Software, Inc. This file is licensed under
5 * the terms of the GNU General Public License version 2. This program
6 * is licensed "as is" without any warranty of any kind, whether express
7 * or implied.
8 */
9
10#include <linux/kernel.h>
11#include <asm/of_device.h>
12
13static int __init powerpc_flash_init(void)
14{
15 struct device_node *node = NULL;
16
17 /*
18 * Register all the devices which type is "rom"
19 */
20 while ((node = of_find_node_by_type(node, "rom")) != NULL) {
21 if (node->name == NULL) {
22 printk(KERN_WARNING "powerpc_flash_init: found 'rom' "
23 "device, but with no name, skipping...\n");
24 continue;
25 }
26 of_platform_device_create(node, node->name, NULL);
27 }
28 return 0;
29}
30
31arch_initcall(powerpc_flash_init);
diff --git a/arch/powerpc/sysdev/todc.c b/arch/powerpc/sysdev/todc.c
deleted file mode 100644
index 0a65980efb50..000000000000
--- a/arch/powerpc/sysdev/todc.c
+++ /dev/null
@@ -1,392 +0,0 @@
1/*
2 * Time of Day Clock support for the M48T35, M48T37, M48T59, and MC146818
3 * Real Time Clocks/Timekeepers.
4 *
5 * Author: Mark A. Greer <mgreer@mvista.com>
6 *
7 * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
8 * the terms of the GNU General Public License version 2. This program
9 * is licensed "as is" without any warranty of any kind, whether express
10 * or implied.
11 */
12#include <linux/errno.h>
13#include <linux/init.h>
14#include <linux/kernel.h>
15#include <linux/time.h>
16#include <linux/timex.h>
17#include <linux/bcd.h>
18#include <linux/mc146818rtc.h>
19
20#include <asm/machdep.h>
21#include <asm/io.h>
22#include <asm/time.h>
23#include <asm/todc.h>
24
25/*
26 * Depending on the hardware on your board and your board design, the
27 * RTC/NVRAM may be accessed either directly (like normal memory) or via
28 * address/data registers. If your board uses the direct method, set
29 * 'nvram_data' to the base address of your nvram and leave 'nvram_as0' and
30 * 'nvram_as1' NULL. If your board uses address/data regs to access nvram,
31 * set 'nvram_as0' to the address of the lower byte, set 'nvram_as1' to the
32 * address of the upper byte (leave NULL if using mc146818), and set
33 * 'nvram_data' to the address of the 8-bit data register.
34 *
35 * Note: Even though the documentation for the various RTC chips say that it
36 * take up to a second before it starts updating once the 'R' bit is
37 * cleared, they always seem to update even though we bang on it many
38 * times a second. This is true, except for the Dallas Semi 1746/1747
39 * (possibly others). Those chips seem to have a real problem whenever
40 * we set the 'R' bit before reading them, they basically stop counting.
41 * --MAG
42 */
43
44/*
45 * 'todc_info' should be initialized in your *_setup.c file to
46 * point to a fully initialized 'todc_info_t' structure.
47 * This structure holds all the register offsets for your particular
48 * TODC/RTC chip.
49 * TODC_ALLOC()/TODC_INIT() will allocate and initialize this table for you.
50 */
51
52#ifdef RTC_FREQ_SELECT
53#undef RTC_FREQ_SELECT
54#define RTC_FREQ_SELECT control_b /* Register A */
55#endif
56
57#ifdef RTC_CONTROL
58#undef RTC_CONTROL
59#define RTC_CONTROL control_a /* Register B */
60#endif
61
62#ifdef RTC_INTR_FLAGS
63#undef RTC_INTR_FLAGS
64#define RTC_INTR_FLAGS watchdog /* Register C */
65#endif
66
67#ifdef RTC_VALID
68#undef RTC_VALID
69#define RTC_VALID interrupts /* Register D */
70#endif
71
72/* Access routines when RTC accessed directly (like normal memory) */
73u_char
74todc_direct_read_val(int addr)
75{
76 return readb((void __iomem *)(todc_info->nvram_data + addr));
77}
78
79void
80todc_direct_write_val(int addr, unsigned char val)
81{
82 writeb(val, (void __iomem *)(todc_info->nvram_data + addr));
83 return;
84}
85
86/* Access routines for accessing m48txx type chips via addr/data regs */
87u_char
88todc_m48txx_read_val(int addr)
89{
90 outb(addr, todc_info->nvram_as0);
91 outb(addr>>todc_info->as0_bits, todc_info->nvram_as1);
92 return inb(todc_info->nvram_data);
93}
94
95void
96todc_m48txx_write_val(int addr, unsigned char val)
97{
98 outb(addr, todc_info->nvram_as0);
99 outb(addr>>todc_info->as0_bits, todc_info->nvram_as1);
100 outb(val, todc_info->nvram_data);
101 return;
102}
103
104/* Access routines for accessing mc146818 type chips via addr/data regs */
105u_char
106todc_mc146818_read_val(int addr)
107{
108 outb_p(addr, todc_info->nvram_as0);
109 return inb_p(todc_info->nvram_data);
110}
111
112void
113todc_mc146818_write_val(int addr, unsigned char val)
114{
115 outb_p(addr, todc_info->nvram_as0);
116 outb_p(val, todc_info->nvram_data);
117}
118
119
120/*
121 * Routines to make RTC chips with NVRAM buried behind an addr/data pair
122 * have the NVRAM and clock regs appear at the same level.
123 * The NVRAM will appear to start at addr 0 and the clock regs will appear
124 * to start immediately after the NVRAM (actually, start at offset
125 * todc_info->nvram_size).
126 */
127static inline u_char
128todc_read_val(int addr)
129{
130 u_char val;
131
132 if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) {
133 if (addr < todc_info->nvram_size) { /* NVRAM */
134 ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr);
135 val = ppc_md.rtc_read_val(todc_info->nvram_data_reg);
136 } else { /* Clock Reg */
137 addr -= todc_info->nvram_size;
138 val = ppc_md.rtc_read_val(addr);
139 }
140 } else
141 val = ppc_md.rtc_read_val(addr);
142
143 return val;
144}
145
146static inline void
147todc_write_val(int addr, u_char val)
148{
149 if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) {
150 if (addr < todc_info->nvram_size) { /* NVRAM */
151 ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr);
152 ppc_md.rtc_write_val(todc_info->nvram_data_reg, val);
153 } else { /* Clock Reg */
154 addr -= todc_info->nvram_size;
155 ppc_md.rtc_write_val(addr, val);
156 }
157 } else
158 ppc_md.rtc_write_val(addr, val);
159}
160
161/*
162 * TODC routines
163 *
164 * There is some ugly stuff in that there are assumptions for the mc146818.
165 *
166 * Assumptions:
167 * - todc_info->control_a has the offset as mc146818 Register B reg
168 * - todc_info->control_b has the offset as mc146818 Register A reg
169 * - m48txx control reg's write enable or 'W' bit is same as
170 * mc146818 Register B 'SET' bit (i.e., 0x80)
171 *
172 * These assumptions were made to make the code simpler.
173 */
174long __init
175todc_time_init(void)
176{
177 u_char cntl_b;
178
179 if (!ppc_md.rtc_read_val)
180 ppc_md.rtc_read_val = ppc_md.nvram_read_val;
181 if (!ppc_md.rtc_write_val)
182 ppc_md.rtc_write_val = ppc_md.nvram_write_val;
183
184 cntl_b = todc_read_val(todc_info->control_b);
185
186 if (todc_info->rtc_type == TODC_TYPE_MC146818) {
187 if ((cntl_b & 0x70) != 0x20) {
188 printk(KERN_INFO "TODC real-time-clock was stopped."
189 " Now starting...");
190 cntl_b &= ~0x70;
191 cntl_b |= 0x20;
192 }
193
194 todc_write_val(todc_info->control_b, cntl_b);
195 } else if (todc_info->rtc_type == TODC_TYPE_DS17285) {
196 u_char mode;
197
198 mode = todc_read_val(TODC_TYPE_DS17285_CNTL_A);
199 /* Make sure countdown clear is not set */
200 mode &= ~0x40;
201 /* Enable oscillator, extended register set */
202 mode |= 0x30;
203 todc_write_val(TODC_TYPE_DS17285_CNTL_A, mode);
204
205 } else if (todc_info->rtc_type == TODC_TYPE_DS1501) {
206 u_char month;
207
208 todc_info->enable_read = TODC_DS1501_CNTL_B_TE;
209 todc_info->enable_write = TODC_DS1501_CNTL_B_TE;
210
211 month = todc_read_val(todc_info->month);
212
213 if ((month & 0x80) == 0x80) {
214 printk(KERN_INFO "TODC %s %s\n",
215 "real-time-clock was stopped.",
216 "Now starting...");
217 month &= ~0x80;
218 todc_write_val(todc_info->month, month);
219 }
220
221 cntl_b &= ~TODC_DS1501_CNTL_B_TE;
222 todc_write_val(todc_info->control_b, cntl_b);
223 } else { /* must be a m48txx type */
224 u_char cntl_a;
225
226 todc_info->enable_read = TODC_MK48TXX_CNTL_A_R;
227 todc_info->enable_write = TODC_MK48TXX_CNTL_A_W;
228
229 cntl_a = todc_read_val(todc_info->control_a);
230
231 /* Check & clear STOP bit in control B register */
232 if (cntl_b & TODC_MK48TXX_DAY_CB) {
233 printk(KERN_INFO "TODC %s %s\n",
234 "real-time-clock was stopped.",
235 "Now starting...");
236
237 cntl_a |= todc_info->enable_write;
238 cntl_b &= ~TODC_MK48TXX_DAY_CB;/* Start Oscil */
239
240 todc_write_val(todc_info->control_a, cntl_a);
241 todc_write_val(todc_info->control_b, cntl_b);
242 }
243
244 /* Make sure READ & WRITE bits are cleared. */
245 cntl_a &= ~(todc_info->enable_write | todc_info->enable_read);
246 todc_write_val(todc_info->control_a, cntl_a);
247 }
248
249 return 0;
250}
251
252/*
253 * There is some ugly stuff in that there are assumptions that for a mc146818,
254 * the todc_info->control_a has the offset of the mc146818 Register B reg and
255 * that the register'ss 'SET' bit is the same as the m48txx's write enable
256 * bit in the control register of the m48txx (i.e., 0x80).
257 *
258 * It was done to make the code look simpler.
259 */
260void
261todc_get_rtc_time(struct rtc_time *tm)
262{
263 uint year = 0, mon = 0, mday = 0, hour = 0, min = 0, sec = 0;
264 uint limit, i;
265 u_char save_control, uip = 0;
266 extern void GregorianDay(struct rtc_time *);
267
268 spin_lock(&rtc_lock);
269 save_control = todc_read_val(todc_info->control_a);
270
271 if (todc_info->rtc_type != TODC_TYPE_MC146818) {
272 limit = 1;
273
274 switch (todc_info->rtc_type) {
275 case TODC_TYPE_DS1553:
276 case TODC_TYPE_DS1557:
277 case TODC_TYPE_DS1743:
278 case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */
279 case TODC_TYPE_DS1747:
280 case TODC_TYPE_DS17285:
281 break;
282 default:
283 todc_write_val(todc_info->control_a,
284 (save_control | todc_info->enable_read));
285 }
286 } else
287 limit = 100000000;
288
289 for (i=0; i<limit; i++) {
290 if (todc_info->rtc_type == TODC_TYPE_MC146818)
291 uip = todc_read_val(todc_info->RTC_FREQ_SELECT);
292
293 sec = todc_read_val(todc_info->seconds) & 0x7f;
294 min = todc_read_val(todc_info->minutes) & 0x7f;
295 hour = todc_read_val(todc_info->hours) & 0x3f;
296 mday = todc_read_val(todc_info->day_of_month) & 0x3f;
297 mon = todc_read_val(todc_info->month) & 0x1f;
298 year = todc_read_val(todc_info->year) & 0xff;
299
300 if (todc_info->rtc_type == TODC_TYPE_MC146818) {
301 uip |= todc_read_val(todc_info->RTC_FREQ_SELECT);
302 if ((uip & RTC_UIP) == 0)
303 break;
304 }
305 }
306
307 if (todc_info->rtc_type != TODC_TYPE_MC146818) {
308 switch (todc_info->rtc_type) {
309 case TODC_TYPE_DS1553:
310 case TODC_TYPE_DS1557:
311 case TODC_TYPE_DS1743:
312 case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */
313 case TODC_TYPE_DS1747:
314 case TODC_TYPE_DS17285:
315 break;
316 default:
317 save_control &= ~(todc_info->enable_read);
318 todc_write_val(todc_info->control_a, save_control);
319 }
320 }
321 spin_unlock(&rtc_lock);
322
323 if ((todc_info->rtc_type != TODC_TYPE_MC146818)
324 || ((save_control & RTC_DM_BINARY) == 0)
325 || RTC_ALWAYS_BCD) {
326 BCD_TO_BIN(sec);
327 BCD_TO_BIN(min);
328 BCD_TO_BIN(hour);
329 BCD_TO_BIN(mday);
330 BCD_TO_BIN(mon);
331 BCD_TO_BIN(year);
332 }
333
334 if ((year + 1900) < 1970) {
335 year += 100;
336 }
337
338 tm->tm_sec = sec;
339 tm->tm_min = min;
340 tm->tm_hour = hour;
341 tm->tm_mday = mday;
342 tm->tm_mon = mon;
343 tm->tm_year = year;
344
345 GregorianDay(tm);
346}
347
348int
349todc_set_rtc_time(struct rtc_time *tm)
350{
351 u_char save_control, save_freq_select = 0;
352
353 spin_lock(&rtc_lock);
354 save_control = todc_read_val(todc_info->control_a);
355
356 /* Assuming MK48T59_RTC_CA_WRITE & RTC_SET are equal */
357 todc_write_val(todc_info->control_a,
358 (save_control | todc_info->enable_write));
359 save_control &= ~(todc_info->enable_write); /* in case it was set */
360
361 if (todc_info->rtc_type == TODC_TYPE_MC146818) {
362 save_freq_select = todc_read_val(todc_info->RTC_FREQ_SELECT);
363 todc_write_val(todc_info->RTC_FREQ_SELECT,
364 save_freq_select | RTC_DIV_RESET2);
365 }
366
367 if ((todc_info->rtc_type != TODC_TYPE_MC146818)
368 || ((save_control & RTC_DM_BINARY) == 0)
369 || RTC_ALWAYS_BCD) {
370 BIN_TO_BCD(tm->tm_sec);
371 BIN_TO_BCD(tm->tm_min);
372 BIN_TO_BCD(tm->tm_hour);
373 BIN_TO_BCD(tm->tm_mon);
374 BIN_TO_BCD(tm->tm_mday);
375 BIN_TO_BCD(tm->tm_year);
376 }
377
378 todc_write_val(todc_info->seconds, tm->tm_sec);
379 todc_write_val(todc_info->minutes, tm->tm_min);
380 todc_write_val(todc_info->hours, tm->tm_hour);
381 todc_write_val(todc_info->month, tm->tm_mon);
382 todc_write_val(todc_info->day_of_month, tm->tm_mday);
383 todc_write_val(todc_info->year, tm->tm_year);
384
385 todc_write_val(todc_info->control_a, save_control);
386
387 if (todc_info->rtc_type == TODC_TYPE_MC146818)
388 todc_write_val(todc_info->RTC_FREQ_SELECT, save_freq_select);
389
390 spin_unlock(&rtc_lock);
391 return 0;
392}
diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c
index 322f86e93de5..ae249c6bbbcf 100644
--- a/arch/powerpc/sysdev/tsi108_pci.c
+++ b/arch/powerpc/sysdev/tsi108_pci.c
@@ -3,6 +3,8 @@
3 * 3 *
4 * 2004-2005 (c) Tundra Semiconductor Corp. 4 * 2004-2005 (c) Tundra Semiconductor Corp.
5 * Author: Alex Bounine (alexandreb@tundra.com) 5 * Author: Alex Bounine (alexandreb@tundra.com)
6 * Author: Roy Zang (tie-fei.zang@freescale.com)
7 * Add pci interrupt router host
6 * 8 *
7 * This program is free software; you can redistribute it and/or modify it 9 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free 10 * under the terms of the GNU General Public License as published by the Free
@@ -48,6 +50,8 @@
48 50
49u32 tsi108_pci_cfg_base; 51u32 tsi108_pci_cfg_base;
50u32 tsi108_csr_vir_base; 52u32 tsi108_csr_vir_base;
53static struct device_node *pci_irq_node;
54static struct irq_host *pci_irq_host;
51 55
52extern u32 get_vir_csrbase(void); 56extern u32 get_vir_csrbase(void);
53extern u32 tsi108_read_reg(u32 reg_offset); 57extern u32 tsi108_read_reg(u32 reg_offset);
@@ -378,6 +382,38 @@ static struct irq_chip tsi108_pci_irq = {
378 .unmask = tsi108_pci_irq_enable, 382 .unmask = tsi108_pci_irq_enable,
379}; 383};
380 384
385static int pci_irq_host_xlate(struct irq_host *h, struct device_node *ct,
386 u32 *intspec, unsigned int intsize,
387 irq_hw_number_t *out_hwirq, unsigned int *out_flags)
388{
389 *out_hwirq = intspec[0];
390 *out_flags = IRQ_TYPE_LEVEL_HIGH;
391 return 0;
392}
393
394static int pci_irq_host_map(struct irq_host *h, unsigned int virq,
395 irq_hw_number_t hw)
396{ unsigned int irq;
397 DBG("%s(%d, 0x%lx)\n", __FUNCTION__, virq, hw);
398 if ((virq >= 1) && (virq <= 4)){
399 irq = virq + IRQ_PCI_INTAD_BASE - 1;
400 get_irq_desc(irq)->status |= IRQ_LEVEL;
401 set_irq_chip(irq, &tsi108_pci_irq);
402 }
403 return 0;
404}
405
406static int pci_irq_host_match(struct irq_host *h, struct device_node *node)
407{
408 return pci_irq_node == node;
409}
410
411static struct irq_host_ops pci_irq_host_ops = {
412 .match = pci_irq_host_match,
413 .map = pci_irq_host_map,
414 .xlate = pci_irq_host_xlate,
415};
416
381/* 417/*
382 * Exported functions 418 * Exported functions
383 */ 419 */
@@ -391,15 +427,15 @@ static struct irq_chip tsi108_pci_irq = {
391 * to the MPIC. 427 * to the MPIC.
392 */ 428 */
393 429
394void __init tsi108_pci_int_init(void) 430void __init tsi108_pci_int_init(struct device_node *node)
395{ 431{
396 u_int i;
397
398 DBG("Tsi108_pci_int_init: initializing PCI interrupts\n"); 432 DBG("Tsi108_pci_int_init: initializing PCI interrupts\n");
399 433
400 for (i = 0; i < NUM_PCI_IRQS; i++) { 434 pci_irq_node = of_node_get(node);
401 irq_desc[i + IRQ_PCI_INTAD_BASE].chip = &tsi108_pci_irq; 435 pci_irq_host = irq_alloc_host(IRQ_HOST_MAP_LEGACY, 0, &pci_irq_host_ops, 0);
402 irq_desc[i + IRQ_PCI_INTAD_BASE].status |= IRQ_LEVEL; 436 if (pci_irq_host == NULL) {
437 printk(KERN_ERR "pci_irq_host: failed to allocate irq host !\n");
438 return;
403 } 439 }
404 440
405 init_pci_source(); 441 init_pci_source();
diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile
index 109d874ecfbe..51d97588e762 100644
--- a/arch/powerpc/xmon/Makefile
+++ b/arch/powerpc/xmon/Makefile
@@ -3,5 +3,10 @@
3ifdef CONFIG_PPC64 3ifdef CONFIG_PPC64
4EXTRA_CFLAGS += -mno-minimal-toc 4EXTRA_CFLAGS += -mno-minimal-toc
5endif 5endif
6obj-y += xmon.o ppc-dis.o ppc-opc.o setjmp.o start.o \ 6
7 nonstdio.o 7obj-y += xmon.o setjmp.o start.o nonstdio.o
8
9ifdef CONFIG_XMON_DISASSEMBLY
10obj-y += ppc-dis.o ppc-opc.o
11obj-$(CONFIG_SPU_BASE) += spu-dis.o spu-opc.o
12endif
diff --git a/arch/powerpc/xmon/dis-asm.h b/arch/powerpc/xmon/dis-asm.h
new file mode 100644
index 000000000000..be3533b93f30
--- /dev/null
+++ b/arch/powerpc/xmon/dis-asm.h
@@ -0,0 +1,31 @@
1#ifndef _POWERPC_XMON_DIS_ASM_H
2#define _POWERPC_XMON_DIS_ASM_H
3/*
4 * Copyright (C) 2006 Michael Ellerman, IBM Corporation.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12extern void print_address (unsigned long memaddr);
13
14#ifdef CONFIG_XMON_DISASSEMBLY
15extern int print_insn_powerpc(unsigned long insn, unsigned long memaddr);
16extern int print_insn_spu(unsigned long insn, unsigned long memaddr);
17#else
18static inline int print_insn_powerpc(unsigned long insn, unsigned long memaddr)
19{
20 printf("%.8x", insn);
21 return 0;
22}
23
24static inline int print_insn_spu(unsigned long insn, unsigned long memaddr)
25{
26 printf("%.8x", insn);
27 return 0;
28}
29#endif
30
31#endif /* _POWERPC_XMON_DIS_ASM_H */
diff --git a/arch/powerpc/xmon/ppc-dis.c b/arch/powerpc/xmon/ppc-dis.c
index ac0a9d2427e0..89098f320ad5 100644
--- a/arch/powerpc/xmon/ppc-dis.c
+++ b/arch/powerpc/xmon/ppc-dis.c
@@ -1,5 +1,6 @@
1/* ppc-dis.c -- Disassemble PowerPC instructions 1/* ppc-dis.c -- Disassemble PowerPC instructions
2 Copyright 1994 Free Software Foundation, Inc. 2 Copyright 1994, 1995, 2000, 2001, 2002, 2003, 2004, 2005, 2006
3 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Cygnus Support 4 Written by Ian Lance Taylor, Cygnus Support
4 5
5This file is part of GDB, GAS, and the GNU binutils. 6This file is part of GDB, GAS, and the GNU binutils.
@@ -16,27 +17,36 @@ the GNU General Public License for more details.
16 17
17You should have received a copy of the GNU General Public License 18You should have received a copy of the GNU General Public License
18along with this file; see the file COPYING. If not, write to the Free 19along with this file; see the file COPYING. If not, write to the Free
19Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 20Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
20 21
22#include <asm/cputable.h>
21#include "nonstdio.h" 23#include "nonstdio.h"
22#include "ansidecl.h" 24#include "ansidecl.h"
23#include "ppc.h" 25#include "ppc.h"
24 26#include "dis-asm.h"
25extern void print_address (unsigned long memaddr);
26 27
27/* Print a PowerPC or POWER instruction. */ 28/* Print a PowerPC or POWER instruction. */
28 29
29int 30int
30print_insn_powerpc (unsigned long insn, unsigned long memaddr, int dialect) 31print_insn_powerpc (unsigned long insn, unsigned long memaddr)
31{ 32{
32 const struct powerpc_opcode *opcode; 33 const struct powerpc_opcode *opcode;
33 const struct powerpc_opcode *opcode_end; 34 const struct powerpc_opcode *opcode_end;
34 unsigned long op; 35 unsigned long op;
36 int dialect;
35 37
36 if (dialect == 0) 38 dialect = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_COMMON
37 dialect = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_COMMON
38 | PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_ALTIVEC; 39 | PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_ALTIVEC;
39 40
41 if (cpu_has_feature(CPU_FTRS_POWER5))
42 dialect |= PPC_OPCODE_POWER5;
43
44 if (cpu_has_feature(CPU_FTRS_CELL))
45 dialect |= PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC;
46
47 if (cpu_has_feature(CPU_FTRS_POWER6))
48 dialect |= PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC;
49
40 /* Get the major opcode of the instruction. */ 50 /* Get the major opcode of the instruction. */
41 op = PPC_OP (insn); 51 op = PPC_OP (insn);
42 52
@@ -121,7 +131,8 @@ print_insn_powerpc (unsigned long insn, unsigned long memaddr, int dialect)
121 } 131 }
122 132
123 /* Print the operand as directed by the flags. */ 133 /* Print the operand as directed by the flags. */
124 if ((operand->flags & PPC_OPERAND_GPR) != 0) 134 if ((operand->flags & PPC_OPERAND_GPR) != 0
135 || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
125 printf("r%ld", value); 136 printf("r%ld", value);
126 else if ((operand->flags & PPC_OPERAND_FPR) != 0) 137 else if ((operand->flags & PPC_OPERAND_FPR) != 0)
127 printf("f%ld", value); 138 printf("f%ld", value);
@@ -137,7 +148,7 @@ print_insn_powerpc (unsigned long insn, unsigned long memaddr, int dialect)
137 else 148 else
138 { 149 {
139 if (operand->bits == 3) 150 if (operand->bits == 3)
140 printf("cr%d", value); 151 printf("cr%ld", value);
141 else 152 else
142 { 153 {
143 static const char *cbnames[4] = { "lt", "gt", "eq", "so" }; 154 static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
diff --git a/arch/powerpc/xmon/ppc-opc.c b/arch/powerpc/xmon/ppc-opc.c
index 5ee8fc32f824..5d841f4b3530 100644
--- a/arch/powerpc/xmon/ppc-opc.c
+++ b/arch/powerpc/xmon/ppc-opc.c
@@ -1,6 +1,6 @@
1/* ppc-opc.c -- PowerPC opcode list 1/* ppc-opc.c -- PowerPC opcode list
2 Copyright 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003 2 Copyright 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004,
3 Free Software Foundation, Inc. 3 2005 Free Software Foundation, Inc.
4 Written by Ian Lance Taylor, Cygnus Support 4 Written by Ian Lance Taylor, Cygnus Support
5 5
6 This file is part of GDB, GAS, and the GNU binutils. 6 This file is part of GDB, GAS, and the GNU binutils.
@@ -17,8 +17,8 @@
17 17
18 You should have received a copy of the GNU General Public License 18 You should have received a copy of the GNU General Public License
19 along with this file; see the file COPYING. If not, write to the Free 19 along with this file; see the file COPYING. If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 20 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
21 02111-1307, USA. */ 21 02110-1301, USA. */
22 22
23#include <linux/stddef.h> 23#include <linux/stddef.h>
24#include "nonstdio.h" 24#include "nonstdio.h"
@@ -86,6 +86,8 @@ static unsigned long insert_sh6 (unsigned long, long, int, const char **);
86static long extract_sh6 (unsigned long, int, int *); 86static long extract_sh6 (unsigned long, int, int *);
87static unsigned long insert_spr (unsigned long, long, int, const char **); 87static unsigned long insert_spr (unsigned long, long, int, const char **);
88static long extract_spr (unsigned long, int, int *); 88static long extract_spr (unsigned long, int, int *);
89static unsigned long insert_sprg (unsigned long, long, int, const char **);
90static long extract_sprg (unsigned long, int, int *);
89static unsigned long insert_tbr (unsigned long, long, int, const char **); 91static unsigned long insert_tbr (unsigned long, long, int, const char **);
90static long extract_tbr (unsigned long, int, int *); 92static long extract_tbr (unsigned long, int, int *);
91static unsigned long insert_ev2 (unsigned long, long, int, const char **); 93static unsigned long insert_ev2 (unsigned long, long, int, const char **);
@@ -196,8 +198,11 @@ const struct powerpc_operand powerpc_operands[] =
196#define BOE BO + 1 198#define BOE BO + 1
197 { 5, 21, insert_boe, extract_boe, 0 }, 199 { 5, 21, insert_boe, extract_boe, 0 },
198 200
201#define BH BOE + 1
202 { 2, 11, NULL, NULL, PPC_OPERAND_OPTIONAL },
203
199 /* The BT field in an X or XL form instruction. */ 204 /* The BT field in an X or XL form instruction. */
200#define BT BOE + 1 205#define BT BH + 1
201 { 5, 21, NULL, NULL, PPC_OPERAND_CR }, 206 { 5, 21, NULL, NULL, PPC_OPERAND_CR },
202 207
203 /* The condition register number portion of the BI field in a B form 208 /* The condition register number portion of the BI field in a B form
@@ -301,10 +306,14 @@ const struct powerpc_operand powerpc_operands[] =
301#define L FXM4 + 1 306#define L FXM4 + 1
302 { 1, 21, NULL, NULL, PPC_OPERAND_OPTIONAL }, 307 { 1, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
303 308
304 /* The LEV field in a POWER SC form instruction. */ 309 /* The LEV field in a POWER SVC form instruction. */
305#define LEV L + 1 310#define SVC_LEV L + 1
306 { 7, 5, NULL, NULL, 0 }, 311 { 7, 5, NULL, NULL, 0 },
307 312
313 /* The LEV field in an SC form instruction. */
314#define LEV SVC_LEV + 1
315 { 7, 5, NULL, NULL, PPC_OPERAND_OPTIONAL },
316
308 /* The LI field in an I form instruction. The lower two bits are 317 /* The LI field in an I form instruction. The lower two bits are
309 forced to zero. */ 318 forced to zero. */
310#define LI LEV + 1 319#define LI LEV + 1
@@ -346,7 +355,7 @@ const struct powerpc_operand powerpc_operands[] =
346 355
347 /* The MO field in an mbar instruction. */ 356 /* The MO field in an mbar instruction. */
348#define MO MB6 + 1 357#define MO MB6 + 1
349 { 5, 21, NULL, NULL, 0 }, 358 { 5, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
350 359
351 /* The NB field in an X form instruction. The value 32 is stored as 360 /* The NB field in an X form instruction. The value 32 is stored as
352 0. */ 361 0. */
@@ -364,30 +373,38 @@ const struct powerpc_operand powerpc_operands[] =
364#define RA_MASK (0x1f << 16) 373#define RA_MASK (0x1f << 16)
365 { 5, 16, NULL, NULL, PPC_OPERAND_GPR }, 374 { 5, 16, NULL, NULL, PPC_OPERAND_GPR },
366 375
376 /* As above, but 0 in the RA field means zero, not r0. */
377#define RA0 RA + 1
378 { 5, 16, NULL, NULL, PPC_OPERAND_GPR_0 },
379
367 /* The RA field in the DQ form lq instruction, which has special 380 /* The RA field in the DQ form lq instruction, which has special
368 value restrictions. */ 381 value restrictions. */
369#define RAQ RA + 1 382#define RAQ RA0 + 1
370 { 5, 16, insert_raq, NULL, PPC_OPERAND_GPR }, 383 { 5, 16, insert_raq, NULL, PPC_OPERAND_GPR_0 },
371 384
372 /* The RA field in a D or X form instruction which is an updating 385 /* The RA field in a D or X form instruction which is an updating
373 load, which means that the RA field may not be zero and may not 386 load, which means that the RA field may not be zero and may not
374 equal the RT field. */ 387 equal the RT field. */
375#define RAL RAQ + 1 388#define RAL RAQ + 1
376 { 5, 16, insert_ral, NULL, PPC_OPERAND_GPR }, 389 { 5, 16, insert_ral, NULL, PPC_OPERAND_GPR_0 },
377 390
378 /* The RA field in an lmw instruction, which has special value 391 /* The RA field in an lmw instruction, which has special value
379 restrictions. */ 392 restrictions. */
380#define RAM RAL + 1 393#define RAM RAL + 1
381 { 5, 16, insert_ram, NULL, PPC_OPERAND_GPR }, 394 { 5, 16, insert_ram, NULL, PPC_OPERAND_GPR_0 },
382 395
383 /* The RA field in a D or X form instruction which is an updating 396 /* The RA field in a D or X form instruction which is an updating
384 store or an updating floating point load, which means that the RA 397 store or an updating floating point load, which means that the RA
385 field may not be zero. */ 398 field may not be zero. */
386#define RAS RAM + 1 399#define RAS RAM + 1
387 { 5, 16, insert_ras, NULL, PPC_OPERAND_GPR }, 400 { 5, 16, insert_ras, NULL, PPC_OPERAND_GPR_0 },
401
402 /* The RA field of the tlbwe instruction, which is optional. */
403#define RAOPT RAS + 1
404 { 5, 16, NULL, NULL, PPC_OPERAND_GPR | PPC_OPERAND_OPTIONAL },
388 405
389 /* The RB field in an X, XO, M, or MDS form instruction. */ 406 /* The RB field in an X, XO, M, or MDS form instruction. */
390#define RB RAS + 1 407#define RB RAOPT + 1
391#define RB_MASK (0x1f << 11) 408#define RB_MASK (0x1f << 11)
392 { 5, 11, NULL, NULL, PPC_OPERAND_GPR }, 409 { 5, 11, NULL, NULL, PPC_OPERAND_GPR },
393 410
@@ -408,15 +425,20 @@ const struct powerpc_operand powerpc_operands[] =
408 /* The RS field of the DS form stq instruction, which has special 425 /* The RS field of the DS form stq instruction, which has special
409 value restrictions. */ 426 value restrictions. */
410#define RSQ RS + 1 427#define RSQ RS + 1
411 { 5, 21, insert_rsq, NULL, PPC_OPERAND_GPR }, 428 { 5, 21, insert_rsq, NULL, PPC_OPERAND_GPR_0 },
412 429
413 /* The RT field of the DQ form lq instruction, which has special 430 /* The RT field of the DQ form lq instruction, which has special
414 value restrictions. */ 431 value restrictions. */
415#define RTQ RSQ + 1 432#define RTQ RSQ + 1
416 { 5, 21, insert_rtq, NULL, PPC_OPERAND_GPR }, 433 { 5, 21, insert_rtq, NULL, PPC_OPERAND_GPR_0 },
434
435 /* The RS field of the tlbwe instruction, which is optional. */
436#define RSO RTQ + 1
437#define RTO RSO
438 { 5, 21, NULL, NULL, PPC_OPERAND_GPR | PPC_OPERAND_OPTIONAL },
417 439
418 /* The SH field in an X or M form instruction. */ 440 /* The SH field in an X or M form instruction. */
419#define SH RTQ + 1 441#define SH RSO + 1
420#define SH_MASK (0x1f << 11) 442#define SH_MASK (0x1f << 11)
421 { 5, 11, NULL, NULL, 0 }, 443 { 5, 11, NULL, NULL, 0 },
422 444
@@ -425,8 +447,12 @@ const struct powerpc_operand powerpc_operands[] =
425#define SH6_MASK ((0x1f << 11) | (1 << 1)) 447#define SH6_MASK ((0x1f << 11) | (1 << 1))
426 { 6, 1, insert_sh6, extract_sh6, 0 }, 448 { 6, 1, insert_sh6, extract_sh6, 0 },
427 449
450 /* The SH field of the tlbwe instruction, which is optional. */
451#define SHO SH6 + 1
452 { 5, 11,NULL, NULL, PPC_OPERAND_OPTIONAL },
453
428 /* The SI field in a D form instruction. */ 454 /* The SI field in a D form instruction. */
429#define SI SH6 + 1 455#define SI SHO + 1
430 { 16, 0, NULL, NULL, PPC_OPERAND_SIGNED }, 456 { 16, 0, NULL, NULL, PPC_OPERAND_SIGNED },
431 457
432 /* The SI field in a D form instruction when we accept a wide range 458 /* The SI field in a D form instruction when we accept a wide range
@@ -448,8 +474,7 @@ const struct powerpc_operand powerpc_operands[] =
448 474
449 /* The SPRG register number in an XFX form m[ft]sprg instruction. */ 475 /* The SPRG register number in an XFX form m[ft]sprg instruction. */
450#define SPRG SPRBAT + 1 476#define SPRG SPRBAT + 1
451#define SPRG_MASK (0x3 << 16) 477 { 5, 16, insert_sprg, extract_sprg, 0 },
452 { 2, 16, NULL, NULL, 0 },
453 478
454 /* The SR field in an X form instruction. */ 479 /* The SR field in an X form instruction. */
455#define SR SPRG + 1 480#define SR SPRG + 1
@@ -536,10 +561,45 @@ const struct powerpc_operand powerpc_operands[] =
536#define WS_MASK (0x7 << 11) 561#define WS_MASK (0x7 << 11)
537 { 3, 11, NULL, NULL, 0 }, 562 { 3, 11, NULL, NULL, 0 },
538 563
539 /* The L field in an mtmsrd instruction */ 564 /* The L field in an mtmsrd or A form instruction. */
540#define MTMSRD_L WS + 1 565#define MTMSRD_L WS + 1
566#define A_L MTMSRD_L
541 { 1, 16, NULL, NULL, PPC_OPERAND_OPTIONAL }, 567 { 1, 16, NULL, NULL, PPC_OPERAND_OPTIONAL },
542 568
569 /* The DCM field in a Z form instruction. */
570#define DCM MTMSRD_L + 1
571 { 6, 16, NULL, NULL, 0 },
572
573 /* Likewise, the DGM field in a Z form instruction. */
574#define DGM DCM + 1
575 { 6, 16, NULL, NULL, 0 },
576
577#define TE DGM + 1
578 { 5, 11, NULL, NULL, 0 },
579
580#define RMC TE + 1
581 { 2, 21, NULL, NULL, 0 },
582
583#define R RMC + 1
584 { 1, 15, NULL, NULL, 0 },
585
586#define SP R + 1
587 { 2, 11, NULL, NULL, 0 },
588
589#define S SP + 1
590 { 1, 11, NULL, NULL, 0 },
591
592 /* SH field starting at bit position 16. */
593#define SH16 S + 1
594 { 6, 10, NULL, NULL, 0 },
595
596 /* The L field in an X form with the RT field fixed instruction. */
597#define XRT_L SH16 + 1
598 { 2, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
599
600 /* The EH field in larx instruction. */
601#define EH XRT_L + 1
602 { 1, 0, NULL, NULL, PPC_OPERAND_OPTIONAL },
543}; 603};
544 604
545/* The functions used to insert and extract complicated operands. */ 605/* The functions used to insert and extract complicated operands. */
@@ -550,7 +610,6 @@ const struct powerpc_operand powerpc_operands[] =
550 and the extraction function just checks that the fields are the 610 and the extraction function just checks that the fields are the
551 same. */ 611 same. */
552 612
553/*ARGSUSED*/
554static unsigned long 613static unsigned long
555insert_bat (unsigned long insn, 614insert_bat (unsigned long insn,
556 long value ATTRIBUTE_UNUSED, 615 long value ATTRIBUTE_UNUSED,
@@ -576,7 +635,6 @@ extract_bat (unsigned long insn,
576 and the extraction function just checks that the fields are the 635 and the extraction function just checks that the fields are the
577 same. */ 636 same. */
578 637
579/*ARGSUSED*/
580static unsigned long 638static unsigned long
581insert_bba (unsigned long insn, 639insert_bba (unsigned long insn,
582 long value ATTRIBUTE_UNUSED, 640 long value ATTRIBUTE_UNUSED,
@@ -599,7 +657,6 @@ extract_bba (unsigned long insn,
599/* The BD field in a B form instruction. The lower two bits are 657/* The BD field in a B form instruction. The lower two bits are
600 forced to zero. */ 658 forced to zero. */
601 659
602/*ARGSUSED*/
603static unsigned long 660static unsigned long
604insert_bd (unsigned long insn, 661insert_bd (unsigned long insn,
605 long value, 662 long value,
@@ -609,7 +666,6 @@ insert_bd (unsigned long insn,
609 return insn | (value & 0xfffc); 666 return insn | (value & 0xfffc);
610} 667}
611 668
612/*ARGSUSED*/
613static long 669static long
614extract_bd (unsigned long insn, 670extract_bd (unsigned long insn,
615 int dialect ATTRIBUTE_UNUSED, 671 int dialect ATTRIBUTE_UNUSED,
@@ -631,7 +687,6 @@ extract_bd (unsigned long insn,
631 in BO field, the "a" bit is 00010 for branch on CR(BI) and 01000 687 in BO field, the "a" bit is 00010 for branch on CR(BI) and 01000
632 for branch on CTR. We only handle the taken/not-taken hint here. */ 688 for branch on CTR. We only handle the taken/not-taken hint here. */
633 689
634/*ARGSUSED*/
635static unsigned long 690static unsigned long
636insert_bdm (unsigned long insn, 691insert_bdm (unsigned long insn,
637 long value, 692 long value,
@@ -677,7 +732,6 @@ extract_bdm (unsigned long insn,
677 This is like BDM, above, except that the branch is expected to be 732 This is like BDM, above, except that the branch is expected to be
678 taken. */ 733 taken. */
679 734
680/*ARGSUSED*/
681static unsigned long 735static unsigned long
682insert_bdp (unsigned long insn, 736insert_bdp (unsigned long insn,
683 long value, 737 long value,
@@ -831,7 +885,6 @@ extract_boe (unsigned long insn,
831/* The DQ field in a DQ form instruction. This is like D, but the 885/* The DQ field in a DQ form instruction. This is like D, but the
832 lower four bits are forced to zero. */ 886 lower four bits are forced to zero. */
833 887
834/*ARGSUSED*/
835static unsigned long 888static unsigned long
836insert_dq (unsigned long insn, 889insert_dq (unsigned long insn,
837 long value, 890 long value,
@@ -843,7 +896,6 @@ insert_dq (unsigned long insn,
843 return insn | (value & 0xfff0); 896 return insn | (value & 0xfff0);
844} 897}
845 898
846/*ARGSUSED*/
847static long 899static long
848extract_dq (unsigned long insn, 900extract_dq (unsigned long insn,
849 int dialect ATTRIBUTE_UNUSED, 901 int dialect ATTRIBUTE_UNUSED,
@@ -918,7 +970,6 @@ extract_ev8 (unsigned long insn,
918/* The DS field in a DS form instruction. This is like D, but the 970/* The DS field in a DS form instruction. This is like D, but the
919 lower two bits are forced to zero. */ 971 lower two bits are forced to zero. */
920 972
921/*ARGSUSED*/
922static unsigned long 973static unsigned long
923insert_ds (unsigned long insn, 974insert_ds (unsigned long insn,
924 long value, 975 long value,
@@ -930,7 +981,6 @@ insert_ds (unsigned long insn,
930 return insn | (value & 0xfffc); 981 return insn | (value & 0xfffc);
931} 982}
932 983
933/*ARGSUSED*/
934static long 984static long
935extract_ds (unsigned long insn, 985extract_ds (unsigned long insn,
936 int dialect ATTRIBUTE_UNUSED, 986 int dialect ATTRIBUTE_UNUSED,
@@ -941,7 +991,6 @@ extract_ds (unsigned long insn,
941 991
942/* The DE field in a DE form instruction. */ 992/* The DE field in a DE form instruction. */
943 993
944/*ARGSUSED*/
945static unsigned long 994static unsigned long
946insert_de (unsigned long insn, 995insert_de (unsigned long insn,
947 long value, 996 long value,
@@ -953,7 +1002,6 @@ insert_de (unsigned long insn,
953 return insn | ((value << 4) & 0xfff0); 1002 return insn | ((value << 4) & 0xfff0);
954} 1003}
955 1004
956/*ARGSUSED*/
957static long 1005static long
958extract_de (unsigned long insn, 1006extract_de (unsigned long insn,
959 int dialect ATTRIBUTE_UNUSED, 1007 int dialect ATTRIBUTE_UNUSED,
@@ -964,7 +1012,6 @@ extract_de (unsigned long insn,
964 1012
965/* The DES field in a DES form instruction. */ 1013/* The DES field in a DES form instruction. */
966 1014
967/*ARGSUSED*/
968static unsigned long 1015static unsigned long
969insert_des (unsigned long insn, 1016insert_des (unsigned long insn,
970 long value, 1017 long value,
@@ -978,7 +1025,6 @@ insert_des (unsigned long insn,
978 return insn | ((value << 2) & 0xfff0); 1025 return insn | ((value << 2) & 0xfff0);
979} 1026}
980 1027
981/*ARGSUSED*/
982static long 1028static long
983extract_des (unsigned long insn, 1029extract_des (unsigned long insn,
984 int dialect ATTRIBUTE_UNUSED, 1030 int dialect ATTRIBUTE_UNUSED,
@@ -995,17 +1041,33 @@ insert_fxm (unsigned long insn,
995 int dialect, 1041 int dialect,
996 const char **errmsg) 1042 const char **errmsg)
997{ 1043{
1044 /* If we're handling the mfocrf and mtocrf insns ensure that exactly
1045 one bit of the mask field is set. */
1046 if ((insn & (1 << 20)) != 0)
1047 {
1048 if (value == 0 || (value & -value) != value)
1049 {
1050 *errmsg = _("invalid mask field");
1051 value = 0;
1052 }
1053 }
1054
998 /* If the optional field on mfcr is missing that means we want to use 1055 /* If the optional field on mfcr is missing that means we want to use
999 the old form of the instruction that moves the whole cr. In that 1056 the old form of the instruction that moves the whole cr. In that
1000 case we'll have VALUE zero. There doesn't seem to be a way to 1057 case we'll have VALUE zero. There doesn't seem to be a way to
1001 distinguish this from the case where someone writes mfcr %r3,0. */ 1058 distinguish this from the case where someone writes mfcr %r3,0. */
1002 if (value == 0) 1059 else if (value == 0)
1003 ; 1060 ;
1004 1061
1005 /* If only one bit of the FXM field is set, we can use the new form 1062 /* If only one bit of the FXM field is set, we can use the new form
1006 of the instruction, which is faster. Unlike the Power4 branch hint 1063 of the instruction, which is faster. Unlike the Power4 branch hint
1007 encoding, this is not backward compatible. */ 1064 encoding, this is not backward compatible. Do not generate the
1008 else if ((dialect & PPC_OPCODE_POWER4) != 0 && (value & -value) == value) 1065 new form unless -mpower4 has been given, or -many and the two
1066 operand form of mfcr was used. */
1067 else if ((value & -value) == value
1068 && ((dialect & PPC_OPCODE_POWER4) != 0
1069 || ((dialect & PPC_OPCODE_ANY) != 0
1070 && (insn & (0x3ff << 1)) == 19 << 1)))
1009 insn |= 1 << 20; 1071 insn |= 1 << 20;
1010 1072
1011 /* Any other value on mfcr is an error. */ 1073 /* Any other value on mfcr is an error. */
@@ -1020,7 +1082,7 @@ insert_fxm (unsigned long insn,
1020 1082
1021static long 1083static long
1022extract_fxm (unsigned long insn, 1084extract_fxm (unsigned long insn,
1023 int dialect, 1085 int dialect ATTRIBUTE_UNUSED,
1024 int *invalid) 1086 int *invalid)
1025{ 1087{
1026 long mask = (insn >> 12) & 0xff; 1088 long mask = (insn >> 12) & 0xff;
@@ -1028,14 +1090,9 @@ extract_fxm (unsigned long insn,
1028 /* Is this a Power4 insn? */ 1090 /* Is this a Power4 insn? */
1029 if ((insn & (1 << 20)) != 0) 1091 if ((insn & (1 << 20)) != 0)
1030 { 1092 {
1031 if ((dialect & PPC_OPCODE_POWER4) == 0) 1093 /* Exactly one bit of MASK should be set. */
1094 if (mask == 0 || (mask & -mask) != mask)
1032 *invalid = 1; 1095 *invalid = 1;
1033 else
1034 {
1035 /* Exactly one bit of MASK should be set. */
1036 if (mask == 0 || (mask & -mask) != mask)
1037 *invalid = 1;
1038 }
1039 } 1096 }
1040 1097
1041 /* Check that non-power4 form of mfcr has a zero MASK. */ 1098 /* Check that non-power4 form of mfcr has a zero MASK. */
@@ -1051,7 +1108,6 @@ extract_fxm (unsigned long insn,
1051/* The LI field in an I form instruction. The lower two bits are 1108/* The LI field in an I form instruction. The lower two bits are
1052 forced to zero. */ 1109 forced to zero. */
1053 1110
1054/*ARGSUSED*/
1055static unsigned long 1111static unsigned long
1056insert_li (unsigned long insn, 1112insert_li (unsigned long insn,
1057 long value, 1113 long value,
@@ -1063,7 +1119,6 @@ insert_li (unsigned long insn,
1063 return insn | (value & 0x3fffffc); 1119 return insn | (value & 0x3fffffc);
1064} 1120}
1065 1121
1066/*ARGSUSED*/
1067static long 1122static long
1068extract_li (unsigned long insn, 1123extract_li (unsigned long insn,
1069 int dialect ATTRIBUTE_UNUSED, 1124 int dialect ATTRIBUTE_UNUSED,
@@ -1163,7 +1218,6 @@ extract_mbe (unsigned long insn,
1163/* The MB or ME field in an MD or MDS form instruction. The high bit 1218/* The MB or ME field in an MD or MDS form instruction. The high bit
1164 is wrapped to the low end. */ 1219 is wrapped to the low end. */
1165 1220
1166/*ARGSUSED*/
1167static unsigned long 1221static unsigned long
1168insert_mb6 (unsigned long insn, 1222insert_mb6 (unsigned long insn,
1169 long value, 1223 long value,
@@ -1173,7 +1227,6 @@ insert_mb6 (unsigned long insn,
1173 return insn | ((value & 0x1f) << 6) | (value & 0x20); 1227 return insn | ((value & 0x1f) << 6) | (value & 0x20);
1174} 1228}
1175 1229
1176/*ARGSUSED*/
1177static long 1230static long
1178extract_mb6 (unsigned long insn, 1231extract_mb6 (unsigned long insn,
1179 int dialect ATTRIBUTE_UNUSED, 1232 int dialect ATTRIBUTE_UNUSED,
@@ -1198,7 +1251,6 @@ insert_nb (unsigned long insn,
1198 return insn | ((value & 0x1f) << 11); 1251 return insn | ((value & 0x1f) << 11);
1199} 1252}
1200 1253
1201/*ARGSUSED*/
1202static long 1254static long
1203extract_nb (unsigned long insn, 1255extract_nb (unsigned long insn,
1204 int dialect ATTRIBUTE_UNUSED, 1256 int dialect ATTRIBUTE_UNUSED,
@@ -1217,7 +1269,6 @@ extract_nb (unsigned long insn,
1217 invalid, since we never want to recognize an instruction which uses 1269 invalid, since we never want to recognize an instruction which uses
1218 a field of this type. */ 1270 a field of this type. */
1219 1271
1220/*ARGSUSED*/
1221static unsigned long 1272static unsigned long
1222insert_nsi (unsigned long insn, 1273insert_nsi (unsigned long insn,
1223 long value, 1274 long value,
@@ -1269,7 +1320,6 @@ insert_ram (unsigned long insn,
1269/* The RA field in the DQ form lq instruction, which has special 1320/* The RA field in the DQ form lq instruction, which has special
1270 value restrictions. */ 1321 value restrictions. */
1271 1322
1272/*ARGSUSED*/
1273static unsigned long 1323static unsigned long
1274insert_raq (unsigned long insn, 1324insert_raq (unsigned long insn,
1275 long value, 1325 long value,
@@ -1304,7 +1354,6 @@ insert_ras (unsigned long insn,
1304 function just copies the BT field into the BA field, and the 1354 function just copies the BT field into the BA field, and the
1305 extraction function just checks that the fields are the same. */ 1355 extraction function just checks that the fields are the same. */
1306 1356
1307/*ARGSUSED*/
1308static unsigned long 1357static unsigned long
1309insert_rbs (unsigned long insn, 1358insert_rbs (unsigned long insn,
1310 long value ATTRIBUTE_UNUSED, 1359 long value ATTRIBUTE_UNUSED,
@@ -1327,7 +1376,6 @@ extract_rbs (unsigned long insn,
1327/* The RT field of the DQ form lq instruction, which has special 1376/* The RT field of the DQ form lq instruction, which has special
1328 value restrictions. */ 1377 value restrictions. */
1329 1378
1330/*ARGSUSED*/
1331static unsigned long 1379static unsigned long
1332insert_rtq (unsigned long insn, 1380insert_rtq (unsigned long insn,
1333 long value, 1381 long value,
@@ -1342,7 +1390,6 @@ insert_rtq (unsigned long insn,
1342/* The RS field of the DS form stq instruction, which has special 1390/* The RS field of the DS form stq instruction, which has special
1343 value restrictions. */ 1391 value restrictions. */
1344 1392
1345/*ARGSUSED*/
1346static unsigned long 1393static unsigned long
1347insert_rsq (unsigned long insn, 1394insert_rsq (unsigned long insn,
1348 long value ATTRIBUTE_UNUSED, 1395 long value ATTRIBUTE_UNUSED,
@@ -1356,7 +1403,6 @@ insert_rsq (unsigned long insn,
1356 1403
1357/* The SH field in an MD form instruction. This is split. */ 1404/* The SH field in an MD form instruction. This is split. */
1358 1405
1359/*ARGSUSED*/
1360static unsigned long 1406static unsigned long
1361insert_sh6 (unsigned long insn, 1407insert_sh6 (unsigned long insn,
1362 long value, 1408 long value,
@@ -1366,7 +1412,6 @@ insert_sh6 (unsigned long insn,
1366 return insn | ((value & 0x1f) << 11) | ((value & 0x20) >> 4); 1412 return insn | ((value & 0x1f) << 11) | ((value & 0x20) >> 4);
1367} 1413}
1368 1414
1369/*ARGSUSED*/
1370static long 1415static long
1371extract_sh6 (unsigned long insn, 1416extract_sh6 (unsigned long insn,
1372 int dialect ATTRIBUTE_UNUSED, 1417 int dialect ATTRIBUTE_UNUSED,
@@ -1395,6 +1440,47 @@ extract_spr (unsigned long insn,
1395 return ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0); 1440 return ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0);
1396} 1441}
1397 1442
1443/* Some dialects have 8 SPRG registers instead of the standard 4. */
1444
1445static unsigned long
1446insert_sprg (unsigned long insn,
1447 long value,
1448 int dialect,
1449 const char **errmsg)
1450{
1451 /* This check uses PPC_OPCODE_403 because PPC405 is later defined
1452 as a synonym. If ever a 405 specific dialect is added this
1453 check should use that instead. */
1454 if (value > 7
1455 || (value > 3
1456 && (dialect & (PPC_OPCODE_BOOKE | PPC_OPCODE_403)) == 0))
1457 *errmsg = _("invalid sprg number");
1458
1459 /* If this is mfsprg4..7 then use spr 260..263 which can be read in
1460 user mode. Anything else must use spr 272..279. */
1461 if (value <= 3 || (insn & 0x100) != 0)
1462 value |= 0x10;
1463
1464 return insn | ((value & 0x17) << 16);
1465}
1466
1467static long
1468extract_sprg (unsigned long insn,
1469 int dialect,
1470 int *invalid)
1471{
1472 unsigned long val = (insn >> 16) & 0x1f;
1473
1474 /* mfsprg can use 260..263 and 272..279. mtsprg only uses spr 272..279
1475 If not BOOKE or 405, then both use only 272..275. */
1476 if (val <= 3
1477 || (val < 0x10 && (insn & 0x100) != 0)
1478 || (val - 0x10 > 3
1479 && (dialect & (PPC_OPCODE_BOOKE | PPC_OPCODE_403)) == 0))
1480 *invalid = 1;
1481 return val & 7;
1482}
1483
1398/* The TBR field in an XFX instruction. This is just like SPR, but it 1484/* The TBR field in an XFX instruction. This is just like SPR, but it
1399 is optional. When TBR is omitted, it must be inserted as 268 (the 1485 is optional. When TBR is omitted, it must be inserted as 268 (the
1400 magic number of the TB register). These functions treat 0 1486 magic number of the TB register). These functions treat 0
@@ -1460,6 +1546,9 @@ extract_tbr (unsigned long insn,
1460/* An A_MASK with the FRA and FRC fields fixed. */ 1546/* An A_MASK with the FRA and FRC fields fixed. */
1461#define AFRAFRC_MASK (A_MASK | FRA_MASK | FRC_MASK) 1547#define AFRAFRC_MASK (A_MASK | FRA_MASK | FRC_MASK)
1462 1548
1549/* An AFRAFRC_MASK, but with L bit clear. */
1550#define AFRALFRC_MASK (AFRAFRC_MASK & ~((unsigned long) 1 << 16))
1551
1463/* A B form instruction. */ 1552/* A B form instruction. */
1464#define B(op, aa, lk) (OP (op) | ((((unsigned long)(aa)) & 1) << 1) | ((lk) & 1)) 1553#define B(op, aa, lk) (OP (op) | ((((unsigned long)(aa)) & 1) << 1) | ((lk) & 1))
1465#define B_MASK B (0x3f, 1, 1) 1554#define B_MASK B (0x3f, 1, 1)
@@ -1494,11 +1583,11 @@ extract_tbr (unsigned long insn,
1494 1583
1495/* An Context form instruction. */ 1584/* An Context form instruction. */
1496#define CTX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x7)) 1585#define CTX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x7))
1497#define CTX_MASK CTX(0x3f, 0x7) 1586#define CTX_MASK CTX(0x3f, 0x7)
1498 1587
1499/* An User Context form instruction. */ 1588/* An User Context form instruction. */
1500#define UCTX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x1f)) 1589#define UCTX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x1f))
1501#define UCTX_MASK UCTX(0x3f, 0x1f) 1590#define UCTX_MASK UCTX(0x3f, 0x1f)
1502 1591
1503/* The main opcode mask with the RA field clear. */ 1592/* The main opcode mask with the RA field clear. */
1504#define DRA_MASK (OP_MASK | RA_MASK) 1593#define DRA_MASK (OP_MASK | RA_MASK)
@@ -1570,12 +1659,21 @@ extract_tbr (unsigned long insn,
1570/* An X form instruction. */ 1659/* An X form instruction. */
1571#define X(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x3ff) << 1)) 1660#define X(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x3ff) << 1))
1572 1661
1662/* A Z form instruction. */
1663#define Z(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x1ff) << 1))
1664
1573/* An X form instruction with the RC bit specified. */ 1665/* An X form instruction with the RC bit specified. */
1574#define XRC(op, xop, rc) (X ((op), (xop)) | ((rc) & 1)) 1666#define XRC(op, xop, rc) (X ((op), (xop)) | ((rc) & 1))
1575 1667
1668/* A Z form instruction with the RC bit specified. */
1669#define ZRC(op, xop, rc) (Z ((op), (xop)) | ((rc) & 1))
1670
1576/* The mask for an X form instruction. */ 1671/* The mask for an X form instruction. */
1577#define X_MASK XRC (0x3f, 0x3ff, 1) 1672#define X_MASK XRC (0x3f, 0x3ff, 1)
1578 1673
1674/* The mask for a Z form instruction. */
1675#define Z_MASK ZRC (0x3f, 0x1ff, 1)
1676
1579/* An X_MASK with the RA field fixed. */ 1677/* An X_MASK with the RA field fixed. */
1580#define XRA_MASK (X_MASK | RA_MASK) 1678#define XRA_MASK (X_MASK | RA_MASK)
1581 1679
@@ -1585,6 +1683,9 @@ extract_tbr (unsigned long insn,
1585/* An X_MASK with the RT field fixed. */ 1683/* An X_MASK with the RT field fixed. */
1586#define XRT_MASK (X_MASK | RT_MASK) 1684#define XRT_MASK (X_MASK | RT_MASK)
1587 1685
1686/* An XRT_MASK mask with the L bits clear. */
1687#define XLRT_MASK (XRT_MASK & ~((unsigned long) 0x3 << 21))
1688
1588/* An X_MASK with the RA and RB fields fixed. */ 1689/* An X_MASK with the RA and RB fields fixed. */
1589#define XRARB_MASK (X_MASK | RA_MASK | RB_MASK) 1690#define XRARB_MASK (X_MASK | RA_MASK | RB_MASK)
1590 1691
@@ -1597,8 +1698,8 @@ extract_tbr (unsigned long insn,
1597/* An XRTRA_MASK, but with L bit clear. */ 1698/* An XRTRA_MASK, but with L bit clear. */
1598#define XRTLRA_MASK (XRTRA_MASK & ~((unsigned long) 1 << 21)) 1699#define XRTLRA_MASK (XRTRA_MASK & ~((unsigned long) 1 << 21))
1599 1700
1600/* An X form comparison instruction. */ 1701/* An X form instruction with the L bit specified. */
1601#define XCMPL(op, xop, l) (X ((op), (xop)) | ((((unsigned long)(l)) & 1) << 21)) 1702#define XOPL(op, xop, l) (X ((op), (xop)) | ((((unsigned long)(l)) & 1) << 21))
1602 1703
1603/* The mask for an X form comparison instruction. */ 1704/* The mask for an X form comparison instruction. */
1604#define XCMP_MASK (X_MASK | (((unsigned long)1) << 22)) 1705#define XCMP_MASK (X_MASK | (((unsigned long)1) << 22))
@@ -1621,6 +1722,9 @@ extract_tbr (unsigned long insn,
1621/* An X form sync instruction with everything filled in except the LS field. */ 1722/* An X form sync instruction with everything filled in except the LS field. */
1622#define XSYNC_MASK (0xff9fffff) 1723#define XSYNC_MASK (0xff9fffff)
1623 1724
1725/* An X_MASK, but with the EH bit clear. */
1726#define XEH_MASK (X_MASK & ~((unsigned long )1))
1727
1624/* An X form AltiVec dss instruction. */ 1728/* An X form AltiVec dss instruction. */
1625#define XDSS(op, xop, a) (X ((op), (xop)) | ((((unsigned long)(a)) & 1) << 25)) 1729#define XDSS(op, xop, a) (X ((op), (xop)) | ((((unsigned long)(a)) & 1) << 25))
1626#define XDSS_MASK XDSS(0x3f, 0x3ff, 1) 1730#define XDSS_MASK XDSS(0x3f, 0x3ff, 1)
@@ -1663,6 +1767,9 @@ extract_tbr (unsigned long insn,
1663#define XLYBB_MASK (XLYLK_MASK | BB_MASK) 1767#define XLYBB_MASK (XLYLK_MASK | BB_MASK)
1664#define XLBOCBBB_MASK (XLOCB_MASK | BB_MASK) 1768#define XLBOCBBB_MASK (XLOCB_MASK | BB_MASK)
1665 1769
1770/* A mask for branch instructions using the BH field. */
1771#define XLBH_MASK (XL_MASK | (0x1c << 11))
1772
1666/* An XL_MASK with the BO and BB fields fixed. */ 1773/* An XL_MASK with the BO and BB fields fixed. */
1667#define XLBOBB_MASK (XL_MASK | BO_MASK | BB_MASK) 1774#define XLBOBB_MASK (XL_MASK | BO_MASK | BB_MASK)
1668 1775
@@ -1682,11 +1789,12 @@ extract_tbr (unsigned long insn,
1682#define XS_MASK XS (0x3f, 0x1ff, 1) 1789#define XS_MASK XS (0x3f, 0x1ff, 1)
1683 1790
1684/* A mask for the FXM version of an XFX form instruction. */ 1791/* A mask for the FXM version of an XFX form instruction. */
1685#define XFXFXM_MASK (X_MASK | (1 << 11)) 1792#define XFXFXM_MASK (X_MASK | (1 << 11) | (1 << 20))
1686 1793
1687/* An XFX form instruction with the FXM field filled in. */ 1794/* An XFX form instruction with the FXM field filled in. */
1688#define XFXM(op, xop, fxm) \ 1795#define XFXM(op, xop, fxm, p4) \
1689 (X ((op), (xop)) | ((((unsigned long)(fxm)) & 0xff) << 12)) 1796 (X ((op), (xop)) | ((((unsigned long)(fxm)) & 0xff) << 12) \
1797 | ((unsigned long)(p4) << 20))
1690 1798
1691/* An XFX form instruction with the SPR field filled in. */ 1799/* An XFX form instruction with the SPR field filled in. */
1692#define XSPR(op, xop, spr) \ 1800#define XSPR(op, xop, spr) \
@@ -1699,7 +1807,7 @@ extract_tbr (unsigned long insn,
1699 1807
1700/* An XFX form instruction with the SPR field filled in except for the 1808/* An XFX form instruction with the SPR field filled in except for the
1701 SPRG field. */ 1809 SPRG field. */
1702#define XSPRG_MASK (XSPR_MASK &~ SPRG_MASK) 1810#define XSPRG_MASK (XSPR_MASK & ~(0x17 << 16))
1703 1811
1704/* An X form instruction with everything filled in except the E field. */ 1812/* An X form instruction with everything filled in except the E field. */
1705#define XE_MASK (0xffff7fff) 1813#define XE_MASK (0xffff7fff)
@@ -1769,6 +1877,9 @@ extract_tbr (unsigned long insn,
1769#define PPCCOM PPC_OPCODE_PPC | PPC_OPCODE_COMMON 1877#define PPCCOM PPC_OPCODE_PPC | PPC_OPCODE_COMMON
1770#define NOPOWER4 PPC_OPCODE_NOPOWER4 | PPCCOM 1878#define NOPOWER4 PPC_OPCODE_NOPOWER4 | PPCCOM
1771#define POWER4 PPC_OPCODE_POWER4 1879#define POWER4 PPC_OPCODE_POWER4
1880#define POWER5 PPC_OPCODE_POWER5
1881#define POWER6 PPC_OPCODE_POWER6
1882#define CELL PPC_OPCODE_CELL
1772#define PPC32 PPC_OPCODE_32 | PPC_OPCODE_PPC 1883#define PPC32 PPC_OPCODE_32 | PPC_OPCODE_PPC
1773#define PPC64 PPC_OPCODE_64 | PPC_OPCODE_PPC 1884#define PPC64 PPC_OPCODE_64 | PPC_OPCODE_PPC
1774#define PPC403 PPC_OPCODE_403 1885#define PPC403 PPC_OPCODE_403
@@ -1776,7 +1887,7 @@ extract_tbr (unsigned long insn,
1776#define PPC440 PPC_OPCODE_440 1887#define PPC440 PPC_OPCODE_440
1777#define PPC750 PPC 1888#define PPC750 PPC
1778#define PPC860 PPC 1889#define PPC860 PPC
1779#define PPCVEC PPC_OPCODE_ALTIVEC | PPC_OPCODE_PPC 1890#define PPCVEC PPC_OPCODE_ALTIVEC
1780#define POWER PPC_OPCODE_POWER 1891#define POWER PPC_OPCODE_POWER
1781#define POWER2 PPC_OPCODE_POWER | PPC_OPCODE_POWER2 1892#define POWER2 PPC_OPCODE_POWER | PPC_OPCODE_POWER2
1782#define PPCPWR2 PPC_OPCODE_PPC | PPC_OPCODE_POWER | PPC_OPCODE_POWER2 1893#define PPCPWR2 PPC_OPCODE_PPC | PPC_OPCODE_POWER | PPC_OPCODE_POWER2
@@ -1790,6 +1901,7 @@ extract_tbr (unsigned long insn,
1790#define BOOKE PPC_OPCODE_BOOKE 1901#define BOOKE PPC_OPCODE_BOOKE
1791#define BOOKE64 PPC_OPCODE_BOOKE64 1902#define BOOKE64 PPC_OPCODE_BOOKE64
1792#define CLASSIC PPC_OPCODE_CLASSIC 1903#define CLASSIC PPC_OPCODE_CLASSIC
1904#define PPCE300 PPC_OPCODE_E300
1793#define PPCSPE PPC_OPCODE_SPE 1905#define PPCSPE PPC_OPCODE_SPE
1794#define PPCISEL PPC_OPCODE_ISEL 1906#define PPCISEL PPC_OPCODE_ISEL
1795#define PPCEFS PPC_OPCODE_EFS 1907#define PPCEFS PPC_OPCODE_EFS
@@ -1952,6 +2064,41 @@ const struct powerpc_opcode powerpc_opcodes[] = {
1952{ "nmaclhwso.", XO(4,494,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, 2064{ "nmaclhwso.", XO(4,494,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
1953{ "mfvscr", VX(4, 1540), VX_MASK, PPCVEC, { VD } }, 2065{ "mfvscr", VX(4, 1540), VX_MASK, PPCVEC, { VD } },
1954{ "mtvscr", VX(4, 1604), VX_MASK, PPCVEC, { VB } }, 2066{ "mtvscr", VX(4, 1604), VX_MASK, PPCVEC, { VB } },
2067
2068 /* Double-precision opcodes. */
2069 /* Some of these conflict with AltiVec, so move them before, since
2070 PPCVEC includes the PPC_OPCODE_PPC set. */
2071{ "efscfd", VX(4, 719), VX_MASK, PPCEFS, { RS, RB } },
2072{ "efdabs", VX(4, 740), VX_MASK, PPCEFS, { RS, RA } },
2073{ "efdnabs", VX(4, 741), VX_MASK, PPCEFS, { RS, RA } },
2074{ "efdneg", VX(4, 742), VX_MASK, PPCEFS, { RS, RA } },
2075{ "efdadd", VX(4, 736), VX_MASK, PPCEFS, { RS, RA, RB } },
2076{ "efdsub", VX(4, 737), VX_MASK, PPCEFS, { RS, RA, RB } },
2077{ "efdmul", VX(4, 744), VX_MASK, PPCEFS, { RS, RA, RB } },
2078{ "efddiv", VX(4, 745), VX_MASK, PPCEFS, { RS, RA, RB } },
2079{ "efdcmpgt", VX(4, 748), VX_MASK, PPCEFS, { CRFD, RA, RB } },
2080{ "efdcmplt", VX(4, 749), VX_MASK, PPCEFS, { CRFD, RA, RB } },
2081{ "efdcmpeq", VX(4, 750), VX_MASK, PPCEFS, { CRFD, RA, RB } },
2082{ "efdtstgt", VX(4, 764), VX_MASK, PPCEFS, { CRFD, RA, RB } },
2083{ "efdtstlt", VX(4, 765), VX_MASK, PPCEFS, { CRFD, RA, RB } },
2084{ "efdtsteq", VX(4, 766), VX_MASK, PPCEFS, { CRFD, RA, RB } },
2085{ "efdcfsi", VX(4, 753), VX_MASK, PPCEFS, { RS, RB } },
2086{ "efdcfsid", VX(4, 739), VX_MASK, PPCEFS, { RS, RB } },
2087{ "efdcfui", VX(4, 752), VX_MASK, PPCEFS, { RS, RB } },
2088{ "efdcfuid", VX(4, 738), VX_MASK, PPCEFS, { RS, RB } },
2089{ "efdcfsf", VX(4, 755), VX_MASK, PPCEFS, { RS, RB } },
2090{ "efdcfuf", VX(4, 754), VX_MASK, PPCEFS, { RS, RB } },
2091{ "efdctsi", VX(4, 757), VX_MASK, PPCEFS, { RS, RB } },
2092{ "efdctsidz",VX(4, 747), VX_MASK, PPCEFS, { RS, RB } },
2093{ "efdctsiz", VX(4, 762), VX_MASK, PPCEFS, { RS, RB } },
2094{ "efdctui", VX(4, 756), VX_MASK, PPCEFS, { RS, RB } },
2095{ "efdctuidz",VX(4, 746), VX_MASK, PPCEFS, { RS, RB } },
2096{ "efdctuiz", VX(4, 760), VX_MASK, PPCEFS, { RS, RB } },
2097{ "efdctsf", VX(4, 759), VX_MASK, PPCEFS, { RS, RB } },
2098{ "efdctuf", VX(4, 758), VX_MASK, PPCEFS, { RS, RB } },
2099{ "efdcfs", VX(4, 751), VX_MASK, PPCEFS, { RS, RB } },
2100 /* End of double-precision opcodes. */
2101
1955{ "vaddcuw", VX(4, 384), VX_MASK, PPCVEC, { VD, VA, VB } }, 2102{ "vaddcuw", VX(4, 384), VX_MASK, PPCVEC, { VD, VA, VB } },
1956{ "vaddfp", VX(4, 10), VX_MASK, PPCVEC, { VD, VA, VB } }, 2103{ "vaddfp", VX(4, 10), VX_MASK, PPCVEC, { VD, VA, VB } },
1957{ "vaddsbs", VX(4, 768), VX_MASK, PPCVEC, { VD, VA, VB } }, 2104{ "vaddsbs", VX(4, 768), VX_MASK, PPCVEC, { VD, VA, VB } },
@@ -2389,16 +2536,16 @@ const struct powerpc_opcode powerpc_opcodes[] = {
2389 2536
2390{ "li", OP(14), DRA_MASK, PPCCOM, { RT, SI } }, 2537{ "li", OP(14), DRA_MASK, PPCCOM, { RT, SI } },
2391{ "lil", OP(14), DRA_MASK, PWRCOM, { RT, SI } }, 2538{ "lil", OP(14), DRA_MASK, PWRCOM, { RT, SI } },
2392{ "addi", OP(14), OP_MASK, PPCCOM, { RT, RA, SI } }, 2539{ "addi", OP(14), OP_MASK, PPCCOM, { RT, RA0, SI } },
2393{ "cal", OP(14), OP_MASK, PWRCOM, { RT, D, RA } }, 2540{ "cal", OP(14), OP_MASK, PWRCOM, { RT, D, RA0 } },
2394{ "subi", OP(14), OP_MASK, PPCCOM, { RT, RA, NSI } }, 2541{ "subi", OP(14), OP_MASK, PPCCOM, { RT, RA0, NSI } },
2395{ "la", OP(14), OP_MASK, PPCCOM, { RT, D, RA } }, 2542{ "la", OP(14), OP_MASK, PPCCOM, { RT, D, RA0 } },
2396 2543
2397{ "lis", OP(15), DRA_MASK, PPCCOM, { RT, SISIGNOPT } }, 2544{ "lis", OP(15), DRA_MASK, PPCCOM, { RT, SISIGNOPT } },
2398{ "liu", OP(15), DRA_MASK, PWRCOM, { RT, SISIGNOPT } }, 2545{ "liu", OP(15), DRA_MASK, PWRCOM, { RT, SISIGNOPT } },
2399{ "addis", OP(15), OP_MASK, PPCCOM, { RT,RA,SISIGNOPT } }, 2546{ "addis", OP(15), OP_MASK, PPCCOM, { RT,RA0,SISIGNOPT } },
2400{ "cau", OP(15), OP_MASK, PWRCOM, { RT,RA,SISIGNOPT } }, 2547{ "cau", OP(15), OP_MASK, PWRCOM, { RT,RA0,SISIGNOPT } },
2401{ "subis", OP(15), OP_MASK, PPCCOM, { RT, RA, NSI } }, 2548{ "subis", OP(15), OP_MASK, PPCCOM, { RT, RA0, NSI } },
2402 2549
2403{ "bdnz-", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BDM } }, 2550{ "bdnz-", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BDM } },
2404{ "bdnz+", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BDP } }, 2551{ "bdnz+", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BDP } },
@@ -2665,9 +2812,9 @@ const struct powerpc_opcode powerpc_opcodes[] = {
2665{ "bcla+", B(16,1,1), B_MASK, PPCCOM, { BOE, BI, BDPA } }, 2812{ "bcla+", B(16,1,1), B_MASK, PPCCOM, { BOE, BI, BDPA } },
2666{ "bcla", B(16,1,1), B_MASK, COM, { BO, BI, BDA } }, 2813{ "bcla", B(16,1,1), B_MASK, COM, { BO, BI, BDA } },
2667 2814
2668{ "sc", SC(17,1,0), 0xffffffff, PPC, { 0 } }, 2815{ "sc", SC(17,1,0), SC_MASK, PPC, { LEV } },
2669{ "svc", SC(17,0,0), SC_MASK, POWER, { LEV, FL1, FL2 } }, 2816{ "svc", SC(17,0,0), SC_MASK, POWER, { SVC_LEV, FL1, FL2 } },
2670{ "svcl", SC(17,0,1), SC_MASK, POWER, { LEV, FL1, FL2 } }, 2817{ "svcl", SC(17,0,1), SC_MASK, POWER, { SVC_LEV, FL1, FL2 } },
2671{ "svca", SC(17,1,0), SC_MASK, PWRCOM, { SV } }, 2818{ "svca", SC(17,1,0), SC_MASK, PWRCOM, { SV } },
2672{ "svcla", SC(17,1,1), SC_MASK, POWER, { SV } }, 2819{ "svcla", SC(17,1,1), SC_MASK, POWER, { SV } },
2673 2820
@@ -2890,12 +3037,12 @@ const struct powerpc_opcode powerpc_opcodes[] = {
2890{ "bdzflrl", XLO(19,BODZF,16,1), XLBOBB_MASK, PPCCOM, { BI } }, 3037{ "bdzflrl", XLO(19,BODZF,16,1), XLBOBB_MASK, PPCCOM, { BI } },
2891{ "bdzflrl-",XLO(19,BODZF,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, 3038{ "bdzflrl-",XLO(19,BODZF,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
2892{ "bdzflrl+",XLO(19,BODZFP,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, 3039{ "bdzflrl+",XLO(19,BODZFP,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
2893{ "bclr", XLLK(19,16,0), XLYBB_MASK, PPCCOM, { BO, BI } },
2894{ "bclrl", XLLK(19,16,1), XLYBB_MASK, PPCCOM, { BO, BI } },
2895{ "bclr+", XLYLK(19,16,1,0), XLYBB_MASK, PPCCOM, { BOE, BI } }, 3040{ "bclr+", XLYLK(19,16,1,0), XLYBB_MASK, PPCCOM, { BOE, BI } },
2896{ "bclrl+", XLYLK(19,16,1,1), XLYBB_MASK, PPCCOM, { BOE, BI } }, 3041{ "bclrl+", XLYLK(19,16,1,1), XLYBB_MASK, PPCCOM, { BOE, BI } },
2897{ "bclr-", XLYLK(19,16,0,0), XLYBB_MASK, PPCCOM, { BOE, BI } }, 3042{ "bclr-", XLYLK(19,16,0,0), XLYBB_MASK, PPCCOM, { BOE, BI } },
2898{ "bclrl-", XLYLK(19,16,0,1), XLYBB_MASK, PPCCOM, { BOE, BI } }, 3043{ "bclrl-", XLYLK(19,16,0,1), XLYBB_MASK, PPCCOM, { BOE, BI } },
3044{ "bclr", XLLK(19,16,0), XLBH_MASK, PPCCOM, { BO, BI, BH } },
3045{ "bclrl", XLLK(19,16,1), XLBH_MASK, PPCCOM, { BO, BI, BH } },
2899{ "bcr", XLLK(19,16,0), XLBB_MASK, PWRCOM, { BO, BI } }, 3046{ "bcr", XLLK(19,16,0), XLBB_MASK, PWRCOM, { BO, BI } },
2900{ "bcrl", XLLK(19,16,1), XLBB_MASK, PWRCOM, { BO, BI } }, 3047{ "bcrl", XLLK(19,16,1), XLBB_MASK, PWRCOM, { BO, BI } },
2901{ "bclre", XLLK(19,17,0), XLBB_MASK, BOOKE64, { BO, BI } }, 3048{ "bclre", XLLK(19,17,0), XLBB_MASK, BOOKE64, { BO, BI } },
@@ -2924,14 +3071,23 @@ const struct powerpc_opcode powerpc_opcodes[] = {
2924 3071
2925{ "crand", XL(19,257), XL_MASK, COM, { BT, BA, BB } }, 3072{ "crand", XL(19,257), XL_MASK, COM, { BT, BA, BB } },
2926 3073
3074{ "hrfid", XL(19,274), 0xffffffff, POWER5 | CELL, { 0 } },
3075
2927{ "crset", XL(19,289), XL_MASK, PPCCOM, { BT, BAT, BBA } }, 3076{ "crset", XL(19,289), XL_MASK, PPCCOM, { BT, BAT, BBA } },
2928{ "creqv", XL(19,289), XL_MASK, COM, { BT, BA, BB } }, 3077{ "creqv", XL(19,289), XL_MASK, COM, { BT, BA, BB } },
2929 3078
3079{ "doze", XL(19,402), 0xffffffff, POWER6, { 0 } },
3080
2930{ "crorc", XL(19,417), XL_MASK, COM, { BT, BA, BB } }, 3081{ "crorc", XL(19,417), XL_MASK, COM, { BT, BA, BB } },
2931 3082
3083{ "nap", XL(19,434), 0xffffffff, POWER6, { 0 } },
3084
2932{ "crmove", XL(19,449), XL_MASK, PPCCOM, { BT, BA, BBA } }, 3085{ "crmove", XL(19,449), XL_MASK, PPCCOM, { BT, BA, BBA } },
2933{ "cror", XL(19,449), XL_MASK, COM, { BT, BA, BB } }, 3086{ "cror", XL(19,449), XL_MASK, COM, { BT, BA, BB } },
2934 3087
3088{ "sleep", XL(19,466), 0xffffffff, POWER6, { 0 } },
3089{ "rvwinkle", XL(19,498), 0xffffffff, POWER6, { 0 } },
3090
2935{ "bctr", XLO(19,BOU,528,0), XLBOBIBB_MASK, COM, { 0 } }, 3091{ "bctr", XLO(19,BOU,528,0), XLBOBIBB_MASK, COM, { 0 } },
2936{ "bctrl", XLO(19,BOU,528,1), XLBOBIBB_MASK, COM, { 0 } }, 3092{ "bctrl", XLO(19,BOU,528,1), XLBOBIBB_MASK, COM, { 0 } },
2937{ "bltctr", XLOCB(19,BOT,CBLT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, 3093{ "bltctr", XLOCB(19,BOT,CBLT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
@@ -3074,12 +3230,12 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3074{ "bfctrl-", XLO(19,BOFM4,528,1), XLBOBB_MASK, POWER4, { BI } }, 3230{ "bfctrl-", XLO(19,BOFM4,528,1), XLBOBB_MASK, POWER4, { BI } },
3075{ "bfctrl+", XLO(19,BOFP,528,1), XLBOBB_MASK, NOPOWER4, { BI } }, 3231{ "bfctrl+", XLO(19,BOFP,528,1), XLBOBB_MASK, NOPOWER4, { BI } },
3076{ "bfctrl+", XLO(19,BOFP4,528,1), XLBOBB_MASK, POWER4, { BI } }, 3232{ "bfctrl+", XLO(19,BOFP4,528,1), XLBOBB_MASK, POWER4, { BI } },
3077{ "bcctr", XLLK(19,528,0), XLYBB_MASK, PPCCOM, { BO, BI } },
3078{ "bcctr-", XLYLK(19,528,0,0), XLYBB_MASK, PPCCOM, { BOE, BI } }, 3233{ "bcctr-", XLYLK(19,528,0,0), XLYBB_MASK, PPCCOM, { BOE, BI } },
3079{ "bcctr+", XLYLK(19,528,1,0), XLYBB_MASK, PPCCOM, { BOE, BI } }, 3234{ "bcctr+", XLYLK(19,528,1,0), XLYBB_MASK, PPCCOM, { BOE, BI } },
3080{ "bcctrl", XLLK(19,528,1), XLYBB_MASK, PPCCOM, { BO, BI } },
3081{ "bcctrl-", XLYLK(19,528,0,1), XLYBB_MASK, PPCCOM, { BOE, BI } }, 3235{ "bcctrl-", XLYLK(19,528,0,1), XLYBB_MASK, PPCCOM, { BOE, BI } },
3082{ "bcctrl+", XLYLK(19,528,1,1), XLYBB_MASK, PPCCOM, { BOE, BI } }, 3236{ "bcctrl+", XLYLK(19,528,1,1), XLYBB_MASK, PPCCOM, { BOE, BI } },
3237{ "bcctr", XLLK(19,528,0), XLBH_MASK, PPCCOM, { BO, BI, BH } },
3238{ "bcctrl", XLLK(19,528,1), XLBH_MASK, PPCCOM, { BO, BI, BH } },
3083{ "bcc", XLLK(19,528,0), XLBB_MASK, PWRCOM, { BO, BI } }, 3239{ "bcc", XLLK(19,528,0), XLBB_MASK, PWRCOM, { BO, BI } },
3084{ "bccl", XLLK(19,528,1), XLBB_MASK, PWRCOM, { BO, BI } }, 3240{ "bccl", XLLK(19,528,1), XLBB_MASK, PWRCOM, { BO, BI } },
3085{ "bcctre", XLLK(19,529,0), XLYBB_MASK, BOOKE64, { BO, BI } }, 3241{ "bcctre", XLLK(19,529,0), XLYBB_MASK, BOOKE64, { BO, BI } },
@@ -3158,8 +3314,8 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3158{ "rldcr", MDS(30,9,0), MDS_MASK, PPC64, { RA, RS, RB, ME6 } }, 3314{ "rldcr", MDS(30,9,0), MDS_MASK, PPC64, { RA, RS, RB, ME6 } },
3159{ "rldcr.", MDS(30,9,1), MDS_MASK, PPC64, { RA, RS, RB, ME6 } }, 3315{ "rldcr.", MDS(30,9,1), MDS_MASK, PPC64, { RA, RS, RB, ME6 } },
3160 3316
3161{ "cmpw", XCMPL(31,0,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } }, 3317{ "cmpw", XOPL(31,0,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } },
3162{ "cmpd", XCMPL(31,0,1), XCMPL_MASK, PPC64, { OBF, RA, RB } }, 3318{ "cmpd", XOPL(31,0,1), XCMPL_MASK, PPC64, { OBF, RA, RB } },
3163{ "cmp", X(31,0), XCMP_MASK, PPC, { BF, L, RA, RB } }, 3319{ "cmp", X(31,0), XCMP_MASK, PPC, { BF, L, RA, RB } },
3164{ "cmp", X(31,0), XCMPL_MASK, PWRCOM, { BF, RA, RB } }, 3320{ "cmp", X(31,0), XCMPL_MASK, PWRCOM, { BF, RA, RB } },
3165 3321
@@ -3228,17 +3384,18 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3228{ "iseleq", X(31,79), X_MASK, PPCISEL, { RT, RA, RB } }, 3384{ "iseleq", X(31,79), X_MASK, PPCISEL, { RT, RA, RB } },
3229{ "isel", XISEL(31,15), XISEL_MASK, PPCISEL, { RT, RA, RB, CRB } }, 3385{ "isel", XISEL(31,15), XISEL_MASK, PPCISEL, { RT, RA, RB, CRB } },
3230 3386
3231{ "mfcr", X(31,19), XRARB_MASK, NOPOWER4, { RT } }, 3387{ "mfocrf", XFXM(31,19,0,1), XFXFXM_MASK, COM, { RT, FXM } },
3388{ "mfcr", X(31,19), XRARB_MASK, NOPOWER4 | COM, { RT } },
3232{ "mfcr", X(31,19), XFXFXM_MASK, POWER4, { RT, FXM4 } }, 3389{ "mfcr", X(31,19), XFXFXM_MASK, POWER4, { RT, FXM4 } },
3233 3390
3234{ "lwarx", X(31,20), X_MASK, PPC, { RT, RA, RB } }, 3391{ "lwarx", X(31,20), XEH_MASK, PPC, { RT, RA0, RB, EH } },
3235 3392
3236{ "ldx", X(31,21), X_MASK, PPC64, { RT, RA, RB } }, 3393{ "ldx", X(31,21), X_MASK, PPC64, { RT, RA0, RB } },
3237 3394
3238{ "icbt", X(31,22), X_MASK, BOOKE, { CT, RA, RB } }, 3395{ "icbt", X(31,22), X_MASK, BOOKE|PPCE300, { CT, RA, RB } },
3239{ "icbt", X(31,262), XRT_MASK, PPC403, { RA, RB } }, 3396{ "icbt", X(31,262), XRT_MASK, PPC403, { RA, RB } },
3240 3397
3241{ "lwzx", X(31,23), X_MASK, PPCCOM, { RT, RA, RB } }, 3398{ "lwzx", X(31,23), X_MASK, PPCCOM, { RT, RA0, RB } },
3242{ "lx", X(31,23), X_MASK, PWRCOM, { RT, RA, RB } }, 3399{ "lx", X(31,23), X_MASK, PWRCOM, { RT, RA, RB } },
3243 3400
3244{ "slw", XRC(31,24,0), X_MASK, PPCCOM, { RA, RS, RB } }, 3401{ "slw", XRC(31,24,0), X_MASK, PPCCOM, { RA, RS, RB } },
@@ -3262,10 +3419,10 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3262 3419
3263{ "icbte", X(31,30), X_MASK, BOOKE64, { CT, RA, RB } }, 3420{ "icbte", X(31,30), X_MASK, BOOKE64, { CT, RA, RB } },
3264 3421
3265{ "lwzxe", X(31,31), X_MASK, BOOKE64, { RT, RA, RB } }, 3422{ "lwzxe", X(31,31), X_MASK, BOOKE64, { RT, RA0, RB } },
3266 3423
3267{ "cmplw", XCMPL(31,32,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } }, 3424{ "cmplw", XOPL(31,32,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } },
3268{ "cmpld", XCMPL(31,32,1), XCMPL_MASK, PPC64, { OBF, RA, RB } }, 3425{ "cmpld", XOPL(31,32,1), XCMPL_MASK, PPC64, { OBF, RA, RB } },
3269{ "cmpl", X(31,32), XCMP_MASK, PPC, { BF, L, RA, RB } }, 3426{ "cmpl", X(31,32), XCMP_MASK, PPC, { BF, L, RA, RB } },
3270{ "cmpl", X(31,32), XCMPL_MASK, PWRCOM, { BF, RA, RB } }, 3427{ "cmpl", X(31,32), XCMPL_MASK, PWRCOM, { BF, RA, RB } },
3271 3428
@@ -3324,15 +3481,16 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3324 3481
3325{ "mfmsr", X(31,83), XRARB_MASK, COM, { RT } }, 3482{ "mfmsr", X(31,83), XRARB_MASK, COM, { RT } },
3326 3483
3327{ "ldarx", X(31,84), X_MASK, PPC64, { RT, RA, RB } }, 3484{ "ldarx", X(31,84), XEH_MASK, PPC64, { RT, RA0, RB, EH } },
3328 3485
3329{ "dcbf", X(31,86), XRT_MASK, PPC, { RA, RB } }, 3486{ "dcbfl", XOPL(31,86,1), XRT_MASK, POWER5, { RA, RB } },
3487{ "dcbf", X(31,86), XLRT_MASK, PPC, { RA, RB, XRT_L } },
3330 3488
3331{ "lbzx", X(31,87), X_MASK, COM, { RT, RA, RB } }, 3489{ "lbzx", X(31,87), X_MASK, COM, { RT, RA0, RB } },
3332 3490
3333{ "dcbfe", X(31,94), XRT_MASK, BOOKE64, { RA, RB } }, 3491{ "dcbfe", X(31,94), XRT_MASK, BOOKE64, { RA, RB } },
3334 3492
3335{ "lbzxe", X(31,95), X_MASK, BOOKE64, { RT, RA, RB } }, 3493{ "lbzxe", X(31,95), X_MASK, BOOKE64, { RT, RA0, RB } },
3336 3494
3337{ "neg", XO(31,104,0,0), XORB_MASK, COM, { RT, RA } }, 3495{ "neg", XO(31,104,0,0), XORB_MASK, COM, { RT, RA } },
3338{ "neg.", XO(31,104,0,1), XORB_MASK, COM, { RT, RA } }, 3496{ "neg.", XO(31,104,0,1), XORB_MASK, COM, { RT, RA } },
@@ -3350,12 +3508,14 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3350 3508
3351{ "lbzux", X(31,119), X_MASK, COM, { RT, RAL, RB } }, 3509{ "lbzux", X(31,119), X_MASK, COM, { RT, RAL, RB } },
3352 3510
3511{ "popcntb", X(31,122), XRB_MASK, POWER5, { RA, RS } },
3512
3353{ "not", XRC(31,124,0), X_MASK, COM, { RA, RS, RBS } }, 3513{ "not", XRC(31,124,0), X_MASK, COM, { RA, RS, RBS } },
3354{ "nor", XRC(31,124,0), X_MASK, COM, { RA, RS, RB } }, 3514{ "nor", XRC(31,124,0), X_MASK, COM, { RA, RS, RB } },
3355{ "not.", XRC(31,124,1), X_MASK, COM, { RA, RS, RBS } }, 3515{ "not.", XRC(31,124,1), X_MASK, COM, { RA, RS, RBS } },
3356{ "nor.", XRC(31,124,1), X_MASK, COM, { RA, RS, RB } }, 3516{ "nor.", XRC(31,124,1), X_MASK, COM, { RA, RS, RB } },
3357 3517
3358{ "lwarxe", X(31,126), X_MASK, BOOKE64, { RT, RA, RB } }, 3518{ "lwarxe", X(31,126), X_MASK, BOOKE64, { RT, RA0, RB } },
3359 3519
3360{ "lbzuxe", X(31,127), X_MASK, BOOKE64, { RT, RAL, RB } }, 3520{ "lbzuxe", X(31,127), X_MASK, BOOKE64, { RT, RAL, RB } },
3361 3521
@@ -3383,21 +3543,22 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3383 3543
3384{ "dcbtstlse",X(31,142),X_MASK, PPCCHLK64, { CT, RA, RB }}, 3544{ "dcbtstlse",X(31,142),X_MASK, PPCCHLK64, { CT, RA, RB }},
3385 3545
3386{ "mtcr", XFXM(31,144,0xff), XRARB_MASK, COM, { RS }}, 3546{ "mtocrf", XFXM(31,144,0,1), XFXFXM_MASK, COM, { FXM, RS } },
3547{ "mtcr", XFXM(31,144,0xff,0), XRARB_MASK, COM, { RS }},
3387{ "mtcrf", X(31,144), XFXFXM_MASK, COM, { FXM, RS } }, 3548{ "mtcrf", X(31,144), XFXFXM_MASK, COM, { FXM, RS } },
3388 3549
3389{ "mtmsr", X(31,146), XRARB_MASK, COM, { RS } }, 3550{ "mtmsr", X(31,146), XRARB_MASK, COM, { RS } },
3390 3551
3391{ "stdx", X(31,149), X_MASK, PPC64, { RS, RA, RB } }, 3552{ "stdx", X(31,149), X_MASK, PPC64, { RS, RA0, RB } },
3392 3553
3393{ "stwcx.", XRC(31,150,1), X_MASK, PPC, { RS, RA, RB } }, 3554{ "stwcx.", XRC(31,150,1), X_MASK, PPC, { RS, RA0, RB } },
3394 3555
3395{ "stwx", X(31,151), X_MASK, PPCCOM, { RS, RA, RB } }, 3556{ "stwx", X(31,151), X_MASK, PPCCOM, { RS, RA0, RB } },
3396{ "stx", X(31,151), X_MASK, PWRCOM, { RS, RA, RB } }, 3557{ "stx", X(31,151), X_MASK, PWRCOM, { RS, RA, RB } },
3397 3558
3398{ "stwcxe.", XRC(31,158,1), X_MASK, BOOKE64, { RS, RA, RB } }, 3559{ "stwcxe.", XRC(31,158,1), X_MASK, BOOKE64, { RS, RA0, RB } },
3399 3560
3400{ "stwxe", X(31,159), X_MASK, BOOKE64, { RS, RA, RB } }, 3561{ "stwxe", X(31,159), X_MASK, BOOKE64, { RS, RA0, RB } },
3401 3562
3402{ "slq", XRC(31,152,0), X_MASK, M601, { RA, RS, RB } }, 3563{ "slq", XRC(31,152,0), X_MASK, M601, { RA, RS, RB } },
3403{ "slq.", XRC(31,152,1), X_MASK, M601, { RA, RS, RB } }, 3564{ "slq.", XRC(31,152,1), X_MASK, M601, { RA, RS, RB } },
@@ -3405,6 +3566,8 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3405{ "sle", XRC(31,153,0), X_MASK, M601, { RA, RS, RB } }, 3566{ "sle", XRC(31,153,0), X_MASK, M601, { RA, RS, RB } },
3406{ "sle.", XRC(31,153,1), X_MASK, M601, { RA, RS, RB } }, 3567{ "sle.", XRC(31,153,1), X_MASK, M601, { RA, RS, RB } },
3407 3568
3569{ "prtyw", X(31,154), XRB_MASK, POWER6, { RA, RS } },
3570
3408{ "wrteei", X(31,163), XE_MASK, PPC403 | BOOKE, { E } }, 3571{ "wrteei", X(31,163), XE_MASK, PPC403 | BOOKE, { E } },
3409 3572
3410{ "dcbtls", X(31,166), X_MASK, PPCCHLK, { CT, RA, RB }}, 3573{ "dcbtls", X(31,166), X_MASK, PPCCHLK, { CT, RA, RB }},
@@ -3415,11 +3578,13 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3415{ "stdux", X(31,181), X_MASK, PPC64, { RS, RAS, RB } }, 3578{ "stdux", X(31,181), X_MASK, PPC64, { RS, RAS, RB } },
3416 3579
3417{ "stwux", X(31,183), X_MASK, PPCCOM, { RS, RAS, RB } }, 3580{ "stwux", X(31,183), X_MASK, PPCCOM, { RS, RAS, RB } },
3418{ "stux", X(31,183), X_MASK, PWRCOM, { RS, RA, RB } }, 3581{ "stux", X(31,183), X_MASK, PWRCOM, { RS, RA0, RB } },
3419 3582
3420{ "sliq", XRC(31,184,0), X_MASK, M601, { RA, RS, SH } }, 3583{ "sliq", XRC(31,184,0), X_MASK, M601, { RA, RS, SH } },
3421{ "sliq.", XRC(31,184,1), X_MASK, M601, { RA, RS, SH } }, 3584{ "sliq.", XRC(31,184,1), X_MASK, M601, { RA, RS, SH } },
3422 3585
3586{ "prtyd", X(31,186), XRB_MASK, POWER6, { RA, RS } },
3587
3423{ "stwuxe", X(31,191), X_MASK, BOOKE64, { RS, RAS, RB } }, 3588{ "stwuxe", X(31,191), X_MASK, BOOKE64, { RS, RAS, RB } },
3424 3589
3425{ "subfze", XO(31,200,0,0), XORB_MASK, PPCCOM, { RT, RA } }, 3590{ "subfze", XO(31,200,0,0), XORB_MASK, PPCCOM, { RT, RA } },
@@ -3442,9 +3607,9 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3442 3607
3443{ "mtsr", X(31,210), XRB_MASK|(1<<20), COM32, { SR, RS } }, 3608{ "mtsr", X(31,210), XRB_MASK|(1<<20), COM32, { SR, RS } },
3444 3609
3445{ "stdcx.", XRC(31,214,1), X_MASK, PPC64, { RS, RA, RB } }, 3610{ "stdcx.", XRC(31,214,1), X_MASK, PPC64, { RS, RA0, RB } },
3446 3611
3447{ "stbx", X(31,215), X_MASK, COM, { RS, RA, RB } }, 3612{ "stbx", X(31,215), X_MASK, COM, { RS, RA0, RB } },
3448 3613
3449{ "sllq", XRC(31,216,0), X_MASK, M601, { RA, RS, RB } }, 3614{ "sllq", XRC(31,216,0), X_MASK, M601, { RA, RS, RB } },
3450{ "sllq.", XRC(31,216,1), X_MASK, M601, { RA, RS, RB } }, 3615{ "sllq.", XRC(31,216,1), X_MASK, M601, { RA, RS, RB } },
@@ -3452,7 +3617,7 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3452{ "sleq", XRC(31,217,0), X_MASK, M601, { RA, RS, RB } }, 3617{ "sleq", XRC(31,217,0), X_MASK, M601, { RA, RS, RB } },
3453{ "sleq.", XRC(31,217,1), X_MASK, M601, { RA, RS, RB } }, 3618{ "sleq.", XRC(31,217,1), X_MASK, M601, { RA, RS, RB } },
3454 3619
3455{ "stbxe", X(31,223), X_MASK, BOOKE64, { RS, RA, RB } }, 3620{ "stbxe", X(31,223), X_MASK, BOOKE64, { RS, RA0, RB } },
3456 3621
3457{ "icblc", X(31,230), X_MASK, PPCCHLK, { CT, RA, RB }}, 3622{ "icblc", X(31,230), X_MASK, PPCCHLK, { CT, RA, RB }},
3458 3623
@@ -3492,7 +3657,7 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3492{ "mtsrin", X(31,242), XRA_MASK, PPC32, { RS, RB } }, 3657{ "mtsrin", X(31,242), XRA_MASK, PPC32, { RS, RB } },
3493{ "mtsri", X(31,242), XRA_MASK, POWER32, { RS, RB } }, 3658{ "mtsri", X(31,242), XRA_MASK, POWER32, { RS, RB } },
3494 3659
3495{ "dcbtst", X(31,246), XRT_MASK, PPC, { CT, RA, RB } }, 3660{ "dcbtst", X(31,246), X_MASK, PPC, { CT, RA, RB } },
3496 3661
3497{ "stbux", X(31,247), X_MASK, COM, { RS, RAS, RB } }, 3662{ "stbux", X(31,247), X_MASK, COM, { RS, RAS, RB } },
3498 3663
@@ -3519,26 +3684,26 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3519{ "addo.", XO(31,266,1,1), XO_MASK, PPCCOM, { RT, RA, RB } }, 3684{ "addo.", XO(31,266,1,1), XO_MASK, PPCCOM, { RT, RA, RB } },
3520{ "caxo.", XO(31,266,1,1), XO_MASK, PWRCOM, { RT, RA, RB } }, 3685{ "caxo.", XO(31,266,1,1), XO_MASK, PWRCOM, { RT, RA, RB } },
3521 3686
3522{ "tlbiel", X(31,274), XRTRA_MASK, POWER4, { RB } }, 3687{ "tlbiel", X(31,274), XRTLRA_MASK, POWER4, { RB, L } },
3523 3688
3524{ "mfapidi", X(31,275), X_MASK, BOOKE, { RT, RA } }, 3689{ "mfapidi", X(31,275), X_MASK, BOOKE, { RT, RA } },
3525 3690
3526{ "lscbx", XRC(31,277,0), X_MASK, M601, { RT, RA, RB } }, 3691{ "lscbx", XRC(31,277,0), X_MASK, M601, { RT, RA, RB } },
3527{ "lscbx.", XRC(31,277,1), X_MASK, M601, { RT, RA, RB } }, 3692{ "lscbx.", XRC(31,277,1), X_MASK, M601, { RT, RA, RB } },
3528 3693
3529{ "dcbt", X(31,278), XRT_MASK, PPC, { CT, RA, RB } }, 3694{ "dcbt", X(31,278), X_MASK, PPC, { CT, RA, RB } },
3530 3695
3531{ "lhzx", X(31,279), X_MASK, COM, { RT, RA, RB } }, 3696{ "lhzx", X(31,279), X_MASK, COM, { RT, RA0, RB } },
3532 3697
3533{ "eqv", XRC(31,284,0), X_MASK, COM, { RA, RS, RB } }, 3698{ "eqv", XRC(31,284,0), X_MASK, COM, { RA, RS, RB } },
3534{ "eqv.", XRC(31,284,1), X_MASK, COM, { RA, RS, RB } }, 3699{ "eqv.", XRC(31,284,1), X_MASK, COM, { RA, RS, RB } },
3535 3700
3536{ "dcbte", X(31,286), X_MASK, BOOKE64, { CT, RA, RB } }, 3701{ "dcbte", X(31,286), X_MASK, BOOKE64, { CT, RA, RB } },
3537 3702
3538{ "lhzxe", X(31,287), X_MASK, BOOKE64, { RT, RA, RB } }, 3703{ "lhzxe", X(31,287), X_MASK, BOOKE64, { RT, RA0, RB } },
3539 3704
3540{ "tlbie", X(31,306), XRTLRA_MASK, PPC, { RB, L } }, 3705{ "tlbie", X(31,306), XRTLRA_MASK, PPC, { RB, L } },
3541{ "tlbi", X(31,306), XRT_MASK, POWER, { RA, RB } }, 3706{ "tlbi", X(31,306), XRT_MASK, POWER, { RA0, RB } },
3542 3707
3543{ "eciwx", X(31,310), X_MASK, PPC, { RT, RA, RB } }, 3708{ "eciwx", X(31,310), X_MASK, PPC, { RT, RA, RB } },
3544 3709
@@ -3607,6 +3772,7 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3607{ "mfsdr1", XSPR(31,339,25), XSPR_MASK, COM, { RT } }, 3772{ "mfsdr1", XSPR(31,339,25), XSPR_MASK, COM, { RT } },
3608{ "mfsrr0", XSPR(31,339,26), XSPR_MASK, COM, { RT } }, 3773{ "mfsrr0", XSPR(31,339,26), XSPR_MASK, COM, { RT } },
3609{ "mfsrr1", XSPR(31,339,27), XSPR_MASK, COM, { RT } }, 3774{ "mfsrr1", XSPR(31,339,27), XSPR_MASK, COM, { RT } },
3775{ "mfcfar", XSPR(31,339,28), XSPR_MASK, POWER6, { RT } },
3610{ "mfpid", XSPR(31,339,48), XSPR_MASK, BOOKE, { RT } }, 3776{ "mfpid", XSPR(31,339,48), XSPR_MASK, BOOKE, { RT } },
3611{ "mfpid", XSPR(31,339,945), XSPR_MASK, PPC403, { RT } }, 3777{ "mfpid", XSPR(31,339,945), XSPR_MASK, PPC403, { RT } },
3612{ "mfcsrr0", XSPR(31,339,58), XSPR_MASK, BOOKE, { RT } }, 3778{ "mfcsrr0", XSPR(31,339,58), XSPR_MASK, BOOKE, { RT } },
@@ -3634,21 +3800,21 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3634{ "mfbar", XSPR(31,339,159), XSPR_MASK, PPC860, { RT } }, 3800{ "mfbar", XSPR(31,339,159), XSPR_MASK, PPC860, { RT } },
3635{ "mfvrsave", XSPR(31,339,256), XSPR_MASK, PPCVEC, { RT } }, 3801{ "mfvrsave", XSPR(31,339,256), XSPR_MASK, PPCVEC, { RT } },
3636{ "mfusprg0", XSPR(31,339,256), XSPR_MASK, BOOKE, { RT } }, 3802{ "mfusprg0", XSPR(31,339,256), XSPR_MASK, BOOKE, { RT } },
3637{ "mfsprg4", XSPR(31,339,260), XSPR_MASK, PPC405, { RT } },
3638{ "mfsprg5", XSPR(31,339,261), XSPR_MASK, PPC405, { RT } },
3639{ "mfsprg6", XSPR(31,339,262), XSPR_MASK, PPC405, { RT } },
3640{ "mfsprg7", XSPR(31,339,263), XSPR_MASK, PPC405, { RT } },
3641{ "mftb", X(31,371), X_MASK, CLASSIC, { RT, TBR } }, 3803{ "mftb", X(31,371), X_MASK, CLASSIC, { RT, TBR } },
3642{ "mftb", XSPR(31,339,268), XSPR_MASK, BOOKE, { RT } }, 3804{ "mftb", XSPR(31,339,268), XSPR_MASK, BOOKE, { RT } },
3643{ "mftbl", XSPR(31,371,268), XSPR_MASK, CLASSIC, { RT } }, 3805{ "mftbl", XSPR(31,371,268), XSPR_MASK, CLASSIC, { RT } },
3644{ "mftbl", XSPR(31,339,268), XSPR_MASK, BOOKE, { RT } }, 3806{ "mftbl", XSPR(31,339,268), XSPR_MASK, BOOKE, { RT } },
3645{ "mftbu", XSPR(31,371,269), XSPR_MASK, CLASSIC, { RT } }, 3807{ "mftbu", XSPR(31,371,269), XSPR_MASK, CLASSIC, { RT } },
3646{ "mftbu", XSPR(31,339,269), XSPR_MASK, BOOKE, { RT } }, 3808{ "mftbu", XSPR(31,339,269), XSPR_MASK, BOOKE, { RT } },
3647{ "mfsprg", XSPR(31,339,272), XSPRG_MASK, PPC, { RT, SPRG } }, 3809{ "mfsprg", XSPR(31,339,256), XSPRG_MASK, PPC, { RT, SPRG } },
3648{ "mfsprg0", XSPR(31,339,272), XSPR_MASK, PPC, { RT } }, 3810{ "mfsprg0", XSPR(31,339,272), XSPR_MASK, PPC, { RT } },
3649{ "mfsprg1", XSPR(31,339,273), XSPR_MASK, PPC, { RT } }, 3811{ "mfsprg1", XSPR(31,339,273), XSPR_MASK, PPC, { RT } },
3650{ "mfsprg2", XSPR(31,339,274), XSPR_MASK, PPC, { RT } }, 3812{ "mfsprg2", XSPR(31,339,274), XSPR_MASK, PPC, { RT } },
3651{ "mfsprg3", XSPR(31,339,275), XSPR_MASK, PPC, { RT } }, 3813{ "mfsprg3", XSPR(31,339,275), XSPR_MASK, PPC, { RT } },
3814{ "mfsprg4", XSPR(31,339,260), XSPR_MASK, PPC405 | BOOKE, { RT } },
3815{ "mfsprg5", XSPR(31,339,261), XSPR_MASK, PPC405 | BOOKE, { RT } },
3816{ "mfsprg6", XSPR(31,339,262), XSPR_MASK, PPC405 | BOOKE, { RT } },
3817{ "mfsprg7", XSPR(31,339,263), XSPR_MASK, PPC405 | BOOKE, { RT } },
3652{ "mfasr", XSPR(31,339,280), XSPR_MASK, PPC64, { RT } }, 3818{ "mfasr", XSPR(31,339,280), XSPR_MASK, PPC64, { RT } },
3653{ "mfear", XSPR(31,339,282), XSPR_MASK, PPC, { RT } }, 3819{ "mfear", XSPR(31,339,282), XSPR_MASK, PPC, { RT } },
3654{ "mfpir", XSPR(31,339,286), XSPR_MASK, BOOKE, { RT } }, 3820{ "mfpir", XSPR(31,339,286), XSPR_MASK, BOOKE, { RT } },
@@ -3699,6 +3865,10 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3699{ "mfspefscr", XSPR(31,339,512), XSPR_MASK, PPCSPE, { RT } }, 3865{ "mfspefscr", XSPR(31,339,512), XSPR_MASK, PPCSPE, { RT } },
3700{ "mfbbear", XSPR(31,339,513), XSPR_MASK, PPCBRLK, { RT } }, 3866{ "mfbbear", XSPR(31,339,513), XSPR_MASK, PPCBRLK, { RT } },
3701{ "mfbbtar", XSPR(31,339,514), XSPR_MASK, PPCBRLK, { RT } }, 3867{ "mfbbtar", XSPR(31,339,514), XSPR_MASK, PPCBRLK, { RT } },
3868{ "mfivor32", XSPR(31,339,528), XSPR_MASK, PPCSPE, { RT } },
3869{ "mfivor33", XSPR(31,339,529), XSPR_MASK, PPCSPE, { RT } },
3870{ "mfivor34", XSPR(31,339,530), XSPR_MASK, PPCSPE, { RT } },
3871{ "mfivor35", XSPR(31,339,531), XSPR_MASK, PPCPMR, { RT } },
3702{ "mfibatu", XSPR(31,339,528), XSPRBAT_MASK, PPC, { RT, SPRBAT } }, 3872{ "mfibatu", XSPR(31,339,528), XSPRBAT_MASK, PPC, { RT, SPRBAT } },
3703{ "mfibatl", XSPR(31,339,529), XSPRBAT_MASK, PPC, { RT, SPRBAT } }, 3873{ "mfibatl", XSPR(31,339,529), XSPRBAT_MASK, PPC, { RT, SPRBAT } },
3704{ "mfdbatu", XSPR(31,339,536), XSPRBAT_MASK, PPC, { RT, SPRBAT } }, 3874{ "mfdbatu", XSPR(31,339,536), XSPRBAT_MASK, PPC, { RT, SPRBAT } },
@@ -3708,10 +3878,11 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3708{ "mfic_dat", XSPR(31,339,562), XSPR_MASK, PPC860, { RT } }, 3878{ "mfic_dat", XSPR(31,339,562), XSPR_MASK, PPC860, { RT } },
3709{ "mfdc_cst", XSPR(31,339,568), XSPR_MASK, PPC860, { RT } }, 3879{ "mfdc_cst", XSPR(31,339,568), XSPR_MASK, PPC860, { RT } },
3710{ "mfdc_adr", XSPR(31,339,569), XSPR_MASK, PPC860, { RT } }, 3880{ "mfdc_adr", XSPR(31,339,569), XSPR_MASK, PPC860, { RT } },
3711{ "mfdc_dat", XSPR(31,339,570), XSPR_MASK, PPC860, { RT } },
3712{ "mfmcsrr0", XSPR(31,339,570), XSPR_MASK, PPCRFMCI, { RT } }, 3881{ "mfmcsrr0", XSPR(31,339,570), XSPR_MASK, PPCRFMCI, { RT } },
3882{ "mfdc_dat", XSPR(31,339,570), XSPR_MASK, PPC860, { RT } },
3713{ "mfmcsrr1", XSPR(31,339,571), XSPR_MASK, PPCRFMCI, { RT } }, 3883{ "mfmcsrr1", XSPR(31,339,571), XSPR_MASK, PPCRFMCI, { RT } },
3714{ "mfmcsr", XSPR(31,339,572), XSPR_MASK, PPCRFMCI, { RT } }, 3884{ "mfmcsr", XSPR(31,339,572), XSPR_MASK, PPCRFMCI, { RT } },
3885{ "mfmcar", XSPR(31,339,573), XSPR_MASK, PPCRFMCI, { RT } },
3715{ "mfdpdr", XSPR(31,339,630), XSPR_MASK, PPC860, { RT } }, 3886{ "mfdpdr", XSPR(31,339,630), XSPR_MASK, PPC860, { RT } },
3716{ "mfdpir", XSPR(31,339,631), XSPR_MASK, PPC860, { RT } }, 3887{ "mfdpir", XSPR(31,339,631), XSPR_MASK, PPC860, { RT } },
3717{ "mfimmr", XSPR(31,339,638), XSPR_MASK, PPC860, { RT } }, 3888{ "mfimmr", XSPR(31,339,638), XSPR_MASK, PPC860, { RT } },
@@ -3775,14 +3946,14 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3775{ "mfpbu2", XSPR(31,339,1023), XSPR_MASK, PPC403, { RT } }, 3946{ "mfpbu2", XSPR(31,339,1023), XSPR_MASK, PPC403, { RT } },
3776{ "mfspr", X(31,339), X_MASK, COM, { RT, SPR } }, 3947{ "mfspr", X(31,339), X_MASK, COM, { RT, SPR } },
3777 3948
3778{ "lwax", X(31,341), X_MASK, PPC64, { RT, RA, RB } }, 3949{ "lwax", X(31,341), X_MASK, PPC64, { RT, RA0, RB } },
3779 3950
3780{ "dst", XDSS(31,342,0), XDSS_MASK, PPCVEC, { RA, RB, STRM } }, 3951{ "dst", XDSS(31,342,0), XDSS_MASK, PPCVEC, { RA, RB, STRM } },
3781{ "dstt", XDSS(31,342,1), XDSS_MASK, PPCVEC, { RA, RB, STRM } }, 3952{ "dstt", XDSS(31,342,1), XDSS_MASK, PPCVEC, { RA, RB, STRM } },
3782 3953
3783{ "lhax", X(31,343), X_MASK, COM, { RT, RA, RB } }, 3954{ "lhax", X(31,343), X_MASK, COM, { RT, RA0, RB } },
3784 3955
3785{ "lhaxe", X(31,351), X_MASK, BOOKE64, { RT, RA, RB } }, 3956{ "lhaxe", X(31,351), X_MASK, BOOKE64, { RT, RA0, RB } },
3786 3957
3787{ "dstst", XDSS(31,374,0), XDSS_MASK, PPCVEC, { RA, RB, STRM } }, 3958{ "dstst", XDSS(31,374,0), XDSS_MASK, PPCVEC, { RA, RB, STRM } },
3788{ "dststt", XDSS(31,374,1), XDSS_MASK, PPCVEC, { RA, RB, STRM } }, 3959{ "dststt", XDSS(31,374,1), XDSS_MASK, PPCVEC, { RA, RB, STRM } },
@@ -3821,14 +3992,20 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3821 3992
3822{ "slbmte", X(31,402), XRA_MASK, PPC64, { RS, RB } }, 3993{ "slbmte", X(31,402), XRA_MASK, PPC64, { RS, RB } },
3823 3994
3824{ "sthx", X(31,407), X_MASK, COM, { RS, RA, RB } }, 3995{ "sthx", X(31,407), X_MASK, COM, { RS, RA0, RB } },
3996
3997{ "cmpb", X(31,508), X_MASK, POWER6, { RA, RS, RB } },
3825 3998
3826{ "lfqx", X(31,791), X_MASK, POWER2, { FRT, RA, RB } }, 3999{ "lfqx", X(31,791), X_MASK, POWER2, { FRT, RA, RB } },
3827 4000
4001{ "lfdpx", X(31,791), X_MASK, POWER6, { FRT, RA, RB } },
4002
3828{ "lfqux", X(31,823), X_MASK, POWER2, { FRT, RA, RB } }, 4003{ "lfqux", X(31,823), X_MASK, POWER2, { FRT, RA, RB } },
3829 4004
3830{ "stfqx", X(31,919), X_MASK, POWER2, { FRS, RA, RB } }, 4005{ "stfqx", X(31,919), X_MASK, POWER2, { FRS, RA, RB } },
3831 4006
4007{ "stfdpx", X(31,919), X_MASK, POWER6, { FRS, RA, RB } },
4008
3832{ "stfqux", X(31,951), X_MASK, POWER2, { FRS, RA, RB } }, 4009{ "stfqux", X(31,951), X_MASK, POWER2, { FRS, RA, RB } },
3833 4010
3834{ "orc", XRC(31,412,0), X_MASK, COM, { RA, RS, RB } }, 4011{ "orc", XRC(31,412,0), X_MASK, COM, { RA, RS, RB } },
@@ -3837,7 +4014,7 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3837{ "sradi", XS(31,413,0), XS_MASK, PPC64, { RA, RS, SH6 } }, 4014{ "sradi", XS(31,413,0), XS_MASK, PPC64, { RA, RS, SH6 } },
3838{ "sradi.", XS(31,413,1), XS_MASK, PPC64, { RA, RS, SH6 } }, 4015{ "sradi.", XS(31,413,1), XS_MASK, PPC64, { RA, RS, SH6 } },
3839 4016
3840{ "sthxe", X(31,415), X_MASK, BOOKE64, { RS, RA, RB } }, 4017{ "sthxe", X(31,415), X_MASK, BOOKE64, { RS, RA0, RB } },
3841 4018
3842{ "slbie", X(31,434), XRTRA_MASK, PPC64, { RB } }, 4019{ "slbie", X(31,434), XRTRA_MASK, PPC64, { RB } },
3843 4020
@@ -3918,6 +4095,7 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3918{ "mtsdr1", XSPR(31,467,25), XSPR_MASK, COM, { RS } }, 4095{ "mtsdr1", XSPR(31,467,25), XSPR_MASK, COM, { RS } },
3919{ "mtsrr0", XSPR(31,467,26), XSPR_MASK, COM, { RS } }, 4096{ "mtsrr0", XSPR(31,467,26), XSPR_MASK, COM, { RS } },
3920{ "mtsrr1", XSPR(31,467,27), XSPR_MASK, COM, { RS } }, 4097{ "mtsrr1", XSPR(31,467,27), XSPR_MASK, COM, { RS } },
4098{ "mtcfar", XSPR(31,467,28), XSPR_MASK, POWER6, { RS } },
3921{ "mtpid", XSPR(31,467,48), XSPR_MASK, BOOKE, { RS } }, 4099{ "mtpid", XSPR(31,467,48), XSPR_MASK, BOOKE, { RS } },
3922{ "mtpid", XSPR(31,467,945), XSPR_MASK, PPC403, { RS } }, 4100{ "mtpid", XSPR(31,467,945), XSPR_MASK, PPC403, { RS } },
3923{ "mtdecar", XSPR(31,467,54), XSPR_MASK, BOOKE, { RS } }, 4101{ "mtdecar", XSPR(31,467,54), XSPR_MASK, BOOKE, { RS } },
@@ -3946,7 +4124,7 @@ const struct powerpc_opcode powerpc_opcodes[] = {
3946{ "mtbar", XSPR(31,467,159), XSPR_MASK, PPC860, { RS } }, 4124{ "mtbar", XSPR(31,467,159), XSPR_MASK, PPC860, { RS } },
3947{ "mtvrsave", XSPR(31,467,256), XSPR_MASK, PPCVEC, { RS } }, 4125{ "mtvrsave", XSPR(31,467,256), XSPR_MASK, PPCVEC, { RS } },
3948{ "mtusprg0", XSPR(31,467,256), XSPR_MASK, BOOKE, { RS } }, 4126{ "mtusprg0", XSPR(31,467,256), XSPR_MASK, BOOKE, { RS } },
3949{ "mtsprg", XSPR(31,467,272), XSPRG_MASK,PPC, { SPRG, RS } }, 4127{ "mtsprg", XSPR(31,467,256), XSPRG_MASK,PPC, { SPRG, RS } },
3950{ "mtsprg0", XSPR(31,467,272), XSPR_MASK, PPC, { RS } }, 4128{ "mtsprg0", XSPR(31,467,272), XSPR_MASK, PPC, { RS } },
3951{ "mtsprg1", XSPR(31,467,273), XSPR_MASK, PPC, { RS } }, 4129{ "mtsprg1", XSPR(31,467,273), XSPR_MASK, PPC, { RS } },
3952{ "mtsprg2", XSPR(31,467,274), XSPR_MASK, PPC, { RS } }, 4130{ "mtsprg2", XSPR(31,467,274), XSPR_MASK, PPC, { RS } },
@@ -4005,6 +4183,10 @@ const struct powerpc_opcode powerpc_opcodes[] = {
4005{ "mtspefscr", XSPR(31,467,512), XSPR_MASK, PPCSPE, { RS } }, 4183{ "mtspefscr", XSPR(31,467,512), XSPR_MASK, PPCSPE, { RS } },
4006{ "mtbbear", XSPR(31,467,513), XSPR_MASK, PPCBRLK, { RS } }, 4184{ "mtbbear", XSPR(31,467,513), XSPR_MASK, PPCBRLK, { RS } },
4007{ "mtbbtar", XSPR(31,467,514), XSPR_MASK, PPCBRLK, { RS } }, 4185{ "mtbbtar", XSPR(31,467,514), XSPR_MASK, PPCBRLK, { RS } },
4186{ "mtivor32", XSPR(31,467,528), XSPR_MASK, PPCSPE, { RS } },
4187{ "mtivor33", XSPR(31,467,529), XSPR_MASK, PPCSPE, { RS } },
4188{ "mtivor34", XSPR(31,467,530), XSPR_MASK, PPCSPE, { RS } },
4189{ "mtivor35", XSPR(31,467,531), XSPR_MASK, PPCPMR, { RS } },
4008{ "mtibatu", XSPR(31,467,528), XSPRBAT_MASK, PPC, { SPRBAT, RS } }, 4190{ "mtibatu", XSPR(31,467,528), XSPRBAT_MASK, PPC, { SPRBAT, RS } },
4009{ "mtibatl", XSPR(31,467,529), XSPRBAT_MASK, PPC, { SPRBAT, RS } }, 4191{ "mtibatl", XSPR(31,467,529), XSPRBAT_MASK, PPC, { SPRBAT, RS } },
4010{ "mtdbatu", XSPR(31,467,536), XSPRBAT_MASK, PPC, { SPRBAT, RS } }, 4192{ "mtdbatu", XSPR(31,467,536), XSPRBAT_MASK, PPC, { SPRBAT, RS } },
@@ -4101,13 +4283,15 @@ const struct powerpc_opcode powerpc_opcodes[] = {
4101 4283
4102{ "clcs", X(31,531), XRB_MASK, M601, { RT, RA } }, 4284{ "clcs", X(31,531), XRB_MASK, M601, { RT, RA } },
4103 4285
4104{ "lswx", X(31,533), X_MASK, PPCCOM, { RT, RA, RB } }, 4286{ "ldbrx", X(31,532), X_MASK, CELL, { RT, RA0, RB } },
4287
4288{ "lswx", X(31,533), X_MASK, PPCCOM, { RT, RA0, RB } },
4105{ "lsx", X(31,533), X_MASK, PWRCOM, { RT, RA, RB } }, 4289{ "lsx", X(31,533), X_MASK, PWRCOM, { RT, RA, RB } },
4106 4290
4107{ "lwbrx", X(31,534), X_MASK, PPCCOM, { RT, RA, RB } }, 4291{ "lwbrx", X(31,534), X_MASK, PPCCOM, { RT, RA0, RB } },
4108{ "lbrx", X(31,534), X_MASK, PWRCOM, { RT, RA, RB } }, 4292{ "lbrx", X(31,534), X_MASK, PWRCOM, { RT, RA, RB } },
4109 4293
4110{ "lfsx", X(31,535), X_MASK, COM, { FRT, RA, RB } }, 4294{ "lfsx", X(31,535), X_MASK, COM, { FRT, RA0, RB } },
4111 4295
4112{ "srw", XRC(31,536,0), X_MASK, PPCCOM, { RA, RS, RB } }, 4296{ "srw", XRC(31,536,0), X_MASK, PPCCOM, { RA, RS, RB } },
4113{ "sr", XRC(31,536,0), X_MASK, PWRCOM, { RA, RS, RB } }, 4297{ "sr", XRC(31,536,0), X_MASK, PWRCOM, { RA, RS, RB } },
@@ -4123,11 +4307,12 @@ const struct powerpc_opcode powerpc_opcodes[] = {
4123{ "maskir", XRC(31,541,0), X_MASK, M601, { RA, RS, RB } }, 4307{ "maskir", XRC(31,541,0), X_MASK, M601, { RA, RS, RB } },
4124{ "maskir.", XRC(31,541,1), X_MASK, M601, { RA, RS, RB } }, 4308{ "maskir.", XRC(31,541,1), X_MASK, M601, { RA, RS, RB } },
4125 4309
4126{ "lwbrxe", X(31,542), X_MASK, BOOKE64, { RT, RA, RB } }, 4310{ "lwbrxe", X(31,542), X_MASK, BOOKE64, { RT, RA0, RB } },
4127 4311
4128{ "lfsxe", X(31,543), X_MASK, BOOKE64, { FRT, RA, RB } }, 4312{ "lfsxe", X(31,543), X_MASK, BOOKE64, { FRT, RA0, RB } },
4129 4313
4130{ "bbelr", X(31,550), X_MASK, PPCBRLK, { 0 }}, 4314{ "bbelr", X(31,550), X_MASK, PPCBRLK, { 0 }},
4315
4131{ "tlbsync", X(31,566), 0xffffffff, PPC, { 0 } }, 4316{ "tlbsync", X(31,566), 0xffffffff, PPC, { 0 } },
4132 4317
4133{ "lfsux", X(31,567), X_MASK, COM, { FRT, RAS, RB } }, 4318{ "lfsux", X(31,567), X_MASK, COM, { FRT, RAS, RB } },
@@ -4136,8 +4321,8 @@ const struct powerpc_opcode powerpc_opcodes[] = {
4136 4321
4137{ "mfsr", X(31,595), XRB_MASK|(1<<20), COM32, { RT, SR } }, 4322{ "mfsr", X(31,595), XRB_MASK|(1<<20), COM32, { RT, SR } },
4138 4323
4139{ "lswi", X(31,597), X_MASK, PPCCOM, { RT, RA, NB } }, 4324{ "lswi", X(31,597), X_MASK, PPCCOM, { RT, RA0, NB } },
4140{ "lsi", X(31,597), X_MASK, PWRCOM, { RT, RA, NB } }, 4325{ "lsi", X(31,597), X_MASK, PWRCOM, { RT, RA0, NB } },
4141 4326
4142{ "lwsync", XSYNC(31,598,1), 0xffffffff, PPC, { 0 } }, 4327{ "lwsync", XSYNC(31,598,1), 0xffffffff, PPC, { 0 } },
4143{ "ptesync", XSYNC(31,598,2), 0xffffffff, PPC64, { 0 } }, 4328{ "ptesync", XSYNC(31,598,2), 0xffffffff, PPC64, { 0 } },
@@ -4145,9 +4330,11 @@ const struct powerpc_opcode powerpc_opcodes[] = {
4145{ "sync", X(31,598), XSYNC_MASK, PPCCOM, { LS } }, 4330{ "sync", X(31,598), XSYNC_MASK, PPCCOM, { LS } },
4146{ "dcs", X(31,598), 0xffffffff, PWRCOM, { 0 } }, 4331{ "dcs", X(31,598), 0xffffffff, PWRCOM, { 0 } },
4147 4332
4148{ "lfdx", X(31,599), X_MASK, COM, { FRT, RA, RB } }, 4333{ "lfdx", X(31,599), X_MASK, COM, { FRT, RA0, RB } },
4334
4335{ "lfdxe", X(31,607), X_MASK, BOOKE64, { FRT, RA0, RB } },
4149 4336
4150{ "lfdxe", X(31,607), X_MASK, BOOKE64, { FRT, RA, RB } }, 4337{ "mffgpr", XRC(31,607,0), XRA_MASK, POWER6, { FRT, RB } },
4151 4338
4152{ "mfsri", X(31,627), X_MASK, PWRCOM, { RT, RA, RB } }, 4339{ "mfsri", X(31,627), X_MASK, PWRCOM, { RT, RA, RB } },
4153 4340
@@ -4159,13 +4346,15 @@ const struct powerpc_opcode powerpc_opcodes[] = {
4159 4346
4160{ "mfsrin", X(31,659), XRA_MASK, PPC32, { RT, RB } }, 4347{ "mfsrin", X(31,659), XRA_MASK, PPC32, { RT, RB } },
4161 4348
4162{ "stswx", X(31,661), X_MASK, PPCCOM, { RS, RA, RB } }, 4349{ "stdbrx", X(31,660), X_MASK, CELL, { RS, RA0, RB } },
4163{ "stsx", X(31,661), X_MASK, PWRCOM, { RS, RA, RB } }, 4350
4351{ "stswx", X(31,661), X_MASK, PPCCOM, { RS, RA0, RB } },
4352{ "stsx", X(31,661), X_MASK, PWRCOM, { RS, RA0, RB } },
4164 4353
4165{ "stwbrx", X(31,662), X_MASK, PPCCOM, { RS, RA, RB } }, 4354{ "stwbrx", X(31,662), X_MASK, PPCCOM, { RS, RA0, RB } },
4166{ "stbrx", X(31,662), X_MASK, PWRCOM, { RS, RA, RB } }, 4355{ "stbrx", X(31,662), X_MASK, PWRCOM, { RS, RA0, RB } },
4167 4356
4168{ "stfsx", X(31,663), X_MASK, COM, { FRS, RA, RB } }, 4357{ "stfsx", X(31,663), X_MASK, COM, { FRS, RA0, RB } },
4169 4358
4170{ "srq", XRC(31,664,0), X_MASK, M601, { RA, RS, RB } }, 4359{ "srq", XRC(31,664,0), X_MASK, M601, { RA, RS, RB } },
4171{ "srq.", XRC(31,664,1), X_MASK, M601, { RA, RS, RB } }, 4360{ "srq.", XRC(31,664,1), X_MASK, M601, { RA, RS, RB } },
@@ -4173,9 +4362,9 @@ const struct powerpc_opcode powerpc_opcodes[] = {
4173{ "sre", XRC(31,665,0), X_MASK, M601, { RA, RS, RB } }, 4362{ "sre", XRC(31,665,0), X_MASK, M601, { RA, RS, RB } },
4174{ "sre.", XRC(31,665,1), X_MASK, M601, { RA, RS, RB } }, 4363{ "sre.", XRC(31,665,1), X_MASK, M601, { RA, RS, RB } },
4175 4364
4176{ "stwbrxe", X(31,670), X_MASK, BOOKE64, { RS, RA, RB } }, 4365{ "stwbrxe", X(31,670), X_MASK, BOOKE64, { RS, RA0, RB } },
4177 4366
4178{ "stfsxe", X(31,671), X_MASK, BOOKE64, { FRS, RA, RB } }, 4367{ "stfsxe", X(31,671), X_MASK, BOOKE64, { FRS, RA0, RB } },
4179 4368
4180{ "stfsux", X(31,695), X_MASK, COM, { FRS, RAS, RB } }, 4369{ "stfsux", X(31,695), X_MASK, COM, { FRS, RAS, RB } },
4181 4370
@@ -4184,10 +4373,10 @@ const struct powerpc_opcode powerpc_opcodes[] = {
4184 4373
4185{ "stfsuxe", X(31,703), X_MASK, BOOKE64, { FRS, RAS, RB } }, 4374{ "stfsuxe", X(31,703), X_MASK, BOOKE64, { FRS, RAS, RB } },
4186 4375
4187{ "stswi", X(31,725), X_MASK, PPCCOM, { RS, RA, NB } }, 4376{ "stswi", X(31,725), X_MASK, PPCCOM, { RS, RA0, NB } },
4188{ "stsi", X(31,725), X_MASK, PWRCOM, { RS, RA, NB } }, 4377{ "stsi", X(31,725), X_MASK, PWRCOM, { RS, RA0, NB } },
4189 4378
4190{ "stfdx", X(31,727), X_MASK, COM, { FRS, RA, RB } }, 4379{ "stfdx", X(31,727), X_MASK, COM, { FRS, RA0, RB } },
4191 4380
4192{ "srlq", XRC(31,728,0), X_MASK, M601, { RA, RS, RB } }, 4381{ "srlq", XRC(31,728,0), X_MASK, M601, { RA, RS, RB } },
4193{ "srlq.", XRC(31,728,1), X_MASK, M601, { RA, RS, RB } }, 4382{ "srlq.", XRC(31,728,1), X_MASK, M601, { RA, RS, RB } },
@@ -4195,7 +4384,9 @@ const struct powerpc_opcode powerpc_opcodes[] = {
4195{ "sreq", XRC(31,729,0), X_MASK, M601, { RA, RS, RB } }, 4384{ "sreq", XRC(31,729,0), X_MASK, M601, { RA, RS, RB } },
4196{ "sreq.", XRC(31,729,1), X_MASK, M601, { RA, RS, RB } }, 4385{ "sreq.", XRC(31,729,1), X_MASK, M601, { RA, RS, RB } },
4197 4386
4198{ "stfdxe", X(31,735), X_MASK, BOOKE64, { FRS, RA, RB } }, 4387{ "stfdxe", X(31,735), X_MASK, BOOKE64, { FRS, RA0, RB } },
4388
4389{ "mftgpr", XRC(31,735,0), XRA_MASK, POWER6, { RT, FRB } },
4199 4390
4200{ "dcba", X(31,758), XRT_MASK, PPC405 | BOOKE, { RA, RB } }, 4391{ "dcba", X(31,758), XRT_MASK, PPC405 | BOOKE, { RA, RB } },
4201 4392
@@ -4211,7 +4402,9 @@ const struct powerpc_opcode powerpc_opcodes[] = {
4211{ "tlbivax", X(31,786), XRT_MASK, BOOKE, { RA, RB } }, 4402{ "tlbivax", X(31,786), XRT_MASK, BOOKE, { RA, RB } },
4212{ "tlbivaxe",X(31,787), XRT_MASK, BOOKE64, { RA, RB } }, 4403{ "tlbivaxe",X(31,787), XRT_MASK, BOOKE64, { RA, RB } },
4213 4404
4214{ "lhbrx", X(31,790), X_MASK, COM, { RT, RA, RB } }, 4405{ "lwzcix", X(31,789), X_MASK, POWER6, { RT, RA0, RB } },
4406
4407{ "lhbrx", X(31,790), X_MASK, COM, { RT, RA0, RB } },
4215 4408
4216{ "sraw", XRC(31,792,0), X_MASK, PPCCOM, { RA, RS, RB } }, 4409{ "sraw", XRC(31,792,0), X_MASK, PPCCOM, { RA, RS, RB } },
4217{ "sra", XRC(31,792,0), X_MASK, PWRCOM, { RA, RS, RB } }, 4410{ "sra", XRC(31,792,0), X_MASK, PWRCOM, { RA, RS, RB } },
@@ -4221,13 +4414,15 @@ const struct powerpc_opcode powerpc_opcodes[] = {
4221{ "srad", XRC(31,794,0), X_MASK, PPC64, { RA, RS, RB } }, 4414{ "srad", XRC(31,794,0), X_MASK, PPC64, { RA, RS, RB } },
4222{ "srad.", XRC(31,794,1), X_MASK, PPC64, { RA, RS, RB } }, 4415{ "srad.", XRC(31,794,1), X_MASK, PPC64, { RA, RS, RB } },
4223 4416
4224{ "lhbrxe", X(31,798), X_MASK, BOOKE64, { RT, RA, RB } }, 4417{ "lhbrxe", X(31,798), X_MASK, BOOKE64, { RT, RA0, RB } },
4225 4418
4226{ "ldxe", X(31,799), X_MASK, BOOKE64, { RT, RA, RB } }, 4419{ "ldxe", X(31,799), X_MASK, BOOKE64, { RT, RA0, RB } },
4227{ "lduxe", X(31,831), X_MASK, BOOKE64, { RT, RA, RB } }, 4420{ "lduxe", X(31,831), X_MASK, BOOKE64, { RT, RA0, RB } },
4228 4421
4229{ "rac", X(31,818), X_MASK, PWRCOM, { RT, RA, RB } }, 4422{ "rac", X(31,818), X_MASK, PWRCOM, { RT, RA, RB } },
4230 4423
4424{ "lhzcix", X(31,821), X_MASK, POWER6, { RT, RA0, RB } },
4425
4231{ "dss", XDSS(31,822,0), XDSS_MASK, PPCVEC, { STRM } }, 4426{ "dss", XDSS(31,822,0), XDSS_MASK, PPCVEC, { STRM } },
4232{ "dssall", XDSS(31,822,1), XDSS_MASK, PPCVEC, { 0 } }, 4427{ "dssall", XDSS(31,822,1), XDSS_MASK, PPCVEC, { 0 } },
4233 4428
@@ -4238,19 +4433,25 @@ const struct powerpc_opcode powerpc_opcodes[] = {
4238 4433
4239{ "slbmfev", X(31,851), XRA_MASK, PPC64, { RT, RB } }, 4434{ "slbmfev", X(31,851), XRA_MASK, PPC64, { RT, RB } },
4240 4435
4436{ "lbzcix", X(31,853), X_MASK, POWER6, { RT, RA0, RB } },
4437
4241{ "mbar", X(31,854), X_MASK, BOOKE, { MO } }, 4438{ "mbar", X(31,854), X_MASK, BOOKE, { MO } },
4242{ "eieio", X(31,854), 0xffffffff, PPC, { 0 } }, 4439{ "eieio", X(31,854), 0xffffffff, PPC, { 0 } },
4243 4440
4244{ "tlbsx", XRC(31,914,0), X_MASK, BOOKE, { RA, RB } }, 4441{ "lfiwax", X(31,855), X_MASK, POWER6, { FRT, RA0, RB } },
4245{ "tlbsx", XRC(31,914,0), X_MASK, PPC403, { RT, RA, RB } }, 4442
4246{ "tlbsx.", XRC(31,914,1), X_MASK, BOOKE, { RA, RB } }, 4443{ "ldcix", X(31,885), X_MASK, POWER6, { RT, RA0, RB } },
4247{ "tlbsx.", XRC(31,914,1), X_MASK, PPC403, { RT, RA, RB } }, 4444
4445{ "tlbsx", XRC(31,914,0), X_MASK, PPC403|BOOKE, { RTO, RA, RB } },
4446{ "tlbsx.", XRC(31,914,1), X_MASK, PPC403|BOOKE, { RTO, RA, RB } },
4248{ "tlbsxe", XRC(31,915,0), X_MASK, BOOKE64, { RA, RB } }, 4447{ "tlbsxe", XRC(31,915,0), X_MASK, BOOKE64, { RA, RB } },
4249{ "tlbsxe.", XRC(31,915,1), X_MASK, BOOKE64, { RA, RB } }, 4448{ "tlbsxe.", XRC(31,915,1), X_MASK, BOOKE64, { RA, RB } },
4250 4449
4251{ "slbmfee", X(31,915), XRA_MASK, PPC64, { RT, RB } }, 4450{ "slbmfee", X(31,915), XRA_MASK, PPC64, { RT, RB } },
4252 4451
4253{ "sthbrx", X(31,918), X_MASK, COM, { RS, RA, RB } }, 4452{ "stwcix", X(31,917), X_MASK, POWER6, { RS, RA0, RB } },
4453
4454{ "sthbrx", X(31,918), X_MASK, COM, { RS, RA0, RB } },
4254 4455
4255{ "sraq", XRC(31,920,0), X_MASK, M601, { RA, RS, RB } }, 4456{ "sraq", XRC(31,920,0), X_MASK, M601, { RA, RS, RB } },
4256{ "sraq.", XRC(31,920,1), X_MASK, M601, { RA, RS, RB } }, 4457{ "sraq.", XRC(31,920,1), X_MASK, M601, { RA, RS, RB } },
@@ -4263,14 +4464,15 @@ const struct powerpc_opcode powerpc_opcodes[] = {
4263{ "extsh.", XRC(31,922,1), XRB_MASK, PPCCOM, { RA, RS } }, 4464{ "extsh.", XRC(31,922,1), XRB_MASK, PPCCOM, { RA, RS } },
4264{ "exts.", XRC(31,922,1), XRB_MASK, PWRCOM, { RA, RS } }, 4465{ "exts.", XRC(31,922,1), XRB_MASK, PWRCOM, { RA, RS } },
4265 4466
4266{ "sthbrxe", X(31,926), X_MASK, BOOKE64, { RS, RA, RB } }, 4467{ "sthbrxe", X(31,926), X_MASK, BOOKE64, { RS, RA0, RB } },
4267 4468
4268{ "stdxe", X(31,927), X_MASK, BOOKE64, { RS, RA, RB } }, 4469{ "stdxe", X(31,927), X_MASK, BOOKE64, { RS, RA0, RB } },
4269 4470
4270{ "tlbrehi", XTLB(31,946,0), XTLB_MASK, PPC403, { RT, RA } }, 4471{ "tlbrehi", XTLB(31,946,0), XTLB_MASK, PPC403, { RT, RA } },
4271{ "tlbrelo", XTLB(31,946,1), XTLB_MASK, PPC403, { RT, RA } }, 4472{ "tlbrelo", XTLB(31,946,1), XTLB_MASK, PPC403, { RT, RA } },
4272{ "tlbre", X(31,946), X_MASK, BOOKE, { 0 } }, 4473{ "tlbre", X(31,946), X_MASK, PPC403|BOOKE, { RSO, RAOPT, SHO } },
4273{ "tlbre", X(31,946), X_MASK, PPC403, { RS, RA, SH } }, 4474
4475{ "sthcix", X(31,949), X_MASK, POWER6, { RS, RA0, RB } },
4274 4476
4275{ "sraiq", XRC(31,952,0), X_MASK, M601, { RA, RS, SH } }, 4477{ "sraiq", XRC(31,952,0), X_MASK, M601, { RA, RS, SH } },
4276{ "sraiq.", XRC(31,952,1), X_MASK, M601, { RA, RS, SH } }, 4478{ "sraiq.", XRC(31,952,1), X_MASK, M601, { RA, RS, SH } },
@@ -4284,13 +4486,14 @@ const struct powerpc_opcode powerpc_opcodes[] = {
4284 4486
4285{ "tlbwehi", XTLB(31,978,0), XTLB_MASK, PPC403, { RT, RA } }, 4487{ "tlbwehi", XTLB(31,978,0), XTLB_MASK, PPC403, { RT, RA } },
4286{ "tlbwelo", XTLB(31,978,1), XTLB_MASK, PPC403, { RT, RA } }, 4488{ "tlbwelo", XTLB(31,978,1), XTLB_MASK, PPC403, { RT, RA } },
4287{ "tlbwe", X(31,978), X_MASK, BOOKE, { 0 } }, 4489{ "tlbwe", X(31,978), X_MASK, PPC403|BOOKE, { RSO, RAOPT, SHO } },
4288{ "tlbwe", X(31,978), X_MASK, PPC403, { RS, RA, SH } },
4289{ "tlbld", X(31,978), XRTRA_MASK, PPC, { RB } }, 4490{ "tlbld", X(31,978), XRTRA_MASK, PPC, { RB } },
4290 4491
4492{ "stbcix", X(31,981), X_MASK, POWER6, { RS, RA0, RB } },
4493
4291{ "icbi", X(31,982), XRT_MASK, PPC, { RA, RB } }, 4494{ "icbi", X(31,982), XRT_MASK, PPC, { RA, RB } },
4292 4495
4293{ "stfiwx", X(31,983), X_MASK, PPC, { FRS, RA, RB } }, 4496{ "stfiwx", X(31,983), X_MASK, PPC, { FRS, RA0, RB } },
4294 4497
4295{ "extsw", XRC(31,986,0), XRB_MASK, PPC64 | BOOKE64,{ RA, RS } }, 4498{ "extsw", XRC(31,986,0), XRB_MASK, PPC64 | BOOKE64,{ RA, RS } },
4296{ "extsw.", XRC(31,986,1), XRB_MASK, PPC64, { RA, RS } }, 4499{ "extsw.", XRC(31,986,1), XRB_MASK, PPC64, { RA, RS } },
@@ -4298,10 +4501,13 @@ const struct powerpc_opcode powerpc_opcodes[] = {
4298{ "icread", X(31,998), XRT_MASK, PPC403|PPC440, { RA, RB } }, 4501{ "icread", X(31,998), XRT_MASK, PPC403|PPC440, { RA, RB } },
4299 4502
4300{ "icbie", X(31,990), XRT_MASK, BOOKE64, { RA, RB } }, 4503{ "icbie", X(31,990), XRT_MASK, BOOKE64, { RA, RB } },
4301{ "stfiwxe", X(31,991), X_MASK, BOOKE64, { FRS, RA, RB } }, 4504{ "stfiwxe", X(31,991), X_MASK, BOOKE64, { FRS, RA0, RB } },
4302 4505
4303{ "tlbli", X(31,1010), XRTRA_MASK, PPC, { RB } }, 4506{ "tlbli", X(31,1010), XRTRA_MASK, PPC, { RB } },
4304 4507
4508{ "stdcix", X(31,1013), X_MASK, POWER6, { RS, RA0, RB } },
4509
4510{ "dcbzl", XOPL(31,1014,1), XRT_MASK,POWER4, { RA, RB } },
4305{ "dcbz", X(31,1014), XRT_MASK, PPC, { RA, RB } }, 4511{ "dcbz", X(31,1014), XRT_MASK, PPC, { RA, RB } },
4306{ "dclz", X(31,1014), XRT_MASK, PPC, { RA, RB } }, 4512{ "dclz", X(31,1014), XRT_MASK, PPC, { RA, RB } },
4307 4513
@@ -4320,86 +4526,104 @@ const struct powerpc_opcode powerpc_opcodes[] = {
4320{ "stvx", X(31, 231), X_MASK, PPCVEC, { VS, RA, RB } }, 4526{ "stvx", X(31, 231), X_MASK, PPCVEC, { VS, RA, RB } },
4321{ "stvxl", X(31, 487), X_MASK, PPCVEC, { VS, RA, RB } }, 4527{ "stvxl", X(31, 487), X_MASK, PPCVEC, { VS, RA, RB } },
4322 4528
4323{ "lwz", OP(32), OP_MASK, PPCCOM, { RT, D, RA } }, 4529/* New load/store left/right index vector instructions that are in the Cell only. */
4324{ "l", OP(32), OP_MASK, PWRCOM, { RT, D, RA } }, 4530{ "lvlx", X(31, 519), X_MASK, CELL, { VD, RA0, RB } },
4531{ "lvlxl", X(31, 775), X_MASK, CELL, { VD, RA0, RB } },
4532{ "lvrx", X(31, 551), X_MASK, CELL, { VD, RA0, RB } },
4533{ "lvrxl", X(31, 807), X_MASK, CELL, { VD, RA0, RB } },
4534{ "stvlx", X(31, 647), X_MASK, CELL, { VS, RA0, RB } },
4535{ "stvlxl", X(31, 903), X_MASK, CELL, { VS, RA0, RB } },
4536{ "stvrx", X(31, 679), X_MASK, CELL, { VS, RA0, RB } },
4537{ "stvrxl", X(31, 935), X_MASK, CELL, { VS, RA0, RB } },
4538
4539{ "lwz", OP(32), OP_MASK, PPCCOM, { RT, D, RA0 } },
4540{ "l", OP(32), OP_MASK, PWRCOM, { RT, D, RA0 } },
4325 4541
4326{ "lwzu", OP(33), OP_MASK, PPCCOM, { RT, D, RAL } }, 4542{ "lwzu", OP(33), OP_MASK, PPCCOM, { RT, D, RAL } },
4327{ "lu", OP(33), OP_MASK, PWRCOM, { RT, D, RA } }, 4543{ "lu", OP(33), OP_MASK, PWRCOM, { RT, D, RA0 } },
4328 4544
4329{ "lbz", OP(34), OP_MASK, COM, { RT, D, RA } }, 4545{ "lbz", OP(34), OP_MASK, COM, { RT, D, RA0 } },
4330 4546
4331{ "lbzu", OP(35), OP_MASK, COM, { RT, D, RAL } }, 4547{ "lbzu", OP(35), OP_MASK, COM, { RT, D, RAL } },
4332 4548
4333{ "stw", OP(36), OP_MASK, PPCCOM, { RS, D, RA } }, 4549{ "stw", OP(36), OP_MASK, PPCCOM, { RS, D, RA0 } },
4334{ "st", OP(36), OP_MASK, PWRCOM, { RS, D, RA } }, 4550{ "st", OP(36), OP_MASK, PWRCOM, { RS, D, RA0 } },
4335 4551
4336{ "stwu", OP(37), OP_MASK, PPCCOM, { RS, D, RAS } }, 4552{ "stwu", OP(37), OP_MASK, PPCCOM, { RS, D, RAS } },
4337{ "stu", OP(37), OP_MASK, PWRCOM, { RS, D, RA } }, 4553{ "stu", OP(37), OP_MASK, PWRCOM, { RS, D, RA0 } },
4338 4554
4339{ "stb", OP(38), OP_MASK, COM, { RS, D, RA } }, 4555{ "stb", OP(38), OP_MASK, COM, { RS, D, RA0 } },
4340 4556
4341{ "stbu", OP(39), OP_MASK, COM, { RS, D, RAS } }, 4557{ "stbu", OP(39), OP_MASK, COM, { RS, D, RAS } },
4342 4558
4343{ "lhz", OP(40), OP_MASK, COM, { RT, D, RA } }, 4559{ "lhz", OP(40), OP_MASK, COM, { RT, D, RA0 } },
4344 4560
4345{ "lhzu", OP(41), OP_MASK, COM, { RT, D, RAL } }, 4561{ "lhzu", OP(41), OP_MASK, COM, { RT, D, RAL } },
4346 4562
4347{ "lha", OP(42), OP_MASK, COM, { RT, D, RA } }, 4563{ "lha", OP(42), OP_MASK, COM, { RT, D, RA0 } },
4348 4564
4349{ "lhau", OP(43), OP_MASK, COM, { RT, D, RAL } }, 4565{ "lhau", OP(43), OP_MASK, COM, { RT, D, RAL } },
4350 4566
4351{ "sth", OP(44), OP_MASK, COM, { RS, D, RA } }, 4567{ "sth", OP(44), OP_MASK, COM, { RS, D, RA0 } },
4352 4568
4353{ "sthu", OP(45), OP_MASK, COM, { RS, D, RAS } }, 4569{ "sthu", OP(45), OP_MASK, COM, { RS, D, RAS } },
4354 4570
4355{ "lmw", OP(46), OP_MASK, PPCCOM, { RT, D, RAM } }, 4571{ "lmw", OP(46), OP_MASK, PPCCOM, { RT, D, RAM } },
4356{ "lm", OP(46), OP_MASK, PWRCOM, { RT, D, RA } }, 4572{ "lm", OP(46), OP_MASK, PWRCOM, { RT, D, RA0 } },
4357 4573
4358{ "stmw", OP(47), OP_MASK, PPCCOM, { RS, D, RA } }, 4574{ "stmw", OP(47), OP_MASK, PPCCOM, { RS, D, RA0 } },
4359{ "stm", OP(47), OP_MASK, PWRCOM, { RS, D, RA } }, 4575{ "stm", OP(47), OP_MASK, PWRCOM, { RS, D, RA0 } },
4360 4576
4361{ "lfs", OP(48), OP_MASK, COM, { FRT, D, RA } }, 4577{ "lfs", OP(48), OP_MASK, COM, { FRT, D, RA0 } },
4362 4578
4363{ "lfsu", OP(49), OP_MASK, COM, { FRT, D, RAS } }, 4579{ "lfsu", OP(49), OP_MASK, COM, { FRT, D, RAS } },
4364 4580
4365{ "lfd", OP(50), OP_MASK, COM, { FRT, D, RA } }, 4581{ "lfd", OP(50), OP_MASK, COM, { FRT, D, RA0 } },
4366 4582
4367{ "lfdu", OP(51), OP_MASK, COM, { FRT, D, RAS } }, 4583{ "lfdu", OP(51), OP_MASK, COM, { FRT, D, RAS } },
4368 4584
4369{ "stfs", OP(52), OP_MASK, COM, { FRS, D, RA } }, 4585{ "stfs", OP(52), OP_MASK, COM, { FRS, D, RA0 } },
4370 4586
4371{ "stfsu", OP(53), OP_MASK, COM, { FRS, D, RAS } }, 4587{ "stfsu", OP(53), OP_MASK, COM, { FRS, D, RAS } },
4372 4588
4373{ "stfd", OP(54), OP_MASK, COM, { FRS, D, RA } }, 4589{ "stfd", OP(54), OP_MASK, COM, { FRS, D, RA0 } },
4374 4590
4375{ "stfdu", OP(55), OP_MASK, COM, { FRS, D, RAS } }, 4591{ "stfdu", OP(55), OP_MASK, COM, { FRS, D, RAS } },
4376 4592
4377{ "lq", OP(56), OP_MASK, POWER4, { RTQ, DQ, RAQ } }, 4593{ "lq", OP(56), OP_MASK, POWER4, { RTQ, DQ, RAQ } },
4378 4594
4379{ "lfq", OP(56), OP_MASK, POWER2, { FRT, D, RA } }, 4595{ "lfq", OP(56), OP_MASK, POWER2, { FRT, D, RA0 } },
4596
4597{ "lfqu", OP(57), OP_MASK, POWER2, { FRT, D, RA0 } },
4380 4598
4381{ "lfqu", OP(57), OP_MASK, POWER2, { FRT, D, RA } }, 4599{ "lfdp", OP(57), OP_MASK, POWER6, { FRT, D, RA0 } },
4382 4600
4383{ "lbze", DEO(58,0), DE_MASK, BOOKE64, { RT, DE, RA } }, 4601{ "lbze", DEO(58,0), DE_MASK, BOOKE64, { RT, DE, RA0 } },
4384{ "lbzue", DEO(58,1), DE_MASK, BOOKE64, { RT, DE, RAL } }, 4602{ "lbzue", DEO(58,1), DE_MASK, BOOKE64, { RT, DE, RAL } },
4385{ "lhze", DEO(58,2), DE_MASK, BOOKE64, { RT, DE, RA } }, 4603{ "lhze", DEO(58,2), DE_MASK, BOOKE64, { RT, DE, RA0 } },
4386{ "lhzue", DEO(58,3), DE_MASK, BOOKE64, { RT, DE, RAL } }, 4604{ "lhzue", DEO(58,3), DE_MASK, BOOKE64, { RT, DE, RAL } },
4387{ "lhae", DEO(58,4), DE_MASK, BOOKE64, { RT, DE, RA } }, 4605{ "lhae", DEO(58,4), DE_MASK, BOOKE64, { RT, DE, RA0 } },
4388{ "lhaue", DEO(58,5), DE_MASK, BOOKE64, { RT, DE, RAL } }, 4606{ "lhaue", DEO(58,5), DE_MASK, BOOKE64, { RT, DE, RAL } },
4389{ "lwze", DEO(58,6), DE_MASK, BOOKE64, { RT, DE, RA } }, 4607{ "lwze", DEO(58,6), DE_MASK, BOOKE64, { RT, DE, RA0 } },
4390{ "lwzue", DEO(58,7), DE_MASK, BOOKE64, { RT, DE, RAL } }, 4608{ "lwzue", DEO(58,7), DE_MASK, BOOKE64, { RT, DE, RAL } },
4391{ "stbe", DEO(58,8), DE_MASK, BOOKE64, { RS, DE, RA } }, 4609{ "stbe", DEO(58,8), DE_MASK, BOOKE64, { RS, DE, RA0 } },
4392{ "stbue", DEO(58,9), DE_MASK, BOOKE64, { RS, DE, RAS } }, 4610{ "stbue", DEO(58,9), DE_MASK, BOOKE64, { RS, DE, RAS } },
4393{ "sthe", DEO(58,10), DE_MASK, BOOKE64, { RS, DE, RA } }, 4611{ "sthe", DEO(58,10), DE_MASK, BOOKE64, { RS, DE, RA0 } },
4394{ "sthue", DEO(58,11), DE_MASK, BOOKE64, { RS, DE, RAS } }, 4612{ "sthue", DEO(58,11), DE_MASK, BOOKE64, { RS, DE, RAS } },
4395{ "stwe", DEO(58,14), DE_MASK, BOOKE64, { RS, DE, RA } }, 4613{ "stwe", DEO(58,14), DE_MASK, BOOKE64, { RS, DE, RA0 } },
4396{ "stwue", DEO(58,15), DE_MASK, BOOKE64, { RS, DE, RAS } }, 4614{ "stwue", DEO(58,15), DE_MASK, BOOKE64, { RS, DE, RAS } },
4397 4615
4398{ "ld", DSO(58,0), DS_MASK, PPC64, { RT, DS, RA } }, 4616{ "ld", DSO(58,0), DS_MASK, PPC64, { RT, DS, RA0 } },
4399 4617
4400{ "ldu", DSO(58,1), DS_MASK, PPC64, { RT, DS, RAL } }, 4618{ "ldu", DSO(58,1), DS_MASK, PPC64, { RT, DS, RAL } },
4401 4619
4402{ "lwa", DSO(58,2), DS_MASK, PPC64, { RT, DS, RA } }, 4620{ "lwa", DSO(58,2), DS_MASK, PPC64, { RT, DS, RA0 } },
4621
4622{ "dadd", XRC(59,2,0), X_MASK, POWER6, { FRT, FRA, FRB } },
4623{ "dadd.", XRC(59,2,1), X_MASK, POWER6, { FRT, FRA, FRB } },
4624
4625{ "dqua", ZRC(59,3,0), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } },
4626{ "dqua.", ZRC(59,3,1), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } },
4403 4627
4404{ "fdivs", A(59,18,0), AFRC_MASK, PPC, { FRT, FRA, FRB } }, 4628{ "fdivs", A(59,18,0), AFRC_MASK, PPC, { FRT, FRA, FRB } },
4405{ "fdivs.", A(59,18,1), AFRC_MASK, PPC, { FRT, FRA, FRB } }, 4629{ "fdivs.", A(59,18,1), AFRC_MASK, PPC, { FRT, FRA, FRB } },
@@ -4413,12 +4637,15 @@ const struct powerpc_opcode powerpc_opcodes[] = {
4413{ "fsqrts", A(59,22,0), AFRAFRC_MASK, PPC, { FRT, FRB } }, 4637{ "fsqrts", A(59,22,0), AFRAFRC_MASK, PPC, { FRT, FRB } },
4414{ "fsqrts.", A(59,22,1), AFRAFRC_MASK, PPC, { FRT, FRB } }, 4638{ "fsqrts.", A(59,22,1), AFRAFRC_MASK, PPC, { FRT, FRB } },
4415 4639
4416{ "fres", A(59,24,0), AFRAFRC_MASK, PPC, { FRT, FRB } }, 4640{ "fres", A(59,24,0), AFRALFRC_MASK, PPC, { FRT, FRB, A_L } },
4417{ "fres.", A(59,24,1), AFRAFRC_MASK, PPC, { FRT, FRB } }, 4641{ "fres.", A(59,24,1), AFRALFRC_MASK, PPC, { FRT, FRB, A_L } },
4418 4642
4419{ "fmuls", A(59,25,0), AFRB_MASK, PPC, { FRT, FRA, FRC } }, 4643{ "fmuls", A(59,25,0), AFRB_MASK, PPC, { FRT, FRA, FRC } },
4420{ "fmuls.", A(59,25,1), AFRB_MASK, PPC, { FRT, FRA, FRC } }, 4644{ "fmuls.", A(59,25,1), AFRB_MASK, PPC, { FRT, FRA, FRC } },
4421 4645
4646{ "frsqrtes", A(59,26,0), AFRALFRC_MASK,POWER5, { FRT, FRB, A_L } },
4647{ "frsqrtes.",A(59,26,1), AFRALFRC_MASK,POWER5, { FRT, FRB, A_L } },
4648
4422{ "fmsubs", A(59,28,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, 4649{ "fmsubs", A(59,28,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
4423{ "fmsubs.", A(59,28,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, 4650{ "fmsubs.", A(59,28,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
4424 4651
@@ -4431,31 +4658,103 @@ const struct powerpc_opcode powerpc_opcodes[] = {
4431{ "fnmadds", A(59,31,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, 4658{ "fnmadds", A(59,31,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
4432{ "fnmadds.",A(59,31,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, 4659{ "fnmadds.",A(59,31,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
4433 4660
4661{ "dmul", XRC(59,34,0), X_MASK, POWER6, { FRT, FRA, FRB } },
4662{ "dmul.", XRC(59,34,1), X_MASK, POWER6, { FRT, FRA, FRB } },
4663
4664{ "drrnd", ZRC(59,35,0), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } },
4665{ "drrnd.", ZRC(59,35,1), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } },
4666
4667{ "dscli", ZRC(59,66,0), Z_MASK, POWER6, { FRT, FRA, SH16 } },
4668{ "dscli.", ZRC(59,66,1), Z_MASK, POWER6, { FRT, FRA, SH16 } },
4669
4670{ "dquai", ZRC(59,67,0), Z_MASK, POWER6, { TE, FRT, FRB, RMC } },
4671{ "dquai.", ZRC(59,67,1), Z_MASK, POWER6, { TE, FRT, FRB, RMC } },
4672
4673{ "dscri", ZRC(59,98,0), Z_MASK, POWER6, { FRT, FRA, SH16 } },
4674{ "dscri.", ZRC(59,98,1), Z_MASK, POWER6, { FRT, FRA, SH16 } },
4675
4676{ "drintx", ZRC(59,99,0), Z_MASK, POWER6, { R, FRT, FRB, RMC } },
4677{ "drintx.", ZRC(59,99,1), Z_MASK, POWER6, { R, FRT, FRB, RMC } },
4678
4679{ "dcmpo", X(59,130), X_MASK, POWER6, { BF, FRA, FRB } },
4680
4681{ "dtstex", X(59,162), X_MASK, POWER6, { BF, FRA, FRB } },
4682{ "dtstdc", Z(59,194), Z_MASK, POWER6, { BF, FRA, DCM } },
4683{ "dtstdg", Z(59,226), Z_MASK, POWER6, { BF, FRA, DGM } },
4684
4685{ "drintn", ZRC(59,227,0), Z_MASK, POWER6, { R, FRT, FRB, RMC } },
4686{ "drintn.", ZRC(59,227,1), Z_MASK, POWER6, { R, FRT, FRB, RMC } },
4687
4688{ "dctdp", XRC(59,258,0), X_MASK, POWER6, { FRT, FRB } },
4689{ "dctdp.", XRC(59,258,1), X_MASK, POWER6, { FRT, FRB } },
4690
4691{ "dctfix", XRC(59,290,0), X_MASK, POWER6, { FRT, FRB } },
4692{ "dctfix.", XRC(59,290,1), X_MASK, POWER6, { FRT, FRB } },
4693
4694{ "ddedpd", XRC(59,322,0), X_MASK, POWER6, { SP, FRT, FRB } },
4695{ "ddedpd.", XRC(59,322,1), X_MASK, POWER6, { SP, FRT, FRB } },
4696
4697{ "dxex", XRC(59,354,0), X_MASK, POWER6, { FRT, FRB } },
4698{ "dxex.", XRC(59,354,1), X_MASK, POWER6, { FRT, FRB } },
4699
4700{ "dsub", XRC(59,514,0), X_MASK, POWER6, { FRT, FRA, FRB } },
4701{ "dsub.", XRC(59,514,1), X_MASK, POWER6, { FRT, FRA, FRB } },
4702
4703{ "ddiv", XRC(59,546,0), X_MASK, POWER6, { FRT, FRA, FRB } },
4704{ "ddiv.", XRC(59,546,1), X_MASK, POWER6, { FRT, FRA, FRB } },
4705
4706{ "dcmpu", X(59,642), X_MASK, POWER6, { BF, FRA, FRB } },
4707
4708{ "dtstsf", X(59,674), X_MASK, POWER6, { BF, FRA, FRB } },
4709
4710{ "drsp", XRC(59,770,0), X_MASK, POWER6, { FRT, FRB } },
4711{ "drsp.", XRC(59,770,1), X_MASK, POWER6, { FRT, FRB } },
4712
4713{ "dcffix", XRC(59,802,0), X_MASK, POWER6, { FRT, FRB } },
4714{ "dcffix.", XRC(59,802,1), X_MASK, POWER6, { FRT, FRB } },
4715
4716{ "denbcd", XRC(59,834,0), X_MASK, POWER6, { S, FRT, FRB } },
4717{ "denbcd.", XRC(59,834,1), X_MASK, POWER6, { S, FRT, FRB } },
4718
4719{ "diex", XRC(59,866,0), X_MASK, POWER6, { FRT, FRA, FRB } },
4720{ "diex.", XRC(59,866,1), X_MASK, POWER6, { FRT, FRA, FRB } },
4721
4434{ "stfq", OP(60), OP_MASK, POWER2, { FRS, D, RA } }, 4722{ "stfq", OP(60), OP_MASK, POWER2, { FRS, D, RA } },
4435 4723
4436{ "stfqu", OP(61), OP_MASK, POWER2, { FRS, D, RA } }, 4724{ "stfqu", OP(61), OP_MASK, POWER2, { FRS, D, RA } },
4437 4725
4438{ "lde", DEO(62,0), DE_MASK, BOOKE64, { RT, DES, RA } }, 4726{ "stfdp", OP(61), OP_MASK, POWER6, { FRT, D, RA0 } },
4439{ "ldue", DEO(62,1), DE_MASK, BOOKE64, { RT, DES, RA } }, 4727
4440{ "lfse", DEO(62,4), DE_MASK, BOOKE64, { FRT, DES, RA } }, 4728{ "lde", DEO(62,0), DE_MASK, BOOKE64, { RT, DES, RA0 } },
4729{ "ldue", DEO(62,1), DE_MASK, BOOKE64, { RT, DES, RA0 } },
4730{ "lfse", DEO(62,4), DE_MASK, BOOKE64, { FRT, DES, RA0 } },
4441{ "lfsue", DEO(62,5), DE_MASK, BOOKE64, { FRT, DES, RAS } }, 4731{ "lfsue", DEO(62,5), DE_MASK, BOOKE64, { FRT, DES, RAS } },
4442{ "lfde", DEO(62,6), DE_MASK, BOOKE64, { FRT, DES, RA } }, 4732{ "lfde", DEO(62,6), DE_MASK, BOOKE64, { FRT, DES, RA0 } },
4443{ "lfdue", DEO(62,7), DE_MASK, BOOKE64, { FRT, DES, RAS } }, 4733{ "lfdue", DEO(62,7), DE_MASK, BOOKE64, { FRT, DES, RAS } },
4444{ "stde", DEO(62,8), DE_MASK, BOOKE64, { RS, DES, RA } }, 4734{ "stde", DEO(62,8), DE_MASK, BOOKE64, { RS, DES, RA0 } },
4445{ "stdue", DEO(62,9), DE_MASK, BOOKE64, { RS, DES, RAS } }, 4735{ "stdue", DEO(62,9), DE_MASK, BOOKE64, { RS, DES, RAS } },
4446{ "stfse", DEO(62,12), DE_MASK, BOOKE64, { FRS, DES, RA } }, 4736{ "stfse", DEO(62,12), DE_MASK, BOOKE64, { FRS, DES, RA0 } },
4447{ "stfsue", DEO(62,13), DE_MASK, BOOKE64, { FRS, DES, RAS } }, 4737{ "stfsue", DEO(62,13), DE_MASK, BOOKE64, { FRS, DES, RAS } },
4448{ "stfde", DEO(62,14), DE_MASK, BOOKE64, { FRS, DES, RA } }, 4738{ "stfde", DEO(62,14), DE_MASK, BOOKE64, { FRS, DES, RA0 } },
4449{ "stfdue", DEO(62,15), DE_MASK, BOOKE64, { FRS, DES, RAS } }, 4739{ "stfdue", DEO(62,15), DE_MASK, BOOKE64, { FRS, DES, RAS } },
4450 4740
4451{ "std", DSO(62,0), DS_MASK, PPC64, { RS, DS, RA } }, 4741{ "std", DSO(62,0), DS_MASK, PPC64, { RS, DS, RA0 } },
4452 4742
4453{ "stdu", DSO(62,1), DS_MASK, PPC64, { RS, DS, RAS } }, 4743{ "stdu", DSO(62,1), DS_MASK, PPC64, { RS, DS, RAS } },
4454 4744
4455{ "stq", DSO(62,2), DS_MASK, POWER4, { RSQ, DS, RA } }, 4745{ "stq", DSO(62,2), DS_MASK, POWER4, { RSQ, DS, RA0 } },
4456 4746
4457{ "fcmpu", X(63,0), X_MASK|(3<<21), COM, { BF, FRA, FRB } }, 4747{ "fcmpu", X(63,0), X_MASK|(3<<21), COM, { BF, FRA, FRB } },
4458 4748
4749{ "daddq", XRC(63,2,0), X_MASK, POWER6, { FRT, FRA, FRB } },
4750{ "daddq.", XRC(63,2,1), X_MASK, POWER6, { FRT, FRA, FRB } },
4751
4752{ "dquaq", ZRC(63,3,0), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } },
4753{ "dquaq.", ZRC(63,3,1), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } },
4754
4755{ "fcpsgn", XRC(63,8,0), X_MASK, POWER6, { FRT, FRA, FRB } },
4756{ "fcpsgn.", XRC(63,8,1), X_MASK, POWER6, { FRT, FRA, FRB } },
4757
4459{ "frsp", XRC(63,12,0), XRA_MASK, COM, { FRT, FRB } }, 4758{ "frsp", XRC(63,12,0), XRA_MASK, COM, { FRT, FRB } },
4460{ "frsp.", XRC(63,12,1), XRA_MASK, COM, { FRT, FRB } }, 4759{ "frsp.", XRC(63,12,1), XRA_MASK, COM, { FRT, FRB } },
4461 4760
@@ -4490,13 +4789,16 @@ const struct powerpc_opcode powerpc_opcodes[] = {
4490{ "fsel", A(63,23,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, 4789{ "fsel", A(63,23,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
4491{ "fsel.", A(63,23,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, 4790{ "fsel.", A(63,23,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
4492 4791
4792{ "fre", A(63,24,0), AFRALFRC_MASK, POWER5, { FRT, FRB, A_L } },
4793{ "fre.", A(63,24,1), AFRALFRC_MASK, POWER5, { FRT, FRB, A_L } },
4794
4493{ "fmul", A(63,25,0), AFRB_MASK, PPCCOM, { FRT, FRA, FRC } }, 4795{ "fmul", A(63,25,0), AFRB_MASK, PPCCOM, { FRT, FRA, FRC } },
4494{ "fm", A(63,25,0), AFRB_MASK, PWRCOM, { FRT, FRA, FRC } }, 4796{ "fm", A(63,25,0), AFRB_MASK, PWRCOM, { FRT, FRA, FRC } },
4495{ "fmul.", A(63,25,1), AFRB_MASK, PPCCOM, { FRT, FRA, FRC } }, 4797{ "fmul.", A(63,25,1), AFRB_MASK, PPCCOM, { FRT, FRA, FRC } },
4496{ "fm.", A(63,25,1), AFRB_MASK, PWRCOM, { FRT, FRA, FRC } }, 4798{ "fm.", A(63,25,1), AFRB_MASK, PWRCOM, { FRT, FRA, FRC } },
4497 4799
4498{ "frsqrte", A(63,26,0), AFRAFRC_MASK, PPC, { FRT, FRB } }, 4800{ "frsqrte", A(63,26,0), AFRALFRC_MASK, PPC, { FRT, FRB, A_L } },
4499{ "frsqrte.",A(63,26,1), AFRAFRC_MASK, PPC, { FRT, FRB } }, 4801{ "frsqrte.",A(63,26,1), AFRALFRC_MASK, PPC, { FRT, FRB, A_L } },
4500 4802
4501{ "fmsub", A(63,28,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, 4803{ "fmsub", A(63,28,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } },
4502{ "fms", A(63,28,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, 4804{ "fms", A(63,28,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } },
@@ -4520,6 +4822,12 @@ const struct powerpc_opcode powerpc_opcodes[] = {
4520 4822
4521{ "fcmpo", X(63,32), X_MASK|(3<<21), COM, { BF, FRA, FRB } }, 4823{ "fcmpo", X(63,32), X_MASK|(3<<21), COM, { BF, FRA, FRB } },
4522 4824
4825{ "dmulq", XRC(63,34,0), X_MASK, POWER6, { FRT, FRA, FRB } },
4826{ "dmulq.", XRC(63,34,1), X_MASK, POWER6, { FRT, FRA, FRB } },
4827
4828{ "drrndq", ZRC(63,35,0), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } },
4829{ "drrndq.", ZRC(63,35,1), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } },
4830
4523{ "mtfsb1", XRC(63,38,0), XRARB_MASK, COM, { BT } }, 4831{ "mtfsb1", XRC(63,38,0), XRARB_MASK, COM, { BT } },
4524{ "mtfsb1.", XRC(63,38,1), XRARB_MASK, COM, { BT } }, 4832{ "mtfsb1.", XRC(63,38,1), XRARB_MASK, COM, { BT } },
4525 4833
@@ -4528,36 +4836,100 @@ const struct powerpc_opcode powerpc_opcodes[] = {
4528 4836
4529{ "mcrfs", X(63,64), XRB_MASK|(3<<21)|(3<<16), COM, { BF, BFA } }, 4837{ "mcrfs", X(63,64), XRB_MASK|(3<<21)|(3<<16), COM, { BF, BFA } },
4530 4838
4839{ "dscliq", ZRC(63,66,0), Z_MASK, POWER6, { FRT, FRA, SH16 } },
4840{ "dscliq.", ZRC(63,66,1), Z_MASK, POWER6, { FRT, FRA, SH16 } },
4841
4842{ "dquaiq", ZRC(63,67,0), Z_MASK, POWER6, { TE, FRT, FRB, RMC } },
4843{ "dquaiq.", ZRC(63,67,1), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } },
4844
4531{ "mtfsb0", XRC(63,70,0), XRARB_MASK, COM, { BT } }, 4845{ "mtfsb0", XRC(63,70,0), XRARB_MASK, COM, { BT } },
4532{ "mtfsb0.", XRC(63,70,1), XRARB_MASK, COM, { BT } }, 4846{ "mtfsb0.", XRC(63,70,1), XRARB_MASK, COM, { BT } },
4533 4847
4534{ "fmr", XRC(63,72,0), XRA_MASK, COM, { FRT, FRB } }, 4848{ "fmr", XRC(63,72,0), XRA_MASK, COM, { FRT, FRB } },
4535{ "fmr.", XRC(63,72,1), XRA_MASK, COM, { FRT, FRB } }, 4849{ "fmr.", XRC(63,72,1), XRA_MASK, COM, { FRT, FRB } },
4536 4850
4851{ "dscriq", ZRC(63,98,0), Z_MASK, POWER6, { FRT, FRA, SH16 } },
4852{ "dscriq.", ZRC(63,98,1), Z_MASK, POWER6, { FRT, FRA, SH16 } },
4853
4854{ "drintxq", ZRC(63,99,0), Z_MASK, POWER6, { R, FRT, FRB, RMC } },
4855{ "drintxq.",ZRC(63,99,1), Z_MASK, POWER6, { R, FRT, FRB, RMC } },
4856
4857{ "dcmpoq", X(63,130), X_MASK, POWER6, { BF, FRA, FRB } },
4858
4537{ "mtfsfi", XRC(63,134,0), XRA_MASK|(3<<21)|(1<<11), COM, { BF, U } }, 4859{ "mtfsfi", XRC(63,134,0), XRA_MASK|(3<<21)|(1<<11), COM, { BF, U } },
4538{ "mtfsfi.", XRC(63,134,1), XRA_MASK|(3<<21)|(1<<11), COM, { BF, U } }, 4860{ "mtfsfi.", XRC(63,134,1), XRA_MASK|(3<<21)|(1<<11), COM, { BF, U } },
4539 4861
4540{ "fnabs", XRC(63,136,0), XRA_MASK, COM, { FRT, FRB } }, 4862{ "fnabs", XRC(63,136,0), XRA_MASK, COM, { FRT, FRB } },
4541{ "fnabs.", XRC(63,136,1), XRA_MASK, COM, { FRT, FRB } }, 4863{ "fnabs.", XRC(63,136,1), XRA_MASK, COM, { FRT, FRB } },
4542 4864
4865{ "dtstexq", X(63,162), X_MASK, POWER6, { BF, FRA, FRB } },
4866{ "dtstdcq", Z(63,194), Z_MASK, POWER6, { BF, FRA, DCM } },
4867{ "dtstdgq", Z(63,226), Z_MASK, POWER6, { BF, FRA, DGM } },
4868
4869{ "drintnq", ZRC(63,227,0), Z_MASK, POWER6, { R, FRT, FRB, RMC } },
4870{ "drintnq.",ZRC(63,227,1), Z_MASK, POWER6, { R, FRT, FRB, RMC } },
4871
4872{ "dctqpq", XRC(63,258,0), X_MASK, POWER6, { FRT, FRB } },
4873{ "dctqpq.", XRC(63,258,1), X_MASK, POWER6, { FRT, FRB } },
4874
4543{ "fabs", XRC(63,264,0), XRA_MASK, COM, { FRT, FRB } }, 4875{ "fabs", XRC(63,264,0), XRA_MASK, COM, { FRT, FRB } },
4544{ "fabs.", XRC(63,264,1), XRA_MASK, COM, { FRT, FRB } }, 4876{ "fabs.", XRC(63,264,1), XRA_MASK, COM, { FRT, FRB } },
4545 4877
4878{ "dctfixq", XRC(63,290,0), X_MASK, POWER6, { FRT, FRB } },
4879{ "dctfixq.",XRC(63,290,1), X_MASK, POWER6, { FRT, FRB } },
4880
4881{ "ddedpdq", XRC(63,322,0), X_MASK, POWER6, { SP, FRT, FRB } },
4882{ "ddedpdq.",XRC(63,322,1), X_MASK, POWER6, { SP, FRT, FRB } },
4883
4884{ "dxexq", XRC(63,354,0), X_MASK, POWER6, { FRT, FRB } },
4885{ "dxexq.", XRC(63,354,1), X_MASK, POWER6, { FRT, FRB } },
4886
4887{ "frin", XRC(63,392,0), XRA_MASK, POWER5, { FRT, FRB } },
4888{ "frin.", XRC(63,392,1), XRA_MASK, POWER5, { FRT, FRB } },
4889{ "friz", XRC(63,424,0), XRA_MASK, POWER5, { FRT, FRB } },
4890{ "friz.", XRC(63,424,1), XRA_MASK, POWER5, { FRT, FRB } },
4891{ "frip", XRC(63,456,0), XRA_MASK, POWER5, { FRT, FRB } },
4892{ "frip.", XRC(63,456,1), XRA_MASK, POWER5, { FRT, FRB } },
4893{ "frim", XRC(63,488,0), XRA_MASK, POWER5, { FRT, FRB } },
4894{ "frim.", XRC(63,488,1), XRA_MASK, POWER5, { FRT, FRB } },
4895
4896{ "dsubq", XRC(63,514,0), X_MASK, POWER6, { FRT, FRA, FRB } },
4897{ "dsubq.", XRC(63,514,1), X_MASK, POWER6, { FRT, FRA, FRB } },
4898
4899{ "ddivq", XRC(63,546,0), X_MASK, POWER6, { FRT, FRA, FRB } },
4900{ "ddivq.", XRC(63,546,1), X_MASK, POWER6, { FRT, FRA, FRB } },
4901
4546{ "mffs", XRC(63,583,0), XRARB_MASK, COM, { FRT } }, 4902{ "mffs", XRC(63,583,0), XRARB_MASK, COM, { FRT } },
4547{ "mffs.", XRC(63,583,1), XRARB_MASK, COM, { FRT } }, 4903{ "mffs.", XRC(63,583,1), XRARB_MASK, COM, { FRT } },
4548 4904
4905{ "dcmpuq", X(63,642), X_MASK, POWER6, { BF, FRA, FRB } },
4906
4907{ "dtstsfq", X(63,674), X_MASK, POWER6, { BF, FRA, FRB } },
4908
4549{ "mtfsf", XFL(63,711,0), XFL_MASK, COM, { FLM, FRB } }, 4909{ "mtfsf", XFL(63,711,0), XFL_MASK, COM, { FLM, FRB } },
4550{ "mtfsf.", XFL(63,711,1), XFL_MASK, COM, { FLM, FRB } }, 4910{ "mtfsf.", XFL(63,711,1), XFL_MASK, COM, { FLM, FRB } },
4551 4911
4912{ "drdpq", XRC(63,770,0), X_MASK, POWER6, { FRT, FRB } },
4913{ "drdpq.", XRC(63,770,1), X_MASK, POWER6, { FRT, FRB } },
4914
4915{ "dcffixq", XRC(63,802,0), X_MASK, POWER6, { FRT, FRB } },
4916{ "dcffixq.",XRC(63,802,1), X_MASK, POWER6, { FRT, FRB } },
4917
4552{ "fctid", XRC(63,814,0), XRA_MASK, PPC64, { FRT, FRB } }, 4918{ "fctid", XRC(63,814,0), XRA_MASK, PPC64, { FRT, FRB } },
4553{ "fctid.", XRC(63,814,1), XRA_MASK, PPC64, { FRT, FRB } }, 4919{ "fctid.", XRC(63,814,1), XRA_MASK, PPC64, { FRT, FRB } },
4554 4920
4555{ "fctidz", XRC(63,815,0), XRA_MASK, PPC64, { FRT, FRB } }, 4921{ "fctidz", XRC(63,815,0), XRA_MASK, PPC64, { FRT, FRB } },
4556{ "fctidz.", XRC(63,815,1), XRA_MASK, PPC64, { FRT, FRB } }, 4922{ "fctidz.", XRC(63,815,1), XRA_MASK, PPC64, { FRT, FRB } },
4557 4923
4924{ "denbcdq", XRC(63,834,0), X_MASK, POWER6, { S, FRT, FRB } },
4925{ "denbcdq.",XRC(63,834,1), X_MASK, POWER6, { S, FRT, FRB } },
4926
4558{ "fcfid", XRC(63,846,0), XRA_MASK, PPC64, { FRT, FRB } }, 4927{ "fcfid", XRC(63,846,0), XRA_MASK, PPC64, { FRT, FRB } },
4559{ "fcfid.", XRC(63,846,1), XRA_MASK, PPC64, { FRT, FRB } }, 4928{ "fcfid.", XRC(63,846,1), XRA_MASK, PPC64, { FRT, FRB } },
4560 4929
4930{ "diexq", XRC(63,866,0), X_MASK, POWER6, { FRT, FRA, FRB } },
4931{ "diexq.", XRC(63,866,1), X_MASK, POWER6, { FRT, FRA, FRB } },
4932
4561}; 4933};
4562 4934
4563const int powerpc_num_opcodes = 4935const int powerpc_num_opcodes =
diff --git a/arch/powerpc/xmon/ppc.h b/arch/powerpc/xmon/ppc.h
index 342237e8dd69..110df96354b4 100644
--- a/arch/powerpc/xmon/ppc.h
+++ b/arch/powerpc/xmon/ppc.h
@@ -1,5 +1,5 @@
1/* ppc.h -- Header file for PowerPC opcode table 1/* ppc.h -- Header file for PowerPC opcode table
2 Copyright 1994, 1995, 1999, 2000, 2001, 2002, 2003 2 Copyright 1994, 1995, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
3 Free Software Foundation, Inc. 3 Free Software Foundation, Inc.
4 Written by Ian Lance Taylor, Cygnus Support 4 Written by Ian Lance Taylor, Cygnus Support
5 5
@@ -17,7 +17,7 @@ the GNU General Public License for more details.
17 17
18You should have received a copy of the GNU General Public License 18You should have received a copy of the GNU General Public License
19along with this file; see the file COPYING. If not, write to the Free 19along with this file; see the file COPYING. If not, write to the Free
20Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 20Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
21 21
22#ifndef PPC_H 22#ifndef PPC_H
23#define PPC_H 23#define PPC_H
@@ -134,6 +134,18 @@ extern const int powerpc_num_opcodes;
134/* Opcode is supported by machine check APU. */ 134/* Opcode is supported by machine check APU. */
135#define PPC_OPCODE_RFMCI 0x800000 135#define PPC_OPCODE_RFMCI 0x800000
136 136
137/* Opcode is only supported by Power5 architecture. */
138#define PPC_OPCODE_POWER5 0x1000000
139
140/* Opcode is supported by PowerPC e300 family. */
141#define PPC_OPCODE_E300 0x2000000
142
143/* Opcode is only supported by Power6 architecture. */
144#define PPC_OPCODE_POWER6 0x4000000
145
146/* Opcode is only supported by PowerPC Cell family. */
147#define PPC_OPCODE_CELL 0x8000000
148
137/* A macro to extract the major opcode from an instruction. */ 149/* A macro to extract the major opcode from an instruction. */
138#define PPC_OP(i) (((i) >> 26) & 0x3f) 150#define PPC_OP(i) (((i) >> 26) & 0x3f)
139 151
@@ -233,25 +245,28 @@ extern const struct powerpc_operand powerpc_operands[];
233 register names with a leading 'r'. */ 245 register names with a leading 'r'. */
234#define PPC_OPERAND_GPR (040) 246#define PPC_OPERAND_GPR (040)
235 247
248/* Like PPC_OPERAND_GPR, but don't print a leading 'r' for r0. */
249#define PPC_OPERAND_GPR_0 (0100)
250
236/* This operand names a floating point register. The disassembler 251/* This operand names a floating point register. The disassembler
237 prints these with a leading 'f'. */ 252 prints these with a leading 'f'. */
238#define PPC_OPERAND_FPR (0100) 253#define PPC_OPERAND_FPR (0200)
239 254
240/* This operand is a relative branch displacement. The disassembler 255/* This operand is a relative branch displacement. The disassembler
241 prints these symbolically if possible. */ 256 prints these symbolically if possible. */
242#define PPC_OPERAND_RELATIVE (0200) 257#define PPC_OPERAND_RELATIVE (0400)
243 258
244/* This operand is an absolute branch address. The disassembler 259/* This operand is an absolute branch address. The disassembler
245 prints these symbolically if possible. */ 260 prints these symbolically if possible. */
246#define PPC_OPERAND_ABSOLUTE (0400) 261#define PPC_OPERAND_ABSOLUTE (01000)
247 262
248/* This operand is optional, and is zero if omitted. This is used for 263/* This operand is optional, and is zero if omitted. This is used for
249 the optional BF and L fields in the comparison instructions. The 264 example, in the optional BF field in the comparison instructions. The
250 assembler must count the number of operands remaining on the line, 265 assembler must count the number of operands remaining on the line,
251 and the number of operands remaining for the opcode, and decide 266 and the number of operands remaining for the opcode, and decide
252 whether this operand is present or not. The disassembler should 267 whether this operand is present or not. The disassembler should
253 print this operand out only if it is not zero. */ 268 print this operand out only if it is not zero. */
254#define PPC_OPERAND_OPTIONAL (01000) 269#define PPC_OPERAND_OPTIONAL (02000)
255 270
256/* This flag is only used with PPC_OPERAND_OPTIONAL. If this operand 271/* This flag is only used with PPC_OPERAND_OPTIONAL. If this operand
257 is omitted, then for the next operand use this operand value plus 272 is omitted, then for the next operand use this operand value plus
@@ -259,24 +274,24 @@ extern const struct powerpc_operand powerpc_operands[];
259 hack is needed because the Power rotate instructions can take 274 hack is needed because the Power rotate instructions can take
260 either 4 or 5 operands. The disassembler should print this operand 275 either 4 or 5 operands. The disassembler should print this operand
261 out regardless of the PPC_OPERAND_OPTIONAL field. */ 276 out regardless of the PPC_OPERAND_OPTIONAL field. */
262#define PPC_OPERAND_NEXT (02000) 277#define PPC_OPERAND_NEXT (04000)
263 278
264/* This operand should be regarded as a negative number for the 279/* This operand should be regarded as a negative number for the
265 purposes of overflow checking (i.e., the normal most negative 280 purposes of overflow checking (i.e., the normal most negative
266 number is disallowed and one more than the normal most positive 281 number is disallowed and one more than the normal most positive
267 number is allowed). This flag will only be set for a signed 282 number is allowed). This flag will only be set for a signed
268 operand. */ 283 operand. */
269#define PPC_OPERAND_NEGATIVE (04000) 284#define PPC_OPERAND_NEGATIVE (010000)
270 285
271/* This operand names a vector unit register. The disassembler 286/* This operand names a vector unit register. The disassembler
272 prints these with a leading 'v'. */ 287 prints these with a leading 'v'. */
273#define PPC_OPERAND_VR (010000) 288#define PPC_OPERAND_VR (020000)
274 289
275/* This operand is for the DS field in a DS form instruction. */ 290/* This operand is for the DS field in a DS form instruction. */
276#define PPC_OPERAND_DS (020000) 291#define PPC_OPERAND_DS (040000)
277 292
278/* This operand is for the DQ field in a DQ form instruction. */ 293/* This operand is for the DQ field in a DQ form instruction. */
279#define PPC_OPERAND_DQ (040000) 294#define PPC_OPERAND_DQ (0100000)
280 295
281/* The POWER and PowerPC assemblers use a few macros. We keep them 296/* The POWER and PowerPC assemblers use a few macros. We keep them
282 with the operands table for simplicity. The macro table is an 297 with the operands table for simplicity. The macro table is an
diff --git a/arch/powerpc/xmon/spu-dis.c b/arch/powerpc/xmon/spu-dis.c
new file mode 100644
index 000000000000..ee929c641bf3
--- /dev/null
+++ b/arch/powerpc/xmon/spu-dis.c
@@ -0,0 +1,248 @@
1/* Disassemble SPU instructions
2
3 Copyright 2006 Free Software Foundation, Inc.
4
5 This file is part of GDB, GAS, and the GNU binutils.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
20
21#include <linux/string.h>
22#include "nonstdio.h"
23#include "ansidecl.h"
24#include "spu.h"
25#include "dis-asm.h"
26
27/* This file provides a disassembler function which uses
28 the disassembler interface defined in dis-asm.h. */
29
30extern const struct spu_opcode spu_opcodes[];
31extern const int spu_num_opcodes;
32
33#define SPU_DISASM_TBL_SIZE (1 << 11)
34static const struct spu_opcode *spu_disassemble_table[SPU_DISASM_TBL_SIZE];
35
36static void
37init_spu_disassemble (void)
38{
39 int i;
40
41 /* If two instructions have the same opcode then we prefer the first
42 * one. In most cases it is just an alternate mnemonic. */
43 for (i = 0; i < spu_num_opcodes; i++)
44 {
45 int o = spu_opcodes[i].opcode;
46 if (o >= SPU_DISASM_TBL_SIZE)
47 continue; /* abort (); */
48 if (spu_disassemble_table[o] == 0)
49 spu_disassemble_table[o] = &spu_opcodes[i];
50 }
51}
52
53/* Determine the instruction from the 10 least significant bits. */
54static const struct spu_opcode *
55get_index_for_opcode (unsigned int insn)
56{
57 const struct spu_opcode *index;
58 unsigned int opcode = insn >> (32-11);
59
60 /* Init the table. This assumes that element 0/opcode 0 (currently
61 * NOP) is always used */
62 if (spu_disassemble_table[0] == 0)
63 init_spu_disassemble ();
64
65 if ((index = spu_disassemble_table[opcode & 0x780]) != 0
66 && index->insn_type == RRR)
67 return index;
68
69 if ((index = spu_disassemble_table[opcode & 0x7f0]) != 0
70 && (index->insn_type == RI18 || index->insn_type == LBT))
71 return index;
72
73 if ((index = spu_disassemble_table[opcode & 0x7f8]) != 0
74 && index->insn_type == RI10)
75 return index;
76
77 if ((index = spu_disassemble_table[opcode & 0x7fc]) != 0
78 && (index->insn_type == RI16))
79 return index;
80
81 if ((index = spu_disassemble_table[opcode & 0x7fe]) != 0
82 && (index->insn_type == RI8))
83 return index;
84
85 if ((index = spu_disassemble_table[opcode & 0x7ff]) != 0)
86 return index;
87
88 return 0;
89}
90
91/* Print a Spu instruction. */
92
93int
94print_insn_spu (unsigned long insn, unsigned long memaddr)
95{
96 int value;
97 int hex_value;
98 const struct spu_opcode *index;
99 enum spu_insns tag;
100
101 index = get_index_for_opcode (insn);
102
103 if (index == 0)
104 {
105 printf(".long 0x%x", insn);
106 }
107 else
108 {
109 int i;
110 int paren = 0;
111 tag = (enum spu_insns)(index - spu_opcodes);
112 printf("%s", index->mnemonic);
113 if (tag == M_BI || tag == M_BISL || tag == M_IRET || tag == M_BISLED
114 || tag == M_BIHNZ || tag == M_BIHZ || tag == M_BINZ || tag == M_BIZ
115 || tag == M_SYNC || tag == M_HBR)
116 {
117 int fb = (insn >> (32-18)) & 0x7f;
118 if (fb & 0x40)
119 printf(tag == M_SYNC ? "c" : "p");
120 if (fb & 0x20)
121 printf("d");
122 if (fb & 0x10)
123 printf("e");
124 }
125 if (index->arg[0] != 0)
126 printf("\t");
127 hex_value = 0;
128 for (i = 1; i <= index->arg[0]; i++)
129 {
130 int arg = index->arg[i];
131 if (arg != A_P && !paren && i > 1)
132 printf(",");
133
134 switch (arg)
135 {
136 case A_T:
137 printf("$%d",
138 DECODE_INSN_RT (insn));
139 break;
140 case A_A:
141 printf("$%d",
142 DECODE_INSN_RA (insn));
143 break;
144 case A_B:
145 printf("$%d",
146 DECODE_INSN_RB (insn));
147 break;
148 case A_C:
149 printf("$%d",
150 DECODE_INSN_RC (insn));
151 break;
152 case A_S:
153 printf("$sp%d",
154 DECODE_INSN_RA (insn));
155 break;
156 case A_H:
157 printf("$ch%d",
158 DECODE_INSN_RA (insn));
159 break;
160 case A_P:
161 paren++;
162 printf("(");
163 break;
164 case A_U7A:
165 printf("%d",
166 173 - DECODE_INSN_U8 (insn));
167 break;
168 case A_U7B:
169 printf("%d",
170 155 - DECODE_INSN_U8 (insn));
171 break;
172 case A_S3:
173 case A_S6:
174 case A_S7:
175 case A_S7N:
176 case A_U3:
177 case A_U5:
178 case A_U6:
179 case A_U7:
180 hex_value = DECODE_INSN_I7 (insn);
181 printf("%d", hex_value);
182 break;
183 case A_S11:
184 print_address(memaddr + DECODE_INSN_I9a (insn) * 4);
185 break;
186 case A_S11I:
187 print_address(memaddr + DECODE_INSN_I9b (insn) * 4);
188 break;
189 case A_S10:
190 case A_S10B:
191 hex_value = DECODE_INSN_I10 (insn);
192 printf("%d", hex_value);
193 break;
194 case A_S14:
195 hex_value = DECODE_INSN_I10 (insn) * 16;
196 printf("%d", hex_value);
197 break;
198 case A_S16:
199 hex_value = DECODE_INSN_I16 (insn);
200 printf("%d", hex_value);
201 break;
202 case A_X16:
203 hex_value = DECODE_INSN_U16 (insn);
204 printf("%u", hex_value);
205 break;
206 case A_R18:
207 value = DECODE_INSN_I16 (insn) * 4;
208 if (value == 0)
209 printf("%d", value);
210 else
211 {
212 hex_value = memaddr + value;
213 print_address(hex_value & 0x3ffff);
214 }
215 break;
216 case A_S18:
217 value = DECODE_INSN_U16 (insn) * 4;
218 if (value == 0)
219 printf("%d", value);
220 else
221 print_address(value);
222 break;
223 case A_U18:
224 value = DECODE_INSN_U18 (insn);
225 if (value == 0 || 1)
226 {
227 hex_value = value;
228 printf("%u", value);
229 }
230 else
231 print_address(value);
232 break;
233 case A_U14:
234 hex_value = DECODE_INSN_U14 (insn);
235 printf("%u", hex_value);
236 break;
237 }
238 if (arg != A_P && paren)
239 {
240 printf(")");
241 paren--;
242 }
243 }
244 if (hex_value > 16)
245 printf("\t# %x", hex_value);
246 }
247 return 4;
248}
diff --git a/arch/powerpc/xmon/spu-insns.h b/arch/powerpc/xmon/spu-insns.h
new file mode 100644
index 000000000000..99dc452821ac
--- /dev/null
+++ b/arch/powerpc/xmon/spu-insns.h
@@ -0,0 +1,410 @@
1/* SPU ELF support for BFD.
2
3 Copyright 2006 Free Software Foundation, Inc.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
20
21/* SPU Opcode Table
22
23-=-=-= FORMAT =-=-=-
24
25 +----+-------+-------+-------+-------+ +------------+-------+-------+-------+
26RRR | op | RC | RB | RA | RT | RI7 | op | I7 | RA | RT |
27 +----+-------+-------+-------+-------+ +------------+-------+-------+-------+
28 0 3 1 1 2 3 0 1 1 2 3
29 0 7 4 1 0 7 4 1
30
31 +-----------+--------+-------+-------+ +---------+----------+-------+-------+
32RI8 | op | I8 | RA | RT | RI10 | op | I10 | RA | RT |
33 +-----------+--------+-------+-------+ +---------+----------+-------+-------+
34 0 9 1 2 3 0 7 1 2 3
35 7 4 1 7 4 1
36
37 +----------+-----------------+-------+ +--------+-------------------+-------+
38RI16 | op | I16 | RT | RI18 | op | I18 | RT |
39 +----------+-----------------+-------+ +--------+-------------------+-------+
40 0 8 2 3 0 6 2 3
41 4 1 4 1
42
43 +------------+-------+-------+-------+ +-------+--+-----------------+-------+
44RR | op | RB | RA | RT | LBT | op |RO| I16 | RO |
45 +------------+-------+-------+-------+ +-------+--+-----------------+-------+
46 0 1 1 2 3 0 6 8 2 3
47 0 7 4 1 4 1
48
49 +------------+----+--+-------+-------+
50 LBTI | op | // |RO| RA | RO |
51 +------------+----+--+-------+-------+
52 0 1 1 1 2 3
53 0 5 7 4 1
54
55-=-=-= OPCODE =-=-=-
56
57OPCODE field specifies the most significant 11bit of the instruction. Some formats don't have 11bits for opcode field, and in this
58case, bit field other than op are defined as 0s. For example, opcode of fma instruction which is RRR format is defined as 0x700,
59since 0x700 -> 11'b11100000000, this means opcode is 4'b1110, and other 7bits are defined as 7'b0000000.
60
61-=-=-= ASM_FORMAT =-=-=-
62
63RRR category RI7 category
64 ASM_RRR mnemonic RC, RA, RB, RT ASM_RI4 mnemonic RT, RA, I4
65 ASM_RI7 mnemonic RT, RA, I7
66
67RI8 category RI10 category
68 ASM_RUI8 mnemonic RT, RA, UI8 ASM_AI10 mnemonic RA, I10
69 ASM_RI10 mnemonic RT, RA, R10
70 ASM_RI10IDX mnemonic RT, I10(RA)
71
72RI16 category RI18 category
73 ASM_I16W mnemonic I16W ASM_RI18 mnemonic RT, I18
74 ASM_RI16 mnemonic RT, I16
75 ASM_RI16W mnemonic RT, I16W
76
77RR category LBT category
78 ASM_MFSPR mnemonic RT, SA ASM_LBT mnemonic brinst, brtarg
79 ASM_MTSPR mnemonic SA, RT
80 ASM_NOOP mnemonic LBTI category
81 ASM_RA mnemonic RA ASM_LBTI mnemonic brinst, RA
82 ASM_RAB mnemonic RA, RB
83 ASM_RDCH mnemonic RT, CA
84 ASM_RR mnemonic RT, RA, RB
85 ASM_RT mnemonic RT
86 ASM_RTA mnemonic RT, RA
87 ASM_WRCH mnemonic CA, RT
88
89Note that RRR instructions have the names for RC and RT reversed from
90what's in the ISA, in order to put RT in the same position it appears
91for other formats.
92
93-=-=-= DEPENDENCY =-=-=-
94
95DEPENDENCY filed consists of 5 digits. This represents which register is used as source and which register is used as target.
96The first(most significant) digit is always 0. Then it is followd by RC, RB, RA and RT digits.
97If the digit is 0, this means the corresponding register is not used in the instruction.
98If the digit is 1, this means the corresponding register is used as a source in the instruction.
99If the digit is 2, this means the corresponding register is used as a target in the instruction.
100If the digit is 3, this means the corresponding register is used as both source and target in the instruction.
101For example, fms instruction has 00113 as the DEPENDENCY field. This means RC is not used in this operation, RB and RA are
102used as sources and RT is the target.
103
104-=-=-= PIPE =-=-=-
105
106This field shows which execution pipe is used for the instruction
107
108pipe0 execution pipelines:
109 FP6 SP floating pipeline
110 FP7 integer operations executed in SP floating pipeline
111 FPD DP floating pipeline
112 FX2 FXU pipeline
113 FX3 Rotate/Shift pipeline
114 FXB Byte pipeline
115 NOP No pipeline
116
117pipe1 execution pipelines:
118 BR Branch pipeline
119 LNOP No pipeline
120 LS Load/Store pipeline
121 SHUF Shuffle pipeline
122 SPR SPR/CH pipeline
123
124*/
125
126#define _A0() {0}
127#define _A1(a) {1,a}
128#define _A2(a,b) {2,a,b}
129#define _A3(a,b,c) {3,a,b,c}
130#define _A4(a,b,c,d) {4,a,b,c,d}
131
132/* TAG FORMAT OPCODE MNEMONIC ASM_FORMAT DEPENDENCY PIPE COMMENT */
133/* 0[RC][RB][RA][RT] */
134/* 1:src, 2:target */
135
136APUOP(M_BR, RI16, 0x190, "br", _A1(A_R18), 00000, BR) /* BRel IP<-IP+I16 */
137APUOP(M_BRSL, RI16, 0x198, "brsl", _A2(A_T,A_R18), 00002, BR) /* BRelSetLink RT,IP<-IP,IP+I16 */
138APUOP(M_BRA, RI16, 0x180, "bra", _A1(A_S18), 00000, BR) /* BRAbs IP<-I16 */
139APUOP(M_BRASL, RI16, 0x188, "brasl", _A2(A_T,A_S18), 00002, BR) /* BRAbsSetLink RT,IP<-IP,I16 */
140APUOP(M_FSMBI, RI16, 0x194, "fsmbi", _A2(A_T,A_X16), 00002, SHUF) /* FormSelMask%I RT<-fsm(I16) */
141APUOP(M_LQA, RI16, 0x184, "lqa", _A2(A_T,A_S18), 00002, LS) /* LoadQAbs RT<-M[I16] */
142APUOP(M_LQR, RI16, 0x19C, "lqr", _A2(A_T,A_R18), 00002, LS) /* LoadQRel RT<-M[IP+I16] */
143APUOP(M_STOP, RR, 0x000, "stop", _A0(), 00000, BR) /* STOP stop */
144APUOP(M_STOP2, RR, 0x000, "stop", _A1(A_U14), 00000, BR) /* STOP stop */
145APUOP(M_STOPD, RR, 0x140, "stopd", _A3(A_T,A_A,A_B), 00111, BR) /* STOPD stop (with register dependencies) */
146APUOP(M_LNOP, RR, 0x001, "lnop", _A0(), 00000, LNOP) /* LNOP no_operation */
147APUOP(M_SYNC, RR, 0x002, "sync", _A0(), 00000, BR) /* SYNC flush_pipe */
148APUOP(M_DSYNC, RR, 0x003, "dsync", _A0(), 00000, BR) /* DSYNC flush_store_queue */
149APUOP(M_MFSPR, RR, 0x00c, "mfspr", _A2(A_T,A_S), 00002, SPR) /* MFSPR RT<-SA */
150APUOP(M_RDCH, RR, 0x00d, "rdch", _A2(A_T,A_H), 00002, SPR) /* ReaDCHannel RT<-CA:data */
151APUOP(M_RCHCNT, RR, 0x00f, "rchcnt", _A2(A_T,A_H), 00002, SPR) /* ReaDCHanCouNT RT<-CA:count */
152APUOP(M_HBRA, LBT, 0x080, "hbra", _A2(A_S11,A_S18), 00000, LS) /* HBRA BTB[B9]<-M[I16] */
153APUOP(M_HBRR, LBT, 0x090, "hbrr", _A2(A_S11,A_R18), 00000, LS) /* HBRR BTB[B9]<-M[IP+I16] */
154APUOP(M_BRZ, RI16, 0x100, "brz", _A2(A_T,A_R18), 00001, BR) /* BRZ IP<-IP+I16_if(RT) */
155APUOP(M_BRNZ, RI16, 0x108, "brnz", _A2(A_T,A_R18), 00001, BR) /* BRNZ IP<-IP+I16_if(RT) */
156APUOP(M_BRHZ, RI16, 0x110, "brhz", _A2(A_T,A_R18), 00001, BR) /* BRHZ IP<-IP+I16_if(RT) */
157APUOP(M_BRHNZ, RI16, 0x118, "brhnz", _A2(A_T,A_R18), 00001, BR) /* BRHNZ IP<-IP+I16_if(RT) */
158APUOP(M_STQA, RI16, 0x104, "stqa", _A2(A_T,A_S18), 00001, LS) /* SToreQAbs M[I16]<-RT */
159APUOP(M_STQR, RI16, 0x11C, "stqr", _A2(A_T,A_R18), 00001, LS) /* SToreQRel M[IP+I16]<-RT */
160APUOP(M_MTSPR, RR, 0x10c, "mtspr", _A2(A_S,A_T), 00001, SPR) /* MTSPR SA<-RT */
161APUOP(M_WRCH, RR, 0x10d, "wrch", _A2(A_H,A_T), 00001, SPR) /* ChanWRite CA<-RT */
162APUOP(M_LQD, RI10, 0x1a0, "lqd", _A4(A_T,A_S14,A_P,A_A), 00012, LS) /* LoadQDisp RT<-M[Ra+I10] */
163APUOP(M_BI, RR, 0x1a8, "bi", _A1(A_A), 00010, BR) /* BI IP<-RA */
164APUOP(M_BISL, RR, 0x1a9, "bisl", _A2(A_T,A_A), 00012, BR) /* BISL RT,IP<-IP,RA */
165APUOP(M_IRET, RR, 0x1aa, "iret", _A1(A_A), 00010, BR) /* IRET IP<-SRR0 */
166APUOP(M_IRET2, RR, 0x1aa, "iret", _A0(), 00010, BR) /* IRET IP<-SRR0 */
167APUOP(M_BISLED, RR, 0x1ab, "bisled", _A2(A_T,A_A), 00012, BR) /* BISLED RT,IP<-IP,RA_if(ext) */
168APUOP(M_HBR, LBTI, 0x1ac, "hbr", _A2(A_S11I,A_A), 00010, LS) /* HBR BTB[B9]<-M[Ra] */
169APUOP(M_FREST, RR, 0x1b8, "frest", _A2(A_T,A_A), 00012, SHUF) /* FREST RT<-recip(RA) */
170APUOP(M_FRSQEST, RR, 0x1b9, "frsqest", _A2(A_T,A_A), 00012, SHUF) /* FRSQEST RT<-rsqrt(RA) */
171APUOP(M_FSM, RR, 0x1b4, "fsm", _A2(A_T,A_A), 00012, SHUF) /* FormSelMask% RT<-expand(Ra) */
172APUOP(M_FSMH, RR, 0x1b5, "fsmh", _A2(A_T,A_A), 00012, SHUF) /* FormSelMask% RT<-expand(Ra) */
173APUOP(M_FSMB, RR, 0x1b6, "fsmb", _A2(A_T,A_A), 00012, SHUF) /* FormSelMask% RT<-expand(Ra) */
174APUOP(M_GB, RR, 0x1b0, "gb", _A2(A_T,A_A), 00012, SHUF) /* GatherBits% RT<-gather(RA) */
175APUOP(M_GBH, RR, 0x1b1, "gbh", _A2(A_T,A_A), 00012, SHUF) /* GatherBits% RT<-gather(RA) */
176APUOP(M_GBB, RR, 0x1b2, "gbb", _A2(A_T,A_A), 00012, SHUF) /* GatherBits% RT<-gather(RA) */
177APUOP(M_CBD, RI7, 0x1f4, "cbd", _A4(A_T,A_U7,A_P,A_A), 00012, SHUF) /* genCtl%%insD RT<-sta(Ra+I4,siz) */
178APUOP(M_CHD, RI7, 0x1f5, "chd", _A4(A_T,A_U7,A_P,A_A), 00012, SHUF) /* genCtl%%insD RT<-sta(Ra+I4,siz) */
179APUOP(M_CWD, RI7, 0x1f6, "cwd", _A4(A_T,A_U7,A_P,A_A), 00012, SHUF) /* genCtl%%insD RT<-sta(Ra+I4,siz) */
180APUOP(M_CDD, RI7, 0x1f7, "cdd", _A4(A_T,A_U7,A_P,A_A), 00012, SHUF) /* genCtl%%insD RT<-sta(Ra+I4,siz) */
181APUOP(M_ROTQBII, RI7, 0x1f8, "rotqbii", _A3(A_T,A_A,A_U3), 00012, SHUF) /* ROTQBII RT<-RA<<<I7 */
182APUOP(M_ROTQBYI, RI7, 0x1fc, "rotqbyi", _A3(A_T,A_A,A_S7N), 00012, SHUF) /* ROTQBYI RT<-RA<<<(I7*8) */
183APUOP(M_ROTQMBII, RI7, 0x1f9, "rotqmbii", _A3(A_T,A_A,A_S3), 00012, SHUF) /* ROTQMBII RT<-RA<<I7 */
184APUOP(M_ROTQMBYI, RI7, 0x1fd, "rotqmbyi", _A3(A_T,A_A,A_S6), 00012, SHUF) /* ROTQMBYI RT<-RA<<I7 */
185APUOP(M_SHLQBII, RI7, 0x1fb, "shlqbii", _A3(A_T,A_A,A_U3), 00012, SHUF) /* SHLQBII RT<-RA<<I7 */
186APUOP(M_SHLQBYI, RI7, 0x1ff, "shlqbyi", _A3(A_T,A_A,A_U5), 00012, SHUF) /* SHLQBYI RT<-RA<<I7 */
187APUOP(M_STQD, RI10, 0x120, "stqd", _A4(A_T,A_S14,A_P,A_A), 00011, LS) /* SToreQDisp M[Ra+I10]<-RT */
188APUOP(M_BIHNZ, RR, 0x12b, "bihnz", _A2(A_T,A_A), 00011, BR) /* BIHNZ IP<-RA_if(RT) */
189APUOP(M_BIHZ, RR, 0x12a, "bihz", _A2(A_T,A_A), 00011, BR) /* BIHZ IP<-RA_if(RT) */
190APUOP(M_BINZ, RR, 0x129, "binz", _A2(A_T,A_A), 00011, BR) /* BINZ IP<-RA_if(RT) */
191APUOP(M_BIZ, RR, 0x128, "biz", _A2(A_T,A_A), 00011, BR) /* BIZ IP<-RA_if(RT) */
192APUOP(M_CBX, RR, 0x1d4, "cbx", _A3(A_T,A_A,A_B), 00112, SHUF) /* genCtl%%insX RT<-sta(Ra+Rb,siz) */
193APUOP(M_CHX, RR, 0x1d5, "chx", _A3(A_T,A_A,A_B), 00112, SHUF) /* genCtl%%insX RT<-sta(Ra+Rb,siz) */
194APUOP(M_CWX, RR, 0x1d6, "cwx", _A3(A_T,A_A,A_B), 00112, SHUF) /* genCtl%%insX RT<-sta(Ra+Rb,siz) */
195APUOP(M_CDX, RR, 0x1d7, "cdx", _A3(A_T,A_A,A_B), 00112, SHUF) /* genCtl%%insX RT<-sta(Ra+Rb,siz) */
196APUOP(M_LQX, RR, 0x1c4, "lqx", _A3(A_T,A_A,A_B), 00112, LS) /* LoadQindeX RT<-M[Ra+Rb] */
197APUOP(M_ROTQBI, RR, 0x1d8, "rotqbi", _A3(A_T,A_A,A_B), 00112, SHUF) /* ROTQBI RT<-RA<<<Rb */
198APUOP(M_ROTQMBI, RR, 0x1d9, "rotqmbi", _A3(A_T,A_A,A_B), 00112, SHUF) /* ROTQMBI RT<-RA<<Rb */
199APUOP(M_SHLQBI, RR, 0x1db, "shlqbi", _A3(A_T,A_A,A_B), 00112, SHUF) /* SHLQBI RT<-RA<<Rb */
200APUOP(M_ROTQBY, RR, 0x1dc, "rotqby", _A3(A_T,A_A,A_B), 00112, SHUF) /* ROTQBY RT<-RA<<<(Rb*8) */
201APUOP(M_ROTQMBY, RR, 0x1dd, "rotqmby", _A3(A_T,A_A,A_B), 00112, SHUF) /* ROTQMBY RT<-RA<<Rb */
202APUOP(M_SHLQBY, RR, 0x1df, "shlqby", _A3(A_T,A_A,A_B), 00112, SHUF) /* SHLQBY RT<-RA<<Rb */
203APUOP(M_ROTQBYBI, RR, 0x1cc, "rotqbybi", _A3(A_T,A_A,A_B), 00112, SHUF) /* ROTQBYBI RT<-RA<<Rb */
204APUOP(M_ROTQMBYBI, RR, 0x1cd, "rotqmbybi", _A3(A_T,A_A,A_B), 00112, SHUF) /* ROTQMBYBI RT<-RA<<Rb */
205APUOP(M_SHLQBYBI, RR, 0x1cf, "shlqbybi", _A3(A_T,A_A,A_B), 00112, SHUF) /* SHLQBYBI RT<-RA<<Rb */
206APUOP(M_STQX, RR, 0x144, "stqx", _A3(A_T,A_A,A_B), 00111, LS) /* SToreQindeX M[Ra+Rb]<-RT */
207APUOP(M_SHUFB, RRR, 0x580, "shufb", _A4(A_C,A_A,A_B,A_T), 02111, SHUF) /* SHUFfleBytes RC<-f(RA,RB,RT) */
208APUOP(M_IL, RI16, 0x204, "il", _A2(A_T,A_S16), 00002, FX2) /* ImmLoad RT<-sxt(I16) */
209APUOP(M_ILH, RI16, 0x20c, "ilh", _A2(A_T,A_X16), 00002, FX2) /* ImmLoadH RT<-I16 */
210APUOP(M_ILHU, RI16, 0x208, "ilhu", _A2(A_T,A_X16), 00002, FX2) /* ImmLoadHUpper RT<-I16<<16 */
211APUOP(M_ILA, RI18, 0x210, "ila", _A2(A_T,A_U18), 00002, FX2) /* ImmLoadAddr RT<-zxt(I18) */
212APUOP(M_NOP, RR, 0x201, "nop", _A1(A_T), 00000, NOP) /* XNOP no_operation */
213APUOP(M_NOP2, RR, 0x201, "nop", _A0(), 00000, NOP) /* XNOP no_operation */
214APUOP(M_IOHL, RI16, 0x304, "iohl", _A2(A_T,A_X16), 00003, FX2) /* AddImmeXt RT<-RT+sxt(I16) */
215APUOP(M_ANDBI, RI10, 0x0b0, "andbi", _A3(A_T,A_A,A_S10B), 00012, FX2) /* AND%I RT<-RA&I10 */
216APUOP(M_ANDHI, RI10, 0x0a8, "andhi", _A3(A_T,A_A,A_S10), 00012, FX2) /* AND%I RT<-RA&I10 */
217APUOP(M_ANDI, RI10, 0x0a0, "andi", _A3(A_T,A_A,A_S10), 00012, FX2) /* AND%I RT<-RA&I10 */
218APUOP(M_ORBI, RI10, 0x030, "orbi", _A3(A_T,A_A,A_S10B), 00012, FX2) /* OR%I RT<-RA|I10 */
219APUOP(M_ORHI, RI10, 0x028, "orhi", _A3(A_T,A_A,A_S10), 00012, FX2) /* OR%I RT<-RA|I10 */
220APUOP(M_ORI, RI10, 0x020, "ori", _A3(A_T,A_A,A_S10), 00012, FX2) /* OR%I RT<-RA|I10 */
221APUOP(M_ORX, RR, 0x1f0, "orx", _A2(A_T,A_A), 00012, BR) /* ORX RT<-RA.w0|RA.w1|RA.w2|RA.w3 */
222APUOP(M_XORBI, RI10, 0x230, "xorbi", _A3(A_T,A_A,A_S10B), 00012, FX2) /* XOR%I RT<-RA^I10 */
223APUOP(M_XORHI, RI10, 0x228, "xorhi", _A3(A_T,A_A,A_S10), 00012, FX2) /* XOR%I RT<-RA^I10 */
224APUOP(M_XORI, RI10, 0x220, "xori", _A3(A_T,A_A,A_S10), 00012, FX2) /* XOR%I RT<-RA^I10 */
225APUOP(M_AHI, RI10, 0x0e8, "ahi", _A3(A_T,A_A,A_S10), 00012, FX2) /* Add%Immed RT<-RA+I10 */
226APUOP(M_AI, RI10, 0x0e0, "ai", _A3(A_T,A_A,A_S10), 00012, FX2) /* Add%Immed RT<-RA+I10 */
227APUOP(M_SFHI, RI10, 0x068, "sfhi", _A3(A_T,A_A,A_S10), 00012, FX2) /* SubFrom%Imm RT<-I10-RA */
228APUOP(M_SFI, RI10, 0x060, "sfi", _A3(A_T,A_A,A_S10), 00012, FX2) /* SubFrom%Imm RT<-I10-RA */
229APUOP(M_CGTBI, RI10, 0x270, "cgtbi", _A3(A_T,A_A,A_S10B), 00012, FX2) /* CGT%I RT<-(RA>I10) */
230APUOP(M_CGTHI, RI10, 0x268, "cgthi", _A3(A_T,A_A,A_S10), 00012, FX2) /* CGT%I RT<-(RA>I10) */
231APUOP(M_CGTI, RI10, 0x260, "cgti", _A3(A_T,A_A,A_S10), 00012, FX2) /* CGT%I RT<-(RA>I10) */
232APUOP(M_CLGTBI, RI10, 0x2f0, "clgtbi", _A3(A_T,A_A,A_S10B), 00012, FX2) /* CLGT%I RT<-(RA>I10) */
233APUOP(M_CLGTHI, RI10, 0x2e8, "clgthi", _A3(A_T,A_A,A_S10), 00012, FX2) /* CLGT%I RT<-(RA>I10) */
234APUOP(M_CLGTI, RI10, 0x2e0, "clgti", _A3(A_T,A_A,A_S10), 00012, FX2) /* CLGT%I RT<-(RA>I10) */
235APUOP(M_CEQBI, RI10, 0x3f0, "ceqbi", _A3(A_T,A_A,A_S10B), 00012, FX2) /* CEQ%I RT<-(RA=I10) */
236APUOP(M_CEQHI, RI10, 0x3e8, "ceqhi", _A3(A_T,A_A,A_S10), 00012, FX2) /* CEQ%I RT<-(RA=I10) */
237APUOP(M_CEQI, RI10, 0x3e0, "ceqi", _A3(A_T,A_A,A_S10), 00012, FX2) /* CEQ%I RT<-(RA=I10) */
238APUOP(M_HGTI, RI10, 0x278, "hgti", _A3(A_T,A_A,A_S10), 00010, FX2) /* HaltGTI halt_if(RA>I10) */
239APUOP(M_HGTI2, RI10, 0x278, "hgti", _A2(A_A,A_S10), 00010, FX2) /* HaltGTI halt_if(RA>I10) */
240APUOP(M_HLGTI, RI10, 0x2f8, "hlgti", _A3(A_T,A_A,A_S10), 00010, FX2) /* HaltLGTI halt_if(RA>I10) */
241APUOP(M_HLGTI2, RI10, 0x2f8, "hlgti", _A2(A_A,A_S10), 00010, FX2) /* HaltLGTI halt_if(RA>I10) */
242APUOP(M_HEQI, RI10, 0x3f8, "heqi", _A3(A_T,A_A,A_S10), 00010, FX2) /* HaltEQImm halt_if(RA=I10) */
243APUOP(M_HEQI2, RI10, 0x3f8, "heqi", _A2(A_A,A_S10), 00010, FX2) /* HaltEQImm halt_if(RA=I10) */
244APUOP(M_MPYI, RI10, 0x3a0, "mpyi", _A3(A_T,A_A,A_S10), 00012, FP7) /* MPYI RT<-RA*I10 */
245APUOP(M_MPYUI, RI10, 0x3a8, "mpyui", _A3(A_T,A_A,A_S10), 00012, FP7) /* MPYUI RT<-RA*I10 */
246APUOP(M_CFLTS, RI8, 0x3b0, "cflts", _A3(A_T,A_A,A_U7A), 00012, FP7) /* CFLTS RT<-int(RA,I8) */
247APUOP(M_CFLTU, RI8, 0x3b2, "cfltu", _A3(A_T,A_A,A_U7A), 00012, FP7) /* CFLTU RT<-int(RA,I8) */
248APUOP(M_CSFLT, RI8, 0x3b4, "csflt", _A3(A_T,A_A,A_U7B), 00012, FP7) /* CSFLT RT<-flt(RA,I8) */
249APUOP(M_CUFLT, RI8, 0x3b6, "cuflt", _A3(A_T,A_A,A_U7B), 00012, FP7) /* CUFLT RT<-flt(RA,I8) */
250APUOP(M_FESD, RR, 0x3b8, "fesd", _A2(A_T,A_A), 00012, FPD) /* FESD RT<-double(RA) */
251APUOP(M_FRDS, RR, 0x3b9, "frds", _A2(A_T,A_A), 00012, FPD) /* FRDS RT<-single(RA) */
252APUOP(M_FSCRRD, RR, 0x398, "fscrrd", _A1(A_T), 00002, FPD) /* FSCRRD RT<-FP_status */
253APUOP(M_FSCRWR, RR, 0x3ba, "fscrwr", _A2(A_T,A_A), 00010, FP7) /* FSCRWR FP_status<-RA */
254APUOP(M_FSCRWR2, RR, 0x3ba, "fscrwr", _A1(A_A), 00010, FP7) /* FSCRWR FP_status<-RA */
255APUOP(M_CLZ, RR, 0x2a5, "clz", _A2(A_T,A_A), 00012, FX2) /* CLZ RT<-clz(RA) */
256APUOP(M_CNTB, RR, 0x2b4, "cntb", _A2(A_T,A_A), 00012, FXB) /* CNT RT<-pop(RA) */
257APUOP(M_XSBH, RR, 0x2b6, "xsbh", _A2(A_T,A_A), 00012, FX2) /* eXtSignBtoH RT<-sign_ext(RA) */
258APUOP(M_XSHW, RR, 0x2ae, "xshw", _A2(A_T,A_A), 00012, FX2) /* eXtSignHtoW RT<-sign_ext(RA) */
259APUOP(M_XSWD, RR, 0x2a6, "xswd", _A2(A_T,A_A), 00012, FX2) /* eXtSignWtoD RT<-sign_ext(RA) */
260APUOP(M_ROTI, RI7, 0x078, "roti", _A3(A_T,A_A,A_S7N), 00012, FX3) /* ROT%I RT<-RA<<<I7 */
261APUOP(M_ROTMI, RI7, 0x079, "rotmi", _A3(A_T,A_A,A_S7), 00012, FX3) /* ROT%MI RT<-RA<<I7 */
262APUOP(M_ROTMAI, RI7, 0x07a, "rotmai", _A3(A_T,A_A,A_S7), 00012, FX3) /* ROTMA%I RT<-RA<<I7 */
263APUOP(M_SHLI, RI7, 0x07b, "shli", _A3(A_T,A_A,A_U6), 00012, FX3) /* SHL%I RT<-RA<<I7 */
264APUOP(M_ROTHI, RI7, 0x07c, "rothi", _A3(A_T,A_A,A_S7N), 00012, FX3) /* ROT%I RT<-RA<<<I7 */
265APUOP(M_ROTHMI, RI7, 0x07d, "rothmi", _A3(A_T,A_A,A_S6), 00012, FX3) /* ROT%MI RT<-RA<<I7 */
266APUOP(M_ROTMAHI, RI7, 0x07e, "rotmahi", _A3(A_T,A_A,A_S6), 00012, FX3) /* ROTMA%I RT<-RA<<I7 */
267APUOP(M_SHLHI, RI7, 0x07f, "shlhi", _A3(A_T,A_A,A_U5), 00012, FX3) /* SHL%I RT<-RA<<I7 */
268APUOP(M_A, RR, 0x0c0, "a", _A3(A_T,A_A,A_B), 00112, FX2) /* Add% RT<-RA+RB */
269APUOP(M_AH, RR, 0x0c8, "ah", _A3(A_T,A_A,A_B), 00112, FX2) /* Add% RT<-RA+RB */
270APUOP(M_SF, RR, 0x040, "sf", _A3(A_T,A_A,A_B), 00112, FX2) /* SubFrom% RT<-RB-RA */
271APUOP(M_SFH, RR, 0x048, "sfh", _A3(A_T,A_A,A_B), 00112, FX2) /* SubFrom% RT<-RB-RA */
272APUOP(M_CGT, RR, 0x240, "cgt", _A3(A_T,A_A,A_B), 00112, FX2) /* CGT% RT<-(RA>RB) */
273APUOP(M_CGTB, RR, 0x250, "cgtb", _A3(A_T,A_A,A_B), 00112, FX2) /* CGT% RT<-(RA>RB) */
274APUOP(M_CGTH, RR, 0x248, "cgth", _A3(A_T,A_A,A_B), 00112, FX2) /* CGT% RT<-(RA>RB) */
275APUOP(M_CLGT, RR, 0x2c0, "clgt", _A3(A_T,A_A,A_B), 00112, FX2) /* CLGT% RT<-(RA>RB) */
276APUOP(M_CLGTB, RR, 0x2d0, "clgtb", _A3(A_T,A_A,A_B), 00112, FX2) /* CLGT% RT<-(RA>RB) */
277APUOP(M_CLGTH, RR, 0x2c8, "clgth", _A3(A_T,A_A,A_B), 00112, FX2) /* CLGT% RT<-(RA>RB) */
278APUOP(M_CEQ, RR, 0x3c0, "ceq", _A3(A_T,A_A,A_B), 00112, FX2) /* CEQ% RT<-(RA=RB) */
279APUOP(M_CEQB, RR, 0x3d0, "ceqb", _A3(A_T,A_A,A_B), 00112, FX2) /* CEQ% RT<-(RA=RB) */
280APUOP(M_CEQH, RR, 0x3c8, "ceqh", _A3(A_T,A_A,A_B), 00112, FX2) /* CEQ% RT<-(RA=RB) */
281APUOP(M_HGT, RR, 0x258, "hgt", _A3(A_T,A_A,A_B), 00110, FX2) /* HaltGT halt_if(RA>RB) */
282APUOP(M_HGT2, RR, 0x258, "hgt", _A2(A_A,A_B), 00110, FX2) /* HaltGT halt_if(RA>RB) */
283APUOP(M_HLGT, RR, 0x2d8, "hlgt", _A3(A_T,A_A,A_B), 00110, FX2) /* HaltLGT halt_if(RA>RB) */
284APUOP(M_HLGT2, RR, 0x2d8, "hlgt", _A2(A_A,A_B), 00110, FX2) /* HaltLGT halt_if(RA>RB) */
285APUOP(M_HEQ, RR, 0x3d8, "heq", _A3(A_T,A_A,A_B), 00110, FX2) /* HaltEQ halt_if(RA=RB) */
286APUOP(M_HEQ2, RR, 0x3d8, "heq", _A2(A_A,A_B), 00110, FX2) /* HaltEQ halt_if(RA=RB) */
287APUOP(M_FCEQ, RR, 0x3c2, "fceq", _A3(A_T,A_A,A_B), 00112, FX2) /* FCEQ RT<-(RA=RB) */
288APUOP(M_FCMEQ, RR, 0x3ca, "fcmeq", _A3(A_T,A_A,A_B), 00112, FX2) /* FCMEQ RT<-(|RA|=|RB|) */
289APUOP(M_FCGT, RR, 0x2c2, "fcgt", _A3(A_T,A_A,A_B), 00112, FX2) /* FCGT RT<-(RA<RB) */
290APUOP(M_FCMGT, RR, 0x2ca, "fcmgt", _A3(A_T,A_A,A_B), 00112, FX2) /* FCMGT RT<-(|RA|<|RB|) */
291APUOP(M_AND, RR, 0x0c1, "and", _A3(A_T,A_A,A_B), 00112, FX2) /* AND RT<-RA&RB */
292APUOP(M_NAND, RR, 0x0c9, "nand", _A3(A_T,A_A,A_B), 00112, FX2) /* NAND RT<-!(RA&RB) */
293APUOP(M_OR, RR, 0x041, "or", _A3(A_T,A_A,A_B), 00112, FX2) /* OR RT<-RA|RB */
294APUOP(M_NOR, RR, 0x049, "nor", _A3(A_T,A_A,A_B), 00112, FX2) /* NOR RT<-!(RA&RB) */
295APUOP(M_XOR, RR, 0x241, "xor", _A3(A_T,A_A,A_B), 00112, FX2) /* XOR RT<-RA^RB */
296APUOP(M_EQV, RR, 0x249, "eqv", _A3(A_T,A_A,A_B), 00112, FX2) /* EQuiValent RT<-!(RA^RB) */
297APUOP(M_ANDC, RR, 0x2c1, "andc", _A3(A_T,A_A,A_B), 00112, FX2) /* ANDComplement RT<-RA&!RB */
298APUOP(M_ORC, RR, 0x2c9, "orc", _A3(A_T,A_A,A_B), 00112, FX2) /* ORComplement RT<-RA|!RB */
299APUOP(M_ABSDB, RR, 0x053, "absdb", _A3(A_T,A_A,A_B), 00112, FXB) /* ABSoluteDiff RT<-|RA-RB| */
300APUOP(M_AVGB, RR, 0x0d3, "avgb", _A3(A_T,A_A,A_B), 00112, FXB) /* AVG% RT<-(RA+RB+1)/2 */
301APUOP(M_SUMB, RR, 0x253, "sumb", _A3(A_T,A_A,A_B), 00112, FXB) /* SUM% RT<-f(RA,RB) */
302APUOP(M_DFA, RR, 0x2cc, "dfa", _A3(A_T,A_A,A_B), 00112, FPD) /* DFAdd RT<-RA+RB */
303APUOP(M_DFM, RR, 0x2ce, "dfm", _A3(A_T,A_A,A_B), 00112, FPD) /* DFMul RT<-RA*RB */
304APUOP(M_DFS, RR, 0x2cd, "dfs", _A3(A_T,A_A,A_B), 00112, FPD) /* DFSub RT<-RA-RB */
305APUOP(M_FA, RR, 0x2c4, "fa", _A3(A_T,A_A,A_B), 00112, FP6) /* FAdd RT<-RA+RB */
306APUOP(M_FM, RR, 0x2c6, "fm", _A3(A_T,A_A,A_B), 00112, FP6) /* FMul RT<-RA*RB */
307APUOP(M_FS, RR, 0x2c5, "fs", _A3(A_T,A_A,A_B), 00112, FP6) /* FSub RT<-RA-RB */
308APUOP(M_MPY, RR, 0x3c4, "mpy", _A3(A_T,A_A,A_B), 00112, FP7) /* MPY RT<-RA*RB */
309APUOP(M_MPYH, RR, 0x3c5, "mpyh", _A3(A_T,A_A,A_B), 00112, FP7) /* MPYH RT<-(RAh*RB)<<16 */
310APUOP(M_MPYHH, RR, 0x3c6, "mpyhh", _A3(A_T,A_A,A_B), 00112, FP7) /* MPYHH RT<-RAh*RBh */
311APUOP(M_MPYHHU, RR, 0x3ce, "mpyhhu", _A3(A_T,A_A,A_B), 00112, FP7) /* MPYHHU RT<-RAh*RBh */
312APUOP(M_MPYS, RR, 0x3c7, "mpys", _A3(A_T,A_A,A_B), 00112, FP7) /* MPYS RT<-(RA*RB)>>16 */
313APUOP(M_MPYU, RR, 0x3cc, "mpyu", _A3(A_T,A_A,A_B), 00112, FP7) /* MPYU RT<-RA*RB */
314APUOP(M_FI, RR, 0x3d4, "fi", _A3(A_T,A_A,A_B), 00112, FP7) /* FInterpolate RT<-f(RA,RB) */
315APUOP(M_ROT, RR, 0x058, "rot", _A3(A_T,A_A,A_B), 00112, FX3) /* ROT% RT<-RA<<<RB */
316APUOP(M_ROTM, RR, 0x059, "rotm", _A3(A_T,A_A,A_B), 00112, FX3) /* ROT%M RT<-RA<<Rb */
317APUOP(M_ROTMA, RR, 0x05a, "rotma", _A3(A_T,A_A,A_B), 00112, FX3) /* ROTMA% RT<-RA<<Rb */
318APUOP(M_SHL, RR, 0x05b, "shl", _A3(A_T,A_A,A_B), 00112, FX3) /* SHL% RT<-RA<<Rb */
319APUOP(M_ROTH, RR, 0x05c, "roth", _A3(A_T,A_A,A_B), 00112, FX3) /* ROT% RT<-RA<<<RB */
320APUOP(M_ROTHM, RR, 0x05d, "rothm", _A3(A_T,A_A,A_B), 00112, FX3) /* ROT%M RT<-RA<<Rb */
321APUOP(M_ROTMAH, RR, 0x05e, "rotmah", _A3(A_T,A_A,A_B), 00112, FX3) /* ROTMA% RT<-RA<<Rb */
322APUOP(M_SHLH, RR, 0x05f, "shlh", _A3(A_T,A_A,A_B), 00112, FX3) /* SHL% RT<-RA<<Rb */
323APUOP(M_MPYHHA, RR, 0x346, "mpyhha", _A3(A_T,A_A,A_B), 00113, FP7) /* MPYHHA RT<-RAh*RBh+RT */
324APUOP(M_MPYHHAU, RR, 0x34e, "mpyhhau", _A3(A_T,A_A,A_B), 00113, FP7) /* MPYHHAU RT<-RAh*RBh+RT */
325APUOP(M_DFMA, RR, 0x35c, "dfma", _A3(A_T,A_A,A_B), 00113, FPD) /* DFMAdd RT<-RT+RA*RB */
326APUOP(M_DFMS, RR, 0x35d, "dfms", _A3(A_T,A_A,A_B), 00113, FPD) /* DFMSub RT<-RA*RB-RT */
327APUOP(M_DFNMS, RR, 0x35e, "dfnms", _A3(A_T,A_A,A_B), 00113, FPD) /* DFNMSub RT<-RT-RA*RB */
328APUOP(M_DFNMA, RR, 0x35f, "dfnma", _A3(A_T,A_A,A_B), 00113, FPD) /* DFNMAdd RT<-(-RT)-RA*RB */
329APUOP(M_FMA, RRR, 0x700, "fma", _A4(A_C,A_A,A_B,A_T), 02111, FP6) /* FMAdd RC<-RT+RA*RB */
330APUOP(M_FMS, RRR, 0x780, "fms", _A4(A_C,A_A,A_B,A_T), 02111, FP6) /* FMSub RC<-RA*RB-RT */
331APUOP(M_FNMS, RRR, 0x680, "fnms", _A4(A_C,A_A,A_B,A_T), 02111, FP6) /* FNMSub RC<-RT-RA*RB */
332APUOP(M_MPYA, RRR, 0x600, "mpya", _A4(A_C,A_A,A_B,A_T), 02111, FP7) /* MPYA RC<-RA*RB+RT */
333APUOP(M_SELB, RRR, 0x400, "selb", _A4(A_C,A_A,A_B,A_T), 02111, FX2) /* SELectBits RC<-RA&RT|RB&!RT */
334/* for system function call, this uses op-code of mtspr */
335APUOP(M_SYSCALL, RI7, 0x10c, "syscall", _A3(A_T,A_A,A_S7N), 00002, SPR) /* System Call */
336/*
337pseudo instruction:
338system call
339value of I9 operation
3400 halt
3411 rt[0] = open(MEM[ra[0]], ra[1])
3422 rt[0] = close(ra[0])
3433 rt[0] = read(ra[0], MEM[ra[1]], ra[2])
3444 rt[0] = write(ra[0], MEM[ra[1]], ra[2])
3455 printf(MEM[ra[0]], ra[1], ra[2], ra[3])
34642 rt[0] = clock()
34752 rt[0] = lseek(ra0, ra1, ra2)
348
349*/
350
351
352/* new multiprecision add/sub */
353APUOP(M_ADDX, RR, 0x340, "addx", _A3(A_T,A_A,A_B), 00113, FX2) /* Add_eXtended RT<-RA+RB+RT */
354APUOP(M_CG, RR, 0x0c2, "cg", _A3(A_T,A_A,A_B), 00112, FX2) /* CarryGenerate RT<-cout(RA+RB) */
355APUOP(M_CGX, RR, 0x342, "cgx", _A3(A_T,A_A,A_B), 00113, FX2) /* CarryGen_eXtd RT<-cout(RA+RB+RT) */
356APUOP(M_SFX, RR, 0x341, "sfx", _A3(A_T,A_A,A_B), 00113, FX2) /* Add_eXtended RT<-RA+RB+RT */
357APUOP(M_BG, RR, 0x042, "bg", _A3(A_T,A_A,A_B), 00112, FX2) /* CarryGenerate RT<-cout(RA+RB) */
358APUOP(M_BGX, RR, 0x343, "bgx", _A3(A_T,A_A,A_B), 00113, FX2) /* CarryGen_eXtd RT<-cout(RA+RB+RT) */
359
360/*
361
362The following ops are a subset of above except with feature bits set.
363Feature bits are bits 11-17 of the instruction:
364
365 11 - C & P feature bit
366 12 - disable interrupts
367 13 - enable interrupts
368
369*/
370APUOPFB(M_BID, RR, 0x1a8, 0x20, "bid", _A1(A_A), 00010, BR) /* BI IP<-RA */
371APUOPFB(M_BIE, RR, 0x1a8, 0x10, "bie", _A1(A_A), 00010, BR) /* BI IP<-RA */
372APUOPFB(M_BISLD, RR, 0x1a9, 0x20, "bisld", _A2(A_T,A_A), 00012, BR) /* BISL RT,IP<-IP,RA */
373APUOPFB(M_BISLE, RR, 0x1a9, 0x10, "bisle", _A2(A_T,A_A), 00012, BR) /* BISL RT,IP<-IP,RA */
374APUOPFB(M_IRETD, RR, 0x1aa, 0x20, "iretd", _A1(A_A), 00010, BR) /* IRET IP<-SRR0 */
375APUOPFB(M_IRETD2, RR, 0x1aa, 0x20, "iretd", _A0(), 00010, BR) /* IRET IP<-SRR0 */
376APUOPFB(M_IRETE, RR, 0x1aa, 0x10, "irete", _A1(A_A), 00010, BR) /* IRET IP<-SRR0 */
377APUOPFB(M_IRETE2, RR, 0x1aa, 0x10, "irete", _A0(), 00010, BR) /* IRET IP<-SRR0 */
378APUOPFB(M_BISLEDD, RR, 0x1ab, 0x20, "bisledd", _A2(A_T,A_A), 00012, BR) /* BISLED RT,IP<-IP,RA_if(ext) */
379APUOPFB(M_BISLEDE, RR, 0x1ab, 0x10, "bislede", _A2(A_T,A_A), 00012, BR) /* BISLED RT,IP<-IP,RA_if(ext) */
380APUOPFB(M_BIHNZD, RR, 0x12b, 0x20, "bihnzd", _A2(A_T,A_A), 00011, BR) /* BIHNZ IP<-RA_if(RT) */
381APUOPFB(M_BIHNZE, RR, 0x12b, 0x10, "bihnze", _A2(A_T,A_A), 00011, BR) /* BIHNZ IP<-RA_if(RT) */
382APUOPFB(M_BIHZD, RR, 0x12a, 0x20, "bihzd", _A2(A_T,A_A), 00011, BR) /* BIHZ IP<-RA_if(RT) */
383APUOPFB(M_BIHZE, RR, 0x12a, 0x10, "bihze", _A2(A_T,A_A), 00011, BR) /* BIHZ IP<-RA_if(RT) */
384APUOPFB(M_BINZD, RR, 0x129, 0x20, "binzd", _A2(A_T,A_A), 00011, BR) /* BINZ IP<-RA_if(RT) */
385APUOPFB(M_BINZE, RR, 0x129, 0x10, "binze", _A2(A_T,A_A), 00011, BR) /* BINZ IP<-RA_if(RT) */
386APUOPFB(M_BIZD, RR, 0x128, 0x20, "bizd", _A2(A_T,A_A), 00011, BR) /* BIZ IP<-RA_if(RT) */
387APUOPFB(M_BIZE, RR, 0x128, 0x10, "bize", _A2(A_T,A_A), 00011, BR) /* BIZ IP<-RA_if(RT) */
388APUOPFB(M_SYNCC, RR, 0x002, 0x40, "syncc", _A0(), 00000, BR) /* SYNCC flush_pipe */
389APUOPFB(M_HBRP, LBTI, 0x1ac, 0x40, "hbrp", _A0(), 00010, LS) /* HBR BTB[B9]<-M[Ra] */
390
391/* Synonyms required by the AS manual. */
392APUOP(M_LR, RI10, 0x020, "lr", _A2(A_T,A_A), 00012, FX2) /* OR%I RT<-RA|I10 */
393APUOP(M_BIHT, RR, 0x12b, "biht", _A2(A_T,A_A), 00011, BR) /* BIHNZ IP<-RA_if(RT) */
394APUOP(M_BIHF, RR, 0x12a, "bihf", _A2(A_T,A_A), 00011, BR) /* BIHZ IP<-RA_if(RT) */
395APUOP(M_BIT, RR, 0x129, "bit", _A2(A_T,A_A), 00011, BR) /* BINZ IP<-RA_if(RT) */
396APUOP(M_BIF, RR, 0x128, "bif", _A2(A_T,A_A), 00011, BR) /* BIZ IP<-RA_if(RT) */
397APUOPFB(M_BIHTD, RR, 0x12b, 0x20, "bihtd", _A2(A_T,A_A), 00011, BR) /* BIHNF IP<-RA_if(RT) */
398APUOPFB(M_BIHTE, RR, 0x12b, 0x10, "bihte", _A2(A_T,A_A), 00011, BR) /* BIHNF IP<-RA_if(RT) */
399APUOPFB(M_BIHFD, RR, 0x12a, 0x20, "bihfd", _A2(A_T,A_A), 00011, BR) /* BIHZ IP<-RA_if(RT) */
400APUOPFB(M_BIHFE, RR, 0x12a, 0x10, "bihfe", _A2(A_T,A_A), 00011, BR) /* BIHZ IP<-RA_if(RT) */
401APUOPFB(M_BITD, RR, 0x129, 0x20, "bitd", _A2(A_T,A_A), 00011, BR) /* BINF IP<-RA_if(RT) */
402APUOPFB(M_BITE, RR, 0x129, 0x10, "bite", _A2(A_T,A_A), 00011, BR) /* BINF IP<-RA_if(RT) */
403APUOPFB(M_BIFD, RR, 0x128, 0x20, "bifd", _A2(A_T,A_A), 00011, BR) /* BIZ IP<-RA_if(RT) */
404APUOPFB(M_BIFE, RR, 0x128, 0x10, "bife", _A2(A_T,A_A), 00011, BR) /* BIZ IP<-RA_if(RT) */
405
406#undef _A0
407#undef _A1
408#undef _A2
409#undef _A3
410#undef _A4
diff --git a/arch/powerpc/xmon/spu-opc.c b/arch/powerpc/xmon/spu-opc.c
new file mode 100644
index 000000000000..efffde9edc6e
--- /dev/null
+++ b/arch/powerpc/xmon/spu-opc.c
@@ -0,0 +1,44 @@
1/* SPU opcode list
2
3 Copyright 2006 Free Software Foundation, Inc.
4
5 This file is part of GDB, GAS, and the GNU binutils.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
20
21#include "spu.h"
22
23/* This file holds the Spu opcode table */
24
25
26/*
27 Example contents of spu-insn.h
28 id_tag mode mode type opcode mnemonic asmtype dependency FPU L/S? branch? instruction
29 QUAD WORD (0,RC,RB,RA,RT) latency
30 APUOP(M_LQD, 1, 0, RI9, 0x1f8, "lqd", ASM_RI9IDX, 00012, FXU, 1, 0) Load Quadword d-form
31 */
32
33const struct spu_opcode spu_opcodes[] = {
34#define APUOP(TAG,MACFORMAT,OPCODE,MNEMONIC,ASMFORMAT,DEP,PIPE) \
35 { MACFORMAT, OPCODE, MNEMONIC, ASMFORMAT },
36#define APUOPFB(TAG,MACFORMAT,OPCODE,FB,MNEMONIC,ASMFORMAT,DEP,PIPE) \
37 { MACFORMAT, OPCODE, MNEMONIC, ASMFORMAT },
38#include "spu-insns.h"
39#undef APUOP
40#undef APUOPFB
41};
42
43const int spu_num_opcodes =
44 sizeof (spu_opcodes) / sizeof (spu_opcodes[0]);
diff --git a/arch/powerpc/xmon/spu.h b/arch/powerpc/xmon/spu.h
new file mode 100644
index 000000000000..c761fc8f35d8
--- /dev/null
+++ b/arch/powerpc/xmon/spu.h
@@ -0,0 +1,126 @@
1/* SPU ELF support for BFD.
2
3 Copyright 2006 Free Software Foundation, Inc.
4
5 This file is part of GDB, GAS, and the GNU binutils.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
20
21
22/* These two enums are from rel_apu/common/spu_asm_format.h */
23/* definition of instruction format */
24typedef enum {
25 RRR,
26 RI18,
27 RI16,
28 RI10,
29 RI8,
30 RI7,
31 RR,
32 LBT,
33 LBTI,
34 IDATA,
35 UNKNOWN_IFORMAT
36} spu_iformat;
37
38/* These values describe assembly instruction arguments. They indicate
39 * how to encode, range checking and which relocation to use. */
40typedef enum {
41 A_T, /* register at pos 0 */
42 A_A, /* register at pos 7 */
43 A_B, /* register at pos 14 */
44 A_C, /* register at pos 21 */
45 A_S, /* special purpose register at pos 7 */
46 A_H, /* channel register at pos 7 */
47 A_P, /* parenthesis, this has to separate regs from immediates */
48 A_S3,
49 A_S6,
50 A_S7N,
51 A_S7,
52 A_U7A,
53 A_U7B,
54 A_S10B,
55 A_S10,
56 A_S11,
57 A_S11I,
58 A_S14,
59 A_S16,
60 A_S18,
61 A_R18,
62 A_U3,
63 A_U5,
64 A_U6,
65 A_U7,
66 A_U14,
67 A_X16,
68 A_U18,
69 A_MAX
70} spu_aformat;
71
72enum spu_insns {
73#define APUOP(TAG,MACFORMAT,OPCODE,MNEMONIC,ASMFORMAT,DEP,PIPE) \
74 TAG,
75#define APUOPFB(TAG,MACFORMAT,OPCODE,FB,MNEMONIC,ASMFORMAT,DEP,PIPE) \
76 TAG,
77#include "spu-insns.h"
78#undef APUOP
79#undef APUOPFB
80 M_SPU_MAX
81};
82
83struct spu_opcode
84{
85 spu_iformat insn_type;
86 unsigned int opcode;
87 char *mnemonic;
88 int arg[5];
89};
90
91#define SIGNED_EXTRACT(insn,size,pos) (((int)((insn) << (32-size-pos))) >> (32-size))
92#define UNSIGNED_EXTRACT(insn,size,pos) (((insn) >> pos) & ((1 << size)-1))
93
94#define DECODE_INSN_RT(insn) (insn & 0x7f)
95#define DECODE_INSN_RA(insn) ((insn >> 7) & 0x7f)
96#define DECODE_INSN_RB(insn) ((insn >> 14) & 0x7f)
97#define DECODE_INSN_RC(insn) ((insn >> 21) & 0x7f)
98
99#define DECODE_INSN_I10(insn) SIGNED_EXTRACT(insn,10,14)
100#define DECODE_INSN_U10(insn) UNSIGNED_EXTRACT(insn,10,14)
101
102/* For branching, immediate loads, hbr and lqa/stqa. */
103#define DECODE_INSN_I16(insn) SIGNED_EXTRACT(insn,16,7)
104#define DECODE_INSN_U16(insn) UNSIGNED_EXTRACT(insn,16,7)
105
106/* for stop */
107#define DECODE_INSN_U14(insn) UNSIGNED_EXTRACT(insn,14,0)
108
109/* For ila */
110#define DECODE_INSN_I18(insn) SIGNED_EXTRACT(insn,18,7)
111#define DECODE_INSN_U18(insn) UNSIGNED_EXTRACT(insn,18,7)
112
113/* For rotate and shift and generate control mask */
114#define DECODE_INSN_I7(insn) SIGNED_EXTRACT(insn,7,14)
115#define DECODE_INSN_U7(insn) UNSIGNED_EXTRACT(insn,7,14)
116
117/* For float <-> int conversion */
118#define DECODE_INSN_I8(insn) SIGNED_EXTRACT(insn,8,14)
119#define DECODE_INSN_U8(insn) UNSIGNED_EXTRACT(insn,8,14)
120
121/* For hbr */
122#define DECODE_INSN_I9a(insn) ((SIGNED_EXTRACT(insn,2,23) << 7) | UNSIGNED_EXTRACT(insn,7,0))
123#define DECODE_INSN_I9b(insn) ((SIGNED_EXTRACT(insn,2,14) << 7) | UNSIGNED_EXTRACT(insn,7,0))
124#define DECODE_INSN_U9a(insn) ((UNSIGNED_EXTRACT(insn,2,23) << 7) | UNSIGNED_EXTRACT(insn,7,0))
125#define DECODE_INSN_U9b(insn) ((UNSIGNED_EXTRACT(insn,2,14) << 7) | UNSIGNED_EXTRACT(insn,7,0))
126
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index f56ffef4defa..a34ed49e0356 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -37,13 +37,18 @@
37#include <asm/sstep.h> 37#include <asm/sstep.h>
38#include <asm/bug.h> 38#include <asm/bug.h>
39#include <asm/irq_regs.h> 39#include <asm/irq_regs.h>
40#include <asm/spu.h>
41#include <asm/spu_priv1.h>
42#include <asm/firmware.h>
40 43
41#ifdef CONFIG_PPC64 44#ifdef CONFIG_PPC64
42#include <asm/hvcall.h> 45#include <asm/hvcall.h>
43#include <asm/paca.h> 46#include <asm/paca.h>
47#include <asm/iseries/it_lp_reg_save.h>
44#endif 48#endif
45 49
46#include "nonstdio.h" 50#include "nonstdio.h"
51#include "dis-asm.h"
47 52
48#define scanhex xmon_scanhex 53#define scanhex xmon_scanhex
49#define skipbl xmon_skipbl 54#define skipbl xmon_skipbl
@@ -107,7 +112,6 @@ static int bsesc(void);
107static void dump(void); 112static void dump(void);
108static void prdump(unsigned long, long); 113static void prdump(unsigned long, long);
109static int ppc_inst_dump(unsigned long, long, int); 114static int ppc_inst_dump(unsigned long, long, int);
110void print_address(unsigned long);
111static void backtrace(struct pt_regs *); 115static void backtrace(struct pt_regs *);
112static void excprint(struct pt_regs *); 116static void excprint(struct pt_regs *);
113static void prregs(struct pt_regs *); 117static void prregs(struct pt_regs *);
@@ -147,9 +151,9 @@ static void xmon_print_symbol(unsigned long address, const char *mid,
147 const char *after); 151 const char *after);
148static const char *getvecname(unsigned long vec); 152static const char *getvecname(unsigned long vec);
149 153
150int xmon_no_auto_backtrace; 154static int do_spu_cmd(void);
151 155
152extern int print_insn_powerpc(unsigned long, unsigned long, int); 156int xmon_no_auto_backtrace;
153 157
154extern void xmon_enter(void); 158extern void xmon_enter(void);
155extern void xmon_leave(void); 159extern void xmon_leave(void);
@@ -209,8 +213,15 @@ Commands:\n\
209 mi show information about memory allocation\n\ 213 mi show information about memory allocation\n\
210 p call a procedure\n\ 214 p call a procedure\n\
211 r print registers\n\ 215 r print registers\n\
212 s single step\n\ 216 s single step\n"
213 S print special registers\n\ 217#ifdef CONFIG_SPU_BASE
218" ss stop execution on all spus\n\
219 sr restore execution on stopped spus\n\
220 sf # dump spu fields for spu # (in hex)\n\
221 sd # dump spu local store for spu # (in hex)\
222 sdi # disassemble spu local store for spu # (in hex)\n"
223#endif
224" S print special registers\n\
214 t print backtrace\n\ 225 t print backtrace\n\
215 x exit monitor and recover\n\ 226 x exit monitor and recover\n\
216 X exit monitor and dont recover\n" 227 X exit monitor and dont recover\n"
@@ -518,6 +529,7 @@ int xmon(struct pt_regs *excp)
518 xmon_save_regs(&regs); 529 xmon_save_regs(&regs);
519 excp = &regs; 530 excp = &regs;
520 } 531 }
532
521 return xmon_core(excp, 0); 533 return xmon_core(excp, 0);
522} 534}
523EXPORT_SYMBOL(xmon); 535EXPORT_SYMBOL(xmon);
@@ -809,6 +821,8 @@ cmds(struct pt_regs *excp)
809 cacheflush(); 821 cacheflush();
810 break; 822 break;
811 case 's': 823 case 's':
824 if (do_spu_cmd() == 0)
825 break;
812 if (do_step(excp)) 826 if (do_step(excp))
813 return cmd; 827 return cmd;
814 break; 828 break;
@@ -1555,11 +1569,6 @@ void super_regs(void)
1555{ 1569{
1556 int cmd; 1570 int cmd;
1557 unsigned long val; 1571 unsigned long val;
1558#ifdef CONFIG_PPC_ISERIES
1559 struct paca_struct *ptrPaca = NULL;
1560 struct lppaca *ptrLpPaca = NULL;
1561 struct ItLpRegSave *ptrLpRegSave = NULL;
1562#endif
1563 1572
1564 cmd = skipbl(); 1573 cmd = skipbl();
1565 if (cmd == '\n') { 1574 if (cmd == '\n') {
@@ -1576,26 +1585,32 @@ void super_regs(void)
1576 printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3)); 1585 printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
1577 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR)); 1586 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR));
1578#ifdef CONFIG_PPC_ISERIES 1587#ifdef CONFIG_PPC_ISERIES
1579 // Dump out relevant Paca data areas. 1588 if (firmware_has_feature(FW_FEATURE_ISERIES)) {
1580 printf("Paca: \n"); 1589 struct paca_struct *ptrPaca;
1581 ptrPaca = get_paca(); 1590 struct lppaca *ptrLpPaca;
1582 1591 struct ItLpRegSave *ptrLpRegSave;
1583 printf(" Local Processor Control Area (LpPaca): \n"); 1592
1584 ptrLpPaca = ptrPaca->lppaca_ptr; 1593 /* Dump out relevant Paca data areas. */
1585 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n", 1594 printf("Paca: \n");
1586 ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1); 1595 ptrPaca = get_paca();
1587 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n", 1596
1588 ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4); 1597 printf(" Local Processor Control Area (LpPaca): \n");
1589 printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5); 1598 ptrLpPaca = ptrPaca->lppaca_ptr;
1590 1599 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n",
1591 printf(" Local Processor Register Save Area (LpRegSave): \n"); 1600 ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1);
1592 ptrLpRegSave = ptrPaca->reg_save_ptr; 1601 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n",
1593 printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n", 1602 ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4);
1594 ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0); 1603 printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5);
1595 printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n", 1604
1596 ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3); 1605 printf(" Local Processor Register Save Area (LpRegSave): \n");
1597 printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n", 1606 ptrLpRegSave = ptrPaca->reg_save_ptr;
1598 ptrLpRegSave->xMSR, ptrLpRegSave->xNIA); 1607 printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n",
1608 ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0);
1609 printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n",
1610 ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3);
1611 printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n",
1612 ptrLpRegSave->xMSR, ptrLpRegSave->xNIA);
1613 }
1599#endif 1614#endif
1600 1615
1601 return; 1616 return;
@@ -2053,8 +2068,11 @@ prdump(unsigned long adrs, long ndump)
2053 } 2068 }
2054} 2069}
2055 2070
2071typedef int (*instruction_dump_func)(unsigned long inst, unsigned long addr);
2072
2056int 2073int
2057ppc_inst_dump(unsigned long adr, long count, int praddr) 2074generic_inst_dump(unsigned long adr, long count, int praddr,
2075 instruction_dump_func dump_func)
2058{ 2076{
2059 int nr, dotted; 2077 int nr, dotted;
2060 unsigned long first_adr; 2078 unsigned long first_adr;
@@ -2084,12 +2102,18 @@ ppc_inst_dump(unsigned long adr, long count, int praddr)
2084 if (praddr) 2102 if (praddr)
2085 printf(REG" %.8x", adr, inst); 2103 printf(REG" %.8x", adr, inst);
2086 printf("\t"); 2104 printf("\t");
2087 print_insn_powerpc(inst, adr, 0); /* always returns 4 */ 2105 dump_func(inst, adr);
2088 printf("\n"); 2106 printf("\n");
2089 } 2107 }
2090 return adr - first_adr; 2108 return adr - first_adr;
2091} 2109}
2092 2110
2111int
2112ppc_inst_dump(unsigned long adr, long count, int praddr)
2113{
2114 return generic_inst_dump(adr, count, praddr, print_insn_powerpc);
2115}
2116
2093void 2117void
2094print_address(unsigned long addr) 2118print_address(unsigned long addr)
2095{ 2119{
@@ -2557,6 +2581,10 @@ void dump_segments(void)
2557 2581
2558void xmon_init(int enable) 2582void xmon_init(int enable)
2559{ 2583{
2584#ifdef CONFIG_PPC_ISERIES
2585 if (firmware_has_feature(FW_FEATURE_ISERIES))
2586 return;
2587#endif
2560 if (enable) { 2588 if (enable) {
2561 __debugger = xmon; 2589 __debugger = xmon;
2562 __debugger_ipi = xmon_ipi; 2590 __debugger_ipi = xmon_ipi;
@@ -2594,6 +2622,10 @@ static struct sysrq_key_op sysrq_xmon_op =
2594 2622
2595static int __init setup_xmon_sysrq(void) 2623static int __init setup_xmon_sysrq(void)
2596{ 2624{
2625#ifdef CONFIG_PPC_ISERIES
2626 if (firmware_has_feature(FW_FEATURE_ISERIES))
2627 return 0;
2628#endif
2597 register_sysrq_key('x', &sysrq_xmon_op); 2629 register_sysrq_key('x', &sysrq_xmon_op);
2598 return 0; 2630 return 0;
2599} 2631}
@@ -2630,3 +2662,263 @@ void __init xmon_setup(void)
2630 if (xmon_early) 2662 if (xmon_early)
2631 debugger(NULL); 2663 debugger(NULL);
2632} 2664}
2665
2666#ifdef CONFIG_SPU_BASE
2667
2668struct spu_info {
2669 struct spu *spu;
2670 u64 saved_mfc_sr1_RW;
2671 u32 saved_spu_runcntl_RW;
2672 unsigned long dump_addr;
2673 u8 stopped_ok;
2674};
2675
2676#define XMON_NUM_SPUS 16 /* Enough for current hardware */
2677
2678static struct spu_info spu_info[XMON_NUM_SPUS];
2679
2680void xmon_register_spus(struct list_head *list)
2681{
2682 struct spu *spu;
2683
2684 list_for_each_entry(spu, list, full_list) {
2685 if (spu->number >= XMON_NUM_SPUS) {
2686 WARN_ON(1);
2687 continue;
2688 }
2689
2690 spu_info[spu->number].spu = spu;
2691 spu_info[spu->number].stopped_ok = 0;
2692 spu_info[spu->number].dump_addr = (unsigned long)
2693 spu_info[spu->number].spu->local_store;
2694 }
2695}
2696
2697static void stop_spus(void)
2698{
2699 struct spu *spu;
2700 int i;
2701 u64 tmp;
2702
2703 for (i = 0; i < XMON_NUM_SPUS; i++) {
2704 if (!spu_info[i].spu)
2705 continue;
2706
2707 if (setjmp(bus_error_jmp) == 0) {
2708 catch_memory_errors = 1;
2709 sync();
2710
2711 spu = spu_info[i].spu;
2712
2713 spu_info[i].saved_spu_runcntl_RW =
2714 in_be32(&spu->problem->spu_runcntl_RW);
2715
2716 tmp = spu_mfc_sr1_get(spu);
2717 spu_info[i].saved_mfc_sr1_RW = tmp;
2718
2719 tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
2720 spu_mfc_sr1_set(spu, tmp);
2721
2722 sync();
2723 __delay(200);
2724
2725 spu_info[i].stopped_ok = 1;
2726
2727 printf("Stopped spu %.2d (was %s)\n", i,
2728 spu_info[i].saved_spu_runcntl_RW ?
2729 "running" : "stopped");
2730 } else {
2731 catch_memory_errors = 0;
2732 printf("*** Error stopping spu %.2d\n", i);
2733 }
2734 catch_memory_errors = 0;
2735 }
2736}
2737
2738static void restart_spus(void)
2739{
2740 struct spu *spu;
2741 int i;
2742
2743 for (i = 0; i < XMON_NUM_SPUS; i++) {
2744 if (!spu_info[i].spu)
2745 continue;
2746
2747 if (!spu_info[i].stopped_ok) {
2748 printf("*** Error, spu %d was not successfully stopped"
2749 ", not restarting\n", i);
2750 continue;
2751 }
2752
2753 if (setjmp(bus_error_jmp) == 0) {
2754 catch_memory_errors = 1;
2755 sync();
2756
2757 spu = spu_info[i].spu;
2758 spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);
2759 out_be32(&spu->problem->spu_runcntl_RW,
2760 spu_info[i].saved_spu_runcntl_RW);
2761
2762 sync();
2763 __delay(200);
2764
2765 printf("Restarted spu %.2d\n", i);
2766 } else {
2767 catch_memory_errors = 0;
2768 printf("*** Error restarting spu %.2d\n", i);
2769 }
2770 catch_memory_errors = 0;
2771 }
2772}
2773
2774#define DUMP_WIDTH 23
2775#define DUMP_VALUE(format, field, value) \
2776do { \
2777 if (setjmp(bus_error_jmp) == 0) { \
2778 catch_memory_errors = 1; \
2779 sync(); \
2780 printf(" %-*s = "format"\n", DUMP_WIDTH, \
2781 #field, value); \
2782 sync(); \
2783 __delay(200); \
2784 } else { \
2785 catch_memory_errors = 0; \
2786 printf(" %-*s = *** Error reading field.\n", \
2787 DUMP_WIDTH, #field); \
2788 } \
2789 catch_memory_errors = 0; \
2790} while (0)
2791
2792#define DUMP_FIELD(obj, format, field) \
2793 DUMP_VALUE(format, field, obj->field)
2794
2795static void dump_spu_fields(struct spu *spu)
2796{
2797 printf("Dumping spu fields at address %p:\n", spu);
2798
2799 DUMP_FIELD(spu, "0x%x", number);
2800 DUMP_FIELD(spu, "%s", name);
2801 DUMP_FIELD(spu, "0x%lx", local_store_phys);
2802 DUMP_FIELD(spu, "0x%p", local_store);
2803 DUMP_FIELD(spu, "0x%lx", ls_size);
2804 DUMP_FIELD(spu, "0x%x", node);
2805 DUMP_FIELD(spu, "0x%lx", flags);
2806 DUMP_FIELD(spu, "0x%lx", dar);
2807 DUMP_FIELD(spu, "0x%lx", dsisr);
2808 DUMP_FIELD(spu, "%d", class_0_pending);
2809 DUMP_FIELD(spu, "0x%lx", irqs[0]);
2810 DUMP_FIELD(spu, "0x%lx", irqs[1]);
2811 DUMP_FIELD(spu, "0x%lx", irqs[2]);
2812 DUMP_FIELD(spu, "0x%x", slb_replace);
2813 DUMP_FIELD(spu, "%d", pid);
2814 DUMP_FIELD(spu, "%d", prio);
2815 DUMP_FIELD(spu, "0x%p", mm);
2816 DUMP_FIELD(spu, "0x%p", ctx);
2817 DUMP_FIELD(spu, "0x%p", rq);
2818 DUMP_FIELD(spu, "0x%p", timestamp);
2819 DUMP_FIELD(spu, "0x%lx", problem_phys);
2820 DUMP_FIELD(spu, "0x%p", problem);
2821 DUMP_VALUE("0x%x", problem->spu_runcntl_RW,
2822 in_be32(&spu->problem->spu_runcntl_RW));
2823 DUMP_VALUE("0x%x", problem->spu_status_R,
2824 in_be32(&spu->problem->spu_status_R));
2825 DUMP_VALUE("0x%x", problem->spu_npc_RW,
2826 in_be32(&spu->problem->spu_npc_RW));
2827 DUMP_FIELD(spu, "0x%p", priv2);
2828 DUMP_FIELD(spu, "0x%p", pdata);
2829}
2830
2831int
2832spu_inst_dump(unsigned long adr, long count, int praddr)
2833{
2834 return generic_inst_dump(adr, count, praddr, print_insn_spu);
2835}
2836
2837static void dump_spu_ls(unsigned long num, int subcmd)
2838{
2839 unsigned long offset, addr, ls_addr;
2840
2841 if (setjmp(bus_error_jmp) == 0) {
2842 catch_memory_errors = 1;
2843 sync();
2844 ls_addr = (unsigned long)spu_info[num].spu->local_store;
2845 sync();
2846 __delay(200);
2847 } else {
2848 catch_memory_errors = 0;
2849 printf("*** Error: accessing spu info for spu %d\n", num);
2850 return;
2851 }
2852 catch_memory_errors = 0;
2853
2854 if (scanhex(&offset))
2855 addr = ls_addr + offset;
2856 else
2857 addr = spu_info[num].dump_addr;
2858
2859 if (addr >= ls_addr + LS_SIZE) {
2860 printf("*** Error: address outside of local store\n");
2861 return;
2862 }
2863
2864 switch (subcmd) {
2865 case 'i':
2866 addr += spu_inst_dump(addr, 16, 1);
2867 last_cmd = "sdi\n";
2868 break;
2869 default:
2870 prdump(addr, 64);
2871 addr += 64;
2872 last_cmd = "sd\n";
2873 break;
2874 }
2875
2876 spu_info[num].dump_addr = addr;
2877}
2878
2879static int do_spu_cmd(void)
2880{
2881 static unsigned long num = 0;
2882 int cmd, subcmd = 0;
2883
2884 cmd = inchar();
2885 switch (cmd) {
2886 case 's':
2887 stop_spus();
2888 break;
2889 case 'r':
2890 restart_spus();
2891 break;
2892 case 'd':
2893 subcmd = inchar();
2894 if (isxdigit(subcmd) || subcmd == '\n')
2895 termch = subcmd;
2896 case 'f':
2897 scanhex(&num);
2898 if (num >= XMON_NUM_SPUS || !spu_info[num].spu) {
2899 printf("*** Error: invalid spu number\n");
2900 return 0;
2901 }
2902
2903 switch (cmd) {
2904 case 'f':
2905 dump_spu_fields(spu_info[num].spu);
2906 break;
2907 default:
2908 dump_spu_ls(num, subcmd);
2909 break;
2910 }
2911
2912 break;
2913 default:
2914 return -1;
2915 }
2916
2917 return 0;
2918}
2919#else /* ! CONFIG_SPU_BASE */
2920static int do_spu_cmd(void)
2921{
2922 return -1;
2923}
2924#endif