]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Tue, 17 Jul 2007 00:58:08 +0000 (17:58 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Tue, 17 Jul 2007 00:58:08 +0000 (17:58 -0700)
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (209 commits)
  [POWERPC] Create add_rtc() function to enable the RTC CMOS driver
  [POWERPC] Add H_ILLAN_ATTRIBUTES hcall number
  [POWERPC] xilinxfb: Parameterize xilinxfb platform device registration
  [POWERPC] Oprofile support for Power 5++
  [POWERPC] Enable arbitary speed tty ioctls and split input/output speed
  [POWERPC] Make drivers/char/hvc_console.c:khvcd() static
  [POWERPC] Remove dead code for preventing pread() and pwrite() calls
  [POWERPC] Remove unnecessary #undef printk from prom.c
  [POWERPC] Fix typo in Ebony default DTS
  [POWERPC] Check for NULL ppc_md.init_IRQ() before calling
  [POWERPC] Remove extra return statement
  [POWERPC] pasemi: Don't auto-select CONFIG_EMBEDDED
  [POWERPC] pasemi: Rename platform
  [POWERPC] arch/powerpc/kernel/sysfs.c: Move NUMA exports
  [POWERPC] Add __read_mostly support for powerpc
  [POWERPC] Modify sched_clock() to make CONFIG_PRINTK_TIME more sane
  [POWERPC] Create a dummy zImage if no valid platform has been selected
  [POWERPC] PS3: Bootwrapper support.
  [POWERPC] powermac i2c: Use mutex
  [POWERPC] Schedule removal of arch/ppc
  ...

Fixed up conflicts manually in:

Documentation/feature-removal-schedule.txt
arch/powerpc/kernel/pci_32.c
arch/powerpc/kernel/pci_64.c
include/asm-powerpc/pci.h

and asked the powerpc people to double-check the result..

280 files changed:
Documentation/cachetlb.txt
Documentation/feature-removal-schedule.txt
Documentation/powerpc/booting-without-of.txt
arch/powerpc/Kconfig
arch/powerpc/Makefile
arch/powerpc/boot/44x.c
arch/powerpc/boot/44x.h
arch/powerpc/boot/Makefile
arch/powerpc/boot/cuboot-83xx.c
arch/powerpc/boot/cuboot-85xx.c
arch/powerpc/boot/cuboot-ebony.c
arch/powerpc/boot/cuboot.c [new file with mode: 0644]
arch/powerpc/boot/cuboot.h [new file with mode: 0644]
arch/powerpc/boot/dcr.h
arch/powerpc/boot/dts/ebony.dts
arch/powerpc/boot/dts/holly.dts
arch/powerpc/boot/dts/mpc7448hpc2.dts
arch/powerpc/boot/dts/mpc8272ads.dts
arch/powerpc/boot/dts/mpc832x_mds.dts
arch/powerpc/boot/dts/mpc832x_rdb.dts
arch/powerpc/boot/dts/mpc8349emitx.dts
arch/powerpc/boot/dts/mpc834x_mds.dts
arch/powerpc/boot/dts/mpc836x_mds.dts
arch/powerpc/boot/dts/mpc8540ads.dts
arch/powerpc/boot/dts/mpc8541cds.dts
arch/powerpc/boot/dts/mpc8544ds.dts
arch/powerpc/boot/dts/mpc8548cds.dts
arch/powerpc/boot/dts/mpc8555cds.dts
arch/powerpc/boot/dts/mpc8560ads.dts
arch/powerpc/boot/dts/mpc8568mds.dts
arch/powerpc/boot/dts/mpc8641_hpcn.dts
arch/powerpc/boot/dts/mpc866ads.dts
arch/powerpc/boot/dts/mpc885ads.dts
arch/powerpc/boot/dts/prpmc2800.dts
arch/powerpc/boot/dts/ps3.dts [new file with mode: 0644]
arch/powerpc/boot/ebony.c
arch/powerpc/boot/main.c
arch/powerpc/boot/of.c
arch/powerpc/boot/of.h [new file with mode: 0644]
arch/powerpc/boot/ofconsole.c [new file with mode: 0644]
arch/powerpc/boot/oflib.c [new file with mode: 0644]
arch/powerpc/boot/ops.h
arch/powerpc/boot/ps3-head.S [new file with mode: 0644]
arch/powerpc/boot/ps3-hvcall.S [new file with mode: 0644]
arch/powerpc/boot/ps3.c [new file with mode: 0644]
arch/powerpc/boot/serial.c
arch/powerpc/boot/stdio.c
arch/powerpc/boot/types.h
arch/powerpc/boot/wrapper
arch/powerpc/boot/zImage.ps3.lds.S [new file with mode: 0644]
arch/powerpc/configs/holly_defconfig
arch/powerpc/configs/ps3_defconfig
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/head_32.S
arch/powerpc/kernel/head_64.S
arch/powerpc/kernel/io.c
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/isa-bridge.c [new file with mode: 0644]
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/misc_64.S
arch/powerpc/kernel/of_platform.c
arch/powerpc/kernel/pci-common.c [new file with mode: 0644]
arch/powerpc/kernel/pci_32.c
arch/powerpc/kernel/pci_64.c
arch/powerpc/kernel/ppc_ksyms.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/ptrace-common.h [deleted file]
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/ptrace32.c
arch/powerpc/kernel/rtas_pci.c
arch/powerpc/kernel/setup-common.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/signal.c [new file with mode: 0644]
arch/powerpc/kernel/signal.h [new file with mode: 0644]
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/kernel/sysfs.c
arch/powerpc/kernel/time.c
arch/powerpc/kernel/vdso.c
arch/powerpc/kernel/vmlinux.lds.S
arch/powerpc/mm/44x_mmu.c
arch/powerpc/mm/4xx_mmu.c
arch/powerpc/mm/Makefile
arch/powerpc/mm/fault.c
arch/powerpc/mm/fsl_booke_mmu.c
arch/powerpc/mm/hash_native_64.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/imalloc.c [deleted file]
arch/powerpc/mm/init_32.c
arch/powerpc/mm/init_64.c
arch/powerpc/mm/mem.c
arch/powerpc/mm/mmu_context_32.c
arch/powerpc/mm/mmu_decl.h
arch/powerpc/mm/pgtable_32.c
arch/powerpc/mm/pgtable_64.c
arch/powerpc/mm/ppc_mmu_32.c
arch/powerpc/mm/stab.c
arch/powerpc/mm/tlb_32.c
arch/powerpc/mm/tlb_64.c
arch/powerpc/oprofile/op_model_power4.c
arch/powerpc/platforms/52xx/efika.c
arch/powerpc/platforms/52xx/lite5200.c
arch/powerpc/platforms/52xx/mpc52xx_pci.c
arch/powerpc/platforms/52xx/mpc52xx_pm.c
arch/powerpc/platforms/82xx/Kconfig
arch/powerpc/platforms/82xx/mpc82xx_ads.c
arch/powerpc/platforms/83xx/Kconfig
arch/powerpc/platforms/83xx/Makefile
arch/powerpc/platforms/83xx/mpc8313_rdb.c
arch/powerpc/platforms/83xx/mpc832x_mds.c
arch/powerpc/platforms/83xx/mpc832x_rdb.c
arch/powerpc/platforms/83xx/mpc834x_itx.c
arch/powerpc/platforms/83xx/mpc834x_mds.c
arch/powerpc/platforms/83xx/mpc836x_mds.c
arch/powerpc/platforms/83xx/mpc83xx.h
arch/powerpc/platforms/83xx/pci.c
arch/powerpc/platforms/83xx/usb.c [new file with mode: 0644]
arch/powerpc/platforms/85xx/misc.c
arch/powerpc/platforms/85xx/mpc8544_ds.c
arch/powerpc/platforms/85xx/mpc85xx.h
arch/powerpc/platforms/85xx/mpc85xx_ads.c
arch/powerpc/platforms/85xx/mpc85xx_cds.c
arch/powerpc/platforms/85xx/mpc85xx_mds.c
arch/powerpc/platforms/85xx/pci.c
arch/powerpc/platforms/86xx/Kconfig
arch/powerpc/platforms/86xx/mpc86xx.h
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
arch/powerpc/platforms/86xx/pci.c
arch/powerpc/platforms/8xx/m8xx_setup.c
arch/powerpc/platforms/8xx/mpc885ads_setup.c
arch/powerpc/platforms/Kconfig
arch/powerpc/platforms/Kconfig.cputype [new file with mode: 0644]
arch/powerpc/platforms/apus/Kconfig [deleted file]
arch/powerpc/platforms/cell/io-workarounds.c
arch/powerpc/platforms/cell/spu_base.c
arch/powerpc/platforms/cell/spufs/backing_ops.c
arch/powerpc/platforms/cell/spufs/context.c
arch/powerpc/platforms/cell/spufs/fault.c
arch/powerpc/platforms/cell/spufs/file.c
arch/powerpc/platforms/cell/spufs/inode.c
arch/powerpc/platforms/cell/spufs/run.c
arch/powerpc/platforms/cell/spufs/sched.c
arch/powerpc/platforms/cell/spufs/spu_restore.c
arch/powerpc/platforms/cell/spufs/spu_save.c
arch/powerpc/platforms/cell/spufs/spufs.h
arch/powerpc/platforms/cell/spufs/switch.c
arch/powerpc/platforms/chrp/Kconfig
arch/powerpc/platforms/chrp/Makefile
arch/powerpc/platforms/chrp/pci.c
arch/powerpc/platforms/embedded6xx/Kconfig
arch/powerpc/platforms/embedded6xx/holly.c
arch/powerpc/platforms/embedded6xx/linkstation.c
arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h
arch/powerpc/platforms/iseries/call_hpt.h
arch/powerpc/platforms/iseries/htab.c
arch/powerpc/platforms/iseries/pci.c
arch/powerpc/platforms/iseries/setup.c
arch/powerpc/platforms/maple/pci.c
arch/powerpc/platforms/pasemi/Kconfig
arch/powerpc/platforms/pasemi/Makefile
arch/powerpc/platforms/pasemi/electra_ide.c [new file with mode: 0644]
arch/powerpc/platforms/pasemi/pci.c
arch/powerpc/platforms/pasemi/setup.c
arch/powerpc/platforms/powermac/Kconfig
arch/powerpc/platforms/powermac/low_i2c.c
arch/powerpc/platforms/powermac/pci.c
arch/powerpc/platforms/ps3/Kconfig
arch/powerpc/platforms/ps3/Makefile
arch/powerpc/platforms/ps3/device-init.c [new file with mode: 0644]
arch/powerpc/platforms/ps3/htab.c
arch/powerpc/platforms/ps3/interrupt.c
arch/powerpc/platforms/ps3/mm.c
arch/powerpc/platforms/ps3/os-area.c
arch/powerpc/platforms/ps3/platform.h
arch/powerpc/platforms/ps3/repository.c
arch/powerpc/platforms/ps3/setup.c
arch/powerpc/platforms/ps3/smp.c
arch/powerpc/platforms/ps3/spu.c
arch/powerpc/platforms/ps3/system-bus.c
arch/powerpc/platforms/ps3/time.c
arch/powerpc/platforms/pseries/Makefile
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/eeh_cache.c
arch/powerpc/platforms/pseries/eeh_driver.c
arch/powerpc/platforms/pseries/eeh_sysfs.c [new file with mode: 0644]
arch/powerpc/platforms/pseries/lpar.c
arch/powerpc/platforms/pseries/pci_dlpar.c
arch/powerpc/platforms/pseries/plpar_wrappers.h
arch/powerpc/platforms/pseries/pseries.h
arch/powerpc/platforms/pseries/reconfig.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/platforms/pseries/xics.c
arch/powerpc/sysdev/Makefile
arch/powerpc/sysdev/fsl_pcie.c [deleted file]
arch/powerpc/sysdev/fsl_soc.c
arch/powerpc/sysdev/indirect_pci.c
arch/powerpc/sysdev/mpc8xx_pic.h
arch/powerpc/sysdev/mv64x60_dev.c
arch/powerpc/sysdev/mv64x60_pci.c
arch/powerpc/sysdev/qe_lib/ucc.c
arch/powerpc/sysdev/qe_lib/ucc_fast.c
arch/powerpc/sysdev/rtc_cmos_setup.c [new file with mode: 0644]
arch/powerpc/sysdev/timer.c
arch/powerpc/sysdev/tsi108_dev.c
arch/powerpc/sysdev/tsi108_pci.c
arch/powerpc/xmon/xmon.c
arch/ppc/kernel/misc.S
arch/ppc/kernel/ppc_ksyms.c
arch/ppc/kernel/setup.c
arch/ppc/mm/tlb.c
arch/ppc/platforms/prep_setup.c
arch/ppc/syslib/Makefile
arch/ppc/syslib/indirect_pci.c [new file with mode: 0644]
arch/ppc/syslib/virtex_devices.c
drivers/block/viodasd.c
drivers/char/briq_panel.c
drivers/char/hvc_console.c
drivers/char/viotape.c
drivers/pci/hotplug/rpadlpar_core.c
drivers/pcmcia/Kconfig
drivers/pcmcia/m8xx_pcmcia.c
drivers/ps3/Makefile
drivers/ps3/ps3av.c
drivers/ps3/ps3av_cmd.c
drivers/ps3/ps3stor_lib.c [new file with mode: 0644]
drivers/ps3/sys-manager-core.c [new file with mode: 0644]
drivers/ps3/sys-manager.c
drivers/ps3/vuart.c
drivers/ps3/vuart.h
drivers/rtc/Kconfig
drivers/serial/cpm_uart/cpm_uart_core.c
drivers/serial/of_serial.c
drivers/video/Kconfig
drivers/video/ps3fb.c
include/asm-powerpc/cache.h
include/asm-powerpc/cputable.h
include/asm-powerpc/floppy.h
include/asm-powerpc/hvcall.h
include/asm-powerpc/io.h
include/asm-powerpc/irq.h
include/asm-powerpc/lppaca.h
include/asm-powerpc/lv1call.h
include/asm-powerpc/machdep.h
include/asm-powerpc/mmu-8xx.h [new file with mode: 0644]
include/asm-powerpc/mmu-fsl-booke.h [new file with mode: 0644]
include/asm-powerpc/mmu-hash32.h [new file with mode: 0644]
include/asm-powerpc/mmu-hash64.h
include/asm-powerpc/mmu.h
include/asm-powerpc/mmu_context.h
include/asm-powerpc/mpc86xx.h
include/asm-powerpc/mpc8xx.h
include/asm-powerpc/pci-bridge.h
include/asm-powerpc/pci.h
include/asm-powerpc/pgtable-ppc32.h
include/asm-powerpc/pgtable-ppc64.h
include/asm-powerpc/pgtable.h
include/asm-powerpc/ppc-pci.h
include/asm-powerpc/processor.h
include/asm-powerpc/prom.h
include/asm-powerpc/ps3.h
include/asm-powerpc/ps3av.h
include/asm-powerpc/ps3fb.h
include/asm-powerpc/ps3stor.h [new file with mode: 0644]
include/asm-powerpc/ptrace.h
include/asm-powerpc/reg.h
include/asm-powerpc/spu.h
include/asm-powerpc/syscalls.h
include/asm-powerpc/system.h
include/asm-powerpc/termbits.h
include/asm-powerpc/thread_info.h
include/asm-powerpc/time.h
include/asm-powerpc/tlbflush.h
include/linux/fsl_devices.h
include/linux/vmalloc.h
mm/vmalloc.c

index debf6813934af05e878863c4a8c53bbf6ae64e62..866b76139420b2b22d25255b136f378b6186d52c 100644 (file)
@@ -253,7 +253,7 @@ Here are the routines, one by one:
 
        The first of these two routines is invoked after map_vm_area()
        has installed the page table entries.  The second is invoked
-       before unmap_vm_area() deletes the page table entries.
+       before unmap_kernel_range() deletes the page table entries.
 
 There exists another whole class of cpu cache issues which currently
 require a whole different set of interfaces to handle properly.
index 18bd2ddccb156aef5175533e084625a50e8827eb..d05e6243b4df2b0bc0db3d58e1105644a91ba48d 100644 (file)
@@ -297,3 +297,16 @@ Why:       Obsolete for multiple years now, NAT core provides the same behaviour.
 Who:   Patrick McHardy <kaber@trash.net>
 
 ---------------------------
+
+What: The arch/ppc and include/asm-ppc directories
+When: Jun 2008
+Why:  The arch/powerpc tree is the merged architecture for ppc32 and ppc64
+      platforms.  Currently there are efforts underway to port the remaining
+      arch/ppc platforms to the merged tree.  New submissions to the arch/ppc
+      tree have been frozen with the 2.6.22 kernel release and that tree will
+      remain in bug-fix only mode until its scheduled removal.  Platforms
+      that are not ported by June 2008 will be removed due to the lack of an
+      interested maintainer.
+Who:  linuxppc-dev@ozlabs.org
+
+---------------------------
index d42d98107d494d906ded560a3e61bfad829e8911..0c2434822094d66945a07ce9afe9564cd682b608 100644 (file)
@@ -42,15 +42,16 @@ Table of Contents
     1) Defining child nodes of an SOC
     2) Representing devices without a current OF specification
       a) MDIO IO device
-      c) PHY nodes
       b) Gianfar-compatible ethernet nodes
+      c) PHY nodes
       d) Interrupt controllers
       e) I2C
       f) Freescale SOC USB controllers
       g) Freescale SOC SEC Security Engines
       h) Board Control and Status (BCSR)
       i) Freescale QUICC Engine module (QE)
-      g) Flash chip nodes
+      j) Flash chip nodes
+      k) Global Utilities Block
 
   VII - Specifying interrupt information for devices
     1) interrupts property
@@ -626,6 +627,14 @@ So the node content can be summarized as a start token, a full path,
 a list of properties, a list of child nodes, and an end token. Every
 child node is a full node structure itself as defined above.
 
+NOTE: The above definition requires that all property definitions for
+a particular node MUST precede any subnode definitions for that node.
+Although the structure would not be ambiguous if properties and
+subnodes were intermingled, the kernel parser requires that the
+properties come first (up until at least 2.6.22).  Any tools
+manipulating a flattened tree must take care to preserve this
+constraint.
+
 4) Device tree "strings" block
 
 In order to save space, property names, which are generally redundant,
@@ -1782,6 +1791,33 @@ platforms are moved over to use the flattened-device-tree model.
                partition-names = "fs\0firmware";
        };
 
+   k) Global Utilities Block
+
+   The global utilities block controls power management, I/O device
+   enabling, power-on-reset configuration monitoring, general-purpose
+   I/O signal configuration, alternate function selection for multiplexed
+   signals, and clock control.
+
+   Required properties:
+
+    - compatible : Should define the compatible device type for
+      global-utilities.
+    - reg : Offset and length of the register set for the device.
+
+  Recommended properties:
+
+    - fsl,has-rstcr : Indicates that the global utilities register set
+      contains a functioning "reset control register" (i.e. the board
+      is wired to reset upon setting the HRESET_REQ bit in this register).
+
+    Example:
+
+       global-utilities@e0000 {        /* global utilities block */
+               compatible = "fsl,mpc8548-guts";
+               reg = <e0000 1000>;
+               fsl,has-rstcr;
+       };
+
    More devices will be defined as this spec matures.
 
 VII - Specifying interrupt information for devices
index 6b8b83ebca7539c1d4bd8d5c8ef504bde6e3a27c..e641bb68d8714488b8332f44a4049171f507df6b 100644 (file)
@@ -4,17 +4,7 @@
 
 mainmenu "Linux/PowerPC Kernel Configuration"
 
-config PPC64
-       bool "64-bit kernel"
-       default n
-       help
-         This option selects whether a 32-bit or a 64-bit kernel
-         will be built.
-
-config PPC_PM_NEEDS_RTC_LIB
-       bool
-       select RTC_LIB
-       default y if PM
+source "arch/powerpc/platforms/Kconfig.cputype"
 
 config PPC32
        bool
@@ -135,123 +125,6 @@ config PPC64_SWSUSP
        depends on PPC64 && (BROKEN || (PPC_PMAC64 && EXPERIMENTAL))
        default y
 
-menu "Processor support"
-choice
-       prompt "Processor Type"
-       depends on PPC32
-       default 6xx
-
-config CLASSIC32
-       bool "52xx/6xx/7xx/74xx"
-       select PPC_FPU
-       select 6xx
-       help
-         There are four families of PowerPC chips supported.  The more common
-         types (601, 603, 604, 740, 750, 7400), the Motorola embedded
-         versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the AMCC
-         embedded versions (403 and 405) and the high end 64 bit Power
-         processors (POWER 3, POWER4, and IBM PPC970 also known as G5).
-
-         This option is the catch-all for 6xx types, including some of the
-         embedded versions.  Unless there is see an option for the specific
-         chip family you are using, you want this option.
-         
-         You do not want this if you are building a kernel for a 64 bit
-         IBM RS/6000 or an Apple G5, choose 6xx.
-         
-         If unsure, select this option
-         
-         Note that the kernel runs in 32-bit mode even on 64-bit chips.
-
-config PPC_82xx
-       bool "Freescale 82xx"
-       select 6xx
-       select PPC_FPU
-
-config PPC_83xx
-       bool "Freescale 83xx"
-       select 6xx
-       select FSL_SOC
-       select 83xx
-       select PPC_FPU
-       select WANT_DEVICE_TREE
-
-config PPC_85xx
-       bool "Freescale 85xx"
-       select E500
-       select FSL_SOC
-       select 85xx
-       select WANT_DEVICE_TREE
-
-config PPC_86xx
-       bool "Freescale 86xx"
-       select 6xx
-       select FSL_SOC
-       select FSL_PCIE
-       select PPC_FPU
-       select ALTIVEC
-       help
-         The Freescale E600 SoCs have 74xx cores.
-
-config PPC_8xx
-       bool "Freescale 8xx"
-       select FSL_SOC
-       select 8xx
-
-config 40x
-       bool "AMCC 40x"
-       select PPC_DCR_NATIVE
-
-config 44x
-       bool "AMCC 44x"
-       select PPC_DCR_NATIVE
-       select WANT_DEVICE_TREE
-
-config E200
-       bool "Freescale e200"
-
-endchoice
-
-config POWER4_ONLY
-       bool "Optimize for POWER4"
-       depends on PPC64
-       default n
-       ---help---
-         Cause the compiler to optimize for POWER4/POWER5/PPC970 processors.
-         The resulting binary will not work on POWER3 or RS64 processors
-         when compiled with binutils 2.15 or later.
-
-config POWER3
-       bool
-       depends on PPC64
-       default y if !POWER4_ONLY
-
-config POWER4
-       depends on PPC64
-       def_bool y
-
-config 6xx
-       bool
-
-# this is temp to handle compat with arch=ppc
-config 8xx
-       bool
-
-# this is temp to handle compat with arch=ppc
-config 83xx
-       bool
-
-# this is temp to handle compat with arch=ppc
-config 85xx
-       bool
-
-config E500
-       bool
-
-config PPC_FPU
-       bool
-       default y if PPC64
-
 config PPC_DCR_NATIVE
        bool
        default n
@@ -270,134 +143,6 @@ config PPC_OF_PLATFORM_PCI
        depends on PPC64 # not supported on 32 bits yet
        default n
 
-config 4xx
-       bool
-       depends on 40x || 44x
-       default y
-
-config BOOKE
-       bool
-       depends on E200 || E500 || 44x
-       default y
-
-config FSL_BOOKE
-       bool
-       depends on E200 || E500
-       default y
-
-config PTE_64BIT
-       bool
-       depends on 44x || E500
-       default y if 44x
-       default y if E500 && PHYS_64BIT
-
-config PHYS_64BIT
-       bool 'Large physical address support' if E500
-       depends on 44x || E500
-       select RESOURCES_64BIT
-       default y if 44x
-       ---help---
-         This option enables kernel support for larger than 32-bit physical
-         addresses.  This features is not be available on all e500 cores.
-
-         If in doubt, say N here.
-
-config ALTIVEC
-       bool "AltiVec Support"
-       depends on CLASSIC32 || POWER4
-       ---help---
-         This option enables kernel support for the Altivec extensions to the
-         PowerPC processor. The kernel currently supports saving and restoring
-         altivec registers, and turning on the 'altivec enable' bit so user
-         processes can execute altivec instructions.
-
-         This option is only usefully if you have a processor that supports
-         altivec (G4, otherwise known as 74xx series), but does not have
-         any affect on a non-altivec cpu (it does, however add code to the
-         kernel).
-
-         If in doubt, say Y here.
-
-config SPE
-       bool "SPE Support"
-       depends on E200 || E500
-       default y
-       ---help---
-         This option enables kernel support for the Signal Processing
-         Extensions (SPE) to the PowerPC processor. The kernel currently
-         supports saving and restoring SPE registers, and turning on the
-         'spe enable' bit so user processes can execute SPE instructions.
-
-         This option is only useful if you have a processor that supports
-         SPE (e500, otherwise known as 85xx series), but does not have any
-         effect on a non-spe cpu (it does, however add code to the kernel).
-
-         If in doubt, say Y here.
-
-config PPC_STD_MMU
-       bool
-       depends on 6xx || POWER3 || POWER4 || PPC64
-       default y
-
-config PPC_STD_MMU_32
-       def_bool y
-       depends on PPC_STD_MMU && PPC32
-
-config PPC_MM_SLICES
-       bool
-       default y if HUGETLB_PAGE
-       default n
-
-config VIRT_CPU_ACCOUNTING
-       bool "Deterministic task and CPU time accounting"
-       depends on PPC64
-       default y
-       help
-         Select this option to enable more accurate task and CPU time
-         accounting.  This is done by reading a CPU counter on each
-         kernel entry and exit and on transitions within the kernel
-         between system, softirq and hardirq state, so there is a
-         small performance impact.  This also enables accounting of
-         stolen time on logically-partitioned systems running on
-         IBM POWER5-based machines.
-
-         If in doubt, say Y here.
-
-config SMP
-       depends on PPC_STD_MMU
-       bool "Symmetric multi-processing support"
-       ---help---
-         This enables support for systems with more than one CPU. If you have
-         a system with only one CPU, say N. If you have a system with more
-         than one CPU, say Y.  Note that the kernel does not currently
-         support SMP machines with 603/603e/603ev or PPC750 ("G3") processors
-         since they have inadequate hardware support for multiprocessor
-         operation.
-
-         If you say N here, the kernel will run on single and multiprocessor
-         machines, but will use only one CPU of a multiprocessor machine. If
-         you say Y here, the kernel will run on single-processor machines.
-         On a single-processor machine, the kernel will run faster if you say
-         N here.
-
-         If you don't know what to do here, say N.
-
-config NR_CPUS
-       int "Maximum number of CPUs (2-128)"
-       range 2 128
-       depends on SMP
-       default "32" if PPC64
-       default "4"
-
-config NOT_COHERENT_CACHE
-       bool
-       depends on 4xx || 8xx || E200
-       default y
-
-config CONFIG_CHECK_CACHE_COHERENCY
-       bool
-endmenu
-
 source "init/Kconfig"
 
 source "arch/powerpc/platforms/Kconfig"
@@ -677,10 +422,6 @@ config SBUS
 config FSL_SOC
        bool
 
-config FSL_PCIE
-       bool
-       depends on PPC_86xx
-
 # Yes MCA RS/6000s exist but Linux-PPC does not currently support any
 config MCA
        bool
@@ -688,10 +429,10 @@ config MCA
 config PCI
        bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \
                || PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \
-               || MPC7448HPC2 || PPC_PS3 || PPC_HOLLY
-       default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \
+               || PPC_PS3
+       default y if !40x && !CPM2 && !8xx && !PPC_83xx \
                && !PPC_85xx && !PPC_86xx
-       default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
+       default PCI_PERMEDIA if !4xx && !CPM2 && !8xx
        default PCI_QSPAN if !4xx && !CPM2 && 8xx
        select ARCH_SUPPORTS_MSI
        help
index fbafd965dcd298049338d84d9b8fca406ab27825..187a39af3e1cefc25bc69146e317964531e5c6e7 100644 (file)
@@ -148,7 +148,7 @@ all: $(KBUILD_IMAGE)
 
 CPPFLAGS_vmlinux.lds   := -Upowerpc
 
-BOOT_TARGETS = zImage zImage.initrd zImage.dts zImage.dts_initrd uImage
+BOOT_TARGETS = zImage zImage.initrd uImage
 
 PHONY += $(BOOT_TARGETS)
 
index d51377d9024f7807b0ca2dac0b52d5427b890ebd..9f64e840bef628d062bdef0327afa8b9692b7420 100644 (file)
@@ -38,3 +38,48 @@ void ibm44x_fixup_memsize(void)
 
        dt_fixup_memory(0, memsize);
 }
+
+#define SPRN_DBCR0             0x134
+#define   DBCR0_RST_SYSTEM     0x30000000
+
+void ibm44x_dbcr_reset(void)
+{
+       unsigned long tmp;
+
+       asm volatile (
+               "mfspr  %0,%1\n"
+               "oris   %0,%0,%2@h\n"
+               "mtspr  %1,%0"
+               : "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM)
+               );
+
+}
+
+/* Read 4xx EBC bus bridge registers to get mappings of the peripheral
+ * banks into the OPB address space */
+void ibm4xx_fixup_ebc_ranges(const char *ebc)
+{
+       void *devp;
+       u32 bxcr;
+       u32 ranges[EBC_NUM_BANKS*4];
+       u32 *p = ranges;
+       int i;
+
+       for (i = 0; i < EBC_NUM_BANKS; i++) {
+               mtdcr(DCRN_EBC0_CFGADDR, EBC_BXCR(i));
+               bxcr = mfdcr(DCRN_EBC0_CFGDATA);
+
+               if ((bxcr & EBC_BXCR_BU) != EBC_BXCR_BU_OFF) {
+                       *p++ = i;
+                       *p++ = 0;
+                       *p++ = bxcr & EBC_BXCR_BAS;
+                       *p++ = EBC_BXCR_BANK_SIZE(bxcr);
+               }
+       }
+
+       devp = finddevice(ebc);
+       if (! devp)
+               fatal("Couldn't locate EBC node %s\n\r", ebc);
+
+       setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32));
+}
index 7b129ad043e19494af4b727c4c87767e0286988b..577982c9a3cd6f5de9653c8ee4f5e669cc74998d 100644 (file)
@@ -11,6 +11,9 @@
 #define _PPC_BOOT_44X_H_
 
 void ibm44x_fixup_memsize(void);
+void ibm4xx_fixup_ebc_ranges(const char *ebc);
+
+void ibm44x_dbcr_reset(void);
 void ebony_init(void *mac0, void *mac1);
 
 #endif /* _PPC_BOOT_44X_H_ */
index ff2701949ee18616021fee3af3332f7043a25ba7..61a6f34ca5ed944045cfe73016cbb443505448dd 100644 (file)
@@ -43,10 +43,11 @@ $(addprefix $(obj)/,$(zlib) gunzip_util.o main.o): \
 
 src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
                ns16550.c serial.c simple_alloc.c div64.S util.S \
-               gunzip_util.c elf_util.c $(zlib) devtree.c \
-               44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c
+               gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
+               44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c
 src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \
-               cuboot-ebony.c treeboot-ebony.c prpmc2800.c
+               cuboot-ebony.c treeboot-ebony.c prpmc2800.c \
+               ps3-head.S ps3-hvcall.S ps3.c
 src-boot := $(src-wlib) $(src-plat) empty.c
 
 src-boot := $(addprefix $(obj)/, $(src-boot))
@@ -75,11 +76,11 @@ $(addprefix $(obj)/,$(zliblinuxheader)): $(obj)/%: $(srctree)/include/linux/%
 $(obj)/empty.c:
        @touch $@
 
-$(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S
+$(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds: $(obj)/%: $(srctree)/$(src)/%.S
        @cp $< $@
 
 clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \
-               empty.c zImage.coff.lds zImage.lds
+               empty.c zImage zImage.coff.lds zImage.ps3.lds zImage.lds
 
 quiet_cmd_bootcc = BOOTCC  $@
       cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $<
@@ -102,7 +103,7 @@ hostprogs-y := addnote addRamDisk hack-coff mktree
 
 targets                += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a)
 extra-y                := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
-                  $(obj)/zImage.lds $(obj)/zImage.coff.lds
+                  $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds
 
 wrapper                :=$(srctree)/$(src)/wrapper
 wrapperbits    := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \
@@ -132,7 +133,7 @@ image-$(CONFIG_PPC_CELLEB)          += zImage.pseries
 image-$(CONFIG_PPC_CHRP)               += zImage.chrp
 image-$(CONFIG_PPC_EFIKA)              += zImage.chrp
 image-$(CONFIG_PPC_PMAC)               += zImage.pmac
-image-$(CONFIG_PPC_HOLLY)              += zImage.holly-elf
+image-$(CONFIG_PPC_HOLLY)              += zImage.holly
 image-$(CONFIG_PPC_PRPMC2800)          += zImage.prpmc2800
 image-$(CONFIG_PPC_ISERIES)            += zImage.iseries
 image-$(CONFIG_DEFAULT_UIMAGE)         += uImage
@@ -157,55 +158,43 @@ targets   += $(image-y) $(initrd-y)
 
 $(addprefix $(obj)/, $(initrd-y)): $(obj)/ramdisk.image.gz
 
-dts-  := $(patsubst zImage%, zImage.dts%, $(image-n) $(image-))
-dts-y := $(patsubst zImage%, zImage.dts%, $(image-y))
-dts-y := $(filter-out $(image-y), $(dts-y))
-targets        += $(image-y) $(dts-y)
-
-dts_initrd-  := $(patsubst zImage%, zImage.dts_initrd%, $(image-n) $(image-))
-dts_initrd-y := $(patsubst zImage%, zImage.dts_initrd%, $(image-y))
-dts_initrd-y := $(filter-out $(image-y), $(dts_initrd-y))
-targets        += $(image-y) $(dts_initrd-y)
-
-$(addprefix $(obj)/, $(dts_initrd-y)): $(obj)/ramdisk.image.gz
+# If CONFIG_WANT_DEVICE_TREE is set and CONFIG_DEVICE_TREE isn't an
+# empty string, define 'dts' to be path to the dts
+# CONFIG_DEVICE_TREE will have "" around it, make sure to strip them
+ifeq ($(CONFIG_WANT_DEVICE_TREE),y)
+ifneq ($(CONFIG_DEVICE_TREE),"")
+dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\
+       ,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE:"%"=%)
+endif
+endif
 
 # Don't put the ramdisk on the pattern rule; when its missing make will try
 # the pattern rule with less dependencies that also matches (even with the
 # hard dependency listed).
-$(obj)/zImage.dts_initrd.%: vmlinux $(wrapperbits) $(dts) $(obj)/ramdisk.image.gz
+$(obj)/zImage.initrd.%: vmlinux $(wrapperbits) $(dts)
        $(call if_changed,wrap,$*,$(dts),,$(obj)/ramdisk.image.gz)
 
-$(obj)/zImage.dts.%: vmlinux $(wrapperbits) $(dts)
+$(obj)/zImage.%: vmlinux $(wrapperbits) $(dts)
        $(call if_changed,wrap,$*,$(dts))
 
-$(obj)/zImage.initrd.%: vmlinux $(wrapperbits)
-       $(call if_changed,wrap,$*,,,$(obj)/ramdisk.image.gz)
-
-$(obj)/zImage.%: vmlinux $(wrapperbits)
-       $(call if_changed,wrap,$*)
-
-$(obj)/zImage.iseries: vmlinux
+# This cannot be in the root of $(src) as the zImage rule always adds a $(obj)
+# prefix
+$(obj)/vmlinux.strip: vmlinux
        $(STRIP) -s -R .comment $< -o $@
 
-$(obj)/zImage.ps3: vmlinux
+$(obj)/zImage.iseries: vmlinux
        $(STRIP) -s -R .comment $< -o $@
 
-$(obj)/zImage.initrd.ps3: vmlinux
-       @echo "  WARNING zImage.initrd.ps3 not supported (yet)"
-
-$(obj)/zImage.holly-elf: vmlinux $(wrapperbits)
-       $(call if_changed,wrap,holly,$(obj)/dts/holly.dts,,)
+$(obj)/zImage.ps3: vmlinux  $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts
+       $(STRIP) -s -R .comment $< -o vmlinux.strip
+       $(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,)
 
-$(obj)/zImage.initrd.holly-elf: vmlinux $(wrapperbits) $(obj)/ramdisk.image.gz
-       $(call if_changed,wrap,holly,$(obj)/dts/holly.dts,,$(obj)/ramdisk.image.gz)
+$(obj)/zImage.initrd.ps3: vmlinux  $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts $(obj)/ramdisk.image.gz
+       $(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,$(obj)/ramdisk.image.gz)
 
 $(obj)/uImage: vmlinux $(wrapperbits)
        $(call if_changed,wrap,uboot)
 
-# CONFIG_DEVICE_TREE will have "" around it, make sure to strip them
-dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\
-       ,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE:"%"=%)
-
 $(obj)/cuImage.%: vmlinux $(dts) $(wrapperbits)
        $(call if_changed,wrap,cuboot-$*,$(dts))
 
@@ -215,22 +204,22 @@ $(obj)/treeImage.initrd.%: vmlinux $(dts) $(wrapperbits)
 $(obj)/treeImage.%: vmlinux $(dts) $(wrapperbits)
        $(call if_changed,wrap,treeboot-$*,$(dts))
 
+# If there isn't a platform selected then just strip the vmlinux.
+ifeq (,$(image-y))
+image-y := vmlinux.strip
+endif
+
 $(obj)/zImage:         $(addprefix $(obj)/, $(image-y))
        @rm -f $@; ln $< $@
 $(obj)/zImage.initrd:  $(addprefix $(obj)/, $(initrd-y))
        @rm -f $@; ln $< $@
-$(obj)/zImage.dts:     $(addprefix $(obj)/, $(dts-y))
-       @rm -f $@; ln $< $@
-$(obj)/zImage.dts_initrd:      $(addprefix $(obj)/, $(dts_initrd-y))
-       @rm -f $@; ln $< $@
-
 
 install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y))
        sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $<
 
 # anything not in $(targets)
-clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* \
-       treeImage.* zImage.dts zImage.dts_initrd
+clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* \
+       otheros.bld
 
 # clean up files cached by wrapper
 clean-kernel := vmlinux.strip vmlinux.bin
index 9af554eea54be6ea105639e05185b3fe5e221a95..296025d8b295a3cb0f8a1219bbfd765c7afd85f6 100644 (file)
 
 #include "ops.h"
 #include "stdio.h"
+#include "cuboot.h"
 
 #define TARGET_83xx
 #include "ppcboot.h"
 
 static bd_t bd;
-extern char _end[];
 extern char _dtb_start[], _dtb_end[];
 
 static void platform_fixups(void)
@@ -52,16 +52,7 @@ static void platform_fixups(void)
 void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
                    unsigned long r6, unsigned long r7)
 {
-       unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
-       unsigned long avail_ram = end_of_ram - (unsigned long)_end;
-
-       memcpy(&bd, (bd_t *)r3, sizeof(bd));
-       loader_info.initrd_addr = r4;
-       loader_info.initrd_size = r4 ? r5 - r4 : 0;
-       loader_info.cmdline = (char *)r6;
-       loader_info.cmdline_len = r7 - r6;
-
-       simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
+       CUBOOT_INIT();
        ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
        serial_console_init();
        platform_ops.fixups = platform_fixups;
index e2560317f2784f0d904815a4e4db05b87d12ece5..10f0f697c9359e9c33787a1728396f8bd4e73255 100644 (file)
 
 #include "ops.h"
 #include "stdio.h"
+#include "cuboot.h"
 
 #define TARGET_85xx
 #include "ppcboot.h"
 
 static bd_t bd;
-extern char _end[];
 extern char _dtb_start[], _dtb_end[];
 
 static void platform_fixups(void)
@@ -53,16 +53,7 @@ static void platform_fixups(void)
 void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
                    unsigned long r6, unsigned long r7)
 {
-       unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
-       unsigned long avail_ram = end_of_ram - (unsigned long)_end;
-
-       memcpy(&bd, (bd_t *)r3, sizeof(bd));
-       loader_info.initrd_addr = r4;
-       loader_info.initrd_size = r4 ? r5 - r4 : 0;
-       loader_info.cmdline = (char *)r6;
-       loader_info.cmdline_len = r7 - r6;
-
-       simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
+       CUBOOT_INIT();
        ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
        serial_console_init();
        platform_ops.fixups = platform_fixups;
index 4464c5f67acb7e3747acf7ef790a4a0b0e360ef6..c5f37ce172ea92654a7509c72680de4bf55c26ef 100644 (file)
 #include "ops.h"
 #include "stdio.h"
 #include "44x.h"
+#include "cuboot.h"
 
 #define TARGET_44x
 #include "ppcboot.h"
 
 static bd_t bd;
-extern char _end[];
-
-BSS_STACK(4096);
 
 void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
                    unsigned long r6, unsigned long r7)
 {
-       unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
-       unsigned long avail_ram = end_of_ram - (unsigned long)_end;
-
-       memcpy(&bd, (bd_t *)r3, sizeof(bd));
-       loader_info.initrd_addr = r4;
-       loader_info.initrd_size = r4 ? r5 : 0;
-       loader_info.cmdline = (char *)r6;
-       loader_info.cmdline_len = r7 - r6;
-
-       simple_alloc_init(_end, avail_ram, 32, 64);
-
+       CUBOOT_INIT();
        ebony_init(&bd.bi_enetaddr, &bd.bi_enet1addr);
 }
diff --git a/arch/powerpc/boot/cuboot.c b/arch/powerpc/boot/cuboot.c
new file mode 100644 (file)
index 0000000..6579546
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Compatibility for old (not device tree aware) U-Boot versions
+ *
+ * Author: Scott Wood <scottwood@freescale.com>
+ * Consolidated using macros by David Gibson <david@gibson.dropbear.id.au>
+ *
+ * Copyright 2007 David Gibson, IBM Corporation.
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "ops.h"
+#include "stdio.h"
+
+#include "ppcboot.h"
+
+extern char _end[];
+extern char _dtb_start[], _dtb_end[];
+
+void cuboot_init(unsigned long r4, unsigned long r5,
+                unsigned long r6, unsigned long r7,
+                unsigned long end_of_ram)
+{
+       unsigned long avail_ram = end_of_ram - (unsigned long)_end;
+
+       loader_info.initrd_addr = r4;
+       loader_info.initrd_size = r4 ? r5 - r4 : 0;
+       loader_info.cmdline = (char *)r6;
+       loader_info.cmdline_len = r7 - r6;
+
+       simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
+}
diff --git a/arch/powerpc/boot/cuboot.h b/arch/powerpc/boot/cuboot.h
new file mode 100644 (file)
index 0000000..cd2aa7f
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _PPC_BOOT_CUBOOT_H_
+#define _PPC_BOOT_CUBOOT_H_
+
+void cuboot_init(unsigned long r4, unsigned long r5,
+                unsigned long r6, unsigned long r7,
+                unsigned long end_of_ram);
+
+#define CUBOOT_INIT() \
+       do { \
+               memcpy(&bd, (bd_t *)r3, sizeof(bd)); \
+               cuboot_init(r4, r5, r6, r7, bd.bi_memstart + bd.bi_memsize); \
+       } while (0)
+
+#endif /* _PPC_BOOT_CUBOOT_H_ */
index 877bc97b1e975752d8513aa0d54bd80dff3b7baf..14b44aa96feaabb42de57f51f87f3d64501488e4 100644 (file)
@@ -26,6 +26,43 @@ static const unsigned long sdram_bxcr[] = { SDRAM0_B0CR, SDRAM0_B1CR, SDRAM0_B2C
 #define                        SDRAM_CONFIG_BANK_SIZE(reg)     \
        (0x00400000 << ((reg & SDRAM_CONFIG_SIZE_MASK) >> 17))
 
+/* 440GP External Bus Controller (EBC) */
+#define DCRN_EBC0_CFGADDR                              0x012
+#define DCRN_EBC0_CFGDATA                              0x013
+#define   EBC_NUM_BANKS                                          8
+#define   EBC_B0CR                                       0x00
+#define   EBC_B1CR                                       0x01
+#define   EBC_B2CR                                       0x02
+#define   EBC_B3CR                                       0x03
+#define   EBC_B4CR                                       0x04
+#define   EBC_B5CR                                       0x05
+#define   EBC_B6CR                                       0x06
+#define   EBC_B7CR                                       0x07
+#define   EBC_BXCR(n)                                    (n)
+#define            EBC_BXCR_BAS                                    0xfff00000
+#define            EBC_BXCR_BS                                     0x000e0000
+#define            EBC_BXCR_BANK_SIZE(reg) \
+       (0x100000 << (((reg) & EBC_BXCR_BS) >> 17))
+#define            EBC_BXCR_BU                                     0x00018000
+#define              EBC_BXCR_BU_OFF                                 0x00000000
+#define              EBC_BXCR_BU_RO                                  0x00008000
+#define              EBC_BXCR_BU_WO                                  0x00010000
+#define              EBC_BXCR_BU_RW                                  0x00018000
+#define            EBC_BXCR_BW                                     0x00006000
+#define   EBC_B0AP                                       0x10
+#define   EBC_B1AP                                       0x11
+#define   EBC_B2AP                                       0x12
+#define   EBC_B3AP                                       0x13
+#define   EBC_B4AP                                       0x14
+#define   EBC_B5AP                                       0x15
+#define   EBC_B6AP                                       0x16
+#define   EBC_B7AP                                       0x17
+#define   EBC_BXAP(n)                                    (0x10+(n))
+#define   EBC_BEAR                                       0x20
+#define   EBC_BESR                                       0x21
+#define   EBC_CFG                                        0x23
+#define   EBC_CID                                        0x24
+
 /* 440GP Clock, PM, chip control */
 #define DCRN_CPC0_SR                                   0x0b0
 #define DCRN_CPC0_ER                                   0x0b1
index 0ec02f4726b592f545dd387a13c152f71607e7cf..c5f99613fc7bab5a8b2358717681a4a48bb49480 100644 (file)
@@ -31,8 +31,8 @@
                        reg = <0>;
                        clock-frequency = <0>; // Filled in by zImage
                        timebase-frequency = <0>; // Filled in by zImage
-                       i-cache-line-size = <32>;
-                       d-cache-line-size = <32>;
+                       i-cache-line-size = <20>;
+                       d-cache-line-size = <20>;
                        i-cache-size = <8000>; /* 32 kB */
                        d-cache-size = <8000>; /* 32 kB */
                        dcr-controller;
                                #address-cells = <2>;
                                #size-cells = <1>;
                                clock-frequency = <0>; // Filled in by zImage
-                               ranges = <0 00000000 fff00000 100000
-                                         1 00000000 48000000 100000
-                                         2 00000000 ff800000 400000
-                                         3 00000000 48200000 100000
-                                         7 00000000 48300000 100000>;
+                               // ranges property is supplied by zImage
+                               // based on firmware's configuration of the
+                               // EBC bridge
                                interrupts = <5 4>;
                                interrupt-parent = <&UIC1>;
 
index 254499b107f48b07ecdf9d8ff7c7edc9e7fb2be5..80a4fab8ee3780f5a52bd5cadd720f67f5f3a8ba 100644 (file)
@@ -46,7 +46,7 @@
 
        tsi109@c0000000 {
                device_type = "tsi-bridge";
-               compatible = "tsi-bridge";
+               compatible = "tsi109-bridge", "tsi108-bridge";
                #address-cells = <1>;
                #size-cells = <1>;
                ranges = <00000000 c0000000 00010000>;
 
                i2c@7000 {
                        device_type = "i2c";
-                       compatible  = "tsi-i2c";
-                       interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+                       compatible  = "tsi109-i2c", "tsi108-i2c";
+                       interrupt-parent = <&MPIC>;
                        interrupts = <e 2>;
                        reg = <7000 400>;
                };
 
-               mdio@6000 {
+               MDIO: mdio@6000 {
                        device_type = "mdio";
-                       compatible = "tsi-ethernet";
+                       compatible = "tsi109-mdio", "tsi108-mdio";
+                       reg = <6000 50>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
 
-                       PHY1: ethernet-phy@6000 {
-                               device_type = "ethernet-phy";
-                               compatible = "bcm54xx";
-                               reg = <6000 50>;
-                               phy-id = <1>;
+                       PHY1: ethernet-phy@1 {
+                               compatible = "bcm5461a";
+                               reg = <1>;
+                               txc-rxc-delay-disable;
                        };
 
-                       PHY2: ethernet-phy@6400 {
-                               device_type = "ethernet-phy";
-                               compatible = "bcm54xx";
-                               reg = <6000 50>;
-                               phy-id = <2>;
+                       PHY2: ethernet-phy@2 {
+                               compatible = "bcm5461a";
+                               reg = <2>;
+                               txc-rxc-delay-disable;
                        };
                };
 
                ethernet@6200 {
                        device_type = "network";
-                       compatible = "tsi-ethernet";
+                       compatible = "tsi109-ethernet", "tsi108-ethernet";
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <6000 200>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+                       interrupt-parent = <&MPIC>;
                        interrupts = <10 2>;
+                       mdio-handle = <&MDIO>;
                        phy-handle = <&PHY1>;
                };
 
                ethernet@6600 {
                        device_type = "network";
-                       compatible = "tsi-ethernet";
+                       compatible = "tsi109-ethernet", "tsi108-ethernet";
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <6400 200>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+                       interrupt-parent = <&MPIC>;
                        interrupts = <11 2>;
+                       mdio-handle = <&MDIO>;
                        phy-handle = <&PHY2>;
                };
 
                        virtual-reg = <c0007808>;
                        clock-frequency = <3F9C6000>;
                        current-speed = <1c200>;
-                       interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+                       interrupt-parent = <&MPIC>;
                        interrupts = <c 2>;
                };
 
                        virtual-reg = <c0007c08>;
                        clock-frequency = <3F9C6000>;
                        current-speed = <1c200>;
-                       interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+                       interrupt-parent = <&MPIC>;
                        interrupts = <d 2>;
                };
 
 
                pci@1000 {
                        device_type = "pci";
-                       compatible = "tsi109";
+                       compatible = "tsi109-pci", "tsi108-pci";
                        #interrupt-cells = <1>;
                        #size-cells = <2>;
                        #address-cells = <3>;
                        ranges = <02000000 0 40000000 40000000 0 10000000
                                  01000000 0 00000000 7e000000 0 00010000>;
                        clock-frequency = <7f28154>;
-                       interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+                       interrupt-parent = <&MPIC>;
                        interrupts = <17 2>;
                        interrupt-map-mask = <f800 0 0 7>;
                        /*----------------------------------------------------+
                                #address-cells = <0>;
                                #interrupt-cells = <2>;
                                interrupts = <17 2>;
-                               interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
+                               interrupt-parent = <&MPIC>;
                        };
                };
        };
 
        chosen {
                linux,stdout-path = "/tsi109@c0000000/serial@7808";
-               bootargs = "console=ttyS0,115200";
        };
 };
index 765c306ecf8034e169e7d4f21e5372e31daa7905..0e3d314a7158116351d5dccd4d6395eefd47e22b 100644 (file)
@@ -45,7 +45,7 @@
                #address-cells = <1>;
                #size-cells = <1>;
                #interrupt-cells = <2>;
-               device_type = "tsi-bridge";
+               device_type = "tsi108-bridge";
                ranges = <00000000 c0000000 00010000>;
                reg = <c0000000 00010000>;
                bus-frequency = <0>;
                        interrupts = <E 0>;
                        reg = <7000 400>;
                        device_type = "i2c";
-                       compatible  = "tsi-i2c";
+                       compatible  = "tsi108-i2c";
                };
 
-               mdio@6000 {
+               MDIO: mdio@6000 {
                        device_type = "mdio";
-                       compatible = "tsi-ethernet";
+                       compatible = "tsi108-mdio";
+                       reg = <6000 50>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
 
-                       phy8: ethernet-phy@6000 {
+                       phy8: ethernet-phy@8 {
                                interrupt-parent = <&mpic>;
                                interrupts = <2 1>;
-                               reg = <6000 50>;
-                               phy-id = <8>;
-                               device_type = "ethernet-phy";
+                               reg = <8>;
                        };
 
-                       phy9: ethernet-phy@6400 {
+                       phy9: ethernet-phy@9 {
                                interrupt-parent = <&mpic>;
                                interrupts = <2 1>;
-                               reg = <6000 50>;
-                               phy-id = <9>;
-                               device_type = "ethernet-phy";
+                               reg = <9>;
                        };
 
                };
                ethernet@6200 {
                        #size-cells = <0>;
                        device_type = "network";
-                       model = "TSI-ETH";
-                       compatible = "tsi-ethernet";
+                       compatible = "tsi108-ethernet";
                        reg = <6000 200>;
                        address = [ 00 06 D2 00 00 01 ];
                        interrupts = <10 2>;
                        interrupt-parent = <&mpic>;
+                       mdio-handle = <&MDIO>;
                        phy-handle = <&phy8>;
                };
 
                        #address-cells = <1>;
                        #size-cells = <0>;
                        device_type = "network";
-                       model = "TSI-ETH";
-                       compatible = "tsi-ethernet";
+                       compatible = "tsi108-ethernet";
                        reg = <6400 200>;
                        address = [ 00 06 D2 00 00 02 ];
                        interrupts = <11 2>;
                        interrupt-parent = <&mpic>;
+                       mdio-handle = <&MDIO>;
                        phy-handle = <&phy9>;
                };
 
                                big-endian;
                };
                pci@1000 {
-                       compatible = "tsi10x";
+                       compatible = "tsi108-pci";
                        device_type = "pci";
                        #interrupt-cells = <1>;
                        #size-cells = <2>;
index 423eedcf634f6be2e07ab64c108dceb935678803..1934b800278e06d42d47d21ce94fd2490483f2f6 100644 (file)
        compatible = "MPC8260ADS";
        #address-cells = <1>;
        #size-cells = <1>;
-       linux,phandle = <100>;
 
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
-               linux,phandle = <200>;
 
                PowerPC,8272@0 {
                        device_type = "cpu";
                        bus-frequency = <0>;
                        clock-frequency = <0>;
                        32-bit;
-                       linux,phandle = <201>;
                };
        };
 
-       interrupt-controller@f8200000 {
-               linux,phandle = <f8200000>;
+               pci_pic: interrupt-controller@f8200000 {
                #address-cells = <0>;
                #interrupt-cells = <2>;
                interrupt-controller;
        };
        memory {
                device_type = "memory";
-               linux,phandle = <300>;
                reg = <00000000 4000000 f4500000 00000020>;
        };
 
        chosen {
                name = "chosen";
                linux,platform = <0>;
-               interrupt-controller = <10c00>;
-               linux,phandle = <400>;
+               interrupt-controller = <&Cpm_pic>;
        };
 
        soc8272@f0000000 {
                        device_type = "mdio";
                        compatible = "fs_enet";
                        reg = <0 0>;
-                       linux,phandle = <24520>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       ethernet-phy@0 {
-                               linux,phandle = <2452000>;
-                               interrupt-parent = <10c00>;
+                       phy0:ethernet-phy@0 {
+                               interrupt-parent = <&Cpm_pic>;
                                interrupts = <17 4>;
                                reg = <0>;
                                bitbang = [ 12 12 13 02 02 01 ];
                                device_type = "ethernet-phy";
                        };
-                       ethernet-phy@1 {
-                               linux,phandle = <2452001>;
-                               interrupt-parent = <10c00>;
+                       phy1:ethernet-phy@1 {
+                               interrupt-parent = <&Cpm_pic>;
                                interrupts = <17 4>;
                                bitbang = [ 12 12 13 02 02 01 ];
                                reg = <3>;
                        reg = <11300 20 8400 100 11380 30>;
                        mac-address = [ 00 11 2F 99 43 54 ];
                        interrupts = <20 2>;
-                       interrupt-parent = <10c00>;
-                       phy-handle = <2452000>;
+                       interrupt-parent = <&Cpm_pic>;
+                       phy-handle = <&Phy0>;
                        rx-clock = <13>;
                        tx-clock = <12>;
                };
                        reg = <11320 20 8500 100 113b0 30>;
                        mac-address = [ 00 11 2F 99 44 54 ];
                        interrupts = <21 2>;
-                       interrupt-parent = <10c00>;
-                       phy-handle = <2452001>;
+                       interrupt-parent = <&Cpm_pic>;
+                       phy-handle = <&Phy1>;
                        rx-clock = <17>;
                        tx-clock = <18>;
                };
 
                cpm@f0000000 {
-                       linux,phandle = <f0000000>;
                        #address-cells = <1>;
                        #size-cells = <1>;
                        #interrupt-cells = <2>;
                                reg = <11a00 20 8000 100>;
                                current-speed = <1c200>;
                                interrupts = <28 2>;
-                               interrupt-parent = <10c00>;
+                               interrupt-parent = <&Cpm_pic>;
                                clock-setup = <0 00ffffff>;
                                rx-clock = <1>;
                                tx-clock = <1>;
                                reg = <11a60 20 8300 100>;
                                current-speed = <1c200>;
                                interrupts = <2b 2>;
-                               interrupt-parent = <10c00>;
+                               interrupt-parent = <&Cpm_pic>;
                                clock-setup = <1b ffffff00>;
                                rx-clock = <4>;
                                tx-clock = <4>;
                        };
 
                };
-               interrupt-controller@10c00 {
-                       linux,phandle = <10c00>;
+                       cpm_pic:interrupt-controller@10c00 {
                        #address-cells = <0>;
                        #interrupt-cells = <2>;
                        interrupt-controller;
                       compatible = "CPM2";
                };
                pci@0500 {
-                       linux,phandle = <0500>;
                        #interrupt-cells = <1>;
                        #size-cells = <2>;
                        #address-cells = <3>;
                                         c000 0 0 2 f8200000 43 8
                                         c000 0 0 3 f8200000 40 8
                                         c000 0 0 4 f8200000 41 8>;
-                       interrupt-parent = <10c00>;
+                       interrupt-parent = <&Cpm_pic>;
                        interrupts = <14 8>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 80000000 80000000 0 40000000
                        compatible = "talitos";
                        reg = <30000 10000>;
                        interrupts = <b 2>;
-                       interrupt-parent = <10c00>;
+                       interrupt-parent = <&Cpm_pic>;
                        num-channels = <4>;
                        channel-fifo-len = <18>;
                        exec-units-mask = <0000007e>;
index 112dd5198fe2d4d4406fb5e29cf6b665eda6b1d1..4fc0c4d34aa83361a9375b2334b8e891e8952b53 100644 (file)
                        reg = <2200 200>;
                        interrupts = <22>;
                        interrupt-parent = < &qeic >;
-                       mac-address = [ 00 04 9f 00 23 23 ];
+                       /*
+                        * mac-address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
+                       mac-address = [ 00 00 00 00 00 00 ];
+                       local-mac-address = [ 00 00 00 00 00 00 ];
                        rx-clock = <19>;
                        tx-clock = <1a>;
                        phy-handle = < &phy3 >;
                        reg = <3000 200>;
                        interrupts = <23>;
                        interrupt-parent = < &qeic >;
-                       mac-address = [ 00 11 22 33 44 55 ];
+                       /*
+                        * mac-address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
+                       mac-address = [ 00 00 00 00 00 00 ];
+                       local-mac-address = [ 00 00 00 00 00 00 ];
                        rx-clock = <17>;
                        tx-clock = <18>;
                        phy-handle = < &phy4 >;
index be4c35784e490c8830e85a8900a831e5b121f7fc..447c03ffabbc2b6422abeca4c33d6c2b4bacefef 100644 (file)
                        reg = <3000 200>;
                        interrupts = <21>;
                        interrupt-parent = <&qeic>;
-                       mac-address = [ 00 04 9f ef 03 02 ];
+                       /*
+                        * mac-address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
+                       mac-address = [ 00 00 00 00 00 00 ];
+                       local-mac-address = [ 00 00 00 00 00 00 ];
                        rx-clock = <20>;
                        tx-clock = <13>;
                        phy-handle = <&phy00>;
                        reg = <2200 200>;
                        interrupts = <22>;
                        interrupt-parent = <&qeic>;
-                       mac-address = [ 00 04 9f ef 03 01 ];
+                       /*
+                        * mac-address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
+                       mac-address = [ 00 00 00 00 00 00 ];
+                       local-mac-address = [ 00 00 00 00 00 00 ];
                        rx-clock = <19>;
                        tx-clock = <1a>;
                        phy-handle = <&phy04>;
index db0d003032759d5f4df388377dc1d57bf682f45f..ae9bca575453eb4c672011533554750b2704dedf 100644 (file)
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <24000 1000>;
+                       /*
+                        * address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
                        address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <20 8 21 8 22 8>;
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <25000 1000>;
+                       /*
+                        * address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
                        address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <23 8 24 8 25 8>;
index df773fafe9d179f886e68628fee8c826614e3887..310e877826b4edf8024dc9552e7fe5b73812d5f2 100644 (file)
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <24000 1000>;
+                       /*
+                        * address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
                        address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <20 8 21 8 22 8>;
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <25000 1000>;
+                       /*
+                        * address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
                        address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <23 8 24 8 25 8>;
index 38c8594df3a4fd372e5d20e89792859e766f7a44..1e914f31dd92c918e453bf926aa1fc7dc2002665 100644 (file)
                        reg = <2000 200>;
                        interrupts = <20>;
                        interrupt-parent = < &qeic >;
-                       mac-address = [ 00 04 9f 00 23 23 ];
+                       /*
+                        * mac-address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
+                       mac-address = [ 00 00 00 00 00 00 ];
+                       local-mac-address = [ 00 00 00 00 00 00 ];
                        rx-clock = <0>;
                        tx-clock = <19>;
                        phy-handle = < &phy0 >;
                        reg = <3000 200>;
                        interrupts = <21>;
                        interrupt-parent = < &qeic >;
-                       mac-address = [ 00 11 22 33 44 55 ];
+                       /*
+                        * mac-address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
+                       mac-address = [ 00 00 00 00 00 00 ];
+                       local-mac-address = [ 00 00 00 00 00 00 ];
                        rx-clock = <0>;
                        tx-clock = <14>;
                        phy-handle = < &phy1 >;
index d91e81c009f51863b23927850311783ed438775b..364a969f5c2fb6282824fb2a262a7b5b9e545c11 100644 (file)
@@ -52,7 +52,7 @@
                        compatible = "fsl,8540-memory-controller";
                        reg = <2000 1000>;
                        interrupt-parent = <&mpic>;
-                       interrupts = <2 2>;
+                       interrupts = <12 2>;
                };
 
                l2-cache-controller@20000 {
                        cache-line-size = <20>; // 32 bytes
                        cache-size = <40000>;   // L2, 256K
                        interrupt-parent = <&mpic>;
-                       interrupts = <0 2>;
+                       interrupts = <10 2>;
                };
 
                i2c@3000 {
                        device_type = "i2c";
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
-                       interrupts = <1b 2>;
+                       interrupts = <2b 2>;
                        interrupt-parent = <&mpic>;
                        dfsrr;
                };
                        reg = <24520 20>;
                        phy0: ethernet-phy@0 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <35 1>;
+                               interrupts = <5 1>;
                                reg = <0>;
                                device_type = "ethernet-phy";
                        };
                        phy1: ethernet-phy@1 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <35 1>;
+                               interrupts = <5 1>;
                                reg = <1>;
                                device_type = "ethernet-phy";
                        };
                        phy3: ethernet-phy@3 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <37 1>;
+                               interrupts = <7 1>;
                                reg = <3>;
                                device_type = "ethernet-phy";
                        };
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <24000 1000>;
-                       address = [ 00 E0 0C 00 73 00 ];
-                       local-mac-address = [ 00 E0 0C 00 73 00 ];
-                       interrupts = <d 2 e 2 12 2>;
+                       /*
+                        * address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
+                       address = [ 00 00 00 00 00 00 ];
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <1d 2 1e 2 22 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy0>;
                };
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <25000 1000>;
-                       address = [ 00 E0 0C 00 73 01 ];
-                       local-mac-address = [ 00 E0 0C 00 73 01 ];
-                       interrupts = <13 2 14 2 18 2>;
+                       /*
+                        * address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
+                       address = [ 00 00 00 00 00 00 ];
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <23 2 24 2 28 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy1>;
                };
                        model = "FEC";
                        compatible = "gianfar";
                        reg = <26000 1000>;
-                       address = [ 00 E0 0C 00 73 02 ];
-                       local-mac-address = [ 00 E0 0C 00 73 02 ];
-                       interrupts = <19 2>;
+                       /*
+                        * address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
+                       address = [ 00 00 00 00 00 00 ];
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <29 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy3>;
                };
                        compatible = "ns16550";
                        reg = <4500 100>;       // reg base, size
                        clock-frequency = <0>;  // should we fill in in uboot?
-                       interrupts = <1a 2>;
+                       interrupts = <2a 2>;
                        interrupt-parent = <&mpic>;
                };
 
                        compatible = "ns16550";
                        reg = <4600 100>;       // reg base, size
                        clock-frequency = <0>;  // should we fill in in uboot?
-                       interrupts = <1a 2>;
+                       interrupts = <2a 2>;
                        interrupt-parent = <&mpic>;
                };
                pci@8000 {
                        interrupt-map = <
 
                                /* IDSEL 0x02 */
-                               1000 0 0 1 &mpic 31 1
-                               1000 0 0 2 &mpic 32 1
-                               1000 0 0 3 &mpic 33 1
-                               1000 0 0 4 &mpic 34 1
+                               1000 0 0 1 &mpic 1 1
+                               1000 0 0 2 &mpic 2 1
+                               1000 0 0 3 &mpic 3 1
+                               1000 0 0 4 &mpic 4 1
 
                                /* IDSEL 0x03 */
-                               1800 0 0 1 &mpic 34 1
-                               1800 0 0 2 &mpic 31 1
-                               1800 0 0 3 &mpic 32 1
-                               1800 0 0 4 &mpic 33 1
+                               1800 0 0 1 &mpic 4 1
+                               1800 0 0 2 &mpic 1 1
+                               1800 0 0 3 &mpic 2 1
+                               1800 0 0 4 &mpic 3 1
 
                                /* IDSEL 0x04 */
-                               2000 0 0 1 &mpic 33 1
-                               2000 0 0 2 &mpic 34 1
-                               2000 0 0 3 &mpic 31 1
-                               2000 0 0 4 &mpic 32 1
+                               2000 0 0 1 &mpic 3 1
+                               2000 0 0 2 &mpic 4 1
+                               2000 0 0 3 &mpic 1 1
+                               2000 0 0 4 &mpic 2 1
 
                                /* IDSEL 0x05 */
-                               2800 0 0 1 &mpic 32 1
-                               2800 0 0 2 &mpic 33 1
-                               2800 0 0 3 &mpic 34 1
-                               2800 0 0 4 &mpic 31 1
+                               2800 0 0 1 &mpic 2 1
+                               2800 0 0 2 &mpic 3 1
+                               2800 0 0 3 &mpic 4 1
+                               2800 0 0 4 &mpic 1 1
 
                                /* IDSEL 0x0c */
-                               6000 0 0 1 &mpic 31 1
-                               6000 0 0 2 &mpic 32 1
-                               6000 0 0 3 &mpic 33 1
-                               6000 0 0 4 &mpic 34 1
+                               6000 0 0 1 &mpic 1 1
+                               6000 0 0 2 &mpic 2 1
+                               6000 0 0 3 &mpic 3 1
+                               6000 0 0 4 &mpic 4 1
 
                                /* IDSEL 0x0d */
-                               6800 0 0 1 &mpic 34 1
-                               6800 0 0 2 &mpic 31 1
-                               6800 0 0 3 &mpic 32 1
-                               6800 0 0 4 &mpic 33 1
+                               6800 0 0 1 &mpic 4 1
+                               6800 0 0 2 &mpic 1 1
+                               6800 0 0 3 &mpic 2 1
+                               6800 0 0 4 &mpic 3 1
 
                                /* IDSEL 0x0e */
-                               7000 0 0 1 &mpic 33 1
-                               7000 0 0 2 &mpic 34 1
-                               7000 0 0 3 &mpic 31 1
-                               7000 0 0 4 &mpic 32 1
+                               7000 0 0 1 &mpic 3 1
+                               7000 0 0 2 &mpic 4 1
+                               7000 0 0 3 &mpic 1 1
+                               7000 0 0 4 &mpic 2 1
 
                                /* IDSEL 0x0f */
-                               7800 0 0 1 &mpic 32 1
-                               7800 0 0 2 &mpic 33 1
-                               7800 0 0 3 &mpic 34 1
-                               7800 0 0 4 &mpic 31 1
+                               7800 0 0 1 &mpic 2 1
+                               7800 0 0 2 &mpic 3 1
+                               7800 0 0 3 &mpic 4 1
+                               7800 0 0 4 &mpic 1 1
 
                                /* IDSEL 0x12 */
-                               9000 0 0 1 &mpic 31 1
-                               9000 0 0 2 &mpic 32 1
-                               9000 0 0 3 &mpic 33 1
-                               9000 0 0 4 &mpic 34 1
+                               9000 0 0 1 &mpic 1 1
+                               9000 0 0 2 &mpic 2 1
+                               9000 0 0 3 &mpic 3 1
+                               9000 0 0 4 &mpic 4 1
 
                                /* IDSEL 0x13 */
-                               9800 0 0 1 &mpic 34 1
-                               9800 0 0 2 &mpic 31 1
-                               9800 0 0 3 &mpic 32 1
-                               9800 0 0 4 &mpic 33 1
+                               9800 0 0 1 &mpic 4 1
+                               9800 0 0 2 &mpic 1 1
+                               9800 0 0 3 &mpic 2 1
+                               9800 0 0 4 &mpic 3 1
 
                                /* IDSEL 0x14 */
-                               a000 0 0 1 &mpic 33 1
-                               a000 0 0 2 &mpic 34 1
-                               a000 0 0 3 &mpic 31 1
-                               a000 0 0 4 &mpic 32 1
+                               a000 0 0 1 &mpic 3 1
+                               a000 0 0 2 &mpic 4 1
+                               a000 0 0 3 &mpic 1 1
+                               a000 0 0 4 &mpic 2 1
 
                                /* IDSEL 0x15 */
-                               a800 0 0 1 &mpic 32 1
-                               a800 0 0 2 &mpic 33 1
-                               a800 0 0 3 &mpic 34 1
-                               a800 0 0 4 &mpic 31 1>;
+                               a800 0 0 1 &mpic 2 1
+                               a800 0 0 2 &mpic 3 1
+                               a800 0 0 3 &mpic 4 1
+                               a800 0 0 4 &mpic 1 1>;
                        interrupt-parent = <&mpic>;
-                       interrupts = <08 2>;
+                       interrupts = <18 2>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 80000000 80000000 0 20000000
                                  01000000 0 00000000 e2000000 0 00100000>;
index 4f2c3af2e052c957dd94bd0365909b8aa663cdc6..070206fffe88c0f7bc9b637e5439c0a026e4561d 100644 (file)
@@ -52,7 +52,7 @@
                        compatible = "fsl,8541-memory-controller";
                        reg = <2000 1000>;
                        interrupt-parent = <&mpic>;
-                       interrupts = <2 2>;
+                       interrupts = <12 2>;
                };
 
                l2-cache-controller@20000 {
                        cache-line-size = <20>; // 32 bytes
                        cache-size = <40000>;   // L2, 256K
                        interrupt-parent = <&mpic>;
-                       interrupts = <0 2>;
+                       interrupts = <10 2>;
                };
 
                i2c@3000 {
                        device_type = "i2c";
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
-                       interrupts = <1b 2>;
+                       interrupts = <2b 2>;
                        interrupt-parent = <&mpic>;
                        dfsrr;
                };
                        reg = <24520 20>;
                        phy0: ethernet-phy@0 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <35 0>;
+                               interrupts = <5 1>;
                                reg = <0>;
                                device_type = "ethernet-phy";
                        };
                        phy1: ethernet-phy@1 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <35 0>;
+                               interrupts = <5 1>;
                                reg = <1>;
                                device_type = "ethernet-phy";
                        };
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <24000 1000>;
-                       local-mac-address = [ 00 E0 0C 00 73 00 ];
-                       interrupts = <d 2 e 2 12 2>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <1d 2 1e 2 22 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy0>;
                };
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <25000 1000>;
-                       local-mac-address = [ 00 E0 0C 00 73 01 ];
-                       interrupts = <13 2 14 2 18 2>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <23 2 24 2 28 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy1>;
                };
                        compatible = "ns16550";
                        reg = <4500 100>;       // reg base, size
                        clock-frequency = <0>;  // should we fill in in uboot?
-                       interrupts = <1a 2>;
+                       interrupts = <2a 2>;
                        interrupt-parent = <&mpic>;
                };
 
                        compatible = "ns16550";
                        reg = <4600 100>;       // reg base, size
                        clock-frequency = <0>;  // should we fill in in uboot?
-                       interrupts = <1a 2>;
+                       interrupts = <2a 2>;
                        interrupt-parent = <&mpic>;
                };
 
                        interrupt-map = <
 
                                /* IDSEL 0x10 */
-                               08000 0 0 1 &mpic 30 1
-                               08000 0 0 2 &mpic 31 1
-                               08000 0 0 3 &mpic 32 1
-                               08000 0 0 4 &mpic 33 1
+                               08000 0 0 1 &mpic 0 1
+                               08000 0 0 2 &mpic 1 1
+                               08000 0 0 3 &mpic 2 1
+                               08000 0 0 4 &mpic 3 1
 
                                /* IDSEL 0x11 */
-                               08800 0 0 1 &mpic 30 1
-                               08800 0 0 2 &mpic 31 1
-                               08800 0 0 3 &mpic 32 1
-                               08800 0 0 4 &mpic 33 1
+                               08800 0 0 1 &mpic 0 1
+                               08800 0 0 2 &mpic 1 1
+                               08800 0 0 3 &mpic 2 1
+                               08800 0 0 4 &mpic 3 1
 
                                /* IDSEL 0x12 (Slot 1) */
-                               09000 0 0 1 &mpic 30 1
-                               09000 0 0 2 &mpic 31 1
-                               09000 0 0 3 &mpic 32 1
-                               09000 0 0 4 &mpic 33 1
+                               09000 0 0 1 &mpic 0 1
+                               09000 0 0 2 &mpic 1 1
+                               09000 0 0 3 &mpic 2 1
+                               09000 0 0 4 &mpic 3 1
 
                                /* IDSEL 0x13 (Slot 2) */
-                               09800 0 0 1 &mpic 31 1
-                               09800 0 0 2 &mpic 32 1
-                               09800 0 0 3 &mpic 33 1
-                               09800 0 0 4 &mpic 30 1
+                               09800 0 0 1 &mpic 1 1
+                               09800 0 0 2 &mpic 2 1
+                               09800 0 0 3 &mpic 3 1
+                               09800 0 0 4 &mpic 0 1
 
                                /* IDSEL 0x14 (Slot 3) */
-                               0a000 0 0 1 &mpic 32 1
-                               0a000 0 0 2 &mpic 33 1
-                               0a000 0 0 3 &mpic 30 1
-                               0a000 0 0 4 &mpic 31 1
+                               0a000 0 0 1 &mpic 2 1
+                               0a000 0 0 2 &mpic 3 1
+                               0a000 0 0 3 &mpic 0 1
+                               0a000 0 0 4 &mpic 1 1
 
                                /* IDSEL 0x15 (Slot 4) */
-                               0a800 0 0 1 &mpic 33 1
-                               0a800 0 0 2 &mpic 30 1
-                               0a800 0 0 3 &mpic 31 1
-                               0a800 0 0 4 &mpic 32 1
+                               0a800 0 0 1 &mpic 3 1
+                               0a800 0 0 2 &mpic 0 1
+                               0a800 0 0 3 &mpic 1 1
+                               0a800 0 0 4 &mpic 2 1
 
                                /* Bus 1 (Tundra Bridge) */
                                /* IDSEL 0x12 (ISA bridge) */
-                               19000 0 0 1 &mpic 30 1
-                               19000 0 0 2 &mpic 31 1
-                               19000 0 0 3 &mpic 32 1
-                               19000 0 0 4 &mpic 33 1>;
+                               19000 0 0 1 &mpic 0 1
+                               19000 0 0 2 &mpic 1 1
+                               19000 0 0 3 &mpic 2 1
+                               19000 0 0 4 &mpic 3 1>;
                        interrupt-parent = <&mpic>;
-                       interrupts = <08 2>;
+                       interrupts = <18 2>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 80000000 80000000 0 20000000
                                  01000000 0 00000000 e2000000 0 00100000>;
                        interrupt-map = <
 
                                /* IDSEL 0x15 */
-                               a800 0 0 1 &mpic 3b 1
-                               a800 0 0 2 &mpic 3b 1
-                               a800 0 0 3 &mpic 3b 1
-                               a800 0 0 4 &mpic 3b 1>;
+                               a800 0 0 1 &mpic b 1
+                               a800 0 0 2 &mpic b 1
+                               a800 0 0 3 &mpic b 1
+                               a800 0 0 4 &mpic b 1>;
                        interrupt-parent = <&mpic>;
-                       interrupts = <09 2>;
+                       interrupts = <19 2>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 a0000000 a0000000 0 20000000
                                  01000000 0 00000000 e3000000 0 00100000>;
index 3033599e74e878c58e7d03fc7c31d9962e6eb25d..828592592460759b75ec1609004448a875628610 100644 (file)
@@ -52,7 +52,7 @@
                        compatible = "fsl,8544-memory-controller";
                        reg = <2000 1000>;
                        interrupt-parent = <&mpic>;
-                       interrupts = <2 2>;
+                       interrupts = <12 2>;
                };
 
                l2-cache-controller@20000 {
                        cache-line-size = <20>; // 32 bytes
                        cache-size = <40000>;   // L2, 256K
                        interrupt-parent = <&mpic>;
-                       interrupts = <0 2>;
+                       interrupts = <10 2>;
                };
 
                i2c@3000 {
                        device_type = "i2c";
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
-                       interrupts = <1b 2>;
+                       interrupts = <2b 2>;
                        interrupt-parent = <&mpic>;
                        dfsrr;
                };
                        reg = <24520 20>;
                        phy0: ethernet-phy@0 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <3a 1>;
+                               interrupts = <a 1>;
                                reg = <0>;
                                device_type = "ethernet-phy";
                        };
                        phy1: ethernet-phy@1 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <3a 1>;
+                               interrupts = <a 1>;
                                reg = <1>;
                                device_type = "ethernet-phy";
                        };
                        compatible = "gianfar";
                        reg = <24000 1000>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <d 2 e 2 12 2>;
+                       interrupts = <1d 2 1e 2 22 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy0>;
                };
                        compatible = "gianfar";
                        reg = <26000 1000>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <f 2 10 2 11 2>;
+                       interrupts = <1f 2 20 2 21 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy1>;
                };
                        compatible = "ns16550";
                        reg = <4500 100>;
                        clock-frequency = <0>;
-                       interrupts = <1a 2>;
+                       interrupts = <2a 2>;
                        interrupt-parent = <&mpic>;
                };
 
                        compatible = "ns16550";
                        reg = <4600 100>;
                        clock-frequency = <0>;
-                       interrupts = <1a 2>;
+                       interrupts = <2a 2>;
                        interrupt-parent = <&mpic>;
                };
 
index ad96381033c09e7f35fbac9b4c3f83040ece2690..9d0b84b66cd43fcaa517a3a149114ab4d94fcfe9 100644 (file)
@@ -52,7 +52,7 @@
                        compatible = "fsl,8548-memory-controller";
                        reg = <2000 1000>;
                        interrupt-parent = <&mpic>;
-                       interrupts = <2 2>;
+                       interrupts = <12 2>;
                };
 
                l2-cache-controller@20000 {
                        cache-line-size = <20>; // 32 bytes
                        cache-size = <80000>;   // L2, 512K
                        interrupt-parent = <&mpic>;
-                       interrupts = <0 2>;
+                       interrupts = <10 2>;
                };
 
                i2c@3000 {
                        device_type = "i2c";
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
-                       interrupts = <1b 2>;
+                       interrupts = <2b 2>;
                        interrupt-parent = <&mpic>;
                        dfsrr;
                };
                        reg = <24520 20>;
                        phy0: ethernet-phy@0 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <35 0>;
+                               interrupts = <5 1>;
                                reg = <0>;
                                device_type = "ethernet-phy";
                        };
                        phy1: ethernet-phy@1 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <35 0>;
+                               interrupts = <5 1>;
                                reg = <1>;
                                device_type = "ethernet-phy";
                        };
                        phy2: ethernet-phy@2 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <35 0>;
+                               interrupts = <5 1>;
                                reg = <2>;
                                device_type = "ethernet-phy";
                        };
                        phy3: ethernet-phy@3 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <35 0>;
+                               interrupts = <5 1>;
                                reg = <3>;
                                device_type = "ethernet-phy";
                        };
                        model = "eTSEC";
                        compatible = "gianfar";
                        reg = <24000 1000>;
-                       local-mac-address = [ 00 E0 0C 00 73 00 ];
-                       interrupts = <d 2 e 2 12 2>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <1d 2 1e 2 22 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy0>;
                };
                        model = "eTSEC";
                        compatible = "gianfar";
                        reg = <25000 1000>;
-                       local-mac-address = [ 00 E0 0C 00 73 01 ];
-                       interrupts = <13 2 14 2 18 2>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <23 2 24 2 28 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy1>;
                };
                        model = "eTSEC";
                        compatible = "gianfar";
                        reg = <26000 1000>;
-                       local-mac-address = [ 00 E0 0C 00 73 02 ];
-                       interrupts = <f 2 10 2 11 2>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <1f 2 20 2 21 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy2>;
                };
                        model = "eTSEC";
                        compatible = "gianfar";
                        reg = <27000 1000>;
-                       local-mac-address = [ 00 E0 0C 00 73 03 ];
-                       interrupts = <15 2 16 2 17 2>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <25 2 26 2 27 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy3>;
                };
                        compatible = "ns16550";
                        reg = <4500 100>;       // reg base, size
                        clock-frequency = <0>;  // should we fill in in uboot?
-                       interrupts = <1a 2>;
+                       interrupts = <2a 2>;
                        interrupt-parent = <&mpic>;
                };
 
                        compatible = "ns16550";
                        reg = <4600 100>;       // reg base, size
                        clock-frequency = <0>;  // should we fill in in uboot?
-                       interrupts = <1a 2>;
+                       interrupts = <2a 2>;
                        interrupt-parent = <&mpic>;
                };
 
+               global-utilities@e0000 {        //global utilities reg
+                       compatible = "fsl,mpc8548-guts";
+                       reg = <e0000 1000>;
+                       fsl,has-rstcr;
+               };
+
                pci1: pci@8000 {
                        interrupt-map-mask = <1f800 0 0 7>;
                        interrupt-map = <
 
                                /* IDSEL 0x10 */
-                               08000 0 0 1 &mpic 30 1
-                               08000 0 0 2 &mpic 31 1
-                               08000 0 0 3 &mpic 32 1
-                               08000 0 0 4 &mpic 33 1
+                               08000 0 0 1 &mpic 0 1
+                               08000 0 0 2 &mpic 1 1
+                               08000 0 0 3 &mpic 2 1
+                               08000 0 0 4 &mpic 3 1
 
                                /* IDSEL 0x11 */
-                               08800 0 0 1 &mpic 30 1
-                               08800 0 0 2 &mpic 31 1
-                               08800 0 0 3 &mpic 32 1
-                               08800 0 0 4 &mpic 33 1
+                               08800 0 0 1 &mpic 0 1
+                               08800 0 0 2 &mpic 1 1
+                               08800 0 0 3 &mpic 2 1
+                               08800 0 0 4 &mpic 3 1
 
                                /* IDSEL 0x12 (Slot 1) */
-                               09000 0 0 1 &mpic 30 1
-                               09000 0 0 2 &mpic 31 1
-                               09000 0 0 3 &mpic 32 1
-                               09000 0 0 4 &mpic 33 1
+                               09000 0 0 1 &mpic 0 1
+                               09000 0 0 2 &mpic 1 1
+                               09000 0 0 3 &mpic 2 1
+                               09000 0 0 4 &mpic 3 1
 
                                /* IDSEL 0x13 (Slot 2) */
-                               09800 0 0 1 &mpic 31 1
-                               09800 0 0 2 &mpic 32 1
-                               09800 0 0 3 &mpic 33 1
-                               09800 0 0 4 &mpic 30 1
+                               09800 0 0 1 &mpic 1 1
+                               09800 0 0 2 &mpic 2 1
+                               09800 0 0 3 &mpic 3 1
+                               09800 0 0 4 &mpic 0 1
 
                                /* IDSEL 0x14 (Slot 3) */
-                               0a000 0 0 1 &mpic 32 1
-                               0a000 0 0 2 &mpic 33 1
-                               0a000 0 0 3 &mpic 30 1
-                               0a000 0 0 4 &mpic 31 1
+                               0a000 0 0 1 &mpic 2 1
+                               0a000 0 0 2 &mpic 3 1
+                               0a000 0 0 3 &mpic 0 1
+                               0a000 0 0 4 &mpic 1 1
 
                                /* IDSEL 0x15 (Slot 4) */
-                               0a800 0 0 1 &mpic 33 1
-                               0a800 0 0 2 &mpic 30 1
-                               0a800 0 0 3 &mpic 31 1
-                               0a800 0 0 4 &mpic 32 1
+                               0a800 0 0 1 &mpic 3 1
+                               0a800 0 0 2 &mpic 0 1
+                               0a800 0 0 3 &mpic 1 1
+                               0a800 0 0 4 &mpic 2 1
 
                                /* Bus 1 (Tundra Bridge) */
                                /* IDSEL 0x12 (ISA bridge) */
-                               19000 0 0 1 &mpic 30 1
-                               19000 0 0 2 &mpic 31 1
-                               19000 0 0 3 &mpic 32 1
-                               19000 0 0 4 &mpic 33 1>;
+                               19000 0 0 1 &mpic 0 1
+                               19000 0 0 2 &mpic 1 1
+                               19000 0 0 3 &mpic 2 1
+                               19000 0 0 4 &mpic 3 1>;
                        interrupt-parent = <&mpic>;
-                       interrupts = <08 2>;
+                       interrupts = <18 2>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 80000000 80000000 0 20000000
                                  01000000 0 00000000 e2000000 0 00100000>;
                        interrupt-map = <
 
                                /* IDSEL 0x15 */
-                               a800 0 0 1 &mpic 3b 1
-                               a800 0 0 2 &mpic 3b 1
-                               a800 0 0 3 &mpic 3b 1
-                               a800 0 0 4 &mpic 3b 1>;
+                               a800 0 0 1 &mpic b 1
+                               a800 0 0 2 &mpic b 1
+                               a800 0 0 3 &mpic b 1
+                               a800 0 0 4 &mpic b 1>;
                        interrupt-parent = <&mpic>;
-                       interrupts = <09 2>;
+                       interrupts = <19 2>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 a0000000 a0000000 0 20000000
                                  01000000 0 00000000 e3000000 0 00100000>;
index 951ed92f1154d6c9fd5940b8924846370a6d2c78..17e45d9a382a1e117c89884a7df4244d0626f431 100644 (file)
@@ -52,7 +52,7 @@
                        compatible = "fsl,8555-memory-controller";
                        reg = <2000 1000>;
                        interrupt-parent = <&mpic>;
-                       interrupts = <2 2>;
+                       interrupts = <12 2>;
                };
 
                l2-cache-controller@20000 {
                        cache-line-size = <20>; // 32 bytes
                        cache-size = <40000>;   // L2, 256K
                        interrupt-parent = <&mpic>;
-                       interrupts = <0 2>;
+                       interrupts = <10 2>;
                };
 
                i2c@3000 {
                        device_type = "i2c";
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
-                       interrupts = <1b 2>;
+                       interrupts = <2b 2>;
                        interrupt-parent = <&mpic>;
                        dfsrr;
                };
                        reg = <24520 20>;
                        phy0: ethernet-phy@0 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <35 0>;
+                               interrupts = <5 1>;
                                reg = <0>;
                                device_type = "ethernet-phy";
                        };
                        phy1: ethernet-phy@1 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <35 0>;
+                               interrupts = <5 1>;
                                reg = <1>;
                                device_type = "ethernet-phy";
                        };
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <24000 1000>;
-                       local-mac-address = [ 00 E0 0C 00 73 00 ];
-                       interrupts = <0d 2 0e 2 12 2>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <1d 2 1e 2 22 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy0>;
                };
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <25000 1000>;
-                       local-mac-address = [ 00 E0 0C 00 73 01 ];
-                       interrupts = <13 2 14 2 18 2>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <23 2 24 2 28 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy1>;
                };
                        compatible = "ns16550";
                        reg = <4500 100>;       // reg base, size
                        clock-frequency = <0>;  // should we fill in in uboot?
-                       interrupts = <1a 2>;
+                       interrupts = <2a 2>;
                        interrupt-parent = <&mpic>;
                };
 
                        compatible = "ns16550";
                        reg = <4600 100>;       // reg base, size
                        clock-frequency = <0>;  // should we fill in in uboot?
-                       interrupts = <1a 2>;
+                       interrupts = <2a 2>;
                        interrupt-parent = <&mpic>;
                };
 
                        interrupt-map = <
 
                                /* IDSEL 0x10 */
-                               08000 0 0 1 &mpic 30 1
-                               08000 0 0 2 &mpic 31 1
-                               08000 0 0 3 &mpic 32 1
-                               08000 0 0 4 &mpic 33 1
+                               08000 0 0 1 &mpic 0 1
+                               08000 0 0 2 &mpic 1 1
+                               08000 0 0 3 &mpic 2 1
+                               08000 0 0 4 &mpic 3 1
 
                                /* IDSEL 0x11 */
-                               08800 0 0 1 &mpic 30 1
-                               08800 0 0 2 &mpic 31 1
-                               08800 0 0 3 &mpic 32 1
-                               08800 0 0 4 &mpic 33 1
+                               08800 0 0 1 &mpic 0 1
+                               08800 0 0 2 &mpic 1 1
+                               08800 0 0 3 &mpic 2 1
+                               08800 0 0 4 &mpic 3 1
 
                                /* IDSEL 0x12 (Slot 1) */
-                               09000 0 0 1 &mpic 30 1
-                               09000 0 0 2 &mpic 31 1
-                               09000 0 0 3 &mpic 32 1
-                               09000 0 0 4 &mpic 33 1
+                               09000 0 0 1 &mpic 0 1
+                               09000 0 0 2 &mpic 1 1
+                               09000 0 0 3 &mpic 2 1
+                               09000 0 0 4 &mpic 3 1
 
                                /* IDSEL 0x13 (Slot 2) */
-                               09800 0 0 1 &mpic 31 1
-                               09800 0 0 2 &mpic 32 1
-                               09800 0 0 3 &mpic 33 1
-                               09800 0 0 4 &mpic 30 1
+                               09800 0 0 1 &mpic 1 1
+                               09800 0 0 2 &mpic 2 1
+                               09800 0 0 3 &mpic 3 1
+                               09800 0 0 4 &mpic 0 1
 
                                /* IDSEL 0x14 (Slot 3) */
-                               0a000 0 0 1 &mpic 32 1
-                               0a000 0 0 2 &mpic 33 1
-                               0a000 0 0 3 &mpic 30 1
-                               0a000 0 0 4 &mpic 31 1
+                               0a000 0 0 1 &mpic 2 1
+                               0a000 0 0 2 &mpic 3 1
+                               0a000 0 0 3 &mpic 0 1
+                               0a000 0 0 4 &mpic 1 1
 
                                /* IDSEL 0x15 (Slot 4) */
-                               0a800 0 0 1 &mpic 33 1
-                               0a800 0 0 2 &mpic 30 1
-                               0a800 0 0 3 &mpic 31 1
-                               0a800 0 0 4 &mpic 32 1
+                               0a800 0 0 1 &mpic 3 1
+                               0a800 0 0 2 &mpic 0 1
+                               0a800 0 0 3 &mpic 1 1
+                               0a800 0 0 4 &mpic 2 1
 
                                /* Bus 1 (Tundra Bridge) */
                                /* IDSEL 0x12 (ISA bridge) */
-                               19000 0 0 1 &mpic 30 1
-                               19000 0 0 2 &mpic 31 1
-                               19000 0 0 3 &mpic 32 1
-                               19000 0 0 4 &mpic 33 1>;
+                               19000 0 0 1 &mpic 0 1
+                               19000 0 0 2 &mpic 1 1
+                               19000 0 0 3 &mpic 2 1
+                               19000 0 0 4 &mpic 3 1>;
                        interrupt-parent = <&mpic>;
-                       interrupts = <08 2>;
+                       interrupts = <18 2>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 80000000 80000000 0 20000000
                                  01000000 0 00000000 e2000000 0 00100000>;
                        interrupt-map = <
 
                                /* IDSEL 0x15 */
-                               a800 0 0 1 &mpic 3b 1
-                               a800 0 0 2 &mpic 3b 1
-                               a800 0 0 3 &mpic 3b 1
-                               a800 0 0 4 &mpic 3b 1>;
+                               a800 0 0 1 &mpic b 1
+                               a800 0 0 2 &mpic b 1
+                               a800 0 0 3 &mpic b 1
+                               a800 0 0 4 &mpic b 1>;
                        interrupt-parent = <&mpic>;
-                       interrupts = <09 2>;
+                       interrupts = <19 2>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 a0000000 a0000000 0 20000000
                                  01000000 0 00000000 e3000000 0 00100000>;
index 80682152b0cf2314acbff0d8d9a51282a0fd7daa..21ccaaa27993626e814763f617576edcc63407a7 100644 (file)
@@ -52,7 +52,7 @@
                        compatible = "fsl,8540-memory-controller";
                        reg = <2000 1000>;
                        interrupt-parent = <&mpic>;
-                       interrupts = <2 2>;
+                       interrupts = <12 2>;
                };
 
                l2-cache-controller@20000 {
@@ -61,7 +61,7 @@
                        cache-line-size = <20>; // 32 bytes
                        cache-size = <40000>;   // L2, 256K
                        interrupt-parent = <&mpic>;
-                       interrupts = <0 2>;
+                       interrupts = <10 2>;
                };
 
                mdio@24520 {
                        #size-cells = <0>;
                        phy0: ethernet-phy@0 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <35 1>;
+                               interrupts = <5 1>;
                                reg = <0>;
                                device_type = "ethernet-phy";
                        };
                        phy1: ethernet-phy@1 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <35 1>;
+                               interrupts = <5 1>;
                                reg = <1>;
                                device_type = "ethernet-phy";
                        };
                        phy2: ethernet-phy@2 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <37 1>;
+                               interrupts = <7 1>;
                                reg = <2>;
                                device_type = "ethernet-phy";
                        };
                        phy3: ethernet-phy@3 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <37 1>;
+                               interrupts = <7 1>;
                                reg = <3>;
                                device_type = "ethernet-phy";
                        };
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <24000 1000>;
-                       address = [ 00 00 0C 00 00 FD ];
-                       interrupts = <d 2 e 2 12 2>;
+                       /*
+                        * address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
+                       address = [ 00 00 00 00 00 00 ];
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <1d 2 1e 2 22 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy0>;
                };
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <25000 1000>;
-                       address = [ 00 00 0C 00 01 FD ];
-                       interrupts = <13 2 14 2 18 2>;
+                       /*
+                        * address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
+                       address = [ 00 00 00 00 00 00 ];
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <23 2 24 2 28 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy1>;
                };
                        interrupt-map = <
 
                                        /* IDSEL 0x2 */
-                                        1000 0 0 1 &mpic 31 1
-                                        1000 0 0 2 &mpic 32 1
-                                        1000 0 0 3 &mpic 33 1
-                                        1000 0 0 4 &mpic 34 1
+                                        1000 0 0 1 &mpic 1 1
+                                        1000 0 0 2 &mpic 2 1
+                                        1000 0 0 3 &mpic 3 1
+                                        1000 0 0 4 &mpic 4 1
 
                                        /* IDSEL 0x3 */
-                                        1800 0 0 1 &mpic 34 1
-                                        1800 0 0 2 &mpic 31 1
-                                        1800 0 0 3 &mpic 32 1
-                                        1800 0 0 4 &mpic 33 1
+                                        1800 0 0 1 &mpic 4 1
+                                        1800 0 0 2 &mpic 1 1
+                                        1800 0 0 3 &mpic 2 1
+                                        1800 0 0 4 &mpic 3 1
 
                                        /* IDSEL 0x4 */
-                                        2000 0 0 1 &mpic 33 1
-                                        2000 0 0 2 &mpic 34 1
-                                        2000 0 0 3 &mpic 31 1
-                                        2000 0 0 4 &mpic 32 1
+                                        2000 0 0 1 &mpic 3 1
+                                        2000 0 0 2 &mpic 4 1
+                                        2000 0 0 3 &mpic 1 1
+                                        2000 0 0 4 &mpic 2 1
 
                                        /* IDSEL 0x5  */
-                                        2800 0 0 1 &mpic 32 1
-                                        2800 0 0 2 &mpic 33 1
-                                        2800 0 0 3 &mpic 34 1
-                                        2800 0 0 4 &mpic 31 1
+                                        2800 0 0 1 &mpic 2 1
+                                        2800 0 0 2 &mpic 3 1
+                                        2800 0 0 3 &mpic 4 1
+                                        2800 0 0 4 &mpic 1 1
 
                                        /* IDSEL 12 */
-                                        6000 0 0 1 &mpic 31 1
-                                        6000 0 0 2 &mpic 32 1
-                                        6000 0 0 3 &mpic 33 1
-                                        6000 0 0 4 &mpic 34 1
+                                        6000 0 0 1 &mpic 1 1
+                                        6000 0 0 2 &mpic 2 1
+                                        6000 0 0 3 &mpic 3 1
+                                        6000 0 0 4 &mpic 4 1
 
                                        /* IDSEL 13 */
-                                        6800 0 0 1 &mpic 34 1
-                                        6800 0 0 2 &mpic 31 1
-                                        6800 0 0 3 &mpic 32 1
-                                        6800 0 0 4 &mpic 33 1
+                                        6800 0 0 1 &mpic 4 1
+                                        6800 0 0 2 &mpic 1 1
+                                        6800 0 0 3 &mpic 2 1
+                                        6800 0 0 4 &mpic 3 1
 
                                        /* IDSEL 14*/
-                                        7000 0 0 1 &mpic 33 1
-                                        7000 0 0 2 &mpic 34 1
-                                        7000 0 0 3 &mpic 31 1
-                                        7000 0 0 4 &mpic 32 1
+                                        7000 0 0 1 &mpic 3 1
+                                        7000 0 0 2 &mpic 4 1
+                                        7000 0 0 3 &mpic 1 1
+                                        7000 0 0 4 &mpic 2 1
 
                                        /* IDSEL 15 */
-                                        7800 0 0 1 &mpic 32 1
-                                        7800 0 0 2 &mpic 33 1
-                                        7800 0 0 3 &mpic 34 1
-                                        7800 0 0 4 &mpic 31 1
+                                        7800 0 0 1 &mpic 2 1
+                                        7800 0 0 2 &mpic 3 1
+                                        7800 0 0 3 &mpic 4 1
+                                        7800 0 0 4 &mpic 1 1
 
                                        /* IDSEL 18 */
-                                        9000 0 0 1 &mpic 31 1
-                                        9000 0 0 2 &mpic 32 1
-                                        9000 0 0 3 &mpic 33 1
-                                        9000 0 0 4 &mpic 34 1
+                                        9000 0 0 1 &mpic 1 1
+                                        9000 0 0 2 &mpic 2 1
+                                        9000 0 0 3 &mpic 3 1
+                                        9000 0 0 4 &mpic 4 1
 
                                        /* IDSEL 19 */
-                                        9800 0 0 1 &mpic 34 1
-                                        9800 0 0 2 &mpic 31 1
-                                        9800 0 0 3 &mpic 32 1
-                                        9800 0 0 4 &mpic 33 1
+                                        9800 0 0 1 &mpic 4 1
+                                        9800 0 0 2 &mpic 1 1
+                                        9800 0 0 3 &mpic 2 1
+                                        9800 0 0 4 &mpic 3 1
 
                                        /* IDSEL 20 */
-                                        a000 0 0 1 &mpic 33 1
-                                        a000 0 0 2 &mpic 34 1
-                                        a000 0 0 3 &mpic 31 1
-                                        a000 0 0 4 &mpic 32 1
+                                        a000 0 0 1 &mpic 3 1
+                                        a000 0 0 2 &mpic 4 1
+                                        a000 0 0 3 &mpic 1 1
+                                        a000 0 0 4 &mpic 2 1
 
                                        /* IDSEL 21 */
-                                        a800 0 0 1 &mpic 32 1
-                                        a800 0 0 2 &mpic 33 1
-                                        a800 0 0 3 &mpic 34 1
-                                        a800 0 0 4 &mpic 31 1>;
+                                        a800 0 0 1 &mpic 2 1
+                                        a800 0 0 2 &mpic 3 1
+                                        a800 0 0 3 &mpic 4 1
+                                        a800 0 0 4 &mpic 1 1>;
 
                        interrupt-parent = <&mpic>;
-                       interrupts = <8 0>;
+                       interrupts = <18 2>;
                        bus-range = <0 0>;
                        ranges = <02000000 0 80000000 80000000 0 20000000
                                  01000000 0 00000000 e2000000 0 01000000>;
                                interrupt-controller;
                                #address-cells = <0>;
                                #interrupt-cells = <2>;
-                               interrupts = <1e 0>;
+                               interrupts = <2e 2>;
                                interrupt-parent = <&mpic>;
                                reg = <90c00 80>;
                                built-in;
                                model = "FCC";
                                device-id = <2>;
                                reg = <91320 20 88500 100 913a0 30>;
-                               mac-address = [ 00 00 0C 00 02 FD ];
+                               /*
+                                * mac-address is deprecated and will be removed
+                                * in 2.6.25.  Only recent versions of
+                                * U-Boot support local-mac-address, however.
+                                */
+                               mac-address = [ 00 00 00 00 00 00 ];
+                               local-mac-address = [ 00 00 00 00 00 00 ];
                                clock-setup = <ff00ffff 250000>;
                                rx-clock = <15>;
                                tx-clock = <16>;
                                model = "FCC";
                                device-id = <3>;
                                reg = <91340 20 88600 100 913d0 30>;
-                               mac-address = [ 00 00 0C 00 03 FD ];
+                               /*
+                                * mac-address is deprecated and will be removed
+                                * in 2.6.25.  Only recent versions of
+                                * U-Boot support local-mac-address, however.
+                                */
+                               mac-address = [ 00 00 00 00 00 00 ];
+                               local-mac-address = [ 00 00 00 00 00 00 ];
                                clock-setup = <ffff00ff 3700>;
                                rx-clock = <17>;
                                tx-clock = <18>;
index a123ec9456bc0bf4425b11142eb4dbe870b6c5e5..6bb18f2807a8cb4037ba67731218513d94f0516d 100644 (file)
@@ -61,7 +61,7 @@
                        compatible = "fsl,8568-memory-controller";
                        reg = <2000 1000>;
                        interrupt-parent = <&mpic>;
-                       interrupts = <2 2>;
+                       interrupts = <12 2>;
                };
 
                l2-cache-controller@20000 {
                        cache-line-size = <20>; // 32 bytes
                        cache-size = <80000>;   // L2, 512K
                        interrupt-parent = <&mpic>;
-                       interrupts = <0 2>;
+                       interrupts = <10 2>;
                };
 
                i2c@3000 {
                        device_type = "i2c";
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
-                       interrupts = <1b 2>;
+                       interrupts = <2b 2>;
                        interrupt-parent = <&mpic>;
                        dfsrr;
                };
@@ -86,7 +86,7 @@
                        device_type = "i2c";
                        compatible = "fsl-i2c";
                        reg = <3100 100>;
-                       interrupts = <1b 2>;
+                       interrupts = <2b 2>;
                        interrupt-parent = <&mpic>;
                        dfsrr;
                };
                        reg = <24520 20>;
                        phy0: ethernet-phy@0 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <31 1>;
+                               interrupts = <1 1>;
                                reg = <0>;
                                device_type = "ethernet-phy";
                        };
                        phy1: ethernet-phy@1 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <32 1>;
+                               interrupts = <2 1>;
                                reg = <1>;
                                device_type = "ethernet-phy";
                        };
                        phy2: ethernet-phy@2 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <31 1>;
+                               interrupts = <1 1>;
                                reg = <2>;
                                device_type = "ethernet-phy";
                        };
                        phy3: ethernet-phy@3 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <32 1>;
+                               interrupts = <2 1>;
                                reg = <3>;
                                device_type = "ethernet-phy";
                        };
                        model = "eTSEC";
                        compatible = "gianfar";
                        reg = <24000 1000>;
+                       /*
+                        * mac-address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
                        mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <d 2 e 2 12 2>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <1d 2 1e 2 22 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy2>;
                };
                        model = "eTSEC";
                        compatible = "gianfar";
                        reg = <25000 1000>;
-                       mac-address = [ 00 00 00 00 00 00];
-                       interrupts = <13 2 14 2 18 2>;
+                       /*
+                        * mac-address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
+                       mac-address = [ 00 00 00 00 00 00 ];
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <23 2 24 2 28 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy3>;
                };
                        compatible = "ns16550";
                        reg = <4500 100>;
                        clock-frequency = <0>;
-                       interrupts = <1a 2>;
+                       interrupts = <2a 2>;
                        interrupt-parent = <&mpic>;
                };
 
                        compatible = "ns16550";
                        reg = <4600 100>;
                        clock-frequency = <0>;
-                       interrupts = <1a 2>;
+                       interrupts = <2a 2>;
                        interrupt-parent = <&mpic>;
                };
 
                        model = "SEC2";
                        compatible = "talitos";
                        reg = <30000 f000>;
-                       interrupts = <1d 2>;
+                       interrupts = <2d 2>;
                        interrupt-parent = <&mpic>;
                        num-channels = <4>;
                        channel-fifo-len = <18>;
                        reg = <2000 200>;
                        interrupts = <20>;
                        interrupt-parent = <&qeic>;
-                       mac-address = [ 00 04 9f 00 23 23 ];
+                       /*
+                        * mac-address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
+                       mac-address = [ 00 00 00 00 00 00 ];
+                       local-mac-address = [ 00 00 00 00 00 00 ];
                        rx-clock = <0>;
                        tx-clock = <19>;
                        phy-handle = <&qe_phy0>;
                        reg = <3000 200>;
                        interrupts = <21>;
                        interrupt-parent = <&qeic>;
-                       mac-address = [ 00 11 22 33 44 55 ];
+                       /*
+                        * mac-address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
+                       mac-address = [ 00 00 00 00 00 00 ];
+                       local-mac-address = [ 00 00 00 00 00 00 ];
                        rx-clock = <0>;
                        tx-clock = <14>;
                        phy-handle = <&qe_phy1>;
                         * gianfar's MDIO bus */
                        qe_phy0: ethernet-phy@00 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <31 1>;
+                               interrupts = <1 1>;
                                reg = <0>;
                                device_type = "ethernet-phy";
                        };
                        qe_phy1: ethernet-phy@01 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <32 1>;
+                               interrupts = <2 1>;
                                reg = <1>;
                                device_type = "ethernet-phy";
                        };
                        qe_phy2: ethernet-phy@02 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <31 1>;
+                               interrupts = <1 1>;
                                reg = <2>;
                                device_type = "ethernet-phy";
                        };
                        qe_phy3: ethernet-phy@03 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <32 1>;
+                               interrupts = <2 1>;
                                reg = <3>;
                                device_type = "ethernet-phy";
                        };
                        reg = <80 80>;
                        built-in;
                        big-endian;
-                       interrupts = <1e 2 1e 2>; //high:30 low:30
+                       interrupts = <2e 2 2e 2>; //high:30 low:30
                        interrupt-parent = <&mpic>;
                };
 
index 260b264c869eeffc0b8aaebc52d25edca645fb23..db56a02b748fdc2f5e907fdfad629ea05018b24e 100644 (file)
                #size-cells = <1>;
                #interrupt-cells = <2>;
                device_type = "soc";
-               ranges = <0 f8000000 00100000>;
-               reg = <f8000000 00100000>;      // CCSRBAR 1M
+               ranges = <00001000 f8001000 000ff000
+                         80000000 80000000 20000000
+                         e2000000 e2000000 00100000
+                         a0000000 a0000000 20000000
+                         e3000000 e3000000 00100000>;
+               reg = <f8000000 00001000>;      // CCSRBAR
                bus-frequency = <0>;
 
                i2c@3000 {
                        reg = <24520 20>;
                        phy0: ethernet-phy@0 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <4a 1>;
+                               interrupts = <a 1>;
                                reg = <0>;
                                device_type = "ethernet-phy";
                        };
                        phy1: ethernet-phy@1 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <4a 1>;
+                               interrupts = <a 1>;
                                reg = <1>;
                                device_type = "ethernet-phy";
                        };
                        phy2: ethernet-phy@2 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <4a 1>;
+                               interrupts = <a 1>;
                                reg = <2>;
                                device_type = "ethernet-phy";
                        };
                        phy3: ethernet-phy@3 {
                                interrupt-parent = <&mpic>;
-                               interrupts = <4a 1>;
+                               interrupts = <a 1>;
                                reg = <3>;
                                device_type = "ethernet-phy";
                        };
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <24000 1000>;
-                       mac-address = [ 00 E0 0C 00 73 00 ];
+                       /*
+                        * mac-address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
+                       mac-address = [ 00 00 00 00 00 00 ];
+                       local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <1d 2 1e 2 22 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy0>;
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <25000 1000>;
-                       mac-address = [ 00 E0 0C 00 73 01 ];
+                       /*
+                        * mac-address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
+                       mac-address = [ 00 00 00 00 00 00 ];
+                       local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <23 2 24 2 28 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy1>;
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <26000 1000>;
-                       mac-address = [ 00 E0 0C 00 02 FD ];
+                       /*
+                        * mac-address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
+                       mac-address = [ 00 00 00 00 00 00 ];
+                       local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <1F 2 20 2 21 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy2>;
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <27000 1000>;
-                       mac-address = [ 00 E0 0C 00 03 FD ];
+                       /*
+                        * mac-address is deprecated and will be removed
+                        * in 2.6.25.  Only recent versions of
+                        * U-Boot support local-mac-address, however.
+                        */
+                       mac-address = [ 00 00 00 00 00 00 ];
+                       local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <25 2 26 2 27 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy3>;
                        #size-cells = <2>;
                        #address-cells = <3>;
                        reg = <8000 1000>;
-                       bus-range = <0 fe>;
+                       bus-range = <0 ff>;
                        ranges = <02000000 0 80000000 80000000 0 20000000
                                  01000000 0 00000000 e2000000 0 00100000>;
                        clock-frequency = <1fca055>;
                                f800 0 0 3 &i8259 0 0
                                f800 0 0 4 &i8259 0 0
                                >;
-                       i8259: i8259@4d0 {
-                               clock-frequency = <0>;
-                               interrupt-controller;
-                               device_type = "interrupt-controller";
-                               #address-cells = <0>;
-                               #interrupt-cells = <2>;
-                               built-in;
-                               compatible = "chrp,iic";
-                               big-endian;
-                               interrupts = <49 2>;
-                               interrupt-parent = <&mpic>;
+                       uli1575@0 {
+                               reg = <0 0 0 0 0>;
+                               #size-cells = <2>;
+                               #address-cells = <3>;
+                               ranges = <02000000 0 80000000
+                                         02000000 0 80000000
+                                         0 20000000
+                                         01000000 0 00000000
+                                         01000000 0 00000000
+                                         0 00100000>;
+
+                               pci_bridge@0 {
+                                       reg = <0 0 0 0 0>;
+                                       #size-cells = <2>;
+                                       #address-cells = <3>;
+                                       ranges = <02000000 0 80000000
+                                                 02000000 0 80000000
+                                                 0 20000000
+                                                 01000000 0 00000000
+                                                 01000000 0 00000000
+                                                 0 00100000>;
+
+                                       isa@1e {
+                                               device_type = "isa";
+                                               #interrupt-cells = <2>;
+                                               #size-cells = <1>;
+                                               #address-cells = <2>;
+                                               reg = <f000 0 0 0 0>;
+                                               ranges = <1 0 01000000 0 0
+                                                         00001000>;
+                                               interrupt-parent = <&i8259>;
+
+                                               i8259: interrupt-controller@20 {
+                                                       reg = <1 20 2
+                                                              1 a0 2
+                                                              1 4d0 2>;
+                                                       clock-frequency = <0>;
+                                                       interrupt-controller;
+                                                       device_type = "interrupt-controller";
+                                                       #address-cells = <0>;
+                                                       #interrupt-cells = <2>;
+                                                       built-in;
+                                                       compatible = "chrp,iic";
+                                                       interrupts = <9 2>;
+                                                       interrupt-parent =
+                                                               <&mpic>;
+                                               };
+
+                                               i8042@60 {
+                                                       #size-cells = <0>;
+                                                       #address-cells = <1>;
+                                                       reg = <1 60 1 1 64 1>;
+                                                       interrupts = <1 3 c 3>;
+                                                       interrupt-parent =
+                                                               <&i8259>;
+
+                                                       keyboard@0 {
+                                                               reg = <0>;
+                                                               compatible = "pnpPNP,303";
+                                                       };
+
+                                                       mouse@1 {
+                                                               reg = <1>;
+                                                               compatible = "pnpPNP,f03";
+                                                       };
+                                               };
+
+                                               rtc@70 {
+                                                       compatible =
+                                                               "pnpPNP,b00";
+                                                       reg = <1 70 2>;
+                                               };
+
+                                               gpio@400 {
+                                                       reg = <1 400 80>;
+                                               };
+                                       };
+                               };
                        };
 
                };
                        interrupt-map-mask = <f800 0 0 7>;
                        interrupt-map = <
                                /* IDSEL 0x0 */
-                               0000 0 0 1 &mpic 44 1
-                               0000 0 0 2 &mpic 45 1
-                               0000 0 0 3 &mpic 46 1
-                               0000 0 0 4 &mpic 47 1
+                               0000 0 0 1 &mpic 4 1
+                               0000 0 0 2 &mpic 5 1
+                               0000 0 0 3 &mpic 6 1
+                               0000 0 0 4 &mpic 7 1
                                >;
                };
 
index c0d06fd129278894b3fefec1a5b5edcfd9098aa7..e5e7726ddb0345ea1212e8d1806b05266ba7f866 100644 (file)
        compatible = "mpc8xx";
        #address-cells = <1>;
        #size-cells = <1>;
-       linux,phandle = <100>;
 
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
-               linux,phandle = <200>;
 
                PowerPC,866@0 {
                        device_type = "cpu";
                        clock-frequency = <0>;
                        32-bit;
                        interrupts = <f 2>;     // decrementer interrupt
-                       interrupt-parent = <ff000000>;
-                       linux,phandle = <201>;
+                       interrupt-parent = <&Mpc8xx_pic>;
                };
        };
 
        memory {
                device_type = "memory";
-               linux,phandle = <300>;
                reg = <00000000 800000>;
        };
 
                        device_type = "mdio";
                        compatible = "fs_enet";
                        reg = <e80 8>;
-                       linux,phandle = <e80>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       ethernet-phy@f {
-                               linux,phandle = <e800f>;
+                       phy: ethernet-phy@f {
                                reg = <f>;
                                device_type = "ethernet-phy";
                        };
                        reg = <e00 188>;
                        mac-address = [ 00 00 0C 00 01 FD ];
                        interrupts = <3 1>;
-                       interrupt-parent = <ff000000>;
-                       phy-handle = <e800f>;
+                       interrupt-parent = <&Mpc8xx_pic>;
+                       phy-handle = <&Phy>;
                };
 
-               pic@ff000000 {
-                       linux,phandle = <ff000000>;
+               mpc8xx_pic: pic@ff000000 {
                        interrupt-controller;
                        #address-cells = <0>;
                        #interrupt-cells = <2>;
@@ -91,7 +84,6 @@
                };
 
                cpm@ff000000 {
-                       linux,phandle = <ff000000>;
                        #address-cells = <1>;
                        #size-cells = <1>;
                        #interrupt-cells = <2>;
                        command-proc = <9c0>;
                        brg-frequency = <0>;
                        interrupts = <0 2>;     // cpm error interrupt
-                       interrupt-parent = <930>;
+                       interrupt-parent = <&Cpm_pic>;
 
-                       pic@930 {
-                               linux,phandle = <930>;
+                       cpm_pic: pic@930 {
                                interrupt-controller;
                                #address-cells = <0>;
                                #interrupt-cells = <2>;
                                interrupts = <5 2 0 2>;
-                               interrupt-parent = <ff000000>;
+                               interrupt-parent = <&Mpc8xx_pic>;
                                reg = <930 20>;
                                built-in;
                                device_type = "cpm-pic";
                                tx-clock = <1>;
                                current-speed = <0>;
                                interrupts = <4 3>;
-                               interrupt-parent = <930>;
+                               interrupt-parent = <&Cpm_pic>;
                        };
 
                        smc@a90 {
                                tx-clock = <2>;
                                current-speed = <0>;
                                interrupts = <3 3>;
-                               interrupt-parent = <930>;
+                               interrupt-parent = <&Cpm_pic>;
                        };
 
                        scc@a00 {
                                reg = <a00 18 3c00 80>;
                                mac-address = [ 00 00 0C 00 03 FD ];
                                interrupts = <1e 3>;
-                               interrupt-parent = <930>;
+                               interrupt-parent = <&Cpm_pic>;
                        };
                };
        };
index 110bf617060389a5a0ffbd68d607b61da1e1234a..dc7ab9c80611567baa497dffbe42d89e040e68e8 100644 (file)
        compatible = "mpc8xx";
        #address-cells = <1>;
        #size-cells = <1>;
-       linux,phandle = <100>;
 
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
-               linux,phandle = <200>;
 
                PowerPC,885@0 {
                        device_type = "cpu";
                        clock-frequency = <0>;
                        32-bit;
                        interrupts = <f 2>;     // decrementer interrupt
-                       interrupt-parent = <ff000000>;
-                       linux,phandle = <201>;
+                       interrupt-parent = <&Mpc8xx_pic>;
                };
        };
 
        memory {
                device_type = "memory";
-               linux,phandle = <300>;
                reg = <00000000 800000>;
        };
 
                        device_type = "mdio";
                        compatible = "fs_enet";
                        reg = <e80 8>;
-                       linux,phandle = <e80>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       ethernet-phy@0 {
-                               linux,phandle = <e8000>;
+                       Phy0: ethernet-phy@0 {
                                reg = <0>;
                                device_type = "ethernet-phy";
                        };
-                       ethernet-phy@1 {
-                               linux,phandle = <e8001>;
+                       Phy1: ethernet-phy@1 {
                                reg = <1>;
                                device_type = "ethernet-phy";
                        };
-                       ethernet-phy@2 {
-                               linux,phandle = <e8002>;
+                       Phy2: ethernet-phy@2 {
                                reg = <2>;
                                device_type = "ethernet-phy";
                        };
@@ -85,8 +77,8 @@
                        reg = <e00 188>;
                        mac-address = [ 00 00 0C 00 01 FD ];
                        interrupts = <3 1>;
-                       interrupt-parent = <ff000000>;
-                       phy-handle = <e8000>;
+                       interrupt-parent = <&Mpc8xx_pic>;
+                       phy-handle = <&Phy1>;
                };
 
                fec@1e00 {
                        reg = <1e00 188>;
                        mac-address = [ 00 00 0C 00 02 FD ];
                        interrupts = <7 1>;
-                       interrupt-parent = <ff000000>;
-                       phy-handle = <e8001>;
+                       interrupt-parent = <&Mpc8xx_pic>;
+                       phy-handle = <&Phy2>;
                };
 
-               pic@ff000000 {
-                       linux,phandle = <ff000000>;
+               Mpc8xx_pic: pic@ff000000 {
                        interrupt-controller;
                        #address-cells = <0>;
                        #interrupt-cells = <2>;
                        compatible = "CPM";
                };
 
+               pcmcia@0080 {
+                       #address-cells = <3>;
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       compatible = "fsl,pq-pcmcia";
+                       device_type = "pcmcia";
+                       reg = <80 80>;
+                       interrupt-parent = <&Mpc8xx_pic>;
+                       interrupts = <d 1>;
+               };
+
                cpm@ff000000 {
-                       linux,phandle = <ff000000>;
                        #address-cells = <1>;
                        #size-cells = <1>;
                        #interrupt-cells = <2>;
                        command-proc = <9c0>;
                        brg-frequency = <0>;
                        interrupts = <0 2>;     // cpm error interrupt
-                       interrupt-parent = <930>;
+                       interrupt-parent = <&Cpm_pic>;
 
-                       pic@930 {
-                               linux,phandle = <930>;
+                       Cpm_pic: pic@930 {
                                interrupt-controller;
                                #address-cells = <0>;
                                #interrupt-cells = <2>;
                                interrupts = <5 2 0 2>;
-                               interrupt-parent = <ff000000>;
+                               interrupt-parent = <&Mpc8xx_pic>;
                                reg = <930 20>;
                                built-in;
                                device_type = "cpm-pic";
                                tx-clock = <1>;
                                current-speed = <0>;
                                interrupts = <4 3>;
-                               interrupt-parent = <930>;
+                               interrupt-parent = <&Cpm_pic>;
                        };
 
                        smc@a90 {
                                tx-clock = <2>;
                                current-speed = <0>;
                                interrupts = <3 3>;
-                               interrupt-parent = <930>;
+                               interrupt-parent = <&Cpm_pic>;
                        };
 
                        scc@a40 {
                                reg = <a40 18 3e00 80>;
                                mac-address = [ 00 00 0C 00 03 FD ];
                                interrupts = <1c 3>;
-                               interrupt-parent = <930>;
-                               phy-handle = <e8002>;
+                               interrupt-parent = <&Cpm_pic>;
+                               phy-handle = <&Phy2>;
                        };
                };
        };
index 568965a022b98aa086768bac8ba7ed48a55850af..699d0df574d5b0bdc422b21be6192cc1dbf39296 100644 (file)
        };
 
        chosen {
-               bootargs = "ip=on console=ttyMM0";
+               bootargs = "ip=on";
                linux,stdout-path = "/mv64x60@f1000000/mpsc@8000";
        };
 };
diff --git a/arch/powerpc/boot/dts/ps3.dts b/arch/powerpc/boot/dts/ps3.dts
new file mode 100644 (file)
index 0000000..379ded2
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ *  PS3 Game Console device tree.
+ *
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/ {
+       model = "SonyPS3";
+       compatible = "sony,ps3";
+       #size-cells = <2>;
+       #address-cells = <2>;
+
+       chosen {
+       };
+
+       /*
+        * We'll get the size of the bootmem block from lv1 after startup,
+        * so we'll put a null entry here.
+        */
+
+       memory {
+               device_type = "memory";
+               reg = <0 0 0 0>;
+       };
+
+       /*
+        * The boot cpu is always zero for PS3.
+        *
+        * dtc expects a clock-frequency and timebase-frequency entries, so
+        * we'll put a null entries here.  These will be initialized after
+        * startup with data from lv1.
+        *
+        * Seems the only way currently to indicate a processor has multiple
+        * threads is with an ibm,ppc-interrupt-server#s entry.  We'll put one
+        * here so we can bring up both of ours.  See smp_setup_cpu_maps().
+        */
+
+       cpus {
+               #size-cells = <0>;
+               #address-cells = <1>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       ibm,ppc-interrupt-server#s = <0 1>;
+                       clock-frequency = <0>;
+                       timebase-frequency = <0>;
+                       i-cache-size = <8000>;
+                       d-cache-size = <8000>;
+                       i-cache-line-size = <80>;
+                       d-cache-line-size = <80>;
+               };
+       };
+};
index b1251ee7a102f2e2ad429307fb0360620c8446f6..75daedafd0a4d3c48f6924d54e7f6c8fbd3d656a 100644 (file)
@@ -100,28 +100,13 @@ static void ebony_fixups(void)
        ibm440gp_fixup_clocks(sysclk, 6 * 1843200);
        ibm44x_fixup_memsize();
        dt_fixup_mac_addresses(ebony_mac0, ebony_mac1);
-}
-
-#define SPRN_DBCR0             0x134
-#define   DBCR0_RST_SYSTEM     0x30000000
-
-static void ebony_exit(void)
-{
-       unsigned long tmp;
-
-       asm volatile (
-               "mfspr  %0,%1\n"
-               "oris   %0,%0,%2@h\n"
-               "mtspr  %1,%0"
-               : "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM)
-               );
-
+       ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
 }
 
 void ebony_init(void *mac0, void *mac1)
 {
        platform_ops.fixups = ebony_fixups;
-       platform_ops.exit = ebony_exit;
+       platform_ops.exit = ibm44x_dbcr_reset;
        ebony_mac0 = mac0;
        ebony_mac1 = mac1;
        ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
index 56b56a8d4b2334081dbc63452697da21cd5c8078..416dc3857bfe8dcc468c8f6c3d0953970a31de40 100644 (file)
@@ -36,8 +36,6 @@ struct addr_range {
        unsigned long size;
 };
 
-typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *);
-
 #undef DEBUG
 
 static struct addr_range prep_kernel(void)
index d16ee3e3f868eb2592822d63ecff77e07faeccc9..385e08b83b7e8070831a305bb66ce48ad024f42c 100644 (file)
@@ -15,8 +15,7 @@
 #include "page.h"
 #include "ops.h"
 
-typedef void *ihandle;
-typedef void *phandle;
+#include "of.h"
 
 extern char _end[];
 
@@ -25,154 +24,10 @@ extern char _end[];
 #define RAM_END                (512<<20)       /* Fixme: use OF */
 #define        ONE_MB          0x100000
 
-int (*prom) (void *);
 
 
 static unsigned long claim_base;
 
-static int call_prom(const char *service, int nargs, int nret, ...)
-{
-       int i;
-       struct prom_args {
-               const char *service;
-               int nargs;
-               int nret;
-               unsigned int args[12];
-       } args;
-       va_list list;
-
-       args.service = service;
-       args.nargs = nargs;
-       args.nret = nret;
-
-       va_start(list, nret);
-       for (i = 0; i < nargs; i++)
-               args.args[i] = va_arg(list, unsigned int);
-       va_end(list);
-
-       for (i = 0; i < nret; i++)
-               args.args[nargs+i] = 0;
-
-       if (prom(&args) < 0)
-               return -1;
-
-       return (nret > 0)? args.args[nargs]: 0;
-}
-
-static int call_prom_ret(const char *service, int nargs, int nret,
-                 unsigned int *rets, ...)
-{
-       int i;
-       struct prom_args {
-               const char *service;
-               int nargs;
-               int nret;
-               unsigned int args[12];
-       } args;
-       va_list list;
-
-       args.service = service;
-       args.nargs = nargs;
-       args.nret = nret;
-
-       va_start(list, rets);
-       for (i = 0; i < nargs; i++)
-               args.args[i] = va_arg(list, unsigned int);
-       va_end(list);
-
-       for (i = 0; i < nret; i++)
-               args.args[nargs+i] = 0;
-
-       if (prom(&args) < 0)
-               return -1;
-
-       if (rets != (void *) 0)
-               for (i = 1; i < nret; ++i)
-                       rets[i-1] = args.args[nargs+i];
-
-       return (nret > 0)? args.args[nargs]: 0;
-}
-
-/*
- * Older OF's require that when claiming a specific range of addresses,
- * we claim the physical space in the /memory node and the virtual
- * space in the chosen mmu node, and then do a map operation to
- * map virtual to physical.
- */
-static int need_map = -1;
-static ihandle chosen_mmu;
-static phandle memory;
-
-/* returns true if s2 is a prefix of s1 */
-static int string_match(const char *s1, const char *s2)
-{
-       for (; *s2; ++s2)
-               if (*s1++ != *s2)
-                       return 0;
-       return 1;
-}
-
-static int check_of_version(void)
-{
-       phandle oprom, chosen;
-       char version[64];
-
-       oprom = finddevice("/openprom");
-       if (oprom == (phandle) -1)
-               return 0;
-       if (getprop(oprom, "model", version, sizeof(version)) <= 0)
-               return 0;
-       version[sizeof(version)-1] = 0;
-       printf("OF version = '%s'\r\n", version);
-       if (!string_match(version, "Open Firmware, 1.")
-           && !string_match(version, "FirmWorks,3."))
-               return 0;
-       chosen = finddevice("/chosen");
-       if (chosen == (phandle) -1) {
-               chosen = finddevice("/chosen@0");
-               if (chosen == (phandle) -1) {
-                       printf("no chosen\n");
-                       return 0;
-               }
-       }
-       if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
-               printf("no mmu\n");
-               return 0;
-       }
-       memory = (ihandle) call_prom("open", 1, 1, "/memory");
-       if (memory == (ihandle) -1) {
-               memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
-               if (memory == (ihandle) -1) {
-                       printf("no memory node\n");
-                       return 0;
-               }
-       }
-       printf("old OF detected\r\n");
-       return 1;
-}
-
-static void *claim(unsigned long virt, unsigned long size, unsigned long align)
-{
-       int ret;
-       unsigned int result;
-
-       if (need_map < 0)
-               need_map = check_of_version();
-       if (align || !need_map)
-               return (void *) call_prom("claim", 3, 1, virt, size, align);
-
-       ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
-                           align, size, virt);
-       if (ret != 0 || result == -1)
-               return (void *) -1;
-       ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
-                           align, size, virt);
-       /* 0x12 == coherent + read/write */
-       ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
-                       0x12, size, virt, virt);
-       return (void *) virt;
-}
-
 static void *of_try_claim(unsigned long size)
 {
        unsigned long addr = 0;
@@ -184,7 +39,7 @@ static void *of_try_claim(unsigned long size)
 #ifdef DEBUG
                printf("    trying: 0x%08lx\n\r", claim_base);
 #endif
-               addr = (unsigned long)claim(claim_base, size, 0);
+               addr = (unsigned long)of_claim(claim_base, size, 0);
                if ((void *)addr != (void *)-1)
                        break;
        }
@@ -208,64 +63,6 @@ static void of_image_hdr(const void *hdr)
        }
 }
 
-static void *of_vmlinux_alloc(unsigned long size)
-{
-       void *p = malloc(size);
-
-       if (!p)
-               fatal("Can't allocate memory for kernel image!\n\r");
-
-       return p;
-}
-
-static void of_exit(void)
-{
-       call_prom("exit", 0, 0);
-}
-
-/*
- * OF device tree routines
- */
-static void *of_finddevice(const char *name)
-{
-       return (phandle) call_prom("finddevice", 1, 1, name);
-}
-
-static int of_getprop(const void *phandle, const char *name, void *buf,
-               const int buflen)
-{
-       return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
-}
-
-static int of_setprop(const void *phandle, const char *name, const void *buf,
-               const int buflen)
-{
-       return call_prom("setprop", 4, 1, phandle, name, buf, buflen);
-}
-
-/*
- * OF console routines
- */
-static void *of_stdout_handle;
-
-static int of_console_open(void)
-{
-       void *devp;
-
-       if (((devp = finddevice("/chosen")) != NULL)
-                       && (getprop(devp, "stdout", &of_stdout_handle,
-                               sizeof(of_stdout_handle))
-                               == sizeof(of_stdout_handle)))
-               return 0;
-
-       return -1;
-}
-
-static void of_console_write(char *buf, int len)
-{
-       call_prom("write", 3, 1, of_stdout_handle, buf, len);
-}
-
 void platform_init(unsigned long a1, unsigned long a2, void *promptr)
 {
        platform_ops.image_hdr = of_image_hdr;
@@ -277,10 +74,9 @@ void platform_init(unsigned long a1, unsigned long a2, void *promptr)
        dt_ops.getprop = of_getprop;
        dt_ops.setprop = of_setprop;
 
-       console_ops.open = of_console_open;
-       console_ops.write = of_console_write;
+       of_console_init();
 
-       prom = (int (*)(void *))promptr;
+       of_init(promptr);
        loader_info.promptr = promptr;
        if (a1 && a2 && a2 != 0xdeadbeef) {
                loader_info.initrd_addr = a1;
diff --git a/arch/powerpc/boot/of.h b/arch/powerpc/boot/of.h
new file mode 100644 (file)
index 0000000..e4c68f7
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef _PPC_BOOT_OF_H_
+#define _PPC_BOOT_OF_H_
+
+typedef void *phandle;
+typedef void *ihandle;
+
+void of_init(void *promptr);
+int of_call_prom(const char *service, int nargs, int nret, ...);
+void *of_claim(unsigned long virt, unsigned long size, unsigned long align);
+void *of_vmlinux_alloc(unsigned long size);
+void of_exit(void);
+void *of_finddevice(const char *name);
+int of_getprop(const void *phandle, const char *name, void *buf,
+              const int buflen);
+int of_setprop(const void *phandle, const char *name, const void *buf,
+              const int buflen);
+
+/* Console functions */
+void of_console_init(void);
+
+#endif /* _PPC_BOOT_OF_H_ */
diff --git a/arch/powerpc/boot/ofconsole.c b/arch/powerpc/boot/ofconsole.c
new file mode 100644 (file)
index 0000000..ce0e024
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * OF console routines
+ *
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <stddef.h>
+#include "types.h"
+#include "elf.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+
+#include "of.h"
+
+static void *of_stdout_handle;
+
+static int of_console_open(void)
+{
+       void *devp;
+
+       if (((devp = of_finddevice("/chosen")) != NULL)
+           && (of_getprop(devp, "stdout", &of_stdout_handle,
+                          sizeof(of_stdout_handle))
+               == sizeof(of_stdout_handle)))
+               return 0;
+
+       return -1;
+}
+
+static void of_console_write(const char *buf, int len)
+{
+       of_call_prom("write", 3, 1, of_stdout_handle, buf, len);
+}
+
+void of_console_init(void)
+{
+       console_ops.open = of_console_open;
+       console_ops.write = of_console_write;
+}
diff --git a/arch/powerpc/boot/oflib.c b/arch/powerpc/boot/oflib.c
new file mode 100644 (file)
index 0000000..95b8fd6
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <stddef.h>
+#include "types.h"
+#include "elf.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+
+#include "of.h"
+
+static int (*prom) (void *);
+
+void of_init(void *promptr)
+{
+       prom = (int (*)(void *))promptr;
+}
+
+int of_call_prom(const char *service, int nargs, int nret, ...)
+{
+       int i;
+       struct prom_args {
+               const char *service;
+               int nargs;
+               int nret;
+               unsigned int args[12];
+       } args;
+       va_list list;
+
+       args.service = service;
+       args.nargs = nargs;
+       args.nret = nret;
+
+       va_start(list, nret);
+       for (i = 0; i < nargs; i++)
+               args.args[i] = va_arg(list, unsigned int);
+       va_end(list);
+
+       for (i = 0; i < nret; i++)
+               args.args[nargs+i] = 0;
+
+       if (prom(&args) < 0)
+               return -1;
+
+       return (nret > 0)? args.args[nargs]: 0;
+}
+
+static int of_call_prom_ret(const char *service, int nargs, int nret,
+                           unsigned int *rets, ...)
+{
+       int i;
+       struct prom_args {
+               const char *service;
+               int nargs;
+               int nret;
+               unsigned int args[12];
+       } args;
+       va_list list;
+
+       args.service = service;
+       args.nargs = nargs;
+       args.nret = nret;
+
+       va_start(list, rets);
+       for (i = 0; i < nargs; i++)
+               args.args[i] = va_arg(list, unsigned int);
+       va_end(list);
+
+       for (i = 0; i < nret; i++)
+               args.args[nargs+i] = 0;
+
+       if (prom(&args) < 0)
+               return -1;
+
+       if (rets != (void *) 0)
+               for (i = 1; i < nret; ++i)
+                       rets[i-1] = args.args[nargs+i];
+
+       return (nret > 0)? args.args[nargs]: 0;
+}
+
+/* returns true if s2 is a prefix of s1 */
+static int string_match(const char *s1, const char *s2)
+{
+       for (; *s2; ++s2)
+               if (*s1++ != *s2)
+                       return 0;
+       return 1;
+}
+
+/*
+ * Older OF's require that when claiming a specific range of addresses,
+ * we claim the physical space in the /memory node and the virtual
+ * space in the chosen mmu node, and then do a map operation to
+ * map virtual to physical.
+ */
+static int need_map = -1;
+static ihandle chosen_mmu;
+static phandle memory;
+
+static int check_of_version(void)
+{
+       phandle oprom, chosen;
+       char version[64];
+
+       oprom = of_finddevice("/openprom");
+       if (oprom == (phandle) -1)
+               return 0;
+       if (of_getprop(oprom, "model", version, sizeof(version)) <= 0)
+               return 0;
+       version[sizeof(version)-1] = 0;
+       printf("OF version = '%s'\r\n", version);
+       if (!string_match(version, "Open Firmware, 1.")
+           && !string_match(version, "FirmWorks,3."))
+               return 0;
+       chosen = of_finddevice("/chosen");
+       if (chosen == (phandle) -1) {
+               chosen = of_finddevice("/chosen@0");
+               if (chosen == (phandle) -1) {
+                       printf("no chosen\n");
+                       return 0;
+               }
+       }
+       if (of_getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
+               printf("no mmu\n");
+               return 0;
+       }
+       memory = (ihandle) of_call_prom("open", 1, 1, "/memory");
+       if (memory == (ihandle) -1) {
+               memory = (ihandle) of_call_prom("open", 1, 1, "/memory@0");
+               if (memory == (ihandle) -1) {
+                       printf("no memory node\n");
+                       return 0;
+               }
+       }
+       printf("old OF detected\r\n");
+       return 1;
+}
+
+void *of_claim(unsigned long virt, unsigned long size, unsigned long align)
+{
+       int ret;
+       unsigned int result;
+
+       if (need_map < 0)
+               need_map = check_of_version();
+       if (align || !need_map)
+               return (void *) of_call_prom("claim", 3, 1, virt, size, align);
+
+       ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", memory,
+                              align, size, virt);
+       if (ret != 0 || result == -1)
+               return (void *) -1;
+       ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
+                              align, size, virt);
+       /* 0x12 == coherent + read/write */
+       ret = of_call_prom("call-method", 6, 1, "map", chosen_mmu,
+                          0x12, size, virt, virt);
+       return (void *) virt;
+}
+
+void *of_vmlinux_alloc(unsigned long size)
+{
+       void *p = malloc(size);
+
+       if (!p)
+               fatal("Can't allocate memory for kernel image!\n\r");
+
+       return p;
+}
+
+void of_exit(void)
+{
+       of_call_prom("exit", 0, 0);
+}
+
+/*
+ * OF device tree routines
+ */
+void *of_finddevice(const char *name)
+{
+       return (phandle) of_call_prom("finddevice", 1, 1, name);
+}
+
+int of_getprop(const void *phandle, const char *name, void *buf,
+              const int buflen)
+{
+       return of_call_prom("getprop", 4, 1, phandle, name, buf, buflen);
+}
+
+int of_setprop(const void *phandle, const char *name, const void *buf,
+              const int buflen)
+{
+       return of_call_prom("setprop", 4, 1, phandle, name, buf, buflen);
+}
index 959124f3f9afb1d8eb64127ae3e3912a6f677cbf..86077066cd7cae1a8c42f0f679f44431ebd241a7 100644 (file)
@@ -19,6 +19,8 @@
 #define        MAX_PATH_LEN            256
 #define        MAX_PROP_LEN            256 /* What should this be? */
 
+typedef void (*kernel_entry_t)(unsigned long r3, unsigned long r4, void *r5);
+
 /* Platform specific operations */
 struct platform_ops {
        void    (*fixups)(void);
@@ -51,7 +53,7 @@ extern struct dt_ops dt_ops;
 /* Console operations */
 struct console_ops {
        int     (*open)(void);
-       void    (*write)(char *buf, int len);
+       void    (*write)(const char *buf, int len);
        void    (*edit_cmdline)(char *buf, int len);
        void    (*close)(void);
        void    *data;
diff --git a/arch/powerpc/boot/ps3-head.S b/arch/powerpc/boot/ps3-head.S
new file mode 100644 (file)
index 0000000..1a6d64a
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ *  PS3 bootwrapper entry.
+ *
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ppc_asm.h"
+
+       .text
+
+/*
+ * __system_reset_overlay - The PS3 first stage entry.
+ *
+ * The bootwraper build script copies the 0x100 bytes at symbol
+ * __system_reset_overlay to offset 0x100 of the rom image.
+ *
+ * The PS3 has a single processor with two threads.
+ */
+
+       .globl __system_reset_overlay
+__system_reset_overlay:
+
+       /* Switch to 32-bit mode. */
+
+       mfmsr   r9
+       clrldi  r9,r9,1
+       mtmsrd  r9
+       nop
+
+       /* Get thread number in r3 and branch. */
+
+       mfspr   r3, 0x88
+       cntlzw. r3, r3
+       li      r4, 0
+       li      r5, 0
+       beq     1f
+
+       /* Secondary goes to __secondary_hold in kernel. */
+
+       li      r4, 0x60
+       mtctr   r4
+       bctr
+
+       /* Primary delays then goes to _zimage_start in wrapper. */
+1:
+       or      31, 31, 31 /* db16cyc */
+       or      31, 31, 31 /* db16cyc */
+
+       lis     r4, _zimage_start@ha
+       addi    r4, r4, _zimage_start@l
+       mtctr   r4
+       bctr
+
+/*
+ * __system_reset_kernel - Place holder for the kernel reset vector.
+ *
+ * The bootwrapper build script copies 0x100 bytes from offset 0x100
+ * of the rom image to the symbol __system_reset_kernel.  At runtime
+ * the bootwrapper program copies the 0x100 bytes at __system_reset_kernel
+ * to ram address 0x100.  This symbol must occupy 0x100 bytes.
+ */
+
+       .globl __system_reset_kernel
+__system_reset_kernel:
+
+       . = __system_reset_kernel + 0x100
diff --git a/arch/powerpc/boot/ps3-hvcall.S b/arch/powerpc/boot/ps3-hvcall.S
new file mode 100644 (file)
index 0000000..c8b7df3
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ *  PS3 bootwrapper hvcalls.
+ *
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ppc_asm.h"
+
+/*
+ * The PS3 hypervisor uses a 64 bit "C" language calling convention.
+ * The routines here marshal arguments between the 32 bit wrapper
+ * program and the 64 bit hvcalls.
+ *
+ *  wrapper           lv1
+ *  32-bit (h,l)      64-bit
+ *
+ *  1: r3,r4          <-> r3
+ *  2: r5,r6          <-> r4
+ *  3: r7,r8          <-> r5
+ *  4: r9,r10         <-> r6
+ *  5: 8(r1),12(r1)   <-> r7
+ *  6: 16(r1),20(r1)  <-> r8
+ *  7: 24(r1),28(r1)  <-> r9
+ *  8: 32(r1),36(r1)  <-> r10
+ *
+ */
+
+.macro GLOBAL name
+       .section ".text"
+       .balign 4
+       .globl \name
+\name:
+.endm
+
+.macro NO_SUPPORT name
+       GLOBAL \name
+       b ps3_no_support
+.endm
+
+.macro HVCALL num
+       li r11, \num
+       .long 0x44000022
+       extsw r3, r3
+.endm
+
+.macro SAVE_LR offset=4
+       mflr r0
+       stw r0, \offset(r1)
+.endm
+
+.macro LOAD_LR offset=4
+       lwz r0, \offset(r1)
+       mtlr r0
+.endm
+
+.macro LOAD_64_REG target,high,low
+       sldi r11, \high, 32
+       or \target, r11, \low
+.endm
+
+.macro LOAD_64_STACK target,offset
+       ld \target, \offset(r1)
+.endm
+
+.macro LOAD_R3
+       LOAD_64_REG r3,r3,r4
+.endm
+
+.macro LOAD_R4
+       LOAD_64_REG r4,r5,r6
+.endm
+
+.macro LOAD_R5
+       LOAD_64_REG r5,r7,r8
+.endm
+
+.macro LOAD_R6
+       LOAD_64_REG r6,r9,r10
+.endm
+
+.macro LOAD_R7
+       LOAD_64_STACK r7,8
+.endm
+
+.macro LOAD_R8
+       LOAD_64_STACK r8,16
+.endm
+
+.macro LOAD_R9
+       LOAD_64_STACK r9,24
+.endm
+
+.macro LOAD_R10
+       LOAD_64_STACK r10,32
+.endm
+
+.macro LOAD_REGS_0
+       stwu 1,-16(1)
+       stw 3, 8(1)
+.endm
+
+.macro LOAD_REGS_5
+       LOAD_R3
+       LOAD_R4
+       LOAD_R5
+       LOAD_R6
+       LOAD_R7
+.endm
+
+.macro LOAD_REGS_6
+       LOAD_REGS_5
+       LOAD_R8
+.endm
+
+.macro LOAD_REGS_8
+       LOAD_REGS_6
+       LOAD_R9
+       LOAD_R10
+.endm
+
+.macro STORE_REGS_0_1
+       lwz r11, 8(r1)
+       std r4, 0(r11)
+       mr r4, r3
+       li r3, 0
+       addi r1,r1,16
+.endm
+
+.macro STORE_REGS_5_2
+       lwz r11, 16(r1)
+       std r4, 0(r11)
+       lwz r11, 24(r1)
+       std r5, 0(r11)
+.endm
+
+.macro STORE_REGS_6_1
+       lwz r11, 24(r1)
+       std r4, 0(r11)
+.endm
+
+GLOBAL lv1_get_logical_ppe_id
+       SAVE_LR
+       LOAD_REGS_0
+       HVCALL 69
+       STORE_REGS_0_1
+       LOAD_LR
+       blr
+
+GLOBAL lv1_get_logical_partition_id
+       SAVE_LR
+       LOAD_REGS_0
+       HVCALL 74
+       STORE_REGS_0_1
+       LOAD_LR
+       blr
+
+GLOBAL lv1_get_repository_node_value
+       SAVE_LR
+       LOAD_REGS_5
+       HVCALL 91
+       STORE_REGS_5_2
+       LOAD_LR
+       blr
+
+GLOBAL lv1_panic
+       SAVE_LR
+       LOAD_REGS_8
+       HVCALL 255
+       LOAD_LR
+       blr
diff --git a/arch/powerpc/boot/ps3.c b/arch/powerpc/boot/ps3.c
new file mode 100644 (file)
index 0000000..893d593
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ *  PS3 bootwrapper support.
+ *
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "elf.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+
+extern s64 lv1_panic(u64 in_1);
+extern s64 lv1_get_logical_partition_id(u64 *out_1);
+extern s64 lv1_get_logical_ppe_id(u64 *out_1);
+extern s64 lv1_get_repository_node_value(u64 in_1, u64 in_2, u64 in_3,
+       u64 in_4, u64 in_5, u64 *out_1, u64 *out_2);
+
+#ifdef DEBUG
+#define DBG(fmt...) printf(fmt)
+#else
+static inline int __attribute__ ((format (printf, 1, 2))) DBG(
+       const char *fmt, ...) {return 0;}
+#endif
+
+BSS_STACK(4096);
+
+/* A buffer that may be edited by tools operating on a zImage binary so as to
+ * edit the command line passed to vmlinux (by setting /chosen/bootargs).
+ * The buffer is put in it's own section so that tools may locate it easier.
+ */
+static char cmdline[COMMAND_LINE_SIZE]
+       __attribute__((__section__("__builtin_cmdline")));
+
+static void prep_cmdline(void *chosen)
+{
+       if (cmdline[0] == '\0')
+               getprop(chosen, "bootargs", cmdline, COMMAND_LINE_SIZE-1);
+       else
+               setprop_str(chosen, "bootargs", cmdline);
+
+       printf("cmdline: '%s'\n", cmdline);
+}
+
+static void ps3_console_write(const char *buf, int len)
+{
+}
+
+static void ps3_exit(void)
+{
+       printf("ps3_exit\n");
+
+       /* lv1_panic will shutdown the lpar. */
+
+       lv1_panic(0); /* zero = do not reboot */
+       while (1);
+}
+
+static int ps3_repository_read_rm_size(u64 *rm_size)
+{
+       s64 result;
+       u64 lpar_id;
+       u64 ppe_id;
+       u64 v2;
+
+       result = lv1_get_logical_partition_id(&lpar_id);
+
+       if (result)
+               return -1;
+
+       result = lv1_get_logical_ppe_id(&ppe_id);
+
+       if (result)
+               return -1;
+
+       /*
+        * n1: 0000000062690000 : ....bi..
+        * n2: 7075000000000000 : pu......
+        * n3: 0000000000000001 : ........
+        * n4: 726d5f73697a6500 : rm_size.
+       */
+
+       result = lv1_get_repository_node_value(lpar_id, 0x0000000062690000ULL,
+               0x7075000000000000ULL, ppe_id, 0x726d5f73697a6500ULL, rm_size,
+               &v2);
+
+       printf("%s:%d: ppe_id  %lu \n", __func__, __LINE__,
+               (unsigned long)ppe_id);
+       printf("%s:%d: lpar_id %lu \n", __func__, __LINE__,
+               (unsigned long)lpar_id);
+       printf("%s:%d: rm_size %llxh \n", __func__, __LINE__, *rm_size);
+
+       return result ? -1 : 0;
+}
+
+void ps3_copy_vectors(void)
+{
+       extern char __system_reset_kernel[];
+
+       memcpy((void *)0x100, __system_reset_kernel, 0x100);
+       flush_cache((void *)0x100, 0x100);
+}
+
+void platform_init(void)
+{
+       extern char _end[];
+       extern char _dtb_start[];
+       extern char _initrd_start[];
+       extern char _initrd_end[];
+       const u32 heapsize = 0x1000000 - (u32)_end; /* 16MiB */
+       void *chosen;
+       unsigned long ft_addr;
+       u64 rm_size;
+
+       console_ops.write = ps3_console_write;
+       platform_ops.exit = ps3_exit;
+
+       printf("\n-- PS3 bootwrapper --\n");
+
+       simple_alloc_init(_end, heapsize, 32, 64);
+       ft_init(_dtb_start, 0, 4);
+
+       chosen = finddevice("/chosen");
+
+       ps3_repository_read_rm_size(&rm_size);
+       dt_fixup_memory(0, rm_size);
+
+       if (_initrd_end > _initrd_start) {
+               setprop_val(chosen, "linux,initrd-start", (u32)(_initrd_start));
+               setprop_val(chosen, "linux,initrd-end", (u32)(_initrd_end));
+       }
+
+       prep_cmdline(chosen);
+
+       ft_addr = dt_ops.finalize();
+
+       ps3_copy_vectors();
+
+       printf(" flat tree at 0x%lx\n\r", ft_addr);
+
+       ((kernel_entry_t)0)(ft_addr, 0, NULL);
+
+       ps3_exit();
+}
index 7fd32330a9a5ae065da03b94db95b4c8efa8fdf8..eaa0d3ae351861957ec2fbe7cad0debce1a2a779 100644 (file)
@@ -27,7 +27,7 @@ static int serial_open(void)
        return scdp->open();
 }
 
-static void serial_write(char *buf, int len)
+static void serial_write(const char *buf, int len)
 {
        struct serial_console_data *scdp = console_ops.data;
 
index 0a9feeb983424f53e98b047609f510adab849f26..5b57800bbc675e11efabec8601a8b9000ce4c196 100644 (file)
@@ -190,7 +190,11 @@ int vsprintf(char *buf, const char *fmt, va_list args)
 
                /* get the conversion qualifier */
                qualifier = -1;
-               if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
+               if (*fmt == 'l' && *(fmt + 1) == 'l') {
+                       qualifier = 'q';
+                       fmt += 2;
+               } else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L'
+                       || *fmt == 'Z') {
                        qualifier = *fmt;
                        ++fmt;
                }
@@ -281,6 +285,10 @@ int vsprintf(char *buf, const char *fmt, va_list args)
                        num = va_arg(args, unsigned long);
                        if (flags & SIGN)
                                num = (signed long) num;
+               } else if (qualifier == 'q') {
+                       num = va_arg(args, unsigned long long);
+                       if (flags & SIGN)
+                               num = (signed long long) num;
                } else if (qualifier == 'Z') {
                        num = va_arg(args, size_t);
                } else if (qualifier == 'h') {
index 79d26e7086770dcbfed2d6fcce0f74cb32429bfd..31393d17a9c1f968288557e0d96d52264d8bfb53 100644 (file)
@@ -7,6 +7,10 @@ typedef unsigned char          u8;
 typedef unsigned short         u16;
 typedef unsigned int           u32;
 typedef unsigned long long     u64;
+typedef signed char            s8;
+typedef short                  s16;
+typedef int                    s32;
+typedef long long              s64;
 
 #define min(x,y) ({ \
        typeof(x) _x = (x);     \
index da77adc73078d3561144edf3d335dab4c901dbdc..65f685479175a354d357b087c5456b414492153c 100755 (executable)
@@ -144,6 +144,15 @@ miboot|uboot)
 cuboot*)
     gzip=
     ;;
+ps3)
+    platformo="$object/ps3-head.o $object/ps3-hvcall.o $object/ps3.o"
+    lds=$object/zImage.ps3.lds
+    gzip=
+    ext=bin
+    objflags="-O binary --set-section-flags=.bss=contents,alloc,load,data"
+    ksection=.kernel:vmlinux.bin
+    isection=.kernel:initrd
+    ;;
 esac
 
 vmz="$tmpdir/`basename \"$kernel\"`.$ext"
@@ -239,4 +248,50 @@ treeboot*)
     fi
     exit 0
     ;;
+ps3)
+    # The ps3's loader supports loading gzipped binary images from flash
+    # rom to addr zero. The loader enters the image at addr 0x100.  A
+    # bootwrapper overlay is use to arrange for the kernel to be loaded
+    # to addr zero and to have a suitable bootwrapper entry at 0x100.
+    # To construct the rom image, 0x100 bytes from offset 0x100 in the
+    # kernel is copied to the bootwrapper symbol __system_reset_kernel.
+    # The 0x100 bytes at the bootwrapper symbol __system_reset_overlay is
+    # then copied to offset 0x100.  At runtime the bootwrapper program
+    # copies the 0x100 bytes at __system_reset_kernel to addr 0x100.
+
+    system_reset_overlay=0x`${CROSS}nm "$ofile" \
+        | grep ' __system_reset_overlay$'       \
+        | cut -d' ' -f1`
+    system_reset_overlay=`printf "%d" $system_reset_overlay`
+    system_reset_kernel=0x`${CROSS}nm "$ofile" \
+        | grep ' __system_reset_kernel$'       \
+        | cut -d' ' -f1`
+    system_reset_kernel=`printf "%d" $system_reset_kernel`
+    overlay_dest="256"
+    overlay_size="256"
+
+    rm -f "$object/otheros.bld"
+
+    ${CROSS}objcopy -O binary "$ofile" "$ofile.bin"
+
+    msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \
+        skip=$overlay_dest seek=$system_reset_kernel      \
+        count=$overlay_size bs=1 2>&1)
+
+    if [ $? -ne "0" ]; then
+       echo $msg
+       exit 1
+    fi
+
+    msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \
+        skip=$system_reset_overlay seek=$overlay_dest     \
+        count=$overlay_size bs=1 2>&1)
+
+    if [ $? -ne "0" ]; then
+       echo $msg
+       exit 2
+    fi
+
+    gzip --force -9 --stdout "$ofile.bin" > "$object/otheros.bld"
+    ;;
 esac
diff --git a/arch/powerpc/boot/zImage.ps3.lds.S b/arch/powerpc/boot/zImage.ps3.lds.S
new file mode 100644 (file)
index 0000000..aaa469c
--- /dev/null
@@ -0,0 +1,50 @@
+OUTPUT_ARCH(powerpc:common)
+ENTRY(_zimage_start)
+EXTERN(_zimage_start)
+SECTIONS
+{
+  _vmlinux_start =  .;
+  .kernel:vmlinux.bin : { *(.kernel:vmlinux.bin) }
+  _vmlinux_end =  .;
+
+  . = ALIGN(4096);
+  _dtb_start = .;
+  .kernel:dtb : { *(.kernel:dtb) }
+  _dtb_end = .;
+
+  . = ALIGN(4096);
+  _initrd_start =  .;
+  .kernel:initrd : { *(.kernel:initrd) }
+  _initrd_end =  .;
+
+  _start = .;
+  .text      :
+  {
+    *(.text)
+    *(.fixup)
+  }
+  _etext = .;
+  . = ALIGN(4096);
+  .data    :
+  {
+    *(.rodata*)
+    *(.data*)
+    *(.sdata*)
+    __got2_start = .;
+    *(.got2)
+    __got2_end = .;
+  }
+
+  . = ALIGN(4096);
+  _edata  =  .;
+
+  . = ALIGN(4096);
+  __bss_start = .;
+  .bss       :
+  {
+   *(.sbss)
+   *(.bss)
+  }
+  . = ALIGN(4096);
+  _end = . ;
+}
index 32781849ad4c608b541596520c390031b0387a4f..04b94f884aae113a2ebb7167dac866386f5bffc2 100644 (file)
@@ -190,10 +190,12 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_PROC_DEVICETREE=y
-# CONFIG_CMDLINE_BOOL is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,115200"
 # CONFIG_PM is not set
 # CONFIG_SECCOMP is not set
-# CONFIG_WANT_DEVICE_TREE is not set
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE="holly.dts"
 CONFIG_ISA_DMA_API=y
 
 #
index 956d1df61e0fab9ab866877b563e60e0ff7860bc..d0b43df444267a7696d7a0e9206461db66e4a8e2 100644 (file)
@@ -156,7 +156,11 @@ CONFIG_PS3_HTAB_SIZE=20
 CONFIG_PS3_USE_LPAR_ADDR=y
 CONFIG_PS3_VUART=y
 CONFIG_PS3_PS3AV=y
-CONFIG_PS3_SYS_MANAGER=y
+CONFIG_PS3_SYS_MANAGER=m
+CONFIG_PS3_STORAGE=y
+CONFIG_PS3_DISK=y
+CONFIG_PS3_ROM=y
+CONFIG_PS3_FLASH=y
 CONFIG_PPC_CELL=y
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_IBM_CELL_BLADE is not set
@@ -335,7 +339,7 @@ CONFIG_BT=m
 CONFIG_BT_L2CAP=m
 CONFIG_BT_SCO=m
 CONFIG_BT_RFCOMM=m
-# CONFIG_BT_RFCOMM_TTY is not set
+CONFIG_BT_RFCOMM_TTY=y
 # CONFIG_BT_BNEP is not set
 CONFIG_BT_HIDP=m
 
@@ -344,7 +348,9 @@ CONFIG_BT_HIDP=m
 #
 CONFIG_BT_HCIUSB=m
 CONFIG_BT_HCIUSB_SCO=y
-# CONFIG_BT_HCIUART is not set
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
 # CONFIG_BT_HCIBCM203X is not set
 # CONFIG_BT_HCIBPA10X is not set
 # CONFIG_BT_HCIBFUSB is not set
@@ -435,7 +441,7 @@ CONFIG_CHR_DEV_SG=m
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
-# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
@@ -479,6 +485,7 @@ CONFIG_NETDEVICES=y
 CONFIG_MII=m
 CONFIG_NETDEV_1000=y
 CONFIG_NETDEV_10000=y
+CONFIG_GELIC_NET=y
 
 #
 # Wireless LAN
@@ -546,7 +553,27 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 #
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_JOYSTICK=y
+# CONFIG_JOYSTICK_ANALOG is not set
+# CONFIG_JOYSTICK_A3D is not set
+# CONFIG_JOYSTICK_ADI is not set
+# CONFIG_JOYSTICK_COBRA is not set
+# CONFIG_JOYSTICK_GF2K is not set
+# CONFIG_JOYSTICK_GRIP is not set
+# CONFIG_JOYSTICK_GRIP_MP is not set
+# CONFIG_JOYSTICK_GUILLEMOT is not set
+# CONFIG_JOYSTICK_INTERACT is not set
+# CONFIG_JOYSTICK_SIDEWINDER is not set
+# CONFIG_JOYSTICK_TMDC is not set
+# CONFIG_JOYSTICK_IFORCE is not set
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_TWIDJOY is not set
+# CONFIG_JOYSTICK_JOYDUMP is not set
+# CONFIG_JOYSTICK_XPAD is not set
 # CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
@@ -563,7 +590,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
-# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -1086,7 +1113,7 @@ CONFIG_HAS_DMA=y
 #
 # CONFIG_PRINTK_TIME is not set
 CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
@@ -1116,16 +1143,7 @@ CONFIG_DEBUG_STACKOVERFLOW=y
 # CONFIG_DEBUGGER is not set
 CONFIG_IRQSTACKS=y
 # CONFIG_BOOTX_TEXT is not set
-CONFIG_PPC_EARLY_DEBUG=y
-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
-# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
-# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
-# CONFIG_PPC_EARLY_DEBUG_44x is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
 
 #
 # Security options
index 3e779f07f21b0819801b946f2e66231c7eaf605c..42c42ecad00c16bb82c6e4a325bc92230c1a909a 100644 (file)
@@ -12,7 +12,8 @@ endif
 
 obj-y                          := semaphore.o cputable.o ptrace.o syscalls.o \
                                   irq.o align.o signal_32.o pmc.o vdso.o \
-                                  init_task.o process.o systbl.o idle.o
+                                  init_task.o process.o systbl.o idle.o \
+                                  signal.o
 obj-y                          += vdso32/
 obj-$(CONFIG_PPC64)            += setup_64.o binfmt_elf32.o sys_ppc32.o \
                                   signal_64.o ptrace32.o \
@@ -65,9 +66,9 @@ obj-$(CONFIG_PPC_UDBG_16550)  += legacy_serial.o udbg_16550.o
 module-$(CONFIG_PPC64)         += module_64.o
 obj-$(CONFIG_MODULES)          += $(module-y)
 
-pci64-$(CONFIG_PPC64)          += pci_64.o pci_dn.o
+pci64-$(CONFIG_PPC64)          += pci_64.o pci_dn.o isa-bridge.o
 pci32-$(CONFIG_PPC32)          := pci_32.o
-obj-$(CONFIG_PCI)              += $(pci64-y) $(pci32-y)
+obj-$(CONFIG_PCI)              += $(pci64-y) $(pci32-y) pci-common.o
 obj-$(CONFIG_PCI_MSI)          += msi.o
 kexec-$(CONFIG_PPC64)          := machine_kexec_64.o
 kexec-$(CONFIG_PPC32)          := machine_kexec_32.o
index b2b5d664d32861f2c71b699e917dd70f07f412f3..b1f8000952f3460912a65206cd44dd064884c614 100644 (file)
@@ -294,6 +294,21 @@ static struct cpu_spec cpu_specs[] = {
                .oprofile_mmcra_sipr    = MMCRA_SIPR,
                .platform               = "power5",
        },
+       {       /* Power5++ */
+               .pvr_mask               = 0xffffff00,
+               .pvr_value              = 0x003b0300,
+               .cpu_name               = "POWER5+ (gs)",
+               .cpu_features           = CPU_FTRS_POWER5,
+               .cpu_user_features      = COMMON_USER_POWER5_PLUS,
+               .icache_bsize           = 128,
+               .dcache_bsize           = 128,
+               .num_pmcs               = 6,
+               .oprofile_cpu_type      = "ppc64/power5++",
+               .oprofile_type          = PPC_OPROFILE_POWER4,
+               .oprofile_mmcra_sihv    = MMCRA_SIHV,
+               .oprofile_mmcra_sipr    = MMCRA_SIPR,
+               .platform               = "power5+",
+       },
        {       /* Power5 GS */
                .pvr_mask               = 0xffff0000,
                .pvr_value              = 0x003b0000,
@@ -1178,8 +1193,8 @@ static struct cpu_spec cpu_specs[] = {
                .platform               = "ppc440",
        },
        { /* 440SP Rev. A */
-               .pvr_mask               = 0xff000fff,
-               .pvr_value              = 0x53000891,
+               .pvr_mask               = 0xfff00fff,
+               .pvr_value              = 0x53200891,
                .cpu_name               = "440SP Rev. A",
                .cpu_features           = CPU_FTRS_44X,
                .cpu_user_features      = COMMON_USER_BOOKE,
@@ -1188,9 +1203,19 @@ static struct cpu_spec cpu_specs[] = {
                .platform               = "ppc440",
        },
        { /* 440SPe Rev. A */
-               .pvr_mask               = 0xff000fff,
-               .pvr_value              = 0x53000890,
-               .cpu_name               = "440SPe Rev. A",
+               .pvr_mask               = 0xfff00fff,
+               .pvr_value              = 0x53400890,
+               .cpu_name               = "440SPe Rev. A",
+               .cpu_features           = CPU_FTRS_44X,
+               .cpu_user_features      = COMMON_USER_BOOKE,
+               .icache_bsize           = 32,
+               .dcache_bsize           = 32,
+               .platform               = "ppc440",
+       },
+       { /* 440SPe Rev. B */
+               .pvr_mask               = 0xfff00fff,
+               .pvr_value              = 0x53400891,
+               .cpu_name               = "440SPe Rev. B",
                .cpu_features           = CPU_FTRS_44X,
                .cpu_user_features      = COMMON_USER_BOOKE,
                .icache_bsize           = 32,
index c897203198b1a1bd6a4cfc8f663f8267061eed34..7d73a13450b060b37623176df2d2f455476c758f 100644 (file)
@@ -9,7 +9,6 @@
  *  rewritten by Paul Mackerras.
  *    Copyright (C) 1996 Paul Mackerras.
  *  MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  This file contains the low-level support and setup for the
  *  PowerPC platform, including trap and interrupt dispatch.
 #include <asm/ppc_asm.h>
 #include <asm/asm-offsets.h>
 
-#ifdef CONFIG_APUS
-#include <asm/amigappc.h>
-#endif
-
 /* 601 only have IBAT; cr0.eq is set on 601 when using this macro */
 #define LOAD_BAT(n, reg, RA, RB)       \
        /* see the comment for clear_bats() -- Cort */ \
@@ -92,11 +87,6 @@ _start:
  *  r4: virtual address of boot_infos_t
  *  r5: 0
  *
- * APUS
- *   r3: 'APUS'
- *   r4: physical address of memory base
- *   Linux/m68k style BootInfo structure at &_end.
- *
  * PREP
  * This is jumped to on prep systems right after the kernel is relocated
  * to its proper place in memory by the boot loader.  The expected layout
@@ -150,14 +140,6 @@ __start:
  */
        bl      early_init
 
-#ifdef CONFIG_APUS
-/* On APUS the __va/__pa constants need to be set to the correct
- * values before continuing.
- */
-       mr      r4,r30
-       bl      fix_mem_constants
-#endif /* CONFIG_APUS */
-
 /* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains
  * the physical address we are running at, returned by early_init()
  */
@@ -167,7 +149,7 @@ __after_mmu_off:
        bl      flush_tlbs
 
        bl      initial_bats
-#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
+#if defined(CONFIG_BOOTX_TEXT)
        bl      setup_disp_bat
 #endif
 
@@ -183,7 +165,6 @@ __after_mmu_off:
 #endif /* CONFIG_6xx */
 
 
-#ifndef CONFIG_APUS
 /*
  * We need to run with _start at physical address 0.
  * On CHRP, we are loaded at 0x10000 since OF on CHRP uses
@@ -196,7 +177,6 @@ __after_mmu_off:
        addis   r4,r3,KERNELBASE@h      /* current address of _start */
        cmpwi   0,r4,0                  /* are we already running at 0? */
        bne     relocate_kernel
-#endif /* CONFIG_APUS */
 /*
  * we now have the 1st 16M of ram mapped with the bats.
  * prep needs the mmu to be turned on here, but pmac already has it on.
@@ -881,85 +861,6 @@ _GLOBAL(copy_and_flush)
        addi    r6,r6,4
        blr
 
-#ifdef CONFIG_APUS
-/*
- * On APUS the physical base address of the kernel is not known at compile
- * time, which means the __pa/__va constants used are incorrect. In the
- * __init section is recorded the virtual addresses of instructions using
- * these constants, so all that has to be done is fix these before
- * continuing the kernel boot.
- *
- * r4 = The physical address of the kernel base.
- */
-fix_mem_constants:
-       mr      r10,r4
-       addis   r10,r10,-KERNELBASE@h    /* virt_to_phys constant */
-       neg     r11,r10                  /* phys_to_virt constant */
-
-       lis     r12,__vtop_table_begin@h
-       ori     r12,r12,__vtop_table_begin@l
-       add     r12,r12,r10              /* table begin phys address */
-       lis     r13,__vtop_table_end@h
-       ori     r13,r13,__vtop_table_end@l
-       add     r13,r13,r10              /* table end phys address */
-       subi    r12,r12,4
-       subi    r13,r13,4
-1:     lwzu    r14,4(r12)               /* virt address of instruction */
-       add     r14,r14,r10              /* phys address of instruction */
-       lwz     r15,0(r14)               /* instruction, now insert top */
-       rlwimi  r15,r10,16,16,31         /* half of vp const in low half */
-       stw     r15,0(r14)               /* of instruction and restore. */
-       dcbst   r0,r14                   /* write it to memory */
-       sync
-       icbi    r0,r14                   /* flush the icache line */
-       cmpw    r12,r13
-       bne     1b
-       sync                            /* additional sync needed on g4 */
-       isync
-
-/*
- * Map the memory where the exception handlers will
- * be copied to when hash constants have been patched.
- */
-#ifdef CONFIG_APUS_FAST_EXCEPT
-       lis     r8,0xfff0
-#else
-       lis     r8,0
-#endif
-       ori     r8,r8,0x2               /* 128KB, supervisor */
-       mtspr   SPRN_DBAT3U,r8
-       mtspr   SPRN_DBAT3L,r8
-
-       lis     r12,__ptov_table_begin@h
-       ori     r12,r12,__ptov_table_begin@l
-       add     r12,r12,r10              /* table begin phys address */
-       lis     r13,__ptov_table_end@h
-       ori     r13,r13,__ptov_table_end@l
-       add     r13,r13,r10              /* table end phys address */
-       subi    r12,r12,4
-       subi    r13,r13,4
-1:     lwzu    r14,4(r12)               /* virt address of instruction */
-       add     r14,r14,r10              /* phys address of instruction */
-       lwz     r15,0(r14)               /* instruction, now insert top */
-       rlwimi  r15,r11,16,16,31         /* half of pv const in low half*/
-       stw     r15,0(r14)               /* of instruction and restore. */
-       dcbst   r0,r14                   /* write it to memory */
-       sync
-       icbi    r0,r14                   /* flush the icache line */
-       cmpw    r12,r13
-       bne     1b
-
-       sync                            /* additional sync needed on g4 */
-       isync                           /* No speculative loading until now */
-       blr
-
-/***********************************************************************
- *  Please note that on APUS the exception handlers are located at the
- *  physical address 0xfff0000. For this reason, the exception handlers
- *  cannot use relative branches to access the code below.
- ***********************************************************************/
-#endif /* CONFIG_APUS */
-
 #ifdef CONFIG_SMP
 #ifdef CONFIG_GEMINI
        .globl  __secondary_start_gemini
@@ -1135,19 +1036,6 @@ start_here:
        bl      __save_cpu_setup
        bl      MMU_init
 
-#ifdef CONFIG_APUS
-       /* Copy exception code to exception vector base on APUS. */
-       lis     r4,KERNELBASE@h
-#ifdef CONFIG_APUS_FAST_EXCEPT
-       lis     r3,0xfff0               /* Copy to 0xfff00000 */
-#else
-       lis     r3,0                    /* Copy to 0x00000000 */
-#endif
-       li      r5,0x4000               /* # bytes of memory to copy */
-       li      r6,0
-       bl      copy_and_flush          /* copy the first 0x4000 bytes */
-#endif  /* CONFIG_APUS */
-
 /*
  * Go back to running unmapped so we can load up new values
  * for SDR1 (hash table pointer) and the segment registers
@@ -1324,11 +1212,7 @@ initial_bats:
 #else
        ori     r8,r8,2                 /* R/W access */
 #endif /* CONFIG_SMP */
-#ifdef CONFIG_APUS
-       ori     r11,r11,BL_8M<<2|0x2    /* set up 8MB BAT registers for 604 */
-#else
        ori     r11,r11,BL_256M<<2|0x2  /* set up BAT registers for 604 */
-#endif /* CONFIG_APUS */
 
        mtspr   SPRN_DBAT0L,r8          /* N.B. 6xx (not 601) have valid */
        mtspr   SPRN_DBAT0U,r11         /* bit in upper BAT register */
@@ -1338,7 +1222,7 @@ initial_bats:
        blr
 
 
-#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
+#ifdef CONFIG_BOOTX_TEXT
 setup_disp_bat:
        /*
         * setup the display bat prepared for us in prom.c
@@ -1362,7 +1246,7 @@ setup_disp_bat:
 1:     mtspr   SPRN_IBAT3L,r8
        mtspr   SPRN_IBAT3U,r11
        blr
-#endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */
+#endif /* CONFIG_BOOTX_TEXT */
 
 #ifdef CONFIG_8260
 /* Jump into the system reset for the rom.
index 1111fcec7673be71b6dd860a669886154d66a3c9..8cdd48ea43912d7a39c5d82c34432787a67f30b2 100644 (file)
@@ -103,8 +103,8 @@ __secondary_hold_acknowledge:
 
        . = 0x60
 /*
- * The following code is used on pSeries to hold secondary processors
- * in a spin loop after they have been freed from OpenFirmware, but
+ * The following code is used to hold secondary processors
+ * in a spin loop after they have entered the kernel, but
  * before the bulk of the kernel has been relocated.  This code
  * is relocated to physical address 0x60 before prom_init is run.
  * All of it must fit below the first exception vector at 0x100.
index 34ae11494ddcd96d0b27a8f961ff2b8d6d166041..e31aca9208eba4a7cc711f52fdb5c755829fe0dc 100644 (file)
@@ -35,7 +35,7 @@ void _insb(const volatile u8 __iomem *port, void *buf, long count)
        asm volatile("sync");
        do {
                tmp = *port;
-               asm volatile("eieio");
+               eieio();
                *tbuf++ = tmp;
        } while (--count != 0);
        asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
@@ -66,7 +66,7 @@ void _insw_ns(const volatile u16 __iomem *port, void *buf, long count)
        asm volatile("sync");
        do {
                tmp = *port;
-               asm volatile("eieio");
+               eieio();
                *tbuf++ = tmp;
        } while (--count != 0);
        asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
@@ -97,7 +97,7 @@ void _insl_ns(const volatile u32 __iomem *port, void *buf, long count)
        asm volatile("sync");
        do {
                tmp = *port;
-               asm volatile("eieio");
+               eieio();
                *tbuf++ = tmp;
        } while (--count != 0);
        asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
@@ -155,21 +155,21 @@ void _memcpy_fromio(void *dest, const volatile void __iomem *src,
        __asm__ __volatile__ ("sync" : : : "memory");
        while(n && (!IO_CHECK_ALIGN(vsrc, 4) || !IO_CHECK_ALIGN(dest, 4))) {
                *((u8 *)dest) = *((volatile u8 *)vsrc);
-               __asm__ __volatile__ ("eieio" : : : "memory");
+               eieio();
                vsrc++;
                dest++;
                n--;
        }
        while(n > 4) {
                *((u32 *)dest) = *((volatile u32 *)vsrc);
-               __asm__ __volatile__ ("eieio" : : : "memory");
+               eieio();
                vsrc += 4;
                dest += 4;
                n -= 4;
        }
        while(n) {
                *((u8 *)dest) = *((volatile u8 *)vsrc);
-               __asm__ __volatile__ ("eieio" : : : "memory");
+               eieio();
                vsrc++;
                dest++;
                n--;
index c2b84c64db20ed16a01472c4a9f8f58fab2c7d1b..2fc87862146cbd68048c0d2307a5eb6b626de086 100644 (file)
@@ -7,7 +7,6 @@
  *    Copyright (C) 1996-2001 Cort Dougan
  *  Adapted for Power Macintosh by Paul Mackerras
  *    Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -337,7 +336,8 @@ void do_IRQ(struct pt_regs *regs)
 
 void __init init_IRQ(void)
 {
-       ppc_md.init_IRQ();
+       if (ppc_md.init_IRQ)
+               ppc_md.init_IRQ();
 #ifdef CONFIG_PPC64
        irq_ctx_init();
 #endif
@@ -597,6 +597,49 @@ static void irq_radix_rdunlock(unsigned long flags)
        local_irq_restore(flags);
 }
 
+static int irq_setup_virq(struct irq_host *host, unsigned int virq,
+                           irq_hw_number_t hwirq)
+{
+       /* Clear IRQ_NOREQUEST flag */
+       get_irq_desc(virq)->status &= ~IRQ_NOREQUEST;
+
+       /* map it */
+       smp_wmb();
+       irq_map[virq].hwirq = hwirq;
+       smp_mb();
+
+       if (host->ops->map(host, virq, hwirq)) {
+               pr_debug("irq: -> mapping failed, freeing\n");
+               irq_free_virt(virq, 1);
+               return -1;
+       }
+
+       return 0;
+}
+
+unsigned int irq_create_direct_mapping(struct irq_host *host)
+{
+       unsigned int virq;
+
+       if (host == NULL)
+               host = irq_default_host;
+
+       BUG_ON(host == NULL);
+       WARN_ON(host->revmap_type != IRQ_HOST_MAP_NOMAP);
+
+       virq = irq_alloc_virt(host, 1, 0);
+       if (virq == NO_IRQ) {
+               pr_debug("irq: create_direct virq allocation failed\n");
+               return NO_IRQ;
+       }
+
+       pr_debug("irq: create_direct obtained virq %d\n", virq);
+
+       if (irq_setup_virq(host, virq, virq))
+               return NO_IRQ;
+
+       return virq;
+}
 
 unsigned int irq_create_mapping(struct irq_host *host,
                                irq_hw_number_t hwirq)
@@ -645,18 +688,9 @@ unsigned int irq_create_mapping(struct irq_host *host,
        }
        pr_debug("irq: -> obtained virq %d\n", virq);
 
-       /* Clear IRQ_NOREQUEST flag */
-       get_irq_desc(virq)->status &= ~IRQ_NOREQUEST;
-
-       /* map it */
-       smp_wmb();
-       irq_map[virq].hwirq = hwirq;
-       smp_mb();
-       if (host->ops->map(host, virq, hwirq)) {
-               pr_debug("irq: -> mapping failed, freeing\n");
-               irq_free_virt(virq, 1);
+       if (irq_setup_virq(host, virq, hwirq))
                return NO_IRQ;
-       }
+
        return virq;
 }
 EXPORT_SYMBOL_GPL(irq_create_mapping);
diff --git a/arch/powerpc/kernel/isa-bridge.c b/arch/powerpc/kernel/isa-bridge.c
new file mode 100644 (file)
index 0000000..f0f49d1
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * Routines for tracking a legacy ISA bridge
+ *
+ * Copyrigh 2007 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
+ *
+ * Some bits and pieces moved over from pci_64.c
+ *
+ * Copyrigh 2003 Anton Blanchard <anton@au.ibm.com>, IBM Corp.
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+#define DEBUG
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/notifier.h>
+
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/ppc-pci.h>
+#include <asm/firmware.h>
+
+unsigned long isa_io_base;     /* NULL if no ISA bus */
+EXPORT_SYMBOL(isa_io_base);
+
+/* Cached ISA bridge dev. */
+static struct device_node *isa_bridge_devnode;
+struct pci_dev *isa_bridge_pcidev;
+EXPORT_SYMBOL_GPL(isa_bridge_pcidev);
+
+#define ISA_SPACE_MASK 0x1
+#define ISA_SPACE_IO 0x1
+
+static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
+                                               unsigned long phb_io_base_phys)
+{
+       /* We should get some saner parsing here and remove these structs */
+       struct pci_address {
+               u32 a_hi;
+               u32 a_mid;
+               u32 a_lo;
+       };
+
+       struct isa_address {
+               u32 a_hi;
+               u32 a_lo;
+       };
+
+       struct isa_range {
+               struct isa_address isa_addr;
+               struct pci_address pci_addr;
+               unsigned int size;
+       };
+
+       const struct isa_range *range;
+       unsigned long pci_addr;
+       unsigned int isa_addr;
+       unsigned int size;
+       int rlen = 0;
+
+       range = of_get_property(isa_node, "ranges", &rlen);
+       if (range == NULL || (rlen < sizeof(struct isa_range)))
+               goto inval_range;
+
+       /* From "ISA Binding to 1275"
+        * The ranges property is laid out as an array of elements,
+        * each of which comprises:
+        *   cells 0 - 1:       an ISA address
+        *   cells 2 - 4:       a PCI address
+        *                      (size depending on dev->n_addr_cells)
+        *   cell 5:            the size of the range
+        */
+       if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO) {
+               range++;
+               rlen -= sizeof(struct isa_range);
+               if (rlen < sizeof(struct isa_range))
+                       goto inval_range;
+       }
+       if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO)
+               goto inval_range;
+
+       isa_addr = range->isa_addr.a_lo;
+       pci_addr = (unsigned long) range->pci_addr.a_mid << 32 |
+               range->pci_addr.a_lo;
+
+       /* Assume these are both zero. Note: We could fix that and
+        * do a proper parsing instead ... oh well, that will do for
+        * now as nobody uses fancy mappings for ISA bridges
+        */
+       if ((pci_addr != 0) || (isa_addr != 0)) {
+               printk(KERN_ERR "unexpected isa to pci mapping: %s\n",
+                      __FUNCTION__);
+               return;
+       }
+
+       /* Align size and make sure it's cropped to 64K */
+       size = PAGE_ALIGN(range->size);
+       if (size > 0x10000)
+               size = 0x10000;
+
+       printk(KERN_ERR "no ISA IO ranges or unexpected isa range,"
+              "mapping 64k\n");
+
+       __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
+                    size, _PAGE_NO_CACHE|_PAGE_GUARDED);
+       return;
+
+inval_range:
+       printk(KERN_ERR "no ISA IO ranges or unexpected isa range,"
+              "mapping 64k\n");
+       __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
+                    0x10000, _PAGE_NO_CACHE|_PAGE_GUARDED);
+}
+
+
+/**
+ * isa_bridge_find_early - Find and map the ISA IO space early before
+ *                         main PCI discovery. This is optionally called by
+ *                         the arch code when adding PCI PHBs to get early
+ *                         access to ISA IO ports
+ */
+void __init isa_bridge_find_early(struct pci_controller *hose)
+{
+       struct device_node *np, *parent = NULL, *tmp;
+
+       /* If we already have an ISA bridge, bail off */
+       if (isa_bridge_devnode != NULL)
+               return;
+
+       /* For each "isa" node in the system. Note : we do a search by
+        * type and not by name. It might be better to do by name but that's
+        * what the code used to do and I don't want to break too much at
+        * once. We can look into changing that separately
+        */
+       for_each_node_by_type(np, "isa") {
+               /* Look for our hose being a parent */
+               for (parent = of_get_parent(np); parent;) {
+                       if (parent == hose->arch_data) {
+                               of_node_put(parent);
+                               break;
+                       }
+                       tmp = parent;
+                       parent = of_get_parent(parent);
+                       of_node_put(tmp);
+               }
+               if (parent != NULL)
+                       break;
+       }
+       if (np == NULL)
+               return;
+       isa_bridge_devnode = np;
+
+       /* Now parse the "ranges" property and setup the ISA mapping */
+       pci_process_ISA_OF_ranges(np, hose->io_base_phys);
+
+       /* Set the global ISA io base to indicate we have an ISA bridge */
+       isa_io_base = ISA_IO_BASE;
+
+       pr_debug("ISA bridge (early) is %s\n", np->full_name);
+}
+
+/**
+ * isa_bridge_find_late - Find and map the ISA IO space upon discovery of
+ *                        a new ISA bridge
+ */
+static void __devinit isa_bridge_find_late(struct pci_dev *pdev,
+                                          struct device_node *devnode)
+{
+       struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+
+       /* Store ISA device node and PCI device */
+       isa_bridge_devnode = of_node_get(devnode);
+       isa_bridge_pcidev = pdev;
+
+       /* Now parse the "ranges" property and setup the ISA mapping */
+       pci_process_ISA_OF_ranges(devnode, hose->io_base_phys);
+
+       /* Set the global ISA io base to indicate we have an ISA bridge */
+       isa_io_base = ISA_IO_BASE;
+
+       pr_debug("ISA bridge (late) is %s on %s\n",
+                devnode->full_name, pci_name(pdev));
+}
+
+/**
+ * isa_bridge_remove - Remove/unmap an ISA bridge
+ */
+static void isa_bridge_remove(void)
+{
+       pr_debug("ISA bridge removed !\n");
+
+       /* Clear the global ISA io base to indicate that we have no more
+        * ISA bridge. Note that drivers don't quite handle that, though
+        * we should probably do something about it. But do we ever really
+        * have ISA bridges being removed on machines using legacy devices ?
+        */
+       isa_io_base = ISA_IO_BASE;
+
+       /* Clear references to the bridge */
+       of_node_put(isa_bridge_devnode);
+       isa_bridge_devnode = NULL;
+       isa_bridge_pcidev = NULL;
+
+       /* Unmap the ISA area */
+       __iounmap_at((void *)ISA_IO_BASE, 0x10000);
+}
+
+/**
+ * isa_bridge_notify - Get notified of PCI devices addition/removal
+ */
+static int __devinit isa_bridge_notify(struct notifier_block *nb,
+                                      unsigned long action, void *data)
+{
+       struct device *dev = data;
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct device_node *devnode = pci_device_to_OF_node(pdev);
+
+       switch(action) {
+       case BUS_NOTIFY_ADD_DEVICE:
+               /* Check if we have an early ISA device, without PCI dev */
+               if (isa_bridge_devnode && isa_bridge_devnode == devnode &&
+                   !isa_bridge_pcidev) {
+                       pr_debug("ISA bridge PCI attached: %s\n",
+                                pci_name(pdev));
+                       isa_bridge_pcidev = pdev;
+               }
+
+               /* Check if we have no ISA device, and this happens to be one,
+                * register it as such if it has an OF device
+                */
+               if (!isa_bridge_devnode && devnode && devnode->type &&
+                   !strcmp(devnode->type, "isa"))
+                       isa_bridge_find_late(pdev, devnode);
+
+               return 0;
+       case BUS_NOTIFY_DEL_DEVICE:
+               /* Check if this our existing ISA device */
+               if (pdev == isa_bridge_pcidev ||
+                   (devnode && devnode == isa_bridge_devnode))
+                       isa_bridge_remove();
+               return 0;
+       }
+       return 0;
+}
+
+static struct notifier_block isa_bridge_notifier = {
+       .notifier_call = isa_bridge_notify
+};
+
+/**
+ * isa_bridge_init - register to be notified of ISA bridge addition/removal
+ *
+ */
+static int __init isa_bridge_init(void)
+{
+       if (firmware_has_feature(FW_FEATURE_ISERIES))
+               return 0;
+       bus_register_notifier(&pci_bus_type, &isa_bridge_notifier);
+       return 0;
+}
+arch_initcall(isa_bridge_init);
index 98decf8ebff44831dae7704fa431beca76a87cbb..e708ab7ca9e845968a6b71d910ecbaaa3f64c6e2 100644 (file)
@@ -392,7 +392,7 @@ BEGIN_FTR_SECTION
        mtspr   SPRN_L1CSR0,r3
        isync
        blr
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE)
        mfspr   r3,SPRN_L1CSR1
        ori     r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
        mtspr   SPRN_L1CSR1,r3
@@ -419,7 +419,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
 _GLOBAL(__flush_icache_range)
 BEGIN_FTR_SECTION
        blr                             /* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
        li      r5,L1_CACHE_BYTES-1
        andc    r3,r3,r5
        subf    r4,r3,r4
@@ -514,8 +514,8 @@ _GLOBAL(invalidate_dcache_range)
  */
 _GLOBAL(__flush_dcache_icache)
 BEGIN_FTR_SECTION
-       blr                                     /* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+       blr
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
        rlwinm  r3,r3,0,0,19                    /* Get page base address */
        li      r4,4096/L1_CACHE_BYTES  /* Number of lines in a page */
        mtctr   r4
@@ -543,7 +543,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
 _GLOBAL(__flush_dcache_icache_phys)
 BEGIN_FTR_SECTION
        blr                                     /* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
        mfmsr   r10
        rlwinm  r0,r10,0,28,26                  /* clear DR */
        mtmsr   r0
index 519861da04235c2fc3a3ba13c9326f02a5af629f..bbb3ba54c51c7b331c7ce2469361b4991a02cd1e 100644 (file)
@@ -646,6 +646,19 @@ _GLOBAL(kexec_sequence)
        /* turn off mmu */
        bl      real_mode
 
+       /* copy  0x100 bytes starting at start to 0 */
+       li      r3,0
+       mr      r4,r30          /* start, aka phys mem offset */
+       li      r5,0x100
+       li      r6,0
+       bl      .copy_and_flush /* (dest, src, copy limit, start offset) */
+1:     /* assume normal blr return */
+
+       /* release other cpus to the new kernel secondary start at 0x60 */
+       mflr    r5
+       li      r6,1
+       stw     r6,kexec_flag-1b(5)
+
        /* clear out hardware hash page table and tlb */
        ld      r5,0(r27)               /* deref function descriptor */
        mtctr   r5
@@ -676,19 +689,6 @@ _GLOBAL(kexec_sequence)
  *    are the boot cpu ?????
  *    other device tree differences (prop sizes, va vs pa, etc)...
  */
-
-       /* copy  0x100 bytes starting at start to 0 */
-       li      r3,0
-       mr      r4,r30
-       li      r5,0x100
-       li      r6,0
-       bl      .copy_and_flush /* (dest, src, copy limit, start offset) */
-1:     /* assume normal blr return */
-
-       /* release other cpus to the new kernel secondary start at 0x60 */
-       mflr    r5
-       li      r6,1
-       stw     r6,kexec_flag-1b(5)
        mr      r3,r25  # my phys cpu
        mr      r4,r30  # start, aka phys mem offset
        mtlr    4
index d454f61c9c7c7b5a84c00ef3f66b730e436171ee..9536ed7f247cebbdcfbc7c4f1bffaccd65d707b3 100644 (file)
@@ -427,14 +427,6 @@ static int __devinit of_pci_phb_probe(struct of_device *dev,
        /* Process "ranges" property */
        pci_process_bridge_OF_ranges(phb, dev->node, 0);
 
-       /* Setup IO space. We use the non-dynamic version of that code here,
-        * which doesn't quite support unplugging. Next kernel release will
-        * have a better fix for this.
-        * Note also that we don't do ISA, this will also be fixed with a
-        * more massive rework.
-        */
-       pci_setup_phb_io(phb, pci_io_base == 0);
-
        /* Init pci_dn data structures */
        pci_devs_phb_init_dynamic(phb);
 
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
new file mode 100644 (file)
index 0000000..faf5ef3
--- /dev/null
@@ -0,0 +1,454 @@
+/*
+ * Contains common pci routines for ALL ppc platform
+ * (based on pci_32.c and pci_64.c)
+ *
+ * Port for PPC64 David Engebretsen, IBM Corp.
+ * Contains common pci routines for ppc64 platform, pSeries and iSeries brands.
+ *
+ * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM
+ *   Rework, based on alpha PCI code.
+ *
+ * Common pmac/prep/chrp pci routines. -- Cort
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/syscalls.h>
+#include <linux/irq.h>
+#include <linux/vmalloc.h>
+
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/byteorder.h>
+#include <asm/machdep.h>
+#include <asm/ppc-pci.h>
+#include <asm/firmware.h>
+
+#ifdef DEBUG
+#include <asm/udbg.h>
+#define DBG(fmt...) printk(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+static DEFINE_SPINLOCK(hose_spinlock);
+
+/* XXX kill that some day ... */
+int global_phb_number;         /* Global phb counter */
+
+extern struct list_head hose_list;
+
+/*
+ * pci_controller(phb) initialized common variables.
+ */
+static void __devinit pci_setup_pci_controller(struct pci_controller *hose)
+{
+       memset(hose, 0, sizeof(struct pci_controller));
+
+       spin_lock(&hose_spinlock);
+       hose->global_number = global_phb_number++;
+       list_add_tail(&hose->list_node, &hose_list);
+       spin_unlock(&hose_spinlock);
+}
+
+struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
+{
+       struct pci_controller *phb;
+
+       if (mem_init_done)
+               phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
+       else
+               phb = alloc_bootmem(sizeof (struct pci_controller));
+       if (phb == NULL)
+               return NULL;
+       pci_setup_pci_controller(phb);
+       phb->arch_data = dev;
+       phb->is_dynamic = mem_init_done;
+#ifdef CONFIG_PPC64
+       if (dev) {
+               int nid = of_node_to_nid(dev);
+
+               if (nid < 0 || !node_online(nid))
+                       nid = -1;
+
+               PHB_SET_NODE(phb, nid);
+       }
+#endif
+       return phb;
+}
+
+void pcibios_free_controller(struct pci_controller *phb)
+{
+       spin_lock(&hose_spinlock);
+       list_del(&phb->list_node);
+       spin_unlock(&hose_spinlock);
+
+       if (phb->is_dynamic)
+               kfree(phb);
+}
+
+/*
+ * Return the domain number for this bus.
+ */
+int pci_domain_nr(struct pci_bus *bus)
+{
+       if (firmware_has_feature(FW_FEATURE_ISERIES))
+               return 0;
+       else {
+               struct pci_controller *hose = pci_bus_to_host(bus);
+
+               return hose->global_number;
+       }
+}
+
+EXPORT_SYMBOL(pci_domain_nr);
+
+#ifdef CONFIG_PPC_OF
+
+/* This routine is meant to be used early during boot, when the
+ * PCI bus numbers have not yet been assigned, and you need to
+ * issue PCI config cycles to an OF device.
+ * It could also be used to "fix" RTAS config cycles if you want
+ * to set pci_assign_all_buses to 1 and still use RTAS for PCI
+ * config cycles.
+ */
+struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
+{
+       if (!have_of)
+               return NULL;
+       while(node) {
+               struct pci_controller *hose, *tmp;
+               list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+                       if (hose->arch_data == node)
+                               return hose;
+               node = node->parent;
+       }
+       return NULL;
+}
+
+static ssize_t pci_show_devspec(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct pci_dev *pdev;
+       struct device_node *np;
+
+       pdev = to_pci_dev (dev);
+       np = pci_device_to_OF_node(pdev);
+       if (np == NULL || np->full_name == NULL)
+               return 0;
+       return sprintf(buf, "%s", np->full_name);
+}
+static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
+#endif /* CONFIG_PPC_OF */
+
+/* Add sysfs properties */
+void pcibios_add_platform_entries(struct pci_dev *pdev)
+{
+#ifdef CONFIG_PPC_OF
+       device_create_file(&pdev->dev, &dev_attr_devspec);
+#endif /* CONFIG_PPC_OF */
+}
+
+char __init *pcibios_setup(char *str)
+{
+       return str;
+}
+
+/*
+ * Reads the interrupt pin to determine if interrupt is use by card.
+ * If the interrupt is used, then gets the interrupt line from the
+ * openfirmware and sets it in the pci_dev and pci_config line.
+ */
+int pci_read_irq_line(struct pci_dev *pci_dev)
+{
+       struct of_irq oirq;
+       unsigned int virq;
+
+       DBG("Try to map irq for %s...\n", pci_name(pci_dev));
+
+#ifdef DEBUG
+       memset(&oirq, 0xff, sizeof(oirq));
+#endif
+       /* Try to get a mapping from the device-tree */
+       if (of_irq_map_pci(pci_dev, &oirq)) {
+               u8 line, pin;
+
+               /* If that fails, lets fallback to what is in the config
+                * space and map that through the default controller. We
+                * also set the type to level low since that's what PCI
+                * interrupts are. If your platform does differently, then
+                * either provide a proper interrupt tree or don't use this
+                * function.
+                */
+               if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
+                       return -1;
+               if (pin == 0)
+                       return -1;
+               if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
+                   line == 0xff) {
+                       return -1;
+               }
+               DBG(" -> no map ! Using irq line %d from PCI config\n", line);
+
+               virq = irq_create_mapping(NULL, line);
+               if (virq != NO_IRQ)
+                       set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
+       } else {
+               DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
+                   oirq.size, oirq.specifier[0], oirq.specifier[1],
+                   oirq.controller->full_name);
+
+               virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+                                            oirq.size);
+       }
+       if(virq == NO_IRQ) {
+               DBG(" -> failed to map !\n");
+               return -1;
+       }
+
+       DBG(" -> mapped to linux irq %d\n", virq);
+
+       pci_dev->irq = virq;
+
+       return 0;
+}
+EXPORT_SYMBOL(pci_read_irq_line);
+
+/*
+ * Platform support for /proc/bus/pci/X/Y mmap()s,
+ * modelled on the sparc64 implementation by Dave Miller.
+ *  -- paulus.
+ */
+
+/*
+ * Adjust vm_pgoff of VMA such that it is the physical page offset
+ * corresponding to the 32-bit pci bus offset for DEV requested by the user.
+ *
+ * Basically, the user finds the base address for his device which he wishes
+ * to mmap.  They read the 32-bit value from the config space base register,
+ * add whatever PAGE_SIZE multiple offset they wish, and feed this into the
+ * offset parameter of mmap on /proc/bus/pci/XXX for that device.
+ *
+ * Returns negative error code on failure, zero on success.
+ */
+static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
+                                              resource_size_t *offset,
+                                              enum pci_mmap_state mmap_state)
+{
+       struct pci_controller *hose = pci_bus_to_host(dev->bus);
+       unsigned long io_offset = 0;
+       int i, res_bit;
+
+       if (hose == 0)
+               return NULL;            /* should never happen */
+
+       /* If memory, add on the PCI bridge address offset */
+       if (mmap_state == pci_mmap_mem) {
+#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
+               *offset += hose->pci_mem_offset;
+#endif
+               res_bit = IORESOURCE_MEM;
+       } else {
+               io_offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+               *offset += io_offset;
+               res_bit = IORESOURCE_IO;
+       }
+
+       /*
+        * Check that the offset requested corresponds to one of the
+        * resources of the device.
+        */
+       for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+               struct resource *rp = &dev->resource[i];
+               int flags = rp->flags;
+
+               /* treat ROM as memory (should be already) */
+               if (i == PCI_ROM_RESOURCE)
+                       flags |= IORESOURCE_MEM;
+
+               /* Active and same type? */
+               if ((flags & res_bit) == 0)
+                       continue;
+
+               /* In the range of this resource? */
+               if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end)
+                       continue;
+
+               /* found it! construct the final physical address */
+               if (mmap_state == pci_mmap_io)
+                       *offset += hose->io_base_phys - io_offset;
+               return rp;
+       }
+
+       return NULL;
+}
+
+/*
+ * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
+ * device mapping.
+ */
+static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
+                                     pgprot_t protection,
+                                     enum pci_mmap_state mmap_state,
+                                     int write_combine)
+{
+       unsigned long prot = pgprot_val(protection);
+
+       /* Write combine is always 0 on non-memory space mappings. On
+        * memory space, if the user didn't pass 1, we check for a
+        * "prefetchable" resource. This is a bit hackish, but we use
+        * this to workaround the inability of /sysfs to provide a write
+        * combine bit
+        */
+       if (mmap_state != pci_mmap_mem)
+               write_combine = 0;
+       else if (write_combine == 0) {
+               if (rp->flags & IORESOURCE_PREFETCH)
+                       write_combine = 1;
+       }
+
+       /* XXX would be nice to have a way to ask for write-through */
+       prot |= _PAGE_NO_CACHE;
+       if (write_combine)
+               prot &= ~_PAGE_GUARDED;
+       else
+               prot |= _PAGE_GUARDED;
+
+       return __pgprot(prot);
+}
+
+/*
+ * This one is used by /dev/mem and fbdev who have no clue about the
+ * PCI device, it tries to find the PCI device first and calls the
+ * above routine
+ */
+pgprot_t pci_phys_mem_access_prot(struct file *file,
+                                 unsigned long pfn,
+                                 unsigned long size,
+                                 pgprot_t protection)
+{
+       struct pci_dev *pdev = NULL;
+       struct resource *found = NULL;
+       unsigned long prot = pgprot_val(protection);
+       unsigned long offset = pfn << PAGE_SHIFT;
+       int i;
+
+       if (page_is_ram(pfn))
+               return __pgprot(prot);
+
+       prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
+
+       for_each_pci_dev(pdev) {
+               for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+                       struct resource *rp = &pdev->resource[i];
+                       int flags = rp->flags;
+
+                       /* Active and same type? */
+                       if ((flags & IORESOURCE_MEM) == 0)
+                               continue;
+                       /* In the range of this resource? */
+                       if (offset < (rp->start & PAGE_MASK) ||
+                           offset > rp->end)
+                               continue;
+                       found = rp;
+                       break;
+               }
+               if (found)
+                       break;
+       }
+       if (found) {
+               if (found->flags & IORESOURCE_PREFETCH)
+                       prot &= ~_PAGE_GUARDED;
+               pci_dev_put(pdev);
+       }
+
+       DBG("non-PCI map for %lx, prot: %lx\n", offset, prot);
+
+       return __pgprot(prot);
+}
+
+
+/*
+ * Perform the actual remap of the pages for a PCI device mapping, as
+ * appropriate for this architecture.  The region in the process to map
+ * is described by vm_start and vm_end members of VMA, the base physical
+ * address is found in vm_pgoff.
+ * The pci device structure is provided so that architectures may make mapping
+ * decisions on a per-device or per-bus basis.
+ *
+ * Returns a negative error code on failure, zero on success.
+ */
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+                       enum pci_mmap_state mmap_state, int write_combine)
+{
+       resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
+       struct resource *rp;
+       int ret;
+
+       rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
+       if (rp == NULL)
+               return -EINVAL;
+
+       vma->vm_pgoff = offset >> PAGE_SHIFT;
+       vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
+                                                 vma->vm_page_prot,
+                                                 mmap_state, write_combine);
+
+       ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+                              vma->vm_end - vma->vm_start, vma->vm_page_prot);
+
+       return ret;
+}
+
+void pci_resource_to_user(const struct pci_dev *dev, int bar,
+                         const struct resource *rsrc,
+                         resource_size_t *start, resource_size_t *end)
+{
+       struct pci_controller *hose = pci_bus_to_host(dev->bus);
+       resource_size_t offset = 0;
+
+       if (hose == NULL)
+               return;
+
+       if (rsrc->flags & IORESOURCE_IO)
+               offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+
+       /* We pass a fully fixed up address to userland for MMIO instead of
+        * a BAR value because X is lame and expects to be able to use that
+        * to pass to /dev/mem !
+        *
+        * That means that we'll have potentially 64 bits values where some
+        * userland apps only expect 32 (like X itself since it thinks only
+        * Sparc has 64 bits MMIO) but if we don't do that, we break it on
+        * 32 bits CHRPs :-(
+        *
+        * Hopefully, the sysfs insterface is immune to that gunk. Once X
+        * has been fixed (and the fix spread enough), we can re-enable the
+        * 2 lines below and pass down a BAR value to userland. In that case
+        * we'll also have to re-enable the matching code in
+        * __pci_mmap_make_offset().
+        *
+        * BenH.
+        */
+#if 0
+       else if (rsrc->flags & IORESOURCE_MEM)
+               offset = hose->pci_mem_offset;
+#endif
+
+       *start = rsrc->start - offset;
+       *end = rsrc->end - offset;
+}
index 86982112b0ddb7e39c301aa1ee30202b12b88bbf..0adf077f3f3a6cdebc104da48505f23212fdcd7a 100644 (file)
@@ -55,8 +55,7 @@ static u8* pci_to_OF_bus_map;
  */
 int pci_assign_all_buses;
 
-struct pci_controller* hose_head;
-struct pci_controller** hose_tail = &hose_head;
+LIST_HEAD(hose_list);
 
 static int pci_bus_count;
 
@@ -573,58 +572,6 @@ pcibios_assign_resources(void)
        }
 }
 
-
-int
-pcibios_enable_resources(struct pci_dev *dev, int mask)
-{
-       u16 cmd, old_cmd;
-       int idx;
-       struct resource *r;
-
-       pci_read_config_word(dev, PCI_COMMAND, &cmd);
-       old_cmd = cmd;
-       for (idx=0; idx<6; idx++) {
-               /* Only set up the requested stuff */
-               if (!(mask & (1<<idx)))
-                       continue;
-       
-               r = &dev->resource[idx];
-               if (r->flags & IORESOURCE_UNSET) {
-                       printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
-                       return -EINVAL;
-               }
-               if (r->flags & IORESOURCE_IO)
-                       cmd |= PCI_COMMAND_IO;
-               if (r->flags & IORESOURCE_MEM)
-                       cmd |= PCI_COMMAND_MEMORY;
-       }
-       if (dev->resource[PCI_ROM_RESOURCE].start)
-               cmd |= PCI_COMMAND_MEMORY;
-       if (cmd != old_cmd) {
-               printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
-               pci_write_config_word(dev, PCI_COMMAND, cmd);
-       }
-       return 0;
-}
-
-static int next_controller_index;
-
-struct pci_controller * __init
-pcibios_alloc_controller(void)
-{
-       struct pci_controller *hose;
-
-       hose = (struct pci_controller *)alloc_bootmem(sizeof(*hose));
-       memset(hose, 0, sizeof(struct pci_controller));
-
-       *hose_tail = hose;
-       hose_tail = &hose->next;
-
-       hose->index = next_controller_index++;
-
-       return hose;
-}
-
 #ifdef CONFIG_PPC_OF
 /*
  * Functions below are used on OpenFirmware machines.
@@ -670,7 +617,7 @@ void
 pcibios_make_OF_bus_map(void)
 {
        int i;
-       struct pci_controller* hose;
+       struct pci_controller *hose, *tmp;
        struct property *map_prop;
        struct device_node *dn;
 
@@ -687,7 +634,7 @@ pcibios_make_OF_bus_map(void)
                pci_to_OF_bus_map[i] = 0xff;
 
        /* For each hose, we begin searching bridges */
-       for(hose=hose_head; hose; hose=hose->next) {
+       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
                struct device_node* node;       
                node = (struct device_node *)hose->arch_data;
                if (!node)
@@ -765,7 +712,7 @@ static struct device_node *scan_OF_for_pci_bus(struct pci_bus *bus)
 
        /* Are we a root bus ? */
        if (bus->self == NULL || bus->parent == NULL) {
-               struct pci_controller *hose = pci_bus_to_hose(bus->number);
+               struct pci_controller *hose = pci_bus_to_host(bus);
                if (hose == NULL)
                        return NULL;
                return of_node_get(hose->arch_data);
@@ -818,27 +765,6 @@ pci_device_to_OF_node(struct pci_dev *dev)
 }
 EXPORT_SYMBOL(pci_device_to_OF_node);
 
-/* This routine is meant to be used early during boot, when the
- * PCI bus numbers have not yet been assigned, and you need to
- * issue PCI config cycles to an OF device.
- * It could also be used to "fix" RTAS config cycles if you want
- * to set pci_assign_all_buses to 1 and still use RTAS for PCI
- * config cycles.
- */
-struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
-{
-       if (!have_of)
-               return NULL;
-       while(node) {
-               struct pci_controller* hose;
-               for (hose=hose_head;hose;hose=hose->next)
-                       if (hose->arch_data == node)
-                               return hose;
-               node=node->parent;
-       }
-       return NULL;
-}
-
 static int
 find_OF_pci_device_filter(struct device_node* node, void* data)
 {
@@ -1027,34 +953,12 @@ pci_create_OF_bus_map(void)
        }
 }
 
-static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct pci_dev *pdev;
-       struct device_node *np;
-
-       pdev = to_pci_dev (dev);
-       np = pci_device_to_OF_node(pdev);
-       if (np == NULL || np->full_name == NULL)
-               return 0;
-       return sprintf(buf, "%s", np->full_name);
-}
-static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
-
 #else /* CONFIG_PPC_OF */
 void pcibios_make_OF_bus_map(void)
 {
 }
 #endif /* CONFIG_PPC_OF */
 
-/* Add sysfs properties */
-int pcibios_add_platform_entries(struct pci_dev *pdev)
-{
-#ifdef CONFIG_PPC_OF
-       return device_create_file(&pdev->dev, &dev_attr_devspec);
-#endif /* CONFIG_PPC_OF */
-}
-
-
 #ifdef CONFIG_PPC_PMAC
 /*
  * This set of routines checks for PCI<->PCI bridges that have closed
@@ -1269,14 +1173,14 @@ pcibios_fixup_p2p_bridges(void)
 static int __init
 pcibios_init(void)
 {
-       struct pci_controller *hose;
+       struct pci_controller *hose, *tmp;
        struct pci_bus *bus;
-       int next_busno;
+       int next_busno = 0;
 
        printk(KERN_INFO "PCI: Probing PCI hardware\n");
 
        /* Scan all of the recorded PCI controllers.  */
-       for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
+       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
                if (pci_assign_all_buses)
                        hose->first_busno = next_busno;
                hose->last_busno = 0xff;
@@ -1319,12 +1223,6 @@ pcibios_init(void)
 
 subsys_initcall(pcibios_init);
 
-unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
-                            unsigned long start, unsigned long size)
-{
-       return start;
-}
-
 void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
        struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
@@ -1342,7 +1240,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
                if (!res->flags) {
                        if (io_offset)
                                printk(KERN_ERR "I/O resource not set for host"
-                                      " bridge %d\n", hose->index);
+                                      " bridge %d\n", hose->global_number);
                        res->start = 0;
                        res->end = IO_SPACE_LIMIT;
                        res->flags = IORESOURCE_IO;
@@ -1356,7 +1254,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
                                if (i > 0)
                                        continue;
                                printk(KERN_ERR "Memory resource not set for "
-                                      "host bridge %d\n", hose->index);
+                                      "host bridge %d\n", hose->global_number);
                                res->start = hose->pci_mem_offset;
                                res->end = ~0U;
                                res->flags = IORESOURCE_MEM;
@@ -1370,7 +1268,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
                for (i = 0; i < 4; ++i) {
                        if ((res = bus->resource[i]) == NULL)
                                continue;
-                       if (!res->flags)
+                       if (!res->flags || bus->self->transparent)
                                continue;
                        if (io_offset && (res->flags & IORESOURCE_IO)) {
                                res->start += io_offset;
@@ -1395,11 +1293,6 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
        }
 }
 
-char __init *pcibios_setup(char *str)
-{
-       return str;
-}
-
 /* the next one is stolen from the alpha port... */
 void __init
 pcibios_update_irq(struct pci_dev *dev, int irq)
@@ -1408,64 +1301,6 @@ pcibios_update_irq(struct pci_dev *dev, int irq)
        /* XXX FIXME - update OF device tree node interrupt property */
 }
 
-#ifdef CONFIG_PPC_MERGE
-/* XXX This is a copy of the ppc64 version. This is temporary until we start
- * merging the 2 PCI layers
- */
-/*
- * Reads the interrupt pin to determine if interrupt is use by card.
- * If the interrupt is used, then gets the interrupt line from the
- * openfirmware and sets it in the pci_dev and pci_config line.
- */
-int pci_read_irq_line(struct pci_dev *pci_dev)
-{
-       struct of_irq oirq;
-       unsigned int virq;
-
-       DBG("Try to map irq for %s...\n", pci_name(pci_dev));
-
-       /* Try to get a mapping from the device-tree */
-       if (of_irq_map_pci(pci_dev, &oirq)) {
-               u8 line, pin;
-
-               /* If that fails, lets fallback to what is in the config
-                * space and map that through the default controller. We
-                * also set the type to level low since that's what PCI
-                * interrupts are. If your platform does differently, then
-                * either provide a proper interrupt tree or don't use this
-                * function.
-                */
-               if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
-                       return -1;
-               if (pin == 0)
-                       return -1;
-               if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
-                   line == 0xff) {
-                       return -1;
-               }
-               DBG(" -> no map ! Using irq line %d from PCI config\n", line);
-
-               virq = irq_create_mapping(NULL, line);
-               if (virq != NO_IRQ)
-                       set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
-       } else {
-               DBG(" -> got one, spec %d cells (0x%08x...) on %s\n",
-                   oirq.size, oirq.specifier[0], oirq.controller->full_name);
-
-               virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
-                                            oirq.size);
-       }
-       if(virq == NO_IRQ) {
-               DBG(" -> failed to map !\n");
-               return -1;
-       }
-       pci_dev->irq = virq;
-
-       return 0;
-}
-EXPORT_SYMBOL(pci_read_irq_line);
-#endif /* CONFIG_PPC_MERGE */
-
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
        u16 cmd, old_cmd;
@@ -1497,281 +1332,17 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
        return 0;
 }
 
-struct pci_controller*
+static struct pci_controller*
 pci_bus_to_hose(int bus)
 {
-       struct pci_controller* hose = hose_head;
+       struct pci_controller *hose, *tmp;
 
-       for (; hose; hose = hose->next)
+       list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
                if (bus >= hose->first_busno && bus <= hose->last_busno)
                        return hose;
        return NULL;
 }
 
-void __iomem *
-pci_bus_io_base(unsigned int bus)
-{
-       struct pci_controller *hose;
-
-       hose = pci_bus_to_hose(bus);
-       if (!hose)
-               return NULL;
-       return hose->io_base_virt;
-}
-
-unsigned long
-pci_bus_io_base_phys(unsigned int bus)
-{
-       struct pci_controller *hose;
-
-       hose = pci_bus_to_hose(bus);
-       if (!hose)
-               return 0;
-       return hose->io_base_phys;
-}
-
-unsigned long
-pci_bus_mem_base_phys(unsigned int bus)
-{
-       struct pci_controller *hose;
-
-       hose = pci_bus_to_hose(bus);
-       if (!hose)
-               return 0;
-       return hose->pci_mem_offset;
-}
-
-unsigned long
-pci_resource_to_bus(struct pci_dev *pdev, struct resource *res)
-{
-       /* Hack alert again ! See comments in chrp_pci.c
-        */
-       struct pci_controller* hose =
-               (struct pci_controller *)pdev->sysdata;
-       if (hose && res->flags & IORESOURCE_MEM)
-               return res->start - hose->pci_mem_offset;
-       /* We may want to do something with IOs here... */
-       return res->start;
-}
-
-
-static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
-                                              resource_size_t *offset,
-                                              enum pci_mmap_state mmap_state)
-{
-       struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
-       unsigned long io_offset = 0;
-       int i, res_bit;
-
-       if (hose == 0)
-               return NULL;            /* should never happen */
-
-       /* If memory, add on the PCI bridge address offset */
-       if (mmap_state == pci_mmap_mem) {
-#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
-               *offset += hose->pci_mem_offset;
-#endif
-               res_bit = IORESOURCE_MEM;
-       } else {
-               io_offset = hose->io_base_virt - (void __iomem *)_IO_BASE;
-               *offset += io_offset;
-               res_bit = IORESOURCE_IO;
-       }
-
-       /*
-        * Check that the offset requested corresponds to one of the
-        * resources of the device.
-        */
-       for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-               struct resource *rp = &dev->resource[i];
-               int flags = rp->flags;
-
-               /* treat ROM as memory (should be already) */
-               if (i == PCI_ROM_RESOURCE)
-                       flags |= IORESOURCE_MEM;
-
-               /* Active and same type? */
-               if ((flags & res_bit) == 0)
-                       continue;
-
-               /* In the range of this resource? */
-               if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end)
-                       continue;
-
-               /* found it! construct the final physical address */
-               if (mmap_state == pci_mmap_io)
-                       *offset += hose->io_base_phys - io_offset;
-               return rp;
-       }
-
-       return NULL;
-}
-
-/*
- * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
- * device mapping.
- */
-static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
-                                     pgprot_t protection,
-                                     enum pci_mmap_state mmap_state,
-                                     int write_combine)
-{
-       unsigned long prot = pgprot_val(protection);
-
-       /* Write combine is always 0 on non-memory space mappings. On
-        * memory space, if the user didn't pass 1, we check for a
-        * "prefetchable" resource. This is a bit hackish, but we use
-        * this to workaround the inability of /sysfs to provide a write
-        * combine bit
-        */
-       if (mmap_state != pci_mmap_mem)
-               write_combine = 0;
-       else if (write_combine == 0) {
-               if (rp->flags & IORESOURCE_PREFETCH)
-                       write_combine = 1;
-       }
-
-       /* XXX would be nice to have a way to ask for write-through */
-       prot |= _PAGE_NO_CACHE;
-       if (write_combine)
-               prot &= ~_PAGE_GUARDED;
-       else
-               prot |= _PAGE_GUARDED;
-
-       return __pgprot(prot);
-}
-
-/*
- * This one is used by /dev/mem and fbdev who have no clue about the
- * PCI device, it tries to find the PCI device first and calls the
- * above routine
- */
-pgprot_t pci_phys_mem_access_prot(struct file *file,
-                                 unsigned long pfn,
-                                 unsigned long size,
-                                 pgprot_t protection)
-{
-       struct pci_dev *pdev = NULL;
-       struct resource *found = NULL;
-       unsigned long prot = pgprot_val(protection);
-       unsigned long offset = pfn << PAGE_SHIFT;
-       int i;
-
-       if (page_is_ram(pfn))
-               return __pgprot(prot);
-
-       prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
-
-       for_each_pci_dev(pdev) {
-               for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-                       struct resource *rp = &pdev->resource[i];
-                       int flags = rp->flags;
-
-                       /* Active and same type? */
-                       if ((flags & IORESOURCE_MEM) == 0)
-                               continue;
-                       /* In the range of this resource? */
-                       if (offset < (rp->start & PAGE_MASK) ||
-                           offset > rp->end)
-                               continue;
-                       found = rp;
-                       break;
-               }
-               if (found)
-                       break;
-       }
-       if (found) {
-               if (found->flags & IORESOURCE_PREFETCH)
-                       prot &= ~_PAGE_GUARDED;
-               pci_dev_put(pdev);
-       }
-
-       DBG("non-PCI map for %lx, prot: %lx\n", offset, prot);
-
-       return __pgprot(prot);
-}
-
-
-/*
- * Perform the actual remap of the pages for a PCI device mapping, as
- * appropriate for this architecture.  The region in the process to map
- * is described by vm_start and vm_end members of VMA, the base physical
- * address is found in vm_pgoff.
- * The pci device structure is provided so that architectures may make mapping
- * decisions on a per-device or per-bus basis.
- *
- * Returns a negative error code on failure, zero on success.
- */
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-                       enum pci_mmap_state mmap_state,
-                       int write_combine)
-{
-       resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
-       struct resource *rp;
-       int ret;
-
-       rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
-       if (rp == NULL)
-               return -EINVAL;
-
-       vma->vm_pgoff = offset >> PAGE_SHIFT;
-       vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
-                                                 vma->vm_page_prot,
-                                                 mmap_state, write_combine);
-
-       ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-                              vma->vm_end - vma->vm_start, vma->vm_page_prot);
-
-       return ret;
-}
-
-/* Obsolete functions. Should be removed once the symbios driver
- * is fixed
- */
-unsigned long
-phys_to_bus(unsigned long pa)
-{
-       struct pci_controller *hose;
-       int i;
-
-       for (hose = hose_head; hose; hose = hose->next) {
-               for (i = 0; i < 3; ++i) {
-                       if (pa >= hose->mem_resources[i].start
-                           && pa <= hose->mem_resources[i].end) {
-                               /*
-                                * XXX the hose->pci_mem_offset really
-                                * only applies to mem_resources[0].
-                                * We need a way to store an offset for
-                                * the others.  -- paulus
-                                */
-                               if (i == 0)
-                                       pa -= hose->pci_mem_offset;
-                               return pa;
-                       }
-               }
-       }
-       /* hmmm, didn't find it */
-       return 0;
-}
-
-unsigned long
-pci_phys_to_bus(unsigned long pa, int busnr)
-{
-       struct pci_controller* hose = pci_bus_to_hose(busnr);
-       if (!hose)
-               return pa;
-       return pa - hose->pci_mem_offset;
-}
-
-unsigned long
-pci_bus_to_phys(unsigned int ba, int busnr)
-{
-       struct pci_controller* hose = pci_bus_to_hose(busnr);
-       if (!hose)
-               return ba;
-       return ba + hose->pci_mem_offset;
-}
-
 /* Provide information on locations of various I/O regions in physical
  * memory.  Do this on a per-card basis so that we choose the right
  * root bridge.
@@ -1814,62 +1385,11 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
        return result;
 }
 
-void pci_resource_to_user(const struct pci_dev *dev, int bar,
-                         const struct resource *rsrc,
-                         resource_size_t *start, resource_size_t *end)
-{
-       struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
-       resource_size_t offset = 0;
-
-       if (hose == NULL)
-               return;
-
-       if (rsrc->flags & IORESOURCE_IO)
-               offset = (unsigned long)hose->io_base_virt - _IO_BASE;
-
-       /* We pass a fully fixed up address to userland for MMIO instead of
-        * a BAR value because X is lame and expects to be able to use that
-        * to pass to /dev/mem !
-        *
-        * That means that we'll have potentially 64 bits values where some
-        * userland apps only expect 32 (like X itself since it thinks only
-        * Sparc has 64 bits MMIO) but if we don't do that, we break it on
-        * 32 bits CHRPs :-(
-        *
-        * Hopefully, the sysfs insterface is immune to that gunk. Once X
-        * has been fixed (and the fix spread enough), we can re-enable the
-        * 2 lines below and pass down a BAR value to userland. In that case
-        * we'll also have to re-enable the matching code in
-        * __pci_mmap_make_offset().
-        *
-        * BenH.
-        */
-#if 0
-       else if (rsrc->flags & IORESOURCE_MEM)
-               offset = hose->pci_mem_offset;
-#endif
-
-       *start = rsrc->start - offset;
-       *end = rsrc->end - offset;
-}
-
-void __init pci_init_resource(struct resource *res, resource_size_t start,
-                             resource_size_t end, int flags, char *name)
-{
-       res->start = start;
-       res->end = end;
-       res->flags = flags;
-       res->name = name;
-       res->parent = NULL;
-       res->sibling = NULL;
-       res->child = NULL;
-}
-
 unsigned long pci_address_to_pio(phys_addr_t address)
 {
-       struct pci_controller* hose = hose_head;
+       struct pci_controller *hose, *tmp;
 
-       for (; hose; hose = hose->next) {
+       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
                unsigned int size = hose->io_resource.end -
                        hose->io_resource.start + 1;
                if (address >= hose->io_base_phys &&
index e3009a43ac56ed117b553fab9f071593142205bb..a97e23ac197639bd17eda467be127214f863af38 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/list.h>
 #include <linux/syscalls.h>
 #include <linux/irq.h>
+#include <linux/vmalloc.h>
 
 #include <asm/processor.h>
 #include <asm/io.h>
 
 unsigned long pci_probe_only = 1;
 int pci_assign_all_buses = 0;
-static int pci_initial_scan_done;
 
 static void fixup_resource(struct resource *res, struct pci_dev *dev);
 static void do_bus_setup(struct pci_bus *bus);
-static void phbs_remap_io(void);
 
 /* pci_io_base -- the base address from which io bars are offsets.
  * This is the lowest I/O base address (so bar values are always positive),
  * and it *must* be the start of ISA space if an ISA bus exists because
- * ISA drivers use hard coded offsets.  If no ISA bus exists a dummy
- * page is mapped and isa_io_limit prevents access to it.
+ * ISA drivers use hard coded offsets.  If no ISA bus exists nothing
+ * is mapped on the first 64K of IO space
  */
-unsigned long isa_io_base;     /* NULL if no ISA bus */
-EXPORT_SYMBOL(isa_io_base);
-unsigned long pci_io_base;
+unsigned long pci_io_base = ISA_IO_BASE;
 EXPORT_SYMBOL(pci_io_base);
 
-void iSeries_pcibios_init(void);
-
 LIST_HEAD(hose_list);
 
 static struct dma_mapping_ops *pci_dma_ops;
 
-int global_phb_number;         /* Global phb counter */
-
-/* Cached ISA bridge dev. */
-struct pci_dev *ppc64_isabridge_dev = NULL;
-EXPORT_SYMBOL_GPL(ppc64_isabridge_dev);
-
 void set_pci_dma_ops(struct dma_mapping_ops *dma_ops)
 {
        pci_dma_ops = dma_ops;
@@ -100,7 +89,7 @@ void  pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region
                return;
 
        if (res->flags & IORESOURCE_IO)
-               offset = (unsigned long)hose->io_base_virt - pci_io_base;
+               offset = (unsigned long)hose->io_base_virt - _IO_BASE;
 
        if (res->flags & IORESOURCE_MEM)
                offset = hose->pci_mem_offset;
@@ -119,7 +108,7 @@ void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
                return;
 
        if (res->flags & IORESOURCE_IO)
-               offset = (unsigned long)hose->io_base_virt - pci_io_base;
+               offset = (unsigned long)hose->io_base_virt - _IO_BASE;
 
        if (res->flags & IORESOURCE_MEM)
                offset = hose->pci_mem_offset;
@@ -156,7 +145,7 @@ void pcibios_align_resource(void *data, struct resource *res,
 
        if (res->flags & IORESOURCE_IO) {
                unsigned long offset = (unsigned long)hose->io_base_virt -
-                                       pci_io_base;
+                                       _IO_BASE;
                /* Make sure we start at our min on all hoses */
                if (start - offset < PCIBIOS_MIN_IO)
                        start = PCIBIOS_MIN_IO + offset;
@@ -180,55 +169,6 @@ void pcibios_align_resource(void *data, struct resource *res,
        res->start = start;
 }
 
-static DEFINE_SPINLOCK(hose_spinlock);
-
-/*
- * pci_controller(phb) initialized common variables.
- */
-static void __devinit pci_setup_pci_controller(struct pci_controller *hose)
-{
-       memset(hose, 0, sizeof(struct pci_controller));
-
-       spin_lock(&hose_spinlock);
-       hose->global_number = global_phb_number++;
-       list_add_tail(&hose->list_node, &hose_list);
-       spin_unlock(&hose_spinlock);
-}
-
-struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
-{
-       struct pci_controller *phb;
-
-       if (mem_init_done)
-               phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
-       else
-               phb = alloc_bootmem(sizeof (struct pci_controller));
-       if (phb == NULL)
-               return NULL;
-       pci_setup_pci_controller(phb);
-       phb->arch_data = dev;
-       phb->is_dynamic = mem_init_done;
-       if (dev) {
-               int nid = of_node_to_nid(dev);
-
-               if (nid < 0 || !node_online(nid))
-                       nid = -1;
-
-               PHB_SET_NODE(phb, nid);
-       }
-       return phb;
-}
-
-void pcibios_free_controller(struct pci_controller *phb)
-{
-       spin_lock(&hose_spinlock);
-       list_del(&phb->list_node);
-       spin_unlock(&hose_spinlock);
-
-       if (phb->is_dynamic)
-               kfree(phb);
-}
-
 void __devinit pcibios_claim_one_bus(struct pci_bus *b)
 {
        struct pci_dev *dev;
@@ -291,7 +231,6 @@ static unsigned int pci_parse_of_flags(u32 addr0)
        return flags;
 }
 
-#define GET_64BIT(prop, i)     ((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1])
 
 static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
 {
@@ -310,8 +249,8 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
                flags = pci_parse_of_flags(addrs[0]);
                if (!flags)
                        continue;
-               base = GET_64BIT(addrs, 1);
-               size = GET_64BIT(addrs, 3);
+               base = of_read_number(&addrs[1], 2);
+               size = of_read_number(&addrs[3], 2);
                if (!size)
                        continue;
                i = addrs[0] & 0xff;
@@ -479,7 +418,7 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
        i = 1;
        for (; len >= 32; len -= 32, ranges += 8) {
                flags = pci_parse_of_flags(ranges[0]);
-               size = GET_64BIT(ranges, 6);
+               size = of_read_number(&ranges[6], 2);
                if (flags == 0 || size == 0)
                        continue;
                if (flags & IORESOURCE_IO) {
@@ -498,7 +437,7 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
                        res = bus->resource[i];
                        ++i;
                }
-               res->start = GET_64BIT(ranges, 1);
+               res->start = of_read_number(&ranges[1], 2);
                res->end = res->start + size - 1;
                res->flags = flags;
                fixup_resource(res, dev);
@@ -537,10 +476,16 @@ void __devinit scan_phb(struct pci_controller *hose)
        bus->secondary = hose->first_busno;
        hose->bus = bus;
 
+       if (!firmware_has_feature(FW_FEATURE_ISERIES))
+               pcibios_map_io_space(bus);
+
        bus->resource[0] = res = &hose->io_resource;
-       if (res->flags && request_resource(&ioport_resource, res))
+       if (res->flags && request_resource(&ioport_resource, res)) {
                printk(KERN_ERR "Failed to request PCI IO region "
                       "on PCI domain %04x\n", hose->global_number);
+               DBG("res->start = 0x%016lx, res->end = 0x%016lx\n",
+                   res->start, res->end);
+       }
 
        for (i = 0; i < 3; ++i) {
                res = &hose->mem_resources[i];
@@ -598,17 +543,6 @@ static int __init pcibios_init(void)
        if (ppc_md.pcibios_fixup)
                ppc_md.pcibios_fixup();
 
-       /* Cache the location of the ISA bridge (if we have one) */
-       ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
-       if (ppc64_isabridge_dev != NULL)
-               printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
-
-       if (!firmware_has_feature(FW_FEATURE_ISERIES))
-               /* map in PCI I/O space */
-               phbs_remap_io();
-
-       pci_initial_scan_done = 1;
-
        printk(KERN_DEBUG "PCI: Probing PCI hardware done\n");
 
        return 0;
@@ -616,11 +550,6 @@ static int __init pcibios_init(void)
 
 subsys_initcall(pcibios_init);
 
-char __init *pcibios_setup(char *str)
-{
-       return str;
-}
-
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
        u16 cmd, oldcmd;
@@ -651,22 +580,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
        return 0;
 }
 
-/*
- * Return the domain number for this bus.
- */
-int pci_domain_nr(struct pci_bus *bus)
-{
-       if (firmware_has_feature(FW_FEATURE_ISERIES))
-               return 0;
-       else {
-               struct pci_controller *hose = pci_bus_to_host(bus);
-
-               return hose->global_number;
-       }
-}
-
-EXPORT_SYMBOL(pci_domain_nr);
-
 /* Decide whether to display the domain number in /proc */
 int pci_proc_domain(struct pci_bus *bus)
 {
@@ -678,281 +591,6 @@ int pci_proc_domain(struct pci_bus *bus)
        }
 }
 
-/*
- * Platform support for /proc/bus/pci/X/Y mmap()s,
- * modelled on the sparc64 implementation by Dave Miller.
- *  -- paulus.
- */
-
-/*
- * Adjust vm_pgoff of VMA such that it is the physical page offset
- * corresponding to the 32-bit pci bus offset for DEV requested by the user.
- *
- * Basically, the user finds the base address for his device which he wishes
- * to mmap.  They read the 32-bit value from the config space base register,
- * add whatever PAGE_SIZE multiple offset they wish, and feed this into the
- * offset parameter of mmap on /proc/bus/pci/XXX for that device.
- *
- * Returns negative error code on failure, zero on success.
- */
-static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
-                                              resource_size_t *offset,
-                                              enum pci_mmap_state mmap_state)
-{
-       struct pci_controller *hose = pci_bus_to_host(dev->bus);
-       unsigned long io_offset = 0;
-       int i, res_bit;
-
-       if (hose == 0)
-               return NULL;            /* should never happen */
-
-       /* If memory, add on the PCI bridge address offset */
-       if (mmap_state == pci_mmap_mem) {
-#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
-               *offset += hose->pci_mem_offset;
-#endif
-               res_bit = IORESOURCE_MEM;
-       } else {
-               io_offset = (unsigned long)hose->io_base_virt - pci_io_base;
-               *offset += io_offset;
-               res_bit = IORESOURCE_IO;
-       }
-
-       /*
-        * Check that the offset requested corresponds to one of the
-        * resources of the device.
-        */
-       for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-               struct resource *rp = &dev->resource[i];
-               int flags = rp->flags;
-
-               /* treat ROM as memory (should be already) */
-               if (i == PCI_ROM_RESOURCE)
-                       flags |= IORESOURCE_MEM;
-
-               /* Active and same type? */
-               if ((flags & res_bit) == 0)
-                       continue;
-
-               /* In the range of this resource? */
-               if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end)
-                       continue;
-
-               /* found it! construct the final physical address */
-               if (mmap_state == pci_mmap_io)
-                       *offset += hose->io_base_phys - io_offset;
-               return rp;
-       }
-
-       return NULL;
-}
-
-/*
- * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
- * device mapping.
- */
-static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
-                                     pgprot_t protection,
-                                     enum pci_mmap_state mmap_state,
-                                     int write_combine)
-{
-       unsigned long prot = pgprot_val(protection);
-
-       /* Write combine is always 0 on non-memory space mappings. On
-        * memory space, if the user didn't pass 1, we check for a
-        * "prefetchable" resource. This is a bit hackish, but we use
-        * this to workaround the inability of /sysfs to provide a write
-        * combine bit
-        */
-       if (mmap_state != pci_mmap_mem)
-               write_combine = 0;
-       else if (write_combine == 0) {
-               if (rp->flags & IORESOURCE_PREFETCH)
-                       write_combine = 1;
-       }
-
-       /* XXX would be nice to have a way to ask for write-through */
-       prot |= _PAGE_NO_CACHE;
-       if (write_combine)
-               prot &= ~_PAGE_GUARDED;
-       else
-               prot |= _PAGE_GUARDED;
-
-       return __pgprot(prot);
-}
-
-/*
- * This one is used by /dev/mem and fbdev who have no clue about the
- * PCI device, it tries to find the PCI device first and calls the
- * above routine
- */
-pgprot_t pci_phys_mem_access_prot(struct file *file,
-                                 unsigned long pfn,
-                                 unsigned long size,
-                                 pgprot_t protection)
-{
-       struct pci_dev *pdev = NULL;
-       struct resource *found = NULL;
-       unsigned long prot = pgprot_val(protection);
-       unsigned long offset = pfn << PAGE_SHIFT;
-       int i;
-
-       if (page_is_ram(pfn))
-               return __pgprot(prot);
-
-       prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
-
-       for_each_pci_dev(pdev) {
-               for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-                       struct resource *rp = &pdev->resource[i];
-                       int flags = rp->flags;
-
-                       /* Active and same type? */
-                       if ((flags & IORESOURCE_MEM) == 0)
-                               continue;
-                       /* In the range of this resource? */
-                       if (offset < (rp->start & PAGE_MASK) ||
-                           offset > rp->end)
-                               continue;
-                       found = rp;
-                       break;
-               }
-               if (found)
-                       break;
-       }
-       if (found) {
-               if (found->flags & IORESOURCE_PREFETCH)
-                       prot &= ~_PAGE_GUARDED;
-               pci_dev_put(pdev);
-       }
-
-       DBG("non-PCI map for %lx, prot: %lx\n", offset, prot);
-
-       return __pgprot(prot);
-}
-
-
-/*
- * Perform the actual remap of the pages for a PCI device mapping, as
- * appropriate for this architecture.  The region in the process to map
- * is described by vm_start and vm_end members of VMA, the base physical
- * address is found in vm_pgoff.
- * The pci device structure is provided so that architectures may make mapping
- * decisions on a per-device or per-bus basis.
- *
- * Returns a negative error code on failure, zero on success.
- */
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-                       enum pci_mmap_state mmap_state, int write_combine)
-{
-       resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
-       struct resource *rp;
-       int ret;
-
-       rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
-       if (rp == NULL)
-               return -EINVAL;
-
-       vma->vm_pgoff = offset >> PAGE_SHIFT;
-       vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
-                                                 vma->vm_page_prot,
-                                                 mmap_state, write_combine);
-
-       ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-                              vma->vm_end - vma->vm_start, vma->vm_page_prot);
-
-       return ret;
-}
-
-static ssize_t pci_show_devspec(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct pci_dev *pdev;
-       struct device_node *np;
-
-       pdev = to_pci_dev (dev);
-       np = pci_device_to_OF_node(pdev);
-       if (np == NULL || np->full_name == NULL)
-               return 0;
-       return sprintf(buf, "%s", np->full_name);
-}
-static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
-
-int pcibios_add_platform_entries(struct pci_dev *pdev)
-{
-       return device_create_file(&pdev->dev, &dev_attr_devspec);
-}
-
-#define ISA_SPACE_MASK 0x1
-#define ISA_SPACE_IO 0x1
-
-static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
-                                     unsigned long phb_io_base_phys,
-                                     void __iomem * phb_io_base_virt)
-{
-       /* Remove these asap */
-
-       struct pci_address {
-               u32 a_hi;
-               u32 a_mid;
-               u32 a_lo;
-       };
-
-       struct isa_address {
-               u32 a_hi;
-               u32 a_lo;
-       };
-
-       struct isa_range {
-               struct isa_address isa_addr;
-               struct pci_address pci_addr;
-               unsigned int size;
-       };
-
-       const struct isa_range *range;
-       unsigned long pci_addr;
-       unsigned int isa_addr;
-       unsigned int size;
-       int rlen = 0;
-
-       range = of_get_property(isa_node, "ranges", &rlen);
-       if (range == NULL || (rlen < sizeof(struct isa_range))) {
-               printk(KERN_ERR "no ISA ranges or unexpected isa range size,"
-                      "mapping 64k\n");
-               __ioremap_explicit(phb_io_base_phys,
-                                  (unsigned long)phb_io_base_virt,
-                                  0x10000, _PAGE_NO_CACHE | _PAGE_GUARDED);
-               return; 
-       }
-       
-       /* From "ISA Binding to 1275"
-        * The ranges property is laid out as an array of elements,
-        * each of which comprises:
-        *   cells 0 - 1:       an ISA address
-        *   cells 2 - 4:       a PCI address 
-        *                      (size depending on dev->n_addr_cells)
-        *   cell 5:            the size of the range
-        */
-       if ((range->isa_addr.a_hi && ISA_SPACE_MASK) == ISA_SPACE_IO) {
-               isa_addr = range->isa_addr.a_lo;
-               pci_addr = (unsigned long) range->pci_addr.a_mid << 32 | 
-                       range->pci_addr.a_lo;
-
-               /* Assume these are both zero */
-               if ((pci_addr != 0) || (isa_addr != 0)) {
-                       printk(KERN_ERR "unexpected isa to pci mapping: %s\n",
-                                       __FUNCTION__);
-                       return;
-               }
-               
-               size = PAGE_ALIGN(range->size);
-
-               __ioremap_explicit(phb_io_base_phys, 
-                                  (unsigned long) phb_io_base_virt, 
-                                  size, _PAGE_NO_CACHE | _PAGE_GUARDED);
-       }
-}
-
 void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
                                            struct device_node *dev, int prim)
 {
@@ -1047,155 +685,122 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
        }
 }
 
-void __devinit pci_setup_phb_io(struct pci_controller *hose, int primary)
+#ifdef CONFIG_HOTPLUG
+
+int pcibios_unmap_io_space(struct pci_bus *bus)
 {
-       unsigned long size = hose->pci_io_size;
-       unsigned long io_virt_offset;
-       struct resource *res;
-       struct device_node *isa_dn;
+       struct pci_controller *hose;
 
-       if (size == 0)
-               return;
+       WARN_ON(bus == NULL);
 
-       hose->io_base_virt = reserve_phb_iospace(size);
-       DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n",
-               hose->global_number, hose->io_base_phys,
-               (unsigned long) hose->io_base_virt);
-
-       if (primary) {
-               pci_io_base = (unsigned long)hose->io_base_virt;
-               isa_dn = of_find_node_by_type(NULL, "isa");
-               if (isa_dn) {
-                       isa_io_base = pci_io_base;
-                       pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys,
-                                               hose->io_base_virt);
-                       of_node_put(isa_dn);
-               }
-       }
+       /* If this is not a PHB, we only flush the hash table over
+        * the area mapped by this bridge. We don't play with the PTE
+        * mappings since we might have to deal with sub-page alignemnts
+        * so flushing the hash table is the only sane way to make sure
+        * that no hash entries are covering that removed bridge area
+        * while still allowing other busses overlapping those pages
+        */
+       if (bus->self) {
+               struct resource *res = bus->resource[0];
 
-       io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base;
-       res = &hose->io_resource;
-       res->start += io_virt_offset;
-       res->end += io_virt_offset;
+               DBG("IO unmapping for PCI-PCI bridge %s\n",
+                   pci_name(bus->self));
 
-       /* If this is called after the initial PCI scan, then we need to
-        * proceed to IO mappings now
-        */
-       if (pci_initial_scan_done)
-               __ioremap_explicit(hose->io_base_phys,
-                                  (unsigned long)hose->io_base_virt,
-                                  hose->pci_io_size,
-                                  _PAGE_NO_CACHE | _PAGE_GUARDED);
-}
+               __flush_hash_table_range(&init_mm, res->start + _IO_BASE,
+                                        res->end - res->start + 1);
+               return 0;
+       }
 
-void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose,
-                                       int primary)
-{
-       unsigned long size = hose->pci_io_size;
-       unsigned long io_virt_offset;
-       struct resource *res;
+       /* Get the host bridge */
+       hose = pci_bus_to_host(bus);
 
-       if (size == 0)
-               return;
+       /* Check if we have IOs allocated */
+       if (hose->io_base_alloc == 0)
+               return 0;
 
-       hose->io_base_virt = __ioremap(hose->io_base_phys, size,
-                                       _PAGE_NO_CACHE | _PAGE_GUARDED);
-       DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n",
-               hose->global_number, hose->io_base_phys,
-               (unsigned long) hose->io_base_virt);
+       DBG("IO unmapping for PHB %s\n",
+           ((struct device_node *)hose->arch_data)->full_name);
+       DBG("  alloc=0x%p\n", hose->io_base_alloc);
 
-       if (primary)
-               pci_io_base = (unsigned long)hose->io_base_virt;
+       /* This is a PHB, we fully unmap the IO area */
+       vunmap(hose->io_base_alloc);
 
-       io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base;
-       res = &hose->io_resource;
-       res->start += io_virt_offset;
-       res->end += io_virt_offset;
+       return 0;
 }
+EXPORT_SYMBOL_GPL(pcibios_unmap_io_space);
 
+#endif /* CONFIG_HOTPLUG */
 
-static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys,
-                               unsigned long *start_virt, unsigned long *size)
+int __devinit pcibios_map_io_space(struct pci_bus *bus)
 {
-       struct pci_controller *hose = pci_bus_to_host(bus);
-       struct resource *res;
-
-       if (bus->self)
-               res = bus->resource[0];
-       else
-               /* Root Bus */
-               res = &hose->io_resource;
-
-       if (res->end == 0 && res->start == 0)
-               return 1;
+       struct vm_struct *area;
+       unsigned long phys_page;
+       unsigned long size_page;
+       unsigned long io_virt_offset;
+       struct pci_controller *hose;
 
-       *start_virt = pci_io_base + res->start;
-       *start_phys = *start_virt + hose->io_base_phys
-               - (unsigned long) hose->io_base_virt;
+       WARN_ON(bus == NULL);
 
-       if (res->end > res->start)
-               *size = res->end - res->start + 1;
-       else {
-               printk("%s(): unexpected region 0x%lx->0x%lx\n",
-                      __FUNCTION__, res->start, res->end);
-               return 1;
+       /* If this not a PHB, nothing to do, page tables still exist and
+        * thus HPTEs will be faulted in when needed
+        */
+       if (bus->self) {
+               DBG("IO mapping for PCI-PCI bridge %s\n",
+                   pci_name(bus->self));
+               DBG("  virt=0x%016lx...0x%016lx\n",
+                   bus->resource[0]->start + _IO_BASE,
+                   bus->resource[0]->end + _IO_BASE);
+               return 0;
        }
 
-       return 0;
-}
-
-int unmap_bus_range(struct pci_bus *bus)
-{
-       unsigned long start_phys;
-       unsigned long start_virt;
-       unsigned long size;
+       /* Get the host bridge */
+       hose = pci_bus_to_host(bus);
+       phys_page = _ALIGN_DOWN(hose->io_base_phys, PAGE_SIZE);
+       size_page = _ALIGN_UP(hose->pci_io_size, PAGE_SIZE);
 
-       if (!bus) {
-               printk(KERN_ERR "%s() expected bus\n", __FUNCTION__);
-               return 1;
-       }
-       
-       if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
-               return 1;
-       if (__iounmap_explicit((void __iomem *) start_virt, size))
-               return 1;
-
-       return 0;
-}
-EXPORT_SYMBOL(unmap_bus_range);
+       /* Make sure IO area address is clear */
+       hose->io_base_alloc = NULL;
 
-int remap_bus_range(struct pci_bus *bus)
-{
-       unsigned long start_phys;
-       unsigned long start_virt;
-       unsigned long size;
+       /* If there's no IO to map on that bus, get away too */
+       if (hose->pci_io_size == 0 || hose->io_base_phys == 0)
+               return 0;
 
-       if (!bus) {
-               printk(KERN_ERR "%s() expected bus\n", __FUNCTION__);
-               return 1;
-       }
-       
-       
-       if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
-               return 1;
-       if (start_phys == 0)
-               return 1;
-       printk(KERN_DEBUG "mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size);
-       if (__ioremap_explicit(start_phys, start_virt, size,
-                              _PAGE_NO_CACHE | _PAGE_GUARDED))
-               return 1;
+       /* Let's allocate some IO space for that guy. We don't pass
+        * VM_IOREMAP because we don't care about alignment tricks that
+        * the core does in that case. Maybe we should due to stupid card
+        * with incomplete address decoding but I'd rather not deal with
+        * those outside of the reserved 64K legacy region.
+        */
+       area = __get_vm_area(size_page, 0, PHB_IO_BASE, PHB_IO_END);
+       if (area == NULL)
+               return -ENOMEM;
+       hose->io_base_alloc = area->addr;
+       hose->io_base_virt = (void __iomem *)(area->addr +
+                                             hose->io_base_phys - phys_page);
+
+       DBG("IO mapping for PHB %s\n",
+           ((struct device_node *)hose->arch_data)->full_name);
+       DBG("  phys=0x%016lx, virt=0x%p (alloc=0x%p)\n",
+           hose->io_base_phys, hose->io_base_virt, hose->io_base_alloc);
+       DBG("  size=0x%016lx (alloc=0x%016lx)\n",
+           hose->pci_io_size, size_page);
+
+       /* Establish the mapping */
+       if (__ioremap_at(phys_page, area->addr, size_page,
+                        _PAGE_NO_CACHE | _PAGE_GUARDED) == NULL)
+               return -ENOMEM;
+
+       /* Fixup hose IO resource */
+       io_virt_offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+       hose->io_resource.start += io_virt_offset;
+       hose->io_resource.end += io_virt_offset;
+
+       DBG("  hose->io_resource=0x%016lx...0x%016lx\n",
+           hose->io_resource.start, hose->io_resource.end);
 
        return 0;
 }
-EXPORT_SYMBOL(remap_bus_range);
-
-static void phbs_remap_io(void)
-{
-       struct pci_controller *hose, *tmp;
-
-       list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
-               remap_bus_range(hose->bus);
-}
+EXPORT_SYMBOL_GPL(pcibios_map_io_space);
 
 static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
 {
@@ -1203,8 +808,7 @@ static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
        unsigned long offset;
 
        if (res->flags & IORESOURCE_IO) {
-               offset = (unsigned long)hose->io_base_virt - pci_io_base;
-
+               offset = (unsigned long)hose->io_base_virt - _IO_BASE;
                res->start += offset;
                res->end += offset;
        } else if (res->flags & IORESOURCE_MEM) {
@@ -1219,9 +823,20 @@ void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
        /* Update device resources.  */
        int i;
 
-       for (i = 0; i < PCI_NUM_RESOURCES; i++)
-               if (dev->resource[i].flags)
-                       fixup_resource(&dev->resource[i], dev);
+       DBG("%s: Fixup resources:\n", pci_name(dev));
+       for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+               struct resource *res = &dev->resource[i];
+               if (!res->flags)
+                       continue;
+
+               DBG("  0x%02x < %08lx:0x%016lx...0x%016lx\n",
+                   i, res->flags, res->start, res->end);
+
+               fixup_resource(res, dev);
+
+               DBG("       > %08lx:0x%016lx...0x%016lx\n",
+                   res->flags, res->start, res->end);
+       }
 }
 EXPORT_SYMBOL(pcibios_fixup_device_resources);
 
@@ -1291,119 +906,6 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 }
 EXPORT_SYMBOL(pcibios_fixup_bus);
 
-/*
- * Reads the interrupt pin to determine if interrupt is use by card.
- * If the interrupt is used, then gets the interrupt line from the 
- * openfirmware and sets it in the pci_dev and pci_config line.
- */
-int pci_read_irq_line(struct pci_dev *pci_dev)
-{
-       struct of_irq oirq;
-       unsigned int virq;
-
-       DBG("Try to map irq for %s...\n", pci_name(pci_dev));
-
-#ifdef DEBUG
-       memset(&oirq, 0xff, sizeof(oirq));
-#endif
-       /* Try to get a mapping from the device-tree */
-       if (of_irq_map_pci(pci_dev, &oirq)) {
-               u8 line, pin;
-
-               /* If that fails, lets fallback to what is in the config
-                * space and map that through the default controller. We
-                * also set the type to level low since that's what PCI
-                * interrupts are. If your platform does differently, then
-                * either provide a proper interrupt tree or don't use this
-                * function.
-                */
-               if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
-                       return -1;
-               if (pin == 0)
-                       return -1;
-               if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
-                   line == 0xff) {
-                       return -1;
-               }
-               DBG(" -> no map ! Using irq line %d from PCI config\n", line);
-
-               virq = irq_create_mapping(NULL, line);
-               if (virq != NO_IRQ)
-                       set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
-       } else {
-               DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
-                   oirq.size, oirq.specifier[0], oirq.specifier[1],
-                   oirq.controller->full_name);
-
-               virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
-                                            oirq.size);
-       }
-       if(virq == NO_IRQ) {
-               DBG(" -> failed to map !\n");
-               return -1;
-       }
-
-       DBG(" -> mapped to linux irq %d\n", virq);
-
-       pci_dev->irq = virq;
-
-       return 0;
-}
-EXPORT_SYMBOL(pci_read_irq_line);
-
-void pci_resource_to_user(const struct pci_dev *dev, int bar,
-                         const struct resource *rsrc,
-                         resource_size_t *start, resource_size_t *end)
-{
-       struct pci_controller *hose = pci_bus_to_host(dev->bus);
-       resource_size_t offset = 0;
-
-       if (hose == NULL)
-               return;
-
-       if (rsrc->flags & IORESOURCE_IO)
-               offset = (unsigned long)hose->io_base_virt - pci_io_base;
-
-       /* We pass a fully fixed up address to userland for MMIO instead of
-        * a BAR value because X is lame and expects to be able to use that
-        * to pass to /dev/mem !
-        *
-        * That means that we'll have potentially 64 bits values where some
-        * userland apps only expect 32 (like X itself since it thinks only
-        * Sparc has 64 bits MMIO) but if we don't do that, we break it on
-        * 32 bits CHRPs :-(
-        *
-        * Hopefully, the sysfs insterface is immune to that gunk. Once X
-        * has been fixed (and the fix spread enough), we can re-enable the
-        * 2 lines below and pass down a BAR value to userland. In that case
-        * we'll also have to re-enable the matching code in
-        * __pci_mmap_make_offset().
-        *
-        * BenH.
-        */
-#if 0
-       else if (rsrc->flags & IORESOURCE_MEM)
-               offset = hose->pci_mem_offset;
-#endif
-
-       *start = rsrc->start - offset;
-       *end = rsrc->end - offset;
-}
-
-struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
-{
-       if (!have_of)
-               return NULL;
-       while(node) {
-               struct pci_controller *hose, *tmp;
-               list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
-                       if (hose->arch_data == node)
-                               return hose;
-               node = node->parent;
-       }
-       return NULL;
-}
-
 unsigned long pci_address_to_pio(phys_addr_t address)
 {
        struct pci_controller *hose, *tmp;
@@ -1412,7 +914,7 @@ unsigned long pci_address_to_pio(phys_addr_t address)
                if (address >= hose->io_base_phys &&
                    address < (hose->io_base_phys + hose->pci_io_size)) {
                        unsigned long base =
-                               (unsigned long)hose->io_base_virt - pci_io_base;
+                               (unsigned long)hose->io_base_virt - _IO_BASE;
                        return base + (address - hose->io_base_phys);
                }
        }
index c96fa9bd35a4f0ecf056dff387ce824e8808fc8e..a20f1951a5ce7b6141f22480c723f83a8b0062f2 100644 (file)
@@ -67,7 +67,6 @@ EXPORT_SYMBOL(ISA_DMA_THRESHOLD);
 EXPORT_SYMBOL(DMA_MODE_READ);
 EXPORT_SYMBOL(DMA_MODE_WRITE);
 
-EXPORT_SYMBOL(do_signal);
 EXPORT_SYMBOL(transfer_to_handler);
 EXPORT_SYMBOL(do_IRQ);
 EXPORT_SYMBOL(machine_check_exception);
@@ -106,10 +105,6 @@ EXPORT_SYMBOL(isa_mem_base);
 EXPORT_SYMBOL(pci_dram_offset);
 EXPORT_SYMBOL(pci_alloc_consistent);
 EXPORT_SYMBOL(pci_free_consistent);
-EXPORT_SYMBOL(pci_bus_io_base);
-EXPORT_SYMBOL(pci_bus_io_base_phys);
-EXPORT_SYMBOL(pci_bus_mem_base_phys);
-EXPORT_SYMBOL(pci_bus_to_hose);
 #endif /* CONFIG_PCI */
 
 EXPORT_SYMBOL(start_thread);
index 6e2f03566b0dd8973f15bc4fac732ce4ff654692..84f000a45e3678cf4d18fa8b194681bc6cdbaf00 100644 (file)
@@ -219,22 +219,26 @@ void discard_lazy_cpu_state(void)
 }
 #endif /* CONFIG_SMP */
 
-#ifdef CONFIG_PPC_MERGE                /* XXX for now */
 int set_dabr(unsigned long dabr)
 {
+#ifdef CONFIG_PPC_MERGE                /* XXX for now */
        if (ppc_md.set_dabr)
                return ppc_md.set_dabr(dabr);
+#endif
 
+       /* XXX should we have a CPU_FTR_HAS_DABR ? */
+#if defined(CONFIG_PPC64) || defined(CONFIG_6xx)
        mtspr(SPRN_DABR, dabr);
+#endif
        return 0;
 }
-#endif
 
 #ifdef CONFIG_PPC64
 DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
-static DEFINE_PER_CPU(unsigned long, current_dabr);
 #endif
 
+static DEFINE_PER_CPU(unsigned long, current_dabr);
+
 struct task_struct *__switch_to(struct task_struct *prev,
        struct task_struct *new)
 {
@@ -299,12 +303,10 @@ struct task_struct *__switch_to(struct task_struct *prev,
 
 #endif /* CONFIG_SMP */
 
-#ifdef CONFIG_PPC64    /* for now */
        if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) {
                set_dabr(new->thread.dabr);
                __get_cpu_var(current_dabr) = new->thread.dabr;
        }
-#endif /* CONFIG_PPC64 */
 
        new_thread = &new->thread;
        old_thread = &current->thread;
@@ -473,12 +475,10 @@ void flush_thread(void)
 
        discard_lazy_cpu_state();
 
-#ifdef CONFIG_PPC64    /* for now */
        if (current->thread.dabr) {
                current->thread.dabr = 0;
                set_dabr(0);
        }
-#endif
 }
 
 void
index af42ddab3ab473ba7f9085c3a28d2f37fb4672c7..37ff99bd98b45ac892cab67a839b4110d68e26dd 100644 (file)
@@ -52,6 +52,7 @@
 #include <asm/pSeries_reconfig.h>
 #include <asm/pci-bridge.h>
 #include <asm/kexec.h>
+#include <asm/system.h>
 
 #ifdef DEBUG
 #define DBG(fmt...) printk(KERN_ERR fmt)
@@ -1005,7 +1006,7 @@ static void __init early_reserve_mem(void)
 
 void __init early_init_devtree(void *params)
 {
-       DBG(" -> early_init_devtree()\n");
+       DBG(" -> early_init_devtree(%p)\n", params);
 
        /* Setup flat device-tree pointer */
        initial_boot_params = params;
@@ -1055,8 +1056,6 @@ void __init early_init_devtree(void *params)
        DBG(" <- early_init_devtree()\n");
 }
 
-#undef printk
-
 int of_n_addr_cells(struct device_node* np)
 {
        const int *ip;
@@ -1375,8 +1374,17 @@ static void of_node_release(struct kref *kref)
        struct device_node *node = kref_to_device_node(kref);
        struct property *prop = node->properties;
 
-       if (!OF_IS_DYNAMIC(node))
+       /* We should never be releasing nodes that haven't been detached. */
+       if (!of_node_check_flag(node, OF_DETACHED)) {
+               printk("WARNING: Bad of_node_put() on %s\n", node->full_name);
+               dump_stack();
+               kref_init(&node->kref);
+               return;
+       }
+
+       if (!of_node_check_flag(node, OF_DYNAMIC))
                return;
+
        while (prop) {
                struct property *next = prop->next;
                kfree(prop->name);
@@ -1432,6 +1440,8 @@ void of_detach_node(const struct device_node *np)
        write_lock(&devtree_lock);
 
        parent = np->parent;
+       if (!parent)
+               goto out_unlock;
 
        if (allnodes == np)
                allnodes = np->allnext;
@@ -1455,6 +1465,9 @@ void of_detach_node(const struct device_node *np)
                prevsib->sibling = np->sibling;
        }
 
+       of_node_set_flag(np, OF_DETACHED);
+
+out_unlock:
        write_unlock(&devtree_lock);
 }
 
@@ -1716,22 +1729,18 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
 }
 EXPORT_SYMBOL(of_get_cpu_node);
 
-#ifdef DEBUG
+#if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
 static struct debugfs_blob_wrapper flat_dt_blob;
 
 static int __init export_flat_device_tree(void)
 {
        struct dentry *d;
 
-       d = debugfs_create_dir("powerpc", NULL);
-       if (!d)
-               return 1;
-
        flat_dt_blob.data = initial_boot_params;
        flat_dt_blob.size = initial_boot_params->totalsize;
 
        d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR,
-                               d, &flat_dt_blob);
+                               powerpc_debugfs_root, &flat_dt_blob);
        if (!d)
                return 1;
 
index d6047c441034935d01e8ef351e87482f5fd0fb9d..a1d582e38627492ace142363659cac979969640f 100644 (file)
@@ -635,6 +635,7 @@ static void __init early_cmdline_parse(void)
 /* ibm,dynamic-reconfiguration-memory property supported */
 #define OV5_DRCONF_MEMORY      0x20
 #define OV5_LARGE_PAGES                0x10    /* large pages supported */
+#define OV5_DONATE_DEDICATE_CPU 0x02   /* donate dedicated CPU support */
 /* PCIe/MSI support.  Without MSI full PCIe is not supported */
 #ifdef CONFIG_PCI_MSI
 #define OV5_MSI                        0x01    /* PCIe/MSI support */
@@ -685,7 +686,8 @@ static unsigned char ibm_architecture_vec[] = {
        /* option vector 5: PAPR/OF options */
        3 - 2,                          /* length */
        0,                              /* don't ignore, don't halt */
-       OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | OV5_MSI,
+       OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY |
+       OV5_DONATE_DEDICATE_CPU | OV5_MSI,
 };
 
 /* Old method - ELF header with PT_NOTE sections */
diff --git a/arch/powerpc/kernel/ptrace-common.h b/arch/powerpc/kernel/ptrace-common.h
deleted file mode 100644 (file)
index 8797ae7..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- *    Copyright (c) 2002 Stephen Rothwell, IBM Coproration
- *    Extracted from ptrace.c and ptrace32.c
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file README.legal in the main directory of
- * this archive for more details.
- */
-
-#ifndef _PPC64_PTRACE_COMMON_H
-#define _PPC64_PTRACE_COMMON_H
-
-#include <asm/system.h>
-
-/*
- * Set of msr bits that gdb can change on behalf of a process.
- */
-#define MSR_DEBUGCHANGE        (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1)
-
-/*
- * Get contents of register REGNO in task TASK.
- */
-static inline unsigned long get_reg(struct task_struct *task, int regno)
-{
-       unsigned long tmp = 0;
-
-       /*
-        * Put the correct FP bits in, they might be wrong as a result
-        * of our lazy FP restore.
-        */
-       if (regno == PT_MSR) {
-               tmp = ((unsigned long *)task->thread.regs)[PT_MSR];
-               tmp |= task->thread.fpexc_mode;
-       } else if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) {
-               tmp = ((unsigned long *)task->thread.regs)[regno];
-       }
-
-       return tmp;
-}
-
-/*
- * Write contents of register REGNO in task TASK.
- */
-static inline int put_reg(struct task_struct *task, int regno,
-                         unsigned long data)
-{
-       if (regno < PT_SOFTE) {
-               if (regno == PT_MSR)
-                       data = (data & MSR_DEBUGCHANGE)
-                               | (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
-               ((unsigned long *)task->thread.regs)[regno] = data;
-               return 0;
-       }
-       return -EIO;
-}
-
-static inline void set_single_step(struct task_struct *task)
-{
-       struct pt_regs *regs = task->thread.regs;
-       if (regs != NULL)
-               regs->msr |= MSR_SE;
-       set_tsk_thread_flag(task, TIF_SINGLESTEP);
-}
-
-static inline void clear_single_step(struct task_struct *task)
-{
-       struct pt_regs *regs = task->thread.regs;
-       if (regs != NULL)
-               regs->msr &= ~MSR_SE;
-       clear_tsk_thread_flag(task, TIF_SINGLESTEP);
-}
-
-#ifdef CONFIG_ALTIVEC
-/*
- * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
- * The transfer totals 34 quadword.  Quadwords 0-31 contain the
- * corresponding vector registers.  Quadword 32 contains the vscr as the
- * last word (offset 12) within that quadword.  Quadword 33 contains the
- * vrsave as the first word (offset 0) within the quadword.
- *
- * This definition of the VMX state is compatible with the current PPC32
- * ptrace interface.  This allows signal handling and ptrace to use the
- * same structures.  This also simplifies the implementation of a bi-arch
- * (combined (32- and 64-bit) gdb.
- */
-
-/*
- * Get contents of AltiVec register state in task TASK
- */
-static inline int get_vrregs(unsigned long __user *data,
-                            struct task_struct *task)
-{
-       unsigned long regsize;
-
-       /* copy AltiVec registers VR[0] .. VR[31] */
-       regsize = 32 * sizeof(vector128);
-       if (copy_to_user(data, task->thread.vr, regsize))
-               return -EFAULT;
-       data += (regsize / sizeof(unsigned long));
-
-       /* copy VSCR */
-       regsize = 1 * sizeof(vector128);
-       if (copy_to_user(data, &task->thread.vscr, regsize))
-               return -EFAULT;
-       data += (regsize / sizeof(unsigned long));
-
-       /* copy VRSAVE */
-       if (put_user(task->thread.vrsave, (u32 __user *)data))
-               return -EFAULT;
-
-       return 0;
-}
-
-/*
- * Write contents of AltiVec register state into task TASK.
- */
-static inline int set_vrregs(struct task_struct *task,
-                            unsigned long __user *data)
-{
-       unsigned long regsize;
-
-       /* copy AltiVec registers VR[0] .. VR[31] */
-       regsize = 32 * sizeof(vector128);
-       if (copy_from_user(task->thread.vr, data, regsize))
-               return -EFAULT;
-       data += (regsize / sizeof(unsigned long));
-
-       /* copy VSCR */
-       regsize = 1 * sizeof(vector128);
-       if (copy_from_user(&task->thread.vscr, data, regsize))
-               return -EFAULT;
-       data += (regsize / sizeof(unsigned long));
-
-       /* copy VRSAVE */
-       if (get_user(task->thread.vrsave, (u32 __user *)data))
-               return -EFAULT;
-
-       return 0;
-}
-#endif
-
-static inline int ptrace_set_debugreg(struct task_struct *task,
-                                     unsigned long addr, unsigned long data)
-{
-       /* We only support one DABR and no IABRS at the moment */
-       if (addr > 0)
-               return -EINVAL;
-
-       /* The bottom 3 bits are flags */
-       if ((data & ~0x7UL) >= TASK_SIZE)
-               return -EIO;
-
-       /* Ensure translation is on */
-       if (data && !(data & DABR_TRANSLATION))
-               return -EIO;
-
-       task->thread.dabr = data;
-       return 0;
-}
-
-#endif /* _PPC64_PTRACE_COMMON_H */
index bf76562167c34dc4334332b65cdc4bc14f90aa6e..0fb53950da439fb4ba1bd669a5e3f0111d09bc98 100644 (file)
 #include <asm/pgtable.h>
 #include <asm/system.h>
 
-#ifdef CONFIG_PPC64
-#include "ptrace-common.h"
-#endif
+/*
+ * does not yet catch signals sent when the child dies.
+ * in exit.c or in signal.c.
+ */
 
-#ifdef CONFIG_PPC32
 /*
  * Set of msr bits that gdb can change on behalf of a process.
  */
 #else
 #define MSR_DEBUGCHANGE        (MSR_SE | MSR_BE)
 #endif
-#endif /* CONFIG_PPC32 */
 
 /*
- * does not yet catch signals sent when the child dies.
- * in exit.c or in signal.c.
+ * Max register writeable via put_reg
  */
-
 #ifdef CONFIG_PPC32
+#define PT_MAX_PUT_REG PT_MQ
+#else
+#define PT_MAX_PUT_REG PT_CCR
+#endif
+
 /*
  * Get contents of register REGNO in task TASK.
  */
-static inline unsigned long get_reg(struct task_struct *task, int regno)
+unsigned long ptrace_get_reg(struct task_struct *task, int regno)
 {
-       if (regno < sizeof(struct pt_regs) / sizeof(unsigned long)
-           && task->thread.regs != NULL)
+       unsigned long tmp = 0;
+
+       if (task->thread.regs == NULL)
+               return -EIO;
+
+       if (regno == PT_MSR) {
+               tmp = ((unsigned long *)task->thread.regs)[PT_MSR];
+               return tmp | task->thread.fpexc_mode;
+       }
+
+       if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long)))
                return ((unsigned long *)task->thread.regs)[regno];
-       return (0);
+
+       return -EIO;
 }
 
 /*
  * Write contents of register REGNO in task TASK.
  */
-static inline int put_reg(struct task_struct *task, int regno,
-                         unsigned long data)
+int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data)
 {
-       if (regno <= PT_MQ && task->thread.regs != NULL) {
+       if (task->thread.regs == NULL)
+               return -EIO;
+
+       if (regno <= PT_MAX_PUT_REG || regno == PT_TRAP) {
                if (regno == PT_MSR)
                        data = (data & MSR_DEBUGCHANGE)
                                | (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
+               /* We prevent mucking around with the reserved area of trap
+                * which are used internally by the kernel
+                */
+               if (regno == PT_TRAP)
+                       data &= 0xfff0;
                ((unsigned long *)task->thread.regs)[regno] = data;
                return 0;
        }
        return -EIO;
 }
 
+
+static int get_fpregs(void __user *data, struct task_struct *task,
+                     int has_fpscr)
+{
+       unsigned int count = has_fpscr ? 33 : 32;
+
+       if (copy_to_user(data, task->thread.fpr, count * sizeof(double)))
+               return -EFAULT;
+       return 0;
+}
+
+static int set_fpregs(void __user *data, struct task_struct *task,
+                     int has_fpscr)
+{
+       unsigned int count = has_fpscr ? 33 : 32;
+
+       if (copy_from_user(task->thread.fpr, data, count * sizeof(double)))
+               return -EFAULT;
+       return 0;
+}
+
+
 #ifdef CONFIG_ALTIVEC
+/*
+ * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
+ * The transfer totals 34 quadword.  Quadwords 0-31 contain the
+ * corresponding vector registers.  Quadword 32 contains the vscr as the
+ * last word (offset 12) within that quadword.  Quadword 33 contains the
+ * vrsave as the first word (offset 0) within the quadword.
+ *
+ * This definition of the VMX state is compatible with the current PPC32
+ * ptrace interface.  This allows signal handling and ptrace to use the
+ * same structures.  This also simplifies the implementation of a bi-arch
+ * (combined (32- and 64-bit) gdb.
+ */
+
 /*
  * Get contents of AltiVec register state in task TASK
  */
-static inline int get_vrregs(unsigned long __user *data, struct task_struct *task)
+static int get_vrregs(unsigned long __user *data, struct task_struct *task)
 {
-       int i, j;
-
-       if (!access_ok(VERIFY_WRITE, data, 133 * sizeof(unsigned long)))
-               return -EFAULT;
+       unsigned long regsize;
 
        /* copy AltiVec registers VR[0] .. VR[31] */
-       for (i = 0; i < 32; i++)
-               for (j = 0; j < 4; j++, data++)
-                       if (__put_user(task->thread.vr[i].u[j], data))
-                               return -EFAULT;
+       regsize = 32 * sizeof(vector128);
+       if (copy_to_user(data, task->thread.vr, regsize))
+               return -EFAULT;
+       data += (regsize / sizeof(unsigned long));
 
        /* copy VSCR */
-       for (i = 0; i < 4; i++, data++)
-               if (__put_user(task->thread.vscr.u[i], data))
-                       return -EFAULT;
+       regsize = 1 * sizeof(vector128);
+       if (copy_to_user(data, &task->thread.vscr, regsize))
+               return -EFAULT;
+       data += (regsize / sizeof(unsigned long));
 
-        /* copy VRSAVE */
-       if (__put_user(task->thread.vrsave, data))
+       /* copy VRSAVE */
+       if (put_user(task->thread.vrsave, (u32 __user *)data))
                return -EFAULT;
 
        return 0;
@@ -115,31 +167,29 @@ static inline int get_vrregs(unsigned long __user *data, struct task_struct *tas
 /*
  * Write contents of AltiVec register state into task TASK.
  */
-static inline int set_vrregs(struct task_struct *task, unsigned long __user *data)
+static int set_vrregs(struct task_struct *task, unsigned long __user *data)
 {
-       int i, j;
-
-       if (!access_ok(VERIFY_READ, data, 133 * sizeof(unsigned long)))
-               return -EFAULT;
+       unsigned long regsize;
 
        /* copy AltiVec registers VR[0] .. VR[31] */
-       for (i = 0; i < 32; i++)
-               for (j = 0; j < 4; j++, data++)
-                       if (__get_user(task->thread.vr[i].u[j], data))
-                               return -EFAULT;
+       regsize = 32 * sizeof(vector128);
+       if (copy_from_user(task->thread.vr, data, regsize))
+               return -EFAULT;
+       data += (regsize / sizeof(unsigned long));
 
        /* copy VSCR */
-       for (i = 0; i < 4; i++, data++)
-               if (__get_user(task->thread.vscr.u[i], data))
-                       return -EFAULT;
+       regsize = 1 * sizeof(vector128);
+       if (copy_from_user(&task->thread.vscr, data, regsize))
+               return -EFAULT;
+       data += (regsize / sizeof(unsigned long));
 
        /* copy VRSAVE */
-       if (__get_user(task->thread.vrsave, data))
+       if (get_user(task->thread.vrsave, (u32 __user *)data))
                return -EFAULT;
 
        return 0;
 }
-#endif
+#endif /* CONFIG_ALTIVEC */
 
 #ifdef CONFIG_SPE
 
@@ -156,7 +206,7 @@ static inline int set_vrregs(struct task_struct *task, unsigned long __user *dat
 /*
  * Get contents of SPE register state in task TASK.
  */
-static inline int get_evrregs(unsigned long *data, struct task_struct *task)
+static int get_evrregs(unsigned long *data, struct task_struct *task)
 {
        int i;
 
@@ -182,7 +232,7 @@ static inline int get_evrregs(unsigned long *data, struct task_struct *task)
 /*
  * Write contents of SPE register state into task TASK.
  */
-static inline int set_evrregs(struct task_struct *task, unsigned long *data)
+static int set_evrregs(struct task_struct *task, unsigned long *data)
 {
        int i;
 
@@ -205,8 +255,8 @@ static inline int set_evrregs(struct task_struct *task, unsigned long *data)
 }
 #endif /* CONFIG_SPE */
 
-static inline void
-set_single_step(struct task_struct *task)
+
+static void set_single_step(struct task_struct *task)
 {
        struct pt_regs *regs = task->thread.regs;
 
@@ -221,8 +271,7 @@ set_single_step(struct task_struct *task)
        set_tsk_thread_flag(task, TIF_SINGLESTEP);
 }
 
-static inline void
-clear_single_step(struct task_struct *task)
+static void clear_single_step(struct task_struct *task)
 {
        struct pt_regs *regs = task->thread.regs;
 
@@ -236,7 +285,25 @@ clear_single_step(struct task_struct *task)
        }
        clear_tsk_thread_flag(task, TIF_SINGLESTEP);
 }
-#endif /* CONFIG_PPC32 */
+
+static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
+                              unsigned long data)
+{
+       /* We only support one DABR and no IABRS at the moment */
+       if (addr > 0)
+               return -EINVAL;
+
+       /* The bottom 3 bits are flags */
+       if ((data & ~0x7UL) >= TASK_SIZE)
+               return -EIO;
+
+       /* Ensure translation is on */
+       if (data && !(data & DABR_TRANSLATION))
+               return -EIO;
+
+       task->thread.dabr = data;
+       return 0;
+}
 
 /*
  * Called by kernel/ptrace.c when detaching..
@@ -249,6 +316,62 @@ void ptrace_disable(struct task_struct *child)
        clear_single_step(child);
 }
 
+/*
+ * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
+ * we mark them as obsolete now, they will be removed in a future version
+ */
+static long arch_ptrace_old(struct task_struct *child, long request, long addr,
+                           long data)
+{
+       int ret = -EPERM;
+
+       switch(request) {
+       case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
+               int i;
+               unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+               unsigned long __user *tmp = (unsigned long __user *)addr;
+
+               for (i = 0; i < 32; i++) {
+                       ret = put_user(*reg, tmp);
+                       if (ret)
+                               break;
+                       reg++;
+                       tmp++;
+               }
+               break;
+       }
+
+       case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
+               int i;
+               unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+               unsigned long __user *tmp = (unsigned long __user *)addr;
+
+               for (i = 0; i < 32; i++) {
+                       ret = get_user(*reg, tmp);
+                       if (ret)
+                               break;
+                       reg++;
+                       tmp++;
+               }
+               break;
+       }
+
+       case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
+               flush_fp_to_thread(child);
+               ret = get_fpregs((void __user *)addr, child, 0);
+               break;
+       }
+
+       case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
+               flush_fp_to_thread(child);
+               ret = set_fpregs((void __user *)addr, child, 0);
+               break;
+       }
+
+       }
+       return ret;
+}
+
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
        int ret = -EPERM;
@@ -284,11 +407,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 #endif
                        break;
 
-#ifdef CONFIG_PPC32
                CHECK_FULL_REGS(child->thread.regs);
-#endif
                if (index < PT_FPR0) {
-                       tmp = get_reg(child, (int) index);
+                       tmp = ptrace_get_reg(child, (int) index);
                } else {
                        flush_fp_to_thread(child);
                        tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
@@ -323,13 +444,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 #endif
                        break;
 
-#ifdef CONFIG_PPC32
                CHECK_FULL_REGS(child->thread.regs);
-#endif
-               if (index == PT_ORIG_R3)
-                       break;
                if (index < PT_FPR0) {
-                       ret = put_reg(child, index, data);
+                       ret = ptrace_put_reg(child, index, data);
                } else {
                        flush_fp_to_thread(child);
                        ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data;
@@ -384,7 +501,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                break;
        }
 
-#ifdef CONFIG_PPC64
        case PTRACE_GET_DEBUGREG: {
                ret = -EINVAL;
                /* We only support one DABR and no IABRS at the moment */
@@ -398,73 +514,61 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
        case PTRACE_SET_DEBUGREG:
                ret = ptrace_set_debugreg(child, addr, data);
                break;
-#endif
 
        case PTRACE_DETACH:
                ret = ptrace_detach(child, data);
                break;
 
-       case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
-               int i;
-               unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
-               unsigned long __user *tmp = (unsigned long __user *)addr;
-
-               for (i = 0; i < 32; i++) {
-                       ret = put_user(*reg, tmp);
-                       if (ret)
-                               break;
-                       reg++;
-                       tmp++;
+#ifdef CONFIG_PPC64
+       case PTRACE_GETREGS64:
+#endif
+       case PTRACE_GETREGS: { /* Get all pt_regs from the child. */
+               int ui;
+               if (!access_ok(VERIFY_WRITE, (void __user *)data,
+                              sizeof(struct pt_regs))) {
+                       ret = -EIO;
+                       break;
+               }
+               ret = 0;
+               for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
+                       ret |= __put_user(ptrace_get_reg(child, ui),
+                                         (unsigned long __user *) data);
+                       data += sizeof(long);
                }
                break;
        }
 
-       case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
-               int i;
-               unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
-               unsigned long __user *tmp = (unsigned long __user *)addr;
-
-               for (i = 0; i < 32; i++) {
-                       ret = get_user(*reg, tmp);
+#ifdef CONFIG_PPC64
+       case PTRACE_SETREGS64:
+#endif
+       case PTRACE_SETREGS: { /* Set all gp regs in the child. */
+               unsigned long tmp;
+               int ui;
+               if (!access_ok(VERIFY_READ, (void __user *)data,
+                              sizeof(struct pt_regs))) {
+                       ret = -EIO;
+                       break;
+               }
+               ret = 0;
+               for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
+                       ret = __get_user(tmp, (unsigned long __user *) data);
                        if (ret)
                                break;
-                       reg++;
-                       tmp++;
+                       ptrace_put_reg(child, ui, tmp);
+                       data += sizeof(long);
                }
                break;
        }
 
-       case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
-               int i;
-               unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
-               unsigned long __user *tmp = (unsigned long __user *)addr;
-
+       case PTRACE_GETFPREGS: { /* Get the child FPU state (FPR0...31 + FPSCR) */
                flush_fp_to_thread(child);
-
-               for (i = 0; i < 32; i++) {
-                       ret = put_user(*reg, tmp);
-                       if (ret)
-                               break;
-                       reg++;
-                       tmp++;
-               }
+               ret = get_fpregs((void __user *)data, child, 1);
                break;
        }
 
-       case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
-               int i;
-               unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
-               unsigned long __user *tmp = (unsigned long __user *)addr;
-
+       case PTRACE_SETFPREGS: { /* Set the child FPU state (FPR0...31 + FPSCR) */
                flush_fp_to_thread(child);
-
-               for (i = 0; i < 32; i++) {
-                       ret = get_user(*reg, tmp);
-                       if (ret)
-                               break;
-                       reg++;
-                       tmp++;
-               }
+               ret = set_fpregs((void __user *)data, child, 1);
                break;
        }
 
@@ -499,11 +603,18 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                break;
 #endif
 
+       /* Old reverse args ptrace callss */
+       case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
+       case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
+       case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */
+       case PPC_PTRACE_SETFPREGS: /* Get FPRs 0 - 31. */
+               ret = arch_ptrace_old(child, request, addr, data);
+               break;
+
        default:
                ret = ptrace_request(child, request, addr, data);
                break;
        }
-
        return ret;
 }
 
index 9b9a230349bc8fea17ae9b247641158efd6617e1..9e6baeac0fb1e569e4fe35bd279d311318d93af2 100644 (file)
 #include <asm/pgtable.h>
 #include <asm/system.h>
 
-#include "ptrace-common.h"
-
 /*
  * does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
  */
 
+/*
+ * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
+ * we mark them as obsolete now, they will be removed in a future version
+ */
+static long compat_ptrace_old(struct task_struct *child, long request,
+                             long addr, long data)
+{
+       int ret = -EPERM;
+
+       switch(request) {
+       case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
+               int i;
+               unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+               unsigned int __user *tmp = (unsigned int __user *)addr;
+
+               for (i = 0; i < 32; i++) {
+                       ret = put_user(*reg, tmp);
+                       if (ret)
+                               break;
+                       reg++;
+                       tmp++;
+               }
+               break;
+       }
+
+       case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
+               int i;
+               unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
+               unsigned int __user *tmp = (unsigned int __user *)addr;
+
+               for (i = 0; i < 32; i++) {
+                       ret = get_user(*reg, tmp);
+                       if (ret)
+                               break;
+                       reg++;
+                       tmp++;
+               }
+               break;
+       }
+
+       }
+       return ret;
+}
+
 long compat_sys_ptrace(int request, int pid, unsigned long addr,
                       unsigned long data)
 {
@@ -123,7 +165,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
                        break;
 
                if (index < PT_FPR0) {
-                       tmp = get_reg(child, index);
+                       tmp = ptrace_get_reg(child, index);
                } else {
                        flush_fp_to_thread(child);
                        /*
@@ -162,7 +204,9 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
                else
                        part = 0;  /* want the 1st half of the register (left-most). */
 
-               /* Validate the input - check to see if address is on the wrong boundary or beyond the end of the user area */
+               /* Validate the input - check to see if address is on the wrong boundary
+                * or beyond the end of the user area
+                */
                if ((addr & 3) || numReg > PT_FPSCR)
                        break;
 
@@ -170,7 +214,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
                        flush_fp_to_thread(child);
                        tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0];
                } else { /* register within PT_REGS struct */
-                       tmp = get_reg(child, numReg);
+                       tmp = ptrace_get_reg(child, numReg);
                } 
                reg32bits = ((u32*)&tmp)[part];
                ret = put_user(reg32bits, (u32 __user *)data);
@@ -226,10 +270,8 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
                if ((addr & 3) || (index > PT_FPSCR32))
                        break;
 
-               if (index == PT_ORIG_R3)
-                       break;
                if (index < PT_FPR0) {
-                       ret = put_reg(child, index, data);
+                       ret = ptrace_put_reg(child, index, data);
                } else {
                        flush_fp_to_thread(child);
                        /*
@@ -258,70 +300,25 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
                /* Determine which register the user wants */
                index = (u64)addr >> 2;
                numReg = index / 2;
+
                /*
                 * Validate the input - check to see if address is on the
                 * wrong boundary or beyond the end of the user area
                 */
                if ((addr & 3) || (numReg > PT_FPSCR))
                        break;
-               /* Insure it is a register we let them change */
-               if ((numReg == PT_ORIG_R3)
-                               || ((numReg > PT_CCR) && (numReg < PT_FPR0)))
-                       break;
-               if (numReg >= PT_FPR0) {
+               if (numReg < PT_FPR0) {
+                       unsigned long freg = ptrace_get_reg(child, numReg);
+                       if (index % 2)
+                               freg = (freg & ~0xfffffffful) | (data & 0xfffffffful);
+                       else
+                               freg = (freg & 0xfffffffful) | (data << 32);
+                       ret = ptrace_put_reg(child, numReg, freg);
+               } else {
                        flush_fp_to_thread(child);
+                       ((unsigned int *)child->thread.regs)[index] = data;
+                       ret = 0;
                }
-               if (numReg == PT_MSR)
-                       data = (data & MSR_DEBUGCHANGE)
-                               | (child->thread.regs->msr & ~MSR_DEBUGCHANGE);
-               ((u32*)child->thread.regs)[index] = data;
-               ret = 0;
-               break;
-       }
-
-       case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
-       case PTRACE_CONT: { /* restart after signal. */
-               ret = -EIO;
-               if (!valid_signal(data))
-                       break;
-               if (request == PTRACE_SYSCALL)
-                       set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-               else
-                       clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-               child->exit_code = data;
-               /* make sure the single step bit is not set. */
-               clear_single_step(child);
-               wake_up_process(child);
-               ret = 0;
-               break;
-       }
-
-       /*
-        * make the child exit.  Best I can do is send it a sigkill.
-        * perhaps it should be put in the status that it wants to
-        * exit.
-        */
-       case PTRACE_KILL: {
-               ret = 0;
-               if (child->exit_state == EXIT_ZOMBIE)   /* already dead */
-                       break;
-               child->exit_code = SIGKILL;
-               /* make sure the single step bit is not set. */
-               clear_single_step(child);
-               wake_up_process(child);
-               break;
-       }
-
-       case PTRACE_SINGLESTEP: {  /* set the trap flag. */
-               ret = -EIO;
-               if (!valid_signal(data))
-                       break;
-               clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-               set_single_step(child);
-               child->exit_code = data;
-               /* give it a chance to run. */
-               wake_up_process(child);
-               ret = 0;
                break;
        }
 
@@ -334,95 +331,67 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
                break;
        }
 
-       case PTRACE_SET_DEBUGREG:
-               ret = ptrace_set_debugreg(child, addr, data);
-               break;
-
-       case PTRACE_DETACH:
-               ret = ptrace_detach(child, data);
+       case PTRACE_GETEVENTMSG:
+               ret = put_user(child->ptrace_message, (unsigned int __user *) data);
                break;
 
-       case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
-               int i;
-               unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
-               unsigned int __user *tmp = (unsigned int __user *)addr;
-
-               for (i = 0; i < 32; i++) {
-                       ret = put_user(*reg, tmp);
-                       if (ret)
-                               break;
-                       reg++;
-                       tmp++;
+       case PTRACE_GETREGS: { /* Get all pt_regs from the child. */
+               int ui;
+               if (!access_ok(VERIFY_WRITE, (void __user *)data,
+                              PT_REGS_COUNT * sizeof(int))) {
+                       ret = -EIO;
+                       break;
                }
-               break;
-       }
-
-       case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
-               int i;
-               unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
-               unsigned int __user *tmp = (unsigned int __user *)addr;
-
-               for (i = 0; i < 32; i++) {
-                       ret = get_user(*reg, tmp);
-                       if (ret)
-                               break;
-                       reg++;
-                       tmp++;
+               ret = 0;
+               for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
+                       ret |= __put_user(ptrace_get_reg(child, ui),
+                                         (unsigned int __user *) data);
+                       data += sizeof(int);
                }
                break;
        }
 
-       case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
-               int i;
-               unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
-               unsigned int __user *tmp = (unsigned int __user *)addr;
-
-               flush_fp_to_thread(child);
-
-               for (i = 0; i < 32; i++) {
-                       ret = put_user(*reg, tmp);
-                       if (ret)
-                               break;
-                       reg++;
-                       tmp++;
+       case PTRACE_SETREGS: { /* Set all gp regs in the child. */
+               unsigned long tmp;
+               int ui;
+               if (!access_ok(VERIFY_READ, (void __user *)data,
+                              PT_REGS_COUNT * sizeof(int))) {
+                       ret = -EIO;
+                       break;
                }
-               break;
-       }
-
-       case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
-               int i;
-               unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
-               unsigned int __user *tmp = (unsigned int __user *)addr;
-
-               flush_fp_to_thread(child);
-
-               for (i = 0; i < 32; i++) {
-                       ret = get_user(*reg, tmp);
+               ret = 0;
+               for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
+                       ret = __get_user(tmp, (unsigned int __user *) data);
                        if (ret)
                                break;
-                       reg++;
-                       tmp++;
+                       ptrace_put_reg(child, ui, tmp);
+                       data += sizeof(int);
                }
                break;
        }
 
-       case PTRACE_GETEVENTMSG:
-               ret = put_user(child->ptrace_message, (unsigned int __user *) data);
-               break;
-
-#ifdef CONFIG_ALTIVEC
+       case PTRACE_GETFPREGS:
+       case PTRACE_SETFPREGS:
        case PTRACE_GETVRREGS:
-               /* Get the child altivec register state. */
-               flush_altivec_to_thread(child);
-               ret = get_vrregs((unsigned long __user *)data, child);
+       case PTRACE_SETVRREGS:
+       case PTRACE_GETREGS64:
+       case PTRACE_SETREGS64:
+       case PPC_PTRACE_GETFPREGS:
+       case PPC_PTRACE_SETFPREGS:
+       case PTRACE_KILL:
+       case PTRACE_SINGLESTEP:
+       case PTRACE_DETACH:
+       case PTRACE_SET_DEBUGREG:
+       case PTRACE_SYSCALL:
+       case PTRACE_CONT:
+               ret = arch_ptrace(child, request, addr, data);
                break;
 
-       case PTRACE_SETVRREGS:
-               /* Set the child altivec register state. */
-               flush_altivec_to_thread(child);
-               ret = set_vrregs(child, (unsigned long __user *)data);
+       /* Old reverse args ptrace callss */
+       case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
+       case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
+               ret = compat_ptrace_old(child, request, addr, data);
                break;
-#endif
 
        default:
                ret = ptrace_request(child, request, addr, data);
index f2286822be0948c5dad8e0df0cd9b80aa4851650..a5de6211b97ad6b8af75dfb2611907ce8d09b689 100644 (file)
@@ -278,10 +278,8 @@ void __init find_and_init_phbs(void)
 {
        struct device_node *node;
        struct pci_controller *phb;
-       unsigned int index;
        struct device_node *root = of_find_node_by_path("/");
 
-       index = 0;
        for (node = of_get_next_child(root, NULL);
             node != NULL;
             node = of_get_next_child(root, node)) {
@@ -295,8 +293,7 @@ void __init find_and_init_phbs(void)
                        continue;
                rtas_setup_phb(phb);
                pci_process_bridge_OF_ranges(phb, node, 0);
-               pci_setup_phb_io(phb, index == 0);
-               index++;
+               isa_bridge_find_early(phb);
        }
 
        of_node_put(root);
@@ -335,7 +332,7 @@ int pcibios_remove_root_bus(struct pci_controller *phb)
                return 1;
        }
 
-       rc = unmap_bus_range(b);
+       rc = pcibios_unmap_io_space(b);
        if (rc) {
                printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",
                        __FUNCTION__, b->name);
index ed07a198f8d665a9b9b90461cb48d464f57abd16..4924c48cb1ffc64df621b6d2dd6790c2b0683100 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/unistd.h>
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
+#include <linux/debugfs.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/processor.h>
@@ -486,6 +487,14 @@ int check_legacy_ioport(unsigned long base_port)
 
        switch(base_port) {
        case I8042_DATA_REG:
+               if (!(np = of_find_compatible_node(NULL, NULL, "pnpPNP,303")))
+                       np = of_find_compatible_node(NULL, NULL, "pnpPNP,f03");
+               if (np) {
+                       parent = of_get_parent(np);
+                       of_node_put(np);
+                       np = parent;
+                       break;
+               }
                np = of_find_node_by_type(NULL, "8042");
                break;
        case FDC_BASE: /* FDC1 */
@@ -571,3 +580,15 @@ static int __init check_cache_coherency(void)
 
 late_initcall(check_cache_coherency);
 #endif /* CONFIG_CHECK_CACHE_COHERENCY */
+
+#ifdef CONFIG_DEBUG_FS
+struct dentry *powerpc_debugfs_root;
+
+static int powerpc_debugfs_init(void)
+{
+       powerpc_debugfs_root = debugfs_create_dir("powerpc", NULL);
+
+       return powerpc_debugfs_root == NULL;
+}
+arch_initcall(powerpc_debugfs_init);
+#endif
index 35f8f443c14f6c9dd383d967889577c9588d4363..7ec6ba56d83dfcb40385f954b72b6ce40ae30475 100644 (file)
@@ -262,13 +262,11 @@ void __init setup_arch(char **cmdline_p)
         * Systems with OF can look in the properties on the cpu node(s)
         * for a possibly more accurate value.
         */
-       if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) {
-               dcache_bsize = cur_cpu_spec->dcache_bsize;
-               icache_bsize = cur_cpu_spec->icache_bsize;
-               ucache_bsize = 0;
-       } else
-               ucache_bsize = dcache_bsize = icache_bsize
-                       = cur_cpu_spec->dcache_bsize;
+       dcache_bsize = cur_cpu_spec->dcache_bsize;
+       icache_bsize = cur_cpu_spec->icache_bsize;
+       ucache_bsize = 0;
+       if (cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE))
+               ucache_bsize = icache_bsize = dcache_bsize;
 
        /* reboot on panic */
        panic_timeout = 180;
index 6018178708a55f76be298d405c0fd8d76c9af6b2..bc43bba05cf84e3793dc01aa1b692364cecf331b 100644 (file)
@@ -350,13 +350,11 @@ void __init setup_system(void)
 {
        DBG(" -> setup_system()\n");
 
-       /* Apply the CPUs-specific and firmware specific fixups to kernel
-        * text (nop out sections not relevant to this CPU or this firmware)
+       /* Apply CPUs-specific fixups to kernel text (nop out sections
+        * not relevant to this CPU)
         */
        do_feature_fixups(cur_cpu_spec->cpu_features,
                          &__start___ftr_fixup, &__stop___ftr_fixup);
-       do_feature_fixups(powerpc_firmware_features,
-                         &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
 
        /*
         * Unflatten the device-tree passed by prom_init or kexec
@@ -394,6 +392,12 @@ void __init setup_system(void)
        if (ppc_md.init_early)
                ppc_md.init_early();
 
+       /* Apply firmware specific fixups to kernel text (nop out
+        * sections not relevant to this firmware)
+        */
+       do_feature_fixups(powerpc_firmware_features,
+                         &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
+
        /*
         * We can discover serial ports now since the above did setup the
         * hash table management for us, thus ioremap works. We do that early
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
new file mode 100644 (file)
index 0000000..c434d6c
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Common signal handling code for both 32 and 64 bits
+ *
+ *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
+ *    Extracted from signal_32.c and signal_64.c
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file README.legal in the main directory of
+ * this archive for more details.
+ */
+
+#include <linux/ptrace.h>
+#include <linux/signal.h>
+#include <asm/uaccess.h>
+#include <asm/unistd.h>
+
+#include "signal.h"
+
+/*
+ * Allocate space for the signal frame
+ */
+void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+                          size_t frame_size)
+{
+        unsigned long oldsp, newsp;
+
+        /* Default to using normal stack */
+        oldsp = regs->gpr[1];
+
+       /* Check for alt stack */
+       if ((ka->sa.sa_flags & SA_ONSTACK) &&
+           current->sas_ss_size && !on_sig_stack(oldsp))
+               oldsp = (current->sas_ss_sp + current->sas_ss_size);
+
+       /* Get aligned frame */
+       newsp = (oldsp - frame_size) & ~0xFUL;
+
+       /* Check access */
+       if (!access_ok(VERIFY_WRITE, (void __user *)newsp, oldsp - newsp))
+               return NULL;
+
+        return (void __user *)newsp;
+}
+
+
+/*
+ * Restore the user process's signal mask
+ */
+void restore_sigmask(sigset_t *set)
+{
+       sigdelsetmask(set, ~_BLOCKABLE);
+       spin_lock_irq(&current->sighand->siglock);
+       current->blocked = *set;
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
+}
+
+static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
+                                 int has_handler)
+{
+       unsigned long ret = regs->gpr[3];
+       int restart = 1;
+
+       /* syscall ? */
+       if (TRAP(regs) != 0x0C00)
+               return;
+
+       /* error signalled ? */
+       if (!(regs->ccr & 0x10000000))
+               return;
+
+       switch (ret) {
+       case ERESTART_RESTARTBLOCK:
+       case ERESTARTNOHAND:
+               /* ERESTARTNOHAND means that the syscall should only be
+                * restarted if there was no handler for the signal, and since
+                * we only get here if there is a handler, we dont restart.
+                */
+               restart = !has_handler;
+               break;
+       case ERESTARTSYS:
+               /* ERESTARTSYS means to restart the syscall if there is no
+                * handler or the handler was registered with SA_RESTART
+                */
+               restart = !has_handler || (ka->sa.sa_flags & SA_RESTART) != 0;
+               break;
+       case ERESTARTNOINTR:
+               /* ERESTARTNOINTR means that the syscall should be
+                * called again after the signal handler returns.
+                */
+               break;
+       default:
+               return;
+       }
+       if (restart) {
+               if (ret == ERESTART_RESTARTBLOCK)
+                       regs->gpr[0] = __NR_restart_syscall;
+               else
+                       regs->gpr[3] = regs->orig_gpr3;
+               regs->nip -= 4;
+               regs->result = 0;
+       } else {
+               regs->result = -EINTR;
+               regs->gpr[3] = EINTR;
+               regs->ccr |= 0x10000000;
+       }
+}
+
+int do_signal(sigset_t *oldset, struct pt_regs *regs)
+{
+       siginfo_t info;
+       int signr;
+       struct k_sigaction ka;
+       int ret;
+       int is32 = is_32bit_task();
+
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = &current->saved_sigmask;
+       else if (!oldset)
+               oldset = &current->blocked;
+
+       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+
+       /* Is there any syscall restart business here ? */
+       check_syscall_restart(regs, &ka, signr > 0);
+
+       if (signr <= 0) {
+               /* No signal to deliver -- put the saved sigmask back */
+               if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+                       clear_thread_flag(TIF_RESTORE_SIGMASK);
+                       sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+               }
+               return 0;               /* no signals delivered */
+       }
+
+        /*
+        * Reenable the DABR before delivering the signal to
+        * user space. The DABR will have been cleared if it
+        * triggered inside the kernel.
+        */
+       if (current->thread.dabr)
+               set_dabr(current->thread.dabr);
+
+       if (is32) {
+               if (ka.sa.sa_flags & SA_SIGINFO)
+                       ret = handle_rt_signal32(signr, &ka, &info, oldset,
+                                       regs);
+               else
+                       ret = handle_signal32(signr, &ka, &info, oldset,
+                                       regs);
+       } else {
+               ret = handle_rt_signal64(signr, &ka, &info, oldset, regs);
+       }
+
+       if (ret) {
+               spin_lock_irq(&current->sighand->siglock);
+               sigorsets(&current->blocked, &current->blocked,
+                         &ka.sa.sa_mask);
+               if (!(ka.sa.sa_flags & SA_NODEFER))
+                       sigaddset(&current->blocked, signr);
+               recalc_sigpending();
+               spin_unlock_irq(&current->sighand->siglock);
+
+               /*
+                * A signal was successfully delivered; the saved sigmask is in
+                * its frame, and we can clear the TIF_RESTORE_SIGMASK flag.
+                */
+               if (test_thread_flag(TIF_RESTORE_SIGMASK))
+                       clear_thread_flag(TIF_RESTORE_SIGMASK);
+       }
+
+       return ret;
+}
+
+long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
+               unsigned long r5, unsigned long r6, unsigned long r7,
+               unsigned long r8, struct pt_regs *regs)
+{
+       return do_sigaltstack(uss, uoss, regs->gpr[1]);
+}
diff --git a/arch/powerpc/kernel/signal.h b/arch/powerpc/kernel/signal.h
new file mode 100644 (file)
index 0000000..77efb3d
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
+ *    Extracted from signal_32.c and signal_64.c
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file README.legal in the main directory of
+ * this archive for more details.
+ */
+
+#ifndef _POWERPC_ARCH_SIGNAL_H
+#define _POWERPC_ARCH_SIGNAL_H
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+                                 size_t frame_size);
+extern void restore_sigmask(sigset_t *set);
+
+extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,
+                          siginfo_t *info, sigset_t *oldset,
+                          struct pt_regs *regs);
+
+extern int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
+                             siginfo_t *info, sigset_t *oldset,
+                             struct pt_regs *regs);
+
+
+#ifdef CONFIG_PPC64
+
+static inline int is_32bit_task(void)
+{
+       return test_thread_flag(TIF_32BIT);
+}
+
+extern int handle_rt_signal64(int signr, struct k_sigaction *ka,
+                             siginfo_t *info, sigset_t *set,
+                             struct pt_regs *regs);
+
+#else /* CONFIG_PPC64 */
+
+static inline int is_32bit_task(void)
+{
+       return 1;
+}
+
+static inline int handle_rt_signal64(int signr, struct k_sigaction *ka,
+                                    siginfo_t *info, sigset_t *set,
+                                    struct pt_regs *regs)
+{
+       return -EFAULT;
+}
+
+#endif /* !defined(CONFIG_PPC64) */
+
+#endif  /* _POWERPC_ARCH_SIGNAL_H */
index dd1dca5bfa81fbebfbce7bcf1e2b1a72842e3a9b..590057e9e98779e227c52d967b776d4b1900214c 100644 (file)
 #include <asm/pgtable.h>
 #endif
 
-#undef DEBUG_SIG
+#include "signal.h"
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+#undef DEBUG_SIG
 
 #ifdef CONFIG_PPC64
-#define do_signal      do_signal32
 #define sys_sigsuspend compat_sys_sigsuspend
 #define sys_rt_sigsuspend      compat_sys_rt_sigsuspend
 #define sys_rt_sigreturn       compat_sys_rt_sigreturn
@@ -231,8 +230,6 @@ static inline int restore_general_regs(struct pt_regs *regs,
 
 #endif /* CONFIG_PPC64 */
 
-int do_signal(sigset_t *oldset, struct pt_regs *regs);
-
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
@@ -251,14 +248,6 @@ long sys_sigsuspend(old_sigset_t mask)
        return -ERESTARTNOHAND;
 }
 
-#ifdef CONFIG_PPC32
-long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, int r5,
-               int r6, int r7, int r8, struct pt_regs *regs)
-{
-       return do_sigaltstack(uss, uoss, regs->gpr[1]);
-}
-#endif
-
 long sys_sigaction(int sig, struct old_sigaction __user *act,
                struct old_sigaction __user *oact)
 {
@@ -293,14 +282,17 @@ long sys_sigaction(int sig, struct old_sigaction __user *act,
 /*
  * When we have signals to deliver, we set up on the
  * user stack, going down from the original stack pointer:
- *     a sigregs struct
+ *     an ABI gap of 56 words
+ *     an mcontext struct
  *     a sigcontext struct
  *     a gap of __SIGNAL_FRAMESIZE bytes
  *
- * Each of these things must be a multiple of 16 bytes in size.
+ * Each of these things must be a multiple of 16 bytes in size. The following
+ * structure represent all of this except the __SIGNAL_FRAMESIZE gap
  *
  */
-struct sigregs {
+struct sigframe {
+       struct sigcontext sctx;         /* the sigcontext */
        struct mcontext mctx;           /* all the register values */
        /*
         * Programs using the rs6000/xcoff abi can save up to 19 gp
@@ -703,44 +695,22 @@ int compat_sys_sigaltstack(u32 __new, u32 __old, int r5,
 }
 #endif /* CONFIG_PPC64 */
 
-
-/*
- * Restore the user process's signal mask
- */
-#ifdef CONFIG_PPC64
-extern void restore_sigmask(sigset_t *set);
-#else /* CONFIG_PPC64 */
-static void restore_sigmask(sigset_t *set)
-{
-       sigdelsetmask(set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = *set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-}
-#endif
-
 /*
  * Set up a signal frame for a "real-time" signal handler
  * (one which gets siginfo).
  */
-static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
+int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
                siginfo_t *info, sigset_t *oldset,
-               struct pt_regs *regs, unsigned long newsp)
+               struct pt_regs *regs)
 {
        struct rt_sigframe __user *rt_sf;
        struct mcontext __user *frame;
-       unsigned long origsp = newsp;
+       unsigned long newsp = 0;
 
        /* Set up Signal Frame */
        /* Put a Real Time Context onto stack */
-       newsp -= sizeof(*rt_sf);
-       rt_sf = (struct rt_sigframe __user *)newsp;
-
-       /* create a stack frame for the caller of the handler */
-       newsp -= __SIGNAL_FRAMESIZE + 16;
-
-       if (!access_ok(VERIFY_WRITE, (void __user *)newsp, origsp - newsp))
+       rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf));
+       if (unlikely(rt_sf == NULL))
                goto badframe;
 
        /* Put the siginfo & fill in most of the ucontext */
@@ -770,8 +740,12 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
 
        current->thread.fpscr.val = 0;  /* turn off all fp exceptions */
 
+       /* create a stack frame for the caller of the handler */
+       newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16);
        if (put_user(regs->gpr[1], (u32 __user *)newsp))
                goto badframe;
+
+       /* Fill registers for signal handler */
        regs->gpr[1] = newsp;
        regs->gpr[3] = sig;
        regs->gpr[4] = (unsigned long) &rt_sf->info;
@@ -1015,27 +989,18 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
 /*
  * OK, we're invoking a handler
  */
-static int handle_signal(unsigned long sig, struct k_sigaction *ka,
-               siginfo_t *info, sigset_t *oldset, struct pt_regs *regs,
-               unsigned long newsp)
+int handle_signal32(unsigned long sig, struct k_sigaction *ka,
+                   siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
 {
        struct sigcontext __user *sc;
-       struct sigregs __user *frame;
-       unsigned long origsp = newsp;
+       struct sigframe __user *frame;
+       unsigned long newsp = 0;
 
        /* Set up Signal Frame */
-       newsp -= sizeof(struct sigregs);
-       frame = (struct sigregs __user *) newsp;
-
-       /* Put a sigcontext on the stack */
-       newsp -= sizeof(*sc);
-       sc = (struct sigcontext __user *) newsp;
-
-       /* create a stack frame for the caller of the handler */
-       newsp -= __SIGNAL_FRAMESIZE;
-
-       if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
+       frame = get_sigframe(ka, regs, sizeof(*frame));
+       if (unlikely(frame == NULL))
                goto badframe;
+       sc = (struct sigcontext __user *) &frame->sctx;
 
 #if _NSIG != 64
 #error "Please adjust handle_signal()"
@@ -1047,7 +1012,7 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
 #else
            || __put_user(oldset->sig[1], &sc->_unused[3])
 #endif
-           || __put_user(to_user_ptr(frame), &sc->regs)
+           || __put_user(to_user_ptr(&frame->mctx), &sc->regs)
            || __put_user(sig, &sc->signal))
                goto badframe;
 
@@ -1063,8 +1028,11 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
 
        current->thread.fpscr.val = 0;  /* turn off all fp exceptions */
 
+       /* create a stack frame for the caller of the handler */
+       newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
        if (put_user(regs->gpr[1], (u32 __user *)newsp))
                goto badframe;
+
        regs->gpr[1] = newsp;
        regs->gpr[3] = sig;
        regs->gpr[4] = (unsigned long) sc;
@@ -1126,106 +1094,3 @@ badframe:
        force_sig(SIGSEGV, current);
        return 0;
 }
-
-/*
- * Note that 'init' is a special process: it doesn't get signals it doesn't
- * want to handle. Thus you cannot kill init even with a SIGKILL even by
- * mistake.
- */
-int do_signal(sigset_t *oldset, struct pt_regs *regs)
-{
-       siginfo_t info;
-       struct k_sigaction ka;
-       unsigned int newsp;
-       int signr, ret;
-
-#ifdef CONFIG_PPC32
-       if (try_to_freeze()) {
-               signr = 0;
-               if (!signal_pending(current))
-                       goto no_signal;
-       }
-#endif
-
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = &current->saved_sigmask;
-       else if (!oldset)
-               oldset = &current->blocked;
-
-       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-#ifdef CONFIG_PPC32
-no_signal:
-#endif
-       if (TRAP(regs) == 0x0C00                /* System Call! */
-           && regs->ccr & 0x10000000           /* error signalled */
-           && ((ret = regs->gpr[3]) == ERESTARTSYS
-               || ret == ERESTARTNOHAND || ret == ERESTARTNOINTR
-               || ret == ERESTART_RESTARTBLOCK)) {
-
-               if (signr > 0
-                   && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK
-                       || (ret == ERESTARTSYS
-                           && !(ka.sa.sa_flags & SA_RESTART)))) {
-                       /* make the system call return an EINTR error */
-                       regs->result = -EINTR;
-                       regs->gpr[3] = EINTR;
-                       /* note that the cr0.SO bit is already set */
-               } else {
-                       regs->nip -= 4; /* Back up & retry system call */
-                       regs->result = 0;
-                       regs->trap = 0;
-                       if (ret == ERESTART_RESTARTBLOCK)
-                               regs->gpr[0] = __NR_restart_syscall;
-                       else
-                               regs->gpr[3] = regs->orig_gpr3;
-               }
-       }
-
-       if (signr == 0) {
-               /* No signal to deliver -- put the saved sigmask back */
-               if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-                       clear_thread_flag(TIF_RESTORE_SIGMASK);
-                       sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-               }
-               return 0;               /* no signals delivered */
-       }
-
-       if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
-           && !on_sig_stack(regs->gpr[1]))
-               newsp = current->sas_ss_sp + current->sas_ss_size;
-       else
-               newsp = regs->gpr[1];
-       newsp &= ~0xfUL;
-
-#ifdef CONFIG_PPC64
-       /*
-        * Reenable the DABR before delivering the signal to
-        * user space. The DABR will have been cleared if it
-        * triggered inside the kernel.
-        */
-       if (current->thread.dabr)
-               set_dabr(current->thread.dabr);
-#endif
-
-       /* Whee!  Actually deliver the signal.  */
-       if (ka.sa.sa_flags & SA_SIGINFO)
-               ret = handle_rt_signal(signr, &ka, &info, oldset, regs, newsp);
-       else
-               ret = handle_signal(signr, &ka, &info, oldset, regs, newsp);
-
-       if (ret) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked, &current->blocked,
-                         &ka.sa.sa_mask);
-               if (!(ka.sa.sa_flags & SA_NODEFER))
-                       sigaddset(&current->blocked, signr);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-               /* A signal was successfully delivered; the saved sigmask is in
-                  its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
-               if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                       clear_thread_flag(TIF_RESTORE_SIGMASK);
-       }
-
-       return ret;
-}
index b27e26852fdbf847ed3f258553b933024fa0adad..de895e6d8c62c03ff601bef5a030e1b792bf4cbb 100644 (file)
@@ -34,9 +34,9 @@
 #include <asm/syscalls.h>
 #include <asm/vdso.h>
 
-#define DEBUG_SIG 0
+#include "signal.h"
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+#define DEBUG_SIG 0
 
 #define GP_REGS_SIZE   min(sizeof(elf_gregset_t), sizeof(struct pt_regs))
 #define FP_REGS_SIZE   sizeof(elf_fpregset_t)
@@ -64,14 +64,6 @@ struct rt_sigframe {
        char abigap[288];
 } __attribute__ ((aligned (16)));
 
-long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5,
-                    unsigned long r6, unsigned long r7, unsigned long r8,
-                    struct pt_regs *regs)
-{
-       return do_sigaltstack(uss, uoss, regs->gpr[1]);
-}
-
-
 /*
  * Set up the sigcontext for the signal frame.
  */
@@ -207,25 +199,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
        return err;
 }
 
-/*
- * Allocate space for the signal frame
- */
-static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
-                                 size_t frame_size)
-{
-        unsigned long newsp;
-
-        /* Default to using normal stack */
-        newsp = regs->gpr[1];
-
-       if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size) {
-               if (! on_sig_stack(regs->gpr[1]))
-                       newsp = (current->sas_ss_sp + current->sas_ss_size);
-       }
-
-        return (void __user *)((newsp - frame_size) & -16ul);
-}
-
 /*
  * Setup the trampoline code on the stack
  */
@@ -252,19 +225,6 @@ static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp)
        return err;
 }
 
-/*
- * Restore the user process's signal mask (also used by signal32.c)
- */
-void restore_sigmask(sigset_t *set)
-{
-       sigdelsetmask(set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = *set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-}
-
-
 /*
  * Handle {get,set,swap}_context operations
  */
@@ -359,7 +319,7 @@ badframe:
        return 0;
 }
 
-static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
+int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
                sigset_t *set, struct pt_regs *regs)
 {
        /* Handler is *really* a pointer to the function descriptor for
@@ -373,8 +333,7 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
        long err = 0;
 
        frame = get_sigframe(ka, regs, sizeof(*frame));
-
-       if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+       if (unlikely(frame == NULL))
                goto badframe;
 
        err |= __put_user(&frame->info, &frame->pinfo);
@@ -411,7 +370,7 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
        funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler;
 
        /* Allocate a dummy caller frame for the signal handler. */
-       newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE;
+       newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
        err |= put_user(regs->gpr[1], (unsigned long __user *)newsp);
 
        /* Set up "regs" so we "return" to the signal handler. */
@@ -442,134 +401,3 @@ badframe:
        force_sigsegv(signr, current);
        return 0;
 }
-
-
-/*
- * OK, we're invoking a handler
- */
-static int handle_signal(unsigned long sig, struct k_sigaction *ka,
-                        siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
-{
-       int ret;
-
-       /* Set up Signal Frame */
-       ret = setup_rt_frame(sig, ka, info, oldset, regs);
-
-       if (ret) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
-               if (!(ka->sa.sa_flags & SA_NODEFER))
-                       sigaddset(&current->blocked,sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
-
-       return ret;
-}
-
-static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
-{
-       switch ((int)regs->result) {
-       case -ERESTART_RESTARTBLOCK:
-       case -ERESTARTNOHAND:
-               /* ERESTARTNOHAND means that the syscall should only be
-                * restarted if there was no handler for the signal, and since
-                * we only get here if there is a handler, we dont restart.
-                */
-               regs->result = -EINTR;
-               regs->gpr[3] = EINTR;
-               regs->ccr |= 0x10000000;
-               break;
-       case -ERESTARTSYS:
-               /* ERESTARTSYS means to restart the syscall if there is no
-                * handler or the handler was registered with SA_RESTART
-                */
-               if (!(ka->sa.sa_flags & SA_RESTART)) {
-                       regs->result = -EINTR;
-                       regs->gpr[3] = EINTR;
-                       regs->ccr |= 0x10000000;
-                       break;
-               }
-               /* fallthrough */
-       case -ERESTARTNOINTR:
-               /* ERESTARTNOINTR means that the syscall should be
-                * called again after the signal handler returns.
-                */
-               regs->gpr[3] = regs->orig_gpr3;
-               regs->nip -= 4;
-               regs->result = 0;
-               break;
-       }
-}
-
-/*
- * Note that 'init' is a special process: it doesn't get signals it doesn't
- * want to handle. Thus you cannot kill init even with a SIGKILL even by
- * mistake.
- */
-int do_signal(sigset_t *oldset, struct pt_regs *regs)
-{
-       siginfo_t info;
-       int signr;
-       struct k_sigaction ka;
-
-       /*
-        * If the current thread is 32 bit - invoke the
-        * 32 bit signal handling code
-        */
-       if (test_thread_flag(TIF_32BIT))
-               return do_signal32(oldset, regs);
-
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = &current->saved_sigmask;
-       else if (!oldset)
-               oldset = &current->blocked;
-
-       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-       if (signr > 0) {
-               int ret;
-
-               /* Whee!  Actually deliver the signal.  */
-               if (TRAP(regs) == 0x0C00)
-                       syscall_restart(regs, &ka);
-
-               /*
-                * Reenable the DABR before delivering the signal to
-                * user space. The DABR will have been cleared if it
-                * triggered inside the kernel.
-                */
-               if (current->thread.dabr)
-                       set_dabr(current->thread.dabr);
-
-               ret = handle_signal(signr, &ka, &info, oldset, regs);
-
-               /* If a signal was successfully delivered, the saved sigmask is in
-                  its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
-               if (ret && test_thread_flag(TIF_RESTORE_SIGMASK))
-                       clear_thread_flag(TIF_RESTORE_SIGMASK);
-
-               return ret;
-       }
-
-       if (TRAP(regs) == 0x0C00) {     /* System Call! */
-               if ((int)regs->result == -ERESTARTNOHAND ||
-                   (int)regs->result == -ERESTARTSYS ||
-                   (int)regs->result == -ERESTARTNOINTR) {
-                       regs->gpr[3] = regs->orig_gpr3;
-                       regs->nip -= 4; /* Back up & retry system call */
-                       regs->result = 0;
-               } else if ((int)regs->result == -ERESTART_RESTARTBLOCK) {
-                       regs->gpr[0] = __NR_restart_syscall;
-                       regs->nip -= 4;
-                       regs->result = 0;
-               }
-       }
-       /* No signal to deliver -- put the saved sigmask back */
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL(do_signal);
index 68991c2d4a1b3a6fcb101728c2be0e9724dcf37d..55d29ed4b7a0f0933c62a7c0cd730190ba59cd4a 100644 (file)
@@ -442,12 +442,14 @@ int sysfs_add_device_to_node(struct sys_device *dev, int nid)
        return sysfs_create_link(&node->sysdev.kobj, &dev->kobj,
                        kobject_name(&dev->kobj));
 }
+EXPORT_SYMBOL_GPL(sysfs_add_device_to_node);
 
 void sysfs_remove_device_from_node(struct sys_device *dev, int nid)
 {
        struct node *node = &node_devices[nid];
        sysfs_remove_link(&node->sysdev.kobj, kobject_name(&dev->kobj));
 }
+EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node);
 
 #else
 static void register_nodes(void)
@@ -457,9 +459,6 @@ static void register_nodes(void)
 
 #endif
 
-EXPORT_SYMBOL_GPL(sysfs_add_device_to_node);
-EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node);
-
 /* Only valid if CPU is present. */
 static ssize_t show_physical_id(struct sys_device *dev, char *buf)
 {
index 2c8564d54e4d009a67527463d1aa2a8c7f3f9d6f..e5df167f7824dfc648984f2fd21d154c3f9cbea1 100644 (file)
@@ -77,9 +77,8 @@
 /* keep track of when we need to update the rtc */
 time_t last_rtc_update;
 #ifdef CONFIG_PPC_ISERIES
-unsigned long iSeries_recal_titan = 0;
-unsigned long iSeries_recal_tb = 0; 
-static unsigned long first_settimeofday = 1;
+static unsigned long __initdata iSeries_recal_titan;
+static signed long __initdata iSeries_recal_tb;
 #endif
 
 /* The decrementer counts down by 128 every 128ns on a 601. */
@@ -113,8 +112,9 @@ u64 ticklen_to_xs;  /* 0.64 fraction */
 DEFINE_SPINLOCK(rtc_lock);
 EXPORT_SYMBOL_GPL(rtc_lock);
 
-u64 tb_to_ns_scale;
-unsigned tb_to_ns_shift;
+static u64 tb_to_ns_scale __read_mostly;
+static unsigned tb_to_ns_shift __read_mostly;
+static unsigned long boot_tb __read_mostly;
 
 struct gettimeofday_struct do_gtod;
 
@@ -214,7 +214,6 @@ static void account_process_time(struct pt_regs *regs)
        run_posix_cpu_timers(current);
 }
 
-#ifdef CONFIG_PPC_SPLPAR
 /*
  * Stuff for accounting stolen time.
  */
@@ -222,19 +221,28 @@ struct cpu_purr_data {
        int     initialized;                    /* thread is running */
        u64     tb;                     /* last TB value read */
        u64     purr;                   /* last PURR value read */
-       spinlock_t lock;
 };
 
+/*
+ * Each entry in the cpu_purr_data array is manipulated only by its
+ * "owner" cpu -- usually in the timer interrupt but also occasionally
+ * in process context for cpu online.  As long as cpus do not touch
+ * each others' cpu_purr_data, disabling local interrupts is
+ * sufficient to serialize accesses.
+ */
 static DEFINE_PER_CPU(struct cpu_purr_data, cpu_purr_data);
 
 static void snapshot_tb_and_purr(void *data)
 {
+       unsigned long flags;
        struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data);
 
+       local_irq_save(flags);
        p->tb = mftb();
        p->purr = mfspr(SPRN_PURR);
        wmb();
        p->initialized = 1;
+       local_irq_restore(flags);
 }
 
 /*
@@ -242,15 +250,14 @@ static void snapshot_tb_and_purr(void *data)
  */
 void snapshot_timebases(void)
 {
-       int cpu;
-
        if (!cpu_has_feature(CPU_FTR_PURR))
                return;
-       for_each_possible_cpu(cpu)
-               spin_lock_init(&per_cpu(cpu_purr_data, cpu).lock);
        on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1);
 }
 
+/*
+ * Must be called with interrupts disabled.
+ */
 void calculate_steal_time(void)
 {
        u64 tb, purr;
@@ -262,7 +269,6 @@ void calculate_steal_time(void)
        pme = &per_cpu(cpu_purr_data, smp_processor_id());
        if (!pme->initialized)
                return;         /* this can happen in early boot */
-       spin_lock(&pme->lock);
        tb = mftb();
        purr = mfspr(SPRN_PURR);
        stolen = (tb - pme->tb) - (purr - pme->purr);
@@ -270,9 +276,9 @@ void calculate_steal_time(void)
                account_steal_time(current, stolen);
        pme->tb = tb;
        pme->purr = purr;
-       spin_unlock(&pme->lock);
 }
 
+#ifdef CONFIG_PPC_SPLPAR
 /*
  * Must be called before the cpu is added to the online map when
  * a cpu is being brought up at runtime.
@@ -284,12 +290,12 @@ static void snapshot_purr(void)
 
        if (!cpu_has_feature(CPU_FTR_PURR))
                return;
+       local_irq_save(flags);
        pme = &per_cpu(cpu_purr_data, smp_processor_id());
-       spin_lock_irqsave(&pme->lock, flags);
        pme->tb = mftb();
        pme->purr = mfspr(SPRN_PURR);
        pme->initialized = 1;
-       spin_unlock_irqrestore(&pme->lock, flags);
+       local_irq_restore(flags);
 }
 
 #endif /* CONFIG_PPC_SPLPAR */
@@ -550,10 +556,15 @@ EXPORT_SYMBOL(profile_pc);
  * returned by the service processor for the timebase frequency.  
  */
 
-static void iSeries_tb_recal(void)
+static int __init iSeries_tb_recal(void)
 {
        struct div_result divres;
        unsigned long titan, tb;
+
+       /* Make sure we only run on iSeries */
+       if (!firmware_has_feature(FW_FEATURE_ISERIES))
+               return -ENODEV;
+
        tb = get_tb();
        titan = HvCallXm_loadTod();
        if ( iSeries_recal_titan ) {
@@ -594,8 +605,18 @@ static void iSeries_tb_recal(void)
        }
        iSeries_recal_titan = titan;
        iSeries_recal_tb = tb;
+
+       return 0;
 }
-#endif
+late_initcall(iSeries_tb_recal);
+
+/* Called from platform early init */
+void __init iSeries_time_init_early(void)
+{
+       iSeries_recal_tb = get_tb();
+       iSeries_recal_titan = HvCallXm_loadTod();
+}
+#endif /* CONFIG_PPC_ISERIES */
 
 /*
  * For iSeries shared processors, we have to let the hypervisor
@@ -735,7 +756,7 @@ unsigned long long sched_clock(void)
 {
        if (__USE_RTC())
                return get_rtc();
-       return mulhdu(get_tb(), tb_to_ns_scale) << tb_to_ns_shift;
+       return mulhdu(get_tb() - boot_tb, tb_to_ns_scale) << tb_to_ns_shift;
 }
 
 int do_settimeofday(struct timespec *tv)
@@ -759,12 +780,6 @@ int do_settimeofday(struct timespec *tv)
         * to the RTC again, or write to the RTC but then they don't call
         * settimeofday to perform this operation.
         */
-#ifdef CONFIG_PPC_ISERIES
-       if (firmware_has_feature(FW_FEATURE_ISERIES) && first_settimeofday) {
-               iSeries_tb_recal();
-               first_settimeofday = 0;
-       }
-#endif
 
        /* Make userspace gettimeofday spin until we're done. */
        ++vdso_data->tb_update_count;
@@ -960,6 +975,8 @@ void __init time_init(void)
        }
        tb_to_ns_scale = scale;
        tb_to_ns_shift = shift;
+       /* Save the current timebase to pretty up CONFIG_PRINTK_TIME */
+       boot_tb = get_tb();
 
        tm = get_boot_time();
 
index 4245579edb4e8ff2de805ba638f4b3982ca80344..cef01e4e898916483f289238e7d4bc3ac79c59bb 100644 (file)
@@ -670,7 +670,7 @@ static int __init vdso_init(void)
        /*
         * Fill up the "systemcfg" stuff for backward compatiblity
         */
-       strcpy(vdso_data->eye_catcher, "SYSTEMCFG:PPC64");
+       strcpy((char *)vdso_data->eye_catcher, "SYSTEMCFG:PPC64");
        vdso_data->version.major = SYSTEMCFG_MAJOR;
        vdso_data->version.minor = SYSTEMCFG_MINOR;
        vdso_data->processor = mfspr(SPRN_PVR);
index 21c39ff2dc39b41c52d0ea04fb66defab5786118..ae4acd84143d91859a418e20229bfcb32589a28e 100644 (file)
@@ -7,6 +7,7 @@
 #define PROVIDE32(x)   PROVIDE(x)
 #endif
 #include <asm-generic/vmlinux.lds.h>
+#include <asm/cache.h>
 
 ENTRY(_stext)
 
@@ -211,6 +212,11 @@ SECTIONS
                *(.data.cacheline_aligned)
        }
 
+       . = ALIGN(L1_CACHE_BYTES);
+       .data.read_mostly : {
+               *(.data.read_mostly)
+       }
+
        . = ALIGN(PAGE_SIZE);
        __data_nosave : {
                __nosave_begin = .;
index ca4dcb07a9393fd47778ae9d1a6687710106e3ec..c3df504765393b05f01ca8a6128b1db7992adc8c 100644 (file)
@@ -12,7 +12,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
index 838e09db71d97f56ca3721917dd2fd0ada843042..7ff2609b64d140b90eeb955e764b4a78a54b233f 100644 (file)
@@ -9,7 +9,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
index 4f839c6a97682165fc9c7d18c91140fea0eddd31..7e4d27ad3deec7e422181daadcbe715444f7df6c 100644 (file)
@@ -11,8 +11,7 @@ obj-$(CONFIG_PPC32)           += init_32.o pgtable_32.o mmu_context_32.o
 hash-$(CONFIG_PPC_NATIVE)      := hash_native_64.o
 obj-$(CONFIG_PPC64)            += init_64.o pgtable_64.o mmu_context_64.o \
                                   hash_utils_64.o hash_low_64.o tlb_64.o \
-                                  slb_low.o slb.o stab.o mmap.o imalloc.o \
-                                  $(hash-y)
+                                  slb_low.o slb.o stab.o mmap.o $(hash-y)
 obj-$(CONFIG_PPC_STD_MMU_32)   += ppc_mmu_32.o hash_low_32.o tlb_32.o
 obj-$(CONFIG_40x)              += 4xx_mmu.o
 obj-$(CONFIG_44x)              += 44x_mmu.o
index 115b25f50bf83786965380f041d301bad44218e0..0ece51310bfe11ec1d2a7b0cfec0f8ab00975c4b 100644 (file)
@@ -380,7 +380,7 @@ out_of_memory:
        }
        printk("VM: killing process %s\n", current->comm);
        if (user_mode(regs))
-               do_exit(SIGKILL);
+               do_group_exit(SIGKILL);
        return SIGKILL;
 
 do_sigbus:
index 123da03ab1186df9bb977d21e238e15c858331f5..afab247d472f4f221b2e789c7373fc68c7d12314 100644 (file)
@@ -14,7 +14,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
index 4a20d890e2f45be63cba2ea465941407935d3b4b..6ba9b47e55afbe746734761c672761dcea07e9f0 100644 (file)
@@ -104,7 +104,7 @@ static inline void tlbie(unsigned long va, int psize, int local)
                spin_unlock(&native_tlbie_lock);
 }
 
-static inline void native_lock_hpte(hpte_t *hptep)
+static inline void native_lock_hpte(struct hash_pte *hptep)
 {
        unsigned long *word = &hptep->v;
 
@@ -116,7 +116,7 @@ static inline void native_lock_hpte(hpte_t *hptep)
        }
 }
 
-static inline void native_unlock_hpte(hpte_t *hptep)
+static inline void native_unlock_hpte(struct hash_pte *hptep)
 {
        unsigned long *word = &hptep->v;
 
@@ -128,7 +128,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
                        unsigned long pa, unsigned long rflags,
                        unsigned long vflags, int psize)
 {
-       hpte_t *hptep = htab_address + hpte_group;
+       struct hash_pte *hptep = htab_address + hpte_group;
        unsigned long hpte_v, hpte_r;
        int i;
 
@@ -163,7 +163,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
 
        hptep->r = hpte_r;
        /* Guarantee the second dword is visible before the valid bit */
-       __asm__ __volatile__ ("eieio" : : : "memory");
+       eieio();
        /*
         * Now set the first dword including the valid bit
         * NOTE: this also unlocks the hpte
@@ -177,7 +177,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
 
 static long native_hpte_remove(unsigned long hpte_group)
 {
-       hpte_t *hptep;
+       struct hash_pte *hptep;
        int i;
        int slot_offset;
        unsigned long hpte_v;
@@ -217,7 +217,7 @@ static long native_hpte_remove(unsigned long hpte_group)
 static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
                                 unsigned long va, int psize, int local)
 {
-       hpte_t *hptep = htab_address + slot;
+       struct hash_pte *hptep = htab_address + slot;
        unsigned long hpte_v, want_v;
        int ret = 0;
 
@@ -233,15 +233,14 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
        /* Even if we miss, we need to invalidate the TLB */
        if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) {
                DBG_LOW(" -> miss\n");
-               native_unlock_hpte(hptep);
                ret = -1;
        } else {
                DBG_LOW(" -> hit\n");
                /* Update the HPTE */
                hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) |
                        (newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C));
-               native_unlock_hpte(hptep);
        }
+       native_unlock_hpte(hptep);
 
        /* Ensure it is out of the tlb too. */
        tlbie(va, psize, local);
@@ -251,7 +250,7 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
 
 static long native_hpte_find(unsigned long va, int psize)
 {
-       hpte_t *hptep;
+       struct hash_pte *hptep;
        unsigned long hash;
        unsigned long i, j;
        long slot;
@@ -294,7 +293,7 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
 {
        unsigned long vsid, va;
        long slot;
-       hpte_t *hptep;
+       struct hash_pte *hptep;
 
        vsid = get_kernel_vsid(ea);
        va = (vsid << 28) | (ea & 0x0fffffff);
@@ -315,7 +314,7 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
 static void native_hpte_invalidate(unsigned long slot, unsigned long va,
                                   int psize, int local)
 {
-       hpte_t *hptep = htab_address + slot;
+       struct hash_pte *hptep = htab_address + slot;
        unsigned long hpte_v;
        unsigned long want_v;
        unsigned long flags;
@@ -345,7 +344,7 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va,
 #define LP_BITS                8
 #define LP_MASK(i)     ((0xFF >> (i)) << LP_SHIFT)
 
-static void hpte_decode(hpte_t *hpte, unsigned long slot,
+static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
                        int *psize, unsigned long *va)
 {
        unsigned long hpte_r = hpte->r;
@@ -415,7 +414,7 @@ static void hpte_decode(hpte_t *hpte, unsigned long slot,
 static void native_hpte_clear(void)
 {
        unsigned long slot, slots, flags;
-       hpte_t *hptep = htab_address;
+       struct hash_pte *hptep = htab_address;
        unsigned long hpte_v, va;
        unsigned long pteg_count;
        int psize;
@@ -462,7 +461,7 @@ static void native_hpte_clear(void)
 static void native_flush_hash_range(unsigned long number, int local)
 {
        unsigned long va, hash, index, hidx, shift, slot;
-       hpte_t *hptep;
+       struct hash_pte *hptep;
        unsigned long hpte_v;
        unsigned long want_v;
        unsigned long flags;
index 4f2f4534a9d8bace0042d443329c8fc923cb0d31..2ce9491b48d409d4763d4822426415c4f5a8c088 100644 (file)
@@ -87,7 +87,7 @@ extern unsigned long dart_tablebase;
 static unsigned long _SDR1;
 struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
 
-hpte_t *htab_address;
+struct hash_pte *htab_address;
 unsigned long htab_size_bytes;
 unsigned long htab_hash_mask;
 int mmu_linear_psize = MMU_PAGE_4K;
diff --git a/arch/powerpc/mm/imalloc.c b/arch/powerpc/mm/imalloc.c
deleted file mode 100644 (file)
index c831815..0000000
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * c 2001 PPC 64 Team, IBM Corp
- * 
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License
- *      as published by the Free Software Foundation; either version
- *      2 of the License, or (at your option) any later version.
- */
-
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <linux/mutex.h>
-#include <asm/cacheflush.h>
-
-#include "mmu_decl.h"
-
-static DEFINE_MUTEX(imlist_mutex);
-struct vm_struct * imlist = NULL;
-
-static int get_free_im_addr(unsigned long size, unsigned long *im_addr)
-{
-       unsigned long addr;
-       struct vm_struct **p, *tmp;
-
-       addr = ioremap_bot;
-       for (p = &imlist; (tmp = *p) ; p = &tmp->next) {
-               if (size + addr < (unsigned long) tmp->addr)
-                       break;
-               if ((unsigned long)tmp->addr >= ioremap_bot)
-                       addr = tmp->size + (unsigned long) tmp->addr;
-               if (addr >= IMALLOC_END-size)
-                       return 1;
-       }
-       *im_addr = addr;
-
-       return 0;
-}
-
-/* Return whether the region described by v_addr and size is a subset
- * of the region described by parent
- */
-static inline int im_region_is_subset(unsigned long v_addr, unsigned long size,
-                       struct vm_struct *parent)
-{
-       return (int) (v_addr >= (unsigned long) parent->addr &&
-                     v_addr < (unsigned long) parent->addr + parent->size &&
-                     size < parent->size);
-}
-
-/* Return whether the region described by v_addr and size is a superset
- * of the region described by child
- */
-static int im_region_is_superset(unsigned long v_addr, unsigned long size,
-               struct vm_struct *child)
-{
-       struct vm_struct parent;
-
-       parent.addr = (void *) v_addr;
-       parent.size = size;
-
-       return im_region_is_subset((unsigned long) child->addr, child->size,
-                       &parent);
-}
-
-/* Return whether the region described by v_addr and size overlaps
- * the region described by vm.  Overlapping regions meet the
- * following conditions:
- * 1) The regions share some part of the address space
- * 2) The regions aren't identical
- * 3) Neither region is a subset of the other
- */
-static int im_region_overlaps(unsigned long v_addr, unsigned long size,
-                    struct vm_struct *vm)
-{
-       if (im_region_is_superset(v_addr, size, vm))
-               return 0;
-
-       return (v_addr + size > (unsigned long) vm->addr + vm->size &&
-               v_addr < (unsigned long) vm->addr + vm->size) ||
-              (v_addr < (unsigned long) vm->addr &&
-               v_addr + size > (unsigned long) vm->addr);
-}
-
-/* Determine imalloc status of region described by v_addr and size.
- * Can return one of the following:
- * IM_REGION_UNUSED   -  Entire region is unallocated in imalloc space.
- * IM_REGION_SUBSET -    Region is a subset of a region that is already
- *                      allocated in imalloc space.
- *                      vm will be assigned to a ptr to the parent region.
- * IM_REGION_EXISTS -    Exact region already allocated in imalloc space.
- *                       vm will be assigned to a ptr to the existing imlist
- *                       member.
- * IM_REGION_OVERLAPS -  Region overlaps an allocated region in imalloc space.
- * IM_REGION_SUPERSET -  Region is a superset of a region that is already
- *                       allocated in imalloc space.
- */
-static int im_region_status(unsigned long v_addr, unsigned long size,
-                   struct vm_struct **vm)
-{
-       struct vm_struct *tmp;
-
-       for (tmp = imlist; tmp; tmp = tmp->next)
-               if (v_addr < (unsigned long) tmp->addr + tmp->size)
-                       break;
-
-       *vm = NULL;
-       if (tmp) {
-               if (im_region_overlaps(v_addr, size, tmp))
-                       return IM_REGION_OVERLAP;
-
-               *vm = tmp;
-               if (im_region_is_subset(v_addr, size, tmp)) {
-                       /* Return with tmp pointing to superset */
-                       return IM_REGION_SUBSET;
-               }
-               if (im_region_is_superset(v_addr, size, tmp)) {
-                       /* Return with tmp pointing to first subset */
-                       return IM_REGION_SUPERSET;
-               }
-               else if (v_addr == (unsigned long) tmp->addr &&
-                        size == tmp->size) {
-                       /* Return with tmp pointing to exact region */
-                       return IM_REGION_EXISTS;
-               }
-       }
-
-       return IM_REGION_UNUSED;
-}
-
-static struct vm_struct * split_im_region(unsigned long v_addr, 
-               unsigned long size, struct vm_struct *parent)
-{
-       struct vm_struct *vm1 = NULL;
-       struct vm_struct *vm2 = NULL;
-       struct vm_struct *new_vm = NULL;
-       
-       vm1 = kmalloc(sizeof(*vm1), GFP_KERNEL);
-       if (vm1 == NULL) {
-               printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
-               return NULL;
-       }
-
-       if (v_addr == (unsigned long) parent->addr) {
-               /* Use existing parent vm_struct to represent child, allocate
-                * new one for the remainder of parent range
-                */
-               vm1->size = parent->size - size;
-               vm1->addr = (void *) (v_addr + size);
-               vm1->next = parent->next;
-
-               parent->size = size;
-               parent->next = vm1;
-               new_vm = parent;
-       } else if (v_addr + size == (unsigned long) parent->addr + 
-                       parent->size) {
-               /* Allocate new vm_struct to represent child, use existing
-                * parent one for remainder of parent range
-                */
-               vm1->size = size;
-               vm1->addr = (void *) v_addr;
-               vm1->next = parent->next;
-               new_vm = vm1;
-
-               parent->size -= size;
-               parent->next = vm1;
-       } else {
-               /* Allocate two new vm_structs for the new child and 
-                * uppermost remainder, and use existing parent one for the
-                * lower remainder of parent range
-                */
-               vm2 = kmalloc(sizeof(*vm2), GFP_KERNEL);
-               if (vm2 == NULL) {
-                       printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
-                       kfree(vm1);
-                       return NULL;
-               }
-
-               vm1->size = size;
-               vm1->addr = (void *) v_addr;
-               vm1->next = vm2;
-               new_vm = vm1;
-
-               vm2->size = ((unsigned long) parent->addr + parent->size) - 
-                               (v_addr + size);
-               vm2->addr = (void *) v_addr + size;
-               vm2->next = parent->next;
-
-               parent->size = v_addr - (unsigned long) parent->addr;
-               parent->next = vm1;
-       }
-
-       return new_vm;
-}
-
-static struct vm_struct * __add_new_im_area(unsigned long req_addr, 
-                                           unsigned long size)
-{
-       struct vm_struct **p, *tmp, *area;
-               
-       for (p = &imlist; (tmp = *p) ; p = &tmp->next) {
-               if (req_addr + size <= (unsigned long)tmp->addr)
-                       break;
-       }
-       
-       area = kmalloc(sizeof(*area), GFP_KERNEL);
-       if (!area)
-               return NULL;
-       area->flags = 0;
-       area->addr = (void *)req_addr;
-       area->size = size;
-       area->next = *p;
-       *p = area;
-
-       return area;
-}
-
-static struct vm_struct * __im_get_area(unsigned long req_addr, 
-                                       unsigned long size,
-                                       int criteria)
-{
-       struct vm_struct *tmp;
-       int status;
-
-       status = im_region_status(req_addr, size, &tmp);
-       if ((criteria & status) == 0) {
-               return NULL;
-       }
-       
-       switch (status) {
-       case IM_REGION_UNUSED:
-               tmp = __add_new_im_area(req_addr, size);
-               break;
-       case IM_REGION_SUBSET:
-               tmp = split_im_region(req_addr, size, tmp);
-               break;
-       case IM_REGION_EXISTS:
-               /* Return requested region */
-               break;
-       case IM_REGION_SUPERSET:
-               /* Return first existing subset of requested region */
-               break;
-       default:
-               printk(KERN_ERR "%s() unexpected imalloc region status\n",
-                               __FUNCTION__);
-               tmp = NULL;
-       }
-
-       return tmp;
-}
-
-struct vm_struct * im_get_free_area(unsigned long size)
-{
-       struct vm_struct *area;
-       unsigned long addr;
-       
-       mutex_lock(&imlist_mutex);
-       if (get_free_im_addr(size, &addr)) {
-               printk(KERN_ERR "%s() cannot obtain addr for size 0x%lx\n",
-                               __FUNCTION__, size);
-               area = NULL;
-               goto next_im_done;
-       }
-
-       area = __im_get_area(addr, size, IM_REGION_UNUSED);
-       if (area == NULL) {
-               printk(KERN_ERR 
-                      "%s() cannot obtain area for addr 0x%lx size 0x%lx\n",
-                       __FUNCTION__, addr, size);
-       }
-next_im_done:
-       mutex_unlock(&imlist_mutex);
-       return area;
-}
-
-struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
-               int criteria)
-{
-       struct vm_struct *area;
-
-       mutex_lock(&imlist_mutex);
-       area = __im_get_area(v_addr, size, criteria);
-       mutex_unlock(&imlist_mutex);
-       return area;
-}
-
-void im_free(void * addr)
-{
-       struct vm_struct **p, *tmp;
-  
-       if (!addr)
-               return;
-       if ((unsigned long) addr & ~PAGE_MASK) {
-               printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__,                        addr);
-               return;
-       }
-       mutex_lock(&imlist_mutex);
-       for (p = &imlist ; (tmp = *p) ; p = &tmp->next) {
-               if (tmp->addr == addr) {
-                       *p = tmp->next;
-                       unmap_vm_area(tmp);
-                       kfree(tmp);
-                       mutex_unlock(&imlist_mutex);
-                       return;
-               }
-       }
-       mutex_unlock(&imlist_mutex);
-       printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__,
-                       addr);
-}
index 5fce6ccecb8dee301d98e5ca97c7d9290a5540d9..e1f5ded851f6ed08c40ff892af4423d7af4b7fa2 100644 (file)
@@ -5,7 +5,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *  PPC44x/36-bit changes by Matt Porter (mporter@mvista.com)
  *
  *  Derived from "arch/i386/mm/init.c"
index 7312a265545f3e2f3b675595c17e6c46c44d5bbc..1d6edf724c85da497f56048e2a590b89ba6e85d1 100644 (file)
@@ -5,7 +5,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
index 0266a94d83b6e86fd9ec004c0e3987462329cfbe..f0e7eedb1ba36677fe0d1d74d2d3c1dd6bf617b2 100644 (file)
@@ -5,7 +5,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *  PPC44x/36-bit changes by Matt Porter (mporter@mvista.com)
  *
  *  Derived from "arch/i386/mm/init.c"
@@ -129,8 +128,6 @@ int __devinit arch_add_memory(int nid, u64 start, u64 size)
        zone = pgdata->node_zones;
 
        return __add_pages(zone, start_pfn, nr_pages);
-
-       return 0;
 }
 
 /*
index 792086b01000e2ed12db55a3f48607cd4426dc17..cc32ba41d9003f7340b3d31b08c42096f7fa65c1 100644 (file)
@@ -11,7 +11,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
index 2558c34eedaae4f3372eb30a1720f539f63e2f42..c94a64fd3c01d2b1b4abec580c532ea634e37aa7 100644 (file)
@@ -8,7 +8,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
@@ -40,8 +39,8 @@ extern int __map_without_bats;
 extern unsigned long ioremap_base;
 extern unsigned int rtas_data, rtas_size;
 
-struct _PTE;
-extern struct _PTE *Hash, *Hash_end;
+struct hash_pte;
+extern struct hash_pte *Hash, *Hash_end;
 extern unsigned long Hash_size, Hash_mask;
 
 extern unsigned int num_tlbcam_entries;
@@ -90,16 +89,4 @@ static inline void flush_HPTE(unsigned context, unsigned long va,
        else
                _tlbie(va);
 }
-#else /* CONFIG_PPC64 */
-/* imalloc region types */
-#define IM_REGION_UNUSED       0x1
-#define IM_REGION_SUBSET       0x2
-#define IM_REGION_EXISTS       0x4
-#define IM_REGION_OVERLAP      0x8
-#define IM_REGION_SUPERSET     0x10
-
-extern struct vm_struct * im_get_free_area(unsigned long size);
-extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
-                                     int region_type);
-extern void im_free(void *addr);
 #endif
index f6ae1a57d652999c679545ae21fd5b6499cfae58..64488723162a371b05f0148f8f54a413f428eed8 100644 (file)
@@ -8,7 +8,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
@@ -37,7 +36,6 @@
 unsigned long ioremap_base;
 unsigned long ioremap_bot;
 EXPORT_SYMBOL(ioremap_bot);    /* aka VMALLOC_END */
-int io_bat_index;
 
 #if defined(CONFIG_6xx) || defined(CONFIG_POWER3)
 #define HAVE_BATS      1
@@ -300,51 +298,6 @@ void __init mapin_ram(void)
        }
 }
 
-/* is x a power of 4? */
-#define is_power_of_4(x)       is_power_of_2(x) && (ffs(x) & 1)
-
-/*
- * Set up a mapping for a block of I/O.
- * virt, phys, size must all be page-aligned.
- * This should only be called before ioremap is called.
- */
-void __init io_block_mapping(unsigned long virt, phys_addr_t phys,
-                            unsigned int size, int flags)
-{
-       int i;
-
-       if (virt > KERNELBASE && virt < ioremap_bot)
-               ioremap_bot = ioremap_base = virt;
-
-#ifdef HAVE_BATS
-       /*
-        * Use a BAT for this if possible...
-        */
-       if (io_bat_index < 2 && is_power_of_2(size)
-           && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) {
-               setbat(io_bat_index, virt, phys, size, flags);
-               ++io_bat_index;
-               return;
-       }
-#endif /* HAVE_BATS */
-
-#ifdef HAVE_TLBCAM
-       /*
-        * Use a CAM for this if possible...
-        */
-       if (tlbcam_index < num_tlbcam_entries && is_power_of_4(size)
-           && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) {
-               settlbcam(tlbcam_index, virt, phys, size, flags, 0);
-               ++tlbcam_index;
-               return;
-       }
-#endif /* HAVE_TLBCAM */
-
-       /* No BATs available, put it in the page tables. */
-       for (i = 0; i < size; i += PAGE_SIZE)
-               map_page(virt + i, phys + i, flags);
-}
-
 /* Scan the real Linux page tables and return a PTE pointer for
  * a virtual address in a context.
  * Returns true (1) if PTE was found, zero otherwise.  The pointer to
@@ -379,82 +332,6 @@ get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp)
         return(retval);
 }
 
-/* Find physical address for this virtual address.  Normally used by
- * I/O functions, but anyone can call it.
- */
-unsigned long iopa(unsigned long addr)
-{
-       unsigned long pa;
-
-       /* I don't know why this won't work on PMacs or CHRP.  It
-        * appears there is some bug, or there is some implicit
-        * mapping done not properly represented by BATs or in page
-        * tables.......I am actively working on resolving this, but
-        * can't hold up other stuff.  -- Dan
-        */
-       pte_t *pte;
-       struct mm_struct *mm;
-
-       /* Check the BATs */
-       pa = v_mapped_by_bats(addr);
-       if (pa)
-               return pa;
-
-       /* Allow mapping of user addresses (within the thread)
-        * for DMA if necessary.
-        */
-       if (addr < TASK_SIZE)
-               mm = current->mm;
-       else
-               mm = &init_mm;
-
-       pa = 0;
-       if (get_pteptr(mm, addr, &pte, NULL)) {
-               pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK);
-               pte_unmap(pte);
-       }
-
-       return(pa);
-}
-
-/* This is will find the virtual address for a physical one....
- * Swiped from APUS, could be dangerous :-).
- * This is only a placeholder until I really find a way to make this
- * work.  -- Dan
- */
-unsigned long
-mm_ptov (unsigned long paddr)
-{
-       unsigned long ret;
-#if 0
-       if (paddr < 16*1024*1024)
-               ret = ZTWO_VADDR(paddr);
-       else {
-               int i;
-
-               for (i = 0; i < kmap_chunk_count;){
-                       unsigned long phys = kmap_chunks[i++];
-                       unsigned long size = kmap_chunks[i++];
-                       unsigned long virt = kmap_chunks[i++];
-                       if (paddr >= phys
-                           && paddr < (phys + size)){
-                               ret = virt + paddr - phys;
-                               goto exit;
-                       }
-               }
-       
-               ret = (unsigned long) __va(paddr);
-       }
-exit:
-#ifdef DEBUGPV
-       printk ("PTOV(%lx)=%lx\n", paddr, ret);
-#endif
-#else
-       ret = (unsigned long)paddr + KERNELBASE;
-#endif
-       return ret;
-}
-
 #ifdef CONFIG_DEBUG_PAGEALLOC
 
 static int __change_page_attr(struct page *page, pgprot_t prot)
index ad6e135bf212ac1b77c87ac1ed8cd8b704b93e28..3dfd10db931a47627b147a2044836d1589262538 100644 (file)
@@ -7,7 +7,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@samba.org)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
 #include <linux/stddef.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/bootmem.h>
-#include <linux/highmem.h>
-#include <linux/idr.h>
-#include <linux/nodemask.h>
-#include <linux/module.h>
 
 #include <asm/pgalloc.h>
 #include <asm/page.h>
 #include <asm/prom.h>
-#include <asm/lmb.h>
-#include <asm/rtas.h>
 #include <asm/io.h>
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
-#include <asm/uaccess.h>
 #include <asm/smp.h>
 #include <asm/machdep.h>
 #include <asm/tlb.h>
-#include <asm/eeh.h>
 #include <asm/processor.h>
-#include <asm/mmzone.h>
 #include <asm/cputable.h>
 #include <asm/sections.h>
 #include <asm/system.h>
-#include <asm/iommu.h>
 #include <asm/abs_addr.h>
-#include <asm/vdso.h>
 #include <asm/firmware.h>
 
 #include "mmu_decl.h"
 
-unsigned long ioremap_bot = IMALLOC_BASE;
-static unsigned long phbs_io_bot = PHBS_IO_BASE;
+unsigned long ioremap_bot = IOREMAP_BASE;
 
 /*
  * map_io_page currently only called by __ioremap
@@ -102,8 +87,8 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags)
                 * entry in the hardware page table.
                 *
                 */
-               if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags,
-                                     mmu_io_psize)) {
+               if (htab_bolt_mapping(ea, (unsigned long)ea + PAGE_SIZE,
+                                     pa, flags, mmu_io_psize)) {
                        printk(KERN_ERR "Failed to do bolted mapping IO "
                               "memory at %016lx !\n", pa);
                        return -ENOMEM;
@@ -113,8 +98,11 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags)
 }
 
 
-static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa,
-                           unsigned long ea, unsigned long size,
+/**
+ * __ioremap_at - Low level function to establish the page tables
+ *                for an IO mapping
+ */
+void __iomem * __ioremap_at(phys_addr_t pa, void *ea, unsigned long size,
                            unsigned long flags)
 {
        unsigned long i;
@@ -122,17 +110,35 @@ static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa,
        if ((flags & _PAGE_PRESENT) == 0)
                flags |= pgprot_val(PAGE_KERNEL);
 
+       WARN_ON(pa & ~PAGE_MASK);
+       WARN_ON(((unsigned long)ea) & ~PAGE_MASK);
+       WARN_ON(size & ~PAGE_MASK);
+
        for (i = 0; i < size; i += PAGE_SIZE)
-               if (map_io_page(ea+i, pa+i, flags))
+               if (map_io_page((unsigned long)ea+i, pa+i, flags))
                        return NULL;
 
-       return (void __iomem *) (ea + (addr & ~PAGE_MASK));
+       return (void __iomem *)ea;
+}
+
+/**
+ * __iounmap_from - Low level function to tear down the page tables
+ *                  for an IO mapping. This is used for mappings that
+ *                  are manipulated manually, like partial unmapping of
+ *                  PCI IOs or ISA space.
+ */
+void __iounmap_at(void *ea, unsigned long size)
+{
+       WARN_ON(((unsigned long)ea) & ~PAGE_MASK);
+       WARN_ON(size & ~PAGE_MASK);
+
+       unmap_kernel_range((unsigned long)ea, size);
 }
 
 void __iomem * __ioremap(phys_addr_t addr, unsigned long size,
                         unsigned long flags)
 {
-       unsigned long pa, ea;
+       phys_addr_t paligned;
        void __iomem *ret;
 
        /*
@@ -144,27 +150,30 @@ void __iomem * __ioremap(phys_addr_t addr, unsigned long size,
         * IMALLOC_END
         * 
         */
-       pa = addr & PAGE_MASK;
-       size = PAGE_ALIGN(addr + size) - pa;
+       paligned = addr & PAGE_MASK;
+       size = PAGE_ALIGN(addr + size) - paligned;
 
-       if ((size == 0) || (pa == 0))
+       if ((size == 0) || (paligned == 0))
                return NULL;
 
        if (mem_init_done) {
                struct vm_struct *area;
-               area = im_get_free_area(size);
+
+               area = __get_vm_area(size, VM_IOREMAP,
+                                    ioremap_bot, IOREMAP_END);
                if (area == NULL)
                        return NULL;
-               ea = (unsigned long)(area->addr);
-               ret = __ioremap_com(addr, pa, ea, size, flags);
+               ret = __ioremap_at(paligned, area->addr, size, flags);
                if (!ret)
-                       im_free(area->addr);
+                       vunmap(area->addr);
        } else {
-               ea = ioremap_bot;
-               ret = __ioremap_com(addr, pa, ea, size, flags);
+               ret = __ioremap_at(paligned, (void *)ioremap_bot, size, flags);
                if (ret)
                        ioremap_bot += size;
        }
+
+       if (ret)
+               ret += addr & ~PAGE_MASK;
        return ret;
 }
 
@@ -187,62 +196,9 @@ void __iomem * ioremap_flags(phys_addr_t addr, unsigned long size,
 }
 
 
-#define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK))
-
-int __ioremap_explicit(phys_addr_t pa, unsigned long ea,
-                      unsigned long size, unsigned long flags)
-{
-       struct vm_struct *area;
-       void __iomem *ret;
-       
-       /* For now, require page-aligned values for pa, ea, and size */
-       if (!IS_PAGE_ALIGNED(pa) || !IS_PAGE_ALIGNED(ea) ||
-           !IS_PAGE_ALIGNED(size)) {
-               printk(KERN_ERR "unaligned value in %s\n", __FUNCTION__);
-               return 1;
-       }
-       
-       if (!mem_init_done) {
-               /* Two things to consider in this case:
-                * 1) No records will be kept (imalloc, etc) that the region
-                *    has been remapped
-                * 2) It won't be easy to iounmap() the region later (because
-                *    of 1)
-                */
-               ;
-       } else {
-               area = im_get_area(ea, size,
-                       IM_REGION_UNUSED|IM_REGION_SUBSET|IM_REGION_EXISTS);
-               if (area == NULL) {
-                       /* Expected when PHB-dlpar is in play */
-                       return 1;
-               }
-               if (ea != (unsigned long) area->addr) {
-                       printk(KERN_ERR "unexpected addr return from "
-                              "im_get_area\n");
-                       return 1;
-               }
-       }
-       
-       ret = __ioremap_com(pa, pa, ea, size, flags);
-       if (ret == NULL) {
-               printk(KERN_ERR "ioremap_explicit() allocation failure !\n");
-               return 1;
-       }
-       if (ret != (void *) ea) {
-               printk(KERN_ERR "__ioremap_com() returned unexpected addr\n");
-               return 1;
-       }
-
-       return 0;
-}
-
 /*  
  * Unmap an IO region and remove it from imalloc'd list.
  * Access to IO memory should be serialized by driver.
- * This code is modeled after vmalloc code - unmap_vm_area()
- *
- * XXX what about calls before mem_init_done (ie python_countermeasures())
  */
 void __iounmap(volatile void __iomem *token)
 {
@@ -251,9 +207,14 @@ void __iounmap(volatile void __iomem *token)
        if (!mem_init_done)
                return;
        
-       addr = (void *) ((unsigned long __force) token & PAGE_MASK);
-
-       im_free(addr);
+       addr = (void *) ((unsigned long __force)
+                        PCI_FIX_ADDR(token) & PAGE_MASK);
+       if ((unsigned long)addr < ioremap_bot) {
+               printk(KERN_WARNING "Attempt to iounmap early bolted mapping"
+                      " at 0x%p\n", addr);
+               return;
+       }
+       vunmap(addr);
 }
 
 void iounmap(volatile void __iomem *token)
@@ -264,77 +225,8 @@ void iounmap(volatile void __iomem *token)
                __iounmap(token);
 }
 
-static int iounmap_subset_regions(unsigned long addr, unsigned long size)
-{
-       struct vm_struct *area;
-
-       /* Check whether subsets of this region exist */
-       area = im_get_area(addr, size, IM_REGION_SUPERSET);
-       if (area == NULL)
-               return 1;
-
-       while (area) {
-               iounmap((void __iomem *) area->addr);
-               area = im_get_area(addr, size,
-                               IM_REGION_SUPERSET);
-       }
-
-       return 0;
-}
-
-int __iounmap_explicit(volatile void __iomem *start, unsigned long size)
-{
-       struct vm_struct *area;
-       unsigned long addr;
-       int rc;
-       
-       addr = (unsigned long __force) start & PAGE_MASK;
-
-       /* Verify that the region either exists or is a subset of an existing
-        * region.  In the latter case, split the parent region to create 
-        * the exact region 
-        */
-       area = im_get_area(addr, size, 
-                           IM_REGION_EXISTS | IM_REGION_SUBSET);
-       if (area == NULL) {
-               /* Determine whether subset regions exist.  If so, unmap */
-               rc = iounmap_subset_regions(addr, size);
-               if (rc) {
-                       printk(KERN_ERR
-                              "%s() cannot unmap nonexistent range 0x%lx\n",
-                               __FUNCTION__, addr);
-                       return 1;
-               }
-       } else {
-               iounmap((void __iomem *) area->addr);
-       }
-       /*
-        * FIXME! This can't be right:
-       iounmap(area->addr);
-        * Maybe it should be "iounmap(area);"
-        */
-       return 0;
-}
-
 EXPORT_SYMBOL(ioremap);
 EXPORT_SYMBOL(ioremap_flags);
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(iounmap);
 EXPORT_SYMBOL(__iounmap);
-
-static DEFINE_SPINLOCK(phb_io_lock);
-
-void __iomem * reserve_phb_iospace(unsigned long size)
-{
-       void __iomem *virt_addr;
-               
-       if (phbs_io_bot >= IMALLOC_BASE) 
-               panic("reserve_phb_iospace(): phb io space overflow\n");
-                       
-       spin_lock(&phb_io_lock);
-       virt_addr = (void __iomem *) phbs_io_bot;
-       phbs_io_bot += size;
-       spin_unlock(&phb_io_lock);
-
-       return virt_addr;
-}
index ec1421a20aaab96d94f6ea162066a95df81fd602..5c45d474cfcc91d2b09211974fad4508e3de3af0 100644 (file)
@@ -11,7 +11,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
 
 #include "mmu_decl.h"
 
-PTE *Hash, *Hash_end;
+struct hash_pte *Hash, *Hash_end;
 unsigned long Hash_size, Hash_mask;
 unsigned long _SDR1;
 
 union ubat {                   /* BAT register values to be loaded */
-       BAT     bat;
+       struct ppc_bat bat;
        u32     word[2];
 } BATS[8][2];                  /* 8 pairs of IBAT, DBAT */
 
@@ -245,7 +244,7 @@ void __init MMU_init_hw(void)
        cacheable_memzero(Hash, Hash_size);
        _SDR1 = __pa(Hash) | SDR1_LOW_BITS;
 
-       Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
+       Hash_end = (struct hash_pte *) ((unsigned long)Hash + Hash_size);
 
        printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n",
               total_memory >> 20, Hash_size >> 10, Hash);
index 132c6bc66ce1405f976a12e1d419e6e05c47e7f8..28492bbdee8e3e0fad592ed705c9f00c71ee2dba 100644 (file)
@@ -55,7 +55,7 @@ static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid)
                for (entry = 0; entry < 8; entry++, ste++) {
                        if (!(ste->esid_data & STE_ESID_V)) {
                                ste->vsid_data = vsid_data;
-                               asm volatile("eieio":::"memory");
+                               eieio();
                                ste->esid_data = esid_data;
                                return (global_entry | entry);
                        }
@@ -101,7 +101,7 @@ static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid)
        asm volatile("sync" : : : "memory");    /* Order update */
 
        castout_ste->vsid_data = vsid_data;
-       asm volatile("eieio" : : : "memory");   /* Order update */
+       eieio();                                /* Order update */
        castout_ste->esid_data = esid_data;
 
        asm volatile("slbie  %0" : : "r" (old_esid << SID_SHIFT));
index 6a69417cbc0ef3cf0eaba041081b2f3a53ae5f96..06c7e77e097ab2ba56a824a9fa930fa55c8c3498 100644 (file)
@@ -11,7 +11,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
index 2bfc4d7e1aa259b37462735c97e299c67d5d9a3e..cbd34fc813eee1ad21c39e05a1366f7bb397e9ef 100644 (file)
@@ -8,7 +8,6 @@
  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
  *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
  *    Copyright (C) 1996 Paul Mackerras
- *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  *
  *  Derived from "arch/i386/mm/init.c"
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
@@ -239,3 +238,59 @@ void pte_free_finish(void)
        pte_free_submit(*batchp);
        *batchp = NULL;
 }
+
+/**
+ * __flush_hash_table_range - Flush all HPTEs for a given address range
+ *                            from the hash table (and the TLB). But keeps
+ *                            the linux PTEs intact.
+ *
+ * @mm         : mm_struct of the target address space (generally init_mm)
+ * @start      : starting address
+ * @end         : ending address (not included in the flush)
+ *
+ * This function is mostly to be used by some IO hotplug code in order
+ * to remove all hash entries from a given address range used to map IO
+ * space on a removed PCI-PCI bidge without tearing down the full mapping
+ * since 64K pages may overlap with other bridges when using 64K pages
+ * with 4K HW pages on IO space.
+ *
+ * Because of that usage pattern, it's only available with CONFIG_HOTPLUG
+ * and is implemented for small size rather than speed.
+ */
+#ifdef CONFIG_HOTPLUG
+
+void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
+                             unsigned long end)
+{
+       unsigned long flags;
+
+       start = _ALIGN_DOWN(start, PAGE_SIZE);
+       end = _ALIGN_UP(end, PAGE_SIZE);
+
+       BUG_ON(!mm->pgd);
+
+       /* Note: Normally, we should only ever use a batch within a
+        * PTE locked section. This violates the rule, but will work
+        * since we don't actually modify the PTEs, we just flush the
+        * hash while leaving the PTEs intact (including their reference
+        * to being hashed). This is not the most performance oriented
+        * way to do things but is fine for our needs here.
+        */
+       local_irq_save(flags);
+       arch_enter_lazy_mmu_mode();
+       for (; start < end; start += PAGE_SIZE) {
+               pte_t *ptep = find_linux_pte(mm->pgd, start);
+               unsigned long pte;
+
+               if (ptep == NULL)
+                       continue;
+               pte = pte_val(*ptep);
+               if (!(pte & _PAGE_HASHPTE))
+                       continue;
+               hpte_need_flush(mm, start, ptep, pte, 0);
+       }
+       arch_leave_lazy_mmu_mode();
+       local_irq_restore(flags);
+}
+
+#endif /* CONFIG_HOTPLUG */
index fe597a154d4f31b553674117ca44e1d05b3f881d..a7c206b665afe4ec0dfb485eb2307b343ddd0cdf 100644 (file)
@@ -1,5 +1,7 @@
 /*
  * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
+ * Added mmcra[slot] support:
+ * Copyright (C) 2006-2007 Will Schmidt <willschm@us.ibm.com>, IBM
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -181,11 +183,17 @@ static void __attribute_used__ kernel_unknown_bucket(void)
  * On GQ and newer the MMCRA stores the HV and PR bits at the time
  * the SIAR was sampled. We use that to work out if the SIAR was sampled in
  * the hypervisor, our exception vectors or RTAS.
+ * If the MMCRA_SAMPLE_ENABLE bit is set, we can use the MMCRA[slot] bits
+ * to more accurately identify the address of the sampled instruction. The
+ * mmcra[slot] bits represent the slot number of a sampled instruction
+ * within an instruction group.  The slot will contain a value between 1
+ * and 5 if MMCRA_SAMPLE_ENABLE is set, otherwise 0.
  */
 static unsigned long get_pc(struct pt_regs *regs)
 {
        unsigned long pc = mfspr(SPRN_SIAR);
        unsigned long mmcra;
+       unsigned long slot;
 
        /* Cant do much about it */
        if (!cur_cpu_spec->oprofile_mmcra_sihv)
@@ -193,6 +201,12 @@ static unsigned long get_pc(struct pt_regs *regs)
 
        mmcra = mfspr(SPRN_MMCRA);
 
+       if (mmcra & MMCRA_SAMPLE_ENABLE) {
+               slot = ((mmcra & MMCRA_SLOT) >> MMCRA_SLOT_SHIFT);
+               if (slot > 1)
+                       pc += 4 * (slot - 1);
+       }
+
        /* Were we in the hypervisor? */
        if (firmware_has_feature(FW_FEATURE_LPAR) &&
            (mmcra & cur_cpu_spec->oprofile_mmcra_sihv))
index f591a9fc19b9db179777d3f35f9597e00b19807c..4be6e7a17b66037ae0804e8dba00c67eed4cfc73 100644 (file)
@@ -54,7 +54,7 @@ static int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
        struct pci_controller *hose = bus->sysdata;
        unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
            | (((bus->number - hose->first_busno) & 0xff) << 16)
-           | (hose->index << 24);
+           | (hose->global_number << 24);
        int ret = -1;
        int rval;
 
@@ -69,7 +69,7 @@ static int rtas_write_config(struct pci_bus *bus, unsigned int devfn,
        struct pci_controller *hose = bus->sysdata;
        unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
            | (((bus->number - hose->first_busno) & 0xff) << 16)
-           | (hose->index << 24);
+           | (hose->global_number << 24);
        int rval;
 
        rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL,
@@ -83,7 +83,7 @@ static struct pci_ops rtas_pci_ops = {
 };
 
 
-void __init efika_pcisetup(void)
+static void __init efika_pcisetup(void)
 {
        const int *bus_range;
        int len;
@@ -128,7 +128,7 @@ void __init efika_pcisetup(void)
        printk(" controlled by %s\n", pcictrl->full_name);
        printk("\n");
 
-       hose = pcibios_alloc_controller();
+       hose = pcibios_alloc_controller(of_node_get(pcictrl));
        if (!hose) {
                printk(KERN_WARNING EFIKA_PLATFORM_NAME
                       ": Can't allocate PCI controller structure for %s\n",
@@ -136,7 +136,6 @@ void __init efika_pcisetup(void)
                return;
        }
 
-       hose->arch_data = of_node_get(pcictrl);
        hose->first_busno = bus_range[0];
        hose->last_busno = bus_range[1];
        hose->ops = &rtas_pci_ops;
@@ -145,7 +144,7 @@ void __init efika_pcisetup(void)
 }
 
 #else
-void __init efika_pcisetup(void)
+static void __init efika_pcisetup(void)
 {}
 #endif
 
@@ -252,6 +251,8 @@ define_machine(efika)
        .progress               = rtas_progress,
        .get_boot_time          = rtas_get_boot_time,
        .calibrate_decr         = generic_calibrate_decr,
+#ifdef CONFIG_PCI
        .phys_mem_access_prot   = pci_phys_mem_access_prot,
+#endif
 };
 
index 1cfc00dfb99a656f488249ea71adbe258084832b..5c46e898fd4526dc3a4f69681d132a26505cf1cc 100644 (file)
@@ -156,7 +156,7 @@ static void __init lite5200_setup_arch(void)
 
 }
 
-void lite5200_show_cpuinfo(struct seq_file *m)
+static void lite5200_show_cpuinfo(struct seq_file *m)
 {
        struct device_node* np = of_find_all_nodes(NULL);
        const char *model = NULL;
index 34d34a26d30576faf647160b4334bee6e56d0327..4c6c82a684b1eb23bb43642b86200d564c491f29 100644 (file)
@@ -112,18 +112,18 @@ mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
        u32 value;
 
        if (ppc_md.pci_exclude_device)
-               if (ppc_md.pci_exclude_device(bus->number, devfn))
+               if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
                        return PCIBIOS_DEVICE_NOT_FOUND;
 
        out_be32(hose->cfg_addr,
                (1 << 31) |
-               ((bus->number - hose->bus_offset) << 16) |
+               (bus->number << 16) |
                (devfn << 8) |
                (offset & 0xfc));
        mb();
 
 #if defined(CONFIG_PPC_MPC5200_BUGFIX)
-       if (bus->number != hose->bus_offset) {
+       if (bus->number) {
                /* workaround for the bug 435 of the MPC5200 (L25R);
                 * Don't do 32 bits config access during type-1 cycles */
                switch (len) {
@@ -169,18 +169,18 @@ mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
        u32 value, mask;
 
        if (ppc_md.pci_exclude_device)
-               if (ppc_md.pci_exclude_device(bus->number, devfn))
+               if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
                        return PCIBIOS_DEVICE_NOT_FOUND;
 
        out_be32(hose->cfg_addr,
                (1 << 31) |
-               ((bus->number - hose->bus_offset) << 16) |
+               (bus->number << 16) |
                (devfn << 8) |
                (offset & 0xfc));
        mb();
 
 #if defined(CONFIG_PPC_MPC5200_BUGFIX)
-       if (bus->number != hose->bus_offset) {
+       if (bus->number) {
                /* workaround for the bug 435 of the MPC5200 (L25R);
                 * Don't do 32 bits config access during type-1 cycles */
                switch (len) {
@@ -385,17 +385,13 @@ mpc52xx_add_bridge(struct device_node *node)
         * tree are needed to configure the 52xx PCI controller.  Rather
         * than parse the tree here, let pci_process_bridge_OF_ranges()
         * do it for us and extract the values after the fact */
-       hose = pcibios_alloc_controller();
+       hose = pcibios_alloc_controller(node);
        if (!hose)
                return -ENOMEM;
 
-       hose->arch_data = node;
-       hose->set_cfg_type = 1;
-
        hose->first_busno = bus_range ? bus_range[0] : 0;
        hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
-       hose->bus_offset = 0;
        hose->ops = &mpc52xx_pci_ops;
 
        pci_regs = ioremap(rsrc.start, rsrc.end - rsrc.start + 1);
index fd40044d16cdd561672facb645f1c2d5f3817a38..ee2e7639c63e85c6d890251a2240450d048c03a1 100644 (file)
@@ -9,8 +9,8 @@
 
 
 /* these are defined in mpc52xx_sleep.S, and only used here */
-extern void mpc52xx_deep_sleep(void *sram, void *sdram_regs,
-               struct mpc52xx_cdm *, struct mpc52xx_intr *);
+extern void mpc52xx_deep_sleep(void __iomem *sram, void __iomem *sdram_regs,
+               struct mpc52xx_cdm __iomem *, struct mpc52xx_intr __iomem*);
 extern void mpc52xx_ds_sram(void);
 extern const long mpc52xx_ds_sram_size;
 extern void mpc52xx_ds_cached(void);
@@ -21,7 +21,7 @@ static void __iomem *sdram;
 static struct mpc52xx_cdm __iomem *cdm;
 static struct mpc52xx_intr __iomem *intr;
 static struct mpc52xx_gpio_wkup __iomem *gpiow;
-static void *sram;
+static void __iomem *sram;
 static int sram_size;
 
 struct mpc52xx_suspend mpc52xx_suspend;
@@ -100,7 +100,7 @@ int mpc52xx_pm_enter(suspend_state_t state)
        u32 clk_enables;
        u32 msr, hid0;
        u32 intr_main_mask;
-       void __iomem * irq_0x500 = (void *)CONFIG_KERNEL_START + 0x500;
+       void __iomem * irq_0x500 = (void __iomem *)CONFIG_KERNEL_START + 0x500;
        unsigned long irq_0x500_stop = (unsigned long)irq_0x500 + mpc52xx_ds_cached_size;
        char saved_0x500[mpc52xx_ds_cached_size];
 
index de7fce9cb6eb8b632e0efb7f2b2c1b1b00409e62..89fde43895c505c678304707c7ded6b579322db9 100644 (file)
@@ -1,5 +1,5 @@
 choice
-       prompt "Machine Type"
+       prompt "82xx Board Type"
        depends on PPC_82xx
        default MPC82xx_ADS
 
index 47cb09f08052837cb2c7f5621dfcca30c4a79f0b..da20832b27f1d0a0f3d38d238b72b1c8181aaaeb 100644 (file)
@@ -49,7 +49,7 @@
 #include <linux/fs_enet_pd.h>
 
 #include <sysdev/fsl_soc.h>
-#include <../sysdev/cpm2_pic.h>
+#include <sysdev/cpm2_pic.h>
 
 #include "pq2ads.h"
 
@@ -507,7 +507,8 @@ void m82xx_pci_init_irq(void)
        return;
 }
 
-static int m82xx_pci_exclude_device(u_char bus, u_char devfn)
+static int m82xx_pci_exclude_device(struct pci_controller *hose,
+                                   u_char bus, u_char devfn)
 {
        if (bus == 0 && PCI_SLOT(devfn) == 0)
                return PCIBIOS_DEVICE_NOT_FOUND;
@@ -515,7 +516,7 @@ static int m82xx_pci_exclude_device(u_char bus, u_char devfn)
                return PCIBIOS_SUCCESSFUL;
 }
 
-void __init add_bridge(struct device_node *np)
+static void __init mpc82xx_add_bridge(struct device_node *np)
 {
        int len;
        struct pci_controller *hose;
@@ -542,19 +543,13 @@ void __init add_bridge(struct device_node *np)
 
        pci_assign_all_buses = 1;
 
-       hose = pcibios_alloc_controller();
+       hose = pcibios_alloc_controller(np);
 
        if (!hose)
                return;
 
-       hose->arch_data = np;
-       hose->set_cfg_type = 1;
-
        hose->first_busno = bus_range ? bus_range[0] : 0;
        hose->last_busno = bus_range ? bus_range[1] : 0xff;
-       hose->bus_offset = 0;
-
-       hose->set_cfg_type = 1;
 
        setup_indirect_pci(hose,
                           r.start + offsetof(pci_cpm2_t, pci_cfg_addr),
@@ -584,7 +579,7 @@ static void __init mpc82xx_ads_setup_arch(void)
 #ifdef CONFIG_PCI
        ppc_md.pci_exclude_device = m82xx_pci_exclude_device;
        for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-               add_bridge(np);
+               mpc82xx_add_bridge(np);
 
        of_node_put(np);
 #endif
index 19cafdf6df9385bc75befac6a2c771e8d15fa582..ec305f18abd8f4da243a1fbea875c43be75b1933 100644 (file)
@@ -1,5 +1,5 @@
 choice
-       prompt "Machine Type"
+       prompt "83xx Board Type"
        depends on PPC_83xx
        default MPC834x_MDS
 
index 31a91b53f52825fde3fb639f19d4f919370534ae..5a98f885779f80765a4560a4328efb36e05e7fec 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Makefile for the PowerPC 83xx linux kernel.
 #
-obj-y                          := misc.o
+obj-y                          := misc.o usb.o
 obj-$(CONFIG_PCI)              += pci.o
 obj-$(CONFIG_MPC8313_RDB)      += mpc8313_rdb.o
 obj-$(CONFIG_MPC832x_RDB)      += mpc832x_rdb.o
index 96970ac887ee267dc2826f607298df6cf930e36c..3edfe170a03b3881f282b847057d29c046756d49 100644 (file)
 #define DBG(fmt...)
 #endif
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 /* ************************************************************************
  *
  * Setup the architecture
@@ -49,10 +44,11 @@ static void __init mpc8313_rdb_setup_arch(void)
 
 #ifdef CONFIG_PCI
        for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-               add_bridge(np);
+               mpc83xx_add_bridge(np);
 
        ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
+       mpc831x_usb_cfg();
 }
 
 void __init mpc8313_rdb_init_IRQ(void)
index 94843ed52a9334b476724e4243cd56520e45b1db..b39cb52c6fb90290c2c6ca368f22f88dc331ddf4 100644 (file)
 #define DBG(fmt...)
 #endif
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 static u8 *bcsr_regs = NULL;
 
 /* ************************************************************************
@@ -80,7 +75,7 @@ static void __init mpc832x_sys_setup_arch(void)
 
 #ifdef CONFIG_PCI
        for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-               add_bridge(np);
+               mpc83xx_add_bridge(np);
        ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
 
index 3db68b73fc3297a8eab6c1bff2d73cf0de3532cf..b2b28a44738c901a0faf6f4efbf762dee4b03f57 100644 (file)
 #define DBG(fmt...)
 #endif
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 /* ************************************************************************
  *
  * Setup the architecture
@@ -53,7 +48,7 @@ static void __init mpc832x_rdb_setup_arch(void)
 
 #ifdef CONFIG_PCI
        for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-               add_bridge(np);
+               mpc83xx_add_bridge(np);
 
        ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
index 40a01947d6840428733df06f316d8f0be3152904..47ba5446f63c8f6c4b54b88f631169072517b93b 100644 (file)
 
 #include "mpc83xx.h"
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 /* ************************************************************************
  *
  * Setup the architecture
@@ -59,10 +54,12 @@ static void __init mpc834x_itx_setup_arch(void)
 
 #ifdef CONFIG_PCI
        for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-               add_bridge(np);
+               mpc83xx_add_bridge(np);
 
        ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
+
+       mpc834x_usb_cfg();
 }
 
 static void __init mpc834x_itx_init_IRQ(void)
index 10394b2d7e7a0bd44cb4cc9871d7ddc30f876897..4c9ff9cadfe4f6d244ae3e897955bc9be579e95c 100644 (file)
 
 #include "mpc83xx.h"
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 #define BCSR5_INT_USB          0x02
-/* Note: This is only for PB, not for PB+PIB
- * On PB only port0 is connected using ULPI */
-static int mpc834x_usb_cfg(void)
+static int mpc834xemds_usb_cfg(void)
 {
-       unsigned long sccr, sicrl;
-       void __iomem *immap;
+       struct device_node *np;
        void __iomem *bcsr_regs = NULL;
        u8 bcsr5;
-       struct device_node *np = NULL;
-       int port0_is_dr = 0;
-
-       if ((np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr")) != NULL)
-               port0_is_dr = 1;
-       if ((np = of_find_compatible_node(NULL, "usb", "fsl-usb2-mph")) != NULL){
-               if (port0_is_dr) {
-                       printk(KERN_WARNING
-                               "There is only one USB port on PB board! \n");
-                       return -1;
-               } else if (!port0_is_dr)
-                       /* No usb port enabled */
-                       return -1;
-       }
-
-       immap = ioremap(get_immrbase(), 0x1000);
-       if (!immap)
-               return -1;
-
-       /* Configure clock */
-       sccr = in_be32(immap + MPC83XX_SCCR_OFFS);
-       if (port0_is_dr)
-               sccr |= MPC83XX_SCCR_USB_DRCM_11;  /* 1:3 */
-       else
-               sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */
-       out_be32(immap + MPC83XX_SCCR_OFFS, sccr);
-
-       /* Configure Pin */
-       sicrl = in_be32(immap + MPC83XX_SICRL_OFFS);
-       /* set port0 only */
-       if (port0_is_dr)
-               sicrl |= MPC83XX_SICRL_USB0;
-       else
-               sicrl &= ~(MPC83XX_SICRL_USB0);
-       out_be32(immap + MPC83XX_SICRL_OFFS, sicrl);
-
-       iounmap(immap);
 
+       mpc834x_usb_cfg();
        /* Map BCSR area */
        np = of_find_node_by_name(NULL, "bcsr");
-       if (np != 0) {
+       if (np) {
                struct resource res;
 
                of_address_to_resource(np, 0, &res);
@@ -129,12 +85,12 @@ static void __init mpc834x_mds_setup_arch(void)
 
 #ifdef CONFIG_PCI
        for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-               add_bridge(np);
+               mpc83xx_add_bridge(np);
 
        ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
 
-       mpc834x_usb_cfg();
+       mpc834xemds_usb_cfg();
 }
 
 static void __init mpc834x_mds_init_IRQ(void)
index bceeff8bbfd21045fb9c873a468720f6f6d90552..0e615fd65c1fd1050c91a833a920fa03945f834d 100644 (file)
 #define DBG(fmt...)
 #endif
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 static u8 *bcsr_regs = NULL;
 
 /* ************************************************************************
@@ -86,7 +81,7 @@ static void __init mpc836x_mds_setup_arch(void)
 
 #ifdef CONFIG_PCI
        for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-               add_bridge(np);
+               mpc83xx_add_bridge(np);
        ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
 
index 9cd03b59c8f4796a177e8df9801a03cd09d02c5e..589ee55730f3945ea0345d2db6c726ea8a0f9b14 100644 (file)
@@ -3,9 +3,11 @@
 
 #include <linux/init.h>
 #include <linux/device.h>
+#include <asm/pci-bridge.h>
 
 /* System Clock Control Register */
 #define MPC83XX_SCCR_OFFS          0xA08
+#define MPC83XX_SCCR_USB_MASK      0x00f00000
 #define MPC83XX_SCCR_USB_MPHCM_11  0x00c00000
 #define MPC83XX_SCCR_USB_MPHCM_01  0x00400000
 #define MPC83XX_SCCR_USB_MPHCM_10  0x00800000
 
 /* system i/o configuration register low */
 #define MPC83XX_SICRL_OFFS         0x114
-#define MPC83XX_SICRL_USB0         0x40000000
-#define MPC83XX_SICRL_USB1         0x20000000
+#define MPC834X_SICRL_USB_MASK     0x60000000
+#define MPC834X_SICRL_USB0         0x40000000
+#define MPC834X_SICRL_USB1         0x20000000
+#define MPC831X_SICRL_USB_MASK     0x00000c00
+#define MPC831X_SICRL_USB_ULPI     0x00000800
 
 /* system i/o configuration register high */
 #define MPC83XX_SICRH_OFFS         0x118
-#define MPC83XX_SICRH_USB_UTMI     0x00020000
+#define MPC834X_SICRH_USB_UTMI     0x00020000
+#define MPC831X_SICRH_USB_MASK     0x000000e0
+#define MPC831X_SICRH_USB_ULPI     0x000000a0
+
+/* USB Control Register */
+#define FSL_USB2_CONTROL_OFFS      0x500
+#define CONTROL_UTMI_PHY_EN        0x00000200
+#define CONTROL_REFSEL_48MHZ       0x00000080
+#define CONTROL_PHY_CLK_SEL_ULPI   0x00000400
+#define CONTROL_OTG_PORT           0x00000020
+
+/* USB PORTSC Registers */
+#define FSL_USB2_PORTSC1_OFFS      0x184
+#define FSL_USB2_PORTSC2_OFFS      0x188
+#define PORTSCX_PTW_16BIT          0x10000000
+#define PORTSCX_PTS_UTMI           0x00000000
+#define PORTSCX_PTS_ULPI           0x80000000
 
 /*
  * Declaration for the various functions exported by the
  * mpc83xx_* files. Mostly for use by mpc83xx_setup
  */
 
-extern int add_bridge(struct device_node *dev);
-extern int mpc83xx_exclude_device(u_char bus, u_char devfn);
+extern int mpc83xx_add_bridge(struct device_node *dev);
+extern int mpc83xx_exclude_device(struct pci_controller *hose,
+                                 u_char bus, u_char devfn);
 extern void mpc83xx_restart(char *cmd);
 extern long mpc83xx_time_init(void);
+extern int mpc834x_usb_cfg(void);
+extern int mpc831x_usb_cfg(void);
 
 #endif                         /* __MPC83XX_H__ */
index 774457d09e947af0c43ef8cd9d4f99b780e1bd8d..c0e2b89154e540457aa9e1fbfacab905870e7d56 100644 (file)
 #define DBG(x...)
 #endif
 
-int mpc83xx_pci2_busno;
-
-int mpc83xx_exclude_device(u_char bus, u_char devfn)
+int mpc83xx_exclude_device(struct pci_controller *hose, u_char bus, u_char devfn)
 {
-       if (bus == 0 && PCI_SLOT(devfn) == 0)
+       if ((bus == hose->first_busno) && PCI_SLOT(devfn) == 0)
                return PCIBIOS_DEVICE_NOT_FOUND;
-       if (mpc83xx_pci2_busno)
-               if (bus == (mpc83xx_pci2_busno) && PCI_SLOT(devfn) == 0)
-                       return PCIBIOS_DEVICE_NOT_FOUND;
        return PCIBIOS_SUCCESSFUL;
 }
 
-int __init add_bridge(struct device_node *dev)
+int __init mpc83xx_add_bridge(struct device_node *dev)
 {
        int len;
        struct pci_controller *hose;
@@ -66,11 +61,10 @@ int __init add_bridge(struct device_node *dev)
                       " bus 0\n", dev->full_name);
        }
 
-       hose = pcibios_alloc_controller();
+       pci_assign_all_buses = 1;
+       hose = pcibios_alloc_controller(dev);
        if (!hose)
                return -ENOMEM;
-       hose->arch_data = dev;
-       hose->set_cfg_type = 1;
 
        hose->first_busno = bus_range ? bus_range[0] : 0;
        hose->last_busno = bus_range ? bus_range[1] : 0xff;
@@ -86,8 +80,6 @@ int __init add_bridge(struct device_node *dev)
        if ((rsrc.start & 0xfffff) == 0x8600) {
                setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384);
                primary = 0;
-               hose->bus_offset = hose->first_busno;
-               mpc83xx_pci2_busno = hose->first_busno;
        }
 
        printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. "
diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c
new file mode 100644 (file)
index 0000000..e7fdf01
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Freescale 83xx USB SOC setup code
+ *
+ * Copyright (C) 2007 Freescale Semiconductor, Inc.
+ * Author: Li Yang
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <sysdev/fsl_soc.h>
+
+#include "mpc83xx.h"
+
+
+#ifdef CONFIG_MPC834x
+int mpc834x_usb_cfg(void)
+{
+       unsigned long sccr, sicrl, sicrh;
+       void __iomem *immap;
+       struct device_node *np = NULL;
+       int port0_is_dr = 0, port1_is_dr = 0;
+       const void *prop, *dr_mode;
+
+       immap = ioremap(get_immrbase(), 0x1000);
+       if (!immap)
+               return -ENOMEM;
+
+       /* Read registers */
+       /* Note: DR and MPH must use the same clock setting in SCCR */
+       sccr = in_be32(immap + MPC83XX_SCCR_OFFS) & ~MPC83XX_SCCR_USB_MASK;
+       sicrl = in_be32(immap + MPC83XX_SICRL_OFFS) & ~MPC834X_SICRL_USB_MASK;
+       sicrh = in_be32(immap + MPC83XX_SICRH_OFFS) & ~MPC834X_SICRH_USB_UTMI;
+
+       np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr");
+       if (np) {
+               sccr |= MPC83XX_SCCR_USB_DRCM_11;  /* 1:3 */
+
+               prop = of_get_property(np, "phy_type", NULL);
+               if (prop && (!strcmp(prop, "utmi") ||
+                                       !strcmp(prop, "utmi_wide"))) {
+                       sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1;
+                       sicrh |= MPC834X_SICRH_USB_UTMI;
+                       port1_is_dr = 1;
+               } else if (prop && !strcmp(prop, "serial")) {
+                       dr_mode = of_get_property(np, "dr_mode", NULL);
+                       if (dr_mode && !strcmp(dr_mode, "otg")) {
+                               sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1;
+                               port1_is_dr = 1;
+                       } else {
+                               sicrl |= MPC834X_SICRL_USB0;
+                       }
+               } else if (prop && !strcmp(prop, "ulpi")) {
+                       sicrl |= MPC834X_SICRL_USB0;
+               } else {
+                       printk(KERN_WARNING "834x USB PHY type not supported\n");
+               }
+               port0_is_dr = 1;
+               of_node_put(np);
+       }
+       np = of_find_compatible_node(NULL, "usb", "fsl-usb2-mph");
+       if (np) {
+               sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */
+
+               prop = of_get_property(np, "port0", NULL);
+               if (prop) {
+                       if (port0_is_dr)
+                               printk(KERN_WARNING
+                                       "834x USB port0 can't be used by both DR and MPH!\n");
+                       sicrl |= MPC834X_SICRL_USB0;
+               }
+               prop = of_get_property(np, "port1", NULL);
+               if (prop) {
+                       if (port1_is_dr)
+                               printk(KERN_WARNING
+                                       "834x USB port1 can't be used by both DR and MPH!\n");
+                       sicrl |= MPC834X_SICRL_USB1;
+               }
+               of_node_put(np);
+       }
+
+       /* Write back */
+       out_be32(immap + MPC83XX_SCCR_OFFS, sccr);
+       out_be32(immap + MPC83XX_SICRL_OFFS, sicrl);
+       out_be32(immap + MPC83XX_SICRH_OFFS, sicrh);
+
+       iounmap(immap);
+       return 0;
+}
+#endif /* CONFIG_MPC834x */
+
+#ifdef CONFIG_PPC_MPC831x
+int mpc831x_usb_cfg(void)
+{
+       u32 temp;
+       void __iomem *immap, *usb_regs;
+       struct device_node *np = NULL;
+       const void *prop;
+       struct resource res;
+       int ret = 0;
+#ifdef CONFIG_USB_OTG
+       const void *dr_mode;
+#endif
+
+       np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr");
+       if (!np)
+               return -ENODEV;
+       prop = of_get_property(np, "phy_type", NULL);
+
+       /* Map IMMR space for pin and clock settings */
+       immap = ioremap(get_immrbase(), 0x1000);
+       if (!immap) {
+               of_node_put(np);
+               return -ENOMEM;
+       }
+
+       /* Configure clock */
+       temp = in_be32(immap + MPC83XX_SCCR_OFFS);
+       temp &= ~MPC83XX_SCCR_USB_MASK;
+       temp |= MPC83XX_SCCR_USB_DRCM_11;  /* 1:3 */
+       out_be32(immap + MPC83XX_SCCR_OFFS, temp);
+
+       /* Configure pin mux for ULPI.  There is no pin mux for UTMI */
+       if (!strcmp(prop, "ulpi")) {
+               temp = in_be32(immap + MPC83XX_SICRL_OFFS);
+               temp &= ~MPC831X_SICRL_USB_MASK;
+               temp |= MPC831X_SICRL_USB_ULPI;
+               out_be32(immap + MPC83XX_SICRL_OFFS, temp);
+
+               temp = in_be32(immap + MPC83XX_SICRH_OFFS);
+               temp &= ~MPC831X_SICRH_USB_MASK;
+               temp |= MPC831X_SICRH_USB_ULPI;
+               out_be32(immap + MPC83XX_SICRH_OFFS, temp);
+       }
+
+       iounmap(immap);
+
+       /* Map USB SOC space */
+       ret = of_address_to_resource(np, 0, &res);
+       if (ret) {
+               of_node_put(np);
+               return ret;
+       }
+       usb_regs = ioremap(res.start, res.end - res.start + 1);
+
+       /* Using on-chip PHY */
+       if (!strcmp(prop, "utmi_wide") ||
+                       !strcmp(prop, "utmi")) {
+               /* Set UTMI_PHY_EN, REFSEL to 48MHZ */
+               out_be32(usb_regs + FSL_USB2_CONTROL_OFFS,
+                               CONTROL_UTMI_PHY_EN | CONTROL_REFSEL_48MHZ);
+       /* Using external UPLI PHY */
+       } else if (!strcmp(prop, "ulpi")) {
+               /* Set PHY_CLK_SEL to ULPI */
+               temp = CONTROL_PHY_CLK_SEL_ULPI;
+#ifdef CONFIG_USB_OTG
+               /* Set OTG_PORT */
+               dr_mode = of_get_property(np, "dr_mode", NULL);
+               if (dr_mode && !strcmp(dr_mode, "otg"))
+                       temp |= CONTROL_OTG_PORT;
+#endif /* CONFIG_USB_OTG */
+               out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, temp);
+       } else {
+               printk(KERN_WARNING "831x USB PHY type not supported\n");
+               ret = -EINVAL;
+       }
+
+       iounmap(usb_regs);
+       of_node_put(np);
+       return ret;
+}
+#endif /* CONFIG_PPC_MPC831x */
index 3e62fcb04c1c523766641db8bb89ec1821a3e378..4fe376e9c3b665d67a0fcda4438feab3ff1a56d3 100644 (file)
 #include <linux/irq.h>
 #include <linux/module.h>
 #include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <sysdev/fsl_soc.h>
+
+static __be32 __iomem *rstcr;
 
 extern void abort(void);
 
+static int __init mpc85xx_rstcr(void)
+{
+       struct device_node *np;
+       np = of_find_node_by_name(NULL, "global-utilities");
+       if ((np && of_get_property(np, "fsl,has-rstcr", NULL))) {
+               const u32 *prop = of_get_property(np, "reg", NULL);
+               if (prop) {
+                       /* map reset control register
+                        * 0xE00B0 is offset of reset control register
+                        */
+                       rstcr = ioremap(get_immrbase() + *prop + 0xB0, 0xff);
+                       if (!rstcr)
+                               printk (KERN_EMERG "Error: reset control "
+                                               "register not mapped!\n");
+               }
+       } else
+               printk (KERN_INFO "rstcr compatible register does not exist!\n");
+       if (np)
+               of_node_put(np);
+       return 0;
+}
+
+arch_initcall(mpc85xx_rstcr);
+
 void mpc85xx_restart(char *cmd)
 {
        local_irq_disable();
+       if (rstcr)
+               /* set reset control register */
+               out_be32(rstcr, 0x2);   /* HRESET_REQ */
        abort();
 }
index bec84ffe708e013ed88cabd8b261823da201d2c7..6fb90aab879fc96a895225527ce481a9999b7560 100644 (file)
@@ -61,24 +61,11 @@ void __init mpc8544_ds_pic_init(void)
                return;
        }
 
-       /* Alloc mpic structure and per isu has 16 INT entries. */
        mpic = mpic_alloc(np, r.start,
                          MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
-                         16, 64, " OPENPIC     ");
+                       0, 256, " OpenPIC  ");
        BUG_ON(mpic == NULL);
 
-       /*
-        * 48 Internal Interrupts
-        */
-       mpic_assign_isu(mpic, 0, r.start + 0x10200);
-       mpic_assign_isu(mpic, 1, r.start + 0x10400);
-       mpic_assign_isu(mpic, 2, r.start + 0x10600);
-
-       /*
-        * 16 External interrupts
-        */
-       mpic_assign_isu(mpic, 3, r.start + 0x10000);
-
        mpic_init(mpic);
 
 #ifdef CONFIG_PPC_I8259
index 83415db33378e71e22bd2f514be1071c53fee2c5..7286ffac2c1dbaeaf77c4b21568fa0523e99b2e5 100644 (file)
@@ -15,4 +15,4 @@
  */
 
 extern void mpc85xx_restart(char *);
-extern int add_bridge(struct device_node *dev);
+extern int mpc85xx_add_bridge(struct device_node *dev);
index 5d27621f09272af77d520afbdb7c1f29a0ebc303..7235f702394c91a3b7a66a2d9938c639da6dcd13 100644 (file)
 #include <asm/fs_pd.h>
 #endif
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 #ifdef CONFIG_PCI
-static int mpc85xx_exclude_device(u_char bus, u_char devfn)
+static int mpc85xx_exclude_device(struct pci_controller *hose,
+                                  u_char bus, u_char devfn)
 {
        if (bus == 0 && PCI_SLOT(devfn) == 0)
                return PCIBIOS_DEVICE_NOT_FOUND;
@@ -91,30 +87,10 @@ static void __init mpc85xx_ads_pic_init(void)
 
        mpic = mpic_alloc(np, r.start,
                        MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
-                       4, 0, " OpenPIC  ");
+                       0, 256, " OpenPIC  ");
        BUG_ON(mpic == NULL);
        of_node_put(np);
 
-       mpic_assign_isu(mpic, 0, r.start + 0x10200);
-       mpic_assign_isu(mpic, 1, r.start + 0x10280);
-       mpic_assign_isu(mpic, 2, r.start + 0x10300);
-       mpic_assign_isu(mpic, 3, r.start + 0x10380);
-       mpic_assign_isu(mpic, 4, r.start + 0x10400);
-       mpic_assign_isu(mpic, 5, r.start + 0x10480);
-       mpic_assign_isu(mpic, 6, r.start + 0x10500);
-       mpic_assign_isu(mpic, 7, r.start + 0x10580);
-
-       /* Unused on this platform (leave room for 8548) */
-       mpic_assign_isu(mpic, 8, r.start + 0x10600);
-       mpic_assign_isu(mpic, 9, r.start + 0x10680);
-       mpic_assign_isu(mpic, 10, r.start + 0x10700);
-       mpic_assign_isu(mpic, 11, r.start + 0x10780);
-
-       /* External Interrupts */
-       mpic_assign_isu(mpic, 12, r.start + 0x10000);
-       mpic_assign_isu(mpic, 13, r.start + 0x10080);
-       mpic_assign_isu(mpic, 14, r.start + 0x10100);
-
        mpic_init(mpic);
 
 #ifdef CONFIG_CPM2
@@ -241,7 +217,7 @@ static void __init mpc85xx_ads_setup_arch(void)
 
 #ifdef CONFIG_PCI
        for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-               add_bridge(np);
+               mpc85xx_add_bridge(np);
        ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 #endif
 }
index 1490eb3ce0d3d447b6d2731645db5f1c78203a7b..50c8d6458362276a825df8510144df1b784b34f0 100644 (file)
 #include <sysdev/fsl_soc.h>
 #include "mpc85xx.h"
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 static int cds_pci_slot = 2;
 static volatile u8 *cadmus;
 
@@ -60,15 +55,11 @@ static volatile u8 *cadmus;
 #define ARCADIA_HOST_BRIDGE_IDSEL      17
 #define ARCADIA_2ND_BRIDGE_IDSEL       3
 
-extern int mpc85xx_pci2_busno;
-
-static int mpc85xx_exclude_device(u_char bus, u_char devfn)
+static int mpc85xx_exclude_device(struct pci_controller *hose,
+                                 u_char bus, u_char devfn)
 {
-       if (bus == 0 && PCI_SLOT(devfn) == 0)
+       if ((bus == hose->first_busno) && PCI_SLOT(devfn) == 0)
                return PCIBIOS_DEVICE_NOT_FOUND;
-       if (mpc85xx_pci2_busno)
-               if (bus == (mpc85xx_pci2_busno) && PCI_SLOT(devfn) == 0)
-                       return PCIBIOS_DEVICE_NOT_FOUND;
        /* We explicitly do not go past the Tundra 320 Bridge */
        if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
                return PCIBIOS_DEVICE_NOT_FOUND;
@@ -78,52 +69,44 @@ static int mpc85xx_exclude_device(u_char bus, u_char devfn)
                return PCIBIOS_SUCCESSFUL;
 }
 
-static void __init mpc85xx_cds_pcibios_fixup(void)
+static void __init mpc85xx_cds_pci_irq_fixup(struct pci_dev *dev)
 {
-       struct pci_dev *dev;
-       u_char          c;
-
-       if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
-                                       PCI_DEVICE_ID_VIA_82C586_1, NULL))) {
+       u_char c;
+       if (dev->vendor == PCI_VENDOR_ID_VIA) {
+               switch (dev->device) {
+               case PCI_DEVICE_ID_VIA_82C586_1:
+                       /*
+                        * U-Boot does not set the enable bits
+                        * for the IDE device. Force them on here.
+                        */
+                       pci_read_config_byte(dev, 0x40, &c);
+                       c |= 0x03; /* IDE: Chip Enable Bits */
+                       pci_write_config_byte(dev, 0x40, c);
+
+                       /*
+                        * Since only primary interface works, force the
+                        * IDE function to standard primary IDE interrupt
+                        * w/ 8259 offset
+                        */
+                       dev->irq = 14;
+                       pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+                       break;
                /*
-                * U-Boot does not set the enable bits
-                * for the IDE device. Force them on here.
+                * Force legacy USB interrupt routing
                 */
-               pci_read_config_byte(dev, 0x40, &c);
-               c |= 0x03; /* IDE: Chip Enable Bits */
-               pci_write_config_byte(dev, 0x40, c);
-
-               /*
-                * Since only primary interface works, force the
-                * IDE function to standard primary IDE interrupt
-                * w/ 8259 offset
+               case PCI_DEVICE_ID_VIA_82C586_2:
+               /* There are two USB controllers.
+                * Identify them by functon number
                 */
-               dev->irq = 14;
-               pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-               pci_dev_put(dev);
-       }
-
-       /*
-        * Force legacy USB interrupt routing
-        */
-       if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
-                                       PCI_DEVICE_ID_VIA_82C586_2, NULL))) {
-               dev->irq = 10;
-               pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10);
-               pci_dev_put(dev);
-       }
-
-       if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
-                                       PCI_DEVICE_ID_VIA_82C586_2, dev))) {
-               dev->irq = 11;
-               pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
-               pci_dev_put(dev);
+                       if (PCI_FUNC(dev->devfn))
+                               dev->irq = 11;
+                       else
+                               dev->irq = 10;
+                       pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+               default:
+                       break;
+               }
        }
-
-       /* Now map all the PCI irqs */
-       dev = NULL;
-       for_each_pci_dev(dev)
-               pci_read_irq_line(dev);
 }
 
 #ifdef CONFIG_PPC_I8259
@@ -165,33 +148,12 @@ static void __init mpc85xx_cds_pic_init(void)
 
        mpic = mpic_alloc(np, r.start,
                        MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
-                       4, 0, " OpenPIC  ");
+                       0, 256, " OpenPIC  ");
        BUG_ON(mpic == NULL);
 
        /* Return the mpic node */
        of_node_put(np);
 
-       mpic_assign_isu(mpic, 0, r.start + 0x10200);
-       mpic_assign_isu(mpic, 1, r.start + 0x10280);
-       mpic_assign_isu(mpic, 2, r.start + 0x10300);
-       mpic_assign_isu(mpic, 3, r.start + 0x10380);
-       mpic_assign_isu(mpic, 4, r.start + 0x10400);
-       mpic_assign_isu(mpic, 5, r.start + 0x10480);
-       mpic_assign_isu(mpic, 6, r.start + 0x10500);
-       mpic_assign_isu(mpic, 7, r.start + 0x10580);
-
-       /* Used only for 8548 so far, but no harm in
-        * allocating them for everyone */
-       mpic_assign_isu(mpic, 8, r.start + 0x10600);
-       mpic_assign_isu(mpic, 9, r.start + 0x10680);
-       mpic_assign_isu(mpic, 10, r.start + 0x10700);
-       mpic_assign_isu(mpic, 11, r.start + 0x10780);
-
-       /* External Interrupts */
-       mpic_assign_isu(mpic, 12, r.start + 0x10000);
-       mpic_assign_isu(mpic, 13, r.start + 0x10080);
-       mpic_assign_isu(mpic, 14, r.start + 0x10100);
-
        mpic_init(mpic);
 
 #ifdef CONFIG_PPC_I8259
@@ -257,9 +219,9 @@ static void __init mpc85xx_cds_setup_arch(void)
 
 #ifdef CONFIG_PCI
        for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-               add_bridge(np);
+               mpc85xx_add_bridge(np);
 
-       ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup;
+       ppc_md.pci_irq_fixup = mpc85xx_cds_pci_irq_fixup;
        ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 #endif
 }
index e3dddbfe66ff711f8a14860d62252c5ebb004080..004b80bd0b846457bfa288367822a8ea24ca43cf 100644 (file)
 #define DBG(fmt...)
 #endif
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-#endif
-
 /* ************************************************************************
  *
  * Setup the architecture
@@ -100,7 +95,7 @@ static void __init mpc85xx_mds_setup_arch(void)
 
 #ifdef CONFIG_PCI
        for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) {
-               add_bridge(np);
+               mpc85xx_add_bridge(np);
        }
        of_node_put(np);
 #endif
@@ -181,29 +176,10 @@ static void __init mpc85xx_mds_pic_init(void)
 
        mpic = mpic_alloc(np, r.start,
                        MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
-                       4, 0, " OpenPIC  ");
+                       0, 256, " OpenPIC  ");
        BUG_ON(mpic == NULL);
        of_node_put(np);
 
-       /* Internal Interrupts */
-       mpic_assign_isu(mpic, 0, r.start + 0x10200);
-       mpic_assign_isu(mpic, 1, r.start + 0x10280);
-       mpic_assign_isu(mpic, 2, r.start + 0x10300);
-       mpic_assign_isu(mpic, 3, r.start + 0x10380);
-       mpic_assign_isu(mpic, 4, r.start + 0x10400);
-       mpic_assign_isu(mpic, 5, r.start + 0x10480);
-       mpic_assign_isu(mpic, 6, r.start + 0x10500);
-       mpic_assign_isu(mpic, 7, r.start + 0x10580);
-       mpic_assign_isu(mpic, 8, r.start + 0x10600);
-       mpic_assign_isu(mpic, 9, r.start + 0x10680);
-       mpic_assign_isu(mpic, 10, r.start + 0x10700);
-       mpic_assign_isu(mpic, 11, r.start + 0x10780);
-
-       /* External Interrupts */
-       mpic_assign_isu(mpic, 12, r.start + 0x10000);
-       mpic_assign_isu(mpic, 13, r.start + 0x10080);
-       mpic_assign_isu(mpic, 14, r.start + 0x10100);
-
        mpic_init(mpic);
 
 #ifdef CONFIG_QUICC_ENGINE
index 48f17e23d771ff0492f8dc9cc46efc753f420555..8118417b73649d8813fb6f37f64772eaf2fb5a47 100644 (file)
 #define DBG(x...)
 #endif
 
-int mpc85xx_pci2_busno = 0;
-
 #ifdef CONFIG_PCI
-int __init add_bridge(struct device_node *dev)
+int __init mpc85xx_add_bridge(struct device_node *dev)
 {
        int len;
        struct pci_controller *hose;
@@ -57,11 +55,10 @@ int __init add_bridge(struct device_node *dev)
                       " bus 0\n", dev->full_name);
        }
 
-       hose = pcibios_alloc_controller();
+       pci_assign_all_buses = 1;
+       hose = pcibios_alloc_controller(dev);
        if (!hose)
                return -ENOMEM;
-       hose->arch_data = dev;
-       hose->set_cfg_type = 1;
 
        hose->first_busno = bus_range ? bus_range[0] : 0;
        hose->last_busno = bus_range ? bus_range[1] : 0xff;
@@ -74,8 +71,6 @@ int __init add_bridge(struct device_node *dev)
        if ((rsrc.start & 0xfffff) == 0x9000) {
                setup_indirect_pci(hose, immr + 0x9000, immr + 0x9004);
                primary = 0;
-               hose->bus_offset = hose->first_busno;
-               mpc85xx_pci2_busno = hose->first_busno;
        }
 
        printk(KERN_INFO "Found MPC85xx PCI host bridge at 0x%016llx. "
index d1bcff5004645ea33ca237a55c32e9ad8c04d9c4..0faebfdc1596978fc55e7e565288fbadf767ed34 100644 (file)
@@ -1,5 +1,5 @@
 choice
-       prompt "Machine Type"
+       prompt "86xx Board Type"
        depends on PPC_86xx
        default MPC8641_HPCN
 
index 2834462590b809ae80de941d77a46aa925bc24e1..23f7ed2a7f884b9583f131929344f634bc976394 100644 (file)
  * mpc86xx_* files. Mostly for use by mpc86xx_setup().
  */
 
-extern int add_bridge(struct device_node *dev);
+extern int mpc86xx_add_bridge(struct device_node *dev);
 
-extern int mpc86xx_exclude_device(u_char bus, u_char devfn);
-
-extern void setup_indirect_pcie(struct pci_controller *hose,
-                                      u32 cfg_addr, u32 cfg_data);
-extern void setup_indirect_pcie_nomap(struct pci_controller *hose,
-                                            void __iomem *cfg_addr,
-                                            void __iomem *cfg_data);
+extern int mpc86xx_exclude_device(struct pci_controller *hose,
+                                 u_char bus, u_char devfn);
 
 extern void __init mpc86xx_smp_init(void);
 
index 1051702c8d4f48c5e2dc9bc0c01be7e913e8eb0b..5b01ec7c13dc518f83efb7fadd40f38273d36f99 100644 (file)
 #define DBG(fmt...) do { } while(0)
 #endif
 
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-unsigned long pci_dram_offset = 0;
-#endif
-
-
 #ifdef CONFIG_PCI
 static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
@@ -81,22 +74,9 @@ mpc86xx_hpcn_init_irq(void)
        /* Alloc mpic structure and per isu has 16 INT entries. */
        mpic1 = mpic_alloc(np, res.start,
                        MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
-                       16, NR_IRQS - 4,
-                       " MPIC     ");
+                       0, 256, " MPIC     ");
        BUG_ON(mpic1 == NULL);
 
-       mpic_assign_isu(mpic1, 0, res.start + 0x10000);
-
-       /* 48 Internal Interrupts */
-       mpic_assign_isu(mpic1, 1, res.start + 0x10200);
-       mpic_assign_isu(mpic1, 2, res.start + 0x10400);
-       mpic_assign_isu(mpic1, 3, res.start + 0x10600);
-
-       /* 16 External interrupts
-        * Moving them from [0 - 15] to [64 - 79]
-        */
-       mpic_assign_isu(mpic1, 4, res.start + 0x10000);
-
        mpic_init(mpic1);
 
 #ifdef CONFIG_PCI
@@ -319,6 +299,7 @@ static void __devinit quirk_uli5229(struct pci_dev *dev)
 {
        unsigned short temp;
        pci_write_config_word(dev, 0x04, 0x0405);
+       dev->class &= ~0x5;
        pci_read_config_word(dev, 0x4a, &temp);
        temp |= 0x1000;
        pci_write_config_word(dev, 0x4a, temp);
@@ -364,9 +345,7 @@ mpc86xx_hpcn_setup_arch(void)
 
 #ifdef CONFIG_PCI
        for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-               add_bridge(np);
-
-       ppc_md.pci_exclude_device = mpc86xx_exclude_device;
+               mpc86xx_add_bridge(np);
 #endif
 
        printk("MPC86xx HPCN board from Freescale Semiconductor\n");
index 8235c562661fc356794c5d04573fda545afe36f0..73cd5b05a84eb49b92270fbeaa71168671fc64fa 100644 (file)
@@ -122,7 +122,6 @@ static void __init
 mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size)
 {
        u16 cmd;
-       unsigned int temps;
 
        DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n",
                        pcie_offset, pcie_size);
@@ -133,22 +132,49 @@ mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size)
        early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd);
 
        early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80);
-
-       /* PCIE Bus, Fix the MPC8641D host bridge's location to bus 0xFF. */
-       early_read_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, &temps);
-       temps = (temps & 0xff000000) | (0xff) | (0x0 << 8) | (0xfe << 16);
-       early_write_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, temps);
 }
 
-int mpc86xx_exclude_device(u_char bus, u_char devfn)
+static void __devinit quirk_fsl_pcie_transparent(struct pci_dev *dev)
 {
-       if (bus == 0 && PCI_SLOT(devfn) == 0)
-               return PCIBIOS_DEVICE_NOT_FOUND;
+       struct resource *res;
+       int i, res_idx = PCI_BRIDGE_RESOURCES;
+       struct pci_controller *hose;
 
-       return PCIBIOS_SUCCESSFUL;
+       /*
+        * Make the bridge be transparent.
+        */
+       dev->transparent = 1;
+
+       hose = pci_bus_to_host(dev->bus);
+       if (!hose) {
+               printk(KERN_ERR "Can't find hose for bus %d\n",
+                      dev->bus->number);
+               return;
+       }
+
+       if (hose->io_resource.flags) {
+               res = &dev->resource[res_idx++];
+               res->start = hose->io_resource.start;
+               res->end = hose->io_resource.end;
+               res->flags = hose->io_resource.flags;
+       }
+
+       for (i = 0; i < 3; i++) {
+               res = &dev->resource[res_idx + i];
+               res->start = hose->mem_resources[i].start;
+               res->end = hose->mem_resources[i].end;
+               res->flags = hose->mem_resources[i].flags;
+       }
 }
 
-int __init add_bridge(struct device_node *dev)
+
+DECLARE_PCI_FIXUP_EARLY(0x1957, 0x7010, quirk_fsl_pcie_transparent);
+DECLARE_PCI_FIXUP_EARLY(0x1957, 0x7011, quirk_fsl_pcie_transparent);
+
+#define PCIE_LTSSM     0x404   /* PCIe Link Training and Status */
+#define PCIE_LTSSM_L0  0x16    /* L0 state */
+
+int __init mpc86xx_add_bridge(struct device_node *dev)
 {
        int len;
        struct pci_controller *hose;
@@ -156,6 +182,7 @@ int __init add_bridge(struct device_node *dev)
        const int *bus_range;
        int has_address = 0;
        int primary = 0;
+       u16 val;
 
        DBG("Adding PCIE host bridge %s\n", dev->full_name);
 
@@ -168,17 +195,23 @@ int __init add_bridge(struct device_node *dev)
                printk(KERN_WARNING "Can't get bus-range for %s, assume"
                       " bus 0\n", dev->full_name);
 
-       hose = pcibios_alloc_controller();
+       pci_assign_all_buses = 1;
+       hose = pcibios_alloc_controller(dev);
        if (!hose)
                return -ENOMEM;
-       hose->arch_data = dev;
-       hose->set_cfg_type = 1;
 
-       /* last_busno = 0xfe cause by MPC8641 PCIE bug */
+       hose->indirect_type = PPC_INDIRECT_TYPE_EXT_REG |
+                               PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS;
+
        hose->first_busno = bus_range ? bus_range[0] : 0x0;
-       hose->last_busno = bus_range ? bus_range[1] : 0xfe;
+       hose->last_busno = bus_range ? bus_range[1] : 0xff;
+
+       setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4);
 
-       setup_indirect_pcie(hose, rsrc.start, rsrc.start + 0x4);
+       /* Probe the hose link training status */
+       early_read_config_word(hose, 0, 0, PCIE_LTSSM, &val);
+       if (val < PCIE_LTSSM_L0)
+               return -ENXIO;
 
        /* Setup the PCIE host controller. */
        mpc86xx_setup_pcie(hose, rsrc.start, rsrc.end - rsrc.start + 1);
index 0901dbada3500e085be2ddf26f882e6384c56371..f1693550c70c1cf7bef1672b3a1ed86c4195ba3d 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/root_dev.h>
 #include <linux/time.h>
 #include <linux/rtc.h>
+#include <linux/fsl_devices.h>
 
 #include <asm/mmu.h>
 #include <asm/reg.h>
 
 #include "sysdev/mpc8xx_pic.h"
 
+#ifdef CONFIG_PCMCIA_M8XX
+struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops;
+#endif
+
 void m8xx_calibrate_decr(void);
 extern void m8xx_wdt_handler_install(bd_t *bp);
 extern int cpm_pic_init(void);
index c36e475d93dc86d3e5dea78731d06fa728810549..dc27dab48df095b268959406f373d97c57d5e300 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <linux/fs_enet_pd.h>
 #include <linux/fs_uart_pd.h>
+#include <linux/fsl_devices.h>
 #include <linux/mii.h>
 
 #include <asm/delay.h>
@@ -51,6 +52,70 @@ static void init_smc1_uart_ioports(struct fs_uart_platform_info* fpi);
 static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi);
 static void init_scc3_ioports(struct fs_platform_info* ptr);
 
+#ifdef CONFIG_PCMCIA_M8XX
+static void pcmcia_hw_setup(int slot, int enable)
+{
+       unsigned *bcsr_io;
+
+       bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+       if (enable)
+               clrbits32(bcsr_io, BCSR1_PCCEN);
+       else
+               setbits32(bcsr_io, BCSR1_PCCEN);
+
+       iounmap(bcsr_io);
+}
+
+static int pcmcia_set_voltage(int slot, int vcc, int vpp)
+{
+       u32 reg = 0;
+       unsigned *bcsr_io;
+
+       bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+       switch(vcc) {
+       case 0:
+               break;
+       case 33:
+               reg |= BCSR1_PCCVCC0;
+               break;
+       case 50:
+               reg |= BCSR1_PCCVCC1;
+               break;
+       default:
+               return 1;
+       }
+
+       switch(vpp) {
+       case 0:
+               break;
+       case 33:
+       case 50:
+               if(vcc == vpp)
+                       reg |= BCSR1_PCCVPP1;
+               else
+                       return 1;
+               break;
+       case 120:
+               if ((vcc == 33) || (vcc == 50))
+                       reg |= BCSR1_PCCVPP0;
+               else
+                       return 1;
+       default:
+               return 1;
+       }
+
+       /* first, turn off all power */
+       clrbits32(bcsr_io, 0x00610000);
+
+       /* enable new powersettings */
+       setbits32(bcsr_io, reg);
+
+       iounmap(bcsr_io);
+       return 0;
+}
+#endif
+
 void __init mpc885ads_board_setup(void)
 {
        cpm8xx_t *cp;
@@ -115,6 +180,12 @@ void __init mpc885ads_board_setup(void)
        immr_unmap(io_port);
 
 #endif
+
+#ifdef CONFIG_PCMCIA_M8XX
+       /*Set up board specific hook-ups*/
+       m8xx_pcmcia_ops.hw_ctrl = pcmcia_hw_setup;
+       m8xx_pcmcia_ops.voltage_set = pcmcia_set_voltage;
+#endif
 }
 
 
index 361acfa2894c77839efe1470208457ee512f54b9..33545d352e9234af9d2d08e0820450bb31aef5be 100644 (file)
@@ -2,7 +2,7 @@ menu "Platform support"
 
 choice
        prompt "Machine type"
-       depends on PPC64 || CLASSIC32
+       depends on PPC64 || 6xx
        default PPC_MULTIPLATFORM
 
 config PPC_MULTIPLATFORM
@@ -16,15 +16,30 @@ config EMBEDDED6xx
        bool "Embedded 6xx/7xx/7xxx-based board"
        depends on PPC32 && (BROKEN||BROKEN_ON_SMP)
 
-config APUS
-       bool "Amiga-APUS"
-       depends on PPC32 && BROKEN
+config PPC_82xx
+       bool "Freescale 82xx"
+       depends on 6xx
+
+config PPC_83xx
+       bool "Freescale 83xx"
+       depends on 6xx
+       select FSL_SOC
+       select 83xx
+       select WANT_DEVICE_TREE
+
+config PPC_86xx
+       bool "Freescale 86xx"
+       depends on 6xx
+       select FSL_SOC
+       select ALTIVEC
        help
-         Select APUS if configuring for a PowerUP Amiga.
-         More information is available at:
-         <http://linux-apus.sourceforge.net/>.
+         The Freescale E600 SoCs have 74xx cores.
 endchoice
 
+config CLASSIC32
+       def_bool y
+       depends on 6xx && PPC_MULTIPLATFORM
+
 source "arch/powerpc/platforms/pseries/Kconfig"
 source "arch/powerpc/platforms/iseries/Kconfig"
 source "arch/powerpc/platforms/chrp/Kconfig"
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
new file mode 100644 (file)
index 0000000..b8b5fde
--- /dev/null
@@ -0,0 +1,221 @@
+config PPC64
+       bool "64-bit kernel"
+       default n
+       help
+         This option selects whether a 32-bit or a 64-bit kernel
+         will be built.
+
+menu "Processor support"
+choice
+       prompt "Processor Type"
+       depends on PPC32
+       default 6xx
+       help
+         There are five families of 32 bit PowerPC chips supported.
+         The most common ones are the desktop and server CPUs (601, 603,
+         604, 740, 750, 74xx) CPUs from Freescale and IBM, with their
+         embedded 52xx/82xx/83xx/86xx counterparts.
+         The other embeeded parts, namely 4xx, 8xx, e200 (55xx) and e500
+         (85xx) each form a family of their own that is not compatible
+         with the others.
+
+         If unsure, select 52xx/6xx/7xx/74xx/82xx/83xx/86xx.
+
+config 6xx
+       bool "52xx/6xx/7xx/74xx/82xx/83xx/86xx"
+       select PPC_FPU
+
+config PPC_85xx
+       bool "Freescale 85xx"
+       select E500
+       select FSL_SOC
+       select 85xx
+       select WANT_DEVICE_TREE
+
+config PPC_8xx
+       bool "Freescale 8xx"
+       select FSL_SOC
+       select 8xx
+
+config 40x
+       bool "AMCC 40x"
+       select PPC_DCR_NATIVE
+
+config 44x
+       bool "AMCC 44x"
+       select PPC_DCR_NATIVE
+       select WANT_DEVICE_TREE
+
+config E200
+       bool "Freescale e200"
+
+endchoice
+
+config POWER4_ONLY
+       bool "Optimize for POWER4"
+       depends on PPC64
+       default n
+       ---help---
+         Cause the compiler to optimize for POWER4/POWER5/PPC970 processors.
+         The resulting binary will not work on POWER3 or RS64 processors
+         when compiled with binutils 2.15 or later.
+
+config POWER3
+       bool
+       depends on PPC64
+       default y if !POWER4_ONLY
+
+config POWER4
+       depends on PPC64
+       def_bool y
+
+config 6xx
+       bool
+
+# this is temp to handle compat with arch=ppc
+config 8xx
+       bool
+
+# this is temp to handle compat with arch=ppc
+config 83xx
+       bool
+
+# this is temp to handle compat with arch=ppc
+config 85xx
+       bool
+
+config E500
+       bool
+
+config PPC_FPU
+       bool
+       default y if PPC64
+
+config 4xx
+       bool
+       depends on 40x || 44x
+       default y
+
+config BOOKE
+       bool
+       depends on E200 || E500 || 44x
+       default y
+
+config FSL_BOOKE
+       bool
+       depends on E200 || E500
+       default y
+
+config PTE_64BIT
+       bool
+       depends on 44x || E500
+       default y if 44x
+       default y if E500 && PHYS_64BIT
+
+config PHYS_64BIT
+       bool 'Large physical address support' if E500
+       depends on 44x || E500
+       select RESOURCES_64BIT
+       default y if 44x
+       ---help---
+         This option enables kernel support for larger than 32-bit physical
+         addresses.  This features is not be available on all e500 cores.
+
+         If in doubt, say N here.
+
+config ALTIVEC
+       bool "AltiVec Support"
+       depends on CLASSIC32 || POWER4
+       ---help---
+         This option enables kernel support for the Altivec extensions to the
+         PowerPC processor. The kernel currently supports saving and restoring
+         altivec registers, and turning on the 'altivec enable' bit so user
+         processes can execute altivec instructions.
+
+         This option is only usefully if you have a processor that supports
+         altivec (G4, otherwise known as 74xx series), but does not have
+         any affect on a non-altivec cpu (it does, however add code to the
+         kernel).
+
+         If in doubt, say Y here.
+
+config SPE
+       bool "SPE Support"
+       depends on E200 || E500
+       default y
+       ---help---
+         This option enables kernel support for the Signal Processing
+         Extensions (SPE) to the PowerPC processor. The kernel currently
+         supports saving and restoring SPE registers, and turning on the
+         'spe enable' bit so user processes can execute SPE instructions.
+
+         This option is only useful if you have a processor that supports
+         SPE (e500, otherwise known as 85xx series), but does not have any
+         effect on a non-spe cpu (it does, however add code to the kernel).
+
+         If in doubt, say Y here.
+
+config PPC_STD_MMU
+       bool
+       depends on 6xx || POWER3 || POWER4 || PPC64
+       default y
+
+config PPC_STD_MMU_32
+       def_bool y
+       depends on PPC_STD_MMU && PPC32
+
+config PPC_MM_SLICES
+       bool
+       default y if HUGETLB_PAGE
+       default n
+
+config VIRT_CPU_ACCOUNTING
+       bool "Deterministic task and CPU time accounting"
+       depends on PPC64
+       default y
+       help
+         Select this option to enable more accurate task and CPU time
+         accounting.  This is done by reading a CPU counter on each
+         kernel entry and exit and on transitions within the kernel
+         between system, softirq and hardirq state, so there is a
+         small performance impact.  This also enables accounting of
+         stolen time on logically-partitioned systems running on
+         IBM POWER5-based machines.
+
+         If in doubt, say Y here.
+
+config SMP
+       depends on PPC_STD_MMU
+       bool "Symmetric multi-processing support"
+       ---help---
+         This enables support for systems with more than one CPU. If you have
+         a system with only one CPU, say N. If you have a system with more
+         than one CPU, say Y.  Note that the kernel does not currently
+         support SMP machines with 603/603e/603ev or PPC750 ("G3") processors
+         since they have inadequate hardware support for multiprocessor
+         operation.
+
+         If you say N here, the kernel will run on single and multiprocessor
+         machines, but will use only one CPU of a multiprocessor machine. If
+         you say Y here, the kernel will run on single-processor machines.
+         On a single-processor machine, the kernel will run faster if you say
+         N here.
+
+         If you don't know what to do here, say N.
+
+config NR_CPUS
+       int "Maximum number of CPUs (2-128)"
+       range 2 128
+       depends on SMP
+       default "32" if PPC64
+       default "4"
+
+config NOT_COHERENT_CACHE
+       bool
+       depends on 4xx || 8xx || E200
+       default y
+
+config CONFIG_CHECK_CACHE_COHERENCY
+       bool
+
+endmenu
diff --git a/arch/powerpc/platforms/apus/Kconfig b/arch/powerpc/platforms/apus/Kconfig
deleted file mode 100644 (file)
index 6bde3bf..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-
-config AMIGA
-       bool
-       depends on APUS
-       default y
-       help
-         This option enables support for the Amiga series of computers.
-
-config ZORRO
-       bool
-       depends on APUS
-       default y
-       help
-         This enables support for the Zorro bus in the Amiga. If you have
-         expansion cards in your Amiga that conform to the Amiga
-         AutoConfig(tm) specification, say Y, otherwise N. Note that even
-         expansion cards that do not fit in the Zorro slots but fit in e.g.
-         the CPU slot may fall in this category, so you have to say Y to let
-         Linux use these.
-
-config ABSTRACT_CONSOLE
-       bool
-       depends on APUS
-       default y
-
-config APUS_FAST_EXCEPT
-       bool
-       depends on APUS
-       default y
-
-config AMIGA_PCMCIA
-       bool "Amiga 1200/600 PCMCIA support"
-       depends on APUS && EXPERIMENTAL
-       help
-         Include support in the kernel for pcmcia on Amiga 1200 and Amiga
-         600. If you intend to use pcmcia cards say Y; otherwise say N.
-
-config AMIGA_BUILTIN_SERIAL
-       tristate "Amiga builtin serial support"
-       depends on APUS
-       help
-         If you want to use your Amiga's built-in serial port in Linux,
-         answer Y.
-
-         To compile this driver as a module, choose M here.
-
-config GVPIOEXT
-       tristate "GVP IO-Extender support"
-       depends on APUS
-       help
-         If you want to use a GVP IO-Extender serial card in Linux, say Y.
-         Otherwise, say N.
-
-config GVPIOEXT_LP
-       tristate "GVP IO-Extender parallel printer support"
-       depends on GVPIOEXT
-       help
-         Say Y to enable driving a printer from the parallel port on your
-         GVP IO-Extender card, N otherwise.
-
-config GVPIOEXT_PLIP
-       tristate "GVP IO-Extender PLIP support"
-       depends on GVPIOEXT
-       help
-         Say Y to enable doing IP over the parallel port on your GVP
-         IO-Extender card, N otherwise.
-
-config MULTIFACE_III_TTY
-       tristate "Multiface Card III serial support"
-       depends on APUS
-       help
-         If you want to use a Multiface III card's serial port in Linux,
-         answer Y.
-
-         To compile this driver as a module, choose M here.
-
-config A2232
-       tristate "Commodore A2232 serial support (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && APUS
-       ---help---
-         This option supports the 2232 7-port serial card shipped with the
-         Amiga 2000 and other Zorro-bus machines, dating from 1989.  At
-         a max of 19,200 bps, the ports are served by a 6551 ACIA UART chip
-         each, plus a 8520 CIA, and a master 6502 CPU and buffer as well. The
-         ports were connected with 8 pin DIN connectors on the card bracket,
-         for which 8 pin to DB25 adapters were supplied. The card also had
-         jumpers internally to toggle various pinning configurations.
-
-         This driver can be built as a module; but then "generic_serial"
-         will also be built as a module. This has to be loaded before
-         "ser_a2232". If you want to do this, answer M here.
-
-config WHIPPET_SERIAL
-       tristate "Hisoft Whippet PCMCIA serial support"
-       depends on AMIGA_PCMCIA
-       help
-         HiSoft has a web page at <http://www.hisoft.co.uk/>, but there
-         is no listing for the Whippet in their Amiga section.
-
-config APNE
-       tristate "PCMCIA NE2000 support"
-       depends on AMIGA_PCMCIA
-       help
-         If you have a PCMCIA NE2000 compatible adapter, say Y.  Otherwise,
-         say N.
-
-         To compile this driver as a module, choose M here: the
-         module will be called apne.
-
-config SERIAL_CONSOLE
-       bool "Support for serial port console"
-       depends on APUS && (AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y)
-
-config HEARTBEAT
-       bool "Use power LED as a heartbeat"
-       depends on APUS
-       help
-         Use the power-on LED on your machine as a load meter.  The exact
-         behavior is platform-dependent, but normally the flash frequency is
-         a hyperbolic function of the 5-minute load average.
-
-config PROC_HARDWARE
-       bool "/proc/hardware support"
-       depends on APUS
-
-source "drivers/zorro/Kconfig"
-
-config PCI_PERMEDIA
-       bool "PCI for Permedia2"
-       depends on !4xx && !8xx && APUS
index 7fb92f23f380a60c66a01eb7a5314ac6bbe79a93..9d7c2ef940a818fff1406e7b6523174499451da9 100644 (file)
@@ -102,7 +102,7 @@ static void spider_io_flush(const volatile void __iomem *addr)
                vaddr = (unsigned long)PCI_FIX_ADDR(addr);
 
                /* Check if it's in allowed range for  PIO */
-               if (vaddr < PHBS_IO_BASE || vaddr >= IMALLOC_BASE)
+               if (vaddr < PHB_IO_BASE || vaddr > PHB_IO_END)
                        return;
 
                /* Try to find a PTE. If not, clear the paddr, we'll do
index a7f5a7653c62e19149fd9d8865d6e0bc2c3aa890..e4d0c9f42abdba0b0034ed8ad87c591fff7f6b7a 100644 (file)
@@ -183,7 +183,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
                spu->slb_replace = 0;
 
        spu_restart_dma(spu);
-
+       spu->stats.slb_flt++;
        return 0;
 }
 
@@ -332,6 +332,7 @@ spu_irq_class_2(int irq, void *data)
        if (stat & 0x10) /* SPU mailbox threshold */
                spu->wbox_callback(spu);
 
+       spu->stats.class2_intr++;
        return stat ? IRQ_HANDLED : IRQ_NONE;
 }
 
@@ -462,8 +463,18 @@ void spu_free(struct spu *spu)
 }
 EXPORT_SYMBOL_GPL(spu_free);
 
+static int spu_shutdown(struct sys_device *sysdev)
+{
+       struct spu *spu = container_of(sysdev, struct spu, sysdev);
+
+       spu_free_irqs(spu);
+       spu_destroy_spu(spu);
+       return 0;
+}
+
 struct sysdev_class spu_sysdev_class = {
-       set_kset_name("spu")
+       set_kset_name("spu"),
+       .shutdown = spu_shutdown,
 };
 
 int spu_add_sysdev_attr(struct sysdev_attribute *attr)
@@ -574,6 +585,9 @@ static int __init create_spu(void *data)
        spin_unlock_irqrestore(&spu_list_lock, flags);
        mutex_unlock(&spu_mutex);
 
+       spu->stats.utilization_state = SPU_UTIL_IDLE;
+       spu->stats.tstamp = jiffies;
+
        goto out;
 
 out_free_irqs:
@@ -586,6 +600,45 @@ out:
        return ret;
 }
 
+static const char *spu_state_names[] = {
+       "user", "system", "iowait", "idle"
+};
+
+static unsigned long long spu_acct_time(struct spu *spu,
+               enum spu_utilization_state state)
+{
+       unsigned long long time = spu->stats.times[state];
+
+       if (spu->stats.utilization_state == state)
+               time += jiffies - spu->stats.tstamp;
+
+       return jiffies_to_msecs(time);
+}
+
+
+static ssize_t spu_stat_show(struct sys_device *sysdev, char *buf)
+{
+       struct spu *spu = container_of(sysdev, struct spu, sysdev);
+
+       return sprintf(buf, "%s %llu %llu %llu %llu "
+                     "%llu %llu %llu %llu %llu %llu %llu %llu\n",
+               spu_state_names[spu->stats.utilization_state],
+               spu_acct_time(spu, SPU_UTIL_USER),
+               spu_acct_time(spu, SPU_UTIL_SYSTEM),
+               spu_acct_time(spu, SPU_UTIL_IOWAIT),
+               spu_acct_time(spu, SPU_UTIL_IDLE),
+               spu->stats.vol_ctx_switch,
+               spu->stats.invol_ctx_switch,
+               spu->stats.slb_flt,
+               spu->stats.hash_flt,
+               spu->stats.min_flt,
+               spu->stats.maj_flt,
+               spu->stats.class2_intr,
+               spu->stats.libassist);
+}
+
+static SYSDEV_ATTR(stat, 0644, spu_stat_show, NULL);
+
 static int __init init_spu_base(void)
 {
        int i, ret = 0;
@@ -611,6 +664,8 @@ static int __init init_spu_base(void)
 
        xmon_register_spus(&spu_full_list);
 
+       spu_add_sysdev_attr(&attr_stat);
+
        return 0;
 
  out_unregister_sysdev_class:
index d32db9ffc6ebc56f31a68ce28c111880f634ea34..07a0e815abf5caafa54223604e79837bab1eed0c 100644 (file)
@@ -320,6 +320,12 @@ static int spu_backing_set_mfc_query(struct spu_context * ctx, u32 mask,
        /* FIXME: what are the side-effects of this? */
        prob->dma_querymask_RW = mask;
        prob->dma_querytype_RW = mode;
+       /* In the current implementation, the SPU context is always
+        * acquired in runnable state when new bits are added to the
+        * mask (tagwait), so it's sufficient just to mask
+        * dma_tagstatus_R with the 'mask' parameter here.
+        */
+       ctx->csa.prob.dma_tagstatus_R &= mask;
 out:
        spin_unlock(&ctx->csa.register_lock);
 
index 7c51cb54bca1ca8ba78c5074631247465dc784e7..6d7bd60f5380bf22a477e309b570145a5062df44 100644 (file)
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <asm/atomic.h>
 #include <asm/spu.h>
 #include <asm/spu_csa.h>
 #include "spufs.h"
 
+
+atomic_t nr_spu_contexts = ATOMIC_INIT(0);
+
 struct spu_context *alloc_spu_context(struct spu_gang *gang)
 {
        struct spu_context *ctx;
@@ -53,10 +57,12 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
        INIT_LIST_HEAD(&ctx->rq);
        if (gang)
                spu_gang_add_ctx(gang, ctx);
-       ctx->rt_priority = current->rt_priority;
-       ctx->policy = current->policy;
-       ctx->prio = current->prio;
-       INIT_DELAYED_WORK(&ctx->sched_work, spu_sched_tick);
+       ctx->cpus_allowed = current->cpus_allowed;
+       spu_set_timeslice(ctx);
+       ctx->stats.execution_state = SPUCTX_UTIL_USER;
+       ctx->stats.tstamp = jiffies;
+
+       atomic_inc(&nr_spu_contexts);
        goto out;
 out_free:
        kfree(ctx);
@@ -76,6 +82,7 @@ void destroy_spu_context(struct kref *kref)
        if (ctx->gang)
                spu_gang_remove_ctx(ctx->gang, ctx);
        BUG_ON(!list_empty(&ctx->rq));
+       atomic_dec(&nr_spu_contexts);
        kfree(ctx);
 }
 
index 0f75c07e29d88be7bec476d50aad2afdc0489d96..e064d0c0d80e6fac6240e86a4f94e0fd0785ca2b 100644 (file)
@@ -33,7 +33,8 @@
  * function. Currently, there are a few corner cases that we haven't had
  * to handle fortunately.
  */
-static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, unsigned long dsisr)
+static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
+               unsigned long dsisr, unsigned *flt)
 {
        struct vm_area_struct *vma;
        unsigned long is_write;
@@ -73,7 +74,8 @@ good_area:
                        goto bad_area;
        }
        ret = 0;
-       switch (handle_mm_fault(mm, vma, ea, is_write)) {
+       *flt = handle_mm_fault(mm, vma, ea, is_write);
+       switch (*flt) {
        case VM_FAULT_MINOR:
                current->min_flt++;
                break;
@@ -153,6 +155,7 @@ int spufs_handle_class1(struct spu_context *ctx)
 {
        u64 ea, dsisr, access;
        unsigned long flags;
+       unsigned flt = 0;
        int ret;
 
        /*
@@ -178,9 +181,17 @@ int spufs_handle_class1(struct spu_context *ctx)
        if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)))
                return 0;
 
+       spuctx_switch_state(ctx, SPUCTX_UTIL_IOWAIT);
+
        pr_debug("ctx %p: ea %016lx, dsisr %016lx state %d\n", ctx, ea,
                dsisr, ctx->state);
 
+       ctx->stats.hash_flt++;
+       if (ctx->state == SPU_STATE_RUNNABLE) {
+               ctx->spu->stats.hash_flt++;
+               spu_switch_state(ctx->spu, SPU_UTIL_IOWAIT);
+       }
+
        /* we must not hold the lock when entering spu_handle_mm_fault */
        spu_release(ctx);
 
@@ -192,7 +203,7 @@ int spufs_handle_class1(struct spu_context *ctx)
 
        /* hashing failed, so try the actual fault handler */
        if (ret)
-               ret = spu_handle_mm_fault(current->mm, ea, dsisr);
+               ret = spu_handle_mm_fault(current->mm, ea, dsisr, &flt);
 
        spu_acquire(ctx);
        /*
@@ -201,11 +212,23 @@ int spufs_handle_class1(struct spu_context *ctx)
         * In case of unhandled error report the problem to user space.
         */
        if (!ret) {
+               if (flt == VM_FAULT_MINOR)
+                       ctx->stats.min_flt++;
+               else
+                       ctx->stats.maj_flt++;
+               if (ctx->state == SPU_STATE_RUNNABLE) {
+                       if (flt == VM_FAULT_MINOR)
+                               ctx->spu->stats.min_flt++;
+                       else
+                               ctx->spu->stats.maj_flt++;
+               }
+
                if (ctx->spu)
                        ctx->ops->restart_dma(ctx);
        } else
                spufs_handle_dma_error(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE);
 
+       spuctx_switch_state(ctx, SPUCTX_UTIL_SYSTEM);
        return ret;
 }
 EXPORT_SYMBOL_GPL(spufs_handle_class1);
index b1e7e2f8a2e9256f4263a1ee72a589de6c592408..c2814ea96af2599c0ab32a080bbf06a0e50d948f 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/pagemap.h>
 #include <linux/poll.h>
 #include <linux/ptrace.h>
+#include <linux/seq_file.h>
 
 #include <asm/io.h>
 #include <asm/semaphore.h>
@@ -39,6 +40,7 @@
 
 #define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000)
 
+
 static int
 spufs_mem_open(struct inode *inode, struct file *file)
 {
@@ -216,12 +218,12 @@ unsigned long spufs_get_unmapped_area(struct file *file, unsigned long addr,
 #endif /* CONFIG_SPU_FS_64K_LS */
 
 static const struct file_operations spufs_mem_fops = {
-       .open                   = spufs_mem_open,
-       .release                = spufs_mem_release,
-       .read                   = spufs_mem_read,
-       .write                  = spufs_mem_write,
-       .llseek                 = generic_file_llseek,
-       .mmap                   = spufs_mem_mmap,
+       .open                   = spufs_mem_open,
+       .release                = spufs_mem_release,
+       .read                   = spufs_mem_read,
+       .write                  = spufs_mem_write,
+       .llseek                 = generic_file_llseek,
+       .mmap                   = spufs_mem_mmap,
 #ifdef CONFIG_SPU_FS_64K_LS
        .get_unmapped_area      = spufs_get_unmapped_area,
 #endif
@@ -1497,14 +1499,15 @@ static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer,
                if (status)
                        ret = status;
        }
-       spu_release(ctx);
 
        if (ret)
-               goto out;
+               goto out_unlock;
 
        ctx->tagwait |= 1 << cmd.tag;
        ret = size;
 
+out_unlock:
+       spu_release(ctx);
 out:
        return ret;
 }
@@ -1515,14 +1518,14 @@ static unsigned int spufs_mfc_poll(struct file *file,poll_table *wait)
        u32 free_elements, tagstatus;
        unsigned int mask;
 
+       poll_wait(file, &ctx->mfc_wq, wait);
+
        spu_acquire(ctx);
        ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2);
        free_elements = ctx->ops->get_mfc_free_elements(ctx);
        tagstatus = ctx->ops->read_mfc_tagstatus(ctx);
        spu_release(ctx);
 
-       poll_wait(file, &ctx->mfc_wq, wait);
-
        mask = 0;
        if (free_elements & 0xffff)
                mask |= POLLOUT | POLLWRNORM;
@@ -1797,6 +1800,29 @@ static int spufs_info_open(struct inode *inode, struct file *file)
        return 0;
 }
 
+static int spufs_caps_show(struct seq_file *s, void *private)
+{
+       struct spu_context *ctx = s->private;
+
+       if (!(ctx->flags & SPU_CREATE_NOSCHED))
+               seq_puts(s, "sched\n");
+       if (!(ctx->flags & SPU_CREATE_ISOLATE))
+               seq_puts(s, "step\n");
+       return 0;
+}
+
+static int spufs_caps_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, spufs_caps_show, SPUFS_I(inode)->i_ctx);
+}
+
+static const struct file_operations spufs_caps_fops = {
+       .open           = spufs_caps_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
 static ssize_t __spufs_mbox_info_read(struct spu_context *ctx,
                        char __user *buf, size_t len, loff_t *pos)
 {
@@ -2014,7 +2040,105 @@ static const struct file_operations spufs_proxydma_info_fops = {
        .read = spufs_proxydma_info_read,
 };
 
+static int spufs_show_tid(struct seq_file *s, void *private)
+{
+       struct spu_context *ctx = s->private;
+
+       seq_printf(s, "%d\n", ctx->tid);
+       return 0;
+}
+
+static int spufs_tid_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, spufs_show_tid, SPUFS_I(inode)->i_ctx);
+}
+
+static const struct file_operations spufs_tid_fops = {
+       .open           = spufs_tid_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static const char *ctx_state_names[] = {
+       "user", "system", "iowait", "loaded"
+};
+
+static unsigned long long spufs_acct_time(struct spu_context *ctx,
+               enum spuctx_execution_state state)
+{
+       unsigned long time = ctx->stats.times[state];
+
+       if (ctx->stats.execution_state == state)
+               time += jiffies - ctx->stats.tstamp;
+
+       return jiffies_to_msecs(time);
+}
+
+static unsigned long long spufs_slb_flts(struct spu_context *ctx)
+{
+       unsigned long long slb_flts = ctx->stats.slb_flt;
+
+       if (ctx->state == SPU_STATE_RUNNABLE) {
+               slb_flts += (ctx->spu->stats.slb_flt -
+                            ctx->stats.slb_flt_base);
+       }
+
+       return slb_flts;
+}
+
+static unsigned long long spufs_class2_intrs(struct spu_context *ctx)
+{
+       unsigned long long class2_intrs = ctx->stats.class2_intr;
+
+       if (ctx->state == SPU_STATE_RUNNABLE) {
+               class2_intrs += (ctx->spu->stats.class2_intr -
+                                ctx->stats.class2_intr_base);
+       }
+
+       return class2_intrs;
+}
+
+
+static int spufs_show_stat(struct seq_file *s, void *private)
+{
+       struct spu_context *ctx = s->private;
+
+       spu_acquire(ctx);
+       seq_printf(s, "%s %llu %llu %llu %llu "
+                     "%llu %llu %llu %llu %llu %llu %llu %llu\n",
+               ctx_state_names[ctx->stats.execution_state],
+               spufs_acct_time(ctx, SPUCTX_UTIL_USER),
+               spufs_acct_time(ctx, SPUCTX_UTIL_SYSTEM),
+               spufs_acct_time(ctx, SPUCTX_UTIL_IOWAIT),
+               spufs_acct_time(ctx, SPUCTX_UTIL_LOADED),
+               ctx->stats.vol_ctx_switch,
+               ctx->stats.invol_ctx_switch,
+               spufs_slb_flts(ctx),
+               ctx->stats.hash_flt,
+               ctx->stats.min_flt,
+               ctx->stats.maj_flt,
+               spufs_class2_intrs(ctx),
+               ctx->stats.libassist);
+       spu_release(ctx);
+       return 0;
+}
+
+static int spufs_stat_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, spufs_show_stat, SPUFS_I(inode)->i_ctx);
+}
+
+static const struct file_operations spufs_stat_fops = {
+       .open           = spufs_stat_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+
 struct tree_descr spufs_dir_contents[] = {
+       { "capabilities", &spufs_caps_fops, 0444, },
        { "mem",  &spufs_mem_fops,  0666, },
        { "regs", &spufs_regs_fops,  0666, },
        { "mbox", &spufs_mbox_fops, 0444, },
@@ -2046,10 +2170,13 @@ struct tree_descr spufs_dir_contents[] = {
        { "wbox_info", &spufs_wbox_info_fops, 0444, },
        { "dma_info", &spufs_dma_info_fops, 0444, },
        { "proxydma_info", &spufs_proxydma_info_fops, 0444, },
+       { "tid", &spufs_tid_fops, 0444, },
+       { "stat", &spufs_stat_fops, 0444, },
        {},
 };
 
 struct tree_descr spufs_dir_nosched_contents[] = {
+       { "capabilities", &spufs_caps_fops, 0444, },
        { "mem",  &spufs_mem_fops,  0666, },
        { "mbox", &spufs_mbox_fops, 0444, },
        { "ibox", &spufs_ibox_fops, 0444, },
@@ -2068,6 +2195,8 @@ struct tree_descr spufs_dir_nosched_contents[] = {
        { "psmap", &spufs_psmap_fops, 0666, },
        { "phys-id", &spufs_id_ops, 0666, },
        { "object-id", &spufs_object_id_ops, 0666, },
+       { "tid", &spufs_tid_fops, 0444, },
+       { "stat", &spufs_stat_fops, 0444, },
        {},
 };
 
index 9807206e02196d479b1ea171ecc754fae9c7a746..f37460e5bfd29b218775e7a8e9f1eb8da7274749 100644 (file)
@@ -232,10 +232,6 @@ static int spufs_dir_close(struct inode *inode, struct file *file)
        return dcache_dir_close(inode, file);
 }
 
-const struct inode_operations spufs_dir_inode_operations = {
-       .lookup = simple_lookup,
-};
-
 const struct file_operations spufs_context_fops = {
        .open           = dcache_dir_open,
        .release        = spufs_dir_close,
@@ -269,7 +265,7 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
                goto out_iput;
 
        ctx->flags = flags;
-       inode->i_op = &spufs_dir_inode_operations;
+       inode->i_op = &simple_dir_inode_operations;
        inode->i_fop = &simple_dir_operations;
        if (flags & SPU_CREATE_NOSCHED)
                ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents,
@@ -386,7 +382,7 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode)
        if (!gang)
                goto out_iput;
 
-       inode->i_op = &spufs_dir_inode_operations;
+       inode->i_op = &simple_dir_inode_operations;
        inode->i_fop = &simple_dir_operations;
 
        d_instantiate(dentry, inode);
@@ -593,7 +589,7 @@ spufs_create_root(struct super_block *sb, void *data)
        if (!inode)
                goto out;
 
-       inode->i_op = &spufs_dir_inode_operations;
+       inode->i_op = &simple_dir_inode_operations;
        inode->i_fop = &simple_dir_operations;
        SPUFS_I(inode)->i_ctx = NULL;
 
index 57626600b1a4b5c7cb3d46d17ef214e5b5807d1d..58ae13b7de84cd50677a740f87d2d25dc0cba7ee 100644 (file)
@@ -29,7 +29,8 @@ static inline int spu_stopped(struct spu_context *ctx, u32 * stat)
        spu = ctx->spu;
        pte_fault = spu->dsisr &
            (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED);
-       return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0;
+       return (!(*stat & SPU_STATUS_RUNNING) || pte_fault || spu->class_0_pending) ?
+               1 : 0;
 }
 
 static int spu_setup_isolated(struct spu_context *ctx)
@@ -142,8 +143,11 @@ static int spu_run_init(struct spu_context *ctx, u32 * npc)
                        runcntl = SPU_RUNCNTL_RUNNABLE;
                ctx->ops->runcntl_write(ctx, runcntl);
        } else {
-               spu_start_tick(ctx);
+               unsigned long mode = SPU_PRIVCNTL_MODE_NORMAL;
                ctx->ops->npc_write(ctx, *npc);
+               if (test_thread_flag(TIF_SINGLESTEP))
+                       mode = SPU_PRIVCNTL_MODE_SINGLE_STEP;
+               out_be64(&ctx->spu->priv2->spu_privcntl_RW, mode);
                ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
        }
 
@@ -155,7 +159,6 @@ static int spu_run_fini(struct spu_context *ctx, u32 * npc,
 {
        int ret = 0;
 
-       spu_stop_tick(ctx);
        *status = ctx->ops->status_read(ctx);
        *npc = ctx->ops->npc_read(ctx);
        spu_release(ctx);
@@ -298,9 +301,22 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
        ctx->ops->master_start(ctx);
        ctx->event_return = 0;
 
-       ret = spu_acquire_runnable(ctx, 0);
-       if (ret)
-               return ret;
+       spu_acquire(ctx);
+       if (ctx->state == SPU_STATE_SAVED) {
+               __spu_update_sched_info(ctx);
+
+               ret = spu_activate(ctx, 0);
+               if (ret) {
+                       spu_release(ctx);
+                       goto out;
+               }
+       } else {
+               /*
+                * We have to update the scheduling priority under active_mutex
+                * to protect against find_victim().
+                */
+               spu_update_sched_info(ctx);
+       }
 
        ret = spu_run_init(ctx, npc);
        if (ret) {
@@ -325,16 +341,20 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
 
                if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
                        ret = spu_reacquire_runnable(ctx, npc, &status);
-                       if (ret) {
-                               spu_stop_tick(ctx);
+                       if (ret)
                                goto out2;
-                       }
                        continue;
                }
                ret = spu_process_events(ctx);
 
        } while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP |
-                                     SPU_STATUS_STOPPED_BY_HALT)));
+                                     SPU_STATUS_STOPPED_BY_HALT |
+                                      SPU_STATUS_SINGLE_STEP)));
+
+       if ((status & SPU_STATUS_STOPPED_BY_STOP) &&
+           (((status >> SPU_STOP_STATUS_SHIFT) & 0x3f00) == 0x2100) &&
+           (ctx->state == SPU_STATE_RUNNABLE))
+               ctx->stats.libassist++;
 
        ctx->ops->master_stop(ctx);
        ret = spu_run_fini(ctx, npc, &status);
@@ -344,10 +364,15 @@ out2:
        if ((ret == 0) ||
            ((ret == -ERESTARTSYS) &&
             ((status & SPU_STATUS_STOPPED_BY_HALT) ||
+             (status & SPU_STATUS_SINGLE_STEP) ||
              ((status & SPU_STATUS_STOPPED_BY_STOP) &&
               (status >> SPU_STOP_STATUS_SHIFT != 0x2104)))))
                ret = status;
 
+       /* Note: we don't need to force_sig SIGTRAP on single-step
+        * since we have TIF_SINGLESTEP set, thus the kernel will do
+        * it upon return from the syscall anyawy
+        */
        if ((status & SPU_STATUS_STOPPED_BY_STOP)
            && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) {
                force_sig(SIGTRAP, current);
index 3b831e07f1ed740eabf0cd95fcafb985f105a8f2..e5b4dd1db286e8c834e9d64ca12b6237fc932d6f 100644 (file)
 #include <linux/numa.h>
 #include <linux/mutex.h>
 #include <linux/notifier.h>
+#include <linux/kthread.h>
+#include <linux/pid_namespace.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include <asm/io.h>
 #include <asm/mmu_context.h>
 #include <asm/spu_priv1.h>
 #include "spufs.h"
 
-#define SPU_TIMESLICE  (HZ)
-
 struct spu_prio_array {
        DECLARE_BITMAP(bitmap, MAX_PRIO);
        struct list_head runq[MAX_PRIO];
        spinlock_t runq_lock;
        struct list_head active_list[MAX_NUMNODES];
        struct mutex active_mutex[MAX_NUMNODES];
+       int nr_active[MAX_NUMNODES];
+       int nr_waiting;
 };
 
+static unsigned long spu_avenrun[3];
 static struct spu_prio_array *spu_prio;
-static struct workqueue_struct *spu_sched_wq;
+static struct task_struct *spusched_task;
+static struct timer_list spusched_timer;
+
+/*
+ * Priority of a normal, non-rt, non-niced'd process (aka nice level 0).
+ */
+#define NORMAL_PRIO            120
+
+/*
+ * Frequency of the spu scheduler tick.  By default we do one SPU scheduler
+ * tick for every 10 CPU scheduler ticks.
+ */
+#define SPUSCHED_TICK          (10)
 
-static inline int node_allowed(int node)
+/*
+ * These are the 'tuning knobs' of the scheduler:
+ *
+ * Minimum timeslice is 5 msecs (or 1 spu scheduler tick, whichever is
+ * larger), default timeslice is 100 msecs, maximum timeslice is 800 msecs.
+ */
+#define MIN_SPU_TIMESLICE      max(5 * HZ / (1000 * SPUSCHED_TICK), 1)
+#define DEF_SPU_TIMESLICE      (100 * HZ / (1000 * SPUSCHED_TICK))
+
+#define MAX_USER_PRIO          (MAX_PRIO - MAX_RT_PRIO)
+#define SCALE_PRIO(x, prio) \
+       max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_SPU_TIMESLICE)
+
+/*
+ * scale user-nice values [ -20 ... 0 ... 19 ] to time slice values:
+ * [800ms ... 100ms ... 5ms]
+ *
+ * The higher a thread's priority, the bigger timeslices
+ * it gets during one round of execution. But even the lowest
+ * priority thread gets MIN_TIMESLICE worth of execution time.
+ */
+void spu_set_timeslice(struct spu_context *ctx)
 {
-       cpumask_t mask;
+       if (ctx->prio < NORMAL_PRIO)
+               ctx->time_slice = SCALE_PRIO(DEF_SPU_TIMESLICE * 4, ctx->prio);
+       else
+               ctx->time_slice = SCALE_PRIO(DEF_SPU_TIMESLICE, ctx->prio);
+}
 
-       if (!nr_cpus_node(node))
-               return 0;
-       mask = node_to_cpumask(node);
-       if (!cpus_intersects(mask, current->cpus_allowed))
-               return 0;
-       return 1;
+/*
+ * Update scheduling information from the owning thread.
+ */
+void __spu_update_sched_info(struct spu_context *ctx)
+{
+       /*
+        * 32-Bit assignment are atomic on powerpc, and we don't care about
+        * memory ordering here because retriving the controlling thread is
+        * per defintion racy.
+        */
+       ctx->tid = current->pid;
+
+       /*
+        * We do our own priority calculations, so we normally want
+        * ->static_prio to start with. Unfortunately thies field
+        * contains junk for threads with a realtime scheduling
+        * policy so we have to look at ->prio in this case.
+        */
+       if (rt_prio(current->prio))
+               ctx->prio = current->prio;
+       else
+               ctx->prio = current->static_prio;
+       ctx->policy = current->policy;
+
+       /*
+        * A lot of places that don't hold active_mutex poke into
+        * cpus_allowed, including grab_runnable_context which
+        * already holds the runq_lock.  So abuse runq_lock
+        * to protect this field aswell.
+        */
+       spin_lock(&spu_prio->runq_lock);
+       ctx->cpus_allowed = current->cpus_allowed;
+       spin_unlock(&spu_prio->runq_lock);
 }
 
-void spu_start_tick(struct spu_context *ctx)
+void spu_update_sched_info(struct spu_context *ctx)
 {
-       if (ctx->policy == SCHED_RR) {
-               /*
-                * Make sure the exiting bit is cleared.
-                */
-               clear_bit(SPU_SCHED_EXITING, &ctx->sched_flags);
-               mb();
-               queue_delayed_work(spu_sched_wq, &ctx->sched_work, SPU_TIMESLICE);
-       }
+       int node = ctx->spu->node;
+
+       mutex_lock(&spu_prio->active_mutex[node]);
+       __spu_update_sched_info(ctx);
+       mutex_unlock(&spu_prio->active_mutex[node]);
 }
 
-void spu_stop_tick(struct spu_context *ctx)
+static int __node_allowed(struct spu_context *ctx, int node)
 {
-       if (ctx->policy == SCHED_RR) {
-               /*
-                * While the work can be rearming normally setting this flag
-                * makes sure it does not rearm itself anymore.
-                */
-               set_bit(SPU_SCHED_EXITING, &ctx->sched_flags);
-               mb();
-               cancel_delayed_work(&ctx->sched_work);
+       if (nr_cpus_node(node)) {
+               cpumask_t mask = node_to_cpumask(node);
+
+               if (cpus_intersects(mask, ctx->cpus_allowed))
+                       return 1;
        }
+
+       return 0;
+}
+
+static int node_allowed(struct spu_context *ctx, int node)
+{
+       int rval;
+
+       spin_lock(&spu_prio->runq_lock);
+       rval = __node_allowed(ctx, node);
+       spin_unlock(&spu_prio->runq_lock);
+
+       return rval;
 }
 
 /**
@@ -99,9 +175,18 @@ void spu_stop_tick(struct spu_context *ctx)
  */
 static void spu_add_to_active_list(struct spu *spu)
 {
-       mutex_lock(&spu_prio->active_mutex[spu->node]);
-       list_add_tail(&spu->list, &spu_prio->active_list[spu->node]);
-       mutex_unlock(&spu_prio->active_mutex[spu->node]);
+       int node = spu->node;
+
+       mutex_lock(&spu_prio->active_mutex[node]);
+       spu_prio->nr_active[node]++;
+       list_add_tail(&spu->list, &spu_prio->active_list[node]);
+       mutex_unlock(&spu_prio->active_mutex[node]);
+}
+
+static void __spu_remove_from_active_list(struct spu *spu)
+{
+       list_del_init(&spu->list);
+       spu_prio->nr_active[spu->node]--;
 }
 
 /**
@@ -113,7 +198,7 @@ static void spu_remove_from_active_list(struct spu *spu)
        int node = spu->node;
 
        mutex_lock(&spu_prio->active_mutex[node]);
-       list_del_init(&spu->list);
+       __spu_remove_from_active_list(spu);
        mutex_unlock(&spu_prio->active_mutex[node]);
 }
 
@@ -144,6 +229,10 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx)
 {
        pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid,
                 spu->number, spu->node);
+
+       ctx->stats.slb_flt_base = spu->stats.slb_flt;
+       ctx->stats.class2_intr_base = spu->stats.class2_intr;
+
        spu->ctx = ctx;
        spu->flags = 0;
        ctx->spu = spu;
@@ -161,8 +250,8 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx)
        spu->timestamp = jiffies;
        spu_cpu_affinity_set(spu, raw_smp_processor_id());
        spu_switch_notify(spu, ctx);
-       spu_add_to_active_list(spu);
        ctx->state = SPU_STATE_RUNNABLE;
+       spu_switch_state(spu, SPU_UTIL_SYSTEM);
 }
 
 /**
@@ -175,7 +264,8 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
        pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__,
                 spu->pid, spu->number, spu->node);
 
-       spu_remove_from_active_list(spu);
+       spu_switch_state(spu, SPU_UTIL_IDLE);
+
        spu_switch_notify(spu, NULL);
        spu_unmap_mappings(ctx);
        spu_save(&ctx->csa, spu);
@@ -192,6 +282,11 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
        ctx->spu = NULL;
        spu->flags = 0;
        spu->ctx = NULL;
+
+       ctx->stats.slb_flt +=
+               (spu->stats.slb_flt - ctx->stats.slb_flt_base);
+       ctx->stats.class2_intr +=
+               (spu->stats.class2_intr - ctx->stats.class2_intr_base);
 }
 
 /**
@@ -200,20 +295,39 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
  */
 static void __spu_add_to_rq(struct spu_context *ctx)
 {
-       int prio = ctx->prio;
-
-       list_add_tail(&ctx->rq, &spu_prio->runq[prio]);
-       set_bit(prio, spu_prio->bitmap);
+       /*
+        * Unfortunately this code path can be called from multiple threads
+        * on behalf of a single context due to the way the problem state
+        * mmap support works.
+        *
+        * Fortunately we need to wake up all these threads at the same time
+        * and can simply skip the runqueue addition for every but the first
+        * thread getting into this codepath.
+        *
+        * It's still quite hacky, and long-term we should proxy all other
+        * threads through the owner thread so that spu_run is in control
+        * of all the scheduling activity for a given context.
+        */
+       if (list_empty(&ctx->rq)) {
+               list_add_tail(&ctx->rq, &spu_prio->runq[ctx->prio]);
+               set_bit(ctx->prio, spu_prio->bitmap);
+               if (!spu_prio->nr_waiting++)
+                       __mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK);
+       }
 }
 
 static void __spu_del_from_rq(struct spu_context *ctx)
 {
        int prio = ctx->prio;
 
-       if (!list_empty(&ctx->rq))
+       if (!list_empty(&ctx->rq)) {
+               if (!--spu_prio->nr_waiting)
+                       del_timer(&spusched_timer);
                list_del_init(&ctx->rq);
-       if (list_empty(&spu_prio->runq[prio]))
-               clear_bit(prio, spu_prio->bitmap);
+
+               if (list_empty(&spu_prio->runq[prio]))
+                       clear_bit(prio, spu_prio->bitmap);
+       }
 }
 
 static void spu_prio_wait(struct spu_context *ctx)
@@ -244,7 +358,7 @@ static struct spu *spu_get_idle(struct spu_context *ctx)
 
        for (n = 0; n < MAX_NUMNODES; n++, node++) {
                node = (node < MAX_NUMNODES) ? node : 0;
-               if (!node_allowed(node))
+               if (!node_allowed(ctx, node))
                        continue;
                spu = spu_alloc_node(node);
                if (spu)
@@ -276,15 +390,15 @@ static struct spu *find_victim(struct spu_context *ctx)
        node = cpu_to_node(raw_smp_processor_id());
        for (n = 0; n < MAX_NUMNODES; n++, node++) {
                node = (node < MAX_NUMNODES) ? node : 0;
-               if (!node_allowed(node))
+               if (!node_allowed(ctx, node))
                        continue;
 
                mutex_lock(&spu_prio->active_mutex[node]);
                list_for_each_entry(spu, &spu_prio->active_list[node], list) {
                        struct spu_context *tmp = spu->ctx;
 
-                       if (tmp->rt_priority < ctx->rt_priority &&
-                           (!victim || tmp->rt_priority < victim->rt_priority))
+                       if (tmp->prio > ctx->prio &&
+                           (!victim || tmp->prio > victim->prio))
                                victim = spu->ctx;
                }
                mutex_unlock(&spu_prio->active_mutex[node]);
@@ -312,7 +426,10 @@ static struct spu *find_victim(struct spu_context *ctx)
                                victim = NULL;
                                goto restart;
                        }
+                       spu_remove_from_active_list(spu);
                        spu_unbind_context(spu, victim);
+                       victim->stats.invol_ctx_switch++;
+                       spu->stats.invol_ctx_switch++;
                        mutex_unlock(&victim->state_mutex);
                        /*
                         * We need to break out of the wait loop in spu_run
@@ -338,22 +455,30 @@ static struct spu *find_victim(struct spu_context *ctx)
  */
 int spu_activate(struct spu_context *ctx, unsigned long flags)
 {
-
-       if (ctx->spu)
-               return 0;
+       spuctx_switch_state(ctx, SPUCTX_UTIL_SYSTEM);
 
        do {
                struct spu *spu;
 
+               /*
+                * If there are multiple threads waiting for a single context
+                * only one actually binds the context while the others will
+                * only be able to acquire the state_mutex once the context
+                * already is in runnable state.
+                */
+               if (ctx->spu)
+                       return 0;
+
                spu = spu_get_idle(ctx);
                /*
                 * If this is a realtime thread we try to get it running by
                 * preempting a lower priority thread.
                 */
-               if (!spu && ctx->rt_priority)
+               if (!spu && rt_prio(ctx->prio))
                        spu = find_victim(ctx);
                if (spu) {
                        spu_bind_context(spu, ctx);
+                       spu_add_to_active_list(spu);
                        return 0;
                }
 
@@ -369,23 +494,28 @@ int spu_activate(struct spu_context *ctx, unsigned long flags)
  * Remove the highest priority context on the runqueue and return it
  * to the caller.  Returns %NULL if no runnable context was found.
  */
-static struct spu_context *grab_runnable_context(int prio)
+static struct spu_context *grab_runnable_context(int prio, int node)
 {
-       struct spu_context *ctx = NULL;
+       struct spu_context *ctx;
        int best;
 
        spin_lock(&spu_prio->runq_lock);
        best = sched_find_first_bit(spu_prio->bitmap);
-       if (best < prio) {
+       while (best < prio) {
                struct list_head *rq = &spu_prio->runq[best];
 
-               BUG_ON(list_empty(rq));
-
-               ctx = list_entry(rq->next, struct spu_context, rq);
-               __spu_del_from_rq(ctx);
+               list_for_each_entry(ctx, rq, rq) {
+                       /* XXX(hch): check for affinity here aswell */
+                       if (__node_allowed(ctx, node)) {
+                               __spu_del_from_rq(ctx);
+                               goto found;
+                       }
+               }
+               best++;
        }
+       ctx = NULL;
+ found:
        spin_unlock(&spu_prio->runq_lock);
-
        return ctx;
 }
 
@@ -395,9 +525,12 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio)
        struct spu_context *new = NULL;
 
        if (spu) {
-               new = grab_runnable_context(max_prio);
+               new = grab_runnable_context(max_prio, spu->node);
                if (new || force) {
+                       spu_remove_from_active_list(spu);
                        spu_unbind_context(spu, ctx);
+                       ctx->stats.vol_ctx_switch++;
+                       spu->stats.vol_ctx_switch++;
                        spu_free(spu);
                        if (new)
                                wake_up(&new->stop_wq);
@@ -417,7 +550,17 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio)
  */
 void spu_deactivate(struct spu_context *ctx)
 {
+       /*
+        * We must never reach this for a nosched context,
+        * but handle the case gracefull instead of panicing.
+        */
+       if (ctx->flags & SPU_CREATE_NOSCHED) {
+               WARN_ON(1);
+               return;
+       }
+
        __spu_deactivate(ctx, 1, MAX_PRIO);
+       spuctx_switch_state(ctx, SPUCTX_UTIL_USER);
 }
 
 /**
@@ -432,56 +575,178 @@ void spu_yield(struct spu_context *ctx)
 {
        if (!(ctx->flags & SPU_CREATE_NOSCHED)) {
                mutex_lock(&ctx->state_mutex);
-               __spu_deactivate(ctx, 0, MAX_PRIO);
+               if (__spu_deactivate(ctx, 0, MAX_PRIO))
+                       spuctx_switch_state(ctx, SPUCTX_UTIL_USER);
+               else {
+                       spuctx_switch_state(ctx, SPUCTX_UTIL_LOADED);
+                       spu_switch_state(ctx->spu, SPU_UTIL_USER);
+               }
                mutex_unlock(&ctx->state_mutex);
        }
 }
 
-void spu_sched_tick(struct work_struct *work)
+static void spusched_tick(struct spu_context *ctx)
 {
-       struct spu_context *ctx =
-               container_of(work, struct spu_context, sched_work.work);
-       int preempted;
+       if (ctx->flags & SPU_CREATE_NOSCHED)
+               return;
+       if (ctx->policy == SCHED_FIFO)
+               return;
+
+       if (--ctx->time_slice)
+               return;
 
        /*
-        * If this context is being stopped avoid rescheduling from the
-        * scheduler tick because we would block on the state_mutex.
-        * The caller will yield the spu later on anyway.
+        * Unfortunately active_mutex ranks outside of state_mutex, so
+        * we have to trylock here.  If we fail give the context another
+        * tick and try again.
         */
-       if (test_bit(SPU_SCHED_EXITING, &ctx->sched_flags))
-               return;
+       if (mutex_trylock(&ctx->state_mutex)) {
+               struct spu *spu = ctx->spu;
+               struct spu_context *new;
 
-       mutex_lock(&ctx->state_mutex);
-       preempted = __spu_deactivate(ctx, 0, ctx->prio + 1);
-       mutex_unlock(&ctx->state_mutex);
+               new = grab_runnable_context(ctx->prio + 1, spu->node);
+               if (new) {
 
-       if (preempted) {
-               /*
-                * We need to break out of the wait loop in spu_run manually
-                * to ensure this context gets put on the runqueue again
-                * ASAP.
-                */
-               wake_up(&ctx->stop_wq);
+                       __spu_remove_from_active_list(spu);
+                       spu_unbind_context(spu, ctx);
+                       ctx->stats.invol_ctx_switch++;
+                       spu->stats.invol_ctx_switch++;
+                       spu_free(spu);
+                       wake_up(&new->stop_wq);
+                       /*
+                        * We need to break out of the wait loop in
+                        * spu_run manually to ensure this context
+                        * gets put on the runqueue again ASAP.
+                        */
+                       wake_up(&ctx->stop_wq);
+               }
+               spu_set_timeslice(ctx);
+               mutex_unlock(&ctx->state_mutex);
        } else {
-               spu_start_tick(ctx);
+               ctx->time_slice++;
        }
 }
 
-int __init spu_sched_init(void)
+/**
+ * count_active_contexts - count nr of active tasks
+ *
+ * Return the number of tasks currently running or waiting to run.
+ *
+ * Note that we don't take runq_lock / active_mutex here.  Reading
+ * a single 32bit value is atomic on powerpc, and we don't care
+ * about memory ordering issues here.
+ */
+static unsigned long count_active_contexts(void)
 {
-       int i;
+       int nr_active = 0, node;
 
-       spu_sched_wq = create_singlethread_workqueue("spusched");
-       if (!spu_sched_wq)
-               return 1;
+       for (node = 0; node < MAX_NUMNODES; node++)
+               nr_active += spu_prio->nr_active[node];
+       nr_active += spu_prio->nr_waiting;
 
-       spu_prio = kzalloc(sizeof(struct spu_prio_array), GFP_KERNEL);
-       if (!spu_prio) {
-               printk(KERN_WARNING "%s: Unable to allocate priority queue.\n",
-                      __FUNCTION__);
-                      destroy_workqueue(spu_sched_wq);
-               return 1;
+       return nr_active;
+}
+
+/**
+ * spu_calc_load - given tick count, update the avenrun load estimates.
+ * @tick:      tick count
+ *
+ * No locking against reading these values from userspace, as for
+ * the CPU loadavg code.
+ */
+static void spu_calc_load(unsigned long ticks)
+{
+       unsigned long active_tasks; /* fixed-point */
+       static int count = LOAD_FREQ;
+
+       count -= ticks;
+
+       if (unlikely(count < 0)) {
+               active_tasks = count_active_contexts() * FIXED_1;
+               do {
+                       CALC_LOAD(spu_avenrun[0], EXP_1, active_tasks);
+                       CALC_LOAD(spu_avenrun[1], EXP_5, active_tasks);
+                       CALC_LOAD(spu_avenrun[2], EXP_15, active_tasks);
+                       count += LOAD_FREQ;
+               } while (count < 0);
        }
+}
+
+static void spusched_wake(unsigned long data)
+{
+       mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK);
+       wake_up_process(spusched_task);
+       spu_calc_load(SPUSCHED_TICK);
+}
+
+static int spusched_thread(void *unused)
+{
+       struct spu *spu, *next;
+       int node;
+
+       while (!kthread_should_stop()) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule();
+               for (node = 0; node < MAX_NUMNODES; node++) {
+                       mutex_lock(&spu_prio->active_mutex[node]);
+                       list_for_each_entry_safe(spu, next,
+                                                &spu_prio->active_list[node],
+                                                list)
+                               spusched_tick(spu->ctx);
+                       mutex_unlock(&spu_prio->active_mutex[node]);
+               }
+       }
+
+       return 0;
+}
+
+#define LOAD_INT(x) ((x) >> FSHIFT)
+#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
+
+static int show_spu_loadavg(struct seq_file *s, void *private)
+{
+       int a, b, c;
+
+       a = spu_avenrun[0] + (FIXED_1/200);
+       b = spu_avenrun[1] + (FIXED_1/200);
+       c = spu_avenrun[2] + (FIXED_1/200);
+
+       /*
+        * Note that last_pid doesn't really make much sense for the
+        * SPU loadavg (it even seems very odd on the CPU side..),
+        * but we include it here to have a 100% compatible interface.
+        */
+       seq_printf(s, "%d.%02d %d.%02d %d.%02d %ld/%d %d\n",
+               LOAD_INT(a), LOAD_FRAC(a),
+               LOAD_INT(b), LOAD_FRAC(b),
+               LOAD_INT(c), LOAD_FRAC(c),
+               count_active_contexts(),
+               atomic_read(&nr_spu_contexts),
+               current->nsproxy->pid_ns->last_pid);
+       return 0;
+}
+
+static int spu_loadavg_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, show_spu_loadavg, NULL);
+}
+
+static const struct file_operations spu_loadavg_fops = {
+       .open           = spu_loadavg_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+int __init spu_sched_init(void)
+{
+       struct proc_dir_entry *entry;
+       int err = -ENOMEM, i;
+
+       spu_prio = kzalloc(sizeof(struct spu_prio_array), GFP_KERNEL);
+       if (!spu_prio)
+               goto out;
+
        for (i = 0; i < MAX_PRIO; i++) {
                INIT_LIST_HEAD(&spu_prio->runq[i]);
                __clear_bit(i, spu_prio->bitmap);
@@ -492,7 +757,30 @@ int __init spu_sched_init(void)
                INIT_LIST_HEAD(&spu_prio->active_list[i]);
        }
        spin_lock_init(&spu_prio->runq_lock);
+
+       setup_timer(&spusched_timer, spusched_wake, 0);
+
+       spusched_task = kthread_run(spusched_thread, NULL, "spusched");
+       if (IS_ERR(spusched_task)) {
+               err = PTR_ERR(spusched_task);
+               goto out_free_spu_prio;
+       }
+
+       entry = create_proc_entry("spu_loadavg", 0, NULL);
+       if (!entry)
+               goto out_stop_kthread;
+       entry->proc_fops = &spu_loadavg_fops;
+
+       pr_debug("spusched: tick: %d, min ticks: %d, default ticks: %d\n",
+                       SPUSCHED_TICK, MIN_SPU_TIMESLICE, DEF_SPU_TIMESLICE);
        return 0;
+
+ out_stop_kthread:
+       kthread_stop(spusched_task);
+ out_free_spu_prio:
+       kfree(spu_prio);
+ out:
+       return err;
 }
 
 void __exit spu_sched_exit(void)
@@ -500,6 +788,11 @@ void __exit spu_sched_exit(void)
        struct spu *spu, *tmp;
        int node;
 
+       remove_proc_entry("spu_loadavg", NULL);
+
+       del_timer_sync(&spusched_timer);
+       kthread_stop(spusched_task);
+
        for (node = 0; node < MAX_NUMNODES; node++) {
                mutex_lock(&spu_prio->active_mutex[node]);
                list_for_each_entry_safe(spu, tmp, &spu_prio->active_list[node],
@@ -510,5 +803,4 @@ void __exit spu_sched_exit(void)
                mutex_unlock(&spu_prio->active_mutex[node]);
        }
        kfree(spu_prio);
-       destroy_workqueue(spu_sched_wq);
 }
index 0bf723dcd677fea39248c6729eef9e554a5582e1..4e19ed7a07568b67991e4e1fce53ca1e9ee65cec 100644 (file)
@@ -296,7 +296,7 @@ static inline void restore_complete(void)
  * This code deviates from the documented sequence in the
  * following aspects:
  *
- *     1. The EA for LSCSA is passed from PPE in the
+ *     1. The EA for LSCSA is passed from PPE in the
  *        signal notification channels.
  *     2. The register spill area is pulled by SPU
  *        into LS, rather than pushed by PPE.
index 196033b8a5799a95cc4266be3941c6b7e5168256..ae95cc1701e9f8236cdd5ede575742f2ff22435c 100644 (file)
@@ -44,7 +44,7 @@ static inline void save_event_mask(void)
         *    Read the SPU_RdEventMsk channel and save to the LSCSA.
         */
        offset = LSCSA_QW_OFFSET(event_mask);
-       regs_spill[offset].slot[0] = spu_readch(SPU_RdEventStatMask);
+       regs_spill[offset].slot[0] = spu_readch(SPU_RdEventMask);
 }
 
 static inline void save_tag_mask(void)
index 47617e8014a5acc402f1c0222dfb1d1c6c3bf972..08b3530288ac34d222ba165f72338d27ebc88d5d 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/fs.h>
+#include <linux/cpumask.h>
 
 #include <asm/spu.h>
 #include <asm/spu_csa.h>
@@ -39,9 +40,17 @@ enum {
 struct spu_context_ops;
 struct spu_gang;
 
-/* ctx->sched_flags */
-enum {
-       SPU_SCHED_EXITING = 0,
+/*
+ * This is the state for spu utilization reporting to userspace.
+ * Because this state is visible to userspace it must never change and needs
+ * to be kept strictly separate from any internal state kept by the kernel.
+ */
+enum spuctx_execution_state {
+       SPUCTX_UTIL_USER = 0,
+       SPUCTX_UTIL_SYSTEM,
+       SPUCTX_UTIL_IOWAIT,
+       SPUCTX_UTIL_LOADED,
+       SPUCTX_UTIL_MAX
 };
 
 struct spu_context {
@@ -81,13 +90,34 @@ struct spu_context {
        struct list_head gang_list;
        struct spu_gang *gang;
 
+       /* owner thread */
+       pid_t tid;
+
        /* scheduler fields */
-       struct list_head rq;
-       struct delayed_work sched_work;
+       struct list_head rq;
+       unsigned int time_slice;
        unsigned long sched_flags;
-       unsigned long rt_priority;
+       cpumask_t cpus_allowed;
        int policy;
        int prio;
+
+       /* statistics */
+       struct {
+               /* updates protected by ctx->state_mutex */
+               enum spuctx_execution_state execution_state;
+               unsigned long tstamp;           /* time of last ctx switch */
+               unsigned long times[SPUCTX_UTIL_MAX];
+               unsigned long long vol_ctx_switch;
+               unsigned long long invol_ctx_switch;
+               unsigned long long min_flt;
+               unsigned long long maj_flt;
+               unsigned long long hash_flt;
+               unsigned long long slb_flt;
+               unsigned long long slb_flt_base; /* # at last ctx switch */
+               unsigned long long class2_intr;
+               unsigned long long class2_intr_base; /* # at last ctx switch */
+               unsigned long long libassist;
+       } stats;
 };
 
 struct spu_gang {
@@ -177,6 +207,7 @@ void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx);
 int spufs_handle_class1(struct spu_context *ctx);
 
 /* context management */
+extern atomic_t nr_spu_contexts;
 static inline void spu_acquire(struct spu_context *ctx)
 {
        mutex_lock(&ctx->state_mutex);
@@ -200,9 +231,9 @@ void spu_acquire_saved(struct spu_context *ctx);
 int spu_activate(struct spu_context *ctx, unsigned long flags);
 void spu_deactivate(struct spu_context *ctx);
 void spu_yield(struct spu_context *ctx);
-void spu_start_tick(struct spu_context *ctx);
-void spu_stop_tick(struct spu_context *ctx);
-void spu_sched_tick(struct work_struct *work);
+void spu_set_timeslice(struct spu_context *ctx);
+void spu_update_sched_info(struct spu_context *ctx);
+void __spu_update_sched_info(struct spu_context *ctx);
 int __init spu_sched_init(void);
 void __exit spu_sched_exit(void);
 
@@ -210,7 +241,7 @@ extern char *isolated_loader;
 
 /*
  * spufs_wait
- *     Same as wait_event_interruptible(), except that here
+ *     Same as wait_event_interruptible(), except that here
  *     we need to call spu_release(ctx) before sleeping, and
  *     then spu_acquire(ctx) when awoken.
  */
@@ -256,4 +287,37 @@ struct spufs_coredump_reader {
 extern struct spufs_coredump_reader spufs_coredump_read[];
 extern int spufs_coredump_num_notes;
 
+/*
+ * This function is a little bit too large for an inline, but
+ * as fault.c is built into the kernel we can't move it out of
+ * line.
+ */
+static inline void spuctx_switch_state(struct spu_context *ctx,
+               enum spuctx_execution_state new_state)
+{
+       WARN_ON(!mutex_is_locked(&ctx->state_mutex));
+
+       if (ctx->stats.execution_state != new_state) {
+               unsigned long curtime = jiffies;
+
+               ctx->stats.times[ctx->stats.execution_state] +=
+                                curtime - ctx->stats.tstamp;
+               ctx->stats.tstamp = curtime;
+               ctx->stats.execution_state = new_state;
+       }
+}
+
+static inline void spu_switch_state(struct spu *spu,
+               enum spuctx_execution_state new_state)
+{
+       if (spu->stats.utilization_state != new_state) {
+               unsigned long curtime = jiffies;
+
+               spu->stats.times[spu->stats.utilization_state] +=
+                                curtime - spu->stats.tstamp;
+               spu->stats.tstamp = curtime;
+               spu->stats.utilization_state = new_state;
+       }
+}
+
 #endif
index 71a0b41adb8c8ed320ba2325716f491ec99b34e0..9c506ba08cdcb4691e32b4d40b7a5ec3a2090894 100644 (file)
@@ -70,7 +70,7 @@
   }
 #endif                         /* debug */
 
-#define POLL_WHILE_FALSE(_c)   POLL_WHILE_TRUE(!(_c))
+#define POLL_WHILE_FALSE(_c)   POLL_WHILE_TRUE(!(_c))
 
 static inline void acquire_spu_lock(struct spu *spu)
 {
@@ -387,6 +387,19 @@ static inline void save_ppu_querytype(struct spu_state *csa, struct spu *spu)
        csa->prob.dma_querytype_RW = in_be32(&prob->dma_querytype_RW);
 }
 
+static inline void save_ppu_tagstatus(struct spu_state *csa, struct spu *spu)
+{
+       struct spu_problem __iomem *prob = spu->problem;
+
+       /* Save the Prxy_TagStatus register in the CSA.
+        *
+        * It is unnecessary to restore dma_tagstatus_R, however,
+        * dma_tagstatus_R in the CSA is accessed via backing_ops, so
+        * we must save it.
+        */
+       csa->prob.dma_tagstatus_R = in_be32(&prob->dma_tagstatus_R);
+}
+
 static inline void save_mfc_csr_tsq(struct spu_state *csa, struct spu *spu)
 {
        struct spu_priv2 __iomem *priv2 = spu->priv2;
@@ -1812,6 +1825,7 @@ static void save_csa(struct spu_state *prev, struct spu *spu)
        save_mfc_queues(prev, spu);     /* Step 19. */
        save_ppu_querymask(prev, spu);  /* Step 20. */
        save_ppu_querytype(prev, spu);  /* Step 21. */
+       save_ppu_tagstatus(prev, spu);  /* NEW.     */
        save_mfc_csr_tsq(prev, spu);    /* Step 22. */
        save_mfc_csr_cmd(prev, spu);    /* Step 23. */
        save_mfc_csr_ato(prev, spu);    /* Step 24. */
@@ -1930,7 +1944,7 @@ static void harvest(struct spu_state *prev, struct spu *spu)
        reset_spu_privcntl(prev, spu);          /* Step 16. */
        reset_spu_lslr(prev, spu);              /* Step 17. */
        setup_mfc_sr1(prev, spu);               /* Step 18. */
-       spu_invalidate_slbs(spu);               /* Step 19. */
+       spu_invalidate_slbs(spu);               /* Step 19. */
        reset_ch_part1(prev, spu);              /* Step 20. */
        reset_ch_part2(prev, spu);              /* Step 21. */
        enable_interrupts(prev, spu);           /* Step 22. */
index d2c690531963597363aa8cc6af42a5eee2121b66..22b4b4e3b6f020e6e1625980f92dcd7c97cc7133 100644 (file)
@@ -8,4 +8,5 @@ config PPC_CHRP
        select PPC_MPC106
        select PPC_UDBG_16550
        select PPC_NATIVE
+       select PCI
        default y
index 902feb1ac4319de74bfe9cf75643efcd5871b7f9..4b3bfadc70fa408eb9f21a07ac63734924573ac0 100644 (file)
@@ -1,4 +1,3 @@
-obj-y                          += setup.o time.o pegasos_eth.o
-obj-$(CONFIG_PCI)              += pci.o
+obj-y                          += setup.o time.o pegasos_eth.o pci.o
 obj-$(CONFIG_SMP)              += smp.o
 obj-$(CONFIG_NVRAM)            += nvram.o
index d32fedc991d36d5a98452dcab5eccfbec09676c8..3690624e49d4c0696290bd3005ffd9700deb8008 100644 (file)
@@ -99,7 +99,7 @@ int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
        struct pci_controller *hose = bus->sysdata;
        unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
                | (((bus->number - hose->first_busno) & 0xff) << 16)
-               | (hose->index << 24);
+               | (hose->global_number << 24);
         int ret = -1;
        int rval;
 
@@ -114,7 +114,7 @@ int rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
        struct pci_controller *hose = bus->sysdata;
        unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
                | (((bus->number - hose->first_busno) & 0xff) << 16)
-               | (hose->index << 24);
+               | (hose->global_number << 24);
        int rval;
 
        rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL,
@@ -254,13 +254,12 @@ chrp_find_bridges(void)
                        printk(" at %llx", (unsigned long long)r.start);
                printk("\n");
 
-               hose = pcibios_alloc_controller();
+               hose = pcibios_alloc_controller(dev);
                if (!hose) {
                        printk("Can't allocate PCI controller structure for %s\n",
                                dev->full_name);
                        continue;
                }
-               hose->arch_data = dev;
                hose->first_busno = bus_range[0];
                hose->last_busno = bus_range[1];
 
index f2d26268ca6f24d977fb776983d37f1e2c4ccaae..bec772674e4066db350f22b77d77bf74c5b32134 100644 (file)
@@ -28,6 +28,7 @@ config PPC_HOLLY
        bool "PPC750GX/CL with TSI10x bridge (Hickory/Holly)"
        select TSI108_BRIDGE
        select PPC_UDBG_16550
+       select WANT_DEVICE_TREE
        help
          Select PPC_HOLLY if configuring for an IBM 750GX/CL Eval
          Board with TSI108/9 bridge (Hickory/Holly)
@@ -44,6 +45,7 @@ endchoice
 config TSI108_BRIDGE
        bool
        depends on MPC7448HPC2 || PPC_HOLLY
+       select PCI
        select MPIC
        select MPIC_WEIRD
        default y
index 3a0b4a01401c2e67db40e180470478b0884a6b8d..6292e36dc57744605b6bd2e762a03ba0bab3344b 100644 (file)
@@ -45,7 +45,7 @@
 
 #define HOLLY_PCI_CFG_PHYS 0x7c000000
 
-int holly_exclude_device(u_char bus, u_char devfn)
+int holly_exclude_device(struct pci_controller *hose, u_char bus, u_char devfn)
 {
        if (bus == 0 && PCI_SLOT(devfn) == 0)
                return PCIBIOS_DEVICE_NOT_FOUND;
index b412f006a9c55a8dd0bd60ebd193ab1277872793..f4d0a7a603f528a09b1ba16ef17161b63be3320e 100644 (file)
@@ -54,8 +54,9 @@ static struct mtd_partition linkstation_physmap_partitions[] = {
        },
 };
 
-static int __init add_bridge(struct device_node *dev)
+static int __init linkstation_add_bridge(struct device_node *dev)
 {
+#ifdef CONFIG_PCI
        int len;
        struct pci_controller *hose;
        const int *bus_range;
@@ -67,18 +68,17 @@ static int __init add_bridge(struct device_node *dev)
                printk(KERN_WARNING "Can't get bus-range for %s, assume"
                                " bus 0\n", dev->full_name);
 
-       hose = pcibios_alloc_controller();
+       hose = pcibios_alloc_controller(dev);
        if (hose == NULL)
                return -ENOMEM;
        hose->first_busno = bus_range ? bus_range[0] : 0;
        hose->last_busno = bus_range ? bus_range[1] : 0xff;
-       hose->arch_data = dev;
        setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
 
        /* Interpret the "ranges" property */
        /* This also maps the I/O region and sets isa_io/mem_base */
        pci_process_bridge_OF_ranges(hose, dev, 1);
-
+#endif
        return 0;
 }
 
@@ -92,7 +92,7 @@ static void __init linkstation_setup_arch(void)
 
        /* Lookup PCI host bridges */
        for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
-               add_bridge(np);
+               linkstation_add_bridge(np);
 
        printk(KERN_INFO "BUFFALO Network Attached Storage Series\n");
        printk(KERN_INFO "(C) 2002-2005 BUFFALO INC.\n");
index 4542e0c837c07681dd6d929f562e22efefa6786d..1e3cc69487b58719665cc459ed582d6b60d39275 100644 (file)
 
 #define MPC7448HPC2_PCI_CFG_PHYS 0xfb000000
 
-#ifndef CONFIG_PCI
-isa_io_base = MPC7448_HPC2_ISA_IO_BASE;
-isa_mem_base = MPC7448_HPC2_ISA_MEM_BASE;
-pci_dram_offset = MPC7448_HPC2_PCI_MEM_OFFSET;
-#endif
-
 extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
 
-int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn)
+int mpc7448_hpc2_exclude_device(struct pci_controller *hose,
+                               u_char bus, u_char devfn)
 {
        if (bus == 0 && PCI_SLOT(devfn) == 0)
                return PCIBIOS_DEVICE_NOT_FOUND;
index a543a5242e34f783e7e6001175dd42e0d0cb2fe8..f7e0e0c7f8d80e75f40a0288172b4507eea0ab86 100644 (file)
@@ -18,9 +18,4 @@
 
 #include <asm/ppcboot.h>
 
-/* Base Addresses for the PCI bus
- */
-#define MPC7448_HPC2_PCI_MEM_OFFSET    (0x00000000)
-#define MPC7448_HPC2_ISA_IO_BASE       (0x00000000)
-#define MPC7448_HPC2_ISA_MEM_BASE      (0x00000000)
 #endif                         /* __PPC_PLATFORMS_MPC7448_HPC2_H */
index a843b0f87b72c10c53a2dd775d318e319d1862c4..8d95fe4b554e231e9662b717058034971e5edc6d 100644 (file)
@@ -76,24 +76,25 @@ static inline u64 HvCallHpt_invalidateSetSwBitsGet(u32 hpteIndex, u8 bitson,
        return compressedStatus;
 }
 
-static inline u64 HvCallHpt_findValid(hpte_t *hpte, u64 vpn)
+static inline u64 HvCallHpt_findValid(struct hash_pte *hpte, u64 vpn)
 {
        return HvCall3Ret16(HvCallHptFindValid, hpte, vpn, 0, 0);
 }
 
-static inline u64 HvCallHpt_findNextValid(hpte_t *hpte, u32 hpteIndex,
+static inline u64 HvCallHpt_findNextValid(struct hash_pte *hpte, u32 hpteIndex,
                u8 bitson, u8 bitsoff)
 {
        return HvCall3Ret16(HvCallHptFindNextValid, hpte, hpteIndex,
                        bitson, bitsoff);
 }
 
-static inline void HvCallHpt_get(hpte_t *hpte, u32 hpteIndex)
+static inline void HvCallHpt_get(struct hash_pte *hpte, u32 hpteIndex)
 {
        HvCall2Ret16(HvCallHptGet, hpte, hpteIndex, 0);
 }
 
-static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit, hpte_t *hpte)
+static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit,
+                                        struct hash_pte *hpte)
 {
        HvCall4(HvCallHptAddValidate, hpteIndex, hBit, hpte->v, hpte->r);
 }
index ed44dfceaa45069f016ba6a809d0c3c2cf3cf4d9..b4e2c7a038e1b0143dfd8ffec17612e765cb460f 100644 (file)
@@ -44,7 +44,7 @@ long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
                         unsigned long vflags, int psize)
 {
        long slot;
-       hpte_t lhpte;
+       struct hash_pte lhpte;
        int secondary = 0;
 
        BUG_ON(psize != MMU_PAGE_4K);
@@ -99,7 +99,7 @@ long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
 
 static unsigned long iSeries_hpte_getword0(unsigned long slot)
 {
-       hpte_t hpte;
+       struct hash_pte hpte;
 
        HvCallHpt_get(&hpte, slot);
        return hpte.v;
@@ -144,7 +144,7 @@ static long iSeries_hpte_remove(unsigned long hpte_group)
 static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
                                  unsigned long va, int psize, int local)
 {
-       hpte_t hpte;
+       struct hash_pte hpte;
        unsigned long want_v;
 
        iSeries_hlock(slot);
@@ -176,7 +176,7 @@ static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
  */
 static long iSeries_hpte_find(unsigned long vpn)
 {
-       hpte_t hpte;
+       struct hash_pte hpte;
        long slot;
 
        /*
index 9c974227155e5a957ad98391bde74a97f4f62a4b..da87162000f0b25aa38c9189622a7105412b1272 100644 (file)
@@ -742,6 +742,11 @@ void __init iSeries_pcibios_init(void)
        /* Install IO hooks */
        ppc_pci_io = iseries_pci_io;
 
+       /* iSeries has no IO space in the common sense, it needs to set
+        * the IO base to 0
+        */
+       pci_io_base = 0;
+
        if (root == NULL) {
                printk(KERN_CRIT "iSeries_pcibios_init: can't find root "
                                "of device tree\n");
@@ -763,7 +768,7 @@ void __init iSeries_pcibios_init(void)
                if (phb == NULL)
                        continue;
 
-               phb->pci_mem_offset = phb->local_number = bus;
+               phb->pci_mem_offset = bus;
                phb->first_busno = bus;
                phb->last_busno = bus;
                phb->ops = &iSeries_pci_ops;
index 7f5dcee814d4cde9f4331eb8442920f8136eb10e..13a8b1908deda3c4c733003fd649701eba0c7cce 100644 (file)
@@ -79,8 +79,6 @@ extern void iSeries_pci_final_fixup(void);
 static void iSeries_pci_final_fixup(void) { }
 #endif
 
-extern unsigned long iSeries_recal_tb;
-extern unsigned long iSeries_recal_titan;
 
 struct MemoryBlock {
        unsigned long absStart;
@@ -292,8 +290,8 @@ static void __init iSeries_init_early(void)
 {
        DBG(" -> iSeries_init_early()\n");
 
-       iSeries_recal_tb = get_tb();
-       iSeries_recal_titan = HvCallXm_loadTod();
+       /* Snapshot the timebase, for use in later recalibration */
+       iSeries_time_init_early();
 
        /*
         * Initialize the DMA/TCE management
index 7aaa5bbc93630e24986491e8b1717bfef5794d13..fceaae40fe7033c70947f3c9f65680d2b0671c0a 100644 (file)
@@ -444,7 +444,7 @@ static void __init setup_u3_ht(struct pci_controller* hose)
        u3_ht = hose;
 }
 
-static int __init add_bridge(struct device_node *dev)
+static int __init maple_add_bridge(struct device_node *dev)
 {
        int len;
        struct pci_controller *hose;
@@ -519,23 +519,6 @@ void __devinit maple_pci_irq_fixup(struct pci_dev *dev)
        DBG(" <- maple_pci_irq_fixup\n");
 }
 
-static void __init maple_fixup_phb_resources(void)
-{
-       struct pci_controller *hose, *tmp;
-       
-       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
-               unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
-
-               hose->io_resource.start += offset;
-               hose->io_resource.end += offset;
-
-               printk(KERN_INFO "PCI Host %d, io start: %llx; io end: %llx\n",
-                      hose->global_number,
-                      (unsigned long long)hose->io_resource.start,
-                      (unsigned long long)hose->io_resource.end);
-       }
-}
-
 void __init maple_pci_init(void)
 {
        struct device_node *np, *root;
@@ -558,7 +541,7 @@ void __init maple_pci_init(void)
                        continue;
                if ((of_device_is_compatible(np, "u4-pcie") ||
                     of_device_is_compatible(np, "u3-agp")) &&
-                   add_bridge(np) == 0)
+                   maple_add_bridge(np) == 0)
                        of_node_get(np);
 
                if (of_device_is_compatible(np, "u3-ht")) {
@@ -570,27 +553,9 @@ void __init maple_pci_init(void)
 
        /* Now setup the HyperTransport host if we found any
         */
-       if (ht && add_bridge(ht) != 0)
+       if (ht && maple_add_bridge(ht) != 0)
                of_node_put(ht);
 
-        /*
-         * We need to call pci_setup_phb_io for the HT bridge first
-         * so it gets the I/O port numbers starting at 0, and we
-         * need to call it for the AGP bridge after that so it gets
-         * small positive I/O port numbers.
-         */
-        if (u3_ht)
-                pci_setup_phb_io(u3_ht, 1);
-        if (u3_agp)
-                pci_setup_phb_io(u3_agp, 0);
-        if (u4_pcie)
-                pci_setup_phb_io(u4_pcie, 0);
-
-       /* Fixup the IO resources on our host bridges as the common code
-        * does it only for childs of the host bridges
-        */
-       maple_fixup_phb_resources();
-
        /* Setup the linkage between OF nodes and PHBs */ 
        pci_devs_phb_init();
 
index 7c5076e38ea1c501e4a1a249cd53ca32002fd07d..95cd90fd81c74f3ed38dd61766787afb0987965b 100644 (file)
@@ -25,4 +25,13 @@ config PPC_PASEMI_MDIO
        help
          Driver for MDIO via GPIO on PWRficient platforms
 
+config ELECTRA_IDE
+      tristate "Electra IDE driver"
+      default y
+      depends on PPC_PASEMI && ATA
+      select PATA_PLATFORM
+      help
+       This includes driver support for the Electra on-board IDE
+       interface.
+
 endmenu
index 2cd2a4f26a48cfd29c2ab32f44e23fb28b836902..f47fcac7e5812d6270f388bf0f893cbe177b4ca8 100644 (file)
@@ -1,3 +1,4 @@
 obj-y  += setup.o pci.o time.o idle.o powersave.o iommu.o
 obj-$(CONFIG_PPC_PASEMI_MDIO)  += gpio_mdio.o
+obj-$(CONFIG_ELECTRA_IDE) += electra_ide.o
 obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o
diff --git a/arch/powerpc/platforms/pasemi/electra_ide.c b/arch/powerpc/platforms/pasemi/electra_ide.c
new file mode 100644 (file)
index 0000000..12fb0c9
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2007 PA Semi, Inc
+ *
+ * Maintained by: Olof Johansson <olof@lixom.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/platform_device.h>
+
+#include <asm/prom.h>
+#include <asm/system.h>
+
+/* The electra IDE interface is incredibly simple: Just a device on the localbus
+ * with interrupts hooked up to one of the GPIOs. The device tree contains the
+ * address window and interrupt mappings already, and the pata_platform driver handles
+ * the rest. We just need to hook the two up.
+ */
+
+#define MAX_IFS        4       /* really, we have only one */
+
+static struct platform_device *pdevs[MAX_IFS];
+
+static int __devinit electra_ide_init(void)
+{
+       struct device_node *np;
+       struct resource r[3];
+       int ret = 0;
+       int i;
+
+       np = of_find_compatible_node(NULL, "ide", "electra-ide");
+       i = 0;
+
+       while (np && i < MAX_IFS) {
+               memset(r, 0, sizeof(r));
+
+               /* pata_platform wants two address ranges: one for the base registers,
+                * another for the control (altstatus). It's located at offset 0x3f6 in
+                * the window, but the device tree only has one large register window
+                * that covers both ranges. So we need to split it up by hand here:
+                */
+
+               ret = of_address_to_resource(np, 0, &r[0]);
+               if (ret)
+                       goto out;
+               ret = of_address_to_resource(np, 0, &r[1]);
+               if (ret)
+                       goto out;
+
+               r[1].start += 0x3f6;
+               r[0].end = r[1].start-1;
+
+               r[2].start = irq_of_parse_and_map(np, 0);
+               r[2].end = irq_of_parse_and_map(np, 0);
+               r[2].flags = IORESOURCE_IRQ;
+
+               pr_debug("registering platform device at 0x%lx/0x%lx, irq is %ld\n",
+                        r[0].start, r[1].start, r[2].start);
+               pdevs[i] = platform_device_register_simple("pata_platform", i, r, 3);
+               if (IS_ERR(pdevs[i])) {
+                       ret = PTR_ERR(pdevs[i]);
+                       pdevs[i] = NULL;
+                       goto out;
+               }
+               np = of_find_compatible_node(np, "ide", "electra-ide");
+       }
+out:
+       return ret;
+}
+module_init(electra_ide_init);
+
+static void __devexit electra_ide_exit(void)
+{
+       int i;
+
+       for (i = 0; i < MAX_IFS; i++)
+               if (pdevs[i])
+                       platform_device_unregister(pdevs[i]);
+}
+module_exit(electra_ide_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
+MODULE_DESCRIPTION("PA Semi Electra IDE driver");
index bbc6dfcfaa91b835c96e8a5cbd6c629a15734d14..ab1f5f62bcd871cbb6d2955b40af5b0754635d51 100644 (file)
@@ -132,7 +132,7 @@ static void __init setup_pa_pxp(struct pci_controller *hose)
        hose->cfg_data = ioremap(0xe0000000, 0x10000000);
 }
 
-static int __init add_bridge(struct device_node *dev)
+static int __init pas_add_bridge(struct device_node *dev)
 {
        struct pci_controller *hose;
 
@@ -150,29 +150,11 @@ static int __init add_bridge(struct device_node *dev)
        printk(KERN_INFO "Found PA-PXP PCI host bridge.\n");
 
        /* Interpret the "ranges" property */
-       /* This also maps the I/O region and sets isa_io/mem_base */
        pci_process_bridge_OF_ranges(hose, dev, 1);
-       pci_setup_phb_io(hose, 1);
 
        return 0;
 }
 
-
-static void __init pas_fixup_phb_resources(void)
-{
-       struct pci_controller *hose, *tmp;
-
-       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
-               unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
-               hose->io_resource.start += offset;
-               hose->io_resource.end += offset;
-               printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n",
-                      hose->global_number,
-                      hose->io_resource.start, hose->io_resource.end);
-       }
-}
-
-
 void __init pas_pci_init(void)
 {
        struct device_node *np, *root;
@@ -185,13 +167,11 @@ void __init pas_pci_init(void)
        }
 
        for (np = NULL; (np = of_get_next_child(root, np)) != NULL;)
-               if (np->name && !strcmp(np->name, "pxp") && !add_bridge(np))
+               if (np->name && !strcmp(np->name, "pxp") && !pas_add_bridge(np))
                        of_node_get(np);
 
        of_node_put(root);
 
-       pas_fixup_phb_resources();
-
        /* Setup the linkage between OF nodes and PHBs */
        pci_devs_phb_init();
 
index c5a3f61f8d857ba010108b01be9e75f624145a56..ffe6528048b57121a6b4e8d74ee509871b3aa24b 100644 (file)
@@ -239,7 +239,7 @@ static int __init pas_probe(void)
        return 1;
 }
 
-define_machine(pas) {
+define_machine(pasemi) {
        .name                   = "PA Semi PA6T-1682M",
        .probe                  = pas_probe,
        .setup_arch             = pas_setup_arch,
index 5b7afe50039a84be6fc7e12c019833cf36acd4dc..055990ca8ce6cb989d43c384fb3ca1c17502bed6 100644 (file)
@@ -2,6 +2,7 @@ config PPC_PMAC
        bool "Apple PowerMac based machines"
        depends on PPC_MULTIPLATFORM
        select MPIC
+       select PCI
        select PPC_INDIRECT_PCI if PPC32
        select PPC_MPC106 if PPC32
        select PPC_NATIVE
index 3f507ab9c5e5accf21dbd741d821dd9f5832f40c..efdf5eb81ecc79790f4cb72946bdb0c345814883 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/interrupt.h>
 #include <linux/completion.h>
 #include <linux/timer.h>
+#include <linux/mutex.h>
 #include <asm/keylargo.h>
 #include <asm/uninorth.h>
 #include <asm/io.h>
@@ -84,7 +85,7 @@ struct pmac_i2c_bus
        void                    *hostdata;
        int                     channel;        /* some hosts have multiple */
        int                     mode;           /* current mode */
-       struct semaphore        sem;
+       struct mutex            mutex;
        int                     opened;
        int                     polled;         /* open mode */
        struct platform_device  *platform_dev;
@@ -104,7 +105,7 @@ static LIST_HEAD(pmac_i2c_busses);
 
 struct pmac_i2c_host_kw
 {
-       struct semaphore        mutex;          /* Access mutex for use by
+       struct mutex            mutex;          /* Access mutex for use by
                                                 * i2c-keywest */
        void __iomem            *base;          /* register base address */
        int                     bsteps;         /* register stepping */
@@ -375,14 +376,14 @@ static void kw_i2c_timeout(unsigned long data)
 static int kw_i2c_open(struct pmac_i2c_bus *bus)
 {
        struct pmac_i2c_host_kw *host = bus->hostdata;
-       down(&host->mutex);
+       mutex_lock(&host->mutex);
        return 0;
 }
 
 static void kw_i2c_close(struct pmac_i2c_bus *bus)
 {
        struct pmac_i2c_host_kw *host = bus->hostdata;
-       up(&host->mutex);
+       mutex_unlock(&host->mutex);
 }
 
 static int kw_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize,
@@ -498,7 +499,7 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np)
                kfree(host);
                return NULL;
        }
-       init_MUTEX(&host->mutex);
+       mutex_init(&host->mutex);
        init_completion(&host->complete);
        spin_lock_init(&host->lock);
        init_timer(&host->timeout_timer);
@@ -571,7 +572,7 @@ static void __init kw_i2c_add(struct pmac_i2c_host_kw *host,
        bus->open = kw_i2c_open;
        bus->close = kw_i2c_close;
        bus->xfer = kw_i2c_xfer;
-       init_MUTEX(&bus->sem);
+       mutex_init(&bus->mutex);
        if (controller == busnode)
                bus->flags = pmac_i2c_multibus;
        list_add(&bus->link, &pmac_i2c_busses);
@@ -798,7 +799,7 @@ static void __init pmu_i2c_probe(void)
                bus->mode = pmac_i2c_mode_std;
                bus->hostdata = bus + 1;
                bus->xfer = pmu_i2c_xfer;
-               init_MUTEX(&bus->sem);
+               mutex_init(&bus->mutex);
                bus->flags = pmac_i2c_multibus;
                list_add(&bus->link, &pmac_i2c_busses);
 
@@ -921,7 +922,7 @@ static void __init smu_i2c_probe(void)
                bus->mode = pmac_i2c_mode_std;
                bus->hostdata = bus + 1;
                bus->xfer = smu_i2c_xfer;
-               init_MUTEX(&bus->sem);
+               mutex_init(&bus->mutex);
                bus->flags = 0;
                list_add(&bus->link, &pmac_i2c_busses);
 
@@ -1093,13 +1094,13 @@ int pmac_i2c_open(struct pmac_i2c_bus *bus, int polled)
 {
        int rc;
 
-       down(&bus->sem);
+       mutex_lock(&bus->mutex);
        bus->polled = polled || pmac_i2c_force_poll;
        bus->opened = 1;
        bus->mode = pmac_i2c_mode_std;
        if (bus->open && (rc = bus->open(bus)) != 0) {
                bus->opened = 0;
-               up(&bus->sem);
+               mutex_unlock(&bus->mutex);
                return rc;
        }
        return 0;
@@ -1112,7 +1113,7 @@ void pmac_i2c_close(struct pmac_i2c_bus *bus)
        if (bus->close)
                bus->close(bus);
        bus->opened = 0;
-       up(&bus->sem);
+       mutex_unlock(&bus->mutex);
 }
 EXPORT_SYMBOL_GPL(pmac_i2c_close);
 
index c4af9e21ac9329532ca1bd7735fe336115576cf4..92586db19754b249f34114764ff59ebd16d7cf35 100644 (file)
@@ -35,8 +35,6 @@
 #define DBG(x...)
 #endif
 
-static int add_bridge(struct device_node *dev);
-
 /* XXX Could be per-controller, but I don't think we risk anything by
  * assuming we won't have both UniNorth and Bandit */
 static int has_uninorth;
@@ -897,7 +895,7 @@ static void __init setup_u3_ht(struct pci_controller* hose)
  * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise,
  * if we have one or more bandit or chaos bridges, we don't have a MPC106.
  */
-static int __init add_bridge(struct device_node *dev)
+static int __init pmac_add_bridge(struct device_node *dev)
 {
        int len;
        struct pci_controller *hose;
@@ -918,15 +916,9 @@ static int __init add_bridge(struct device_node *dev)
                       " bus 0\n", dev->full_name);
        }
 
-       /* XXX Different prototypes, to be merged */
-#ifdef CONFIG_PPC64
        hose = pcibios_alloc_controller(dev);
-#else
-       hose = pcibios_alloc_controller();
-#endif
        if (!hose)
                return -ENOMEM;
-       hose->arch_data = dev;
        hose->first_busno = bus_range ? bus_range[0] : 0;
        hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
@@ -1006,19 +998,6 @@ void __devinit pmac_pci_irq_fixup(struct pci_dev *dev)
 #endif /* CONFIG_PPC32 */
 }
 
-#ifdef CONFIG_PPC64
-static void __init pmac_fixup_phb_resources(void)
-{
-       struct pci_controller *hose, *tmp;
-
-       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
-               printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n",
-                      hose->global_number,
-                      hose->io_resource.start, hose->io_resource.end);
-       }
-}
-#endif
-
 void __init pmac_pci_init(void)
 {
        struct device_node *np, *root;
@@ -1036,7 +1015,7 @@ void __init pmac_pci_init(void)
                if (strcmp(np->name, "bandit") == 0
                    || strcmp(np->name, "chaos") == 0
                    || strcmp(np->name, "pci") == 0) {
-                       if (add_bridge(np) == 0)
+                       if (pmac_add_bridge(np) == 0)
                                of_node_get(np);
                }
                if (strcmp(np->name, "ht") == 0) {
@@ -1050,28 +1029,9 @@ void __init pmac_pci_init(void)
        /* Probe HT last as it relies on the agp resources to be already
         * setup
         */
-       if (ht && add_bridge(ht) != 0)
+       if (ht && pmac_add_bridge(ht) != 0)
                of_node_put(ht);
 
-       /*
-        * We need to call pci_setup_phb_io for the HT bridge first
-        * so it gets the I/O port numbers starting at 0, and we
-        * need to call it for the AGP bridge after that so it gets
-        * small positive I/O port numbers.
-        */
-       if (u3_ht)
-               pci_setup_phb_io(u3_ht, 1);
-       if (u3_agp)
-               pci_setup_phb_io(u3_agp, 0);
-       if (u4_pcie)
-               pci_setup_phb_io(u4_pcie, 0);
-
-       /*
-        * On ppc64, fixup the IO resources on our host bridges as
-        * the common code does it only for children of the host bridges
-        */
-       pmac_fixup_phb_resources();
-
        /* Setup the linkage between OF nodes and PHBs */
        pci_devs_phb_init();
 
index 40f0008af4d1a9af93c7f85bffe2e640594f9581..a05079b07696b3bdd43be061df046a4b0e943d8f 100644 (file)
@@ -7,6 +7,7 @@ config PPC_PS3
        select USB_OHCI_BIG_ENDIAN_MMIO
        select USB_ARCH_HAS_EHCI
        select USB_EHCI_BIG_ENDIAN_MMIO
+       select MEMORY_HOTPLUG
        help
          This option enables support for the Sony PS3 game console
          and other platforms using the PS3 hypervisor.
@@ -73,18 +74,12 @@ config PS3_USE_LPAR_ADDR
 
 config PS3_VUART
        depends on PPC_PS3
-       bool "PS3 Virtual UART support" if PS3_ADVANCED
-       default y
-       help
-         Include support for the PS3 Virtual UART.
-
-         This support is required for several system services
-         including the System Manager and AV Settings.  In
-         general, all users will say Y.
+       tristate
 
 config PS3_PS3AV
+       depends on PPC_PS3
        tristate "PS3 AV settings driver" if PS3_ADVANCED
-       depends on PS3_VUART
+       select PS3_VUART
        default y
        help
          Include support for the PS3 AV Settings driver.
@@ -93,13 +88,18 @@ config PS3_PS3AV
          general, all users will say Y or M.
 
 config PS3_SYS_MANAGER
-       bool "PS3 System Manager driver" if PS3_ADVANCED
-       depends on PS3_VUART
-       default y
+       depends on PPC_PS3
+       tristate "PS3 System Manager driver" if PS3_ADVANCED
+       select PS3_VUART
+       default m
        help
          Include support for the PS3 System Manager.
 
          This support is required for system control.  In
-         general, all users will say Y.
+         general, all users will say Y or M.
+
+config PS3_STORAGE
+       depends on PPC_PS3
+       tristate
 
 endmenu
index a0048fcf0866160c48a5e42ea5cff8558324ccc5..ac1bdf844ecabaf26abcc3b8b2e42e5d31743619 100644 (file)
@@ -4,3 +4,4 @@ obj-y += system-bus.o
 
 obj-$(CONFIG_SMP) += smp.o
 obj-$(CONFIG_SPU_BASE) += spu.o
+obj-y += device-init.o
diff --git a/arch/powerpc/platforms/ps3/device-init.c b/arch/powerpc/platforms/ps3/device-init.c
new file mode 100644 (file)
index 0000000..825ebb2
--- /dev/null
@@ -0,0 +1,785 @@
+/*
+ *  PS3 device registration routines.
+ *
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/delay.h>
+#include <linux/freezer.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/init.h>
+
+#include <asm/firmware.h>
+#include <asm/lv1call.h>
+#include <asm/ps3stor.h>
+
+#include "platform.h"
+
+/**
+ * ps3_setup_gelic_device - Setup and register a gelic device instance.
+ *
+ * Allocates memory for a struct ps3_system_bus_device instance, initialises the
+ * structure members, and registers the device instance with the system bus.
+ */
+
+static int __init ps3_setup_gelic_device(
+       const struct ps3_repository_device *repo)
+{
+       int result;
+       struct layout {
+               struct ps3_system_bus_device dev;
+               struct ps3_dma_region d_region;
+       } *p;
+
+       pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+       BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB);
+       BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_GELIC);
+
+       p = kzalloc(sizeof(struct layout), GFP_KERNEL);
+
+       if (!p) {
+               result = -ENOMEM;
+               goto fail_malloc;
+       }
+
+       p->dev.match_id = PS3_MATCH_ID_GELIC;
+       p->dev.dev_type = PS3_DEVICE_TYPE_SB;
+       p->dev.bus_id = repo->bus_id;
+       p->dev.dev_id = repo->dev_id;
+       p->dev.d_region = &p->d_region;
+
+       result = ps3_repository_find_interrupt(repo,
+               PS3_INTERRUPT_TYPE_EVENT_PORT, &p->dev.interrupt_id);
+
+       if (result) {
+               pr_debug("%s:%d ps3_repository_find_interrupt failed\n",
+                       __func__, __LINE__);
+               goto fail_find_interrupt;
+       }
+
+       BUG_ON(p->dev.interrupt_id != 0);
+
+       result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K,
+               PS3_DMA_OTHER, NULL, 0);
+
+       if (result) {
+               pr_debug("%s:%d ps3_dma_region_init failed\n",
+                       __func__, __LINE__);
+               goto fail_dma_init;
+       }
+
+       result = ps3_system_bus_device_register(&p->dev);
+
+       if (result) {
+               pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+                       __func__, __LINE__);
+               goto fail_device_register;
+       }
+
+       pr_debug(" <- %s:%d\n", __func__, __LINE__);
+       return result;
+
+fail_device_register:
+fail_dma_init:
+fail_find_interrupt:
+       kfree(p);
+fail_malloc:
+       pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__);
+       return result;
+}
+
+static int __init_refok ps3_setup_uhc_device(
+       const struct ps3_repository_device *repo, enum ps3_match_id match_id,
+       enum ps3_interrupt_type interrupt_type, enum ps3_reg_type reg_type)
+{
+       int result;
+       struct layout {
+               struct ps3_system_bus_device dev;
+               struct ps3_dma_region d_region;
+               struct ps3_mmio_region m_region;
+       } *p;
+       u64 bus_addr;
+       u64 len;
+
+       pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+       BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB);
+       BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_USB);
+
+       p = kzalloc(sizeof(struct layout), GFP_KERNEL);
+
+       if (!p) {
+               result = -ENOMEM;
+               goto fail_malloc;
+       }
+
+       p->dev.match_id = match_id;
+       p->dev.dev_type = PS3_DEVICE_TYPE_SB;
+       p->dev.bus_id = repo->bus_id;
+       p->dev.dev_id = repo->dev_id;
+       p->dev.d_region = &p->d_region;
+       p->dev.m_region = &p->m_region;
+
+       result = ps3_repository_find_interrupt(repo,
+               interrupt_type, &p->dev.interrupt_id);
+
+       if (result) {
+               pr_debug("%s:%d ps3_repository_find_interrupt failed\n",
+                       __func__, __LINE__);
+               goto fail_find_interrupt;
+       }
+
+       result = ps3_repository_find_reg(repo, reg_type,
+               &bus_addr, &len);
+
+       if (result) {
+               pr_debug("%s:%d ps3_repository_find_reg failed\n",
+                       __func__, __LINE__);
+               goto fail_find_reg;
+       }
+
+       result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K,
+               PS3_DMA_INTERNAL, NULL, 0);
+
+       if (result) {
+               pr_debug("%s:%d ps3_dma_region_init failed\n",
+                       __func__, __LINE__);
+               goto fail_dma_init;
+       }
+
+       result = ps3_mmio_region_init(&p->dev, p->dev.m_region, bus_addr, len,
+               PS3_MMIO_4K);
+
+       if (result) {
+               pr_debug("%s:%d ps3_mmio_region_init failed\n",
+                       __func__, __LINE__);
+               goto fail_mmio_init;
+       }
+
+       result = ps3_system_bus_device_register(&p->dev);
+
+       if (result) {
+               pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+                       __func__, __LINE__);
+               goto fail_device_register;
+       }
+
+       pr_debug(" <- %s:%d\n", __func__, __LINE__);
+       return result;
+
+fail_device_register:
+fail_mmio_init:
+fail_dma_init:
+fail_find_reg:
+fail_find_interrupt:
+       kfree(p);
+fail_malloc:
+       pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__);
+       return result;
+}
+
+static int __init ps3_setup_ehci_device(
+       const struct ps3_repository_device *repo)
+{
+       return ps3_setup_uhc_device(repo, PS3_MATCH_ID_EHCI,
+               PS3_INTERRUPT_TYPE_SB_EHCI, PS3_REG_TYPE_SB_EHCI);
+}
+
+static int __init ps3_setup_ohci_device(
+       const struct ps3_repository_device *repo)
+{
+       return ps3_setup_uhc_device(repo, PS3_MATCH_ID_OHCI,
+               PS3_INTERRUPT_TYPE_SB_OHCI, PS3_REG_TYPE_SB_OHCI);
+}
+
+static int __init ps3_setup_vuart_device(enum ps3_match_id match_id,
+       unsigned int port_number)
+{
+       int result;
+       struct layout {
+               struct ps3_system_bus_device dev;
+       } *p;
+
+       pr_debug(" -> %s:%d: match_id %u, port %u\n", __func__, __LINE__,
+               match_id, port_number);
+
+       p = kzalloc(sizeof(struct layout), GFP_KERNEL);
+
+       if (!p)
+               return -ENOMEM;
+
+       p->dev.match_id = match_id;
+       p->dev.dev_type = PS3_DEVICE_TYPE_VUART;
+       p->dev.port_number = port_number;
+
+       result = ps3_system_bus_device_register(&p->dev);
+
+       if (result)
+               pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+                       __func__, __LINE__);
+
+       pr_debug(" <- %s:%d\n", __func__, __LINE__);
+       return result;
+}
+
+static int ps3stor_wait_for_completion(u64 dev_id, u64 tag,
+                                      unsigned int timeout)
+{
+       int result = -1;
+       unsigned int retries = 0;
+       u64 status;
+
+       for (retries = 0; retries < timeout; retries++) {
+               result = lv1_storage_check_async_status(dev_id, tag, &status);
+               if (!result)
+                       break;
+
+               msleep(1);
+       }
+
+       if (result)
+               pr_debug("%s:%u: check_async_status: %s, status %lx\n",
+                        __func__, __LINE__, ps3_result(result), status);
+
+       return result;
+}
+
+/**
+ * ps3_storage_wait_for_device - Wait for a storage device to become ready.
+ * @repo: The repository device to wait for.
+ *
+ * Uses the hypervisor's storage device notification mechanism to wait until
+ * a storage device is ready.  The device notification mechanism uses a
+ * psuedo device (id = -1) to asynchronously notify the guest when storage
+ * devices become ready.  The notification device has a block size of 512
+ * bytes.
+ */
+
+static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo)
+{
+       int result;
+       const u64 notification_dev_id = (u64)-1LL;
+       const unsigned int timeout = HZ;
+       u64 lpar;
+       u64 tag;
+       struct {
+               u64 operation_code;     /* must be zero */
+               u64 event_mask;         /* 1 = device ready */
+       } *notify_cmd;
+       struct {
+               u64 event_type;         /* notify_device_ready */
+               u64 bus_id;
+               u64 dev_id;
+               u64 dev_type;
+               u64 dev_port;
+       } *notify_event;
+       enum {
+               notify_device_ready = 1
+       };
+
+       pr_debug(" -> %s:%u: bus_id %u, dev_id %u, dev_type %u\n", __func__,
+                __LINE__, repo->bus_id, repo->dev_id, repo->dev_type);
+
+       notify_cmd = kzalloc(512, GFP_KERNEL);
+       notify_event = (void *)notify_cmd;
+       if (!notify_cmd)
+               return -ENOMEM;
+
+       lpar = ps3_mm_phys_to_lpar(__pa(notify_cmd));
+
+       result = lv1_open_device(repo->bus_id, notification_dev_id, 0);
+       if (result) {
+               printk(KERN_ERR "%s:%u: lv1_open_device %s\n", __func__,
+                      __LINE__, ps3_result(result));
+               result = -ENODEV;
+               goto fail_free;
+       }
+
+       /* Setup and write the request for device notification. */
+
+       notify_cmd->operation_code = 0; /* must be zero */
+       notify_cmd->event_mask = 0x01;  /* device ready */
+
+       result = lv1_storage_write(notification_dev_id, 0, 0, 1, 0, lpar,
+                                  &tag);
+       if (result) {
+               printk(KERN_ERR "%s:%u: write failed %s\n", __func__, __LINE__,
+                      ps3_result(result));
+               result = -ENODEV;
+               goto fail_close;
+       }
+
+       /* Wait for the write completion */
+
+       result = ps3stor_wait_for_completion(notification_dev_id, tag,
+                                            timeout);
+       if (result) {
+               printk(KERN_ERR "%s:%u: write not completed %s\n", __func__,
+                      __LINE__, ps3_result(result));
+               result = -ENODEV;
+               goto fail_close;
+       }
+
+       /* Loop here processing the requested notification events. */
+
+       result = -ENODEV;
+       while (1) {
+               memset(notify_event, 0, sizeof(*notify_event));
+
+               result = lv1_storage_read(notification_dev_id, 0, 0, 1, 0,
+                                         lpar, &tag);
+               if (result) {
+                       printk(KERN_ERR "%s:%u: write failed %s\n", __func__,
+                              __LINE__, ps3_result(result));
+                       break;
+               }
+
+               result = ps3stor_wait_for_completion(notification_dev_id, tag,
+                                                    timeout);
+               if (result) {
+                       printk(KERN_ERR "%s:%u: read not completed %s\n",
+                              __func__, __LINE__, ps3_result(result));
+                       break;
+               }
+
+               if (notify_event->event_type != notify_device_ready ||
+                   notify_event->bus_id != repo->bus_id) {
+                       pr_debug("%s:%u: bad notify_event: event %lu, "
+                                "dev_id %lu, dev_type %lu\n",
+                                __func__, __LINE__, notify_event->event_type,
+                                notify_event->dev_id, notify_event->dev_type);
+                       break;
+               }
+
+               if (notify_event->dev_id == repo->dev_id &&
+                   notify_event->dev_type == repo->dev_type) {
+                       pr_debug("%s:%u: device ready: dev_id %u\n", __func__,
+                                __LINE__, repo->dev_id);
+                       result = 0;
+                       break;
+               }
+
+               if (notify_event->dev_id == repo->dev_id &&
+                   notify_event->dev_type == PS3_DEV_TYPE_NOACCESS) {
+                       pr_debug("%s:%u: no access: dev_id %u\n", __func__,
+                                __LINE__, repo->dev_id);
+                       break;
+               }
+       }
+
+fail_close:
+       lv1_close_device(repo->bus_id, notification_dev_id);
+fail_free:
+       kfree(notify_cmd);
+       pr_debug(" <- %s:%u\n", __func__, __LINE__);
+       return result;
+}
+
+static int ps3_setup_storage_dev(const struct ps3_repository_device *repo,
+                                enum ps3_match_id match_id)
+{
+       int result;
+       struct ps3_storage_device *p;
+       u64 port, blk_size, num_blocks;
+       unsigned int num_regions, i;
+
+       pr_debug(" -> %s:%u: match_id %u\n", __func__, __LINE__, match_id);
+
+       result = ps3_repository_read_stor_dev_info(repo->bus_index,
+                                                  repo->dev_index, &port,
+                                                  &blk_size, &num_blocks,
+                                                  &num_regions);
+       if (result) {
+               printk(KERN_ERR "%s:%u: _read_stor_dev_info failed %d\n",
+                      __func__, __LINE__, result);
+               return -ENODEV;
+       }
+
+       pr_debug("%s:%u: index %u:%u: port %lu blk_size %lu num_blocks %lu "
+                "num_regions %u\n", __func__, __LINE__, repo->bus_index,
+                repo->dev_index, port, blk_size, num_blocks, num_regions);
+
+       p = kzalloc(sizeof(struct ps3_storage_device) +
+                   num_regions * sizeof(struct ps3_storage_region),
+                   GFP_KERNEL);
+       if (!p) {
+               result = -ENOMEM;
+               goto fail_malloc;
+       }
+
+       p->sbd.match_id = match_id;
+       p->sbd.dev_type = PS3_DEVICE_TYPE_SB;
+       p->sbd.bus_id = repo->bus_id;
+       p->sbd.dev_id = repo->dev_id;
+       p->sbd.d_region = &p->dma_region;
+       p->blk_size = blk_size;
+       p->num_regions = num_regions;
+
+       result = ps3_repository_find_interrupt(repo,
+                                              PS3_INTERRUPT_TYPE_EVENT_PORT,
+                                              &p->sbd.interrupt_id);
+       if (result) {
+               printk(KERN_ERR "%s:%u: find_interrupt failed %d\n", __func__,
+                      __LINE__, result);
+               result = -ENODEV;
+               goto fail_find_interrupt;
+       }
+
+       /* FIXME: Arrange to only do this on a 'cold' boot */
+
+       result = ps3_storage_wait_for_device(repo);
+       if (result) {
+               printk(KERN_ERR "%s:%u: storage_notification failed %d\n",
+                      __func__, __LINE__, result);
+               result = -ENODEV;
+               goto fail_probe_notification;
+       }
+
+       for (i = 0; i < num_regions; i++) {
+               unsigned int id;
+               u64 start, size;
+
+               result = ps3_repository_read_stor_dev_region(repo->bus_index,
+                                                            repo->dev_index,
+                                                            i, &id, &start,
+                                                            &size);
+               if (result) {
+                       printk(KERN_ERR
+                              "%s:%u: read_stor_dev_region failed %d\n",
+                              __func__, __LINE__, result);
+                       result = -ENODEV;
+                       goto fail_read_region;
+               }
+               pr_debug("%s:%u: region %u: id %u start %lu size %lu\n",
+                        __func__, __LINE__, i, id, start, size);
+
+               p->regions[i].id = id;
+               p->regions[i].start = start;
+               p->regions[i].size = size;
+       }
+
+       result = ps3_system_bus_device_register(&p->sbd);
+       if (result) {
+               pr_debug("%s:%u ps3_system_bus_device_register failed\n",
+                        __func__, __LINE__);
+               goto fail_device_register;
+       }
+
+       pr_debug(" <- %s:%u\n", __func__, __LINE__);
+       return 0;
+
+fail_device_register:
+fail_read_region:
+fail_probe_notification:
+fail_find_interrupt:
+       kfree(p);
+fail_malloc:
+       pr_debug(" <- %s:%u: fail.\n", __func__, __LINE__);
+       return result;
+}
+
+static int __init ps3_register_vuart_devices(void)
+{
+       int result;
+       unsigned int port_number;
+
+       pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+       result = ps3_repository_read_vuart_av_port(&port_number);
+       if (result)
+               port_number = 0; /* av default */
+
+       result = ps3_setup_vuart_device(PS3_MATCH_ID_AV_SETTINGS, port_number);
+       WARN_ON(result);
+
+       result = ps3_repository_read_vuart_sysmgr_port(&port_number);
+       if (result)
+               port_number = 2; /* sysmgr default */
+
+       result = ps3_setup_vuart_device(PS3_MATCH_ID_SYSTEM_MANAGER,
+               port_number);
+       WARN_ON(result);
+
+       pr_debug(" <- %s:%d\n", __func__, __LINE__);
+       return result;
+}
+
+static int __init ps3_register_sound_devices(void)
+{
+       int result;
+       struct layout {
+               struct ps3_system_bus_device dev;
+               struct ps3_dma_region d_region;
+               struct ps3_mmio_region m_region;
+       } *p;
+
+       pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+       p = kzalloc(sizeof(*p), GFP_KERNEL);
+       if (!p)
+               return -ENOMEM;
+
+       p->dev.match_id = PS3_MATCH_ID_SOUND;
+       p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;
+       p->dev.d_region = &p->d_region;
+       p->dev.m_region = &p->m_region;
+
+       result = ps3_system_bus_device_register(&p->dev);
+
+       if (result)
+               pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+                       __func__, __LINE__);
+
+       pr_debug(" <- %s:%d\n", __func__, __LINE__);
+       return result;
+}
+
+static int __init ps3_register_graphics_devices(void)
+{
+       int result;
+       struct layout {
+               struct ps3_system_bus_device dev;
+       } *p;
+
+       pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+       p = kzalloc(sizeof(struct layout), GFP_KERNEL);
+
+       if (!p)
+               return -ENOMEM;
+
+       p->dev.match_id = PS3_MATCH_ID_GRAPHICS;
+       p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;
+
+       result = ps3_system_bus_device_register(&p->dev);
+
+       if (result)
+               pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+                       __func__, __LINE__);
+
+       pr_debug(" <- %s:%d\n", __func__, __LINE__);
+       return result;
+}
+
+/**
+ * ps3_register_repository_device - Register a device from the repositiory info.
+ *
+ */
+
+static int ps3_register_repository_device(
+       const struct ps3_repository_device *repo)
+{
+       int result;
+
+       switch (repo->dev_type) {
+       case PS3_DEV_TYPE_SB_GELIC:
+               result = ps3_setup_gelic_device(repo);
+               if (result) {
+                       pr_debug("%s:%d ps3_setup_gelic_device failed\n",
+                               __func__, __LINE__);
+               }
+               break;
+       case PS3_DEV_TYPE_SB_USB:
+
+               /* Each USB device has both an EHCI and an OHCI HC */
+
+               result = ps3_setup_ehci_device(repo);
+
+               if (result) {
+                       pr_debug("%s:%d ps3_setup_ehci_device failed\n",
+                               __func__, __LINE__);
+               }
+
+               result = ps3_setup_ohci_device(repo);
+
+               if (result) {
+                       pr_debug("%s:%d ps3_setup_ohci_device failed\n",
+                               __func__, __LINE__);
+               }
+               break;
+       case PS3_DEV_TYPE_STOR_DISK:
+               result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_DISK);
+
+               /* Some devices are not accessable from the Other OS lpar. */
+               if (result == -ENODEV) {
+                       result = 0;
+                       pr_debug("%s:%u: not accessable\n", __func__,
+                                __LINE__);
+               }
+
+               if (result)
+                       pr_debug("%s:%u ps3_setup_storage_dev failed\n",
+                                __func__, __LINE__);
+               break;
+
+       case PS3_DEV_TYPE_STOR_ROM:
+               result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_ROM);
+               if (result)
+                       pr_debug("%s:%u ps3_setup_storage_dev failed\n",
+                                __func__, __LINE__);
+               break;
+
+       case PS3_DEV_TYPE_STOR_FLASH:
+               result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_FLASH);
+               if (result)
+                       pr_debug("%s:%u ps3_setup_storage_dev failed\n",
+                                __func__, __LINE__);
+               break;
+
+       default:
+               result = 0;
+               pr_debug("%s:%u: unsupported dev_type %u\n", __func__, __LINE__,
+                       repo->dev_type);
+       }
+
+       return result;
+}
+
+/**
+ * ps3_probe_thread - Background repository probing at system startup.
+ *
+ * This implementation only supports background probing on a single bus.
+ */
+
+static int ps3_probe_thread(void *data)
+{
+       struct ps3_repository_device *repo = data;
+       int result;
+       unsigned int ms = 250;
+
+       pr_debug(" -> %s:%u: kthread started\n", __func__, __LINE__);
+
+       do {
+               try_to_freeze();
+
+               pr_debug("%s:%u: probing...\n", __func__, __LINE__);
+
+               do {
+                       result = ps3_repository_find_device(repo);
+
+                       if (result == -ENODEV)
+                               pr_debug("%s:%u: nothing new\n", __func__,
+                                       __LINE__);
+                       else if (result)
+                               pr_debug("%s:%u: find device error.\n",
+                                       __func__, __LINE__);
+                       else {
+                               pr_debug("%s:%u: found device\n", __func__,
+                                       __LINE__);
+                               ps3_register_repository_device(repo);
+                               ps3_repository_bump_device(repo);
+                               ms = 250;
+                       }
+               } while (!result);
+
+               pr_debug("%s:%u: ms %u\n", __func__, __LINE__, ms);
+
+               if ( ms > 60000)
+                       break;
+
+               msleep_interruptible(ms);
+
+               /* An exponential backoff. */
+               ms <<= 1;
+
+       } while (!kthread_should_stop());
+
+       pr_debug(" <- %s:%u: kthread finished\n", __func__, __LINE__);
+
+       return 0;
+}
+
+/**
+ * ps3_start_probe_thread - Starts the background probe thread.
+ *
+ */
+
+static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type)
+{
+       int result;
+       struct task_struct *task;
+       static struct ps3_repository_device repo; /* must be static */
+
+       pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+       memset(&repo, 0, sizeof(repo));
+
+       repo.bus_type = bus_type;
+
+       result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index);
+
+       if (result) {
+               printk(KERN_ERR "%s: Cannot find bus (%d)\n", __func__, result);
+               return -ENODEV;
+       }
+
+       result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id);
+
+       if (result) {
+               printk(KERN_ERR "%s: read_bus_id failed %d\n", __func__,
+                       result);
+               return -ENODEV;
+       }
+
+       task = kthread_run(ps3_probe_thread, &repo, "ps3-probe-%u", bus_type);
+
+       if (IS_ERR(task)) {
+               result = PTR_ERR(task);
+               printk(KERN_ERR "%s: kthread_run failed %d\n", __func__,
+                      result);
+               return result;
+       }
+
+       pr_debug(" <- %s:%d\n", __func__, __LINE__);
+       return 0;
+}
+
+/**
+ * ps3_register_devices - Probe the system and register devices found.
+ *
+ * A device_initcall() routine.
+ */
+
+static int __init ps3_register_devices(void)
+{
+       int result;
+
+       if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+               return -ENODEV;
+
+       pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+       /* ps3_repository_dump_bus_info(); */
+
+       result = ps3_start_probe_thread(PS3_BUS_TYPE_STORAGE);
+
+       ps3_register_vuart_devices();
+
+       ps3_register_graphics_devices();
+
+       ps3_repository_find_devices(PS3_BUS_TYPE_SB,
+               ps3_register_repository_device);
+
+       ps3_register_sound_devices();
+
+       pr_debug(" <- %s:%d\n", __func__, __LINE__);
+       return 0;
+}
+
+device_initcall(ps3_register_devices);
index a1409e450c70172faa23bdeb85c2a8021054b5aa..5d2e176a1b18379fb9c2bb01a8609b95674aca9a 100644 (file)
 #include "platform.h"
 
 #if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
 #else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
 #endif
 
-static hpte_t *htab;
+static struct hash_pte *htab;
 static unsigned long htab_addr;
 static unsigned char *bolttab;
 static unsigned char *inusetab;
@@ -44,8 +44,8 @@ static DEFINE_SPINLOCK(ps3_bolttab_lock);
 #define debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g) \
        _debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__)
 static void _debug_dump_hpte(unsigned long pa, unsigned long va,
-       unsigned long group, unsigned long bitmap, hpte_t lhpte, int psize,
-       unsigned long slot, const char* func, int line)
+       unsigned long group, unsigned long bitmap, struct hash_pte lhpte,
+       int psize, unsigned long slot, const char* func, int line)
 {
        DBG("%s:%d: pa     = %lxh\n", func, line, pa);
        DBG("%s:%d: lpar   = %lxh\n", func, line,
@@ -63,7 +63,7 @@ static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va,
        unsigned long pa, unsigned long rflags, unsigned long vflags, int psize)
 {
        unsigned long slot;
-       hpte_t lhpte;
+       struct hash_pte lhpte;
        int secondary = 0;
        unsigned long result;
        unsigned long bitmap;
@@ -234,10 +234,17 @@ static void ps3_hpte_invalidate(unsigned long slot, unsigned long va,
 
 static void ps3_hpte_clear(void)
 {
-       /* Make sure to clean up the frame buffer device first */
-       ps3fb_cleanup();
+       int result;
 
-       lv1_unmap_htab(htab_addr);
+       DBG(" -> %s:%d\n", __func__, __LINE__);
+
+       result = lv1_unmap_htab(htab_addr);
+       BUG_ON(result);
+
+       ps3_mm_shutdown();
+       ps3_mm_vas_destroy();
+
+       DBG(" <- %s:%d\n", __func__, __LINE__);
 }
 
 void __init ps3_hpte_init(unsigned long htab_size)
@@ -255,7 +262,7 @@ void __init ps3_hpte_init(unsigned long htab_size)
 
        ppc64_pft_size = __ilog2(htab_size);
 
-       bitmap_size = htab_size / sizeof(hpte_t) / 8;
+       bitmap_size = htab_size / sizeof(struct hash_pte) / 8;
 
        bolttab = __va(lmb_alloc(bitmap_size, 1));
        inusetab = __va(lmb_alloc(bitmap_size, 1));
@@ -273,8 +280,8 @@ void __init ps3_map_htab(void)
 
        result = lv1_map_htab(0, &htab_addr);
 
-       htab = (hpte_t *)__ioremap(htab_addr, htab_size,
-                                  pgprot_val(PAGE_READONLY_X));
+       htab = (__force struct hash_pte *)ioremap_flags(htab_addr, htab_size,
+                                           pgprot_val(PAGE_READONLY_X));
 
        DBG("%s:%d: lpar %016lxh, virt %016lxh\n", __func__, __LINE__,
                htab_addr, (unsigned long)htab);
index ec9030dbb5f1ba13fc86c116d1675f6a5c82dc15..67e32ec9b37e8da948d488ced85d1f757298cd62 100644 (file)
@@ -30,9 +30,9 @@
 #include "platform.h"
 
 #if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
 #else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
 #endif
 
 /**
@@ -78,18 +78,84 @@ struct ps3_bmp {
 /**
  * struct ps3_private - a per cpu data structure
  * @bmp: ps3_bmp structure
- * @node: HV logical_ppe_id
- * @cpu: HV thread_id
+ * @ppe_id: HV logical_ppe_id
+ * @thread_id: HV thread_id
  */
 
 struct ps3_private {
        struct ps3_bmp bmp __attribute__ ((aligned (PS3_BMP_MINALIGN)));
-       u64 node;
-       unsigned int cpu;
+       u64 ppe_id;
+       u64 thread_id;
 };
 
 static DEFINE_PER_CPU(struct ps3_private, ps3_private);
 
+/**
+ * ps3_chip_mask - Set an interrupt mask bit in ps3_bmp.
+ * @virq: The assigned Linux virq.
+ *
+ * Sets ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
+ */
+
+static void ps3_chip_mask(unsigned int virq)
+{
+       struct ps3_private *pd = get_irq_chip_data(virq);
+       unsigned long flags;
+
+       pr_debug("%s:%d: thread_id %lu, virq %d\n", __func__, __LINE__,
+               pd->thread_id, virq);
+
+       local_irq_save(flags);
+       clear_bit(63 - virq, &pd->bmp.mask);
+       lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
+       local_irq_restore(flags);
+}
+
+/**
+ * ps3_chip_unmask - Clear an interrupt mask bit in ps3_bmp.
+ * @virq: The assigned Linux virq.
+ *
+ * Clears ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
+ */
+
+static void ps3_chip_unmask(unsigned int virq)
+{
+       struct ps3_private *pd = get_irq_chip_data(virq);
+       unsigned long flags;
+
+       pr_debug("%s:%d: thread_id %lu, virq %d\n", __func__, __LINE__,
+               pd->thread_id, virq);
+
+       local_irq_save(flags);
+       set_bit(63 - virq, &pd->bmp.mask);
+       lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
+       local_irq_restore(flags);
+}
+
+/**
+ * ps3_chip_eoi - HV end-of-interrupt.
+ * @virq: The assigned Linux virq.
+ *
+ * Calls lv1_end_of_interrupt_ext().
+ */
+
+static void ps3_chip_eoi(unsigned int virq)
+{
+       const struct ps3_private *pd = get_irq_chip_data(virq);
+       lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, virq);
+}
+
+/**
+ * ps3_irq_chip - Represents the ps3_bmp as a Linux struct irq_chip.
+ */
+
+static struct irq_chip ps3_irq_chip = {
+       .typename = "ps3",
+       .mask = ps3_chip_mask,
+       .unmask = ps3_chip_unmask,
+       .eoi = ps3_chip_eoi,
+};
+
 /**
  * ps3_virq_setup - virq related setup.
  * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
@@ -134,6 +200,8 @@ int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
                goto fail_set;
        }
 
+       ps3_chip_mask(*virq);
+
        return result;
 
 fail_set:
@@ -153,8 +221,8 @@ int ps3_virq_destroy(unsigned int virq)
 {
        const struct ps3_private *pd = get_irq_chip_data(virq);
 
-       pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__,
-               pd->node, pd->cpu, virq);
+       pr_debug("%s:%d: ppe_id %lu, thread_id %lu, virq %u\n", __func__,
+               __LINE__, pd->ppe_id, pd->thread_id, virq);
 
        set_irq_chip_data(virq, NULL);
        irq_dispose_mapping(virq);
@@ -190,7 +258,8 @@ int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
 
        /* Binds outlet to cpu + virq. */
 
-       result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0);
+       result = lv1_connect_irq_plug_ext(pd->ppe_id, pd->thread_id, *virq,
+               outlet, 0);
 
        if (result) {
                pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n",
@@ -222,10 +291,12 @@ int ps3_irq_plug_destroy(unsigned int virq)
        int result;
        const struct ps3_private *pd = get_irq_chip_data(virq);
 
-       pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__,
-               pd->node, pd->cpu, virq);
+       pr_debug("%s:%d: ppe_id %lu, thread_id %lu, virq %u\n", __func__,
+               __LINE__, pd->ppe_id, pd->thread_id, virq);
+
+       ps3_chip_mask(virq);
 
-       result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq);
+       result = lv1_disconnect_irq_plug_ext(pd->ppe_id, pd->thread_id, virq);
 
        if (result)
                pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n",
@@ -282,7 +353,9 @@ int ps3_event_receive_port_destroy(unsigned int virq)
 {
        int result;
 
-       pr_debug(" -> %s:%d virq: %u\n", __func__, __LINE__, virq);
+       pr_debug(" -> %s:%d virq %u\n", __func__, __LINE__, virq);
+
+       ps3_chip_mask(virq);
 
        result = lv1_destruct_event_receive_port(virq_to_hw(virq));
 
@@ -290,17 +363,14 @@ int ps3_event_receive_port_destroy(unsigned int virq)
                pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n",
                        __func__, __LINE__, ps3_result(result));
 
-       /* lv1_destruct_event_receive_port() destroys the IRQ plug,
-        * so don't call ps3_irq_plug_destroy() here.
+       /*
+        * Don't call ps3_virq_destroy() here since ps3_smp_cleanup_cpu()
+        * calls from interrupt context (smp_call_function) when kexecing.
         */
 
-       result = ps3_virq_destroy(virq);
-       BUG_ON(result);
-
        pr_debug(" <- %s:%d\n", __func__, __LINE__);
        return result;
 }
-EXPORT_SYMBOL_GPL(ps3_event_receive_port_destroy);
 
 int ps3_send_event_locally(unsigned int virq)
 {
@@ -311,17 +381,15 @@ int ps3_send_event_locally(unsigned int virq)
  * ps3_sb_event_receive_port_setup - Setup a system bus event receive port.
  * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be
  * serviced on.
- * @did: The HV device identifier read from the system repository.
- * @interrupt_id: The device interrupt id read from the system repository.
+ * @dev: The system bus device instance.
  * @virq: The assigned Linux virq.
  *
  * An event irq represents a virtual device interrupt.  The interrupt_id
  * coresponds to the software interrupt number.
  */
 
-int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu,
-       const struct ps3_device_id *did, unsigned int interrupt_id,
-       unsigned int *virq)
+int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev,
+       enum ps3_cpu_binding cpu, unsigned int *virq)
 {
        /* this should go in system-bus.c */
 
@@ -332,8 +400,8 @@ int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu,
        if (result)
                return result;
 
-       result = lv1_connect_interrupt_event_receive_port(did->bus_id,
-               did->dev_id, virq_to_hw(*virq), interrupt_id);
+       result = lv1_connect_interrupt_event_receive_port(dev->bus_id,
+               dev->dev_id, virq_to_hw(*virq), dev->interrupt_id);
 
        if (result) {
                pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port"
@@ -345,24 +413,24 @@ int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu,
        }
 
        pr_debug("%s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
-               interrupt_id, *virq);
+               dev->interrupt_id, *virq);
 
        return 0;
 }
 EXPORT_SYMBOL(ps3_sb_event_receive_port_setup);
 
-int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did,
-       unsigned int interrupt_id, unsigned int virq)
+int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev,
+       unsigned int virq)
 {
        /* this should go in system-bus.c */
 
        int result;
 
        pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__,
-               interrupt_id, virq);
+               dev->interrupt_id, virq);
 
-       result = lv1_disconnect_interrupt_event_receive_port(did->bus_id,
-               did->dev_id, virq_to_hw(virq), interrupt_id);
+       result = lv1_disconnect_interrupt_event_receive_port(dev->bus_id,
+               dev->dev_id, virq_to_hw(virq), dev->interrupt_id);
 
        if (result)
                pr_debug("%s:%d: lv1_disconnect_interrupt_event_receive_port"
@@ -372,6 +440,14 @@ int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did,
        result = ps3_event_receive_port_destroy(virq);
        BUG_ON(result);
 
+       /*
+        * ps3_event_receive_port_destroy() destroys the IRQ plug,
+        * so don't call ps3_irq_plug_destroy() here.
+        */
+
+       result = ps3_virq_destroy(virq);
+       BUG_ON(result);
+
        pr_debug(" <- %s:%d\n", __func__, __LINE__);
        return result;
 }
@@ -412,16 +488,24 @@ EXPORT_SYMBOL_GPL(ps3_io_irq_setup);
 int ps3_io_irq_destroy(unsigned int virq)
 {
        int result;
+       unsigned long outlet = virq_to_hw(virq);
 
-       result = lv1_destruct_io_irq_outlet(virq_to_hw(virq));
+       ps3_chip_mask(virq);
 
-       if (result)
-               pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
-                       __func__, __LINE__, ps3_result(result));
+       /*
+        * lv1_destruct_io_irq_outlet() will destroy the IRQ plug,
+        * so call ps3_irq_plug_destroy() first.
+        */
 
        result = ps3_irq_plug_destroy(virq);
        BUG_ON(result);
 
+       result = lv1_destruct_io_irq_outlet(outlet);
+
+       if (result)
+               pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
+                       __func__, __LINE__, ps3_result(result));
+
        return result;
 }
 EXPORT_SYMBOL_GPL(ps3_io_irq_destroy);
@@ -461,11 +545,13 @@ int ps3_vuart_irq_setup(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
 
        return result;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_irq_setup);
 
 int ps3_vuart_irq_destroy(unsigned int virq)
 {
        int result;
 
+       ps3_chip_mask(virq);
        result = lv1_deconfigure_virtual_uart_irq();
 
        if (result) {
@@ -479,6 +565,7 @@ int ps3_vuart_irq_destroy(unsigned int virq)
 
        return result;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_irq_destroy);
 
 /**
  * ps3_spe_irq_setup - Setup an spe virq.
@@ -514,9 +601,14 @@ int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id,
 
 int ps3_spe_irq_destroy(unsigned int virq)
 {
-       int result = ps3_irq_plug_destroy(virq);
+       int result;
+
+       ps3_chip_mask(virq);
+
+       result = ps3_irq_plug_destroy(virq);
        BUG_ON(result);
-       return 0;
+
+       return result;
 }
 
 
@@ -533,7 +625,7 @@ static void _dump_64_bmp(const char *header, const u64 *p, unsigned cpu,
                *p & 0xffff);
 }
 
-static void __attribute__ ((unused)) _dump_256_bmp(const char *header,
+static void __maybe_unused _dump_256_bmp(const char *header,
        const u64 *p, unsigned cpu, const char* func, int line)
 {
        pr_debug("%s:%d: %s %u {%016lx:%016lx:%016lx:%016lx}\n",
@@ -546,86 +638,25 @@ static void _dump_bmp(struct ps3_private* pd, const char* func, int line)
        unsigned long flags;
 
        spin_lock_irqsave(&pd->bmp.lock, flags);
-       _dump_64_bmp("stat", &pd->bmp.status, pd->cpu, func, line);
-       _dump_64_bmp("mask", &pd->bmp.mask, pd->cpu, func, line);
+       _dump_64_bmp("stat", &pd->bmp.status, pd->thread_id, func, line);
+       _dump_64_bmp("mask", &pd->bmp.mask, pd->thread_id, func, line);
        spin_unlock_irqrestore(&pd->bmp.lock, flags);
 }
 
 #define dump_mask(_x) _dump_mask(_x, __func__, __LINE__)
-static void __attribute__ ((unused)) _dump_mask(struct ps3_private* pd,
+static void __maybe_unused _dump_mask(struct ps3_private *pd,
        const char* func, int line)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&pd->bmp.lock, flags);
-       _dump_64_bmp("mask", &pd->bmp.mask, pd->cpu, func, line);
+       _dump_64_bmp("mask", &pd->bmp.mask, pd->thread_id, func, line);
        spin_unlock_irqrestore(&pd->bmp.lock, flags);
 }
 #else
 static void dump_bmp(struct ps3_private* pd) {};
 #endif /* defined(DEBUG) */
 
-static void ps3_chip_mask(unsigned int virq)
-{
-       struct ps3_private *pd = get_irq_chip_data(virq);
-       u64 bit = 0x8000000000000000UL >> virq;
-       u64 *p = &pd->bmp.mask;
-       u64 old;
-       unsigned long flags;
-
-       pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq);
-
-       local_irq_save(flags);
-       asm volatile(
-                    "1:        ldarx %0,0,%3\n"
-                    "andc      %0,%0,%2\n"
-                    "stdcx.    %0,0,%3\n"
-                    "bne-      1b"
-                    : "=&r" (old), "+m" (*p)
-                    : "r" (bit), "r" (p)
-                    : "cc" );
-
-       lv1_did_update_interrupt_mask(pd->node, pd->cpu);
-       local_irq_restore(flags);
-}
-
-static void ps3_chip_unmask(unsigned int virq)
-{
-       struct ps3_private *pd = get_irq_chip_data(virq);
-       u64 bit = 0x8000000000000000UL >> virq;
-       u64 *p = &pd->bmp.mask;
-       u64 old;
-       unsigned long flags;
-
-       pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq);
-
-       local_irq_save(flags);
-       asm volatile(
-                    "1:        ldarx %0,0,%3\n"
-                    "or        %0,%0,%2\n"
-                    "stdcx.    %0,0,%3\n"
-                    "bne-      1b"
-                    : "=&r" (old), "+m" (*p)
-                    : "r" (bit), "r" (p)
-                    : "cc" );
-
-       lv1_did_update_interrupt_mask(pd->node, pd->cpu);
-       local_irq_restore(flags);
-}
-
-static void ps3_chip_eoi(unsigned int virq)
-{
-       const struct ps3_private *pd = get_irq_chip_data(virq);
-       lv1_end_of_interrupt_ext(pd->node, pd->cpu, virq);
-}
-
-static struct irq_chip irq_chip = {
-       .typename = "ps3",
-       .mask = ps3_chip_mask,
-       .unmask = ps3_chip_unmask,
-       .eoi = ps3_chip_eoi,
-};
-
 static void ps3_host_unmap(struct irq_host *h, unsigned int virq)
 {
        set_irq_chip_data(virq, NULL);
@@ -637,7 +668,7 @@ static int ps3_host_map(struct irq_host *h, unsigned int virq,
        pr_debug("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq,
                virq);
 
-       set_irq_chip_and_handler(virq, &irq_chip, handle_fasteoi_irq);
+       set_irq_chip_and_handler(virq, &ps3_irq_chip, handle_fasteoi_irq);
 
        return 0;
 }
@@ -657,7 +688,7 @@ void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq)
                cpu, virq, pd->bmp.ipi_debug_brk_mask);
 }
 
-unsigned int ps3_get_irq(void)
+static unsigned int ps3_get_irq(void)
 {
        struct ps3_private *pd = &__get_cpu_var(ps3_private);
        u64 x = (pd->bmp.status & pd->bmp.mask);
@@ -672,8 +703,8 @@ unsigned int ps3_get_irq(void)
        plug &= 0x3f;
 
        if (unlikely(plug) == NO_IRQ) {
-               pr_debug("%s:%d: no plug found: cpu %u\n", __func__, __LINE__,
-                       pd->cpu);
+               pr_debug("%s:%d: no plug found: thread_id %lu\n", __func__,
+                       __LINE__, pd->thread_id);
                dump_bmp(&per_cpu(ps3_private, 0));
                dump_bmp(&per_cpu(ps3_private, 1));
                return NO_IRQ;
@@ -703,16 +734,16 @@ void __init ps3_init_IRQ(void)
        for_each_possible_cpu(cpu) {
                struct ps3_private *pd = &per_cpu(ps3_private, cpu);
 
-               lv1_get_logical_ppe_id(&pd->node);
-               pd->cpu = get_hard_smp_processor_id(cpu);
+               lv1_get_logical_ppe_id(&pd->ppe_id);
+               pd->thread_id = get_hard_smp_processor_id(cpu);
                spin_lock_init(&pd->bmp.lock);
 
-               pr_debug("%s:%d: node %lu, cpu %d, bmp %lxh\n", __func__,
-                       __LINE__, pd->node, pd->cpu,
+               pr_debug("%s:%d: ppe_id %lu, thread_id %lu, bmp %lxh\n",
+                       __func__, __LINE__, pd->ppe_id, pd->thread_id,
                        ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
 
-               result = lv1_configure_irq_state_bitmap(pd->node, pd->cpu,
-                       ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
+               result = lv1_configure_irq_state_bitmap(pd->ppe_id,
+                       pd->thread_id, ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
 
                if (result)
                        pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:"
@@ -722,3 +753,16 @@ void __init ps3_init_IRQ(void)
 
        ppc_md.get_irq = ps3_get_irq;
 }
+
+void ps3_shutdown_IRQ(int cpu)
+{
+       int result;
+       u64 ppe_id;
+       u64 thread_id = get_hard_smp_processor_id(cpu);
+
+       lv1_get_logical_ppe_id(&ppe_id);
+       result = lv1_configure_irq_state_bitmap(ppe_id, thread_id, 0);
+
+       DBG("%s:%d: lv1_configure_irq_state_bitmap (%lu:%lu/%d) %s\n", __func__,
+               __LINE__, ppe_id, thread_id, cpu, ps3_result(result));
+}
index f8a3e206c584b42f97b811da0b09b1402633bb95..7bb3e1620974d0b14c076ded52205b0973474233 100644 (file)
@@ -30,9 +30,9 @@
 #include "platform.h"
 
 #if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
 #else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
 #endif
 
 enum {
@@ -115,7 +115,8 @@ struct map {
 };
 
 #define debug_dump_map(x) _debug_dump_map(x, __func__, __LINE__)
-static void _debug_dump_map(const struct map* m, const char* func, int line)
+static void __maybe_unused _debug_dump_map(const struct map *m,
+       const char *func, int line)
 {
        DBG("%s:%d: map.total     = %lxh\n", func, line, m->total);
        DBG("%s:%d: map.rm.size   = %lxh\n", func, line, m->rm.size);
@@ -212,9 +213,15 @@ fail:
 
 void ps3_mm_vas_destroy(void)
 {
+       int result;
+
+       DBG("%s:%d: map.vas_id    = %lu\n", __func__, __LINE__, map.vas_id);
+
        if (map.vas_id) {
-               lv1_select_virtual_address_space(0);
-               lv1_destruct_virtual_address_space(map.vas_id);
+               result = lv1_select_virtual_address_space(0);
+               BUG_ON(result);
+               result = lv1_destruct_virtual_address_space(map.vas_id);
+               BUG_ON(result);
                map.vas_id = 0;
        }
 }
@@ -232,7 +239,7 @@ void ps3_mm_vas_destroy(void)
  * @size is rounded down to a multiple of the vas large page size.
  */
 
-int ps3_mm_region_create(struct mem_region *r, unsigned long size)
+static int ps3_mm_region_create(struct mem_region *r, unsigned long size)
 {
        int result;
        unsigned long muid;
@@ -273,10 +280,14 @@ zero_region:
  * @r: pointer to struct mem_region
  */
 
-void ps3_mm_region_destroy(struct mem_region *r)
+static void ps3_mm_region_destroy(struct mem_region *r)
 {
+       int result;
+
+       DBG("%s:%d: r->base = %lxh\n", __func__, __LINE__, r->base);
        if (r->base) {
-               lv1_release_memory(r->base);
+               result = lv1_release_memory(r->base);
+               BUG_ON(result);
                r->size = r->base = r->offset = 0;
                map.total = map.rm.size;
        }
@@ -329,31 +340,34 @@ core_initcall(ps3_mm_add_memory);
 /*============================================================================*/
 
 /**
- * dma_lpar_to_bus - Translate an lpar address to ioc mapped bus address.
+ * dma_sb_lpar_to_bus - Translate an lpar address to ioc mapped bus address.
  * @r: pointer to dma region structure
  * @lpar_addr: HV lpar address
  */
 
-static unsigned long dma_lpar_to_bus(struct ps3_dma_region *r,
+static unsigned long dma_sb_lpar_to_bus(struct ps3_dma_region *r,
        unsigned long lpar_addr)
 {
-       BUG_ON(lpar_addr >= map.r1.base + map.r1.size);
-       return r->bus_addr + (lpar_addr <= map.rm.size ? lpar_addr
-               : lpar_addr - map.r1.offset);
+       if (lpar_addr >= map.rm.size)
+               lpar_addr -= map.r1.offset;
+       BUG_ON(lpar_addr < r->offset);
+       BUG_ON(lpar_addr >= r->offset + r->len);
+       return r->bus_addr + lpar_addr - r->offset;
 }
 
 #define dma_dump_region(_a) _dma_dump_region(_a, __func__, __LINE__)
-static void _dma_dump_region(const struct ps3_dma_region *r, const char* func,
-       int line)
+static void  __maybe_unused _dma_dump_region(const struct ps3_dma_region *r,
+       const char *func, int line)
 {
-       DBG("%s:%d: dev        %u:%u\n", func, line, r->did.bus_id,
-               r->did.dev_id);
+       DBG("%s:%d: dev        %u:%u\n", func, line, r->dev->bus_id,
+               r->dev->dev_id);
        DBG("%s:%d: page_size  %u\n", func, line, r->page_size);
        DBG("%s:%d: bus_addr   %lxh\n", func, line, r->bus_addr);
        DBG("%s:%d: len        %lxh\n", func, line, r->len);
+       DBG("%s:%d: offset     %lxh\n", func, line, r->offset);
 }
 
-/**
+  /**
  * dma_chunk - A chunk of dma pages mapped by the io controller.
  * @region - The dma region that owns this chunk.
  * @lpar_addr: Starting lpar address of the area to map.
@@ -381,10 +395,11 @@ static void _dma_dump_chunk (const struct dma_chunk* c, const char* func,
        int line)
 {
        DBG("%s:%d: r.dev        %u:%u\n", func, line,
-               c->region->did.bus_id, c->region->did.dev_id);
+               c->region->dev->bus_id, c->region->dev->dev_id);
        DBG("%s:%d: r.bus_addr   %lxh\n", func, line, c->region->bus_addr);
        DBG("%s:%d: r.page_size  %u\n", func, line, c->region->page_size);
        DBG("%s:%d: r.len        %lxh\n", func, line, c->region->len);
+       DBG("%s:%d: r.offset     %lxh\n", func, line, c->region->offset);
        DBG("%s:%d: c.lpar_addr  %lxh\n", func, line, c->lpar_addr);
        DBG("%s:%d: c.bus_addr   %lxh\n", func, line, c->bus_addr);
        DBG("%s:%d: c.len        %lxh\n", func, line, c->len);
@@ -395,39 +410,68 @@ static struct dma_chunk * dma_find_chunk(struct ps3_dma_region *r,
 {
        struct dma_chunk *c;
        unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, 1 << r->page_size);
-       unsigned long aligned_len = _ALIGN_UP(len, 1 << r->page_size);
+       unsigned long aligned_len = _ALIGN_UP(len+bus_addr-aligned_bus,
+                                             1 << r->page_size);
 
        list_for_each_entry(c, &r->chunk_list.head, link) {
                /* intersection */
-               if (aligned_bus >= c->bus_addr
-                       && aligned_bus < c->bus_addr + c->len
-                       && aligned_bus + aligned_len <= c->bus_addr + c->len) {
+               if (aligned_bus >= c->bus_addr &&
+                   aligned_bus + aligned_len <= c->bus_addr + c->len)
                        return c;
-               }
+
                /* below */
-               if (aligned_bus + aligned_len <= c->bus_addr) {
+               if (aligned_bus + aligned_len <= c->bus_addr)
                        continue;
-               }
+
                /* above */
-               if (aligned_bus >= c->bus_addr + c->len) {
+               if (aligned_bus >= c->bus_addr + c->len)
                        continue;
-               }
 
                /* we don't handle the multi-chunk case for now */
-
                dma_dump_chunk(c);
                BUG();
        }
        return NULL;
 }
 
-static int dma_free_chunk(struct dma_chunk *c)
+static struct dma_chunk *dma_find_chunk_lpar(struct ps3_dma_region *r,
+       unsigned long lpar_addr, unsigned long len)
+{
+       struct dma_chunk *c;
+       unsigned long aligned_lpar = _ALIGN_DOWN(lpar_addr, 1 << r->page_size);
+       unsigned long aligned_len = _ALIGN_UP(len + lpar_addr - aligned_lpar,
+                                             1 << r->page_size);
+
+       list_for_each_entry(c, &r->chunk_list.head, link) {
+               /* intersection */
+               if (c->lpar_addr <= aligned_lpar &&
+                   aligned_lpar < c->lpar_addr + c->len) {
+                       if (aligned_lpar + aligned_len <= c->lpar_addr + c->len)
+                               return c;
+                       else {
+                               dma_dump_chunk(c);
+                               BUG();
+                       }
+               }
+               /* below */
+               if (aligned_lpar + aligned_len <= c->lpar_addr) {
+                       continue;
+               }
+               /* above */
+               if (c->lpar_addr + c->len <= aligned_lpar) {
+                       continue;
+               }
+       }
+       return NULL;
+}
+
+static int dma_sb_free_chunk(struct dma_chunk *c)
 {
        int result = 0;
 
        if (c->bus_addr) {
-               result = lv1_unmap_device_dma_region(c->region->did.bus_id,
-                       c->region->did.dev_id, c->bus_addr, c->len);
+               result = lv1_unmap_device_dma_region(c->region->dev->bus_id,
+                       c->region->dev->dev_id, c->bus_addr, c->len);
                BUG_ON(result);
        }
 
@@ -435,8 +479,39 @@ static int dma_free_chunk(struct dma_chunk *c)
        return result;
 }
 
+static int dma_ioc0_free_chunk(struct dma_chunk *c)
+{
+       int result = 0;
+       int iopage;
+       unsigned long offset;
+       struct ps3_dma_region *r = c->region;
+
+       DBG("%s:start\n", __func__);
+       for (iopage = 0; iopage < (c->len >> r->page_size); iopage++) {
+               offset = (1 << r->page_size) * iopage;
+               /* put INVALID entry */
+               result = lv1_put_iopte(0,
+                                      c->bus_addr + offset,
+                                      c->lpar_addr + offset,
+                                      r->ioid,
+                                      0);
+               DBG("%s: bus=%#lx, lpar=%#lx, ioid=%d\n", __func__,
+                   c->bus_addr + offset,
+                   c->lpar_addr + offset,
+                   r->ioid);
+
+               if (result) {
+                       DBG("%s:%d: lv1_put_iopte failed: %s\n", __func__,
+                           __LINE__, ps3_result(result));
+               }
+       }
+       kfree(c);
+       DBG("%s:end\n", __func__);
+       return result;
+}
+
 /**
- * dma_map_pages - Maps dma pages into the io controller bus address space.
+ * dma_sb_map_pages - Maps dma pages into the io controller bus address space.
  * @r: Pointer to a struct ps3_dma_region.
  * @phys_addr: Starting physical address of the area to map.
  * @len: Length in bytes of the area to map.
@@ -446,8 +521,8 @@ static int dma_free_chunk(struct dma_chunk *c)
  * make the HV call to add the pages into the io controller address space.
  */
 
-static int dma_map_pages(struct ps3_dma_region *r, unsigned long phys_addr,
-       unsigned long len, struct dma_chunk **c_out)
+static int dma_sb_map_pages(struct ps3_dma_region *r, unsigned long phys_addr,
+           unsigned long len, struct dma_chunk **c_out, u64 iopte_flag)
 {
        int result;
        struct dma_chunk *c;
@@ -461,13 +536,13 @@ static int dma_map_pages(struct ps3_dma_region *r, unsigned long phys_addr,
 
        c->region = r;
        c->lpar_addr = ps3_mm_phys_to_lpar(phys_addr);
-       c->bus_addr = dma_lpar_to_bus(r, c->lpar_addr);
+       c->bus_addr = dma_sb_lpar_to_bus(r, c->lpar_addr);
        c->len = len;
 
-       result = lv1_map_device_dma_region(c->region->did.bus_id,
-               c->region->did.dev_id, c->lpar_addr, c->bus_addr, c->len,
-               0xf800000000000000UL);
-
+       BUG_ON(iopte_flag != 0xf800000000000000UL);
+       result = lv1_map_device_dma_region(c->region->dev->bus_id,
+                                          c->region->dev->dev_id, c->lpar_addr,
+                                          c->bus_addr, c->len, iopte_flag);
        if (result) {
                DBG("%s:%d: lv1_map_device_dma_region failed: %s\n",
                        __func__, __LINE__, ps3_result(result));
@@ -487,26 +562,120 @@ fail_alloc:
        return result;
 }
 
+static int dma_ioc0_map_pages(struct ps3_dma_region *r, unsigned long phys_addr,
+                             unsigned long len, struct dma_chunk **c_out,
+                             u64 iopte_flag)
+{
+       int result;
+       struct dma_chunk *c, *last;
+       int iopage, pages;
+       unsigned long offset;
+
+       DBG(KERN_ERR "%s: phy=%#lx, lpar%#lx, len=%#lx\n", __func__,
+           phys_addr, ps3_mm_phys_to_lpar(phys_addr), len);
+       c = kzalloc(sizeof(struct dma_chunk), GFP_ATOMIC);
+
+       if (!c) {
+               result = -ENOMEM;
+               goto fail_alloc;
+       }
+
+       c->region = r;
+       c->len = len;
+       c->lpar_addr = ps3_mm_phys_to_lpar(phys_addr);
+       /* allocate IO address */
+       if (list_empty(&r->chunk_list.head)) {
+               /* first one */
+               c->bus_addr = r->bus_addr;
+       } else {
+               /* derive from last bus addr*/
+               last  = list_entry(r->chunk_list.head.next,
+                                  struct dma_chunk, link);
+               c->bus_addr = last->bus_addr + last->len;
+               DBG("%s: last bus=%#lx, len=%#lx\n", __func__,
+                   last->bus_addr, last->len);
+       }
+
+       /* FIXME: check whether length exceeds region size */
+
+       /* build ioptes for the area */
+       pages = len >> r->page_size;
+       DBG("%s: pgsize=%#x len=%#lx pages=%#x iopteflag=%#lx\n", __func__,
+           r->page_size, r->len, pages, iopte_flag);
+       for (iopage = 0; iopage < pages; iopage++) {
+               offset = (1 << r->page_size) * iopage;
+               result = lv1_put_iopte(0,
+                                      c->bus_addr + offset,
+                                      c->lpar_addr + offset,
+                                      r->ioid,
+                                      iopte_flag);
+               if (result) {
+                       printk(KERN_WARNING "%s:%d: lv1_map_device_dma_region "
+                               "failed: %s\n", __func__, __LINE__,
+                               ps3_result(result));
+                       goto fail_map;
+               }
+               DBG("%s: pg=%d bus=%#lx, lpar=%#lx, ioid=%#x\n", __func__,
+                   iopage, c->bus_addr + offset, c->lpar_addr + offset,
+                   r->ioid);
+       }
+
+       /* be sure that last allocated one is inserted at head */
+       list_add(&c->link, &r->chunk_list.head);
+
+       *c_out = c;
+       DBG("%s: end\n", __func__);
+       return 0;
+
+fail_map:
+       for (iopage--; 0 <= iopage; iopage--) {
+               lv1_put_iopte(0,
+                             c->bus_addr + offset,
+                             c->lpar_addr + offset,
+                             r->ioid,
+                             0);
+       }
+       kfree(c);
+fail_alloc:
+       *c_out = NULL;
+       return result;
+}
+
 /**
- * dma_region_create - Create a device dma region.
+ * dma_sb_region_create - Create a device dma region.
  * @r: Pointer to a struct ps3_dma_region.
  *
  * This is the lowest level dma region create routine, and is the one that
  * will make the HV call to create the region.
  */
 
-static int dma_region_create(struct ps3_dma_region* r)
+static int dma_sb_region_create(struct ps3_dma_region *r)
 {
        int result;
 
-       r->len = _ALIGN_UP(map.total, 1 << r->page_size);
+       pr_info(" -> %s:%d:\n", __func__, __LINE__);
+
+       BUG_ON(!r);
+
+       if (!r->dev->bus_id) {
+               pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__,
+                       r->dev->bus_id, r->dev->dev_id);
+               return 0;
+       }
+
+       DBG("%s:%u: len = 0x%lx, page_size = %u, offset = 0x%lx\n", __func__,
+           __LINE__, r->len, r->page_size, r->offset);
+
+       BUG_ON(!r->len);
+       BUG_ON(!r->page_size);
+       BUG_ON(!r->region_ops);
+
        INIT_LIST_HEAD(&r->chunk_list.head);
        spin_lock_init(&r->chunk_list.lock);
 
-       result = lv1_allocate_device_dma_region(r->did.bus_id, r->did.dev_id,
-               r->len, r->page_size, r->region_type, &r->bus_addr);
-
-       dma_dump_region(r);
+       result = lv1_allocate_device_dma_region(r->dev->bus_id, r->dev->dev_id,
+               roundup_pow_of_two(r->len), r->page_size, r->region_type,
+               &r->bus_addr);
 
        if (result) {
                DBG("%s:%d: lv1_allocate_device_dma_region failed: %s\n",
@@ -517,6 +686,27 @@ static int dma_region_create(struct ps3_dma_region* r)
        return result;
 }
 
+static int dma_ioc0_region_create(struct ps3_dma_region *r)
+{
+       int result;
+
+       INIT_LIST_HEAD(&r->chunk_list.head);
+       spin_lock_init(&r->chunk_list.lock);
+
+       result = lv1_allocate_io_segment(0,
+                                        r->len,
+                                        r->page_size,
+                                        &r->bus_addr);
+       if (result) {
+               DBG("%s:%d: lv1_allocate_io_segment failed: %s\n",
+                       __func__, __LINE__, ps3_result(result));
+               r->len = r->bus_addr = 0;
+       }
+       DBG("%s: len=%#lx, pg=%d, bus=%#lx\n", __func__,
+           r->len, r->page_size, r->bus_addr);
+       return result;
+}
+
 /**
  * dma_region_free - Free a device dma region.
  * @r: Pointer to a struct ps3_dma_region.
@@ -525,31 +715,62 @@ static int dma_region_create(struct ps3_dma_region* r)
  * will make the HV call to free the region.
  */
 
-static int dma_region_free(struct ps3_dma_region* r)
+static int dma_sb_region_free(struct ps3_dma_region *r)
 {
        int result;
        struct dma_chunk *c;
        struct dma_chunk *tmp;
 
+       BUG_ON(!r);
+
+       if (!r->dev->bus_id) {
+               pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__,
+                       r->dev->bus_id, r->dev->dev_id);
+               return 0;
+       }
+
        list_for_each_entry_safe(c, tmp, &r->chunk_list.head, link) {
                list_del(&c->link);
-               dma_free_chunk(c);
+               dma_sb_free_chunk(c);
        }
 
-       result = lv1_free_device_dma_region(r->did.bus_id, r->did.dev_id,
+       result = lv1_free_device_dma_region(r->dev->bus_id, r->dev->dev_id,
                r->bus_addr);
 
        if (result)
                DBG("%s:%d: lv1_free_device_dma_region failed: %s\n",
                        __func__, __LINE__, ps3_result(result));
 
-       r->len = r->bus_addr = 0;
+       r->bus_addr = 0;
+
+       return result;
+}
+
+static int dma_ioc0_region_free(struct ps3_dma_region *r)
+{
+       int result;
+       struct dma_chunk *c, *n;
+
+       DBG("%s: start\n", __func__);
+       list_for_each_entry_safe(c, n, &r->chunk_list.head, link) {
+               list_del(&c->link);
+               dma_ioc0_free_chunk(c);
+       }
+
+       result = lv1_release_io_segment(0, r->bus_addr);
+
+       if (result)
+               DBG("%s:%d: lv1_free_device_dma_region failed: %s\n",
+                       __func__, __LINE__, ps3_result(result));
+
+       r->bus_addr = 0;
+       DBG("%s: end\n", __func__);
 
        return result;
 }
 
 /**
- * dma_map_area - Map an area of memory into a device dma region.
+ * dma_sb_map_area - Map an area of memory into a device dma region.
  * @r: Pointer to a struct ps3_dma_region.
  * @virt_addr: Starting virtual address of the area to map.
  * @len: Length in bytes of the area to map.
@@ -559,16 +780,19 @@ static int dma_region_free(struct ps3_dma_region* r)
  * This is the common dma mapping routine.
  */
 
-static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
-       unsigned long len, unsigned long *bus_addr)
+static int dma_sb_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
+          unsigned long len, unsigned long *bus_addr,
+          u64 iopte_flag)
 {
        int result;
        unsigned long flags;
        struct dma_chunk *c;
        unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr)
                : virt_addr;
-
-       *bus_addr = dma_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr));
+       unsigned long aligned_phys = _ALIGN_DOWN(phys_addr, 1 << r->page_size);
+       unsigned long aligned_len = _ALIGN_UP(len + phys_addr - aligned_phys,
+                                             1 << r->page_size);
+       *bus_addr = dma_sb_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr));
 
        if (!USE_DYNAMIC_DMA) {
                unsigned long lpar_addr = ps3_mm_phys_to_lpar(phys_addr);
@@ -588,17 +812,18 @@ static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
        c = dma_find_chunk(r, *bus_addr, len);
 
        if (c) {
+               DBG("%s:%d: reusing mapped chunk", __func__, __LINE__);
+               dma_dump_chunk(c);
                c->usage_count++;
                spin_unlock_irqrestore(&r->chunk_list.lock, flags);
                return 0;
        }
 
-       result = dma_map_pages(r, _ALIGN_DOWN(phys_addr, 1 << r->page_size),
-               _ALIGN_UP(len, 1 << r->page_size), &c);
+       result = dma_sb_map_pages(r, aligned_phys, aligned_len, &c, iopte_flag);
 
        if (result) {
                *bus_addr = 0;
-               DBG("%s:%d: dma_map_pages failed (%d)\n",
+               DBG("%s:%d: dma_sb_map_pages failed (%d)\n",
                        __func__, __LINE__, result);
                spin_unlock_irqrestore(&r->chunk_list.lock, flags);
                return result;
@@ -610,8 +835,57 @@ static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
        return result;
 }
 
+static int dma_ioc0_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
+            unsigned long len, unsigned long *bus_addr,
+            u64 iopte_flag)
+{
+       int result;
+       unsigned long flags;
+       struct dma_chunk *c;
+       unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr)
+               : virt_addr;
+       unsigned long aligned_phys = _ALIGN_DOWN(phys_addr, 1 << r->page_size);
+       unsigned long aligned_len = _ALIGN_UP(len + phys_addr - aligned_phys,
+                                             1 << r->page_size);
+
+       DBG(KERN_ERR "%s: vaddr=%#lx, len=%#lx\n", __func__,
+           virt_addr, len);
+       DBG(KERN_ERR "%s: ph=%#lx a_ph=%#lx a_l=%#lx\n", __func__,
+           phys_addr, aligned_phys, aligned_len);
+
+       spin_lock_irqsave(&r->chunk_list.lock, flags);
+       c = dma_find_chunk_lpar(r, ps3_mm_phys_to_lpar(phys_addr), len);
+
+       if (c) {
+               /* FIXME */
+               BUG();
+               *bus_addr = c->bus_addr + phys_addr - aligned_phys;
+               c->usage_count++;
+               spin_unlock_irqrestore(&r->chunk_list.lock, flags);
+               return 0;
+       }
+
+       result = dma_ioc0_map_pages(r, aligned_phys, aligned_len, &c,
+                                   iopte_flag);
+
+       if (result) {
+               *bus_addr = 0;
+               DBG("%s:%d: dma_ioc0_map_pages failed (%d)\n",
+                       __func__, __LINE__, result);
+               spin_unlock_irqrestore(&r->chunk_list.lock, flags);
+               return result;
+       }
+       *bus_addr = c->bus_addr + phys_addr - aligned_phys;
+       DBG("%s: va=%#lx pa=%#lx a_pa=%#lx bus=%#lx\n", __func__,
+           virt_addr, phys_addr, aligned_phys, *bus_addr);
+       c->usage_count = 1;
+
+       spin_unlock_irqrestore(&r->chunk_list.lock, flags);
+       return result;
+}
+
 /**
- * dma_unmap_area - Unmap an area of memory from a device dma region.
+ * dma_sb_unmap_area - Unmap an area of memory from a device dma region.
  * @r: Pointer to a struct ps3_dma_region.
  * @bus_addr: The starting ioc bus address of the area to unmap.
  * @len: Length in bytes of the area to unmap.
@@ -619,7 +893,7 @@ static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
  * This is the common dma unmap routine.
  */
 
-int dma_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr,
+static int dma_sb_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr,
        unsigned long len)
 {
        unsigned long flags;
@@ -631,7 +905,8 @@ int dma_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr,
        if (!c) {
                unsigned long aligned_bus = _ALIGN_DOWN(bus_addr,
                        1 << r->page_size);
-               unsigned long aligned_len = _ALIGN_UP(len, 1 << r->page_size);
+               unsigned long aligned_len = _ALIGN_UP(len + bus_addr
+                       - aligned_bus, 1 << r->page_size);
                DBG("%s:%d: not found: bus_addr %lxh\n",
                        __func__, __LINE__, bus_addr);
                DBG("%s:%d: not found: len %lxh\n",
@@ -647,94 +922,166 @@ int dma_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr,
 
        if (!c->usage_count) {
                list_del(&c->link);
-               dma_free_chunk(c);
+               dma_sb_free_chunk(c);
        }
 
        spin_unlock_irqrestore(&r->chunk_list.lock, flags);
        return 0;
 }
 
+static int dma_ioc0_unmap_area(struct ps3_dma_region *r,
+                       unsigned long bus_addr, unsigned long len)
+{
+       unsigned long flags;
+       struct dma_chunk *c;
+
+       DBG("%s: start a=%#lx l=%#lx\n", __func__, bus_addr, len);
+       spin_lock_irqsave(&r->chunk_list.lock, flags);
+       c = dma_find_chunk(r, bus_addr, len);
+
+       if (!c) {
+               unsigned long aligned_bus = _ALIGN_DOWN(bus_addr,
+                                                       1 << r->page_size);
+               unsigned long aligned_len = _ALIGN_UP(len + bus_addr
+                                                     - aligned_bus,
+                                                     1 << r->page_size);
+               DBG("%s:%d: not found: bus_addr %lxh\n",
+                   __func__, __LINE__, bus_addr);
+               DBG("%s:%d: not found: len %lxh\n",
+                   __func__, __LINE__, len);
+               DBG("%s:%d: not found: aligned_bus %lxh\n",
+                   __func__, __LINE__, aligned_bus);
+               DBG("%s:%d: not found: aligned_len %lxh\n",
+                   __func__, __LINE__, aligned_len);
+               BUG();
+       }
+
+       c->usage_count--;
+
+       if (!c->usage_count) {
+               list_del(&c->link);
+               dma_ioc0_free_chunk(c);
+       }
+
+       spin_unlock_irqrestore(&r->chunk_list.lock, flags);
+       DBG("%s: end\n", __func__);
+       return 0;
+}
+
 /**
- * dma_region_create_linear - Setup a linear dma maping for a device.
+ * dma_sb_region_create_linear - Setup a linear dma mapping for a device.
  * @r: Pointer to a struct ps3_dma_region.
  *
  * This routine creates an HV dma region for the device and maps all available
  * ram into the io controller bus address space.
  */
 
-static int dma_region_create_linear(struct ps3_dma_region *r)
+static int dma_sb_region_create_linear(struct ps3_dma_region *r)
 {
        int result;
-       unsigned long tmp;
-
-       /* force 16M dma pages for linear mapping */
-
-       if (r->page_size != PS3_DMA_16M) {
-               pr_info("%s:%d: forcing 16M pages for linear map\n",
-                       __func__, __LINE__);
-               r->page_size = PS3_DMA_16M;
+       unsigned long virt_addr, len, tmp;
+
+       if (r->len > 16*1024*1024) {    /* FIXME: need proper fix */
+               /* force 16M dma pages for linear mapping */
+               if (r->page_size != PS3_DMA_16M) {
+                       pr_info("%s:%d: forcing 16M pages for linear map\n",
+                               __func__, __LINE__);
+                       r->page_size = PS3_DMA_16M;
+                       r->len = _ALIGN_UP(r->len, 1 << r->page_size);
+               }
        }
 
-       result = dma_region_create(r);
+       result = dma_sb_region_create(r);
        BUG_ON(result);
 
-       result = dma_map_area(r, map.rm.base, map.rm.size, &tmp);
-       BUG_ON(result);
-
-       if (USE_LPAR_ADDR)
-               result = dma_map_area(r, map.r1.base, map.r1.size,
-                       &tmp);
-       else
-               result = dma_map_area(r, map.rm.size, map.r1.size,
-                       &tmp);
+       if (r->offset < map.rm.size) {
+               /* Map (part of) 1st RAM chunk */
+               virt_addr = map.rm.base + r->offset;
+               len = map.rm.size - r->offset;
+               if (len > r->len)
+                       len = r->len;
+               result = dma_sb_map_area(r, virt_addr, len, &tmp,
+                       IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M);
+               BUG_ON(result);
+       }
 
-       BUG_ON(result);
+       if (r->offset + r->len > map.rm.size) {
+               /* Map (part of) 2nd RAM chunk */
+               virt_addr = USE_LPAR_ADDR ? map.r1.base : map.rm.size;
+               len = r->len;
+               if (r->offset >= map.rm.size)
+                       virt_addr += r->offset - map.rm.size;
+               else
+                       len -= map.rm.size - r->offset;
+               result = dma_sb_map_area(r, virt_addr, len, &tmp,
+                       IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M);
+               BUG_ON(result);
+       }
 
        return result;
 }
 
 /**
- * dma_region_free_linear - Free a linear dma mapping for a device.
+ * dma_sb_region_free_linear - Free a linear dma mapping for a device.
  * @r: Pointer to a struct ps3_dma_region.
  *
  * This routine will unmap all mapped areas and free the HV dma region.
  */
 
-static int dma_region_free_linear(struct ps3_dma_region *r)
+static int dma_sb_region_free_linear(struct ps3_dma_region *r)
 {
        int result;
+       unsigned long bus_addr, len, lpar_addr;
+
+       if (r->offset < map.rm.size) {
+               /* Unmap (part of) 1st RAM chunk */
+               lpar_addr = map.rm.base + r->offset;
+               len = map.rm.size - r->offset;
+               if (len > r->len)
+                       len = r->len;
+               bus_addr = dma_sb_lpar_to_bus(r, lpar_addr);
+               result = dma_sb_unmap_area(r, bus_addr, len);
+               BUG_ON(result);
+       }
 
-       result = dma_unmap_area(r, dma_lpar_to_bus(r, 0), map.rm.size);
-       BUG_ON(result);
-
-       result = dma_unmap_area(r, dma_lpar_to_bus(r, map.r1.base),
-               map.r1.size);
-       BUG_ON(result);
+       if (r->offset + r->len > map.rm.size) {
+               /* Unmap (part of) 2nd RAM chunk */
+               lpar_addr = map.r1.base;
+               len = r->len;
+               if (r->offset >= map.rm.size)
+                       lpar_addr += r->offset - map.rm.size;
+               else
+                       len -= map.rm.size - r->offset;
+               bus_addr = dma_sb_lpar_to_bus(r, lpar_addr);
+               result = dma_sb_unmap_area(r, bus_addr, len);
+               BUG_ON(result);
+       }
 
-       result = dma_region_free(r);
+       result = dma_sb_region_free(r);
        BUG_ON(result);
 
        return result;
 }
 
 /**
- * dma_map_area_linear - Map an area of memory into a device dma region.
+ * dma_sb_map_area_linear - Map an area of memory into a device dma region.
  * @r: Pointer to a struct ps3_dma_region.
  * @virt_addr: Starting virtual address of the area to map.
  * @len: Length in bytes of the area to map.
  * @bus_addr: A pointer to return the starting ioc bus address of the area to
  * map.
  *
- * This routine just returns the coresponding bus address.  Actual mapping
+ * This routine just returns the corresponding bus address.  Actual mapping
  * occurs in dma_region_create_linear().
  */
 
-static int dma_map_area_linear(struct ps3_dma_region *r,
-       unsigned long virt_addr, unsigned long len, unsigned long *bus_addr)
+static int dma_sb_map_area_linear(struct ps3_dma_region *r,
+       unsigned long virt_addr, unsigned long len, unsigned long *bus_addr,
+       u64 iopte_flag)
 {
        unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr)
                : virt_addr;
-       *bus_addr = dma_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr));
+       *bus_addr = dma_sb_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr));
        return 0;
 }
 
@@ -744,42 +1091,98 @@ static int dma_map_area_linear(struct ps3_dma_region *r,
  * @bus_addr: The starting ioc bus address of the area to unmap.
  * @len: Length in bytes of the area to unmap.
  *
- * This routine does nothing.  Unmapping occurs in dma_region_free_linear().
+ * This routine does nothing.  Unmapping occurs in dma_sb_region_free_linear().
  */
 
-static int dma_unmap_area_linear(struct ps3_dma_region *r,
+static int dma_sb_unmap_area_linear(struct ps3_dma_region *r,
        unsigned long bus_addr, unsigned long len)
 {
        return 0;
+};
+
+static const struct ps3_dma_region_ops ps3_dma_sb_region_ops =  {
+       .create = dma_sb_region_create,
+       .free = dma_sb_region_free,
+       .map = dma_sb_map_area,
+       .unmap = dma_sb_unmap_area
+};
+
+static const struct ps3_dma_region_ops ps3_dma_sb_region_linear_ops = {
+       .create = dma_sb_region_create_linear,
+       .free = dma_sb_region_free_linear,
+       .map = dma_sb_map_area_linear,
+       .unmap = dma_sb_unmap_area_linear
+};
+
+static const struct ps3_dma_region_ops ps3_dma_ioc0_region_ops = {
+       .create = dma_ioc0_region_create,
+       .free = dma_ioc0_region_free,
+       .map = dma_ioc0_map_area,
+       .unmap = dma_ioc0_unmap_area
+};
+
+int ps3_dma_region_init(struct ps3_system_bus_device *dev,
+       struct ps3_dma_region *r, enum ps3_dma_page_size page_size,
+       enum ps3_dma_region_type region_type, void *addr, unsigned long len)
+{
+       unsigned long lpar_addr;
+
+       lpar_addr = addr ? ps3_mm_phys_to_lpar(__pa(addr)) : 0;
+
+       r->dev = dev;
+       r->page_size = page_size;
+       r->region_type = region_type;
+       r->offset = lpar_addr;
+       if (r->offset >= map.rm.size)
+               r->offset -= map.r1.offset;
+       r->len = len ? len : _ALIGN_UP(map.total, 1 << r->page_size);
+
+       switch (dev->dev_type) {
+       case PS3_DEVICE_TYPE_SB:
+               r->region_ops =  (USE_DYNAMIC_DMA)
+                       ? &ps3_dma_sb_region_ops
+                       : &ps3_dma_sb_region_linear_ops;
+               break;
+       case PS3_DEVICE_TYPE_IOC0:
+               r->region_ops = &ps3_dma_ioc0_region_ops;
+               break;
+       default:
+               BUG();
+               return -EINVAL;
+       }
+       return 0;
 }
+EXPORT_SYMBOL(ps3_dma_region_init);
 
 int ps3_dma_region_create(struct ps3_dma_region *r)
 {
-       return (USE_DYNAMIC_DMA)
-               ? dma_region_create(r)
-               : dma_region_create_linear(r);
+       BUG_ON(!r);
+       BUG_ON(!r->region_ops);
+       BUG_ON(!r->region_ops->create);
+       return r->region_ops->create(r);
 }
+EXPORT_SYMBOL(ps3_dma_region_create);
 
 int ps3_dma_region_free(struct ps3_dma_region *r)
 {
-       return (USE_DYNAMIC_DMA)
-               ? dma_region_free(r)
-               : dma_region_free_linear(r);
+       BUG_ON(!r);
+       BUG_ON(!r->region_ops);
+       BUG_ON(!r->region_ops->free);
+       return r->region_ops->free(r);
 }
+EXPORT_SYMBOL(ps3_dma_region_free);
 
 int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr,
-       unsigned long len, unsigned long *bus_addr)
+       unsigned long len, unsigned long *bus_addr,
+       u64 iopte_flag)
 {
-       return (USE_DYNAMIC_DMA)
-               ? dma_map_area(r, virt_addr, len, bus_addr)
-               : dma_map_area_linear(r, virt_addr, len, bus_addr);
+       return r->region_ops->map(r, virt_addr, len, bus_addr, iopte_flag);
 }
 
 int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr,
        unsigned long len)
 {
-       return (USE_DYNAMIC_DMA) ? dma_unmap_area(r, bus_addr, len)
-               : dma_unmap_area_linear(r, bus_addr, len);
+       return r->region_ops->unmap(r, bus_addr, len);
 }
 
 /*============================================================================*/
@@ -810,12 +1213,13 @@ void __init ps3_mm_init(void)
        BUG_ON(map.rm.base);
        BUG_ON(!map.rm.size);
 
-       lmb_add(map.rm.base, map.rm.size);
-       lmb_analyze();
 
        /* arrange to do this in ps3_mm_add_memory */
        ps3_mm_region_create(&map.r1, map.total - map.rm.size);
 
+       /* correct map.total for the real total amount of memory we use */
+       map.total = map.rm.size + map.r1.size;
+
        DBG(" <- %s:%d\n", __func__, __LINE__);
 }
 
index 5c3da08bc0c4cac0935379c7d40107ec21fcf69e..b70e474014f028c9da8c938d164e7c7d4defcd26 100644 (file)
@@ -133,7 +133,7 @@ struct saved_params {
 } static saved_params;
 
 #define dump_header(_a) _dump_header(_a, __func__, __LINE__)
-static void _dump_header(const struct os_area_header __iomem *h, const char* func,
+static void _dump_header(const struct os_area_header *h, const char *func,
        int line)
 {
        pr_debug("%s:%d: h.magic_num:         '%s'\n", func, line,
@@ -151,7 +151,7 @@ static void _dump_header(const struct os_area_header __iomem *h, const char* fun
 }
 
 #define dump_params(_a) _dump_params(_a, __func__, __LINE__)
-static void _dump_params(const struct os_area_params __iomem *p, const char* func,
+static void _dump_params(const struct os_area_params *p, const char *func,
        int line)
 {
        pr_debug("%s:%d: p.boot_flag:       %u\n", func, line, p->boot_flag);
index ca04f03305c76751307389bc94329c936a98872d..87d52060fec0a44276aa3cbc5fc4517bfc2cccb6 100644 (file)
@@ -41,6 +41,7 @@ void ps3_mm_shutdown(void);
 /* irq */
 
 void ps3_init_IRQ(void);
+void ps3_shutdown_IRQ(int cpu);
 void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq);
 
 /* smp */
@@ -82,6 +83,7 @@ enum ps3_dev_type {
        PS3_DEV_TYPE_STOR_ROM = TYPE_ROM,       /* 5 */
        PS3_DEV_TYPE_SB_GPIO = 6,
        PS3_DEV_TYPE_STOR_FLASH = TYPE_RBC,     /* 14 */
+       PS3_DEV_TYPE_NOACCESS = 255,
 };
 
 int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
@@ -129,24 +131,28 @@ int ps3_repository_read_dev_reg(unsigned int bus_index,
 /* repository bus enumerators */
 
 struct ps3_repository_device {
+       enum ps3_bus_type bus_type;
        unsigned int bus_index;
+       unsigned int bus_id;
+       enum ps3_dev_type dev_type;
        unsigned int dev_index;
-       struct ps3_device_id did;
+       unsigned int dev_id;
 };
 
-int ps3_repository_find_device(enum ps3_bus_type bus_type,
-       enum ps3_dev_type dev_type,
-       const struct ps3_repository_device *start_dev,
-       struct ps3_repository_device *dev);
-static inline int ps3_repository_find_first_device(
-       enum ps3_bus_type bus_type, enum ps3_dev_type dev_type,
-       struct ps3_repository_device *dev)
+static inline struct ps3_repository_device *ps3_repository_bump_device(
+       struct ps3_repository_device *repo)
 {
-       return ps3_repository_find_device(bus_type, dev_type, NULL, dev);
+       repo->dev_index++;
+       return repo;
 }
-int ps3_repository_find_interrupt(const struct ps3_repository_device *dev,
+int ps3_repository_find_device(struct ps3_repository_device *repo);
+int ps3_repository_find_devices(enum ps3_bus_type bus_type,
+       int (*callback)(const struct ps3_repository_device *repo));
+int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from,
+       unsigned int *bus_index);
+int ps3_repository_find_interrupt(const struct ps3_repository_device *repo,
        enum ps3_interrupt_type intr_type, unsigned int *interrupt_id);
-int ps3_repository_find_reg(const struct ps3_repository_device *dev,
+int ps3_repository_find_reg(const struct ps3_repository_device *repo,
        enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len);
 
 /* repository block device info */
@@ -216,4 +222,19 @@ int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id);
 int ps3_repository_read_spu_resource_id(unsigned int res_index,
        enum ps3_spu_resource_type* resource_type, unsigned int *resource_id);
 
+/* repository vuart info */
+
+int ps3_repository_read_vuart_av_port(unsigned int *port);
+int ps3_repository_read_vuart_sysmgr_port(unsigned int *port);
+
+/* Page table entries */
+#define IOPTE_PP_W             0x8000000000000000ul /* protection: write */
+#define IOPTE_PP_R             0x4000000000000000ul /* protection: read */
+#define IOPTE_M                        0x2000000000000000ul /* coherency required */
+#define IOPTE_SO_R             0x1000000000000000ul /* ordering: writes */
+#define IOPTE_SO_RW             0x1800000000000000ul /* ordering: r & w */
+#define IOPTE_RPN_Mask         0x07fffffffffff000ul /* RPN */
+#define IOPTE_H                        0x0000000000000800ul /* cache hint */
+#define IOPTE_IOID_Mask                0x00000000000007fful /* ioid */
+
 #endif
index ae586a0e5d3f9c75771058b7c22b9279fc8cb237..8cc37cfea0f22306e487709a0f2f49328f57c952 100644 (file)
@@ -138,7 +138,7 @@ static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
                pr_debug("%s:%d: lv1_get_repository_node_value failed: %s\n",
                        __func__, __LINE__, ps3_result(result));
                dump_node_name(lpar_id, n1, n2, n3, n4);
-               return result;
+               return -ENOENT;
        }
 
        dump_node(lpar_id, n1, n2, n3, n4, v1, v2);
@@ -155,7 +155,7 @@ static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
                pr_debug("%s:%d: warning: discarding non-zero v2: %016lx\n",
                        __func__, __LINE__, v2);
 
-       return result;
+       return 0;
 }
 
 int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
@@ -314,324 +314,140 @@ int ps3_repository_read_dev_reg(unsigned int bus_index,
                reg_index, bus_addr, len);
 }
 
-#if defined(DEBUG)
-int ps3_repository_dump_resource_info(unsigned int bus_index,
-       unsigned int dev_index)
-{
-       int result = 0;
-       unsigned int res_index;
 
-       pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
-               bus_index, dev_index);
 
-       for (res_index = 0; res_index < 10; res_index++) {
-               enum ps3_interrupt_type intr_type;
-               unsigned int interrupt_id;
+int ps3_repository_find_device(struct ps3_repository_device *repo)
+{
+       int result;
+       struct ps3_repository_device tmp = *repo;
+       unsigned int num_dev;
 
-               result = ps3_repository_read_dev_intr(bus_index, dev_index,
-                       res_index, &intr_type, &interrupt_id);
+       BUG_ON(repo->bus_index > 10);
+       BUG_ON(repo->dev_index > 10);
 
-               if (result) {
-                       if (result !=  LV1_NO_ENTRY)
-                               pr_debug("%s:%d ps3_repository_read_dev_intr"
-                                       " (%u:%u) failed\n", __func__, __LINE__,
-                                       bus_index, dev_index);
-                       break;
-               }
+       result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev);
 
-               pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n",
-                       __func__, __LINE__, bus_index, dev_index, intr_type,
-                       interrupt_id);
+       if (result) {
+               pr_debug("%s:%d read_bus_num_dev failed\n", __func__, __LINE__);
+               return result;
        }
 
-       for (res_index = 0; res_index < 10; res_index++) {
-               enum ps3_reg_type reg_type;
-               u64 bus_addr;
-               u64 len;
-
-               result = ps3_repository_read_dev_reg(bus_index, dev_index,
-                       res_index, &reg_type, &bus_addr, &len);
+       pr_debug("%s:%d: bus_type %u, bus_index %u, bus_id %u, num_dev %u\n",
+               __func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id,
+               num_dev);
 
-               if (result) {
-                       if (result !=  LV1_NO_ENTRY)
-                               pr_debug("%s:%d ps3_repository_read_dev_reg"
-                                       " (%u:%u) failed\n", __func__, __LINE__,
-                                       bus_index, dev_index);
-                       break;
-               }
-
-               pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n",
-                       __func__, __LINE__, bus_index, dev_index, reg_type,
-                       bus_addr, len);
+       if (tmp.dev_index >= num_dev) {
+               pr_debug("%s:%d: no device found\n", __func__, __LINE__);
+               return -ENODEV;
        }
 
-       pr_debug(" <- %s:%d\n", __func__, __LINE__);
-       return result;
-}
-
-static int dump_stor_dev_info(unsigned int bus_index, unsigned int dev_index)
-{
-       int result = 0;
-       unsigned int num_regions, region_index;
-       u64 port, blk_size, num_blocks;
-
-       pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
-               bus_index, dev_index);
+       result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index,
+               &tmp.dev_type);
 
-       result = ps3_repository_read_stor_dev_info(bus_index, dev_index, &port,
-               &blk_size, &num_blocks, &num_regions);
        if (result) {
-               pr_debug("%s:%d ps3_repository_read_stor_dev_info"
-                       " (%u:%u) failed\n", __func__, __LINE__,
-                       bus_index, dev_index);
-               goto out;
+               pr_debug("%s:%d read_dev_type failed\n", __func__, __LINE__);
+               return result;
        }
 
-       pr_debug("%s:%d  (%u:%u): port %lu, blk_size %lu, num_blocks "
-                "%lu, num_regions %u\n",
-                __func__, __LINE__, bus_index, dev_index, port,
-                blk_size, num_blocks, num_regions);
-
-       for (region_index = 0; region_index < num_regions; region_index++) {
-               unsigned int region_id;
-               u64 region_start, region_size;
-
-               result = ps3_repository_read_stor_dev_region(bus_index,
-                       dev_index, region_index, &region_id, &region_start,
-                       &region_size);
-               if (result) {
-                        pr_debug("%s:%d ps3_repository_read_stor_dev_region"
-                                 " (%u:%u) failed\n", __func__, __LINE__,
-                                 bus_index, dev_index);
-                       break;
-               }
+       result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index,
+               &tmp.dev_id);
 
-               pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n",
-                        __func__, __LINE__, bus_index, dev_index, region_id,
-                        region_start, region_size);
+       if (result) {
+               pr_debug("%s:%d ps3_repository_read_dev_id failed\n", __func__,
+               __LINE__);
+               return result;
        }
 
-out:
-       pr_debug(" <- %s:%d\n", __func__, __LINE__);
-       return result;
-}
-
-static int dump_device_info(unsigned int bus_index, enum ps3_bus_type bus_type,
-                           unsigned int num_dev)
-{
-       int result = 0;
-       unsigned int dev_index;
-
-       pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, bus_index);
-
-       for (dev_index = 0; dev_index < num_dev; dev_index++) {
-               enum ps3_dev_type dev_type;
-               unsigned int dev_id;
-
-               result = ps3_repository_read_dev_type(bus_index, dev_index,
-                       &dev_type);
-
-               if (result) {
-                       pr_debug("%s:%d ps3_repository_read_dev_type"
-                               " (%u:%u) failed\n", __func__, __LINE__,
-                               bus_index, dev_index);
-                       break;
-               }
-
-               result = ps3_repository_read_dev_id(bus_index, dev_index,
-                       &dev_id);
-
-               if (result) {
-                       pr_debug("%s:%d ps3_repository_read_dev_id"
-                               " (%u:%u) failed\n", __func__, __LINE__,
-                               bus_index, dev_index);
-                       continue;
-               }
+       pr_debug("%s:%d: found: dev_type %u, dev_index %u, dev_id %u\n",
+               __func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id);
 
-               pr_debug("%s:%d  (%u:%u): dev_type %u, dev_id %u\n", __func__,
-                       __LINE__, bus_index, dev_index, dev_type, dev_id);
-
-               ps3_repository_dump_resource_info(bus_index, dev_index);
-
-               if (bus_type == PS3_BUS_TYPE_STORAGE)
-                       dump_stor_dev_info(bus_index, dev_index);
-       }
-
-       pr_debug(" <- %s:%d\n", __func__, __LINE__);
-       return result;
+       *repo = tmp;
+       return 0;
 }
 
-int ps3_repository_dump_bus_info(void)
+int __devinit ps3_repository_find_devices(enum ps3_bus_type bus_type,
+       int (*callback)(const struct ps3_repository_device *repo))
 {
        int result = 0;
-       unsigned int bus_index;
+       struct ps3_repository_device repo;
 
-       pr_debug(" -> %s:%d\n", __func__, __LINE__);
+       pr_debug(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type);
 
-       for (bus_index = 0; bus_index < 10; bus_index++) {
-               enum ps3_bus_type bus_type;
-               unsigned int bus_id;
-               unsigned int num_dev;
+       for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) {
 
-               result = ps3_repository_read_bus_type(bus_index, &bus_type);
+               result = ps3_repository_read_bus_type(repo.bus_index,
+                       &repo.bus_type);
 
                if (result) {
                        pr_debug("%s:%d read_bus_type(%u) failed\n",
-                               __func__, __LINE__, bus_index);
+                               __func__, __LINE__, repo.bus_index);
                        break;
                }
 
-               result = ps3_repository_read_bus_id(bus_index, &bus_id);
-
-               if (result) {
-                       pr_debug("%s:%d read_bus_id(%u) failed\n",
-                               __func__, __LINE__, bus_index);
+               if (repo.bus_type != bus_type) {
+                       pr_debug("%s:%d: skip, bus_type %u\n", __func__,
+                               __LINE__, repo.bus_type);
                        continue;
                }
 
-               if (bus_index != bus_id)
-                       pr_debug("%s:%d bus_index != bus_id\n",
-                               __func__, __LINE__);
-
-               result = ps3_repository_read_bus_num_dev(bus_index, &num_dev);
+               result = ps3_repository_read_bus_id(repo.bus_index,
+                       &repo.bus_id);
 
                if (result) {
-                       pr_debug("%s:%d read_bus_num_dev(%u) failed\n",
-                               __func__, __LINE__, bus_index);
+                       pr_debug("%s:%d read_bus_id(%u) failed\n",
+                               __func__, __LINE__, repo.bus_index);
                        continue;
                }
 
-               pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n",
-                       __func__, __LINE__, bus_index, bus_type, bus_id,
-                       num_dev);
+               for (repo.dev_index = 0; ; repo.dev_index++) {
+                       result = ps3_repository_find_device(&repo);
 
-               dump_device_info(bus_index, bus_type, num_dev);
-       }
+                       if (result == -ENODEV) {
+                               result = 0;
+                               break;
+                       } else if (result)
+                               break;
 
-       pr_debug(" <- %s:%d\n", __func__, __LINE__);
-       return result;
-}
-#endif /* defined(DEBUG) */
-
-static int find_device(unsigned int bus_index, unsigned int num_dev,
-       unsigned int start_dev_index, enum ps3_dev_type dev_type,
-       struct ps3_repository_device *dev)
-{
-       int result = 0;
-       unsigned int dev_index;
+                       result = callback(&repo);
 
-       pr_debug("%s:%d: find dev_type %u\n", __func__, __LINE__, dev_type);
-
-       dev->dev_index = UINT_MAX;
-
-       for (dev_index = start_dev_index; dev_index < num_dev; dev_index++) {
-               enum ps3_dev_type x;
-
-               result = ps3_repository_read_dev_type(bus_index, dev_index,
-                       &x);
-
-               if (result) {
-                       pr_debug("%s:%d read_dev_type failed\n",
-                               __func__, __LINE__);
-                       return result;
+                       if (result) {
+                               pr_debug("%s:%d: abort at callback\n", __func__,
+                                       __LINE__);
+                               break;
+                       }
                }
-
-               if (x == dev_type)
-                       break;
-       }
-
-       if (dev_index == num_dev)
-               return -1;
-
-       pr_debug("%s:%d: found dev_type %u at dev_index %u\n",
-               __func__, __LINE__, dev_type, dev_index);
-
-       result = ps3_repository_read_dev_id(bus_index, dev_index,
-               &dev->did.dev_id);
-
-       if (result) {
-               pr_debug("%s:%d read_dev_id failed\n",
-                       __func__, __LINE__);
-               return result;
+               break;
        }
 
-       dev->dev_index = dev_index;
-
-       pr_debug("%s:%d found: dev_id %u\n", __func__, __LINE__,
-               dev->did.dev_id);
-
+       pr_debug(" <- %s:%d\n", __func__, __LINE__);
        return result;
 }
 
-int ps3_repository_find_device (enum ps3_bus_type bus_type,
-       enum ps3_dev_type dev_type,
-       const struct ps3_repository_device *start_dev,
-       struct ps3_repository_device *dev)
+int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from,
+       unsigned int *bus_index)
 {
-       int result = 0;
-       unsigned int bus_index;
-       unsigned int num_dev;
-
-       pr_debug("%s:%d: find bus_type %u, dev_type %u\n", __func__, __LINE__,
-               bus_type, dev_type);
-
-       BUG_ON(start_dev && start_dev->bus_index > 10);
-
-       for (bus_index = start_dev ? start_dev->bus_index : 0; bus_index < 10;
-               bus_index++) {
-               enum ps3_bus_type x;
-
-               result = ps3_repository_read_bus_type(bus_index, &x);
+       unsigned int i;
+       enum ps3_bus_type type;
+       int error;
 
-               if (result) {
+       for (i = from; i < 10; i++) {
+               error = ps3_repository_read_bus_type(i, &type);
+               if (error) {
                        pr_debug("%s:%d read_bus_type failed\n",
                                __func__, __LINE__);
-                       dev->bus_index = UINT_MAX;
-                       return result;
+                       *bus_index = UINT_MAX;
+                       return error;
+               }
+               if (type == bus_type) {
+                       *bus_index = i;
+                       return 0;
                }
-               if (x == bus_type)
-                       break;
-       }
-
-       if (bus_index >= 10)
-               return -ENODEV;
-
-       pr_debug("%s:%d: found bus_type %u at bus_index %u\n",
-               __func__, __LINE__, bus_type, bus_index);
-
-       result = ps3_repository_read_bus_num_dev(bus_index, &num_dev);
-
-       if (result) {
-               pr_debug("%s:%d read_bus_num_dev failed\n",
-                       __func__, __LINE__);
-               return result;
-       }
-
-       result = find_device(bus_index, num_dev, start_dev
-               ? start_dev->dev_index + 1 : 0, dev_type, dev);
-
-       if (result) {
-               pr_debug("%s:%d get_did failed\n", __func__, __LINE__);
-               return result;
-       }
-
-       result = ps3_repository_read_bus_id(bus_index, &dev->did.bus_id);
-
-       if (result) {
-               pr_debug("%s:%d read_bus_id failed\n",
-                       __func__, __LINE__);
-               return result;
        }
-
-       dev->bus_index = bus_index;
-
-       pr_debug("%s:%d found: bus_id %u, dev_id %u\n",
-               __func__, __LINE__, dev->did.bus_id, dev->did.dev_id);
-
-       return result;
+       *bus_index = UINT_MAX;
+       return -ENODEV;
 }
 
-int ps3_repository_find_interrupt(const struct ps3_repository_device *dev,
+int ps3_repository_find_interrupt(const struct ps3_repository_device *repo,
        enum ps3_interrupt_type intr_type, unsigned int *interrupt_id)
 {
        int result = 0;
@@ -645,8 +461,8 @@ int ps3_repository_find_interrupt(const struct ps3_repository_device *dev,
                enum ps3_interrupt_type t;
                unsigned int id;
 
-               result = ps3_repository_read_dev_intr(dev->bus_index,
-                       dev->dev_index, res_index, &t, &id);
+               result = ps3_repository_read_dev_intr(repo->bus_index,
+                       repo->dev_index, res_index, &t, &id);
 
                if (result) {
                        pr_debug("%s:%d read_dev_intr failed\n",
@@ -669,7 +485,7 @@ int ps3_repository_find_interrupt(const struct ps3_repository_device *dev,
        return result;
 }
 
-int ps3_repository_find_reg(const struct ps3_repository_device *dev,
+int ps3_repository_find_reg(const struct ps3_repository_device *repo,
        enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len)
 {
        int result = 0;
@@ -684,8 +500,8 @@ int ps3_repository_find_reg(const struct ps3_repository_device *dev,
                u64 a;
                u64 l;
 
-               result = ps3_repository_read_dev_reg(dev->bus_index,
-                       dev->dev_index, res_index, &t, &a, &l);
+               result = ps3_repository_read_dev_reg(repo->bus_index,
+                       repo->dev_index, res_index, &t, &a, &l);
 
                if (result) {
                        pr_debug("%s:%d read_dev_reg failed\n",
@@ -965,6 +781,36 @@ int ps3_repository_read_boot_dat_size(unsigned int *size)
        return result;
 }
 
+int ps3_repository_read_vuart_av_port(unsigned int *port)
+{
+       int result;
+       u64 v1;
+
+       result = read_node(PS3_LPAR_ID_CURRENT,
+               make_first_field("bi", 0),
+               make_field("vir_uart", 0),
+               make_field("port", 0),
+               make_field("avset", 0),
+               &v1, 0);
+       *port = v1;
+       return result;
+}
+
+int ps3_repository_read_vuart_sysmgr_port(unsigned int *port)
+{
+       int result;
+       u64 v1;
+
+       result = read_node(PS3_LPAR_ID_CURRENT,
+               make_first_field("bi", 0),
+               make_field("vir_uart", 0),
+               make_field("port", 0),
+               make_field("sysmgr", 0),
+               &v1, 0);
+       *port = v1;
+       return result;
+}
+
 /**
   * ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area.
   * address: lpar address of cell_ext_os_area
@@ -1026,3 +872,205 @@ int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq)
        return result ? result
                : ps3_repository_read_tb_freq(node_id, tb_freq);
 }
+
+#if defined(DEBUG)
+
+int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo)
+{
+       int result = 0;
+       unsigned int res_index;
+
+       pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
+               repo->bus_index, repo->dev_index);
+
+       for (res_index = 0; res_index < 10; res_index++) {
+               enum ps3_interrupt_type intr_type;
+               unsigned int interrupt_id;
+
+               result = ps3_repository_read_dev_intr(repo->bus_index,
+                       repo->dev_index, res_index, &intr_type, &interrupt_id);
+
+               if (result) {
+                       if (result !=  LV1_NO_ENTRY)
+                               pr_debug("%s:%d ps3_repository_read_dev_intr"
+                                       " (%u:%u) failed\n", __func__, __LINE__,
+                                       repo->bus_index, repo->dev_index);
+                       break;
+               }
+
+               pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n",
+                       __func__, __LINE__, repo->bus_index, repo->dev_index,
+                       intr_type, interrupt_id);
+       }
+
+       for (res_index = 0; res_index < 10; res_index++) {
+               enum ps3_reg_type reg_type;
+               u64 bus_addr;
+               u64 len;
+
+               result = ps3_repository_read_dev_reg(repo->bus_index,
+                       repo->dev_index, res_index, &reg_type, &bus_addr, &len);
+
+               if (result) {
+                       if (result !=  LV1_NO_ENTRY)
+                               pr_debug("%s:%d ps3_repository_read_dev_reg"
+                                       " (%u:%u) failed\n", __func__, __LINE__,
+                                       repo->bus_index, repo->dev_index);
+                       break;
+               }
+
+               pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n",
+                       __func__, __LINE__, repo->bus_index, repo->dev_index,
+                       reg_type, bus_addr, len);
+       }
+
+       pr_debug(" <- %s:%d\n", __func__, __LINE__);
+       return result;
+}
+
+static int dump_stor_dev_info(struct ps3_repository_device *repo)
+{
+       int result = 0;
+       unsigned int num_regions, region_index;
+       u64 port, blk_size, num_blocks;
+
+       pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
+               repo->bus_index, repo->dev_index);
+
+       result = ps3_repository_read_stor_dev_info(repo->bus_index,
+               repo->dev_index, &port, &blk_size, &num_blocks, &num_regions);
+       if (result) {
+               pr_debug("%s:%d ps3_repository_read_stor_dev_info"
+                       " (%u:%u) failed\n", __func__, __LINE__,
+                       repo->bus_index, repo->dev_index);
+               goto out;
+       }
+
+       pr_debug("%s:%d  (%u:%u): port %lu, blk_size %lu, num_blocks "
+                "%lu, num_regions %u\n",
+                __func__, __LINE__, repo->bus_index, repo->dev_index, port,
+                blk_size, num_blocks, num_regions);
+
+       for (region_index = 0; region_index < num_regions; region_index++) {
+               unsigned int region_id;
+               u64 region_start, region_size;
+
+               result = ps3_repository_read_stor_dev_region(repo->bus_index,
+                       repo->dev_index, region_index, &region_id,
+                       &region_start, &region_size);
+               if (result) {
+                        pr_debug("%s:%d ps3_repository_read_stor_dev_region"
+                                 " (%u:%u) failed\n", __func__, __LINE__,
+                                 repo->bus_index, repo->dev_index);
+                       break;
+               }
+
+               pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n",
+                       __func__, __LINE__, repo->bus_index, repo->dev_index,
+                       region_id, region_start, region_size);
+       }
+
+out:
+       pr_debug(" <- %s:%d\n", __func__, __LINE__);
+       return result;
+}
+
+static int dump_device_info(struct ps3_repository_device *repo,
+       unsigned int num_dev)
+{
+       int result = 0;
+
+       pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, repo->bus_index);
+
+       for (repo->dev_index = 0; repo->dev_index < num_dev;
+               repo->dev_index++) {
+
+               result = ps3_repository_read_dev_type(repo->bus_index,
+                       repo->dev_index, &repo->dev_type);
+
+               if (result) {
+                       pr_debug("%s:%d ps3_repository_read_dev_type"
+                               " (%u:%u) failed\n", __func__, __LINE__,
+                               repo->bus_index, repo->dev_index);
+                       break;
+               }
+
+               result = ps3_repository_read_dev_id(repo->bus_index,
+                       repo->dev_index, &repo->dev_id);
+
+               if (result) {
+                       pr_debug("%s:%d ps3_repository_read_dev_id"
+                               " (%u:%u) failed\n", __func__, __LINE__,
+                               repo->bus_index, repo->dev_index);
+                       continue;
+               }
+
+               pr_debug("%s:%d  (%u:%u): dev_type %u, dev_id %u\n", __func__,
+                       __LINE__, repo->bus_index, repo->dev_index,
+                       repo->dev_type, repo->dev_id);
+
+               ps3_repository_dump_resource_info(repo);
+
+               if (repo->bus_type == PS3_BUS_TYPE_STORAGE)
+                       dump_stor_dev_info(repo);
+       }
+
+       pr_debug(" <- %s:%d\n", __func__, __LINE__);
+       return result;
+}
+
+int ps3_repository_dump_bus_info(void)
+{
+       int result = 0;
+       struct ps3_repository_device repo;
+
+       pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+       memset(&repo, 0, sizeof(repo));
+
+       for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) {
+               unsigned int num_dev;
+
+               result = ps3_repository_read_bus_type(repo.bus_index,
+                       &repo.bus_type);
+
+               if (result) {
+                       pr_debug("%s:%d read_bus_type(%u) failed\n",
+                               __func__, __LINE__, repo.bus_index);
+                       break;
+               }
+
+               result = ps3_repository_read_bus_id(repo.bus_index,
+                       &repo.bus_id);
+
+               if (result) {
+                       pr_debug("%s:%d read_bus_id(%u) failed\n",
+                               __func__, __LINE__, repo.bus_index);
+                       continue;
+               }
+
+               if (repo.bus_index != repo.bus_id)
+                       pr_debug("%s:%d bus_index != bus_id\n",
+                               __func__, __LINE__);
+
+               result = ps3_repository_read_bus_num_dev(repo.bus_index,
+                       &num_dev);
+
+               if (result) {
+                       pr_debug("%s:%d read_bus_num_dev(%u) failed\n",
+                               __func__, __LINE__, repo.bus_index);
+                       continue;
+               }
+
+               pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n",
+                       __func__, __LINE__, repo.bus_index, repo.bus_type,
+                       repo.bus_id, num_dev);
+
+               dump_device_info(&repo, num_dev);
+       }
+
+       pr_debug(" <- %s:%d\n", __func__, __LINE__);
+       return result;
+}
+
+#endif /* defined(DEBUG) */
index 9353967666216a33c08520755ce50d1fc65709a9..aa05288de64e13b89aadecc06191ea08b474c7bc 100644 (file)
 #include "platform.h"
 
 #if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
 #else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
 #endif
 
 #if !defined(CONFIG_SMP)
 static void smp_send_stop(void) {}
 #endif
 
-int ps3_get_firmware_version(union ps3_firmware_version *v)
+static union ps3_firmware_version ps3_firmware_version;
+
+void ps3_get_firmware_version(union ps3_firmware_version *v)
 {
-       int result = lv1_get_version_info(&v->raw);
+       *v = ps3_firmware_version;
+}
+EXPORT_SYMBOL_GPL(ps3_get_firmware_version);
 
-       if (result) {
-               v->raw = 0;
-               return -1;
-       }
+int ps3_compare_firmware_version(u16 major, u16 minor, u16 rev)
+{
+       union ps3_firmware_version x;
+
+       x.pad = 0;
+       x.major = major;
+       x.minor = minor;
+       x.rev = rev;
 
-       return result;
+       return (ps3_firmware_version.raw - x.raw);
 }
-EXPORT_SYMBOL_GPL(ps3_get_firmware_version);
+EXPORT_SYMBOL_GPL(ps3_compare_firmware_version);
 
 static void ps3_power_save(void)
 {
@@ -99,7 +107,8 @@ static void ps3_panic(char *str)
        while(1);
 }
 
-#ifdef CONFIG_FB_PS3
+#if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE) || \
+    defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE)
 static void prealloc(struct ps3_prealloc *p)
 {
        if (!p->size)
@@ -115,12 +124,15 @@ static void prealloc(struct ps3_prealloc *p)
        printk(KERN_INFO "%s: %lu bytes at %p\n", p->name, p->size,
               p->address);
 }
+#endif
 
+#if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE)
 struct ps3_prealloc ps3fb_videomemory = {
-    .name = "ps3fb videomemory",
-    .size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024,
-    .align = 1024*1024                 /* the GPU requires 1 MiB alignment */
+       .name = "ps3fb videomemory",
+       .size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024,
+       .align = 1024*1024              /* the GPU requires 1 MiB alignment */
 };
+EXPORT_SYMBOL_GPL(ps3fb_videomemory);
 #define prealloc_ps3fb_videomemory()   prealloc(&ps3fb_videomemory)
 
 static int __init early_parse_ps3fb(char *p)
@@ -137,6 +149,30 @@ early_param("ps3fb", early_parse_ps3fb);
 #define prealloc_ps3fb_videomemory()   do { } while (0)
 #endif
 
+#if defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE)
+struct ps3_prealloc ps3flash_bounce_buffer = {
+       .name = "ps3flash bounce buffer",
+       .size = 256*1024,
+       .align = 256*1024
+};
+EXPORT_SYMBOL_GPL(ps3flash_bounce_buffer);
+#define prealloc_ps3flash_bounce_buffer()      prealloc(&ps3flash_bounce_buffer)
+
+static int __init early_parse_ps3flash(char *p)
+{
+       if (!p)
+               return 1;
+
+       if (!strcmp(p, "off"))
+               ps3flash_bounce_buffer.size = 0;
+
+       return 0;
+}
+early_param("ps3flash", early_parse_ps3flash);
+#else
+#define prealloc_ps3flash_bounce_buffer()      do { } while (0)
+#endif
+
 static int ps3_set_dabr(u64 dabr)
 {
        enum {DABR_USER = 1, DABR_KERNEL = 2,};
@@ -146,13 +182,13 @@ static int ps3_set_dabr(u64 dabr)
 
 static void __init ps3_setup_arch(void)
 {
-       union ps3_firmware_version v;
 
        DBG(" -> %s:%d\n", __func__, __LINE__);
 
-       ps3_get_firmware_version(&v);
-       printk(KERN_INFO "PS3 firmware version %u.%u.%u\n", v.major, v.minor,
-               v.rev);
+       lv1_get_version_info(&ps3_firmware_version.raw);
+       printk(KERN_INFO "PS3 firmware version %u.%u.%u\n",
+              ps3_firmware_version.major, ps3_firmware_version.minor,
+              ps3_firmware_version.rev);
 
        ps3_spu_set_platform();
        ps3_map_htab();
@@ -166,6 +202,8 @@ static void __init ps3_setup_arch(void)
 #endif
 
        prealloc_ps3fb_videomemory();
+       prealloc_ps3flash_bounce_buffer();
+
        ppc_md.power_save = ps3_power_save;
 
        DBG(" <- %s:%d\n", __func__, __LINE__);
@@ -184,7 +222,7 @@ static int __init ps3_probe(void)
        DBG(" -> %s:%d\n", __func__, __LINE__);
 
        dt_root = of_get_flat_dt_root();
-       if (!of_flat_dt_is_compatible(dt_root, "PS3"))
+       if (!of_flat_dt_is_compatible(dt_root, "sony,ps3"))
                return 0;
 
        powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE;
@@ -201,31 +239,12 @@ static int __init ps3_probe(void)
 #if defined(CONFIG_KEXEC)
 static void ps3_kexec_cpu_down(int crash_shutdown, int secondary)
 {
-       DBG(" -> %s:%d\n", __func__, __LINE__);
-
-       if (secondary) {
-               int cpu;
-               for_each_online_cpu(cpu)
-                       if (cpu)
-                               ps3_smp_cleanup_cpu(cpu);
-       } else
-               ps3_smp_cleanup_cpu(0);
-
-       DBG(" <- %s:%d\n", __func__, __LINE__);
-}
-
-static void ps3_machine_kexec(struct kimage *image)
-{
-       unsigned long ppe_id;
-
-       DBG(" -> %s:%d\n", __func__, __LINE__);
+       int cpu = smp_processor_id();
 
-       lv1_get_logical_ppe_id(&ppe_id);
-       lv1_configure_irq_state_bitmap(ppe_id, 0, 0);
-       ps3_mm_shutdown();
-       ps3_mm_vas_destroy();
+       DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
 
-       default_machine_kexec(image);
+       ps3_smp_cleanup_cpu(cpu);
+       ps3_shutdown_IRQ(cpu);
 
        DBG(" <- %s:%d\n", __func__, __LINE__);
 }
@@ -247,7 +266,7 @@ define_machine(ps3) {
        .power_off                      = ps3_power_off,
 #if defined(CONFIG_KEXEC)
        .kexec_cpu_down                 = ps3_kexec_cpu_down,
-       .machine_kexec                  = ps3_machine_kexec,
+       .machine_kexec                  = default_machine_kexec,
        .machine_kexec_prepare          = default_machine_kexec_prepare,
        .machine_crash_shutdown         = default_machine_crash_shutdown,
 #endif
index 53416ec5198b0beabaea0f4b85a81295537f6c1a..f0b12f212363589a69cc104d7d2df1a484a27c7d 100644 (file)
@@ -27,9 +27,9 @@
 #include "platform.h"
 
 #if defined(DEBUG)
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG udbg_printf
 #else
-#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
+#define DBG pr_debug
 #endif
 
 static irqreturn_t ipi_function_handler(int irq, void *msg)
@@ -39,11 +39,11 @@ static irqreturn_t ipi_function_handler(int irq, void *msg)
 }
 
 /**
-  * virqs - a per cpu array of virqs for ipi use
+  * ps3_ipi_virqs - a per cpu array of virqs for ipi use
   */
 
 #define MSG_COUNT 4
-static DEFINE_PER_CPU(unsigned int, virqs[MSG_COUNT]);
+static DEFINE_PER_CPU(unsigned int, ps3_ipi_virqs[MSG_COUNT]);
 
 static const char *names[MSG_COUNT] = {
        "ipi call",
@@ -62,7 +62,7 @@ static void do_message_pass(int target, int msg)
                return;
        }
 
-       virq = per_cpu(virqs, target)[msg];
+       virq = per_cpu(ps3_ipi_virqs, target)[msg];
        result = ps3_send_event_locally(virq);
 
        if (result)
@@ -94,13 +94,13 @@ static int ps3_smp_probe(void)
 static void __init ps3_smp_setup_cpu(int cpu)
 {
        int result;
-       unsigned int *virqs = per_cpu(virqs, cpu);
+       unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu);
        int i;
 
        DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
 
        /*
-        * Check assumptions on virqs[] indexing. If this
+        * Check assumptions on ps3_ipi_virqs[] indexing. If this
         * check fails, then a different mapping of PPC_MSG_
         * to index needs to be setup.
         */
@@ -132,13 +132,13 @@ static void __init ps3_smp_setup_cpu(int cpu)
 
 void ps3_smp_cleanup_cpu(int cpu)
 {
-       unsigned int *virqs = per_cpu(virqs, cpu);
+       unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu);
        int i;
 
        DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
 
        for (i = 0; i < MSG_COUNT; i++) {
-               free_irq(virqs[i], (void*)(long)i);
+               /* Can't call free_irq from interrupt context. */
                ps3_event_receive_port_destroy(virqs[i]);
                virqs[i] = NO_IRQ;
        }
index 651437cb2c183f0fab1938bd42cde56ef5f48670..c7f734c894625b272205c7829cdc980ede866b88 100644 (file)
@@ -182,15 +182,18 @@ static int __init setup_areas(struct spu *spu)
 {
        struct table {char* name; unsigned long addr; unsigned long size;};
 
-       spu_pdata(spu)->shadow = __ioremap(
-               spu_pdata(spu)->shadow_addr, sizeof(struct spe_shadow),
-               pgprot_val(PAGE_READONLY) | _PAGE_NO_CACHE | _PAGE_GUARDED);
+       spu_pdata(spu)->shadow = ioremap_flags(spu_pdata(spu)->shadow_addr,
+                                              sizeof(struct spe_shadow),
+                                              pgprot_val(PAGE_READONLY) |
+                                              _PAGE_NO_CACHE);
        if (!spu_pdata(spu)->shadow) {
                pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__);
                goto fail_ioremap;
        }
 
-       spu->local_store = ioremap(spu->local_store_phys, LS_SIZE);
+       spu->local_store = (__force void *)ioremap_flags(spu->local_store_phys,
+               LS_SIZE, _PAGE_NO_CACHE);
+
        if (!spu->local_store) {
                pr_debug("%s:%d: ioremap local_store failed\n",
                        __func__, __LINE__);
@@ -199,6 +202,7 @@ static int __init setup_areas(struct spu *spu)
 
        spu->problem = ioremap(spu->problem_phys,
                sizeof(struct spu_problem));
+
        if (!spu->problem) {
                pr_debug("%s:%d: ioremap problem failed\n", __func__, __LINE__);
                goto fail_ioremap;
@@ -206,6 +210,7 @@ static int __init setup_areas(struct spu *spu)
 
        spu->priv2 = ioremap(spu_pdata(spu)->priv2_addr,
                sizeof(struct spu_priv2));
+
        if (!spu->priv2) {
                pr_debug("%s:%d: ioremap priv2 failed\n", __func__, __LINE__);
                goto fail_ioremap;
index 6bda51027cc6e2d3cd2c6791756ecba60d3d2886..4bb634a17e433fa3e2f675a10c7ac0c59da1f098 100644 (file)
 
 #include "platform.h"
 
+static struct device ps3_system_bus = {
+       .bus_id = "ps3_system",
+};
+
+/* FIXME: need device usage counters! */
+struct {
+       struct mutex mutex;
+       int sb_11; /* usb 0 */
+       int sb_12; /* usb 0 */
+       int gpu;
+} static usage_hack;
+
+static int ps3_is_device(struct ps3_system_bus_device *dev,
+                        unsigned int bus_id, unsigned int dev_id)
+{
+       return dev->bus_id == bus_id && dev->dev_id == dev_id;
+}
+
+static int ps3_open_hv_device_sb(struct ps3_system_bus_device *dev)
+{
+       int result;
+
+       BUG_ON(!dev->bus_id);
+       mutex_lock(&usage_hack.mutex);
+
+       if (ps3_is_device(dev, 1, 1)) {
+               usage_hack.sb_11++;
+               if (usage_hack.sb_11 > 1) {
+                       result = 0;
+                       goto done;
+               }
+       }
+
+       if (ps3_is_device(dev, 1, 2)) {
+               usage_hack.sb_12++;
+               if (usage_hack.sb_12 > 1) {
+                       result = 0;
+                       goto done;
+               }
+       }
+
+       result = lv1_open_device(dev->bus_id, dev->dev_id, 0);
+
+       if (result) {
+               pr_debug("%s:%d: lv1_open_device failed: %s\n", __func__,
+                       __LINE__, ps3_result(result));
+                       result = -EPERM;
+       }
+
+done:
+       mutex_unlock(&usage_hack.mutex);
+       return result;
+}
+
+static int ps3_close_hv_device_sb(struct ps3_system_bus_device *dev)
+{
+       int result;
+
+       BUG_ON(!dev->bus_id);
+       mutex_lock(&usage_hack.mutex);
+
+       if (ps3_is_device(dev, 1, 1)) {
+               usage_hack.sb_11--;
+               if (usage_hack.sb_11) {
+                       result = 0;
+                       goto done;
+               }
+       }
+
+       if (ps3_is_device(dev, 1, 2)) {
+               usage_hack.sb_12--;
+               if (usage_hack.sb_12) {
+                       result = 0;
+                       goto done;
+               }
+       }
+
+       result = lv1_close_device(dev->bus_id, dev->dev_id);
+       BUG_ON(result);
+
+done:
+       mutex_unlock(&usage_hack.mutex);
+       return result;
+}
+
+static int ps3_open_hv_device_gpu(struct ps3_system_bus_device *dev)
+{
+       int result;
+
+       mutex_lock(&usage_hack.mutex);
+
+       usage_hack.gpu++;
+       if (usage_hack.gpu > 1) {
+               result = 0;
+               goto done;
+       }
+
+       result = lv1_gpu_open(0);
+
+       if (result) {
+               pr_debug("%s:%d: lv1_gpu_open failed: %s\n", __func__,
+                       __LINE__, ps3_result(result));
+                       result = -EPERM;
+       }
+
+done:
+       mutex_unlock(&usage_hack.mutex);
+       return result;
+}
+
+static int ps3_close_hv_device_gpu(struct ps3_system_bus_device *dev)
+{
+       int result;
+
+       mutex_lock(&usage_hack.mutex);
+
+       usage_hack.gpu--;
+       if (usage_hack.gpu) {
+               result = 0;
+               goto done;
+       }
+
+       result = lv1_gpu_close();
+       BUG_ON(result);
+
+done:
+       mutex_unlock(&usage_hack.mutex);
+       return result;
+}
+
+int ps3_open_hv_device(struct ps3_system_bus_device *dev)
+{
+       BUG_ON(!dev);
+       pr_debug("%s:%d: match_id: %u\n", __func__, __LINE__, dev->match_id);
+
+       switch (dev->match_id) {
+       case PS3_MATCH_ID_EHCI:
+       case PS3_MATCH_ID_OHCI:
+       case PS3_MATCH_ID_GELIC:
+       case PS3_MATCH_ID_STOR_DISK:
+       case PS3_MATCH_ID_STOR_ROM:
+       case PS3_MATCH_ID_STOR_FLASH:
+               return ps3_open_hv_device_sb(dev);
+
+       case PS3_MATCH_ID_SOUND:
+       case PS3_MATCH_ID_GRAPHICS:
+               return ps3_open_hv_device_gpu(dev);
+
+       case PS3_MATCH_ID_AV_SETTINGS:
+       case PS3_MATCH_ID_SYSTEM_MANAGER:
+               pr_debug("%s:%d: unsupported match_id: %u\n", __func__,
+                       __LINE__, dev->match_id);
+               pr_debug("%s:%d: bus_id: %u\n", __func__,
+                       __LINE__, dev->bus_id);
+               BUG();
+               return -EINVAL;
+
+       default:
+               break;
+       }
+
+       pr_debug("%s:%d: unknown match_id: %u\n", __func__, __LINE__,
+               dev->match_id);
+       BUG();
+       return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(ps3_open_hv_device);
+
+int ps3_close_hv_device(struct ps3_system_bus_device *dev)
+{
+       BUG_ON(!dev);
+       pr_debug("%s:%d: match_id: %u\n", __func__, __LINE__, dev->match_id);
+
+       switch (dev->match_id) {
+       case PS3_MATCH_ID_EHCI:
+       case PS3_MATCH_ID_OHCI:
+       case PS3_MATCH_ID_GELIC:
+       case PS3_MATCH_ID_STOR_DISK:
+       case PS3_MATCH_ID_STOR_ROM:
+       case PS3_MATCH_ID_STOR_FLASH:
+               return ps3_close_hv_device_sb(dev);
+
+       case PS3_MATCH_ID_SOUND:
+       case PS3_MATCH_ID_GRAPHICS:
+               return ps3_close_hv_device_gpu(dev);
+
+       case PS3_MATCH_ID_AV_SETTINGS:
+       case PS3_MATCH_ID_SYSTEM_MANAGER:
+               pr_debug("%s:%d: unsupported match_id: %u\n", __func__,
+                       __LINE__, dev->match_id);
+               pr_debug("%s:%d: bus_id: %u\n", __func__,
+                       __LINE__, dev->bus_id);
+               BUG();
+               return -EINVAL;
+
+       default:
+               break;
+       }
+
+       pr_debug("%s:%d: unknown match_id: %u\n", __func__, __LINE__,
+               dev->match_id);
+       BUG();
+       return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(ps3_close_hv_device);
+
 #define dump_mmio_region(_a) _dump_mmio_region(_a, __func__, __LINE__)
 static void _dump_mmio_region(const struct ps3_mmio_region* r,
        const char* func, int line)
 {
-       pr_debug("%s:%d: dev       %u:%u\n", func, line, r->did.bus_id,
-               r->did.dev_id);
+       pr_debug("%s:%d: dev       %u:%u\n", func, line, r->dev->bus_id,
+               r->dev->dev_id);
        pr_debug("%s:%d: bus_addr  %lxh\n", func, line, r->bus_addr);
        pr_debug("%s:%d: len       %lxh\n", func, line, r->len);
        pr_debug("%s:%d: lpar_addr %lxh\n", func, line, r->lpar_addr);
 }
 
-int ps3_mmio_region_create(struct ps3_mmio_region *r)
+static int ps3_sb_mmio_region_create(struct ps3_mmio_region *r)
 {
        int result;
 
-       result = lv1_map_device_mmio_region(r->did.bus_id, r->did.dev_id,
+       result = lv1_map_device_mmio_region(r->dev->bus_id, r->dev->dev_id,
                r->bus_addr, r->len, r->page_size, &r->lpar_addr);
 
        if (result) {
@@ -57,13 +263,26 @@ int ps3_mmio_region_create(struct ps3_mmio_region *r)
        dump_mmio_region(r);
        return result;
 }
+
+static int ps3_ioc0_mmio_region_create(struct ps3_mmio_region *r)
+{
+       /* device specific; do nothing currently */
+       return 0;
+}
+
+int ps3_mmio_region_create(struct ps3_mmio_region *r)
+{
+       return r->mmio_ops->create(r);
+}
 EXPORT_SYMBOL_GPL(ps3_mmio_region_create);
 
-int ps3_free_mmio_region(struct ps3_mmio_region *r)
+static int ps3_sb_free_mmio_region(struct ps3_mmio_region *r)
 {
        int result;
 
-       result = lv1_unmap_device_mmio_region(r->did.bus_id, r->did.dev_id,
+       dump_mmio_region(r);
+;
+       result = lv1_unmap_device_mmio_region(r->dev->bus_id, r->dev->dev_id,
                r->lpar_addr);
 
        if (result)
@@ -73,14 +292,60 @@ int ps3_free_mmio_region(struct ps3_mmio_region *r)
        r->lpar_addr = 0;
        return result;
 }
+
+static int ps3_ioc0_free_mmio_region(struct ps3_mmio_region *r)
+{
+       /* device specific; do nothing currently */
+       return 0;
+}
+
+
+int ps3_free_mmio_region(struct ps3_mmio_region *r)
+{
+       return r->mmio_ops->free(r);
+}
+
 EXPORT_SYMBOL_GPL(ps3_free_mmio_region);
 
+static const struct ps3_mmio_region_ops ps3_mmio_sb_region_ops = {
+       .create = ps3_sb_mmio_region_create,
+       .free = ps3_sb_free_mmio_region
+};
+
+static const struct ps3_mmio_region_ops ps3_mmio_ioc0_region_ops = {
+       .create = ps3_ioc0_mmio_region_create,
+       .free = ps3_ioc0_free_mmio_region
+};
+
+int ps3_mmio_region_init(struct ps3_system_bus_device *dev,
+       struct ps3_mmio_region *r, unsigned long bus_addr, unsigned long len,
+       enum ps3_mmio_page_size page_size)
+{
+       r->dev = dev;
+       r->bus_addr = bus_addr;
+       r->len = len;
+       r->page_size = page_size;
+       switch (dev->dev_type) {
+       case PS3_DEVICE_TYPE_SB:
+               r->mmio_ops = &ps3_mmio_sb_region_ops;
+               break;
+       case PS3_DEVICE_TYPE_IOC0:
+               r->mmio_ops = &ps3_mmio_ioc0_region_ops;
+               break;
+       default:
+               BUG();
+               return -EINVAL;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ps3_mmio_region_init);
+
 static int ps3_system_bus_match(struct device *_dev,
        struct device_driver *_drv)
 {
        int result;
-       struct ps3_system_bus_driver *drv = to_ps3_system_bus_driver(_drv);
-       struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+       struct ps3_system_bus_driver *drv = ps3_drv_to_system_bus_drv(_drv);
+       struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 
        result = dev->match_id == drv->match_id;
 
@@ -92,32 +357,14 @@ static int ps3_system_bus_match(struct device *_dev,
 
 static int ps3_system_bus_probe(struct device *_dev)
 {
-       int result;
-       struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
-       struct ps3_system_bus_driver *drv =
-               to_ps3_system_bus_driver(_dev->driver);
-
-       result = lv1_open_device(dev->did.bus_id, dev->did.dev_id, 0);
-
-       if (result) {
-               pr_debug("%s:%d: lv1_open_device failed (%d)\n",
-                       __func__, __LINE__, result);
-               result = -EACCES;
-               goto clean_none;
-       }
-
-       if (dev->d_region->did.bus_id) {
-               result = ps3_dma_region_create(dev->d_region);
+       int result = 0;
+       struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+       struct ps3_system_bus_driver *drv;
 
-               if (result) {
-                       pr_debug("%s:%d: ps3_dma_region_create failed (%d)\n",
-                               __func__, __LINE__, result);
-                       BUG_ON("check region type");
-                       result = -EINVAL;
-                       goto clean_device;
-               }
-       }
+       BUG_ON(!dev);
+       pr_info(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id);
 
+       drv = ps3_system_bus_dev_to_system_bus_drv(dev);
        BUG_ON(!drv);
 
        if (drv->probe)
@@ -126,56 +373,127 @@ static int ps3_system_bus_probe(struct device *_dev)
                pr_info("%s:%d: %s no probe method\n", __func__, __LINE__,
                        dev->core.bus_id);
 
-       if (result) {
-               pr_debug("%s:%d: drv->probe failed\n", __func__, __LINE__);
-               goto clean_dma;
-       }
-
-       return result;
-
-clean_dma:
-       ps3_dma_region_free(dev->d_region);
-clean_device:
-       lv1_close_device(dev->did.bus_id, dev->did.dev_id);
-clean_none:
+       pr_info(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id);
        return result;
 }
 
 static int ps3_system_bus_remove(struct device *_dev)
 {
-       struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
-       struct ps3_system_bus_driver *drv =
-               to_ps3_system_bus_driver(_dev->driver);
+       int result = 0;
+       struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+       struct ps3_system_bus_driver *drv;
+
+       BUG_ON(!dev);
+       pr_info(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id);
+
+       drv = ps3_system_bus_dev_to_system_bus_drv(dev);
+       BUG_ON(!drv);
 
        if (drv->remove)
-               drv->remove(dev);
+               result = drv->remove(dev);
        else
-               pr_info("%s:%d: %s no remove method\n", __func__, __LINE__,
-                       dev->core.bus_id);
+               dev_dbg(&dev->core, "%s:%d %s: no remove method\n",
+                       __func__, __LINE__, drv->core.name);
+
+       pr_info(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id);
+       return result;
+}
+
+static void ps3_system_bus_shutdown(struct device *_dev)
+{
+       struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+       struct ps3_system_bus_driver *drv;
+
+       BUG_ON(!dev);
+
+       dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__,
+               dev->match_id);
+
+       if (!dev->core.driver) {
+               dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__,
+                       __LINE__);
+               return;
+       }
+
+       drv = ps3_system_bus_dev_to_system_bus_drv(dev);
+
+       BUG_ON(!drv);
+
+       dev_dbg(&dev->core, "%s:%d: %s -> %s\n", __func__, __LINE__,
+               dev->core.bus_id, drv->core.name);
+
+       if (drv->shutdown)
+               drv->shutdown(dev);
+       else if (drv->remove) {
+               dev_dbg(&dev->core, "%s:%d %s: no shutdown, calling remove\n",
+                       __func__, __LINE__, drv->core.name);
+               drv->remove(dev);
+       } else {
+               dev_dbg(&dev->core, "%s:%d %s: no shutdown method\n",
+                       __func__, __LINE__, drv->core.name);
+               BUG();
+       }
+
+       dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
+}
+
+static int ps3_system_bus_uevent(struct device *_dev, char **envp,
+                                int num_envp, char *buffer, int buffer_size)
+{
+       struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+       int i = 0, length = 0;
 
-       ps3_dma_region_free(dev->d_region);
-       ps3_free_mmio_region(dev->m_region);
-       lv1_close_device(dev->did.bus_id, dev->did.dev_id);
+       if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+                          &length, "MODALIAS=ps3:%d",
+                          dev->match_id))
+               return -ENOMEM;
 
+       envp[i] = NULL;
        return 0;
 }
 
+static ssize_t modalias_show(struct device *_dev, struct device_attribute *a,
+       char *buf)
+{
+       struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+       int len = snprintf(buf, PAGE_SIZE, "ps3:%d\n", dev->match_id);
+
+       return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+}
+
+static struct device_attribute ps3_system_bus_dev_attrs[] = {
+       __ATTR_RO(modalias),
+       __ATTR_NULL,
+};
+
 struct bus_type ps3_system_bus_type = {
        .name = "ps3_system_bus",
        .match = ps3_system_bus_match,
+       .uevent = ps3_system_bus_uevent,
        .probe = ps3_system_bus_probe,
        .remove = ps3_system_bus_remove,
+       .shutdown = ps3_system_bus_shutdown,
+       .dev_attrs = ps3_system_bus_dev_attrs,
 };
 
-int __init ps3_system_bus_init(void)
+static int __init ps3_system_bus_init(void)
 {
        int result;
 
        if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
                return -ENODEV;
 
+       pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+       mutex_init(&usage_hack.mutex);
+
+       result = device_register(&ps3_system_bus);
+       BUG_ON(result);
+
        result = bus_register(&ps3_system_bus_type);
        BUG_ON(result);
+
+       pr_debug(" <- %s:%d\n", __func__, __LINE__);
        return result;
 }
 
@@ -185,16 +503,13 @@ core_initcall(ps3_system_bus_init);
  * Returns the virtual address of the buffer and sets dma_handle
  * to the dma address (mapping) of the first page.
  */
-
 static void * ps3_alloc_coherent(struct device *_dev, size_t size,
-       dma_addr_t *dma_handle, gfp_t flag)
+                                     dma_addr_t *dma_handle, gfp_t flag)
 {
        int result;
-       struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+       struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
        unsigned long virt_addr;
 
-       BUG_ON(!dev->d_region->bus_addr);
-
        flag &= ~(__GFP_DMA | __GFP_HIGHMEM);
        flag |= __GFP_ZERO;
 
@@ -205,7 +520,8 @@ static void * ps3_alloc_coherent(struct device *_dev, size_t size,
                goto clean_none;
        }
 
-       result = ps3_dma_map(dev->d_region, virt_addr, size, dma_handle);
+       result = ps3_dma_map(dev->d_region, virt_addr, size, dma_handle,
+                            IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M);
 
        if (result) {
                pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
@@ -226,7 +542,7 @@ clean_none:
 static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr,
        dma_addr_t dma_handle)
 {
-       struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+       struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 
        ps3_dma_unmap(dev->d_region, dma_handle, size);
        free_pages((unsigned long)vaddr, get_order(size));
@@ -239,15 +555,16 @@ static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr,
  * byte within the page as vaddr.
  */
 
-static dma_addr_t ps3_map_single(struct device *_dev, void *ptr, size_t size,
+static dma_addr_t ps3_sb_map_single(struct device *_dev, void *ptr, size_t size,
        enum dma_data_direction direction)
 {
-       struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+       struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
        int result;
        unsigned long bus_addr;
 
        result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size,
-               &bus_addr);
+                            &bus_addr,
+                            IOPTE_PP_R | IOPTE_PP_W | IOPTE_SO_RW | IOPTE_M);
 
        if (result) {
                pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
@@ -257,10 +574,44 @@ static dma_addr_t ps3_map_single(struct device *_dev, void *ptr, size_t size,
        return bus_addr;
 }
 
+static dma_addr_t ps3_ioc0_map_single(struct device *_dev, void *ptr,
+                                     size_t size,
+                                     enum dma_data_direction direction)
+{
+       struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
+       int result;
+       unsigned long bus_addr;
+       u64 iopte_flag;
+
+       iopte_flag = IOPTE_M;
+       switch (direction) {
+       case DMA_BIDIRECTIONAL:
+               iopte_flag |= IOPTE_PP_R | IOPTE_PP_W | IOPTE_SO_RW;
+               break;
+       case DMA_TO_DEVICE:
+               iopte_flag |= IOPTE_PP_R | IOPTE_SO_R;
+               break;
+       case DMA_FROM_DEVICE:
+               iopte_flag |= IOPTE_PP_W | IOPTE_SO_RW;
+               break;
+       default:
+               /* not happned */
+               BUG();
+       };
+       result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size,
+                            &bus_addr, iopte_flag);
+
+       if (result) {
+               pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
+                       __func__, __LINE__, result);
+       }
+       return bus_addr;
+}
+
 static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr,
        size_t size, enum dma_data_direction direction)
 {
-       struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+       struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
        int result;
 
        result = ps3_dma_unmap(dev->d_region, dma_addr, size);
@@ -271,20 +622,20 @@ static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr,
        }
 }
 
-static int ps3_map_sg(struct device *_dev, struct scatterlist *sg, int nents,
+static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sg, int nents,
        enum dma_data_direction direction)
 {
 #if defined(CONFIG_PS3_DYNAMIC_DMA)
        BUG_ON("do");
        return -EPERM;
 #else
-       struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+       struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
        int i;
 
        for (i = 0; i < nents; i++, sg++) {
                int result = ps3_dma_map(dev->d_region,
                        page_to_phys(sg->page) + sg->offset, sg->length,
-                       &sg->dma_address);
+                                        &sg->dma_address, 0);
 
                if (result) {
                        pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
@@ -299,7 +650,15 @@ static int ps3_map_sg(struct device *_dev, struct scatterlist *sg, int nents,
 #endif
 }
 
-static void ps3_unmap_sg(struct device *_dev, struct scatterlist *sg,
+static int ps3_ioc0_map_sg(struct device *_dev, struct scatterlist *sg,
+                          int nents,
+                          enum dma_data_direction direction)
+{
+       BUG();
+       return 0;
+}
+
+static void ps3_sb_unmap_sg(struct device *_dev, struct scatterlist *sg,
        int nents, enum dma_data_direction direction)
 {
 #if defined(CONFIG_PS3_DYNAMIC_DMA)
@@ -307,18 +666,34 @@ static void ps3_unmap_sg(struct device *_dev, struct scatterlist *sg,
 #endif
 }
 
+static void ps3_ioc0_unmap_sg(struct device *_dev, struct scatterlist *sg,
+                           int nents, enum dma_data_direction direction)
+{
+       BUG();
+}
+
 static int ps3_dma_supported(struct device *_dev, u64 mask)
 {
        return mask >= DMA_32BIT_MASK;
 }
 
-static struct dma_mapping_ops ps3_dma_ops = {
+static struct dma_mapping_ops ps3_sb_dma_ops = {
        .alloc_coherent = ps3_alloc_coherent,
        .free_coherent = ps3_free_coherent,
-       .map_single = ps3_map_single,
+       .map_single = ps3_sb_map_single,
        .unmap_single = ps3_unmap_single,
-       .map_sg = ps3_map_sg,
-       .unmap_sg = ps3_unmap_sg,
+       .map_sg = ps3_sb_map_sg,
+       .unmap_sg = ps3_sb_unmap_sg,
+       .dma_supported = ps3_dma_supported
+};
+
+static struct dma_mapping_ops ps3_ioc0_dma_ops = {
+       .alloc_coherent = ps3_alloc_coherent,
+       .free_coherent = ps3_free_coherent,
+       .map_single = ps3_ioc0_map_single,
+       .unmap_single = ps3_unmap_single,
+       .map_sg = ps3_ioc0_map_sg,
+       .unmap_sg = ps3_ioc0_unmap_sg,
        .dma_supported = ps3_dma_supported
 };
 
@@ -328,7 +703,7 @@ static struct dma_mapping_ops ps3_dma_ops = {
 
 static void ps3_system_bus_release_device(struct device *_dev)
 {
-       struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev);
+       struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
        kfree(dev);
 }
 
@@ -343,19 +718,38 @@ static void ps3_system_bus_release_device(struct device *_dev)
 int ps3_system_bus_device_register(struct ps3_system_bus_device *dev)
 {
        int result;
-       static unsigned int dev_count = 1;
+       static unsigned int dev_ioc0_count;
+       static unsigned int dev_sb_count;
+       static unsigned int dev_vuart_count;
 
-       dev->core.parent = NULL;
+       if (!dev->core.parent)
+               dev->core.parent = &ps3_system_bus;
        dev->core.bus = &ps3_system_bus_type;
        dev->core.release = ps3_system_bus_release_device;
 
+       switch (dev->dev_type) {
+       case PS3_DEVICE_TYPE_IOC0:
+               dev->core.archdata.dma_ops = &ps3_ioc0_dma_ops;
+               snprintf(dev->core.bus_id, sizeof(dev->core.bus_id),
+                       "ioc0_%02x", ++dev_ioc0_count);
+               break;
+       case PS3_DEVICE_TYPE_SB:
+               dev->core.archdata.dma_ops = &ps3_sb_dma_ops;
+               snprintf(dev->core.bus_id, sizeof(dev->core.bus_id),
+                       "sb_%02x", ++dev_sb_count);
+
+               break;
+       case PS3_DEVICE_TYPE_VUART:
+               snprintf(dev->core.bus_id, sizeof(dev->core.bus_id),
+                       "vuart_%02x", ++dev_vuart_count);
+               break;
+       default:
+               BUG();
+       };
+
        dev->core.archdata.of_node = NULL;
-       dev->core.archdata.dma_ops = &ps3_dma_ops;
        dev->core.archdata.numa_node = 0;
 
-       snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "sb_%02x",
-               dev_count++);
-
        pr_debug("%s:%d add %s\n", __func__, __LINE__, dev->core.bus_id);
 
        result = device_register(&dev->core);
@@ -368,9 +762,15 @@ int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv)
 {
        int result;
 
+       pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, drv->core.name);
+
+       if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+               return -ENODEV;
+
        drv->core.bus = &ps3_system_bus_type;
 
        result = driver_register(&drv->core);
+       pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, drv->core.name);
        return result;
 }
 
@@ -378,7 +778,9 @@ EXPORT_SYMBOL_GPL(ps3_system_bus_driver_register);
 
 void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv)
 {
+       pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, drv->core.name);
        driver_unregister(&drv->core);
+       pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, drv->core.name);
 }
 
 EXPORT_SYMBOL_GPL(ps3_system_bus_driver_unregister);
index 1bae8b19b363611c2f9808520dfe788e89f499ea..802a9ccacb5ea130cecbd143616c5944adde1e2c 100644 (file)
@@ -39,7 +39,7 @@ static void _dump_tm(const struct rtc_time *tm, const char* func, int line)
 }
 
 #define dump_time(_a) _dump_time(_a, __func__, __LINE__)
-static void __attribute__ ((unused)) _dump_time(int time, const char* func,
+static void __maybe_unused _dump_time(int time, const char *func,
        int line)
 {
        struct rtc_time tm;
index ae1fc92dc1c976a7f397c9d04f2375e1bd2d7bf0..992ba6753cf238710bb89c2b74f9bcb394c53c77 100644 (file)
@@ -8,7 +8,7 @@ obj-y                   := lpar.o hvCall.o nvram.o reconfig.o \
 obj-$(CONFIG_SMP)      += smp.o
 obj-$(CONFIG_XICS)     += xics.o
 obj-$(CONFIG_SCANLOG)  += scanlog.o
-obj-$(CONFIG_EEH)      += eeh.o eeh_cache.o eeh_driver.o eeh_event.o
+obj-$(CONFIG_EEH)      += eeh.o eeh_cache.o eeh_driver.o eeh_event.o eeh_sysfs.o
 obj-$(CONFIG_KEXEC)    += kexec.o
 obj-$(CONFIG_PCI)      += pci.o pci_dlpar.o
 obj-$(CONFIG_PCI_MSI)  += msi.o
index 5f3e6d8659fec09d2909e801737bf39f1a9b4717..b8770395013d9bb74304e2f848b16b7da6424b51 100644 (file)
@@ -1,6 +1,8 @@
 /*
  * eeh.c
- * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation
+ * Copyright IBM Corporation 2001, 2005, 2006
+ * Copyright Dave Engebretsen & Todd Inglett 2001
+ * Copyright Linas Vepstas 2005, 2006
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -15,6 +17,8 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Please address comments and feedback to Linas Vepstas <linas@austin.ibm.com>
  */
 
 #include <linux/delay.h>
@@ -117,7 +121,6 @@ static unsigned long no_cfg_addr;
 static unsigned long ignored_check;
 static unsigned long total_mmio_ffs;
 static unsigned long false_positives;
-static unsigned long ignored_failures;
 static unsigned long slot_resets;
 
 #define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE)
@@ -505,6 +508,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
                printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n",
                       ret, dn->full_name);
                false_positives++;
+               pdn->eeh_false_positives ++;
                rc = 0;
                goto dn_unlock;
        }
@@ -513,6 +517,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
         * they are empty when they don't have children. */
        if ((rets[0] == 5) && (dn->child == NULL)) {
                false_positives++;
+               pdn->eeh_false_positives ++;
                rc = 0;
                goto dn_unlock;
        }
@@ -522,6 +527,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
                printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n",
                       ret, dn->full_name);
                false_positives++;
+               pdn->eeh_false_positives ++;
                rc = 0;
                goto dn_unlock;
        }
@@ -529,6 +535,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
        /* If not the kind of error we know about, punt. */
        if (rets[0] != 1 && rets[0] != 2 && rets[0] != 4 && rets[0] != 5) {
                false_positives++;
+               pdn->eeh_false_positives ++;
                rc = 0;
                goto dn_unlock;
        }
@@ -921,6 +928,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
        pdn->eeh_mode = 0;
        pdn->eeh_check_count = 0;
        pdn->eeh_freeze_count = 0;
+       pdn->eeh_false_positives = 0;
 
        if (status && strcmp(status, "ok") != 0)
                return NULL;    /* ignore devices with bad status */
@@ -1139,7 +1147,8 @@ static void eeh_add_device_late(struct pci_dev *dev)
        pdn = PCI_DN(dn);
        pdn->pcidev = dev;
 
-       pci_addr_cache_insert_device (dev);
+       pci_addr_cache_insert_device(dev);
+       eeh_sysfs_add_device(dev);
 }
 
 void eeh_add_device_tree_late(struct pci_bus *bus)
@@ -1178,6 +1187,7 @@ static void eeh_remove_device(struct pci_dev *dev)
        printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev));
 #endif
        pci_addr_cache_remove_device(dev);
+       eeh_sysfs_remove_device(dev);
 
        dn = pci_device_to_OF_node(dev);
        if (PCI_DN(dn)->pcidev) {
@@ -1214,11 +1224,10 @@ static int proc_eeh_show(struct seq_file *m, void *v)
                                "check not wanted=%ld\n"
                                "eeh_total_mmio_ffs=%ld\n"
                                "eeh_false_positives=%ld\n"
-                               "eeh_ignored_failures=%ld\n"
                                "eeh_slot_resets=%ld\n",
                                no_device, no_dn, no_cfg_addr, 
                                ignored_check, total_mmio_ffs, 
-                               false_positives, ignored_failures, 
+                               false_positives,
                                slot_resets);
        }
 
index f2bae04424f8a3933e8b49a4a261c7147de3ec75..e49c815eae23496a23555187a023432b4a450172 100644 (file)
@@ -2,7 +2,8 @@
  * eeh_cache.c
  * PCI address cache; allows the lookup of PCI devices based on I/O address
  *
- * Copyright (C) 2004 Linas Vepstas <linas@austin.ibm.com> IBM Corporation
+ * Copyright IBM Corporation 2004
+ * Copyright Linas Vepstas <linas@austin.ibm.com> 2004
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -295,6 +296,8 @@ void __init pci_addr_cache_build(void)
                        continue;
                pci_dev_get (dev);  /* matching put is in eeh_remove_device() */
                PCI_DN(dn)->pcidev = dev;
+
+               eeh_sysfs_add_device(dev);
        }
 
 #ifdef DEBUG
index 161a5844ab6c243da27df37ba188fc5e98e72eba..15e015ef68653f78dec23d8ca4008be911b4acb4 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * PCI Error Recovery Driver for RPA-compliant PPC64 platform.
- * Copyright (C) 2004, 2005 Linas Vepstas <linas@linas.org>
+ * Copyright IBM Corp. 2004 2005
+ * Copyright Linas Vepstas <linas@linas.org> 2004, 2005
  *
  * All rights reserved.
  *
@@ -19,8 +20,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <linas@us.ibm.com>
- *
+ * Send comments and feedback to Linas Vepstas <linas@austin.ibm.com>
  */
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff --git a/arch/powerpc/platforms/pseries/eeh_sysfs.c b/arch/powerpc/platforms/pseries/eeh_sysfs.c
new file mode 100644 (file)
index 0000000..15e13b5
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Sysfs entries for PCI Error Recovery for PAPR-compliant platform.
+ * Copyright IBM Corporation 2007
+ * Copyright Linas Vepstas <linas@austin.ibm.com> 2007
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send comments and feedback to Linas Vepstas <linas@austin.ibm.com>
+ */
+#include <linux/pci.h>
+#include <asm/ppc-pci.h>
+#include <asm/pci-bridge.h>
+#include <linux/kobject.h>
+
+/**
+ * EEH_SHOW_ATTR -- create sysfs entry for eeh statistic
+ * @_name: name of file in sysfs directory
+ * @_memb: name of member in struct pci_dn to access
+ * @_format: printf format for display
+ *
+ * All of the attributes look very similar, so just
+ * auto-gen a cut-n-paste routine to display them.
+ */
+#define EEH_SHOW_ATTR(_name,_memb,_format)               \
+static ssize_t eeh_show_##_name(struct device *dev,      \
+               struct device_attribute *attr, char *buf)          \
+{                                                        \
+       struct pci_dev *pdev = to_pci_dev(dev);               \
+       struct device_node *dn = pci_device_to_OF_node(pdev); \
+       struct pci_dn *pdn;                                   \
+                                                             \
+       if (!dn || PCI_DN(dn) == NULL)                        \
+               return 0;                                          \
+                                                             \
+       pdn = PCI_DN(dn);                                     \
+       return sprintf(buf, _format "\n", pdn->_memb);        \
+}                                                        \
+static DEVICE_ATTR(_name, S_IRUGO, eeh_show_##_name, NULL);
+
+
+EEH_SHOW_ATTR(eeh_mode, eeh_mode, "0x%x");
+EEH_SHOW_ATTR(eeh_config_addr, eeh_config_addr, "0x%x");
+EEH_SHOW_ATTR(eeh_pe_config_addr, eeh_pe_config_addr, "0x%x");
+EEH_SHOW_ATTR(eeh_check_count, eeh_check_count, "%d");
+EEH_SHOW_ATTR(eeh_freeze_count, eeh_freeze_count, "%d");
+EEH_SHOW_ATTR(eeh_false_positives, eeh_false_positives, "%d");
+
+void eeh_sysfs_add_device(struct pci_dev *pdev)
+{
+       int rc=0;
+
+       rc += device_create_file(&pdev->dev, &dev_attr_eeh_mode);
+       rc += device_create_file(&pdev->dev, &dev_attr_eeh_config_addr);
+       rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
+       rc += device_create_file(&pdev->dev, &dev_attr_eeh_check_count);
+       rc += device_create_file(&pdev->dev, &dev_attr_eeh_false_positives);
+       rc += device_create_file(&pdev->dev, &dev_attr_eeh_freeze_count);
+
+       if (rc)
+               printk(KERN_WARNING "EEH: Unable to create sysfs entries\n");
+}
+
+void eeh_sysfs_remove_device(struct pci_dev *pdev)
+{
+       device_remove_file(&pdev->dev, &dev_attr_eeh_mode);
+       device_remove_file(&pdev->dev, &dev_attr_eeh_config_addr);
+       device_remove_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
+       device_remove_file(&pdev->dev, &dev_attr_eeh_check_count);
+       device_remove_file(&pdev->dev, &dev_attr_eeh_false_positives);
+       device_remove_file(&pdev->dev, &dev_attr_eeh_freeze_count);
+}
+
index 362dfbc260a69d4bc629ecf789676e21f07d4b71..8cc6eeeaae2f1649368fdac4ba7eebf9c1227e05 100644 (file)
@@ -373,12 +373,23 @@ static void pSeries_lpar_hptab_clear(void)
 {
        unsigned long size_bytes = 1UL << ppc64_pft_size;
        unsigned long hpte_count = size_bytes >> 4;
-       unsigned long dummy1, dummy2;
+       unsigned long dummy1, dummy2, dword0;
+       long lpar_rc;
        int i;
 
        /* TODO: Use bulk call */
-       for (i = 0; i < hpte_count; i++)
-               plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2);
+       for (i = 0; i < hpte_count; i++) {
+               /* dont remove HPTEs with VRMA mappings */
+               lpar_rc = plpar_pte_remove_raw(H_ANDCOND, i, HPTE_V_1TB_SEG,
+                                               &dummy1, &dummy2);
+               if (lpar_rc == H_NOT_FOUND) {
+                       lpar_rc = plpar_pte_read_raw(0, i, &dword0, &dummy1);
+                       if (!lpar_rc && ((dword0 & HPTE_V_VRMA_MASK)
+                               != HPTE_V_VRMA_MASK))
+                               /* Can be hpte for 1TB Seg. So remove it */
+                               plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2);
+               }
+       }
 }
 
 /*
index ffaf6c5c517bda0527945e4ff7146f28c668db19..47f0e0857f0ecac871c87e28fddec3579bef9da9 100644 (file)
@@ -110,8 +110,6 @@ pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
                        }
                }
        }
-
-       eeh_add_device_tree_late(bus);
 }
 EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices);
 
@@ -139,6 +137,8 @@ pcibios_pci_config_bridge(struct pci_dev *dev)
 
        /* Make the discovered devices available */
        pci_bus_add_devices(child_bus);
+
+       eeh_add_device_tree_late(child_bus);
        return 0;
 }
 
@@ -171,6 +171,7 @@ pcibios_add_pci_devices(struct pci_bus * bus)
                if (!list_empty(&bus->devices)) {
                        pcibios_fixup_new_pci_devices(bus, 0);
                        pci_bus_add_devices(bus);
+                       eeh_add_device_tree_late(bus);
                }
        } else if (mode == PCI_PROBE_NORMAL) {
                /* use legacy probe */
@@ -179,6 +180,7 @@ pcibios_add_pci_devices(struct pci_bus * bus)
                if (num) {
                        pcibios_fixup_new_pci_devices(bus, 1);
                        pci_bus_add_devices(bus);
+                       eeh_add_device_tree_late(bus);
                }
 
                list_for_each_entry(dev, &bus->devices, bus_list)
@@ -200,8 +202,6 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
        rtas_setup_phb(phb);
        pci_process_bridge_OF_ranges(phb, dn, 0);
 
-       pci_setup_phb_io_dynamic(phb, primary);
-
        pci_devs_phb_init_dynamic(phb);
 
        if (dn->child)
@@ -210,6 +210,7 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
        scan_phb(phb);
        pcibios_fixup_new_pci_devices(phb->bus, 0);
        pci_bus_add_devices(phb->bus);
+       eeh_add_device_tree_late(phb->bus);
 
        return phb;
 }
index 2e4d10c9eea89a961e7f7c0b3e88cb2291eadbf2..d003c80fa31d2b4369f0021fd3a9b38ab99dd4ae 100644 (file)
@@ -108,6 +108,21 @@ static inline long plpar_pte_read(unsigned long flags, unsigned long ptex,
        return rc;
 }
 
+/* plpar_pte_read_raw can be called in real mode. It calls plpar_hcall_raw */
+static inline long plpar_pte_read_raw(unsigned long flags, unsigned long ptex,
+               unsigned long *old_pteh_ret, unsigned long *old_ptel_ret)
+{
+       long rc;
+       unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+       rc = plpar_hcall_raw(H_READ, retbuf, flags, ptex);
+
+       *old_pteh_ret = retbuf[0];
+       *old_ptel_ret = retbuf[1];
+
+       return rc;
+}
+
 static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex,
                unsigned long avpn)
 {
index 2729d559fd91b729e78eb6ece183e1b02be1a241..61e19f78b923099c3691de50ece491adbf158d31 100644 (file)
@@ -33,6 +33,8 @@ static inline void setup_kexec_cpu_down_xics(void) { }
 static inline void setup_kexec_cpu_down_mpic(void) { }
 #endif
 
+extern void pSeries_final_fixup(void);
+
 /* Poweron flag used for enabling auto ups restart */
 extern unsigned long rtas_poweron_auto;
 
index 5aa97aff3391ee9a822997d6d4cd893798324725..c02f8742c54de5792650c2e641003637921cad03 100644 (file)
@@ -123,7 +123,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist
        strcpy(np->full_name, path);
 
        np->properties = proplist;
-       OF_MARK_DYNAMIC(np);
+       of_node_set_flag(np, OF_DYNAMIC);
        kref_init(&np->kref);
 
        np->parent = derive_parent(path);
index a031d99becb772964adabc4d4a93f5c1ccbd68e6..59e69f085cb419e2ca037fb1273ccbcf1b8824d9 100644 (file)
@@ -399,6 +399,7 @@ static void pseries_dedicated_idle_sleep(void)
         * a good time to find other work to dispatch.
         */
        get_lppaca()->idle = 1;
+       get_lppaca()->donate_dedicated_cpu = 1;
 
        /*
         * We come in with interrupts disabled, and need_resched()
@@ -431,6 +432,7 @@ static void pseries_dedicated_idle_sleep(void)
 
 out:
        HMT_medium();
+       get_lppaca()->donate_dedicated_cpu = 0;
        get_lppaca()->idle = 0;
 }
 
index f1df942072bbdefdb3e7a397e2c7637c53423d43..5bd90a7eb763327e06300d7dd51aef3eb6ff4123 100644 (file)
@@ -156,9 +156,9 @@ static inline void lpar_qirr_info(int n_cpu , u8 value)
 
 
 #ifdef CONFIG_SMP
-static int get_irq_server(unsigned int virq)
+static int get_irq_server(unsigned int virq, unsigned int strict_check)
 {
-       unsigned int server;
+       int server;
        /* For the moment only implement delivery to all cpus or one cpu */
        cpumask_t cpumask = irq_desc[virq].affinity;
        cpumask_t tmp = CPU_MASK_NONE;
@@ -166,22 +166,25 @@ static int get_irq_server(unsigned int virq)
        if (!distribute_irqs)
                return default_server;
 
-       if (cpus_equal(cpumask, CPU_MASK_ALL)) {
-               server = default_distrib_server;
-       } else {
+       if (!cpus_equal(cpumask, CPU_MASK_ALL)) {
                cpus_and(tmp, cpu_online_map, cpumask);
 
-               if (cpus_empty(tmp))
-                       server = default_distrib_server;
-               else
-                       server = get_hard_smp_processor_id(first_cpu(tmp));
+               server = first_cpu(tmp);
+
+               if (server < NR_CPUS)
+                       return get_hard_smp_processor_id(server);
+
+               if (strict_check)
+                       return -1;
        }
 
-       return server;
+       if (cpus_equal(cpu_online_map, cpu_present_map))
+               return default_distrib_server;
 
+       return default_server;
 }
 #else
-static int get_irq_server(unsigned int virq)
+static int get_irq_server(unsigned int virq, unsigned int strict_check)
 {
        return default_server;
 }
@@ -192,7 +195,7 @@ static void xics_unmask_irq(unsigned int virq)
 {
        unsigned int irq;
        int call_status;
-       unsigned int server;
+       int server;
 
        pr_debug("xics: unmask virq %d\n", virq);
 
@@ -201,7 +204,7 @@ static void xics_unmask_irq(unsigned int virq)
        if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
                return;
 
-       server = get_irq_server(virq);
+       server = get_irq_server(virq, 0);
 
        call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
                                DEFAULT_PRIORITY);
@@ -398,8 +401,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
        unsigned int irq;
        int status;
        int xics_status[2];
-       unsigned long newmask;
-       cpumask_t tmp = CPU_MASK_NONE;
+       int irq_server;
 
        irq = (unsigned int)irq_map[virq].hwirq;
        if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
@@ -413,18 +415,21 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
                return;
        }
 
-       /* For the moment only implement delivery to all cpus or one cpu */
-       if (cpus_equal(cpumask, CPU_MASK_ALL)) {
-               newmask = default_distrib_server;
-       } else {
-               cpus_and(tmp, cpu_online_map, cpumask);
-               if (cpus_empty(tmp))
-                       return;
-               newmask = get_hard_smp_processor_id(first_cpu(tmp));
+       /*
+        * For the moment only implement delivery to all cpus or one cpu.
+        * Get current irq_server for the given irq
+        */
+       irq_server = get_irq_server(irq, 1);
+       if (irq_server == -1) {
+               char cpulist[128];
+               cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
+               printk(KERN_WARNING "xics_set_affinity: No online cpus in "
+                               "the mask %s for irq %d\n", cpulist, virq);
+               return;
        }
 
        status = rtas_call(ibm_set_xive, 3, 1, NULL,
-                               irq, newmask, xics_status[1]);
+                               irq, irq_server, xics_status[1]);
 
        if (status) {
                printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive "
index c3ce0bd12c0b94e461219dca62d3fef5a7650ad9..f65078c3d3b38fe0048f1437f27cf702e2d28746 100644 (file)
@@ -5,7 +5,6 @@ endif
 mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o
 obj-$(CONFIG_MPIC)             += mpic.o $(mpic-msi-obj-y)
 
-obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
 obj-$(CONFIG_PPC_MPC106)       += grackle.o
 obj-$(CONFIG_PPC_DCR)          += dcr.o
 obj-$(CONFIG_PPC_DCR_NATIVE)   += dcr-low.o
@@ -13,16 +12,19 @@ obj-$(CONFIG_PPC_PMI)               += pmi.o
 obj-$(CONFIG_U3_DART)          += dart_iommu.o
 obj-$(CONFIG_MMIO_NVRAM)       += mmio_nvram.o
 obj-$(CONFIG_FSL_SOC)          += fsl_soc.o
-obj-$(CONFIG_FSL_PCIE)         += fsl_pcie.o
 obj-$(CONFIG_TSI108_BRIDGE)    += tsi108_pci.o tsi108_dev.o
 obj-$(CONFIG_QUICC_ENGINE)     += qe_lib/
 mv64x60-$(CONFIG_PCI)          += mv64x60_pci.o
 obj-$(CONFIG_MV64X60)          += $(mv64x60-y) mv64x60_pic.o mv64x60_dev.o
+obj-$(CONFIG_RTC_DRV_CMOS)     += rtc_cmos_setup.o
 
 # contains only the suspend handler for time
+ifeq ($(CONFIG_RTC_CLASS),)
 obj-$(CONFIG_PM)               += timer.o
+endif
 
 ifeq ($(CONFIG_PPC_MERGE),y)
+obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
 obj-$(CONFIG_PPC_I8259)                += i8259.o
 obj-$(CONFIG_PPC_83xx)         += ipic.o
 obj-$(CONFIG_4xx)              += uic.o
diff --git a/arch/powerpc/sysdev/fsl_pcie.c b/arch/powerpc/sysdev/fsl_pcie.c
deleted file mode 100644 (file)
index 041c07e..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Support for indirect PCI bridges.
- *
- * Copyright (C) 1998 Gabriel Paubert.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * "Temporary" MPC8548 Errata file -
- * The standard indirect_pci code should work with future silicon versions.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include <asm/machdep.h>
-
-#define PCI_CFG_OUT out_be32
-
-/* ERRATA PCI-Ex 14 PCIE Controller timeout */
-#define PCIE_FIX               out_be32(hose->cfg_addr+0x4, 0x0400ffff)
-
-
-static int
-indirect_read_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset,
-                    int len, u32 *val)
-{
-       struct pci_controller *hose = bus->sysdata;
-       volatile void __iomem *cfg_data;
-       u32 temp;
-
-       if (ppc_md.pci_exclude_device)
-               if (ppc_md.pci_exclude_device(bus->number, devfn))
-                       return PCIBIOS_DEVICE_NOT_FOUND;
-
-       /* Possible artifact of CDCpp50937 needs further investigation */
-       if (devfn != 0x0 && bus->number == 0xff)
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       PCIE_FIX;
-       if (bus->number == 0xff) {
-               PCI_CFG_OUT(hose->cfg_addr,
-                           (0x80000000 | ((offset & 0xf00) << 16) |
-                            ((bus->number - hose->bus_offset) << 16)
-                            | (devfn << 8) | ((offset & 0xfc) )));
-       } else {
-               PCI_CFG_OUT(hose->cfg_addr,
-                           (0x80000001 | ((offset & 0xf00) << 16) |
-                            ((bus->number - hose->bus_offset) << 16)
-                            | (devfn << 8) | ((offset & 0xfc) )));
-       }
-
-       /*
-        * Note: the caller has already checked that offset is
-        * suitably aligned and that len is 1, 2 or 4.
-        */
-       /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
-       cfg_data = hose->cfg_data;
-       PCIE_FIX;
-       temp = in_le32(cfg_data);
-       switch (len) {
-       case 1:
-               *val = (temp >> (((offset & 3))*8)) & 0xff;
-               break;
-       case 2:
-               *val = (temp >> (((offset & 3))*8)) & 0xffff;
-               break;
-       default:
-               *val = temp;
-               break;
-       }
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-indirect_write_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset,
-                     int len, u32 val)
-{
-       struct pci_controller *hose = bus->sysdata;
-       volatile void __iomem *cfg_data;
-       u32 temp;
-
-       if (ppc_md.pci_exclude_device)
-               if (ppc_md.pci_exclude_device(bus->number, devfn))
-                       return PCIBIOS_DEVICE_NOT_FOUND;
-
-       /* Possible artifact of CDCpp50937 needs further investigation */
-       if (devfn != 0x0 && bus->number == 0xff)
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       PCIE_FIX;
-       if (bus->number == 0xff) {
-               PCI_CFG_OUT(hose->cfg_addr,
-                           (0x80000000 | ((offset & 0xf00) << 16) |
-                            ((bus->number - hose->bus_offset) << 16)
-                            | (devfn << 8) | ((offset & 0xfc) )));
-       } else {
-               PCI_CFG_OUT(hose->cfg_addr,
-                           (0x80000001 | ((offset & 0xf00) << 16) |
-                            ((bus->number - hose->bus_offset) << 16)
-                            | (devfn << 8) | ((offset & 0xfc) )));
-        }
-
-       /*
-        * Note: the caller has already checked that offset is
-        * suitably aligned and that len is 1, 2 or 4.
-        */
-       /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
-       cfg_data = hose->cfg_data;
-       switch (len) {
-       case 1:
-               PCIE_FIX;
-               temp = in_le32(cfg_data);
-               temp = (temp & ~(0xff << ((offset & 3) * 8))) |
-                       (val << ((offset & 3) * 8));
-               PCIE_FIX;
-               out_le32(cfg_data, temp);
-               break;
-       case 2:
-               PCIE_FIX;
-               temp = in_le32(cfg_data);
-               temp = (temp & ~(0xffff << ((offset & 3) * 8)));
-               temp |= (val << ((offset & 3) * 8)) ;
-               PCIE_FIX;
-               out_le32(cfg_data, temp);
-               break;
-       default:
-               PCIE_FIX;
-               out_le32(cfg_data, val);
-               break;
-       }
-       PCIE_FIX;
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops indirect_pcie_ops = {
-       indirect_read_config_pcie,
-       indirect_write_config_pcie
-};
-
-void __init
-setup_indirect_pcie_nomap(struct pci_controller* hose, void __iomem * cfg_addr,
-       void __iomem * cfg_data)
-{
-       hose->cfg_addr = cfg_addr;
-       hose->cfg_data = cfg_data;
-       hose->ops = &indirect_pcie_ops;
-}
-
-void __init
-setup_indirect_pcie(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
-{
-       unsigned long base = cfg_addr & PAGE_MASK;
-       void __iomem *mbase, *addr, *data;
-
-       mbase = ioremap(base, PAGE_SIZE);
-       addr = mbase + (cfg_addr & ~PAGE_MASK);
-       if ((cfg_data & PAGE_MASK) != base)
-               mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
-       data = mbase + (cfg_data & ~PAGE_MASK);
-       setup_indirect_pcie_nomap(hose, addr, data);
-}
index cad175724359df4099a84b00c4af154cbd2362a5..c0ddc80d8160452238bbf0de29cf23c24340785b 100644 (file)
@@ -1028,6 +1028,19 @@ err:
 
 arch_initcall(fs_enet_of_init);
 
+static int __init fsl_pcmcia_of_init(void)
+{
+       struct device_node *np = NULL;
+       /*
+        * Register all the devices which type is "pcmcia"
+        */
+       while ((np = of_find_compatible_node(np,
+                       "pcmcia", "fsl,pq-pcmcia")) != NULL)
+                           of_platform_device_create(np, "m8xx-pcmcia", NULL);
+       return 0;
+}
+
+arch_initcall(fsl_pcmcia_of_init);
 
 static const char *smc_regs = "regs";
 static const char *smc_pram = "pram";
index e71488469704bbea18077cbf903871b72d34afeb..c7e6e859b393c5b11998fbd73836ab3ff9f14722 100644 (file)
@@ -33,18 +33,27 @@ indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
        struct pci_controller *hose = bus->sysdata;
        volatile void __iomem *cfg_data;
        u8 cfg_type = 0;
+       u32 bus_no, reg;
 
        if (ppc_md.pci_exclude_device)
-               if (ppc_md.pci_exclude_device(bus->number, devfn))
+               if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
                        return PCIBIOS_DEVICE_NOT_FOUND;
        
-       if (hose->set_cfg_type)
+       if (hose->indirect_type & PPC_INDIRECT_TYPE_SET_CFG_TYPE)
                if (bus->number != hose->first_busno)
                        cfg_type = 1;
 
-       PCI_CFG_OUT(hose->cfg_addr,                                      
-                (0x80000000 | ((bus->number - hose->bus_offset) << 16)
-                 | (devfn << 8) | ((offset & 0xfc) | cfg_type)));
+       bus_no = (bus->number == hose->first_busno) ?
+                       hose->self_busno : bus->number;
+
+       if (hose->indirect_type & PPC_INDIRECT_TYPE_EXT_REG)
+               reg = ((offset & 0xf00) << 16) | (offset & 0xfc);
+       else
+               reg = offset & 0xfc;
+
+       PCI_CFG_OUT(hose->cfg_addr,
+                (0x80000000 | (bus_no << 16)
+                 | (devfn << 8) | reg | cfg_type));
 
        /*
         * Note: the caller has already checked that offset is
@@ -72,18 +81,33 @@ indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
        struct pci_controller *hose = bus->sysdata;
        volatile void __iomem *cfg_data;
        u8 cfg_type = 0;
+       u32 bus_no, reg;
 
        if (ppc_md.pci_exclude_device)
-               if (ppc_md.pci_exclude_device(bus->number, devfn))
+               if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
                        return PCIBIOS_DEVICE_NOT_FOUND;
 
-       if (hose->set_cfg_type)
+       if (hose->indirect_type & PPC_INDIRECT_TYPE_SET_CFG_TYPE)
                if (bus->number != hose->first_busno)
                        cfg_type = 1;
 
-       PCI_CFG_OUT(hose->cfg_addr,                                      
-                (0x80000000 | ((bus->number - hose->bus_offset) << 16)
-                 | (devfn << 8) | ((offset & 0xfc) | cfg_type)));
+       bus_no = (bus->number == hose->first_busno) ?
+                       hose->self_busno : bus->number;
+
+       if (hose->indirect_type & PPC_INDIRECT_TYPE_EXT_REG)
+               reg = ((offset & 0xf00) << 16) | (offset & 0xfc);
+       else
+               reg = offset & 0xfc;
+
+       PCI_CFG_OUT(hose->cfg_addr,
+                (0x80000000 | (bus_no << 16)
+                 | (devfn << 8) | reg | cfg_type));
+
+       /* surpress setting of PCI_PRIMARY_BUS */
+       if (hose->indirect_type & PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS)
+               if ((offset == PCI_PRIMARY_BUS) &&
+                       (bus->number == hose->first_busno))
+               val &= 0xffffff00;
 
        /*
         * Note: the caller has already checked that offset is
index afa2ee6717c149309b8aa7ad53226f64048a0605..9fe00eebdc8b8cd150c11f0b1c836b092dc39b0e 100644 (file)
@@ -4,9 +4,16 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 
-extern struct hw_interrupt_type mpc8xx_pic;
-
 int mpc8xx_pic_init(void);
 unsigned int mpc8xx_get_irq(void);
 
+/*
+ * Some internal interrupt registers use an 8-bit mask for the interrupt
+ * level instead of a number.
+ */
+static inline uint mk_int_int_mask(uint mask)
+{
+       return (1 << (7 - (mask/2)));
+}
+
 #endif /* _PPC_KERNEL_PPC8xx_H */
index 4b0a9c88eeb3563937638b34ad8e26527418bb70..b618fa60aef342f42dad4e845f1d9a73718cfee3 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/console.h>
 #include <linux/mv643xx.h>
 #include <linux/platform_device.h>
 
@@ -420,3 +421,30 @@ error:
        return err;
 }
 arch_initcall(mv64x60_device_setup);
+
+static int __init mv64x60_add_mpsc_console(void)
+{
+       struct device_node *np = NULL;
+       const char *prop;
+
+       prop = of_get_property(of_chosen, "linux,stdout-path", NULL);
+       if (prop == NULL)
+               goto not_mpsc;
+
+       np = of_find_node_by_path(prop);
+       if (!np)
+               goto not_mpsc;
+
+       if (!of_device_is_compatible(np, "marvell,mpsc"))
+               goto not_mpsc;
+
+       prop = of_get_property(np, "block-index", NULL);
+       if (!prop)
+               goto not_mpsc;
+
+       add_preferred_console("ttyMM", *(int *)prop, NULL);
+
+not_mpsc:
+       return 0;
+}
+console_initcall(mv64x60_add_mpsc_console);
index b5aef4cbc8d21f3ef0fd160fbef4e49b5e7e1dbf..45db86c2363c469a982a7e6cbefe3444e0c21391 100644 (file)
@@ -137,18 +137,15 @@ static int __init mv64x60_add_bridge(struct device_node *dev)
                printk(KERN_WARNING "Can't get bus-range for %s, assume"
                       " bus 0\n", dev->full_name);
 
-       hose = pcibios_alloc_controller();
+       hose = pcibios_alloc_controller(dev);
        if (!hose)
                return -ENOMEM;
 
-       hose->arch_data = dev;
-       hose->set_cfg_type = 1;
-
        hose->first_busno = bus_range ? bus_range[0] : 0;
        hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
        setup_indirect_pci(hose, rsrc.start, rsrc.start + 4);
-       hose->bus_offset = hose->first_busno;
+       hose->self_busno = hose->first_busno;
 
        printk(KERN_INFO "Found MV64x60 PCI host bridge at 0x%016llx. "
               "Firmware bus number: %d->%d\n",
index ac12a44d516f6ceb6d987ec4f09d7c85a67ee77a..f970e5415ac00aaa13f1b9f551c9efa53f633e4e 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/stddef.h>
+#include <linux/module.h>
 
 #include <asm/irq.h>
 #include <asm/io.h>
@@ -40,6 +41,7 @@ int ucc_set_qe_mux_mii_mng(int ucc_num)
 
        return 0;
 }
+EXPORT_SYMBOL(ucc_set_qe_mux_mii_mng);
 
 int ucc_set_type(int ucc_num, struct ucc_common *regs,
                 enum ucc_speed_type speed)
index 9143236853fc029029f0a178f5319cb383650506..3df202e8d33253a4b17744ac58daea10662d8afa 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/stddef.h>
 #include <linux/interrupt.h>
 #include <linux/err.h>
+#include <linux/module.h>
 
 #include <asm/io.h>
 #include <asm/immap_qe.h>
@@ -70,6 +71,7 @@ void ucc_fast_dump_regs(struct ucc_fast_private * uccf)
        printk(KERN_INFO "guemr : addr - 0x%08x, val - 0x%02x",
                  (u32) & uccf->uf_regs->guemr, uccf->uf_regs->guemr);
 }
+EXPORT_SYMBOL(ucc_fast_dump_regs);
 
 u32 ucc_fast_get_qe_cr_subblock(int uccf_num)
 {
@@ -85,11 +87,13 @@ u32 ucc_fast_get_qe_cr_subblock(int uccf_num)
        default: return QE_CR_SUBBLOCK_INVALID;
        }
 }
+EXPORT_SYMBOL(ucc_fast_get_qe_cr_subblock);
 
 void ucc_fast_transmit_on_demand(struct ucc_fast_private * uccf)
 {
        out_be16(&uccf->uf_regs->utodr, UCC_FAST_TOD);
 }
+EXPORT_SYMBOL(ucc_fast_transmit_on_demand);
 
 void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode)
 {
@@ -110,6 +114,7 @@ void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode)
        }
        out_be32(&uf_regs->gumr, gumr);
 }
+EXPORT_SYMBOL(ucc_fast_enable);
 
 void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode)
 {
@@ -130,6 +135,7 @@ void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode)
        }
        out_be32(&uf_regs->gumr, gumr);
 }
+EXPORT_SYMBOL(ucc_fast_disable);
 
 int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** uccf_ret)
 {
@@ -341,6 +347,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
        *uccf_ret = uccf;
        return 0;
 }
+EXPORT_SYMBOL(ucc_fast_init);
 
 void ucc_fast_free(struct ucc_fast_private * uccf)
 {
@@ -355,3 +362,4 @@ void ucc_fast_free(struct ucc_fast_private * uccf)
 
        kfree(uccf);
 }
+EXPORT_SYMBOL(ucc_fast_free);
diff --git a/arch/powerpc/sysdev/rtc_cmos_setup.c b/arch/powerpc/sysdev/rtc_cmos_setup.c
new file mode 100644 (file)
index 0000000..e276048
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Setup code for PC-style Real-Time Clock.
+ *
+ * Author: Wade Farnsworth <wfarnsworth@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/mc146818rtc.h>
+
+#include <asm/prom.h>
+
+static int  __init add_rtc(void)
+{
+       struct device_node *np;
+       struct platform_device *pd;
+       struct resource res;
+       int ret;
+
+       np = of_find_compatible_node(NULL, NULL, "pnpPNP,b00");
+       if (!np)
+               return -ENODEV;
+
+       ret = of_address_to_resource(np, 0, &res);
+       of_node_put(np);
+       if (ret)
+               return ret;
+
+       /*
+        * RTC_PORT(x) is hardcoded in asm/mc146818rtc.h.  Verify that the
+        * address provided by the device node matches.
+        */
+       if (res.start != RTC_PORT(0))
+               return -EINVAL;
+
+       pd = platform_device_register_simple("rtc_cmos", -1,
+                                            &res, 1);
+       if (IS_ERR(pd))
+               return PTR_ERR(pd);
+
+       return 0;
+}
+fs_initcall(add_rtc);
index 4a01748b4217aa4272b81e8fa0e9528cdf727340..e81e7ec2e799adbf521ac49edf87f7bf47e11537 100644 (file)
@@ -24,7 +24,12 @@ static int timer_resume(struct sys_device *dev)
 
        /* get current RTC time and convert to seconds */
        get_rtc_time(&cur_rtc_tm);
-       rtc_tm_to_time(&cur_rtc_tm, &cur_rtc_time);
+       cur_rtc_time = mktime(cur_rtc_tm.tm_year + 1900,
+                             cur_rtc_tm.tm_mon + 1,
+                             cur_rtc_tm.tm_mday,
+                             cur_rtc_tm.tm_hour,
+                             cur_rtc_tm.tm_min,
+                             cur_rtc_tm.tm_sec);
 
        diff = cur_rtc_time - suspend_rtc_time;
 
@@ -44,7 +49,12 @@ static int timer_suspend(struct sys_device *dev, pm_message_t state)
        WARN_ON(!ppc_md.get_rtc_time);
 
        get_rtc_time(&suspend_rtc_tm);
-       rtc_tm_to_time(&suspend_rtc_tm, &suspend_rtc_time);
+       suspend_rtc_time = mktime(suspend_rtc_tm.tm_year + 1900,
+                                 suspend_rtc_tm.tm_mon + 1,
+                                 suspend_rtc_tm.tm_mday,
+                                 suspend_rtc_tm.tm_hour,
+                                 suspend_rtc_tm.tm_min,
+                                 suspend_rtc_tm.tm_sec);
 
        return 0;
 }
index 7d3b09b7d5449244683e97ab0b6539b9072a345c..a113d800cbf0eba4e5ac235fafa9e0bf363b425b 100644 (file)
@@ -72,12 +72,11 @@ static int __init tsi108_eth_of_init(void)
        int ret;
 
        for (np = NULL, i = 0;
-            (np = of_find_compatible_node(np, "network", "tsi-ethernet")) != NULL;
+            (np = of_find_compatible_node(np, "network", "tsi108-ethernet")) != NULL;
             i++) {
                struct resource r[2];
-               struct device_node *phy;
+               struct device_node *phy, *mdio;
                hw_info tsi_eth_data;
-               const unsigned int *id;
                const unsigned int *phy_id;
                const void *mac_addr;
                const phandle *ph;
@@ -111,6 +110,13 @@ static int __init tsi108_eth_of_init(void)
                if (mac_addr)
                        memcpy(tsi_eth_data.mac_addr, mac_addr, 6);
 
+               ph = of_get_property(np, "mdio-handle", NULL);
+               mdio = of_find_node_by_phandle(*ph);
+               ret = of_address_to_resource(mdio, 0, &res);
+               of_node_put(mdio);
+               if (ret)
+                       goto unreg;
+
                ph = of_get_property(np, "phy-handle", NULL);
                phy = of_find_node_by_phandle(*ph);
 
@@ -119,20 +125,25 @@ static int __init tsi108_eth_of_init(void)
                        goto unreg;
                }
 
-               id = of_get_property(phy, "reg", NULL);
-               phy_id = of_get_property(phy, "phy-id", NULL);
-               ret = of_address_to_resource(phy, 0, &res);
-               if (ret) {
-                       of_node_put(phy);
-                       goto unreg;
-               }
+               phy_id = of_get_property(phy, "reg", NULL);
+
                tsi_eth_data.regs = r[0].start;
                tsi_eth_data.phyregs = res.start;
                tsi_eth_data.phy = *phy_id;
                tsi_eth_data.irq_num = irq_of_parse_and_map(np, 0);
-               if (of_device_is_compatible(phy, "bcm54xx"))
+
+               /* Some boards with the TSI108 bridge (e.g. Holly)
+                * have a miswiring of the ethernet PHYs which
+                * requires a workaround.  The special
+                * "txc-rxc-delay-disable" property enables this
+                * workaround.  FIXME: Need to port the tsi108_eth
+                * driver itself to phylib and use a non-misleading
+                * name for the workaround flag - it's not actually to
+                * do with the model of PHY in use */
+               if (of_get_property(phy, "txc-rxc-delay-disable", NULL))
                        tsi_eth_data.phy_type = TSI108_PHY_BCM54XX;
                of_node_put(phy);
+
                ret =
                    platform_device_add_data(tsi_eth_dev, &tsi_eth_data,
                                             sizeof(hw_info));
index 2153163fa593b22643f09f2aa4b2d4a3ba1a3d55..90db8a720fedec7198c972fd2e48925a944e37db 100644 (file)
@@ -64,9 +64,10 @@ tsi108_direct_write_config(struct pci_bus *bus, unsigned int devfunc,
                           int offset, int len, u32 val)
 {
        volatile unsigned char *cfg_addr;
+       struct pci_controller *hose = bus->sysdata;
 
        if (ppc_md.pci_exclude_device)
-               if (ppc_md.pci_exclude_device(bus->number, devfunc))
+               if (ppc_md.pci_exclude_device(hose, bus->number, devfunc))
                        return PCIBIOS_DEVICE_NOT_FOUND;
 
        cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
@@ -149,10 +150,11 @@ tsi108_direct_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
                          int len, u32 * val)
 {
        volatile unsigned char *cfg_addr;
+       struct pci_controller *hose = bus->sysdata;
        u32 temp;
 
        if (ppc_md.pci_exclude_device)
-               if (ppc_md.pci_exclude_device(bus->number, devfn))
+               if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
                        return PCIBIOS_DEVICE_NOT_FOUND;
 
        cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
@@ -219,14 +221,12 @@ int __init tsi108_setup_pci(struct device_node *dev, u32 cfg_phys, int primary)
                       " bus 0\n", dev->full_name);
        }
 
-       hose = pcibios_alloc_controller();
+       hose = pcibios_alloc_controller(dev);
 
        if (!hose) {
                printk("PCI Host bridge init failed\n");
                return -ENOMEM;
        }
-       hose->arch_data = dev;
-       hose->set_cfg_type = 1;
 
        hose->first_busno = bus_range ? bus_range[0] : 0;
        hose->last_busno = bus_range ? bus_range[1] : 0xff;
index 28fdf4f50c274e2b574aacf58945e13af45c89a3..669e6566ad70983fc2fa1d3a246460521d3cf059 100644 (file)
@@ -2634,7 +2634,7 @@ static int __init setup_xmon_sysrq(void)
 __initcall(setup_xmon_sysrq);
 #endif /* CONFIG_MAGIC_SYSRQ */
 
-int __initdata xmon_early, xmon_off;
+static int __initdata xmon_early, xmon_off;
 
 static int __init early_parse_xmon(char *p)
 {
index d319f9ba2379d812f31d5bfbc8b249989de79636..0da55368655c90a0018504d79c0125fd51326e25 100644 (file)
@@ -328,7 +328,7 @@ BEGIN_FTR_SECTION
        mtspr   SPRN_L1CSR0,r3
        isync
        blr
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE)
        mfspr   r3,SPRN_L1CSR1
        ori     r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
        mtspr   SPRN_L1CSR1,r3
@@ -355,7 +355,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
 _GLOBAL(__flush_icache_range)
 BEGIN_FTR_SECTION
        blr                             /* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
        li      r5,L1_CACHE_BYTES-1
        andc    r3,r3,r5
        subf    r4,r3,r4
@@ -472,7 +472,7 @@ _GLOBAL(flush_dcache_all)
 _GLOBAL(__flush_dcache_icache)
 BEGIN_FTR_SECTION
        blr                                     /* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
        rlwinm  r3,r3,0,0,19                    /* Get page base address */
        li      r4,4096/L1_CACHE_BYTES  /* Number of lines in a page */
        mtctr   r4
@@ -500,7 +500,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
 _GLOBAL(__flush_dcache_icache_phys)
 BEGIN_FTR_SECTION
        blr                                     /* for 601, do nothing */
-END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
        mfmsr   r10
        rlwinm  r0,r10,0,28,26                  /* clear DR */
        mtmsr   r0
index a4165209ac7cd738499087a71cb74c92336f6d0d..63f0a987139b4335b2255a76f5834ea47ac5dcb5 100644 (file)
@@ -64,7 +64,6 @@ extern unsigned long mm_ptov (unsigned long paddr);
 
 EXPORT_SYMBOL(clear_pages);
 EXPORT_SYMBOL(clear_user_page);
-EXPORT_SYMBOL(do_signal);
 EXPORT_SYMBOL(transfer_to_handler);
 EXPORT_SYMBOL(do_IRQ);
 EXPORT_SYMBOL(machine_check_exception);
index c79704f5409c52a14db7fd7576c49985a6618e38..967c1ef59a6bd10f91abe56c95e3f6cb97faabd0 100644 (file)
@@ -526,7 +526,7 @@ void __init setup_arch(char **cmdline_p)
         * Systems with OF can look in the properties on the cpu node(s)
         * for a possibly more accurate value.
         */
-       if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) {
+       if (! cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE)) {
                dcache_bsize = cur_cpu_spec->dcache_bsize;
                icache_bsize = cur_cpu_spec->icache_bsize;
                ucache_bsize = 0;
index fa29740a28f57dade5052629de5f625cdbc8a56c..4ff260bc9dd1d1dffb0ebb2f66cf1908f1656d49 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/highmem.h>
+#include <linux/pagemap.h>
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
 
index 6f21110a9747ef20b216edf38b5701eb91c12e0f..3c56654bfc6f28580a42a7e4cc4a043dcd8e300d 100644 (file)
@@ -69,9 +69,6 @@
 
 TODC_ALLOC();
 
-unsigned char ucBoardRev;
-unsigned char ucBoardRevMaj, ucBoardRevMin;
-
 extern unsigned char prep_nvram_read_val(int addr);
 extern void prep_nvram_write_val(int addr,
                                 unsigned char val);
index 95694159b22602310fa088e39c8bb4d628792674..543795be58c8a769ef0b447f4e13a98da27cd394 100644 (file)
@@ -7,6 +7,7 @@ CFLAGS_btext.o          += -fPIC
 
 wdt-mpc8xx-$(CONFIG_8xx_WDT)   += m8xx_wdt.o
 
+obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
 obj-$(CONFIG_PPCBUG_NVRAM)     += prep_nvram.o
 obj-$(CONFIG_PPC_OCP)          += ocp.o
 obj-$(CONFIG_IBM_OCP)          += ibm_ocp.o
diff --git a/arch/ppc/syslib/indirect_pci.c b/arch/ppc/syslib/indirect_pci.c
new file mode 100644 (file)
index 0000000..83b323a
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Support for indirect PCI bridges.
+ *
+ * Copyright (C) 1998 Gabriel Paubert.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+
+#ifdef CONFIG_PPC_INDIRECT_PCI_BE
+#define PCI_CFG_OUT out_be32
+#else
+#define PCI_CFG_OUT out_le32
+#endif
+
+static int
+indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+                    int len, u32 *val)
+{
+       struct pci_controller *hose = bus->sysdata;
+       volatile void __iomem *cfg_data;
+       u8 cfg_type = 0;
+
+       if (ppc_md.pci_exclude_device)
+               if (ppc_md.pci_exclude_device(bus->number, devfn))
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+
+       if (hose->set_cfg_type)
+               if (bus->number != hose->first_busno)
+                       cfg_type = 1;
+
+       PCI_CFG_OUT(hose->cfg_addr,
+                (0x80000000 | ((bus->number - hose->bus_offset) << 16)
+                 | (devfn << 8) | ((offset & 0xfc) | cfg_type)));
+
+       /*
+        * Note: the caller has already checked that offset is
+        * suitably aligned and that len is 1, 2 or 4.
+        */
+       cfg_data = hose->cfg_data + (offset & 3);
+       switch (len) {
+       case 1:
+               *val = in_8(cfg_data);
+               break;
+       case 2:
+               *val = in_le16(cfg_data);
+               break;
+       default:
+               *val = in_le32(cfg_data);
+               break;
+       }
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+                     int len, u32 val)
+{
+       struct pci_controller *hose = bus->sysdata;
+       volatile void __iomem *cfg_data;
+       u8 cfg_type = 0;
+
+       if (ppc_md.pci_exclude_device)
+               if (ppc_md.pci_exclude_device(bus->number, devfn))
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+
+       if (hose->set_cfg_type)
+               if (bus->number != hose->first_busno)
+                       cfg_type = 1;
+
+       PCI_CFG_OUT(hose->cfg_addr,
+                (0x80000000 | ((bus->number - hose->bus_offset) << 16)
+                 | (devfn << 8) | ((offset & 0xfc) | cfg_type)));
+
+       /*
+        * Note: the caller has already checked that offset is
+        * suitably aligned and that len is 1, 2 or 4.
+        */
+       cfg_data = hose->cfg_data + (offset & 3);
+       switch (len) {
+       case 1:
+               out_8(cfg_data, val);
+               break;
+       case 2:
+               out_le16(cfg_data, val);
+               break;
+       default:
+               out_le32(cfg_data, val);
+               break;
+       }
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops indirect_pci_ops =
+{
+       indirect_read_config,
+       indirect_write_config
+};
+
+void __init
+setup_indirect_pci_nomap(struct pci_controller* hose, void __iomem * cfg_addr,
+       void __iomem * cfg_data)
+{
+       hose->cfg_addr = cfg_addr;
+       hose->cfg_data = cfg_data;
+       hose->ops = &indirect_pci_ops;
+}
+
+void __init
+setup_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
+{
+       unsigned long base = cfg_addr & PAGE_MASK;
+       void __iomem *mbase, *addr, *data;
+
+       mbase = ioremap(base, PAGE_SIZE);
+       addr = mbase + (cfg_addr & ~PAGE_MASK);
+       if ((cfg_data & PAGE_MASK) != base)
+               mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
+       data = mbase + (cfg_data & ~PAGE_MASK);
+       setup_indirect_pci_nomap(hose, addr, data);
+}
index 16546788e23b59faea05d1769da6eca2e49c53fa..ace4ec08de5118f5e68fc4286f19ec8f5b27d094 100644 (file)
        }, \
 }
 
+/*
+ * ML300/ML403 Video Device: shortcut macro for single instance
+ */
+#define XPAR_TFT(num) { \
+       .name = "xilinxfb", \
+       .id = num, \
+       .num_resources = 1, \
+       .resource = (struct resource[]) { \
+               { \
+                       .start = XPAR_TFT_##num##_BASEADDR, \
+                       .end = XPAR_TFT_##num##_BASEADDR+7, \
+                       .flags = IORESOURCE_IO, \
+               }, \
+       }, \
+}
 
 /* UART 8250 driver platform data table */
 struct plat_serial8250_port virtex_serial_platform_data[] = {
@@ -146,20 +161,17 @@ struct platform_device virtex_platform_devices[] = {
        XPAR_SYSACE(1),
 #endif
 
-       /* ML300/403 reference design framebuffer */
 #if defined(XPAR_TFT_0_BASEADDR)
-       {
-               .name           = "xilinxfb",
-               .id             = 0,
-               .num_resources  = 1,
-               .resource = (struct resource[]) {
-                       {
-                               .start  = XPAR_TFT_0_BASEADDR,
-                               .end    = XPAR_TFT_0_BASEADDR+7,
-                               .flags  = IORESOURCE_IO,
-                       },
-               },
-       },
+       XPAR_TFT(0),
+#endif
+#if defined(XPAR_TFT_1_BASEADDR)
+       XPAR_TFT(1),
+#endif
+#if defined(XPAR_TFT_2_BASEADDR)
+       XPAR_TFT(2),
+#endif
+#if defined(XPAR_TFT_3_BASEADDR)
+       XPAR_TFT(3),
 #endif
 };
 
index 68592c3360111ef47de71cb88858bfb25d5b8a31..dae39911a11dd37a93c7c0323423c0d78357a563 100644 (file)
@@ -252,10 +252,10 @@ static int viodasd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
        struct gendisk *disk = bdev->bd_disk;
        struct viodasd_device *d = disk->private_data;
 
-       geo->sectors = d->sectors ? d->sectors : 0;
+       geo->sectors = d->sectors ? d->sectors : 32;
        geo->heads = d->tracks ? d->tracks  : 64;
        geo->cylinders = d->cylinders ? d->cylinders :
-               get_capacity(disk) / (geo->cylinders * geo->heads);
+               get_capacity(disk) / (geo->sectors * geo->heads);
 
        return 0;
 }
index ed53f541d9e8a90e2aa4d06cd4952a1372512013..b6f2639f903d344754f211f12e7e630759e2861a 100644 (file)
@@ -91,11 +91,6 @@ static ssize_t briq_panel_read(struct file *file, char __user *buf, size_t count
        unsigned short c;
        unsigned char cp;
 
-#if 0  /*  Can't seek (pread) on this device  */
-       if (ppos != &file->f_pos)
-               return -ESPIPE;
-#endif
-
        if (!vfd_is_open)
                return -ENODEV;
 
@@ -139,11 +134,6 @@ static ssize_t briq_panel_write(struct file *file, const char __user *buf, size_
        size_t indx = len;
        int i, esc = 0;
 
-#if 0  /*  Can't seek (pwrite) on this device  */
-       if (ppos != &file->f_pos)
-               return -ESPIPE;
-#endif
-
        if (!vfd_is_open)
                return -EBUSY;
 
index 322bc5f7d86b791dd8350642c1b390fe6b54784c..b3ab42e0dd4af4599c32483c35cb104e8416fddb 100644 (file)
@@ -674,7 +674,7 @@ static const cpumask_t cpus_in_xmon = CPU_MASK_NONE;
  * calling hvc_poll() who determines whether a console adapter support
  * interrupts.
  */
-int khvcd(void *unused)
+static int khvcd(void *unused)
 {
        int poll_mask;
        struct hvc_struct *hp;
index 13faf8d17482a58fdd3dcee95e33769f4bbb6b59..db57277117bb4015b94e280adfab125a5e8870d4 100644 (file)
@@ -873,12 +873,12 @@ free_op:
 }
 
 const struct file_operations viotap_fops = {
-       owner: THIS_MODULE,
-       read: viotap_read,
-       write: viotap_write,
-       ioctl: viotap_ioctl,
-       open: viotap_open,
-       release: viotap_release,
+       .owner =        THIS_MODULE,
+       .read =         viotap_read,
+       .write =        viotap_write,
+       .ioctl =        viotap_ioctl,
+       .open =         viotap_open,
+       .release =      viotap_release,
 };
 
 /* Handle interrupt events for tape */
index bb3c101c2c5ae6b8cf47be0603bd5f93b0d335b1..deb6b5e35febfd47d32dea6b74c6a5543f2d5f12 100644 (file)
@@ -159,8 +159,8 @@ static void dlpar_pci_add_bus(struct device_node *dn)
        /* Claim new bus resources */
        pcibios_claim_one_bus(dev->bus);
 
-       /* ioremap() for child bus, which may or may not succeed */
-       remap_bus_range(dev->subordinate);
+       /* Map IO space for child bus, which may or may not succeed */
+       pcibios_map_io_space(dev->subordinate);
 
        /* Add new devices to global lists.  Register in proc, sysfs. */
        pci_bus_add_devices(phb->bus);
@@ -390,7 +390,7 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
        } else
                pcibios_remove_pci_devices(bus);
 
-       if (unmap_bus_range(bus)) {
+       if (pcibios_unmap_io_space(bus)) {
                printk(KERN_ERR "%s: failed to unmap bus range\n",
                        __FUNCTION__);
                return -ERANGE;
index 35f88649d3b7424b5809386c63915c1d44f0a4e5..c0c77f82d051ee4ab8dcc910f4278e7458528f22 100644 (file)
@@ -180,14 +180,15 @@ config TCIC
          PCMCIA cards are plugged into. If unsure, say N.
 
 config PCMCIA_M8XX
-        tristate "MPC8xx PCMCIA support"
-        depends on PCMCIA && PPC && 8xx 
-        select PCCARD_IODYN
-        help
-        Say Y here to include support for PowerPC 8xx series PCMCIA
-        controller.
-
-        This driver is also available as a module called m8xx_pcmcia.
+       tristate "MPC8xx PCMCIA support"
+       depends on PCMCIA && PPC && 8xx
+       select PCCARD_IODYN
+       select PCCARD_NONSTATIC
+       help
+         Say Y here to include support for PowerPC 8xx series PCMCIA
+         controller.
+
+         This driver is also available as a module called m8xx_pcmcia.
 
 config HD64465_PCMCIA
        tristate "HD64465 host bridge support"
index 9721ed7bf5023e704726af89073a51e9e54a85b7..3b40f9623cc9bb2c1bda5ea4d8f8c4d98ad50b47 100644 (file)
@@ -10,7 +10,7 @@
  * Further fixes, v2.6 kernel port
  *     <marcelo.tosatti@cyclades.com>
  * 
- * Some fixes, additions (C) 2005 Montavista Software, Inc. 
+ * Some fixes, additions (C) 2005-2007 Montavista Software, Inc.
  *     <vbordug@ru.mvista.com>
  *
  * "The ExCA standard specifies that socket controllers should provide
 #include <linux/fcntl.h>
 #include <linux/string.h>
 
-#include <asm/io.h>
-#include <asm/bitops.h>
-#include <asm/system.h>
-
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
 
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <asm/system.h>
+#include <asm/time.h>
 #include <asm/mpc8xx.h>
 #include <asm/8xx_immap.h>
 #include <asm/irq.h>
+#include <asm/fs_pd.h>
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
 
 #include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
@@ -146,27 +149,17 @@ MODULE_LICENSE("Dual MPL/GPL");
 #define PCMCIA_MEM_WIN_BASE 0xe0000000 /* base address for memory window 0   */
 #define PCMCIA_MEM_WIN_SIZE 0x04000000 /* each memory window is 64 MByte     */
 #define PCMCIA_IO_WIN_BASE  _IO_BASE   /* base address for io window 0       */
-
-#define PCMCIA_SCHLVL PCMCIA_INTERRUPT /* Status Change Interrupt Level      */
-
 /* ------------------------------------------------------------------------- */
 
-/* 2.4.x and newer has this always in HZ */
-#define M8XX_BUSFREQ ((((bd_t *)&(__res))->bi_busfreq))
-
-static int pcmcia_schlvl = PCMCIA_SCHLVL;
+static int pcmcia_schlvl;
 
 static DEFINE_SPINLOCK(events_lock);
 
-
 #define PCMCIA_SOCKET_KEY_5V 1
 #define PCMCIA_SOCKET_KEY_LV 2
 
 /* look up table for pgcrx registers */
-static u32 *m8xx_pgcrx[2] = {
-       &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcra,
-       &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcrb
-};
+static u32 *m8xx_pgcrx[2];
 
 /*
  * This structure is used to address each window in the PCMCIA controller.
@@ -228,11 +221,16 @@ struct event_table {
        u32 eventbit;
 };
 
+static const char driver_name[] = "m8xx-pcmcia";
+
 struct socket_info {
        void    (*handler)(void *info, u32 events);
        void    *info;
 
        u32 slot;
+       pcmconf8xx_t *pcmcia;
+       u32 bus_freq;
+       int hwirq;
 
        socket_state_t state;
        struct pccard_mem_map mem_win[PCMCIA_MEM_WIN_NO];
@@ -408,78 +406,21 @@ static void hardware_disable(int slot)
 #if defined(CONFIG_MPC885ADS)
 
 #define PCMCIA_BOARD_MSG "MPC885ADS"
+#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
 
-static int voltage_set(int slot, int vcc, int vpp)
+static inline void hardware_enable(int slot)
 {
-       u32 reg = 0;
-       unsigned *bcsr_io;
-
-       bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
-
-       switch(vcc) {
-               case 0:
-                       break;
-               case 33:
-                       reg |= BCSR1_PCCVCC0;
-                       break;
-               case 50:
-                       reg |= BCSR1_PCCVCC1;
-                       break;
-               default:
-                       goto out_unmap;
-       }
-
-       switch(vpp) {
-               case 0:
-                       break;
-               case 33:
-               case 50:
-                       if(vcc == vpp)
-                               reg |= BCSR1_PCCVPP1;
-                       else
-                               goto out_unmap;
-                       break;
-               case 120:
-                       if ((vcc == 33) || (vcc == 50))
-                               reg |= BCSR1_PCCVPP0;
-                       else
-                               goto out_unmap;
-               default:
-                       goto out_unmap;
-       }
-
-       /* first, turn off all power */
-       out_be32(bcsr_io, in_be32(bcsr_io) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK));
-
-       /* enable new powersettings */
-       out_be32(bcsr_io, in_be32(bcsr_io) | reg);
-
-       iounmap(bcsr_io);
-       return 0;
-
-out_unmap:
-       iounmap(bcsr_io);
-       return 1;
+        m8xx_pcmcia_ops.hw_ctrl(slot, 1);
 }
 
-#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
-
-static void hardware_enable(int slot)
+static inline void hardware_disable(int slot)
 {
-       unsigned *bcsr_io;
-
-       bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
-       out_be32(bcsr_io, in_be32(bcsr_io) & ~BCSR1_PCCEN);
-       iounmap(bcsr_io);
+       m8xx_pcmcia_ops.hw_ctrl(slot, 0);
 }
 
-static void hardware_disable(int slot)
+static inline int voltage_set(int slot, int vcc, int vpp)
 {
-       unsigned *bcsr_io;
-
-       bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
-       out_be32(bcsr_io, in_be32(bcsr_io) |  BCSR1_PCCEN);
-       iounmap(bcsr_io);
+       return m8xx_pcmcia_ops.voltage_set(slot, vcc, vpp);
 }
 
 #endif
@@ -604,48 +545,6 @@ static int voltage_set(int slot, int vcc, int vpp)
 
 #endif /* CONFIG_PRxK */
 
-static void m8xx_shutdown(void)
-{
-       u32 m, i;
-       struct pcmcia_win *w;
-
-       for(i = 0; i < PCMCIA_SOCKETS_NO; i++){
-               w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
-
-               out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, M8XX_PCMCIA_MASK(i));
-               out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) & ~M8XX_PCMCIA_MASK(i));
-
-               /* turn off interrupt and disable CxOE */
-               out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE);
-
-               /* turn off memory windows */
-               for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
-                       out_be32(&w->or, 0); /* set to not valid */
-                       w++;
-               }
-
-               /* turn off voltage */
-               voltage_set(i, 0, 0);
-
-               /* disable external hardware */
-               hardware_disable(i);
-       }
-
-       free_irq(pcmcia_schlvl, NULL);
-}
-
-static struct device_driver m8xx_driver = {
-        .name = "m8xx-pcmcia",
-        .bus = &platform_bus_type,
-        .suspend = pcmcia_socket_dev_suspend,
-        .resume = pcmcia_socket_dev_resume,
-};
-
-static struct platform_device m8xx_device = {
-        .name = "m8xx-pcmcia",
-        .id = 0,
-};
-
 static u32 pending_events[PCMCIA_SOCKETS_NO];
 static DEFINE_SPINLOCK(pending_event_lock);
 
@@ -654,13 +553,14 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev)
        struct socket_info *s;
        struct event_table *e;
        unsigned int i, events, pscr, pipr, per;
+       pcmconf8xx_t    *pcmcia = socket[0].pcmcia;
 
        dprintk("Interrupt!\n");
        /* get interrupt sources */
 
-       pscr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr);
-       pipr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr);
-       per = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per);
+       pscr = in_be32(&pcmcia->pcmc_pscr);
+       pipr = in_be32(&pcmcia->pcmc_pipr);
+       per = in_be32(&pcmcia->pcmc_per);
 
        for(i = 0; i < PCMCIA_SOCKETS_NO; i++) {
                s = &socket[i];
@@ -724,7 +624,7 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev)
                        per &= ~M8XX_PCMCIA_RDY_L(0);
                        per &= ~M8XX_PCMCIA_RDY_L(1);
 
-                       out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, per);
+                       out_be32(&pcmcia->pcmc_per, per);
 
                        if (events)
                                pcmcia_parse_events(&socket[i].socket, events);
@@ -732,7 +632,7 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev)
        }
 
        /* clear the interrupt sources */
-       out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, pscr);
+       out_be32(&pcmcia->pcmc_pscr, pscr);
 
        dprintk("Interrupt done.\n");
 
@@ -753,7 +653,7 @@ static u32 m8xx_get_graycode(u32 size)
        return k;
 }
 
-static u32 m8xx_get_speed(u32 ns, u32 is_io)
+static u32 m8xx_get_speed(u32 ns, u32 is_io, u32 bus_freq)
 {
        u32 reg, clocks, psst, psl, psht;
 
@@ -781,7 +681,7 @@ static u32 m8xx_get_speed(u32 ns, u32 is_io)
 
 #define ADJ 180 /* 80 % longer accesstime - to be sure */
 
-       clocks = ((M8XX_BUSFREQ / 1000) * ns) / 1000;
+       clocks = ((bus_freq / 1000) * ns) / 1000;
        clocks = (clocks * ADJ) / (100*1000);
        if(clocks >= PCMCIA_BMT_LIMIT) {
                printk( "Max access time limit reached\n");
@@ -806,8 +706,9 @@ static int m8xx_get_status(struct pcmcia_socket *sock, unsigned int *value)
        int lsock = container_of(sock, struct socket_info, socket)->slot;
        struct socket_info *s = &socket[lsock];
        unsigned int pipr, reg;
+       pcmconf8xx_t *pcmcia = s->pcmcia;
 
-       pipr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr);
+       pipr = in_be32(&pcmcia->pcmc_pipr);
 
        *value  = ((pipr & (M8XX_PCMCIA_CD1(lsock)
                            | M8XX_PCMCIA_CD2(lsock))) == 0) ? SS_DETECT : 0;
@@ -918,6 +819,7 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
        struct event_table *e;
        unsigned int reg;
        unsigned long flags;
+       pcmconf8xx_t *pcmcia = socket[0].pcmcia;
 
        dprintk( "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
              "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags,
@@ -927,6 +829,7 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
        if(voltage_set(lsock, state->Vcc, state->Vpp))
                return -EINVAL;
 
+
        /* Take care of reset... */
        if(state->flags & SS_RESET)
                out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) |  M8XX_PGCRX_CXRESET); /* active high */
@@ -982,7 +885,8 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
                 * If io_irq is non-zero we should enable irq.
                 */
                if(state->io_irq) {
-                       out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | mk_int_int_mask(state->io_irq) << 24);
+                       out_be32(M8XX_PGCRX(lsock),
+                                in_be32(M8XX_PGCRX(lsock)) | mk_int_int_mask(s->hwirq) << 24);
                        /*
                         * Strange thing here:
                         * The manual does not tell us which interrupt
@@ -1027,7 +931,7 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
         * Writing ones will clear the bits.
         */
 
-       out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, reg);
+       out_be32(&pcmcia->pcmc_pscr, reg);
 
        /*
         * Write the mask.
@@ -1036,15 +940,8 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
         * Ones will enable the interrupt.
         */
 
-       /*
-         reg |= ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per
-         & M8XX_PCMCIA_MASK(lsock);
-       */
-
-       reg |= in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) &
-               (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
-
-       out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, reg);
+       reg |= in_be32(&pcmcia->pcmc_per) & (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
+       out_be32(&pcmcia->pcmc_per, reg);
 
        spin_unlock_irqrestore(&events_lock, flags);
 
@@ -1062,6 +959,8 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
        struct socket_info *s = &socket[lsock];
        struct pcmcia_win *w;
        unsigned int reg, winnr;
+       pcmconf8xx_t *pcmcia = s->pcmcia;
+
 
 #define M8XX_SIZE (io->stop - io->start + 1)
 #define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start)
@@ -1086,7 +985,7 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
 
                /* setup registers */
 
-               w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+               w = (void *) &pcmcia->pcmc_pbr0;
                w += winnr;
 
                out_be32(&w->or, 0); /* turn off window first */
@@ -1095,12 +994,13 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
                reg <<= 27;
                reg |= M8XX_PCMCIA_POR_IO |(lsock << 2);
 
-               reg |= m8xx_get_speed(io->speed, 1);
+               reg |= m8xx_get_speed(io->speed, 1, s->bus_freq);
 
                if(io->flags & MAP_WRPROT)
                        reg |= M8XX_PCMCIA_POR_WRPROT;
 
-               if(io->flags & (MAP_16BIT | MAP_AUTOSZ))
+               /*if(io->flags & (MAP_16BIT | MAP_AUTOSZ))*/
+               if(io->flags & MAP_16BIT)
                        reg |= M8XX_PCMCIA_POR_16BIT;
 
                if(io->flags & MAP_ACTIVE)
@@ -1117,7 +1017,7 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
 
                /* setup registers */
 
-               w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+               w = (void *) &pcmcia->pcmc_pbr0;
                w += winnr;
 
                out_be32(&w->or, 0); /* turn off window */
@@ -1144,6 +1044,7 @@ static int m8xx_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *m
        struct pcmcia_win *w;
        struct pccard_mem_map *old;
        unsigned int reg, winnr;
+       pcmconf8xx_t *pcmcia = s->pcmcia;
 
        dprintk( "SetMemMap(%d, %d, %#2.2x, %d ns, "
              "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
@@ -1166,12 +1067,12 @@ static int m8xx_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *m
 
        /* Setup the window in the pcmcia controller */
 
-       w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+       w = (void *) &pcmcia->pcmc_pbr0;
        w += winnr;
 
        reg |= lsock << 2;
 
-       reg |= m8xx_get_speed(mem->speed, 0);
+       reg |= m8xx_get_speed(mem->speed, 0, s->bus_freq);
 
        if(mem->flags & MAP_ATTRIB)
                reg |=  M8XX_PCMCIA_POR_ATTRMEM;
@@ -1236,60 +1137,69 @@ static int m8xx_sock_init(struct pcmcia_socket *sock)
 
 }
 
-static int m8xx_suspend(struct pcmcia_socket *sock)
+static int m8xx_sock_suspend(struct pcmcia_socket *sock)
 {
        return m8xx_set_socket(sock, &dead_socket);
 }
 
 static struct pccard_operations m8xx_services = {
        .init   = m8xx_sock_init,
-       .suspend = m8xx_suspend,
+       .suspend = m8xx_sock_suspend,
        .get_status = m8xx_get_status,
        .set_socket = m8xx_set_socket,
        .set_io_map = m8xx_set_io_map,
        .set_mem_map = m8xx_set_mem_map,
 };
 
-static int __init m8xx_init(void)
+static int __init m8xx_probe(struct of_device *ofdev, const struct of_device_id *match)
 {
        struct pcmcia_win *w;
-       unsigned int i,m;
+       unsigned int i, m, hwirq;
+       pcmconf8xx_t *pcmcia;
+       int status;
+       struct device_node *np = ofdev->node;
 
        pcmcia_info("%s\n", version);
 
-       if (driver_register(&m8xx_driver))
-               return -1;
+       pcmcia = of_iomap(np, 0);
+       if(pcmcia == NULL)
+               return -EINVAL;
+
+       pcmcia_schlvl = irq_of_parse_and_map(np, 0);
+       hwirq  = irq_map[pcmcia_schlvl].hwirq;
+       if (pcmcia_schlvl < 0)
+               return -EINVAL;
+
+       m8xx_pgcrx[0] = &pcmcia->pcmc_pgcra;
+       m8xx_pgcrx[1] = &pcmcia->pcmc_pgcrb;
+
 
        pcmcia_info(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG
-                   " with IRQ %u.\n", pcmcia_schlvl);
+                   " with IRQ %u  (%d). \n", pcmcia_schlvl, hwirq);
 
        /* Configure Status change interrupt */
 
-       if(request_irq(pcmcia_schlvl, m8xx_interrupt, 0,
-                         "m8xx_pcmcia", NULL)) {
+       if(request_irq(pcmcia_schlvl, m8xx_interrupt, IRQF_SHARED,
+                         driver_name, socket)) {
                pcmcia_error("Cannot allocate IRQ %u for SCHLVL!\n",
                             pcmcia_schlvl);
                return -1;
        }
 
-       w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
-
-       out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr,
-               M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1));
+       w = (void *) &pcmcia->pcmc_pbr0;
 
-       out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per,
-               in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) &
-               ~(M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1)));
+       out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1));
+       clrbits32(&pcmcia->pcmc_per, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
 
-/* connect interrupt and disable CxOE */
+       /* connect interrupt and disable CxOE */
 
-       out_be32(M8XX_PGCRX(0), M8XX_PGCRX_CXOE | (mk_int_int_mask(pcmcia_schlvl) << 16));
-       out_be32(M8XX_PGCRX(1), M8XX_PGCRX_CXOE | (mk_int_int_mask(pcmcia_schlvl) << 16));
+       out_be32(M8XX_PGCRX(0), M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16));
+       out_be32(M8XX_PGCRX(1), M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16));
 
-/* intialize the fixed memory windows */
+       /* intialize the fixed memory windows */
 
        for(i = 0; i < PCMCIA_SOCKETS_NO; i++){
-               for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
+               for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
                        out_be32(&w->br, PCMCIA_MEM_WIN_BASE +
                                (PCMCIA_MEM_WIN_SIZE
                                 * (m + i * PCMCIA_MEM_WIN_NO)));
@@ -1300,16 +1210,14 @@ static int __init m8xx_init(void)
                }
        }
 
-/* turn off voltage */
+       /* turn off voltage */
        voltage_set(0, 0, 0);
        voltage_set(1, 0, 0);
 
-/* Enable external hardware */
+       /* Enable external hardware */
        hardware_enable(0);
        hardware_enable(1);
 
-       platform_device_register(&m8xx_device);
-
        for (i = 0 ; i < PCMCIA_SOCKETS_NO; i++) {
                socket[i].slot = i;
                socket[i].socket.owner = THIS_MODULE;
@@ -1317,30 +1225,105 @@ static int __init m8xx_init(void)
                socket[i].socket.irq_mask = 0x000;
                socket[i].socket.map_size = 0x1000;
                socket[i].socket.io_offset = 0;
-               socket[i].socket.pci_irq = i  ? 7 : 9;
+               socket[i].socket.pci_irq = pcmcia_schlvl;
                socket[i].socket.ops = &m8xx_services;
-               socket[i].socket.resource_ops = &pccard_iodyn_ops;
+               socket[i].socket.resource_ops = &pccard_nonstatic_ops;
                socket[i].socket.cb_dev = NULL;
-               socket[i].socket.dev.parent = &m8xx_device.dev;
+               socket[i].socket.dev.parent = &ofdev->dev;
+               socket[i].pcmcia = pcmcia;
+               socket[i].bus_freq = ppc_proc_freq;
+               socket[i].hwirq = hwirq;
+
+
        }
 
-       for (i = 0; i < PCMCIA_SOCKETS_NO; i++)
-               pcmcia_register_socket(&socket[i].socket);
+       for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
+               status = pcmcia_register_socket(&socket[i].socket);
+               if (status < 0)
+                       pcmcia_error("Socket register failed\n");
+       }
 
        return 0;
 }
 
-static void __exit m8xx_exit(void)
+static int m8xx_remove(struct of_device* ofdev)
 {
-       int i;
+       u32 m, i;
+       struct pcmcia_win *w;
+       pcmconf8xx_t *pcmcia = socket[0].pcmcia;
+
+       for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
+               w = (void *) &pcmcia->pcmc_pbr0;
+
+               out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(i));
+               out_be32(&pcmcia->pcmc_per,
+                       in_be32(&pcmcia->pcmc_per) & ~M8XX_PCMCIA_MASK(i));
 
+               /* turn off interrupt and disable CxOE */
+               out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE);
+
+               /* turn off memory windows */
+               for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
+                       out_be32(&w->or, 0); /* set to not valid */
+                       w++;
+               }
+
+               /* turn off voltage */
+               voltage_set(i, 0, 0);
+
+               /* disable external hardware */
+               hardware_disable(i);
+       }
        for (i = 0; i < PCMCIA_SOCKETS_NO; i++)
                pcmcia_unregister_socket(&socket[i].socket);
 
-       m8xx_shutdown();
+       free_irq(pcmcia_schlvl, NULL);
 
-       platform_device_unregister(&m8xx_device);
-       driver_unregister(&m8xx_driver);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int m8xx_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       return pcmcia_socket_dev_suspend(&pdev->dev, state);
+}
+
+static int m8xx_resume(struct platform_device *pdev)
+{
+       return pcmcia_socket_dev_resume(&pdev->dev);
+}
+#else
+#define m8xx_suspend NULL
+#define m8xx_resume NULL
+#endif
+
+static struct of_device_id m8xx_pcmcia_match[] = {
+       {
+               .type = "pcmcia",
+               .compatible = "fsl,pq-pcmcia",
+       },
+       {},
+};
+
+MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match);
+
+static struct of_platform_driver m8xx_pcmcia_driver = {
+       .name           = (char *) driver_name,
+       .match_table    = m8xx_pcmcia_match,
+       .probe          = m8xx_probe,
+       .remove         = m8xx_remove,
+       .suspend        = m8xx_suspend,
+       .resume         = m8xx_resume,
+};
+
+static int __init m8xx_init(void)
+{
+       return of_register_platform_driver(&m8xx_pcmcia_driver);
+}
+
+static void __exit m8xx_exit(void)
+{
+       of_unregister_platform_driver(&m8xx_pcmcia_driver);
 }
 
 module_init(m8xx_init);
index e251d1c1171c18592e469105ee588346c02ae03e..746031de2195c7a370b2343494a3cb6a56b3d366 100644 (file)
@@ -1,3 +1,6 @@
 obj-$(CONFIG_PS3_VUART) += vuart.o
-obj-$(CONFIG_PS3_PS3AV) += ps3av.o ps3av_cmd.o
+obj-$(CONFIG_PS3_PS3AV) += ps3av_mod.o
+ps3av_mod-objs         += ps3av.o ps3av_cmd.o
+obj-$(CONFIG_PPC_PS3) += sys-manager-core.o
 obj-$(CONFIG_PS3_SYS_MANAGER) += sys-manager.o
+obj-$(CONFIG_PS3_STORAGE) += ps3stor_lib.o
index 1393e64335f9b0b8804023a1970ae248a534b799..85e21614f8688e37cfeae21adb3ed0f7a88e3ceb 100644 (file)
@@ -1,32 +1,30 @@
 /*
- * Copyright (C) 2006 Sony Computer Entertainment Inc.
- * Copyright 2006, 2007 Sony Corporation
+ *  PS3 AV backend support.
  *
- * AV backend support for PS3
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony Corp.
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; version 2 of the License.
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
  *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/kernel.h>
 #include <linux/ioctl.h>
 
 #include <asm/firmware.h>
-#include <asm/lv1call.h>
 #include <asm/ps3av.h>
 #include <asm/ps3.h>
 
@@ -39,13 +37,12 @@ static int timeout = 5000;  /* in msec ( 5 sec ) */
 module_param(timeout, int, 0644);
 
 static struct ps3av {
-       int available;
        struct mutex mutex;
        struct work_struct work;
        struct completion done;
        struct workqueue_struct *wq;
        int open_count;
-       struct ps3_vuart_port_device *dev;
+       struct ps3_system_bus_device *dev;
 
        int region;
        struct ps3av_pkt_av_get_hw_conf av_hw_conf;
@@ -55,11 +52,13 @@ static struct ps3av {
        u32 audio_port;
        int ps3av_mode;
        int ps3av_mode_old;
-} ps3av;
-
-static struct ps3_vuart_port_device ps3av_dev = {
-       .match_id = PS3_MATCH_ID_AV_SETTINGS
-};
+       union {
+               struct ps3av_reply_hdr reply_hdr;
+               u8 raw[PS3AV_BUF_SIZE];
+       } recv_buf;
+       void (*flip_ctl)(int on, void *data);
+       void *flip_data;
+} *ps3av;
 
 /* color space */
 #define YUV444 PS3AV_CMD_VIDEO_CS_YUV444_8
@@ -169,7 +168,7 @@ static int ps3av_parse_event_packet(const struct ps3av_reply_hdr *hdr)
        if (hdr->cid & PS3AV_EVENT_CMD_MASK) {
                table = ps3av_search_cmd_table(hdr->cid, PS3AV_EVENT_CMD_MASK);
                if (table)
-                       dev_dbg(&ps3av_dev.core,
+                       dev_dbg(&ps3av->dev->core,
                                "recv event packet cid:%08x port:0x%x size:%d\n",
                                hdr->cid, ps3av_event_get_port_id(hdr->cid),
                                hdr->size);
@@ -182,6 +181,41 @@ static int ps3av_parse_event_packet(const struct ps3av_reply_hdr *hdr)
        return 0;
 }
 
+
+#define POLLING_INTERVAL  25   /* in msec */
+
+static int ps3av_vuart_write(struct ps3_system_bus_device *dev,
+                            const void *buf, unsigned long size)
+{
+       int error;
+       dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
+       error = ps3_vuart_write(dev, buf, size);
+       dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
+       return error ? error : size;
+}
+
+static int ps3av_vuart_read(struct ps3_system_bus_device *dev, void *buf,
+                           unsigned long size, int timeout)
+{
+       int error;
+       int loopcnt = 0;
+
+       dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
+       timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL;
+       while (loopcnt++ <= timeout) {
+               error = ps3_vuart_read(dev, buf, size);
+               if (!error)
+                       return size;
+               if (error != -EAGAIN) {
+                       printk(KERN_ERR "%s: ps3_vuart_read failed %d\n",
+                              __func__, error);
+                       return error;
+               }
+               msleep(POLLING_INTERVAL);
+       }
+       return -EWOULDBLOCK;
+}
+
 static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
                              struct ps3av_reply_hdr *recv_buf, int write_len,
                              int read_len)
@@ -190,13 +224,13 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
        u32 cmd;
        int event;
 
-       if (!ps3av.available)
+       if (!ps3av)
                return -ENODEV;
 
        /* send pkt */
-       res = ps3av_vuart_write(ps3av.dev, send_buf, write_len);
+       res = ps3av_vuart_write(ps3av->dev, send_buf, write_len);
        if (res < 0) {
-               dev_dbg(&ps3av_dev.core,
+               dev_dbg(&ps3av->dev->core,
                        "%s: ps3av_vuart_write() failed (result=%d)\n",
                        __func__, res);
                return res;
@@ -206,20 +240,20 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
        cmd = send_buf->cid;
        do {
                /* read header */
-               res = ps3av_vuart_read(ps3av.dev, recv_buf, PS3AV_HDR_SIZE,
+               res = ps3av_vuart_read(ps3av->dev, recv_buf, PS3AV_HDR_SIZE,
                                       timeout);
                if (res != PS3AV_HDR_SIZE) {
-                       dev_dbg(&ps3av_dev.core,
+                       dev_dbg(&ps3av->dev->core,
                                "%s: ps3av_vuart_read() failed (result=%d)\n",
                                __func__, res);
                        return res;
                }
 
                /* read body */
-               res = ps3av_vuart_read(ps3av.dev, &recv_buf->cid,
+               res = ps3av_vuart_read(ps3av->dev, &recv_buf->cid,
                                       recv_buf->size, timeout);
                if (res < 0) {
-                       dev_dbg(&ps3av_dev.core,
+                       dev_dbg(&ps3av->dev->core,
                                "%s: ps3av_vuart_read() failed (result=%d)\n",
                                __func__, res);
                        return res;
@@ -230,7 +264,7 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
        } while (event);
 
        if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) {
-               dev_dbg(&ps3av_dev.core, "%s: reply err (result=%x)\n",
+               dev_dbg(&ps3av->dev->core, "%s: reply err (result=%x)\n",
                        __func__, recv_buf->cid);
                return -EINVAL;
        }
@@ -245,7 +279,7 @@ static int ps3av_process_reply_packet(struct ps3av_send_hdr *cmd_buf,
        int return_len;
 
        if (recv_buf->version != PS3AV_VERSION) {
-               dev_dbg(&ps3av_dev.core, "reply_packet invalid version:%x\n",
+               dev_dbg(&ps3av->dev->core, "reply_packet invalid version:%x\n",
                        recv_buf->version);
                return -EFAULT;
        }
@@ -267,16 +301,11 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
                 struct ps3av_send_hdr *buf)
 {
        int res = 0;
-       static union {
-               struct ps3av_reply_hdr reply_hdr;
-               u8 raw[PS3AV_BUF_SIZE];
-       } recv_buf;
-
        u32 *table;
 
-       BUG_ON(!ps3av.available);
+       BUG_ON(!ps3av);
 
-       mutex_lock(&ps3av.mutex);
+       mutex_lock(&ps3av->mutex);
 
        table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK);
        BUG_ON(!table);
@@ -288,7 +317,7 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
        ps3av_set_hdr(cid, send_len, buf);
 
        /* send packet via vuart */
-       res = ps3av_send_cmd_pkt(buf, &recv_buf.reply_hdr, send_len,
+       res = ps3av_send_cmd_pkt(buf, &ps3av->recv_buf.reply_hdr, send_len,
                                 usr_buf_size);
        if (res < 0) {
                printk(KERN_ERR
@@ -298,7 +327,7 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
        }
 
        /* process reply packet */
-       res = ps3av_process_reply_packet(buf, &recv_buf.reply_hdr,
+       res = ps3av_process_reply_packet(buf, &ps3av->recv_buf.reply_hdr,
                                         usr_buf_size);
        if (res < 0) {
                printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n",
@@ -306,11 +335,11 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
                goto err;
        }
 
-       mutex_unlock(&ps3av.mutex);
+       mutex_unlock(&ps3av->mutex);
        return 0;
 
       err:
-       mutex_unlock(&ps3av.mutex);
+       mutex_unlock(&ps3av->mutex);
        printk(KERN_ERR "%s: failed cid:%x res:%d\n", __func__, cid, res);
        return res;
 }
@@ -319,11 +348,11 @@ static int ps3av_set_av_video_mute(u32 mute)
 {
        int i, num_of_av_port, res;
 
-       num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
-                        ps3av.av_hw_conf.num_of_avmulti;
+       num_of_av_port = ps3av->av_hw_conf.num_of_hdmi +
+                        ps3av->av_hw_conf.num_of_avmulti;
        /* video mute on */
        for (i = 0; i < num_of_av_port; i++) {
-               res = ps3av_cmd_av_video_mute(1, &ps3av.av_port[i], mute);
+               res = ps3av_cmd_av_video_mute(1, &ps3av->av_port[i], mute);
                if (res < 0)
                        return -1;
        }
@@ -335,13 +364,13 @@ static int ps3av_set_video_disable_sig(void)
 {
        int i, num_of_hdmi_port, num_of_av_port, res;
 
-       num_of_hdmi_port = ps3av.av_hw_conf.num_of_hdmi;
-       num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
-                        ps3av.av_hw_conf.num_of_avmulti;
+       num_of_hdmi_port = ps3av->av_hw_conf.num_of_hdmi;
+       num_of_av_port = ps3av->av_hw_conf.num_of_hdmi +
+                        ps3av->av_hw_conf.num_of_avmulti;
 
        /* tv mute */
        for (i = 0; i < num_of_hdmi_port; i++) {
-               res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
+               res = ps3av_cmd_av_tv_mute(ps3av->av_port[i],
                                           PS3AV_CMD_MUTE_ON);
                if (res < 0)
                        return -1;
@@ -350,11 +379,11 @@ static int ps3av_set_video_disable_sig(void)
 
        /* video mute on */
        for (i = 0; i < num_of_av_port; i++) {
-               res = ps3av_cmd_av_video_disable_sig(ps3av.av_port[i]);
+               res = ps3av_cmd_av_video_disable_sig(ps3av->av_port[i]);
                if (res < 0)
                        return -1;
                if (i < num_of_hdmi_port) {
-                       res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
+                       res = ps3av_cmd_av_tv_mute(ps3av->av_port[i],
                                                   PS3AV_CMD_MUTE_OFF);
                        if (res < 0)
                                return -1;
@@ -369,17 +398,17 @@ static int ps3av_set_audio_mute(u32 mute)
 {
        int i, num_of_av_port, num_of_opt_port, res;
 
-       num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
-                        ps3av.av_hw_conf.num_of_avmulti;
-       num_of_opt_port = ps3av.av_hw_conf.num_of_spdif;
+       num_of_av_port = ps3av->av_hw_conf.num_of_hdmi +
+                        ps3av->av_hw_conf.num_of_avmulti;
+       num_of_opt_port = ps3av->av_hw_conf.num_of_spdif;
 
        for (i = 0; i < num_of_av_port; i++) {
-               res = ps3av_cmd_av_audio_mute(1, &ps3av.av_port[i], mute);
+               res = ps3av_cmd_av_audio_mute(1, &ps3av->av_port[i], mute);
                if (res < 0)
                        return -1;
        }
        for (i = 0; i < num_of_opt_port; i++) {
-               res = ps3av_cmd_audio_mute(1, &ps3av.opt_port[i], mute);
+               res = ps3av_cmd_audio_mute(1, &ps3av->opt_port[i], mute);
                if (res < 0)
                        return -1;
        }
@@ -394,40 +423,40 @@ int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source)
        struct ps3av_pkt_audio_mode audio_mode;
        u32 len = 0;
 
-       num_of_audio = ps3av.av_hw_conf.num_of_hdmi +
-                      ps3av.av_hw_conf.num_of_avmulti +
-                      ps3av.av_hw_conf.num_of_spdif;
+       num_of_audio = ps3av->av_hw_conf.num_of_hdmi +
+                      ps3av->av_hw_conf.num_of_avmulti +
+                      ps3av->av_hw_conf.num_of_spdif;
 
        avb_param.num_of_video_pkt = 0;
        avb_param.num_of_audio_pkt = PS3AV_AVB_NUM_AUDIO;       /* always 0 */
        avb_param.num_of_av_video_pkt = 0;
-       avb_param.num_of_av_audio_pkt = ps3av.av_hw_conf.num_of_hdmi;
+       avb_param.num_of_av_audio_pkt = ps3av->av_hw_conf.num_of_hdmi;
 
-       vid = video_mode_table[ps3av.ps3av_mode].vid;
+       vid = video_mode_table[ps3av->ps3av_mode].vid;
 
        /* audio mute */
        ps3av_set_audio_mute(PS3AV_CMD_MUTE_ON);
 
        /* audio inactive */
-       res = ps3av_cmd_audio_active(0, ps3av.audio_port);
+       res = ps3av_cmd_audio_active(0, ps3av->audio_port);
        if (res < 0)
-               dev_dbg(&ps3av_dev.core,
+               dev_dbg(&ps3av->dev->core,
                        "ps3av_cmd_audio_active OFF failed\n");
 
        /* audio_pkt */
        for (i = 0; i < num_of_audio; i++) {
-               ps3av_cmd_set_audio_mode(&audio_mode, ps3av.av_port[i], ch, fs,
-                                        word_bits, format, source);
-               if (i < ps3av.av_hw_conf.num_of_hdmi) {
+               ps3av_cmd_set_audio_mode(&audio_mode, ps3av->av_port[i], ch,
+                                        fs, word_bits, format, source);
+               if (i < ps3av->av_hw_conf.num_of_hdmi) {
                        /* hdmi only */
                        len += ps3av_cmd_set_av_audio_param(&avb_param.buf[len],
-                                                           ps3av.av_port[i],
+                                                           ps3av->av_port[i],
                                                            &audio_mode, vid);
                }
                /* audio_mode pkt should be sent separately */
                res = ps3av_cmd_audio_mode(&audio_mode);
                if (res < 0)
-                       dev_dbg(&ps3av_dev.core,
+                       dev_dbg(&ps3av->dev->core,
                                "ps3av_cmd_audio_mode failed, port:%x\n", i);
        }
 
@@ -435,15 +464,16 @@ int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source)
        len += offsetof(struct ps3av_pkt_avb_param, buf);
        res = ps3av_cmd_avb_param(&avb_param, len);
        if (res < 0)
-               dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n");
+               dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n");
 
        /* audio mute */
        ps3av_set_audio_mute(PS3AV_CMD_MUTE_OFF);
 
        /* audio active */
-       res = ps3av_cmd_audio_active(1, ps3av.audio_port);
+       res = ps3av_cmd_audio_active(1, ps3av->audio_port);
        if (res < 0)
-               dev_dbg(&ps3av_dev.core, "ps3av_cmd_audio_active ON failed\n");
+               dev_dbg(&ps3av->dev->core,
+                       "ps3av_cmd_audio_active ON failed\n");
 
        return 0;
 }
@@ -456,7 +486,7 @@ static int ps3av_set_videomode(void)
        ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON);
 
        /* wake up ps3avd to do the actual video mode setting */
-       queue_work(ps3av.wq, &ps3av.work);
+       queue_work(ps3av->wq, &ps3av->work);
 
        return 0;
 }
@@ -473,8 +503,8 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id)
 
        avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO;       /* num of head */
        avb_param.num_of_audio_pkt = 0;
-       avb_param.num_of_av_video_pkt = ps3av.av_hw_conf.num_of_hdmi +
-                                       ps3av.av_hw_conf.num_of_avmulti;
+       avb_param.num_of_av_video_pkt = ps3av->av_hw_conf.num_of_hdmi +
+                                       ps3av->av_hw_conf.num_of_avmulti;
        avb_param.num_of_av_audio_pkt = 0;
 
        /* video signal off */
@@ -484,21 +514,21 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id)
        if (id & PS3AV_MODE_HDCP_OFF) {
                res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF);
                if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
-                       dev_dbg(&ps3av_dev.core, "Not supported\n");
+                       dev_dbg(&ps3av->dev->core, "Not supported\n");
                else if (res)
-                       dev_dbg(&ps3av_dev.core,
+                       dev_dbg(&ps3av->dev->core,
                                "ps3av_cmd_av_hdmi_mode failed\n");
        } else if (old_id & PS3AV_MODE_HDCP_OFF) {
                res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL);
                if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
-                       dev_dbg(&ps3av_dev.core,
+                       dev_dbg(&ps3av->dev->core,
                                "ps3av_cmd_av_hdmi_mode failed\n");
        }
 
        /* video_pkt */
        for (i = 0; i < avb_param.num_of_video_pkt; i++)
                len += ps3av_cmd_set_video_mode(&avb_param.buf[len],
-                                               ps3av.head[i], video_mode->vid,
+                                               ps3av->head[i], video_mode->vid,
                                                video_mode->fmt, id);
        /* av_video_pkt */
        for (i = 0; i < avb_param.num_of_av_video_pkt; i++) {
@@ -507,12 +537,12 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id)
                else
                        av_video_cs = video_mode->cs;
 #ifndef PS3AV_HDMI_YUV
-               if (ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 ||
-                   ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_1)
+               if (ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 ||
+                   ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_1)
                        av_video_cs = RGB8;     /* use RGB for HDMI */
 #endif
                len += ps3av_cmd_set_av_video_cs(&avb_param.buf[len],
-                                                ps3av.av_port[i],
+                                                ps3av->av_port[i],
                                                 video_mode->vid, av_video_cs,
                                                 video_mode->aspect, id);
        }
@@ -524,7 +554,7 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id)
                       "%s: Command failed. Please try your request again. \n",
                       __func__);
        else if (res)
-               dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n");
+               dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n");
 
        msleep(1500);
        /* av video mute */
@@ -533,8 +563,8 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id)
 
 static void ps3avd(struct work_struct *work)
 {
-       ps3av_set_videomode_cont(ps3av.ps3av_mode, ps3av.ps3av_mode_old);
-       complete(&ps3av.done);
+       ps3av_set_videomode_cont(ps3av->ps3av_mode, ps3av->ps3av_mode_old);
+       complete(&ps3av->done);
 }
 
 static int ps3av_vid2table_id(int vid)
@@ -601,7 +631,7 @@ static int ps3av_hdmi_get_vid(struct ps3av_info_monitor *info)
                return vid;
        }
 
-       if (ps3av.region & PS3AV_REGION_60)
+       if (ps3av->region & PS3AV_REGION_60)
                vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
        else
                vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
@@ -643,16 +673,16 @@ static int ps3av_auto_videomode(struct ps3av_pkt_av_get_hw_conf *av_hw_conf,
                vid = PS3AV_DEFAULT_DVI_VID;
        } else if (vid == -1) {
                /* no HDMI interface or HDMI is off */
-               if (ps3av.region & PS3AV_REGION_60)
+               if (ps3av->region & PS3AV_REGION_60)
                        vid = PS3AV_DEFAULT_AVMULTI_VID_REG_60;
                else
                        vid = PS3AV_DEFAULT_AVMULTI_VID_REG_50;
-               if (ps3av.region & PS3AV_REGION_RGB)
+               if (ps3av->region & PS3AV_REGION_RGB)
                        rgb = PS3AV_MODE_RGB;
        } else if (boot) {
                /* HDMI: using DEFAULT HDMI_VID while booting up */
                info = &monitor_info.info;
-               if (ps3av.region & PS3AV_REGION_60) {
+               if (ps3av->region & PS3AV_REGION_60) {
                        if (info->res_60.res_bits & PS3AV_RESBIT_720x480P)
                                vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
                        else if (info->res_50.res_bits & PS3AV_RESBIT_720x576P)
@@ -715,14 +745,14 @@ int ps3av_set_video_mode(u32 id, int boot)
 
        size = ARRAY_SIZE(video_mode_table);
        if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) {
-               dev_dbg(&ps3av_dev.core, "%s: error id :%d\n", __func__, id);
+               dev_dbg(&ps3av->dev->core, "%s: error id :%d\n", __func__, id);
                return -EINVAL;
        }
 
        /* auto mode */
        option = id & ~PS3AV_MODE_MASK;
        if ((id & PS3AV_MODE_MASK) == 0) {
-               id = ps3av_auto_videomode(&ps3av.av_hw_conf, boot);
+               id = ps3av_auto_videomode(&ps3av->av_hw_conf, boot);
                if (id < 1) {
                        printk(KERN_ERR "%s: invalid id :%d\n", __func__, id);
                        return -EINVAL;
@@ -731,11 +761,11 @@ int ps3av_set_video_mode(u32 id, int boot)
        }
 
        /* set videomode */
-       wait_for_completion(&ps3av.done);
-       ps3av.ps3av_mode_old = ps3av.ps3av_mode;
-       ps3av.ps3av_mode = id;
+       wait_for_completion(&ps3av->done);
+       ps3av->ps3av_mode_old = ps3av->ps3av_mode;
+       ps3av->ps3av_mode = id;
        if (ps3av_set_videomode())
-               ps3av.ps3av_mode = ps3av.ps3av_mode_old;
+               ps3av->ps3av_mode = ps3av->ps3av_mode_old;
 
        return 0;
 }
@@ -744,7 +774,7 @@ EXPORT_SYMBOL_GPL(ps3av_set_video_mode);
 
 int ps3av_get_auto_mode(int boot)
 {
-       return ps3av_auto_videomode(&ps3av.av_hw_conf, boot);
+       return ps3av_auto_videomode(&ps3av->av_hw_conf, boot);
 }
 
 EXPORT_SYMBOL_GPL(ps3av_get_auto_mode);
@@ -772,7 +802,7 @@ EXPORT_SYMBOL_GPL(ps3av_set_mode);
 
 int ps3av_get_mode(void)
 {
-       return ps3av.ps3av_mode;
+       return ps3av ? ps3av->ps3av_mode : 0;
 }
 
 EXPORT_SYMBOL_GPL(ps3av_get_mode);
@@ -842,82 +872,65 @@ int ps3av_audio_mute(int mute)
 
 EXPORT_SYMBOL_GPL(ps3av_audio_mute);
 
-int ps3av_dev_open(void)
+void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data),
+                            void *flip_data)
 {
-       int status = 0;
-
-       mutex_lock(&ps3av.mutex);
-       if (!ps3av.open_count++) {
-               status = lv1_gpu_open(0);
-               if (status) {
-                       printk(KERN_ERR "%s: lv1_gpu_open failed %d\n",
-                              __func__, status);
-                       ps3av.open_count--;
-               }
-       }
-       mutex_unlock(&ps3av.mutex);
-
-       return status;
+       mutex_lock(&ps3av->mutex);
+       ps3av->flip_ctl = flip_ctl;
+       ps3av->flip_data = flip_data;
+       mutex_unlock(&ps3av->mutex);
 }
+EXPORT_SYMBOL_GPL(ps3av_register_flip_ctl);
 
-EXPORT_SYMBOL_GPL(ps3av_dev_open);
-
-int ps3av_dev_close(void)
+void ps3av_flip_ctl(int on)
 {
-       int status = 0;
-
-       mutex_lock(&ps3av.mutex);
-       if (ps3av.open_count <= 0) {
-               printk(KERN_ERR "%s: GPU already closed\n", __func__);
-               status = -1;
-       } else if (!--ps3av.open_count) {
-               status = lv1_gpu_close();
-               if (status)
-                       printk(KERN_WARNING "%s: lv1_gpu_close failed %d\n",
-                              __func__, status);
-       }
-       mutex_unlock(&ps3av.mutex);
-
-       return status;
+       mutex_lock(&ps3av->mutex);
+       if (ps3av->flip_ctl)
+               ps3av->flip_ctl(on, ps3av->flip_data);
+       mutex_unlock(&ps3av->mutex);
 }
 
-EXPORT_SYMBOL_GPL(ps3av_dev_close);
-
-static int ps3av_probe(struct ps3_vuart_port_device *dev)
+static int ps3av_probe(struct ps3_system_bus_device *dev)
 {
        int res;
        u32 id;
 
-       dev_dbg(&ps3av_dev.core, "init ...\n");
-       dev_dbg(&ps3av_dev.core, "  timeout=%d\n", timeout);
+       dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
+       dev_dbg(&dev->core, "  timeout=%d\n", timeout);
 
-       memset(&ps3av, 0, sizeof(ps3av));
-
-       mutex_init(&ps3av.mutex);
-       ps3av.ps3av_mode = 0;
-       ps3av.dev = dev;
+       if (ps3av) {
+               dev_err(&dev->core, "Only one ps3av device is supported\n");
+               return -EBUSY;
+       }
 
-       INIT_WORK(&ps3av.work, ps3avd);
-       init_completion(&ps3av.done);
-       complete(&ps3av.done);
-       ps3av.wq = create_singlethread_workqueue("ps3avd");
-       if (!ps3av.wq)
+       ps3av = kzalloc(sizeof(*ps3av), GFP_KERNEL);
+       if (!ps3av)
                return -ENOMEM;
 
-       ps3av.available = 1;
+       mutex_init(&ps3av->mutex);
+       ps3av->ps3av_mode = 0;
+       ps3av->dev = dev;
+
+       INIT_WORK(&ps3av->work, ps3avd);
+       init_completion(&ps3av->done);
+       complete(&ps3av->done);
+       ps3av->wq = create_singlethread_workqueue("ps3avd");
+       if (!ps3av->wq)
+               goto fail;
+
        switch (ps3_os_area_get_av_multi_out()) {
        case PS3_PARAM_AV_MULTI_OUT_NTSC:
-               ps3av.region = PS3AV_REGION_60;
+               ps3av->region = PS3AV_REGION_60;
                break;
        case PS3_PARAM_AV_MULTI_OUT_PAL_YCBCR:
        case PS3_PARAM_AV_MULTI_OUT_SECAM:
-               ps3av.region = PS3AV_REGION_50;
+               ps3av->region = PS3AV_REGION_50;
                break;
        case PS3_PARAM_AV_MULTI_OUT_PAL_RGB:
-               ps3av.region = PS3AV_REGION_50 | PS3AV_REGION_RGB;
+               ps3av->region = PS3AV_REGION_50 | PS3AV_REGION_RGB;
                break;
        default:
-               ps3av.region = PS3AV_REGION_60;
+               ps3av->region = PS3AV_REGION_60;
                break;
        }
 
@@ -927,39 +940,47 @@ static int ps3av_probe(struct ps3_vuart_port_device *dev)
                printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __func__,
                       res);
 
-       ps3av_get_hw_conf(&ps3av);
-       id = ps3av_auto_videomode(&ps3av.av_hw_conf, 1);
-       mutex_lock(&ps3av.mutex);
-       ps3av.ps3av_mode = id;
-       mutex_unlock(&ps3av.mutex);
+       ps3av_get_hw_conf(ps3av);
+       id = ps3av_auto_videomode(&ps3av->av_hw_conf, 1);
+       mutex_lock(&ps3av->mutex);
+       ps3av->ps3av_mode = id;
+       mutex_unlock(&ps3av->mutex);
 
-       dev_dbg(&ps3av_dev.core, "init...done\n");
+       dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
 
        return 0;
+
+fail:
+       kfree(ps3av);
+       ps3av = NULL;
+       return -ENOMEM;
 }
 
-static int ps3av_remove(struct ps3_vuart_port_device *dev)
+static int ps3av_remove(struct ps3_system_bus_device *dev)
 {
-       if (ps3av.available) {
+       dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
+       if (ps3av) {
                ps3av_cmd_fin();
-               if (ps3av.wq)
-                       destroy_workqueue(ps3av.wq);
-               ps3av.available = 0;
+               if (ps3av->wq)
+                       destroy_workqueue(ps3av->wq);
+               kfree(ps3av);
+               ps3av = NULL;
        }
 
+       dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
        return 0;
 }
 
-static void ps3av_shutdown(struct ps3_vuart_port_device *dev)
+static void ps3av_shutdown(struct ps3_system_bus_device *dev)
 {
+       dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
        ps3av_remove(dev);
+       dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
 }
 
 static struct ps3_vuart_port_driver ps3av_driver = {
-       .match_id = PS3_MATCH_ID_AV_SETTINGS,
-       .core = {
-               .name = "ps3_av",
-       },
+       .core.match_id = PS3_MATCH_ID_AV_SETTINGS,
+       .core.core.name = "ps3_av",
        .probe = ps3av_probe,
        .remove = ps3av_remove,
        .shutdown = ps3av_shutdown,
@@ -972,6 +993,8 @@ static int ps3av_module_init(void)
        if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
                return -ENODEV;
 
+       pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
        error = ps3_vuart_port_driver_register(&ps3av_driver);
        if (error) {
                printk(KERN_ERR
@@ -980,20 +1003,21 @@ static int ps3av_module_init(void)
                return error;
        }
 
-       error = ps3_vuart_port_device_register(&ps3av_dev);
-       if (error)
-               printk(KERN_ERR
-                      "%s: ps3_vuart_port_device_register failed %d\n",
-                      __func__, error);
-
+       pr_debug(" <- %s:%d\n", __func__, __LINE__);
        return error;
 }
 
 static void __exit ps3av_module_exit(void)
 {
-       device_unregister(&ps3av_dev.core);
+       pr_debug(" -> %s:%d\n", __func__, __LINE__);
        ps3_vuart_port_driver_unregister(&ps3av_driver);
+       pr_debug(" <- %s:%d\n", __func__, __LINE__);
 }
 
 subsys_initcall(ps3av_module_init);
 module_exit(ps3av_module_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("PS3 AV Settings Driver");
+MODULE_AUTHOR("Sony Computer Entertainment Inc.");
+MODULE_ALIAS(PS3_MODULE_ALIAS_AV_SETTINGS);
index 0145ea173c42579067b1654404dff801f5edadee..f72f5ddf18e4e38e735ea9698e0645453879fcf9 100644 (file)
@@ -143,6 +143,14 @@ static u32 ps3av_vid_video2av(int vid)
        return PS3AV_CMD_AV_VID_480P;
 }
 
+static int ps3av_hdmi_range(void)
+{
+       if (ps3_compare_firmware_version(1, 8, 0) < 0)
+               return 0;
+       else
+               return 1; /* supported */
+}
+
 int ps3av_cmd_init(void)
 {
        int res;
@@ -350,6 +358,10 @@ u32 ps3av_cmd_set_av_video_cs(void *p, u32 avport, int video_vid, int cs_out,
        /* should be same as video_mode.video_cs_out */
        av_video_cs->av_cs_in = ps3av_cs_video2av(PS3AV_CMD_VIDEO_CS_RGB_8);
        av_video_cs->bitlen_out = ps3av_cs_video2av_bitlen(cs_out);
+       if ((id & PS3AV_MODE_WHITE) && ps3av_hdmi_range())
+               av_video_cs->super_white = PS3AV_CMD_AV_SUPER_WHITE_ON;
+       else /* default off */
+               av_video_cs->super_white = PS3AV_CMD_AV_SUPER_WHITE_OFF;
        av_video_cs->aspect = aspect;
        if (id & PS3AV_MODE_DITHER) {
                av_video_cs->dither = PS3AV_CMD_AV_DITHER_ON
@@ -392,6 +404,10 @@ u32 ps3av_cmd_set_video_mode(void *p, u32 head, int video_vid, int video_fmt,
        video_mode->pitch = video_mode->width * 4;      /* line_length */
        video_mode->video_out_format = PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT;
        video_mode->video_format = ps3av_video_fmt_table[video_fmt].format;
+       if ((id & PS3AV_MODE_COLOR) && ps3av_hdmi_range())
+               video_mode->video_cl_cnv = PS3AV_CMD_VIDEO_CL_CNV_DISABLE_LUT;
+       else /* default enable */
+               video_mode->video_cl_cnv = PS3AV_CMD_VIDEO_CL_CNV_ENABLE_LUT;
        video_mode->video_order = ps3av_video_fmt_table[video_fmt].order;
 
        pr_debug("%s: video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n",
@@ -852,7 +868,7 @@ int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len)
 {
        int res;
 
-       ps3fb_flip_ctl(0);      /* flip off */
+       ps3av_flip_ctl(0);      /* flip off */
 
        /* avb packet */
        res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb),
@@ -866,7 +882,7 @@ int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len)
                         res);
 
       out:
-       ps3fb_flip_ctl(1);      /* flip on */
+       ps3av_flip_ctl(1);      /* flip on */
        return res;
 }
 
@@ -987,34 +1003,3 @@ void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *
                | PS3AV_CMD_AV_LAYOUT_176 \
                | PS3AV_CMD_AV_LAYOUT_192)
 
-/************************* vuart ***************************/
-
-#define POLLING_INTERVAL  25   /* in msec */
-
-int ps3av_vuart_write(struct ps3_vuart_port_device *dev, const void *buf,
-                     unsigned long size)
-{
-       int error = ps3_vuart_write(dev, buf, size);
-       return error ? error : size;
-}
-
-int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
-                    unsigned long size, int timeout)
-{
-       int error;
-       int loopcnt = 0;
-
-       timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL;
-       while (loopcnt++ <= timeout) {
-               error = ps3_vuart_read(dev, buf, size);
-               if (!error)
-                       return size;
-               if (error != -EAGAIN) {
-                       printk(KERN_ERR "%s: ps3_vuart_read failed %d\n",
-                              __func__, error);
-                       return error;
-               }
-               msleep(POLLING_INTERVAL);
-       }
-       return -EWOULDBLOCK;
-}
diff --git a/drivers/ps3/ps3stor_lib.c b/drivers/ps3/ps3stor_lib.c
new file mode 100644 (file)
index 0000000..3a9824e
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+ * PS3 Storage Library
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2007 Sony Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/dma-mapping.h>
+
+#include <asm/lv1call.h>
+#include <asm/ps3stor.h>
+
+
+static int ps3stor_probe_access(struct ps3_storage_device *dev)
+{
+       int res, error;
+       unsigned int i;
+       unsigned long n;
+
+       if (dev->sbd.match_id == PS3_MATCH_ID_STOR_ROM) {
+               /* special case: CD-ROM is assumed always accessible */
+               dev->accessible_regions = 1;
+               return 0;
+       }
+
+       error = -EPERM;
+       for (i = 0; i < dev->num_regions; i++) {
+               dev_dbg(&dev->sbd.core,
+                       "%s:%u: checking accessibility of region %u\n",
+                       __func__, __LINE__, i);
+
+               dev->region_idx = i;
+               res = ps3stor_read_write_sectors(dev, dev->bounce_lpar, 0, 1,
+                                                0);
+               if (res) {
+                       dev_dbg(&dev->sbd.core, "%s:%u: read failed, "
+                               "region %u is not accessible\n", __func__,
+                               __LINE__, i);
+                       continue;
+               }
+
+               dev_dbg(&dev->sbd.core, "%s:%u: region %u is accessible\n",
+                       __func__, __LINE__, i);
+               set_bit(i, &dev->accessible_regions);
+
+               /* We can access at least one region */
+               error = 0;
+       }
+       if (error)
+               return error;
+
+       n = hweight_long(dev->accessible_regions);
+       if (n > 1)
+               dev_info(&dev->sbd.core,
+                        "%s:%u: %lu accessible regions found. Only the first "
+                        "one will be used",
+                        __func__, __LINE__, n);
+       dev->region_idx = __ffs(dev->accessible_regions);
+       dev_info(&dev->sbd.core,
+                "First accessible region has index %u start %lu size %lu\n",
+                dev->region_idx, dev->regions[dev->region_idx].start,
+                dev->regions[dev->region_idx].size);
+
+       return 0;
+}
+
+
+/**
+ *     ps3stor_setup - Setup a storage device before use
+ *     @dev: Pointer to a struct ps3_storage_device
+ *     @handler: Pointer to an interrupt handler
+ *
+ *     Returns 0 for success, or an error code
+ */
+int ps3stor_setup(struct ps3_storage_device *dev, irq_handler_t handler)
+{
+       int error, res, alignment;
+       enum ps3_dma_page_size page_size;
+
+       error = ps3_open_hv_device(&dev->sbd);
+       if (error) {
+               dev_err(&dev->sbd.core,
+                       "%s:%u: ps3_open_hv_device failed %d\n", __func__,
+                       __LINE__, error);
+               goto fail;
+       }
+
+       error = ps3_sb_event_receive_port_setup(&dev->sbd, PS3_BINDING_CPU_ANY,
+                                               &dev->irq);
+       if (error) {
+               dev_err(&dev->sbd.core,
+                       "%s:%u: ps3_sb_event_receive_port_setup failed %d\n",
+                      __func__, __LINE__, error);
+               goto fail_close_device;
+       }
+
+       error = request_irq(dev->irq, handler, IRQF_DISABLED,
+                           dev->sbd.core.driver->name, dev);
+       if (error) {
+               dev_err(&dev->sbd.core, "%s:%u: request_irq failed %d\n",
+                       __func__, __LINE__, error);
+               goto fail_sb_event_receive_port_destroy;
+       }
+
+       alignment = min(__ffs(dev->bounce_size),
+                       __ffs((unsigned long)dev->bounce_buf));
+       if (alignment < 12) {
+               dev_err(&dev->sbd.core,
+                       "%s:%u: bounce buffer not aligned (%lx at 0x%p)\n",
+                       __func__, __LINE__, dev->bounce_size, dev->bounce_buf);
+               error = -EINVAL;
+               goto fail_free_irq;
+       } else if (alignment < 16)
+               page_size = PS3_DMA_4K;
+       else
+               page_size = PS3_DMA_64K;
+       dev->sbd.d_region = &dev->dma_region;
+       ps3_dma_region_init(&dev->sbd, &dev->dma_region, page_size,
+                           PS3_DMA_OTHER, dev->bounce_buf, dev->bounce_size);
+       res = ps3_dma_region_create(&dev->dma_region);
+       if (res) {
+               dev_err(&dev->sbd.core, "%s:%u: cannot create DMA region\n",
+                       __func__, __LINE__);
+               error = -ENOMEM;
+               goto fail_free_irq;
+       }
+
+       dev->bounce_lpar = ps3_mm_phys_to_lpar(__pa(dev->bounce_buf));
+       dev->bounce_dma = dma_map_single(&dev->sbd.core, dev->bounce_buf,
+                                        dev->bounce_size, DMA_BIDIRECTIONAL);
+       if (!dev->bounce_dma) {
+               dev_err(&dev->sbd.core, "%s:%u: map DMA region failed\n",
+                       __func__, __LINE__);
+               error = -ENODEV;
+               goto fail_free_dma;
+       }
+
+       error = ps3stor_probe_access(dev);
+       if (error) {
+               dev_err(&dev->sbd.core, "%s:%u: No accessible regions found\n",
+                       __func__, __LINE__);
+               goto fail_unmap_dma;
+       }
+       return 0;
+
+fail_unmap_dma:
+       dma_unmap_single(&dev->sbd.core, dev->bounce_dma, dev->bounce_size,
+                        DMA_BIDIRECTIONAL);
+fail_free_dma:
+       ps3_dma_region_free(&dev->dma_region);
+fail_free_irq:
+       free_irq(dev->irq, dev);
+fail_sb_event_receive_port_destroy:
+       ps3_sb_event_receive_port_destroy(&dev->sbd, dev->irq);
+fail_close_device:
+       ps3_close_hv_device(&dev->sbd);
+fail:
+       return error;
+}
+EXPORT_SYMBOL_GPL(ps3stor_setup);
+
+
+/**
+ *     ps3stor_teardown - Tear down a storage device after use
+ *     @dev: Pointer to a struct ps3_storage_device
+ */
+void ps3stor_teardown(struct ps3_storage_device *dev)
+{
+       int error;
+
+       dma_unmap_single(&dev->sbd.core, dev->bounce_dma, dev->bounce_size,
+                        DMA_BIDIRECTIONAL);
+       ps3_dma_region_free(&dev->dma_region);
+
+       free_irq(dev->irq, dev);
+
+       error = ps3_sb_event_receive_port_destroy(&dev->sbd, dev->irq);
+       if (error)
+               dev_err(&dev->sbd.core,
+                       "%s:%u: destroy event receive port failed %d\n",
+                       __func__, __LINE__, error);
+
+       error = ps3_close_hv_device(&dev->sbd);
+       if (error)
+               dev_err(&dev->sbd.core,
+                       "%s:%u: ps3_close_hv_device failed %d\n", __func__,
+                       __LINE__, error);
+}
+EXPORT_SYMBOL_GPL(ps3stor_teardown);
+
+
+/**
+ *     ps3stor_read_write_sectors - read/write from/to a storage device
+ *     @dev: Pointer to a struct ps3_storage_device
+ *     @lpar: HV logical partition address
+ *     @start_sector: First sector to read/write
+ *     @sectors: Number of sectors to read/write
+ *     @write: Flag indicating write (non-zero) or read (zero)
+ *
+ *     Returns 0 for success, -1 in case of failure to submit the command, or
+ *     an LV1 status value in case of other errors
+ */
+u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar,
+                              u64 start_sector, u64 sectors, int write)
+{
+       unsigned int region_id = dev->regions[dev->region_idx].id;
+       const char *op = write ? "write" : "read";
+       int res;
+
+       dev_dbg(&dev->sbd.core, "%s:%u: %s %lu sectors starting at %lu\n",
+               __func__, __LINE__, op, sectors, start_sector);
+
+       init_completion(&dev->done);
+       res = write ? lv1_storage_write(dev->sbd.dev_id, region_id,
+                                       start_sector, sectors, 0, lpar,
+                                       &dev->tag)
+                   : lv1_storage_read(dev->sbd.dev_id, region_id,
+                                      start_sector, sectors, 0, lpar,
+                                      &dev->tag);
+       if (res) {
+               dev_dbg(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
+                       __LINE__, op, res);
+               return -1;
+       }
+
+       wait_for_completion(&dev->done);
+       if (dev->lv1_status) {
+               dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__,
+                       __LINE__, op, dev->lv1_status);
+               return dev->lv1_status;
+       }
+
+       dev_dbg(&dev->sbd.core, "%s:%u: %s completed\n", __func__, __LINE__,
+               op);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ps3stor_read_write_sectors);
+
+
+/**
+ *     ps3stor_send_command - send a device command to a storage device
+ *     @dev: Pointer to a struct ps3_storage_device
+ *     @cmd: Command number
+ *     @arg1: First command argument
+ *     @arg2: Second command argument
+ *     @arg3: Third command argument
+ *     @arg4: Fourth command argument
+ *
+ *     Returns 0 for success, -1 in case of failure to submit the command, or
+ *     an LV1 status value in case of other errors
+ */
+u64 ps3stor_send_command(struct ps3_storage_device *dev, u64 cmd, u64 arg1,
+                        u64 arg2, u64 arg3, u64 arg4)
+{
+       int res;
+
+       dev_dbg(&dev->sbd.core, "%s:%u: send device command 0x%lx\n", __func__,
+               __LINE__, cmd);
+
+       init_completion(&dev->done);
+
+       res = lv1_storage_send_device_command(dev->sbd.dev_id, cmd, arg1,
+                                             arg2, arg3, arg4, &dev->tag);
+       if (res) {
+               dev_err(&dev->sbd.core,
+                       "%s:%u: send_device_command 0x%lx failed %d\n",
+                       __func__, __LINE__, cmd, res);
+               return -1;
+       }
+
+       wait_for_completion(&dev->done);
+       if (dev->lv1_status) {
+               dev_dbg(&dev->sbd.core, "%s:%u: command 0x%lx failed 0x%lx\n",
+                       __func__, __LINE__, cmd, dev->lv1_status);
+               return dev->lv1_status;
+       }
+
+       dev_dbg(&dev->sbd.core, "%s:%u: command 0x%lx completed\n", __func__,
+               __LINE__, cmd);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ps3stor_send_command);
+
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PS3 Storage Bus Library");
+MODULE_AUTHOR("Sony Corporation");
diff --git a/drivers/ps3/sys-manager-core.c b/drivers/ps3/sys-manager-core.c
new file mode 100644 (file)
index 0000000..31648f7
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ *  PS3 System Manager core.
+ *
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <asm/ps3.h>
+
+/**
+ * Staticly linked routines that allow late binding of a loaded sys-manager
+ * module.
+ */
+
+static struct ps3_sys_manager_ops ps3_sys_manager_ops;
+
+/**
+ * ps3_register_sys_manager_ops - Bind ps3_sys_manager_ops to a module.
+ * @ops: struct ps3_sys_manager_ops.
+ *
+ * To be called from ps3_sys_manager_probe() and ps3_sys_manager_remove() to
+ * register call back ops for power control.  Copies data to the static
+ * variable ps3_sys_manager_ops.
+ */
+
+void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops)
+{
+       BUG_ON(!ops);
+       BUG_ON(!ops->dev);
+       ps3_sys_manager_ops = ops ? *ops : ps3_sys_manager_ops;
+}
+EXPORT_SYMBOL_GPL(ps3_sys_manager_register_ops);
+
+void ps3_sys_manager_power_off(void)
+{
+       if (ps3_sys_manager_ops.power_off)
+               ps3_sys_manager_ops.power_off(ps3_sys_manager_ops.dev);
+
+       printk(KERN_EMERG "System Halted, OK to turn off power\n");
+       local_irq_disable();
+       while (1)
+               (void)0;
+}
+
+void ps3_sys_manager_restart(void)
+{
+       if (ps3_sys_manager_ops.restart)
+               ps3_sys_manager_ops.restart(ps3_sys_manager_ops.dev);
+
+       printk(KERN_EMERG "System Halted, OK to turn off power\n");
+       local_irq_disable();
+       while (1)
+               (void)0;
+}
index 3aa2b0dcc36956d6afc9622530ea78b00e5b3290..8461b08ab9fb627e06b55bb97367cb783068bec4 100644 (file)
@@ -35,7 +35,7 @@ MODULE_DESCRIPTION("PS3 System Manager");
 /**
  * ps3_sys_manager - PS3 system manager driver.
  *
- * The system manager provides an asyncronous system event notification
+ * The system manager provides an asynchronous system event notification
  * mechanism for reporting events like thermal alert and button presses to
  * guests.  It also provides support to control system shutdown and startup.
  *
@@ -52,6 +52,7 @@ MODULE_DESCRIPTION("PS3 System Manager");
  * @size: Header size in bytes, curently 16.
  * @payload_size: Message payload size in bytes.
  * @service_id: Message type, one of enum ps3_sys_manager_service_id.
+ * @request_tag: Unique number to identify reply.
  */
 
 struct ps3_sys_manager_header {
@@ -61,29 +62,49 @@ struct ps3_sys_manager_header {
        u16 reserved_1;
        u32 payload_size;
        u16 service_id;
-       u16 reserved_2[3];
+       u16 reserved_2;
+       u32 request_tag;
 };
 
+#define dump_sm_header(_h) _dump_sm_header(_h, __func__, __LINE__)
+static void __maybe_unused _dump_sm_header(
+       const struct ps3_sys_manager_header *h, const char *func, int line)
+{
+       pr_debug("%s:%d: version:      %xh\n", func, line, h->version);
+       pr_debug("%s:%d: size:         %xh\n", func, line, h->size);
+       pr_debug("%s:%d: payload_size: %xh\n", func, line, h->payload_size);
+       pr_debug("%s:%d: service_id:   %xh\n", func, line, h->service_id);
+       pr_debug("%s:%d: request_tag:  %xh\n", func, line, h->request_tag);
+}
+
 /**
- * @PS3_SM_RX_MSG_LEN - System manager received message length.
+ * @PS3_SM_RX_MSG_LEN_MIN - Shortest received message length.
+ * @PS3_SM_RX_MSG_LEN_MAX - Longest received message length.
  *
- * Currently all messages received from the system manager are the same length
- * (16 bytes header + 16 bytes payload = 32 bytes).  This knowlege is used to
- * simplify the logic.
+ * Currently all messages received from the system manager are either
+ * (16 bytes header + 8 bytes payload = 24 bytes) or (16 bytes header
+ * + 16 bytes payload = 32 bytes).  This knowlege is used to simplify
+ * the logic.
  */
 
 enum {
-       PS3_SM_RX_MSG_LEN = 32,
+       PS3_SM_RX_MSG_LEN_MIN = 24,
+       PS3_SM_RX_MSG_LEN_MAX = 32,
 };
 
 /**
  * enum ps3_sys_manager_service_id - Message header service_id.
- * @PS3_SM_SERVICE_ID_REQUEST:      guest --> sys_manager.
- * @PS3_SM_SERVICE_ID_COMMAND:      guest <-- sys_manager.
- * @PS3_SM_SERVICE_ID_RESPONSE:     guest --> sys_manager.
- * @PS3_SM_SERVICE_ID_SET_ATTR:     guest --> sys_manager.
- * @PS3_SM_SERVICE_ID_EXTERN_EVENT: guest <-- sys_manager.
- * @PS3_SM_SERVICE_ID_SET_NEXT_OP:  guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_REQUEST:       guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_REQUEST_ERROR: guest <-- sys_manager.
+ * @PS3_SM_SERVICE_ID_COMMAND:       guest <-- sys_manager.
+ * @PS3_SM_SERVICE_ID_RESPONSE:      guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_SET_ATTR:      guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_EXTERN_EVENT:  guest <-- sys_manager.
+ * @PS3_SM_SERVICE_ID_SET_NEXT_OP:   guest --> sys_manager.
+ *
+ * PS3_SM_SERVICE_ID_REQUEST_ERROR is returned for invalid data values in a
+ * a PS3_SM_SERVICE_ID_REQUEST message.  It also seems to be returned when
+ * a REQUEST message is sent at the wrong time.
  */
 
 enum ps3_sys_manager_service_id {
@@ -93,6 +114,7 @@ enum ps3_sys_manager_service_id {
        PS3_SM_SERVICE_ID_COMMAND = 3,
        PS3_SM_SERVICE_ID_EXTERN_EVENT = 4,
        PS3_SM_SERVICE_ID_SET_NEXT_OP = 5,
+       PS3_SM_SERVICE_ID_REQUEST_ERROR = 6,
        PS3_SM_SERVICE_ID_SET_ATTR = 8,
 };
 
@@ -184,12 +206,22 @@ enum ps3_sys_manager_cmd {
        PS3_SM_CMD_SHUTDOWN = 1, /* shutdown guest OS */
 };
 
+/**
+ * ps3_sm_force_power_off - Poweroff helper.
+ *
+ * A global variable used to force a poweroff when the power button has
+ * been pressed irrespective of how init handles the ctrl_alt_del signal.
+ *
+ */
+
+static unsigned int ps3_sm_force_power_off;
+
 /**
  * ps3_sys_manager_write - Helper to write a two part message to the vuart.
  *
  */
 
-static int ps3_sys_manager_write(struct ps3_vuart_port_device *dev,
+static int ps3_sys_manager_write(struct ps3_system_bus_device *dev,
        const struct ps3_sys_manager_header *header, const void *payload)
 {
        int result;
@@ -213,15 +245,10 @@ static int ps3_sys_manager_write(struct ps3_vuart_port_device *dev,
  *
  */
 
-static int ps3_sys_manager_send_attr(struct ps3_vuart_port_device *dev,
+static int ps3_sys_manager_send_attr(struct ps3_system_bus_device *dev,
        enum ps3_sys_manager_attr attr)
 {
-       static const struct ps3_sys_manager_header header = {
-               .version = 1,
-               .size = 16,
-               .payload_size = 16,
-               .service_id = PS3_SM_SERVICE_ID_SET_ATTR,
-       };
+       struct ps3_sys_manager_header header;
        struct {
                u8 version;
                u8 reserved_1[3];
@@ -232,6 +259,12 @@ static int ps3_sys_manager_send_attr(struct ps3_vuart_port_device *dev,
 
        dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, attr);
 
+       memset(&header, 0, sizeof(header));
+       header.version = 1;
+       header.size = 16;
+       header.payload_size = 16;
+       header.service_id = PS3_SM_SERVICE_ID_SET_ATTR;
+
        memset(&payload, 0, sizeof(payload));
        payload.version = 1;
        payload.attribute = attr;
@@ -245,16 +278,11 @@ static int ps3_sys_manager_send_attr(struct ps3_vuart_port_device *dev,
  * Tell the system manager what to do after this lpar is destroyed.
  */
 
-static int ps3_sys_manager_send_next_op(struct ps3_vuart_port_device *dev,
+static int ps3_sys_manager_send_next_op(struct ps3_system_bus_device *dev,
        enum ps3_sys_manager_next_op op,
        enum ps3_sys_manager_wake_source wake_source)
 {
-       static const struct ps3_sys_manager_header header = {
-               .version = 1,
-               .size = 16,
-               .payload_size = 16,
-               .service_id = PS3_SM_SERVICE_ID_SET_NEXT_OP,
-       };
+       struct ps3_sys_manager_header header;
        struct {
                u8 version;
                u8 type;
@@ -268,6 +296,12 @@ static int ps3_sys_manager_send_next_op(struct ps3_vuart_port_device *dev,
 
        dev_dbg(&dev->core, "%s:%d: (%xh)\n", __func__, __LINE__, op);
 
+       memset(&header, 0, sizeof(header));
+       header.version = 1;
+       header.size = 16;
+       header.payload_size = 16;
+       header.service_id = PS3_SM_SERVICE_ID_SET_NEXT_OP;
+
        memset(&payload, 0, sizeof(payload));
        payload.version = 3;
        payload.type = op;
@@ -286,32 +320,35 @@ static int ps3_sys_manager_send_next_op(struct ps3_vuart_port_device *dev,
  * the command is then communicated back to the system manager with a response
  * message.
  *
- * Currently, the only supported request it the 'shutdown self' request.
+ * Currently, the only supported request is the 'shutdown self' request.
  */
 
-static int ps3_sys_manager_send_request_shutdown(struct ps3_vuart_port_device *dev)
+static int ps3_sys_manager_send_request_shutdown(
+       struct ps3_system_bus_device *dev)
 {
-       static const struct ps3_sys_manager_header header = {
-               .version = 1,
-               .size = 16,
-               .payload_size = 16,
-               .service_id = PS3_SM_SERVICE_ID_REQUEST,
-       };
+       struct ps3_sys_manager_header header;
        struct {
                u8 version;
                u8 type;
                u8 gos_id;
                u8 reserved_1[13];
-       } static const payload = {
-               .version = 1,
-               .type = 1, /* shutdown */
-               .gos_id = 0, /* self */
-       };
+       } payload;
 
        BUILD_BUG_ON(sizeof(payload) != 16);
 
        dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
+       memset(&header, 0, sizeof(header));
+       header.version = 1;
+       header.size = 16;
+       header.payload_size = 16;
+       header.service_id = PS3_SM_SERVICE_ID_REQUEST;
+
+       memset(&payload, 0, sizeof(payload));
+       payload.version = 1;
+       payload.type = 1; /* shutdown */
+       payload.gos_id = 0; /* self */
+
        return ps3_sys_manager_write(dev, &header, &payload);
 }
 
@@ -323,15 +360,10 @@ static int ps3_sys_manager_send_request_shutdown(struct ps3_vuart_port_device *d
  * failure of a command sent by the system manager.
  */
 
-static int ps3_sys_manager_send_response(struct ps3_vuart_port_device *dev,
+static int ps3_sys_manager_send_response(struct ps3_system_bus_device *dev,
        u64 status)
 {
-       static const struct ps3_sys_manager_header header = {
-               .version = 1,
-               .size = 16,
-               .payload_size = 16,
-               .service_id = PS3_SM_SERVICE_ID_RESPONSE,
-       };
+       struct ps3_sys_manager_header header;
        struct {
                u8 version;
                u8 reserved_1[3];
@@ -344,6 +376,12 @@ static int ps3_sys_manager_send_response(struct ps3_vuart_port_device *dev,
        dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__,
                (status ? "nak" : "ack"));
 
+       memset(&header, 0, sizeof(header));
+       header.version = 1;
+       header.size = 16;
+       header.payload_size = 16;
+       header.service_id = PS3_SM_SERVICE_ID_RESPONSE;
+
        memset(&payload, 0, sizeof(payload));
        payload.version = 1;
        payload.status = status;
@@ -356,7 +394,7 @@ static int ps3_sys_manager_send_response(struct ps3_vuart_port_device *dev,
  *
  */
 
-static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev)
+static int ps3_sys_manager_handle_event(struct ps3_system_bus_device *dev)
 {
        int result;
        struct {
@@ -370,7 +408,7 @@ static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev)
        BUILD_BUG_ON(sizeof(event) != 16);
 
        result = ps3_vuart_read(dev, &event, sizeof(event));
-       BUG_ON(result);
+       BUG_ON(result && "need to retry here");
 
        if (event.version != 1) {
                dev_dbg(&dev->core, "%s:%d: unsupported event version (%u)\n",
@@ -382,11 +420,34 @@ static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev)
        case PS3_SM_EVENT_POWER_PRESSED:
                dev_dbg(&dev->core, "%s:%d: POWER_PRESSED\n",
                        __func__, __LINE__);
+               ps3_sm_force_power_off = 1;
+               /*
+                * A memory barrier is use here to sync memory since
+                * ps3_sys_manager_final_restart() could be called on
+                * another cpu.
+                */
+               wmb();
+               kill_cad_pid(SIGINT, 1); /* ctrl_alt_del */
                break;
        case PS3_SM_EVENT_POWER_RELEASED:
                dev_dbg(&dev->core, "%s:%d: POWER_RELEASED (%u ms)\n",
                        __func__, __LINE__, event.value);
-               kill_cad_pid(SIGINT, 1);
+               break;
+       case PS3_SM_EVENT_RESET_PRESSED:
+               dev_dbg(&dev->core, "%s:%d: RESET_PRESSED\n",
+                       __func__, __LINE__);
+               ps3_sm_force_power_off = 0;
+               /*
+                * A memory barrier is use here to sync memory since
+                * ps3_sys_manager_final_restart() could be called on
+                * another cpu.
+                */
+               wmb();
+               kill_cad_pid(SIGINT, 1); /* ctrl_alt_del */
+               break;
+       case PS3_SM_EVENT_RESET_RELEASED:
+               dev_dbg(&dev->core, "%s:%d: RESET_RELEASED (%u ms)\n",
+                       __func__, __LINE__, event.value);
                break;
        case PS3_SM_EVENT_THERMAL_ALERT:
                dev_dbg(&dev->core, "%s:%d: THERMAL_ALERT (zone %u)\n",
@@ -411,7 +472,7 @@ static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev)
  * The system manager sends this in reply to a 'request' message from the guest.
  */
 
-static int ps3_sys_manager_handle_cmd(struct ps3_vuart_port_device *dev)
+static int ps3_sys_manager_handle_cmd(struct ps3_system_bus_device *dev)
 {
        int result;
        struct {
@@ -425,6 +486,7 @@ static int ps3_sys_manager_handle_cmd(struct ps3_vuart_port_device *dev)
        dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
        result = ps3_vuart_read(dev, &cmd, sizeof(cmd));
+       BUG_ON(result && "need to retry here");
 
        if(result)
                return result;
@@ -448,9 +510,10 @@ static int ps3_sys_manager_handle_cmd(struct ps3_vuart_port_device *dev)
 /**
  * ps3_sys_manager_handle_msg - First stage msg handler.
  *
+ * Can be called directly to manually poll vuart and pump message handler.
  */
 
-static int ps3_sys_manager_handle_msg(struct ps3_vuart_port_device *dev)
+static int ps3_sys_manager_handle_msg(struct ps3_system_bus_device *dev)
 {
        int result;
        struct ps3_sys_manager_header header;
@@ -464,12 +527,17 @@ static int ps3_sys_manager_handle_msg(struct ps3_vuart_port_device *dev)
        if (header.version != 1) {
                dev_dbg(&dev->core, "%s:%d: unsupported header version (%u)\n",
                        __func__, __LINE__, header.version);
+               dump_sm_header(&header);
                goto fail_header;
        }
 
        BUILD_BUG_ON(sizeof(header) != 16);
-       BUG_ON(header.size != 16);
-       BUG_ON(header.payload_size != 16);
+
+       if (header.size != 16 || (header.payload_size != 8
+               && header.payload_size != 16)) {
+               dump_sm_header(&header);
+               BUG();
+       }
 
        switch (header.service_id) {
        case PS3_SM_SERVICE_ID_EXTERN_EVENT:
@@ -478,6 +546,11 @@ static int ps3_sys_manager_handle_msg(struct ps3_vuart_port_device *dev)
        case PS3_SM_SERVICE_ID_COMMAND:
                dev_dbg(&dev->core, "%s:%d: COMMAND\n", __func__, __LINE__);
                return ps3_sys_manager_handle_cmd(dev);
+       case PS3_SM_SERVICE_ID_REQUEST_ERROR:
+               dev_dbg(&dev->core, "%s:%d: REQUEST_ERROR\n", __func__,
+                       __LINE__);
+               dump_sm_header(&header);
+               break;
        default:
                dev_dbg(&dev->core, "%s:%d: unknown service_id (%u)\n",
                        __func__, __LINE__, header.service_id);
@@ -494,45 +567,25 @@ fail_id:
 }
 
 /**
- * ps3_sys_manager_work - Asyncronous read handler.
- *
- * Signaled when a complete message arrives at the vuart port.
- */
-
-static void ps3_sys_manager_work(struct work_struct *work)
-{
-       struct ps3_vuart_port_device *dev = ps3_vuart_work_to_port_device(work);
-
-       ps3_sys_manager_handle_msg(dev);
-       ps3_vuart_read_async(dev, ps3_sys_manager_work, PS3_SM_RX_MSG_LEN);
-}
-
-struct {
-       struct ps3_vuart_port_device *dev;
-} static drv_priv;
-
-/**
- * ps3_sys_manager_restart - The final platform machine_restart routine.
+ * ps3_sys_manager_final_power_off - The final platform machine_power_off routine.
  *
- * This routine never returns.  The routine disables asyncronous vuart reads
+ * This routine never returns.  The routine disables asynchronous vuart reads
  * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
  * the shutdown command sent from the system manager.  Soon after the
  * acknowledgement is sent the lpar is destroyed by the HV.  This routine
- * should only be called from ps3_restart().
+ * should only be called from ps3_power_off() through
+ * ps3_sys_manager_ops.power_off.
  */
 
-void ps3_sys_manager_restart(void)
+static void ps3_sys_manager_final_power_off(struct ps3_system_bus_device *dev)
 {
-       struct ps3_vuart_port_device *dev = drv_priv.dev;
-
-       BUG_ON(!drv_priv.dev);
+       BUG_ON(!dev);
 
        dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
        ps3_vuart_cancel_async(dev);
 
-       ps3_sys_manager_send_attr(dev, 0);
-       ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_LPAR_REBOOT,
+       ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN,
                PS3_SM_WAKE_DEFAULT);
        ps3_sys_manager_send_request_shutdown(dev);
 
@@ -543,26 +596,33 @@ void ps3_sys_manager_restart(void)
 }
 
 /**
- * ps3_sys_manager_power_off - The final platform machine_power_off routine.
+ * ps3_sys_manager_final_restart - The final platform machine_restart routine.
  *
- * This routine never returns.  The routine disables asyncronous vuart reads
+ * This routine never returns.  The routine disables asynchronous vuart reads
  * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
  * the shutdown command sent from the system manager.  Soon after the
  * acknowledgement is sent the lpar is destroyed by the HV.  This routine
- * should only be called from ps3_power_off().
+ * should only be called from ps3_restart() through ps3_sys_manager_ops.restart.
  */
 
-void ps3_sys_manager_power_off(void)
+static void ps3_sys_manager_final_restart(struct ps3_system_bus_device *dev)
 {
-       struct ps3_vuart_port_device *dev = drv_priv.dev;
-
-       BUG_ON(!drv_priv.dev);
+       BUG_ON(!dev);
 
        dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
+       /* Check if we got here via a power button event. */
+
+       if (ps3_sm_force_power_off) {
+               dev_dbg(&dev->core, "%s:%d: forcing poweroff\n",
+                       __func__, __LINE__);
+               ps3_sys_manager_final_power_off(dev);
+       }
+
        ps3_vuart_cancel_async(dev);
 
-       ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN,
+       ps3_sys_manager_send_attr(dev, 0);
+       ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_LPAR_REBOOT,
                PS3_SM_WAKE_DEFAULT);
        ps3_sys_manager_send_request_shutdown(dev);
 
@@ -572,31 +632,60 @@ void ps3_sys_manager_power_off(void)
                ps3_sys_manager_handle_msg(dev);
 }
 
-static int ps3_sys_manager_probe(struct ps3_vuart_port_device *dev)
+/**
+ * ps3_sys_manager_work - Asynchronous read handler.
+ *
+ * Signaled when PS3_SM_RX_MSG_LEN_MIN bytes arrive at the vuart port.
+ */
+
+static void ps3_sys_manager_work(struct ps3_system_bus_device *dev)
+{
+       ps3_sys_manager_handle_msg(dev);
+       ps3_vuart_read_async(dev, PS3_SM_RX_MSG_LEN_MIN);
+}
+
+static int ps3_sys_manager_probe(struct ps3_system_bus_device *dev)
 {
        int result;
+       struct ps3_sys_manager_ops ops;
 
        dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
-       BUG_ON(drv_priv.dev);
-       drv_priv.dev = dev;
+       ops.power_off = ps3_sys_manager_final_power_off;
+       ops.restart = ps3_sys_manager_final_restart;
+       ops.dev = dev;
+
+       /* ps3_sys_manager_register_ops copies ops. */
+
+       ps3_sys_manager_register_ops(&ops);
 
        result = ps3_sys_manager_send_attr(dev, PS3_SM_ATTR_ALL);
        BUG_ON(result);
 
-       result = ps3_vuart_read_async(dev, ps3_sys_manager_work,
-               PS3_SM_RX_MSG_LEN);
+       result = ps3_vuart_read_async(dev, PS3_SM_RX_MSG_LEN_MIN);
        BUG_ON(result);
 
        return result;
 }
 
+static int ps3_sys_manager_remove(struct ps3_system_bus_device *dev)
+{
+       dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+       return 0;
+}
+
+static void ps3_sys_manager_shutdown(struct ps3_system_bus_device *dev)
+{
+       dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+}
+
 static struct ps3_vuart_port_driver ps3_sys_manager = {
-       .match_id = PS3_MATCH_ID_SYSTEM_MANAGER,
-       .core = {
-               .name = "ps3_sys_manager",
-       },
+       .core.match_id = PS3_MATCH_ID_SYSTEM_MANAGER,
+       .core.core.name = "ps3_sys_manager",
        .probe = ps3_sys_manager_probe,
+       .remove = ps3_sys_manager_remove,
+       .shutdown = ps3_sys_manager_shutdown,
+       .work = ps3_sys_manager_work,
 };
 
 static int __init ps3_sys_manager_init(void)
@@ -608,3 +697,6 @@ static int __init ps3_sys_manager_init(void)
 }
 
 module_init(ps3_sys_manager_init);
+/* Module remove not supported. */
+
+MODULE_ALIAS(PS3_MODULE_ALIAS_SYSTEM_MANAGER);
index ec2d36a1bc67ae98c22b8cd2589572b05633f646..bea25a1391ee3adc0475be28aeb236c716eb1324 100644 (file)
@@ -70,6 +70,34 @@ enum vuart_interrupt_mask {
        INTERRUPT_MASK_DISCONNECT = 4,
 };
 
+/**
+ * struct ps3_vuart_port_priv - private vuart device data.
+ */
+
+struct ps3_vuart_port_priv {
+       u64 interrupt_mask;
+
+       struct {
+               spinlock_t lock;
+               struct list_head head;
+       } tx_list;
+       struct {
+               struct ps3_vuart_work work;
+               unsigned long bytes_held;
+               spinlock_t lock;
+               struct list_head head;
+       } rx_list;
+       struct ps3_vuart_stats stats;
+};
+
+static struct ps3_vuart_port_priv *to_port_priv(
+       struct ps3_system_bus_device *dev)
+{
+       BUG_ON(!dev);
+       BUG_ON(!dev->driver_priv);
+       return (struct ps3_vuart_port_priv *)dev->driver_priv;
+}
+
 /**
  * struct ports_bmp - bitmap indicating ports needing service.
  *
@@ -83,31 +111,14 @@ struct ports_bmp {
 } __attribute__ ((aligned (32)));
 
 #define dump_ports_bmp(_b) _dump_ports_bmp(_b, __func__, __LINE__)
-static void __attribute__ ((unused)) _dump_ports_bmp(
+static void __maybe_unused _dump_ports_bmp(
        const struct ports_bmp* bmp, const char* func, int line)
 {
        pr_debug("%s:%d: ports_bmp: %016lxh\n", func, line, bmp->status);
 }
 
-static int ps3_vuart_match_id_to_port(enum ps3_match_id match_id,
-       unsigned int *port_number)
-{
-       switch(match_id) {
-       case PS3_MATCH_ID_AV_SETTINGS:
-               *port_number = 0;
-               return 0;
-       case PS3_MATCH_ID_SYSTEM_MANAGER:
-               *port_number = 2;
-               return 0;
-       default:
-               WARN_ON(1);
-               *port_number = UINT_MAX;
-               return -EINVAL;
-       };
-}
-
 #define dump_port_params(_b) _dump_port_params(_b, __func__, __LINE__)
-static void __attribute__ ((unused)) _dump_port_params(unsigned int port_number,
+static void __maybe_unused _dump_port_params(unsigned int port_number,
        const char* func, int line)
 {
 #if defined(DEBUG)
@@ -144,14 +155,14 @@ struct vuart_triggers {
        unsigned long tx;
 };
 
-int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
+int ps3_vuart_get_triggers(struct ps3_system_bus_device *dev,
        struct vuart_triggers *trig)
 {
        int result;
        unsigned long size;
        unsigned long val;
 
-       result = lv1_get_virtual_uart_param(dev->priv->port_number,
+       result = lv1_get_virtual_uart_param(dev->port_number,
                PARAM_TX_TRIGGER, &trig->tx);
 
        if (result) {
@@ -160,7 +171,7 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
                return result;
        }
 
-       result = lv1_get_virtual_uart_param(dev->priv->port_number,
+       result = lv1_get_virtual_uart_param(dev->port_number,
                PARAM_RX_BUF_SIZE, &size);
 
        if (result) {
@@ -169,7 +180,7 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
                return result;
        }
 
-       result = lv1_get_virtual_uart_param(dev->priv->port_number,
+       result = lv1_get_virtual_uart_param(dev->port_number,
                PARAM_RX_TRIGGER, &val);
 
        if (result) {
@@ -186,13 +197,13 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
        return result;
 }
 
-int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
+int ps3_vuart_set_triggers(struct ps3_system_bus_device *dev, unsigned int tx,
        unsigned int rx)
 {
        int result;
        unsigned long size;
 
-       result = lv1_set_virtual_uart_param(dev->priv->port_number,
+       result = lv1_set_virtual_uart_param(dev->port_number,
                PARAM_TX_TRIGGER, tx);
 
        if (result) {
@@ -201,7 +212,7 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
                return result;
        }
 
-       result = lv1_get_virtual_uart_param(dev->priv->port_number,
+       result = lv1_get_virtual_uart_param(dev->port_number,
                PARAM_RX_BUF_SIZE, &size);
 
        if (result) {
@@ -210,7 +221,7 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
                return result;
        }
 
-       result = lv1_set_virtual_uart_param(dev->priv->port_number,
+       result = lv1_set_virtual_uart_param(dev->port_number,
                PARAM_RX_TRIGGER, size - rx);
 
        if (result) {
@@ -225,10 +236,12 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
        return result;
 }
 
-static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev,
+static int ps3_vuart_get_rx_bytes_waiting(struct ps3_system_bus_device *dev,
        u64 *bytes_waiting)
 {
-       int result = lv1_get_virtual_uart_param(dev->priv->port_number,
+       int result;
+
+       result = lv1_get_virtual_uart_param(dev->port_number,
                PARAM_RX_BYTES, bytes_waiting);
 
        if (result)
@@ -240,17 +253,24 @@ static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev,
        return result;
 }
 
-static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev,
+/**
+ * ps3_vuart_set_interrupt_mask - Enable/disable the port interrupt sources.
+ * @dev: The struct ps3_system_bus_device instance.
+ * @bmp: Logical OR of enum vuart_interrupt_mask values. A zero bit disables.
+ */
+
+static int ps3_vuart_set_interrupt_mask(struct ps3_system_bus_device *dev,
        unsigned long mask)
 {
        int result;
+       struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 
        dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask);
 
-       dev->priv->interrupt_mask = mask;
+       priv->interrupt_mask = mask;
 
-       result = lv1_set_virtual_uart_param(dev->priv->port_number,
-               PARAM_INTERRUPT_MASK, dev->priv->interrupt_mask);
+       result = lv1_set_virtual_uart_param(dev->port_number,
+               PARAM_INTERRUPT_MASK, priv->interrupt_mask);
 
        if (result)
                dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n",
@@ -259,79 +279,96 @@ static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev,
        return result;
 }
 
-static int ps3_vuart_get_interrupt_status(struct ps3_vuart_port_device *dev,
+static int ps3_vuart_get_interrupt_status(struct ps3_system_bus_device *dev,
        unsigned long *status)
 {
+       int result;
+       struct ps3_vuart_port_priv *priv = to_port_priv(dev);
        u64 tmp;
-       int result = lv1_get_virtual_uart_param(dev->priv->port_number,
+
+       result = lv1_get_virtual_uart_param(dev->port_number,
                PARAM_INTERRUPT_STATUS, &tmp);
 
        if (result)
                dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n",
                        __func__, __LINE__, ps3_result(result));
 
-       *status = tmp & dev->priv->interrupt_mask;
+       *status = tmp & priv->interrupt_mask;
 
        dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n",
-               __func__, __LINE__, dev->priv->interrupt_mask, tmp, *status);
+               __func__, __LINE__, priv->interrupt_mask, tmp, *status);
 
        return result;
 }
 
-int ps3_vuart_enable_interrupt_tx(struct ps3_vuart_port_device *dev)
+int ps3_vuart_enable_interrupt_tx(struct ps3_system_bus_device *dev)
 {
-       return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0
-               : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+       struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+       return (priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0
+               : ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
                | INTERRUPT_MASK_TX);
 }
 
-int ps3_vuart_enable_interrupt_rx(struct ps3_vuart_port_device *dev)
+int ps3_vuart_enable_interrupt_rx(struct ps3_system_bus_device *dev)
 {
-       return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0
-               : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+       struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+       return (priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0
+               : ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
                | INTERRUPT_MASK_RX);
 }
 
-int ps3_vuart_enable_interrupt_disconnect(struct ps3_vuart_port_device *dev)
+int ps3_vuart_enable_interrupt_disconnect(struct ps3_system_bus_device *dev)
 {
-       return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0
-               : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+       struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+       return (priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0
+               : ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
                | INTERRUPT_MASK_DISCONNECT);
 }
 
-int ps3_vuart_disable_interrupt_tx(struct ps3_vuart_port_device *dev)
+int ps3_vuart_disable_interrupt_tx(struct ps3_system_bus_device *dev)
 {
-       return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX)
-               ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+       struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+       return (priv->interrupt_mask & INTERRUPT_MASK_TX)
+               ? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
                & ~INTERRUPT_MASK_TX) : 0;
 }
 
-int ps3_vuart_disable_interrupt_rx(struct ps3_vuart_port_device *dev)
+int ps3_vuart_disable_interrupt_rx(struct ps3_system_bus_device *dev)
 {
-       return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX)
-               ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+       struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+       return (priv->interrupt_mask & INTERRUPT_MASK_RX)
+               ? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
                & ~INTERRUPT_MASK_RX) : 0;
 }
 
-int ps3_vuart_disable_interrupt_disconnect(struct ps3_vuart_port_device *dev)
+int ps3_vuart_disable_interrupt_disconnect(struct ps3_system_bus_device *dev)
 {
-       return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT)
-               ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
+       struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+
+       return (priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT)
+               ? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
                & ~INTERRUPT_MASK_DISCONNECT) : 0;
 }
 
 /**
  * ps3_vuart_raw_write - Low level write helper.
+ * @dev: The struct ps3_system_bus_device instance.
  *
  * Do not call ps3_vuart_raw_write directly, use ps3_vuart_write.
  */
 
-static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev,
+static int ps3_vuart_raw_write(struct ps3_system_bus_device *dev,
        const void* buf, unsigned int bytes, unsigned long *bytes_written)
 {
        int result;
+       struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 
-       result = lv1_write_virtual_uart(dev->priv->port_number,
+       result = lv1_write_virtual_uart(dev->port_number,
                ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written);
 
        if (result) {
@@ -340,28 +377,30 @@ static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev,
                return result;
        }
 
-       dev->priv->stats.bytes_written += *bytes_written;
+       priv->stats.bytes_written += *bytes_written;
 
        dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__, __LINE__,
-               *bytes_written, bytes, dev->priv->stats.bytes_written);
+               *bytes_written, bytes, priv->stats.bytes_written);
 
        return result;
 }
 
 /**
  * ps3_vuart_raw_read - Low level read helper.
+ * @dev: The struct ps3_system_bus_device instance.
  *
  * Do not call ps3_vuart_raw_read directly, use ps3_vuart_read.
  */
 
-static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf,
+static int ps3_vuart_raw_read(struct ps3_system_bus_device *dev, void *buf,
        unsigned int bytes, unsigned long *bytes_read)
 {
        int result;
+       struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 
        dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes);
 
-       result = lv1_read_virtual_uart(dev->priv->port_number,
+       result = lv1_read_virtual_uart(dev->port_number,
                ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read);
 
        if (result) {
@@ -370,25 +409,27 @@ static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf,
                return result;
        }
 
-       dev->priv->stats.bytes_read += *bytes_read;
+       priv->stats.bytes_read += *bytes_read;
 
        dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__,
-               *bytes_read, bytes, dev->priv->stats.bytes_read);
+               *bytes_read, bytes, priv->stats.bytes_read);
 
        return result;
 }
 
 /**
  * ps3_vuart_clear_rx_bytes - Discard bytes received.
+ * @dev: The struct ps3_system_bus_device instance.
  * @bytes: Max byte count to discard, zero = all pending.
  *
  * Used to clear pending rx interrupt source.  Will not block.
  */
 
-void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev,
+void ps3_vuart_clear_rx_bytes(struct ps3_system_bus_device *dev,
        unsigned int bytes)
 {
        int result;
+       struct ps3_vuart_port_priv *priv = to_port_priv(dev);
        u64 bytes_waiting;
        void* tmp;
 
@@ -418,8 +459,9 @@ void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev,
 
        /* Don't include these bytes in the stats. */
 
-       dev->priv->stats.bytes_read -= bytes_waiting;
+       priv->stats.bytes_read -= bytes_waiting;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_clear_rx_bytes);
 
 /**
  * struct list_buffer - An element for a port device fifo buffer list.
@@ -435,6 +477,7 @@ struct list_buffer {
 
 /**
  * ps3_vuart_write - the entry point for writing data to a port
+ * @dev: The struct ps3_system_bus_device instance.
  *
  * If the port is idle on entry as much of the incoming data is written to
  * the port as the port will accept.  Otherwise a list buffer is created
@@ -442,25 +485,26 @@ struct list_buffer {
  * then enqueued for transmision via the transmit interrupt.
  */
 
-int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
+int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf,
        unsigned int bytes)
 {
        static unsigned long dbg_number;
        int result;
+       struct ps3_vuart_port_priv *priv = to_port_priv(dev);
        unsigned long flags;
        struct list_buffer *lb;
 
        dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
                bytes, bytes);
 
-       spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
+       spin_lock_irqsave(&priv->tx_list.lock, flags);
 
-       if (list_empty(&dev->priv->tx_list.head)) {
+       if (list_empty(&priv->tx_list.head)) {
                unsigned long bytes_written;
 
                result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written);
 
-               spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
+               spin_unlock_irqrestore(&priv->tx_list.lock, flags);
 
                if (result) {
                        dev_dbg(&dev->core,
@@ -478,7 +522,7 @@ int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
                bytes -= bytes_written;
                buf += bytes_written;
        } else
-               spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
+               spin_unlock_irqrestore(&priv->tx_list.lock, flags);
 
        lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL);
 
@@ -491,29 +535,86 @@ int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
        lb->tail = lb->data + bytes;
        lb->dbg_number = ++dbg_number;
 
-       spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
-       list_add_tail(&lb->link, &dev->priv->tx_list.head);
+       spin_lock_irqsave(&priv->tx_list.lock, flags);
+       list_add_tail(&lb->link, &priv->tx_list.head);
        ps3_vuart_enable_interrupt_tx(dev);
-       spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
+       spin_unlock_irqrestore(&priv->tx_list.lock, flags);
 
        dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n",
                __func__, __LINE__, lb->dbg_number, bytes);
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_write);
+
+/**
+ * ps3_vuart_queue_rx_bytes - Queue waiting bytes into the buffer list.
+ * @dev: The struct ps3_system_bus_device instance.
+ * @bytes_queued: Number of bytes queued to the buffer list.
+ *
+ * Must be called with priv->rx_list.lock held.
+ */
+
+static int ps3_vuart_queue_rx_bytes(struct ps3_system_bus_device *dev,
+       u64 *bytes_queued)
+{
+       static unsigned long dbg_number;
+       int result;
+       struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+       struct list_buffer *lb;
+       u64 bytes;
+
+       *bytes_queued = 0;
+
+       result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes);
+       BUG_ON(result);
+
+       if (result)
+               return -EIO;
+
+       if (!bytes)
+               return 0;
+
+       /* Add some extra space for recently arrived data. */
+
+       bytes += 128;
+
+       lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC);
+
+       if (!lb)
+               return -ENOMEM;
+
+       ps3_vuart_raw_read(dev, lb->data, bytes, &bytes);
+
+       lb->head = lb->data;
+       lb->tail = lb->data + bytes;
+       lb->dbg_number = ++dbg_number;
+
+       list_add_tail(&lb->link, &priv->rx_list.head);
+       priv->rx_list.bytes_held += bytes;
+
+       dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n",
+               __func__, __LINE__, lb->dbg_number, bytes);
+
+       *bytes_queued = bytes;
+
+       return 0;
+}
 
 /**
- * ps3_vuart_read - the entry point for reading data from a port
+ * ps3_vuart_read - The entry point for reading data from a port.
  *
- * If enough bytes to satisfy the request are held in the buffer list those
- * bytes are dequeued and copied to the caller's buffer.  Emptied list buffers
- * are retiered.  If the request cannot be statified by bytes held in the list
- * buffers -EAGAIN is returned.
+ * Queue data waiting at the port, and if enough bytes to satisfy the request
+ * are held in the buffer list those bytes are dequeued and copied to the
+ * caller's buffer.  Emptied list buffers are retiered.  If the request cannot
+ * be statified by bytes held in the list buffers -EAGAIN is returned.
  */
 
-int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
+int ps3_vuart_read(struct ps3_system_bus_device *dev, void *buf,
        unsigned int bytes)
 {
+       int result;
+       struct ps3_vuart_port_priv *priv = to_port_priv(dev);
        unsigned long flags;
        struct list_buffer *lb, *n;
        unsigned long bytes_read;
@@ -521,30 +622,37 @@ int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
        dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
                bytes, bytes);
 
-       spin_lock_irqsave(&dev->priv->rx_list.lock, flags);
+       spin_lock_irqsave(&priv->rx_list.lock, flags);
 
-       if (dev->priv->rx_list.bytes_held < bytes) {
-               spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
-               dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n",
-                       __func__, __LINE__,
-                       bytes - dev->priv->rx_list.bytes_held);
-               return -EAGAIN;
+       /* Queue rx bytes here for polled reads. */
+
+       while (priv->rx_list.bytes_held < bytes) {
+               u64 tmp;
+
+               result = ps3_vuart_queue_rx_bytes(dev, &tmp);
+               if (result || !tmp) {
+                       dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n",
+                               __func__, __LINE__,
+                               bytes - priv->rx_list.bytes_held);
+                       spin_unlock_irqrestore(&priv->rx_list.lock, flags);
+                       return -EAGAIN;
+               }
        }
 
-       list_for_each_entry_safe(lb, n, &dev->priv->rx_list.head, link) {
+       list_for_each_entry_safe(lb, n, &priv->rx_list.head, link) {
                bytes_read = min((unsigned int)(lb->tail - lb->head), bytes);
 
                memcpy(buf, lb->head, bytes_read);
                buf += bytes_read;
                bytes -= bytes_read;
-               dev->priv->rx_list.bytes_held -= bytes_read;
+               priv->rx_list.bytes_held -= bytes_read;
 
                if (bytes_read < lb->tail - lb->head) {
                        lb->head += bytes_read;
                        dev_dbg(&dev->core, "%s:%d: buf_%lu: dequeued %lxh "
                                "bytes\n", __func__, __LINE__, lb->dbg_number,
                                bytes_read);
-                       spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
+                       spin_unlock_irqrestore(&priv->rx_list.lock, flags);
                        return 0;
                }
 
@@ -556,16 +664,32 @@ int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
                kfree(lb);
        }
 
-       spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
+       spin_unlock_irqrestore(&priv->rx_list.lock, flags);
        return 0;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_read);
 
-int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func,
-       unsigned int bytes)
+/**
+ * ps3_vuart_work - Asynchronous read handler.
+ */
+
+static void ps3_vuart_work(struct work_struct *work)
+{
+       struct ps3_system_bus_device *dev =
+               ps3_vuart_work_to_system_bus_dev(work);
+       struct ps3_vuart_port_driver *drv =
+               ps3_system_bus_dev_to_vuart_drv(dev);
+
+       BUG_ON(!drv);
+       drv->work(dev);
+}
+
+int ps3_vuart_read_async(struct ps3_system_bus_device *dev, unsigned int bytes)
 {
+       struct ps3_vuart_port_priv *priv = to_port_priv(dev);
        unsigned long flags;
 
-       if(dev->priv->work.trigger) {
+       if (priv->rx_list.work.trigger) {
                dev_dbg(&dev->core, "%s:%d: warning, multiple calls\n",
                        __func__, __LINE__);
                return -EAGAIN;
@@ -573,30 +697,32 @@ int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func,
 
        BUG_ON(!bytes);
 
-       PREPARE_WORK(&dev->priv->work.work, func);
+       PREPARE_WORK(&priv->rx_list.work.work, ps3_vuart_work);
 
-       spin_lock_irqsave(&dev->priv->work.lock, flags);
-       if(dev->priv->rx_list.bytes_held >= bytes) {
+       spin_lock_irqsave(&priv->rx_list.lock, flags);
+       if (priv->rx_list.bytes_held >= bytes) {
                dev_dbg(&dev->core, "%s:%d: schedule_work %xh bytes\n",
                        __func__, __LINE__, bytes);
-               schedule_work(&dev->priv->work.work);
-               spin_unlock_irqrestore(&dev->priv->work.lock, flags);
+               schedule_work(&priv->rx_list.work.work);
+               spin_unlock_irqrestore(&priv->rx_list.lock, flags);
                return 0;
        }
 
-       dev->priv->work.trigger = bytes;
-       spin_unlock_irqrestore(&dev->priv->work.lock, flags);
+       priv->rx_list.work.trigger = bytes;
+       spin_unlock_irqrestore(&priv->rx_list.lock, flags);
 
        dev_dbg(&dev->core, "%s:%d: waiting for %u(%xh) bytes\n", __func__,
                __LINE__, bytes, bytes);
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_read_async);
 
-void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev)
+void ps3_vuart_cancel_async(struct ps3_system_bus_device *dev)
 {
-       dev->priv->work.trigger = 0;
+       to_port_priv(dev)->rx_list.work.trigger = 0;
 }
+EXPORT_SYMBOL_GPL(ps3_vuart_cancel_async);
 
 /**
  * ps3_vuart_handle_interrupt_tx - third stage transmit interrupt handler
@@ -606,18 +732,19 @@ void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev)
  * adjusts the final list buffer state for a partial write.
  */
 
-static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev)
+static int ps3_vuart_handle_interrupt_tx(struct ps3_system_bus_device *dev)
 {
        int result = 0;
+       struct ps3_vuart_port_priv *priv = to_port_priv(dev);
        unsigned long flags;
        struct list_buffer *lb, *n;
        unsigned long bytes_total = 0;
 
        dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
-       spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
+       spin_lock_irqsave(&priv->tx_list.lock, flags);
 
-       list_for_each_entry_safe(lb, n, &dev->priv->tx_list.head, link) {
+       list_for_each_entry_safe(lb, n, &priv->tx_list.head, link) {
 
                unsigned long bytes_written;
 
@@ -651,7 +778,7 @@ static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev)
 
        ps3_vuart_disable_interrupt_tx(dev);
 port_full:
-       spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
+       spin_unlock_irqrestore(&priv->tx_list.lock, flags);
        dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n",
                __func__, __LINE__, bytes_total);
        return result;
@@ -665,60 +792,37 @@ port_full:
  * buffer list.  Buffer list data is dequeued via ps3_vuart_read.
  */
 
-static int ps3_vuart_handle_interrupt_rx(struct ps3_vuart_port_device *dev)
+static int ps3_vuart_handle_interrupt_rx(struct ps3_system_bus_device *dev)
 {
-       static unsigned long dbg_number;
-       int result = 0;
+       int result;
+       struct ps3_vuart_port_priv *priv = to_port_priv(dev);
        unsigned long flags;
-       struct list_buffer *lb;
-       unsigned long bytes;
+       u64 bytes;
 
        dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
-       result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes);
-
-       if (result)
-               return -EIO;
-
-       BUG_ON(!bytes);
-
-       /* Add some extra space for recently arrived data. */
-
-       bytes += 128;
-
-       lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC);
+       spin_lock_irqsave(&priv->rx_list.lock, flags);
+       result = ps3_vuart_queue_rx_bytes(dev, &bytes);
 
-       if (!lb)
-               return -ENOMEM;
-
-       ps3_vuart_raw_read(dev, lb->data, bytes, &bytes);
-
-       lb->head = lb->data;
-       lb->tail = lb->data + bytes;
-       lb->dbg_number = ++dbg_number;
-
-       spin_lock_irqsave(&dev->priv->rx_list.lock, flags);
-       list_add_tail(&lb->link, &dev->priv->rx_list.head);
-       dev->priv->rx_list.bytes_held += bytes;
-       spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
-
-       dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n",
-               __func__, __LINE__, lb->dbg_number, bytes);
+       if (result) {
+               spin_unlock_irqrestore(&priv->rx_list.lock, flags);
+               return result;
+       }
 
-       spin_lock_irqsave(&dev->priv->work.lock, flags);
-       if(dev->priv->work.trigger
-               && dev->priv->rx_list.bytes_held >= dev->priv->work.trigger) {
+       if (priv->rx_list.work.trigger && priv->rx_list.bytes_held
+               >= priv->rx_list.work.trigger) {
                dev_dbg(&dev->core, "%s:%d: schedule_work %lxh bytes\n",
-                       __func__, __LINE__, dev->priv->work.trigger);
-               dev->priv->work.trigger = 0;
-               schedule_work(&dev->priv->work.work);
+                       __func__, __LINE__, priv->rx_list.work.trigger);
+               priv->rx_list.work.trigger = 0;
+               schedule_work(&priv->rx_list.work.work);
        }
-       spin_unlock_irqrestore(&dev->priv->work.lock, flags);
-       return 0;
+
+       spin_unlock_irqrestore(&priv->rx_list.lock, flags);
+       return result;
 }
 
 static int ps3_vuart_handle_interrupt_disconnect(
-       struct ps3_vuart_port_device *dev)
+       struct ps3_system_bus_device *dev)
 {
        dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
        BUG_ON("no support");
@@ -733,9 +837,10 @@ static int ps3_vuart_handle_interrupt_disconnect(
  * stage handler after one iteration.
  */
 
-static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
+static int ps3_vuart_handle_port_interrupt(struct ps3_system_bus_device *dev)
 {
        int result;
+       struct ps3_vuart_port_priv *priv = to_port_priv(dev);
        unsigned long status;
 
        result = ps3_vuart_get_interrupt_status(dev, &status);
@@ -747,21 +852,21 @@ static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
                status);
 
        if (status & INTERRUPT_MASK_DISCONNECT) {
-               dev->priv->stats.disconnect_interrupts++;
+               priv->stats.disconnect_interrupts++;
                result = ps3_vuart_handle_interrupt_disconnect(dev);
                if (result)
                        ps3_vuart_disable_interrupt_disconnect(dev);
        }
 
        if (status & INTERRUPT_MASK_TX) {
-               dev->priv->stats.tx_interrupts++;
+               priv->stats.tx_interrupts++;
                result = ps3_vuart_handle_interrupt_tx(dev);
                if (result)
                        ps3_vuart_disable_interrupt_tx(dev);
        }
 
        if (status & INTERRUPT_MASK_RX) {
-               dev->priv->stats.rx_interrupts++;
+               priv->stats.rx_interrupts++;
                result = ps3_vuart_handle_interrupt_rx(dev);
                if (result)
                        ps3_vuart_disable_interrupt_rx(dev);
@@ -771,11 +876,11 @@ static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
 }
 
 struct vuart_bus_priv {
-       const struct ports_bmp bmp;
+       struct ports_bmp *bmp;
        unsigned int virq;
        struct semaphore probe_mutex;
        int use_count;
-       struct ps3_vuart_port_device *devices[PORT_COUNT];
+       struct ps3_system_bus_device *devices[PORT_COUNT];
 } static vuart_bus_priv;
 
 /**
@@ -788,17 +893,16 @@ struct vuart_bus_priv {
 
 static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private)
 {
-       struct vuart_bus_priv *bus_priv;
+       struct vuart_bus_priv *bus_priv = _private;
 
-       BUG_ON(!_private);
-       bus_priv = (struct vuart_bus_priv *)_private;
+       BUG_ON(!bus_priv);
 
        while (1) {
                unsigned int port;
 
-               dump_ports_bmp(&bus_priv->bmp);
+               dump_ports_bmp(bus_priv->bmp);
 
-               port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp.status);
+               port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp->status);
 
                if (port == BITS_PER_LONG)
                        break;
@@ -812,100 +916,144 @@ static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private)
        return IRQ_HANDLED;
 }
 
-static int ps3_vuart_match(struct device *_dev, struct device_driver *_drv)
+static int ps3_vuart_bus_interrupt_get(void)
 {
        int result;
-       struct ps3_vuart_port_driver *drv = to_ps3_vuart_port_driver(_drv);
-       struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
 
-       result = dev->match_id == drv->match_id;
+       pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+       vuart_bus_priv.use_count++;
+
+       BUG_ON(vuart_bus_priv.use_count > 2);
+
+       if (vuart_bus_priv.use_count != 1) {
+               return 0;
+       }
+
+       BUG_ON(vuart_bus_priv.bmp);
+
+       vuart_bus_priv.bmp = kzalloc(sizeof(struct ports_bmp), GFP_KERNEL);
+
+       if (!vuart_bus_priv.bmp) {
+               pr_debug("%s:%d: kzalloc failed.\n", __func__, __LINE__);
+               result = -ENOMEM;
+               goto fail_bmp_malloc;
+       }
+
+       result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY, vuart_bus_priv.bmp,
+               &vuart_bus_priv.virq);
+
+       if (result) {
+               pr_debug("%s:%d: ps3_vuart_irq_setup failed (%d)\n",
+                       __func__, __LINE__, result);
+               result = -EPERM;
+               goto fail_alloc_irq;
+       }
+
+       result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler,
+               IRQF_DISABLED, "vuart", &vuart_bus_priv);
 
-       dev_info(&dev->core, "%s:%d: dev=%u(%s), drv=%u(%s): %s\n", __func__,
-               __LINE__, dev->match_id, dev->core.bus_id, drv->match_id,
-               drv->core.name, (result ? "match" : "miss"));
+       if (result) {
+               pr_debug("%s:%d: request_irq failed (%d)\n",
+                       __func__, __LINE__, result);
+               goto fail_request_irq;
+       }
 
+       pr_debug(" <- %s:%d: ok\n", __func__, __LINE__);
        return result;
+
+fail_request_irq:
+       ps3_vuart_irq_destroy(vuart_bus_priv.virq);
+       vuart_bus_priv.virq = NO_IRQ;
+fail_alloc_irq:
+       kfree(vuart_bus_priv.bmp);
+       vuart_bus_priv.bmp = NULL;
+fail_bmp_malloc:
+       vuart_bus_priv.use_count--;
+       pr_debug(" <- %s:%d: failed\n", __func__, __LINE__);
+       return result;
+}
+
+static int ps3_vuart_bus_interrupt_put(void)
+{
+       pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+       vuart_bus_priv.use_count--;
+
+       BUG_ON(vuart_bus_priv.use_count < 0);
+
+       if (vuart_bus_priv.use_count != 0)
+               return 0;
+
+       free_irq(vuart_bus_priv.virq, &vuart_bus_priv);
+
+       ps3_vuart_irq_destroy(vuart_bus_priv.virq);
+       vuart_bus_priv.virq = NO_IRQ;
+
+       kfree(vuart_bus_priv.bmp);
+       vuart_bus_priv.bmp = NULL;
+
+       pr_debug(" <- %s:%d\n", __func__, __LINE__);
+       return 0;
 }
 
-static int ps3_vuart_probe(struct device *_dev)
+static int ps3_vuart_probe(struct ps3_system_bus_device *dev)
 {
        int result;
-       unsigned int port_number;
-       struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
-       struct ps3_vuart_port_driver *drv =
-               to_ps3_vuart_port_driver(_dev->driver);
+       struct ps3_vuart_port_driver *drv;
+       struct ps3_vuart_port_priv *priv = NULL;
 
        dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
 
+       drv = ps3_system_bus_dev_to_vuart_drv(dev);
+
+       dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__,
+               drv->core.core.name);
+
        BUG_ON(!drv);
 
-       down(&vuart_bus_priv.probe_mutex);
+       if (dev->port_number >= PORT_COUNT) {
+               BUG();
+               return -EINVAL;
+       }
 
-       /* Setup vuart_bus_priv.devices[]. */
+       down(&vuart_bus_priv.probe_mutex);
 
-       result = ps3_vuart_match_id_to_port(dev->match_id,
-               &port_number);
+       result = ps3_vuart_bus_interrupt_get();
 
-       if (result) {
-               dev_dbg(&dev->core, "%s:%d: unknown match_id (%d)\n",
-                       __func__, __LINE__, dev->match_id);
-               result = -EINVAL;
-               goto fail_match;
-       }
+       if (result)
+               goto fail_setup_interrupt;
 
-       if (vuart_bus_priv.devices[port_number]) {
+       if (vuart_bus_priv.devices[dev->port_number]) {
                dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__,
-                       __LINE__, port_number);
+                       __LINE__, dev->port_number);
                result = -EBUSY;
-               goto fail_match;
+               goto fail_busy;
        }
 
-       vuart_bus_priv.devices[port_number] = dev;
+       vuart_bus_priv.devices[dev->port_number] = dev;
 
-       /* Setup dev->priv. */
+       /* Setup dev->driver_priv. */
 
-       dev->priv = kzalloc(sizeof(struct ps3_vuart_port_priv), GFP_KERNEL);
+       dev->driver_priv = kzalloc(sizeof(struct ps3_vuart_port_priv),
+               GFP_KERNEL);
 
-       if (!dev->priv) {
+       if (!dev->driver_priv) {
                result = -ENOMEM;
-               goto fail_alloc;
+               goto fail_dev_malloc;
        }
 
-       dev->priv->port_number = port_number;
-
-       INIT_LIST_HEAD(&dev->priv->tx_list.head);
-       spin_lock_init(&dev->priv->tx_list.lock);
+       priv = to_port_priv(dev);
 
-       INIT_LIST_HEAD(&dev->priv->rx_list.head);
-       spin_lock_init(&dev->priv->rx_list.lock);
+       INIT_LIST_HEAD(&priv->tx_list.head);
+       spin_lock_init(&priv->tx_list.lock);
 
-       INIT_WORK(&dev->priv->work.work, NULL);
-       spin_lock_init(&dev->priv->work.lock);
-       dev->priv->work.trigger = 0;
-       dev->priv->work.dev = dev;
+       INIT_LIST_HEAD(&priv->rx_list.head);
+       spin_lock_init(&priv->rx_list.lock);
 
-       if (++vuart_bus_priv.use_count == 1) {
-
-               result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY,
-                       (void*)&vuart_bus_priv.bmp.status, &vuart_bus_priv.virq);
-
-               if (result) {
-                       dev_dbg(&dev->core,
-                               "%s:%d: ps3_vuart_irq_setup failed (%d)\n",
-                               __func__, __LINE__, result);
-                       result = -EPERM;
-                       goto fail_alloc_irq;
-               }
-
-               result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler,
-                       IRQF_DISABLED, "vuart", &vuart_bus_priv);
-
-               if (result) {
-                       dev_info(&dev->core, "%s:%d: request_irq failed (%d)\n",
-                               __func__, __LINE__, result);
-                       goto fail_request_irq;
-               }
-       }
+       INIT_WORK(&priv->rx_list.work.work, NULL);
+       priv->rx_list.work.trigger = 0;
+       priv->rx_list.work.dev = dev;
 
        /* clear stale pending interrupts */
 
@@ -936,150 +1084,158 @@ static int ps3_vuart_probe(struct device *_dev)
 
 fail_probe:
        ps3_vuart_set_interrupt_mask(dev, 0);
-fail_request_irq:
-       ps3_vuart_irq_destroy(vuart_bus_priv.virq);
-       vuart_bus_priv.virq = NO_IRQ;
-fail_alloc_irq:
-       --vuart_bus_priv.use_count;
-       kfree(dev->priv);
-       dev->priv = NULL;
-fail_alloc:
-       vuart_bus_priv.devices[port_number] = NULL;
-fail_match:
+       kfree(dev->driver_priv);
+       dev->driver_priv = NULL;
+fail_dev_malloc:
+       vuart_bus_priv.devices[dev->port_number] = NULL;
+fail_busy:
+       ps3_vuart_bus_interrupt_put();
+fail_setup_interrupt:
        up(&vuart_bus_priv.probe_mutex);
-       dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__);
+       dev_dbg(&dev->core, "%s:%d: failed\n", __func__, __LINE__);
        return result;
 }
 
-static int ps3_vuart_remove(struct device *_dev)
+/**
+ * ps3_vuart_cleanup - common cleanup helper.
+ * @dev: The struct ps3_system_bus_device instance.
+ *
+ * Cleans interrupts and HV resources.  Must be called with
+ * vuart_bus_priv.probe_mutex held.  Used by ps3_vuart_remove and
+ * ps3_vuart_shutdown.  After this call, polled reading will still work.
+ */
+
+static int ps3_vuart_cleanup(struct ps3_system_bus_device *dev)
 {
-       struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
-       struct ps3_vuart_port_driver *drv =
-               to_ps3_vuart_port_driver(_dev->driver);
+       dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+       ps3_vuart_cancel_async(dev);
+       ps3_vuart_set_interrupt_mask(dev, 0);
+       ps3_vuart_bus_interrupt_put();
+       return 0;
+}
+
+/**
+ * ps3_vuart_remove - Completely clean the device instance.
+ * @dev: The struct ps3_system_bus_device instance.
+ *
+ * Cleans all memory, interrupts and HV resources.  After this call the
+ * device can no longer be used.
+ */
+
+static int ps3_vuart_remove(struct ps3_system_bus_device *dev)
+{
+       struct ps3_vuart_port_priv *priv = to_port_priv(dev);
+       struct ps3_vuart_port_driver *drv;
+
+       BUG_ON(!dev);
 
        down(&vuart_bus_priv.probe_mutex);
 
-       dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__,
-               dev->core.bus_id);
+       dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__,
+               dev->match_id);
 
-       BUG_ON(vuart_bus_priv.use_count < 1);
+       if (!dev->core.driver) {
+               dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__,
+                       __LINE__);
+               up(&vuart_bus_priv.probe_mutex);
+               return 0;
+       }
 
-       if (drv->remove)
-               drv->remove(dev);
-       else
-               dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__,
-                       __LINE__, dev->core.bus_id);
+       drv = ps3_system_bus_dev_to_vuart_drv(dev);
 
-       vuart_bus_priv.devices[dev->priv->port_number] = NULL;
+       BUG_ON(!drv);
 
-       if (--vuart_bus_priv.use_count == 0) {
+       if (drv->remove) {
+               drv->remove(dev);
+       } else {
+               dev_dbg(&dev->core, "%s:%d: no remove method\n", __func__,
+               __LINE__);
                BUG();
-               free_irq(vuart_bus_priv.virq, &vuart_bus_priv);
-               ps3_vuart_irq_destroy(vuart_bus_priv.virq);
-               vuart_bus_priv.virq = NO_IRQ;
        }
 
-       kfree(dev->priv);
-       dev->priv = NULL;
+       ps3_vuart_cleanup(dev);
+
+       vuart_bus_priv.devices[dev->port_number] = NULL;
+       kfree(priv);
+       priv = NULL;
 
+       dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
        up(&vuart_bus_priv.probe_mutex);
        return 0;
 }
 
-static void ps3_vuart_shutdown(struct device *_dev)
-{
-       struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
-       struct ps3_vuart_port_driver *drv =
-               to_ps3_vuart_port_driver(_dev->driver);
-
-       dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__,
-               dev->core.bus_id);
-
-       if (drv->shutdown)
-               drv->shutdown(dev);
-       else
-               dev_dbg(&dev->core, "%s:%d: %s no shutdown method\n", __func__,
-                       __LINE__, dev->core.bus_id);
-}
-
 /**
- * ps3_vuart_bus - The vuart bus instance.
+ * ps3_vuart_shutdown - Cleans interrupts and HV resources.
+ * @dev: The struct ps3_system_bus_device instance.
  *
- * The vuart is managed as a bus that port devices connect to.
+ * Cleans interrupts and HV resources.  After this call the
+ * device can still be used in polling mode.  This behavior required
+ * by sys-manager to be able to complete the device power operation
+ * sequence.
  */
 
-struct bus_type ps3_vuart_bus = {
-        .name = "ps3_vuart",
-       .match = ps3_vuart_match,
-       .probe = ps3_vuart_probe,
-       .remove = ps3_vuart_remove,
-       .shutdown = ps3_vuart_shutdown,
-};
-
-int __init ps3_vuart_bus_init(void)
+static int ps3_vuart_shutdown(struct ps3_system_bus_device *dev)
 {
-       int result;
+       struct ps3_vuart_port_driver *drv;
 
-       pr_debug("%s:%d:\n", __func__, __LINE__);
+       BUG_ON(!dev);
 
-       if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
-               return -ENODEV;
+       down(&vuart_bus_priv.probe_mutex);
 
-       init_MUTEX(&vuart_bus_priv.probe_mutex);
-       result = bus_register(&ps3_vuart_bus);
-       BUG_ON(result);
+       dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__,
+               dev->match_id);
 
-       return result;
-}
+       if (!dev->core.driver) {
+               dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__,
+                       __LINE__);
+               up(&vuart_bus_priv.probe_mutex);
+               return 0;
+       }
 
-void __exit ps3_vuart_bus_exit(void)
-{
-       pr_debug("%s:%d:\n", __func__, __LINE__);
-       bus_unregister(&ps3_vuart_bus);
-}
+       drv = ps3_system_bus_dev_to_vuart_drv(dev);
 
-core_initcall(ps3_vuart_bus_init);
-module_exit(ps3_vuart_bus_exit);
+       BUG_ON(!drv);
 
-/**
- * ps3_vuart_port_release_device - Remove a vuart port device.
- */
+       if (drv->shutdown)
+               drv->shutdown(dev);
+       else if (drv->remove) {
+               dev_dbg(&dev->core, "%s:%d: no shutdown, calling remove\n",
+                       __func__, __LINE__);
+               drv->remove(dev);
+       } else {
+               dev_dbg(&dev->core, "%s:%d: no shutdown method\n", __func__,
+                       __LINE__);
+               BUG();
+       }
 
-static void ps3_vuart_port_release_device(struct device *_dev)
-{
-#if defined(DEBUG)
-       struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
+       ps3_vuart_cleanup(dev);
 
-       dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+       dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
 
-       BUG_ON(dev->priv && "forgot to free");
-       memset(&dev->core, 0, sizeof(dev->core));
-#endif
+       up(&vuart_bus_priv.probe_mutex);
+       return 0;
 }
 
-/**
- * ps3_vuart_port_device_register - Add a vuart port device.
- */
-
-int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev)
+static int __init ps3_vuart_bus_init(void)
 {
-       static unsigned int dev_count = 1;
-
-       BUG_ON(dev->priv && "forgot to free");
+       pr_debug("%s:%d:\n", __func__, __LINE__);
 
-       dev->core.parent = NULL;
-       dev->core.bus = &ps3_vuart_bus;
-       dev->core.release = ps3_vuart_port_release_device;
+       if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+               return -ENODEV;
 
-       snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "vuart_%02x",
-               dev_count++);
+       init_MUTEX(&vuart_bus_priv.probe_mutex);
 
-       dev_dbg(&dev->core, "%s:%d register\n", __func__, __LINE__);
+       return 0;
+}
 
-       return device_register(&dev->core);
+static void __exit ps3_vuart_bus_exit(void)
+{
+       pr_debug("%s:%d:\n", __func__, __LINE__);
 }
 
-EXPORT_SYMBOL_GPL(ps3_vuart_port_device_register);
+core_initcall(ps3_vuart_bus_init);
+module_exit(ps3_vuart_bus_exit);
 
 /**
  * ps3_vuart_port_driver_register - Add a vuart port device driver.
@@ -1089,12 +1245,18 @@ int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv)
 {
        int result;
 
-       pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name);
-       drv->core.bus = &ps3_vuart_bus;
-       result = driver_register(&drv->core);
+       pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.core.name);
+
+       BUG_ON(!drv->core.match_id);
+       BUG_ON(!drv->core.core.name);
+
+       drv->core.probe = ps3_vuart_probe;
+       drv->core.remove = ps3_vuart_remove;
+       drv->core.shutdown = ps3_vuart_shutdown;
+
+       result = ps3_system_bus_driver_register(&drv->core);
        return result;
 }
-
 EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register);
 
 /**
@@ -1103,8 +1265,7 @@ EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register);
 
 void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv)
 {
-       pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name);
-       driver_unregister(&drv->core);
+       pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.core.name);
+       ps3_system_bus_driver_unregister(&drv->core);
 }
-
 EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_unregister);
index 1be992d568c8344afe0d280886ae7e869ea9fcb8..eb7f6d94a8908d0bd9b70561511d164e386c93b8 100644 (file)
@@ -34,29 +34,7 @@ struct ps3_vuart_stats {
 struct ps3_vuart_work {
        struct work_struct work;
        unsigned long trigger;
-       spinlock_t lock;
-       struct ps3_vuart_port_device* dev; /* to convert work to device */
-};
-
-/**
- * struct ps3_vuart_port_priv - private vuart device data.
- */
-
-struct ps3_vuart_port_priv {
-       unsigned int port_number;
-       u64 interrupt_mask;
-
-       struct {
-               spinlock_t lock;
-               struct list_head head;
-       } tx_list;
-       struct {
-               unsigned long bytes_held;
-               spinlock_t lock;
-               struct list_head head;
-       } rx_list;
-       struct ps3_vuart_stats stats;
-       struct ps3_vuart_work work;
+       struct ps3_system_bus_device *dev; /* to convert work to device */
 };
 
 /**
@@ -64,32 +42,30 @@ struct ps3_vuart_port_priv {
  */
 
 struct ps3_vuart_port_driver {
-       enum ps3_match_id match_id;
-       struct device_driver core;
-       int (*probe)(struct ps3_vuart_port_device *);
-       int (*remove)(struct ps3_vuart_port_device *);
-       void (*shutdown)(struct ps3_vuart_port_device *);
-       int (*tx_event)(struct ps3_vuart_port_device *dev);
-       int (*rx_event)(struct ps3_vuart_port_device *dev);
-       int (*disconnect_event)(struct ps3_vuart_port_device *dev);
-       /* int (*suspend)(struct ps3_vuart_port_device *, pm_message_t); */
-       /* int (*resume)(struct ps3_vuart_port_device *); */
+       struct ps3_system_bus_driver core;
+       int (*probe)(struct ps3_system_bus_device *);
+       int (*remove)(struct ps3_system_bus_device *);
+       void (*shutdown)(struct ps3_system_bus_device *);
+       void (*work)(struct ps3_system_bus_device *);
+       /* int (*tx_event)(struct ps3_system_bus_device *dev); */
+       /* int (*rx_event)(struct ps3_system_bus_device *dev); */
+       /* int (*disconnect_event)(struct ps3_system_bus_device *dev); */
+       /* int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */
+       /* int (*resume)(struct ps3_system_bus_device *); */
 };
 
 int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv);
 void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv);
 
-static inline struct ps3_vuart_port_driver *to_ps3_vuart_port_driver(
-       struct device_driver *_drv)
-{
-       return container_of(_drv, struct ps3_vuart_port_driver, core);
-}
-static inline struct ps3_vuart_port_device *to_ps3_vuart_port_device(
-       struct device *_dev)
+static inline struct ps3_vuart_port_driver *
+       ps3_system_bus_dev_to_vuart_drv(struct ps3_system_bus_device *_dev)
 {
-       return container_of(_dev, struct ps3_vuart_port_device, core);
+       struct ps3_system_bus_driver *sbd =
+               ps3_system_bus_dev_to_system_bus_drv(_dev);
+       BUG_ON(!sbd);
+       return container_of(sbd, struct ps3_vuart_port_driver, core);
 }
-static inline struct ps3_vuart_port_device *ps3_vuart_work_to_port_device(
+static inline struct ps3_system_bus_device *ps3_vuart_work_to_system_bus_dev(
        struct work_struct *_work)
 {
        struct ps3_vuart_work *vw = container_of(_work, struct ps3_vuart_work,
@@ -97,14 +73,13 @@ static inline struct ps3_vuart_port_device *ps3_vuart_work_to_port_device(
        return vw->dev;
 }
 
-int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
-       unsigned int bytes);
-int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
+int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf,
        unsigned int bytes);
-int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func,
+int ps3_vuart_read(struct ps3_system_bus_device *dev, void *buf,
        unsigned int bytes);
-void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev);
-void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev,
+int ps3_vuart_read_async(struct ps3_system_bus_device *dev, unsigned int bytes);
+void ps3_vuart_cancel_async(struct ps3_system_bus_device *dev);
+void ps3_vuart_clear_rx_bytes(struct ps3_system_bus_device *dev,
        unsigned int bytes);
 
 #endif
index 4e4c10a7fd3a285add0920bb284129a0cbb78d65..83b071b6ece4184a0198683cb6dc032d281ad077 100644 (file)
@@ -246,7 +246,7 @@ comment "Platform RTC drivers"
 config RTC_DRV_CMOS
        tristate "PC-style 'CMOS'"
        depends on RTC_CLASS && (X86 || ALPHA || ARM26 || ARM \
-               || M32R || ATARI || POWERPC || MIPS)
+               || M32R || ATARI || PPC || MIPS)
        help
          Say "yes" here to get direct support for the real time clock
          found in every PC or ACPI-based system, and some other boards.
index b63ff8dd7304d8efd19d174a4ef9201d652ae6ae..cefde58dbad2c73dcba3078d108034d0332bd148 100644 (file)
@@ -678,7 +678,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
                }
                bdp->cbd_datlen = count;
                bdp->cbd_sc |= BD_SC_READY;
-               __asm__("eieio");
+               eieio();
                /* Get next BD. */
                if (bdp->cbd_sc & BD_SC_WRAP)
                        bdp = pinfo->tx_bd_base;
index 7ffdaeaf0545e2201803322a1b6959bd73feb3d8..a64d858219969d218c9a973d5b04224a838ea433 100644 (file)
 #include <asm/of_platform.h>
 #include <asm/prom.h>
 
+struct of_serial_info {
+       int type;
+       int line;
+};
+
 /*
  * Fill a struct uart_port for a given device node
  */
@@ -62,6 +67,7 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev,
 static int __devinit of_platform_serial_probe(struct of_device *ofdev,
                                                const struct of_device_id *id)
 {
+       struct of_serial_info *info;
        struct uart_port port;
        int port_type;
        int ret;
@@ -69,30 +75,35 @@ static int __devinit of_platform_serial_probe(struct of_device *ofdev,
        if (of_find_property(ofdev->node, "used-by-rtas", NULL))
                return -EBUSY;
 
+       info = kmalloc(sizeof(*info), GFP_KERNEL);
+       if (info == NULL)
+               return -ENOMEM;
+
        port_type = (unsigned long)id->data;
        ret = of_platform_serial_setup(ofdev, port_type, &port);
        if (ret)
                goto out;
 
        switch (port_type) {
-       case PORT_UNKNOWN:
-               dev_info(&ofdev->dev, "Unknown serial port found, "
-                       "attempting to use 8250 driver\n");
-               /* fallthrough */
        case PORT_8250 ... PORT_MAX_8250:
                ret = serial8250_register_port(&port);
                break;
        default:
                /* need to add code for these */
+       case PORT_UNKNOWN:
+               dev_info(&ofdev->dev, "Unknown serial port found, ignored\n");
                ret = -ENODEV;
                break;
        }
        if (ret < 0)
                goto out;
 
-       ofdev->dev.driver_data = (void *)(unsigned long)ret;
+       info->type = port_type;
+       info->line = ret;
+       ofdev->dev.driver_data = info;
        return 0;
 out:
+       kfree(info);
        irq_dispose_mapping(port.irq);
        return ret;
 }
@@ -102,8 +113,16 @@ out:
  */
 static int of_platform_serial_remove(struct of_device *ofdev)
 {
-       int line = (unsigned long)ofdev->dev.driver_data;
-       serial8250_unregister_port(line);
+       struct of_serial_info *info = ofdev->dev.driver_data;
+       switch (info->type) {
+       case PORT_8250 ... PORT_MAX_8250:
+               serial8250_unregister_port(info->line);
+               break;
+       default:
+               /* need to add code for these */
+               break;
+       }
+       kfree(info);
        return 0;
 }
 
index 403dac787ebf0f98975802648455470b9d8edcac..9b7a76be36a0bc203cc8973878b688e667ab4c21 100644 (file)
@@ -1790,8 +1790,8 @@ config FB_IBM_GXT4500
          adaptor, found on some IBM System P (pSeries) machines.
 
 config FB_PS3
-       bool "PS3 GPU framebuffer driver"
-       depends on (FB = y) && PS3_PS3AV
+       tristate "PS3 GPU framebuffer driver"
+       depends on FB && PS3_PS3AV
        select FB_SYS_FILLRECT
        select FB_SYS_COPYAREA
        select FB_SYS_IMAGEBLIT
index 9cf92ba5d6e309a16676ef6816271722f0eb09b3..08b7ffbbbbd862dc14f9cc405d5288c9f3409fa3 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/platform_device.h>
 #include <linux/console.h>
 #include <linux/ioctl.h>
 #include <linux/notifier.h>
@@ -46,6 +45,9 @@
 #include <asm/ps3fb.h>
 #include <asm/ps3.h>
 
+
+#define DEVICE_NAME            "ps3fb"
+
 #ifdef PS3FB_DEBUG
 #define DPRINTK(fmt, args...) printk("%s: " fmt, __func__ , ##args)
 #else
@@ -126,7 +128,6 @@ struct gpu_driver_info {
 
 struct ps3fb_priv {
        unsigned int irq_no;
-       void *dev;
 
        u64 context_handle, memory_handle;
        void *xdr_ea;
@@ -171,7 +172,7 @@ static const struct ps3fb_res_table ps3fb_res[] = {
        {    0,    0,   0,   0 , 0} };
 
 /* default resolution */
-#define GPU_RES_INDEX                /* 720 x 480 */
+#define GPU_RES_INDEX  0               /* 720 x 480 */
 
 static const struct fb_videomode ps3fb_modedb[] = {
     /* 60 Hz broadcast modes (modes "1" to "5") */
@@ -298,10 +299,9 @@ static const struct fb_videomode ps3fb_modedb[] = {
 #define FB_OFF(i)      (GPU_OFFSET - VP_OFF(i) % GPU_OFFSET)
 
 static int ps3fb_mode;
-module_param(ps3fb_mode, bool, 0);
-
-static char *mode_option __initdata;
+module_param(ps3fb_mode, int, 0);
 
+static char *mode_option __devinitdata;
 
 static int ps3fb_get_res_table(u32 xres, u32 yres)
 {
@@ -681,15 +681,15 @@ int ps3fb_wait_for_vsync(u32 crtc)
 
 EXPORT_SYMBOL_GPL(ps3fb_wait_for_vsync);
 
-void ps3fb_flip_ctl(int on)
+void ps3fb_flip_ctl(int on, void *data)
 {
+       struct ps3fb_priv *priv = data;
        if (on)
-               atomic_dec_if_positive(&ps3fb.ext_flip);
+               atomic_dec_if_positive(&priv->ext_flip);
        else
-               atomic_inc(&ps3fb.ext_flip);
+               atomic_inc(&priv->ext_flip);
 }
 
-EXPORT_SYMBOL_GPL(ps3fb_flip_ctl);
 
     /*
      * ioctl
@@ -851,37 +851,9 @@ static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr)
        return IRQ_HANDLED;
 }
 
-#ifndef MODULE
-static int __init ps3fb_setup(char *options)
-{
-       char *this_opt;
-       int mode = 0;
-
-       if (!options || !*options)
-               return 0;       /* no options */
-
-       while ((this_opt = strsep(&options, ",")) != NULL) {
-               if (!*this_opt)
-                       continue;
-               if (!strncmp(this_opt, "mode:", 5))
-                       mode = simple_strtoul(this_opt + 5, NULL, 0);
-               else
-                       mode_option = this_opt;
-       }
-       return mode;
-}
-#endif /* MODULE */
-
-    /*
-     *  Initialisation
-     */
 
-static void ps3fb_platform_release(struct device *device)
-{
-       /* This is called when the reference count goes to zero. */
-}
-
-static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev)
+static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo,
+                               struct ps3_system_bus_device *dev)
 {
        int error;
 
@@ -897,7 +869,6 @@ static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev)
                return -EINVAL;
        }
 
-       ps3fb.dev = dev;
        error = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
                                   &ps3fb.irq_no);
        if (error) {
@@ -907,7 +878,7 @@ static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev)
        }
 
        error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED,
-                           "ps3fb vsync", ps3fb.dev);
+                           DEVICE_NAME, dev);
        if (error) {
                printk(KERN_ERR "%s: request_irq failed %d\n", __func__,
                       error);
@@ -966,16 +937,45 @@ static struct fb_ops ps3fb_ops = {
 };
 
 static struct fb_fix_screeninfo ps3fb_fix __initdata = {
-       .id =           "PS3 FB",
+       .id =           DEVICE_NAME,
        .type =         FB_TYPE_PACKED_PIXELS,
        .visual =       FB_VISUAL_TRUECOLOR,
        .accel =        FB_ACCEL_NONE,
 };
 
-static int __init ps3fb_probe(struct platform_device *dev)
+static int ps3fb_set_sync(void)
+{
+       int status;
+
+#ifdef HEAD_A
+       status = lv1_gpu_context_attribute(0x0,
+                                          L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
+                                          0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
+       if (status) {
+               printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_SYNC "
+                      "failed: %d\n", __func__, status);
+               return -1;
+       }
+#endif
+#ifdef HEAD_B
+       status = lv1_gpu_context_attribute(0x0,
+                                          L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
+                                          1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
+
+       if (status) {
+               printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE "
+                      "failed: %d\n", __func__, status);
+               return -1;
+       }
+#endif
+       return 0;
+}
+
+static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
 {
        struct fb_info *info;
        int retval = -ENOMEM;
+       u32 xres, yres;
        u64 ddr_lpar = 0;
        u64 lpar_dma_control = 0;
        u64 lpar_driver_info = 0;
@@ -986,6 +986,30 @@ static int __init ps3fb_probe(struct platform_device *dev)
        unsigned long offset;
        struct task_struct *task;
 
+       status = ps3_open_hv_device(dev);
+       if (status) {
+               printk(KERN_ERR "%s: ps3_open_hv_device failed\n", __func__);
+               goto err;
+       }
+
+       if (!ps3fb_mode)
+               ps3fb_mode = ps3av_get_mode();
+       DPRINTK("ps3av_mode:%d\n", ps3fb_mode);
+
+       if (ps3fb_mode > 0 &&
+           !ps3av_video_mode2res(ps3fb_mode, &xres, &yres)) {
+               ps3fb.res_index = ps3fb_get_res_table(xres, yres);
+               DPRINTK("res_index:%d\n", ps3fb.res_index);
+       } else
+               ps3fb.res_index = GPU_RES_INDEX;
+
+       atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */
+       atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */
+       init_waitqueue_head(&ps3fb.wait_vsync);
+       ps3fb.num_frames = 1;
+
+       ps3fb_set_sync();
+
        /* get gpu context handle */
        status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0,
                                         &ps3fb.memory_handle, &ddr_lpar);
@@ -1029,7 +1053,7 @@ static int __init ps3fb_probe(struct platform_device *dev)
         * leakage into userspace
         */
        memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size);
-       info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
+       info = framebuffer_alloc(sizeof(u32) * 16, &dev->core);
        if (!info)
                goto err_free_irq;
 
@@ -1061,19 +1085,20 @@ static int __init ps3fb_probe(struct platform_device *dev)
        if (retval < 0)
                goto err_fb_dealloc;
 
-       platform_set_drvdata(dev, info);
+       dev->core.driver_data = info;
 
        printk(KERN_INFO
               "fb%d: PS3 frame buffer device, using %ld KiB of video memory\n",
               info->node, ps3fb_videomemory.size >> 10);
 
-       task = kthread_run(ps3fbd, info, "ps3fbd");
+       task = kthread_run(ps3fbd, info, DEVICE_NAME);
        if (IS_ERR(task)) {
                retval = PTR_ERR(task);
                goto err_unregister_framebuffer;
        }
 
        ps3fb.task = task;
+       ps3av_register_flip_ctl(ps3fb_flip_ctl, &ps3fb);
 
        return 0;
 
@@ -1084,7 +1109,7 @@ err_fb_dealloc:
 err_framebuffer_release:
        framebuffer_release(info);
 err_free_irq:
-       free_irq(ps3fb.irq_no, ps3fb.dev);
+       free_irq(ps3fb.irq_no, dev);
        ps3_irq_plug_destroy(ps3fb.irq_no);
 err_iounmap_dinfo:
        iounmap((u8 __iomem *)ps3fb.dinfo);
@@ -1096,26 +1121,30 @@ err:
        return retval;
 }
 
-static void ps3fb_shutdown(struct platform_device *dev)
+static int ps3fb_shutdown(struct ps3_system_bus_device *dev)
 {
-       ps3fb_flip_ctl(0);      /* flip off */
+       int status;
+       struct fb_info *info = dev->core.driver_data;
+
+       DPRINTK(" -> %s:%d\n", __func__, __LINE__);
+
+       ps3fb_flip_ctl(0, &ps3fb);      /* flip off */
        ps3fb.dinfo->irq.mask = 0;
-       free_irq(ps3fb.irq_no, ps3fb.dev);
-       ps3_irq_plug_destroy(ps3fb.irq_no);
-       iounmap((u8 __iomem *)ps3fb.dinfo);
-}
 
-void ps3fb_cleanup(void)
-{
-       int status;
+       if (info) {
+               unregister_framebuffer(info);
+               fb_dealloc_cmap(&info->cmap);
+               framebuffer_release(info);
+       }
 
+       ps3av_register_flip_ctl(NULL, NULL);
        if (ps3fb.task) {
                struct task_struct *task = ps3fb.task;
                ps3fb.task = NULL;
                kthread_stop(task);
        }
        if (ps3fb.irq_no) {
-               free_irq(ps3fb.irq_no, ps3fb.dev);
+               free_irq(ps3fb.irq_no, dev);
                ps3_irq_plug_destroy(ps3fb.irq_no);
        }
        iounmap((u8 __iomem *)ps3fb.dinfo);
@@ -1128,134 +1157,69 @@ void ps3fb_cleanup(void)
        if (status)
                DPRINTK("lv1_gpu_memory_free failed: %d\n", status);
 
-       ps3av_dev_close();
-}
+       ps3_close_hv_device(dev);
+       DPRINTK(" <- %s:%d\n", __func__, __LINE__);
 
-EXPORT_SYMBOL_GPL(ps3fb_cleanup);
-
-static int ps3fb_remove(struct platform_device *dev)
-{
-       struct fb_info *info = platform_get_drvdata(dev);
-
-       if (info) {
-               unregister_framebuffer(info);
-               fb_dealloc_cmap(&info->cmap);
-               framebuffer_release(info);
-       }
-       ps3fb_cleanup();
        return 0;
 }
 
-static struct platform_driver ps3fb_driver = {
-       .probe  = ps3fb_probe,
-       .remove = ps3fb_remove,
-       .shutdown = ps3fb_shutdown,
-       .driver = { .name = "ps3fb" }
-};
-
-static struct platform_device ps3fb_device = {
-       .name   = "ps3fb",
-       .id     = 0,
-       .dev    = { .release = ps3fb_platform_release }
+static struct ps3_system_bus_driver ps3fb_driver = {
+       .match_id       = PS3_MATCH_ID_GRAPHICS,
+       .core.name      = DEVICE_NAME,
+       .core.owner     = THIS_MODULE,
+       .probe          = ps3fb_probe,
+       .remove         = ps3fb_shutdown,
+       .shutdown       = ps3fb_shutdown,
 };
 
-int ps3fb_set_sync(void)
+static int __init ps3fb_setup(void)
 {
-       int status;
+       char *options;
 
-#ifdef HEAD_A
-       status = lv1_gpu_context_attribute(0x0,
-                                          L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
-                                          0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
-       if (status) {
-               printk(KERN_ERR
-                      "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: %d\n",
-                      __func__, status);
-               return -1;
-       }
-#endif
-#ifdef HEAD_B
-       status = lv1_gpu_context_attribute(0x0,
-                                          L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
-                                          1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
-
-       if (status) {
-               printk(KERN_ERR
-                      "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
-                      __func__, status);
-               return -1;
-       }
-#endif
+#ifdef MODULE
        return 0;
-}
-
-EXPORT_SYMBOL_GPL(ps3fb_set_sync);
-
-static int __init ps3fb_init(void)
-{
-       int error;
-#ifndef MODULE
-       int mode;
-       char *option = NULL;
-
-       if (fb_get_options("ps3fb", &option))
-               goto err;
 #endif
 
-       if (!ps3fb_videomemory.address)
-               goto err;
-
-       error = ps3av_dev_open();
-       if (error) {
-               printk(KERN_ERR "%s: ps3av_dev_open failed\n", __func__);
-               goto err;
-       }
+       if (fb_get_options(DEVICE_NAME, &options))
+               return -ENXIO;
 
-       ps3fb_mode = ps3av_get_mode();
-       DPRINTK("ps3av_mode:%d\n", ps3fb_mode);
-#ifndef MODULE
-       mode = ps3fb_setup(option);     /* check boot option */
-       if (mode)
-               ps3fb_mode = mode;
-#endif
-       if (ps3fb_mode > 0) {
-               u32 xres, yres;
-               ps3av_video_mode2res(ps3fb_mode, &xres, &yres);
-               ps3fb.res_index = ps3fb_get_res_table(xres, yres);
-               DPRINTK("res_index:%d\n", ps3fb.res_index);
-       } else
-               ps3fb.res_index = GPU_RES_INDEX;
+       if (!options || !*options)
+               return 0;
 
-       atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */
-       atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */
-       init_waitqueue_head(&ps3fb.wait_vsync);
-       ps3fb.num_frames = 1;
+       while (1) {
+               char *this_opt = strsep(&options, ",");
 
-       error = platform_driver_register(&ps3fb_driver);
-       if (!error) {
-               error = platform_device_register(&ps3fb_device);
-               if (error)
-                       platform_driver_unregister(&ps3fb_driver);
+               if (!this_opt)
+                       break;
+               if (!*this_opt)
+                       continue;
+               if (!strncmp(this_opt, "mode:", 5))
+                       ps3fb_mode = simple_strtoul(this_opt + 5, NULL, 0);
+               else
+                       mode_option = this_opt;
        }
+       return 0;
+}
 
-       ps3fb_set_sync();
-
-       return error;
+static int __init ps3fb_init(void)
+{
+       if (!ps3fb_videomemory.address ||  ps3fb_setup())
+               return -ENXIO;
 
-err:
-       return -ENXIO;
+       return ps3_system_bus_driver_register(&ps3fb_driver);
 }
 
-module_init(ps3fb_init);
-
-#ifdef MODULE
 static void __exit ps3fb_exit(void)
 {
-       platform_device_unregister(&ps3fb_device);
-       platform_driver_unregister(&ps3fb_driver);
+       DPRINTK(" -> %s:%d\n", __func__, __LINE__);
+       ps3_system_bus_driver_unregister(&ps3fb_driver);
+       DPRINTK(" <- %s:%d\n", __func__, __LINE__);
 }
 
+module_init(ps3fb_init);
 module_exit(ps3fb_exit);
 
 MODULE_LICENSE("GPL");
-#endif                         /* MODULE */
+MODULE_DESCRIPTION("PS3 GPU Frame Buffer Driver");
+MODULE_AUTHOR("Sony Computer Entertainment Inc.");
+MODULE_ALIAS(PS3_MODULE_ALIAS_GRAPHICS);
index 642be62cf393cd468b61b04e5adb4d87f23f7c07..53507046a1b101adcbda66dad89fc715ad9d0908 100644 (file)
@@ -34,5 +34,9 @@ struct ppc64_caches {
 extern struct ppc64_caches ppc64_caches;
 #endif /* __powerpc64__ && ! __ASSEMBLY__ */
 
+#if !defined(__ASSEMBLY__)
+#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_CACHE_H */
index 82d595a52109e9f08b8845fab66f9370ef048790..3dc8e2dfca84d26c9b92c36fc28ed42b068aacfd 100644 (file)
@@ -111,7 +111,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
 /* CPU kernel features */
 
 /* Retain the 32b definitions all use bottom half of word */
-#define CPU_FTR_SPLIT_ID_CACHE         ASM_CONST(0x0000000000000001)
+#define CPU_FTR_COHERENT_ICACHE                ASM_CONST(0x0000000000000001)
 #define CPU_FTR_L2CR                   ASM_CONST(0x0000000000000002)
 #define CPU_FTR_SPEC7450               ASM_CONST(0x0000000000000004)
 #define CPU_FTR_ALTIVEC                        ASM_CONST(0x0000000000000008)
@@ -135,6 +135,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
 #define CPU_FTR_PPC_LE                 ASM_CONST(0x0000000000200000)
 #define CPU_FTR_REAL_LE                        ASM_CONST(0x0000000000400000)
 #define CPU_FTR_FPU_UNAVAILABLE                ASM_CONST(0x0000000000800000)
+#define CPU_FTR_UNIFIED_ID_CACHE       ASM_CONST(0x0000000001000000)
 
 /*
  * Add the 64-bit processor unique features in the top half of the word;
@@ -154,7 +155,6 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
 #define CPU_FTR_MMCRA                  LONG_ASM_CONST(0x0000004000000000)
 #define CPU_FTR_CTRL                   LONG_ASM_CONST(0x0000008000000000)
 #define CPU_FTR_SMT                    LONG_ASM_CONST(0x0000010000000000)
-#define CPU_FTR_COHERENT_ICACHE                LONG_ASM_CONST(0x0000020000000000)
 #define CPU_FTR_LOCKLESS_TLBIE         LONG_ASM_CONST(0x0000040000000000)
 #define CPU_FTR_CI_LARGE_PAGE          LONG_ASM_CONST(0x0000100000000000)
 #define CPU_FTR_PAUSE_ZERO             LONG_ASM_CONST(0x0000200000000000)
@@ -206,164 +206,149 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
                     !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \
                     !defined(CONFIG_BOOKE))
 
-#define CPU_FTRS_PPC601        (CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE)
-#define CPU_FTRS_603   (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_PPC601        (CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE | \
+       CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE)
+#define CPU_FTRS_603   (CPU_FTR_COMMON | \
            CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
            CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
-#define CPU_FTRS_604   (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_604   (CPU_FTR_COMMON | \
            CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE | \
            CPU_FTR_PPC_LE)
-#define CPU_FTRS_740_NOTAU     (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_740_NOTAU     (CPU_FTR_COMMON | \
            CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
-#define CPU_FTRS_740   (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_740   (CPU_FTR_COMMON | \
            CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
            CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
            CPU_FTR_PPC_LE)
-#define CPU_FTRS_750   (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_750   (CPU_FTR_COMMON | \
            CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
            CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
            CPU_FTR_PPC_LE)
-#define CPU_FTRS_750CL (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-           CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-           CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
-#define CPU_FTRS_750FX1        (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-           CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-           CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM | CPU_FTR_PPC_LE)
-#define CPU_FTRS_750FX2        (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-           CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-           CPU_FTR_NO_DPM | CPU_FTR_PPC_LE)
-#define CPU_FTRS_750FX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-           CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-           CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
-#define CPU_FTRS_750GX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-           CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-           CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-           CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7400_NOTAU    (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_750CL (CPU_FTRS_750 | CPU_FTR_HAS_HIGH_BATS)
+#define CPU_FTRS_750FX1        (CPU_FTRS_750 | CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM)
+#define CPU_FTRS_750FX2        (CPU_FTRS_750 | CPU_FTR_NO_DPM)
+#define CPU_FTRS_750FX (CPU_FTRS_750 | CPU_FTR_DUAL_PLL_750FX | \
+               CPU_FTR_HAS_HIGH_BATS)
+#define CPU_FTRS_750GX (CPU_FTRS_750FX)
+#define CPU_FTRS_7400_NOTAU    (CPU_FTR_COMMON | \
            CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
            CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \
            CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7400  (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7400  (CPU_FTR_COMMON | \
            CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
            CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \
            CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7450_20       (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7450_20       (CPU_FTR_COMMON | \
            CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
            CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
            CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7450_21       (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7450_21       (CPU_FTR_COMMON | \
            CPU_FTR_USE_TB | \
            CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
            CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
            CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
            CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7450_23       (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7450_23       (CPU_FTR_COMMON | \
            CPU_FTR_USE_TB | \
            CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
            CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
            CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7455_1        (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7455_1        (CPU_FTR_COMMON | \
            CPU_FTR_USE_TB | \
            CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS | \
            CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7455_20       (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7455_20       (CPU_FTR_COMMON | \
            CPU_FTR_USE_TB | \
            CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
            CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
            CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
            CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7455  (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7455  (CPU_FTR_COMMON | \
            CPU_FTR_USE_TB | \
            CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
            CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
            CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
            CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7447_10       (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7447_10       (CPU_FTR_COMMON | \
            CPU_FTR_USE_TB | \
            CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
            CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
            CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
            CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7447  (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7447  (CPU_FTR_COMMON | \
            CPU_FTR_USE_TB | \
            CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
            CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
            CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
            CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7447A (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7447A (CPU_FTR_COMMON | \
            CPU_FTR_USE_TB | \
            CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
            CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
            CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
-#define CPU_FTRS_7448  (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_7448  (CPU_FTR_COMMON | \
            CPU_FTR_USE_TB | \
            CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
            CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
            CPU_FTR_PPC_LE)
-#define CPU_FTRS_82XX  (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_82XX  (CPU_FTR_COMMON | \
            CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB)
-#define CPU_FTRS_G2_LE (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+#define CPU_FTRS_G2_LE (CPU_FTR_MAYBE_CAN_DOZE | \
            CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS)
-#define CPU_FTRS_E300  (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+#define CPU_FTRS_E300  (CPU_FTR_MAYBE_CAN_DOZE | \
            CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
            CPU_FTR_COMMON)
-#define CPU_FTRS_E300C2        (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+#define CPU_FTRS_E300C2        (CPU_FTR_MAYBE_CAN_DOZE | \
            CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
            CPU_FTR_COMMON | CPU_FTR_FPU_UNAVAILABLE)
-#define CPU_FTRS_CLASSIC32     (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+#define CPU_FTRS_CLASSIC32     (CPU_FTR_COMMON | \
            CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE)
-#define CPU_FTRS_8XX   (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB)
-#define CPU_FTRS_40X   (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
-           CPU_FTR_NODSISRALIGN)
-#define CPU_FTRS_44X   (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
-           CPU_FTR_NODSISRALIGN)
-#define CPU_FTRS_E200  (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
-#define CPU_FTRS_E500  (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
-           CPU_FTR_NODSISRALIGN)
-#define CPU_FTRS_E500_2        (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_8XX   (CPU_FTR_USE_TB)
+#define CPU_FTRS_40X   (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_44X   (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_E200  (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | \
+           CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE)
+#define CPU_FTRS_E500  (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_E500_2        (CPU_FTR_USE_TB | \
            CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN)
 #define CPU_FTRS_GENERIC_32    (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
 
 /* 64-bit CPUs */
-#define CPU_FTRS_POWER3        (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER3        (CPU_FTR_USE_TB | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | CPU_FTR_PPC_LE)
-#define CPU_FTRS_RS64  (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_RS64  (CPU_FTR_USE_TB | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | \
            CPU_FTR_MMCRA | CPU_FTR_CTRL)
-#define CPU_FTRS_POWER4        (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER4        (CPU_FTR_USE_TB | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_MMCRA)
-#define CPU_FTRS_PPC970        (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_PPC970        (CPU_FTR_USE_TB | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA)
-#define CPU_FTRS_POWER5        (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER5        (CPU_FTR_USE_TB | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_MMCRA | CPU_FTR_SMT | \
            CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
            CPU_FTR_PURR)
-#define CPU_FTRS_POWER6 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_MMCRA | CPU_FTR_SMT | \
            CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
            CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
            CPU_FTR_DSCR)
-#define CPU_FTRS_CELL  (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_CELL  (CPU_FTR_USE_TB | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
            CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_CELL_TB_BUG)
-#define CPU_FTRS_PA6T (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_PA6T (CPU_FTR_USE_TB | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
            CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \
            CPU_FTR_PURR | CPU_FTR_REAL_LE)
-#define CPU_FTRS_COMPATIBLE    (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+#define CPU_FTRS_COMPATIBLE    (CPU_FTR_USE_TB | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2)
 
 #ifdef __powerpc64__
index afa700ded877fb9b64c98766fdfcfcd97844bfda..34146f0eea63c7af99dd9687478c1d1b329da5b0 100644 (file)
@@ -29,7 +29,7 @@
 #define fd_free_irq()           free_irq(FLOPPY_IRQ, NULL);
 
 #include <linux/pci.h>
-#include <asm/ppc-pci.h>       /* for ppc64_isabridge_dev */
+#include <asm/ppc-pci.h>       /* for isa_bridge_pcidev */
 
 #define fd_dma_setup(addr,size,mode,io) fd_ops->_dma_setup(addr,size,mode,io)
 
@@ -139,12 +139,12 @@ static int hard_dma_setup(char *addr, unsigned long size, int mode, int io)
        if (bus_addr 
            && (addr != prev_addr || size != prev_size || dir != prev_dir)) {
                /* different from last time -- unmap prev */
-               pci_unmap_single(ppc64_isabridge_dev, bus_addr, prev_size, prev_dir);
+               pci_unmap_single(isa_bridge_pcidev, bus_addr, prev_size, prev_dir);
                bus_addr = 0;
        }
 
        if (!bus_addr)  /* need to map it */
-               bus_addr = pci_map_single(ppc64_isabridge_dev, addr, size, dir);
+               bus_addr = pci_map_single(isa_bridge_pcidev, addr, size, dir);
 
        /* remember this one as prev */
        prev_addr = addr;
index 62efd9d7a43d508a8b4bcb9f7fe8e3838fa0cc37..bf6cd7cb996cf9f911d52bfaa20ff150a011684c 100644 (file)
 #define H_FREE_LOGICAL_LAN_BUFFER 0x1D4
 #define H_QUERY_INT_STATE       0x1E4
 #define H_POLL_PENDING         0x1D8
+#define H_ILLAN_ATTRIBUTES     0x244
 #define H_JOIN                 0x298
 #define H_VASI_STATE            0x2A4
 #define H_ENABLE_CRQ           0x2B0
index 350c9bdb31dccc7007c1f0bfa7bc72d569b55754..bb8d965f96c6bc42969c51009fe38ba7f12b371d 100644 (file)
@@ -607,9 +607,9 @@ static inline void iosync(void)
  *
  * * iounmap undoes such a mapping and can be hooked
  *
- * * __ioremap_explicit (and the pending __iounmap_explicit) are low level
- *   functions to create hand-made mappings for use only by the PCI code
- *   and cannot currently be hooked.
+ * * __ioremap_at (and the pending __iounmap_at) are low level functions to
+ *   create hand-made mappings for use only by the PCI code and cannot
+ *   currently be hooked. Must be page aligned.
  *
  * * __ioremap is the low level implementation used by ioremap and
  *   ioremap_flags and cannot be hooked (but can be used by a hook on one
@@ -629,19 +629,9 @@ extern void __iomem *__ioremap(phys_addr_t, unsigned long size,
                               unsigned long flags);
 extern void __iounmap(volatile void __iomem *addr);
 
-extern int __ioremap_explicit(phys_addr_t p_addr, unsigned long v_addr,
-                             unsigned long size, unsigned long flags);
-extern int __iounmap_explicit(volatile void __iomem *start,
-                             unsigned long size);
-
-extern void __iomem * reserve_phb_iospace(unsigned long size);
-
-/* Those are more 32 bits only functions */
-extern unsigned long iopa(unsigned long addr);
-extern unsigned long mm_ptov(unsigned long addr) __attribute_const__;
-extern void io_block_mapping(unsigned long virt, phys_addr_t phys,
-                            unsigned int size, int flags);
-
+extern void __iomem * __ioremap_at(phys_addr_t pa, void *ea,
+                                  unsigned long size, unsigned long flags);
+extern void __iounmap_at(void *ea, unsigned long size);
 
 /*
  * When CONFIG_PPC_INDIRECT_IO is set, we use the generic iomap implementation
@@ -651,8 +641,8 @@ extern void io_block_mapping(unsigned long virt, phys_addr_t phys,
  */
 #define HAVE_ARCH_PIO_SIZE             1
 #define PIO_OFFSET                     0x00000000UL
-#define PIO_MASK                       0x3fffffffUL
-#define PIO_RESERVED                   0x40000000UL
+#define PIO_MASK                       (FULL_IO_SIZE - 1)
+#define PIO_RESERVED                   (FULL_IO_SIZE)
 
 #define mmio_read16be(addr)            readw_be(addr)
 #define mmio_read32be(addr)            readl_be(addr)
index 05dd5a3eb3aad70f6fcee5db37ef203be69bcb95..0485c53db2b5dc64273ba5661918710c686a61e6 100644 (file)
@@ -223,6 +223,15 @@ extern void irq_dispose_mapping(unsigned int virq);
 extern unsigned int irq_find_mapping(struct irq_host *host,
                                     irq_hw_number_t hwirq);
 
+/**
+ * irq_create_direct_mapping - Allocate a virq for direct mapping
+ * @host: host to allocate the virq for or NULL for default host
+ *
+ * This routine is used for irq controllers which can choose the hardware
+ * interrupt numbers they generate. In such a case it's simplest to use
+ * the linux virq as the hardware interrupt number.
+ */
+extern unsigned int irq_create_direct_mapping(struct irq_host *host);
 
 /**
  * irq_radix_revmap - Find a linux virq from a hw irq number.
index 821ea0c512b415b552f7e088142e41063df96a6d..567ed92cd91ff6f1cf0b7193b990de75ec90ede1 100644 (file)
@@ -98,7 +98,7 @@ struct lppaca {
        u64     saved_gpr5;             // Saved GPR5                   x30-x37
 
        u8      reserved4;              // Reserved                     x38-x38
-       u8      cpuctls_task_attrs;     // Task attributes for cpuctls  x39-x39
+       u8      donate_dedicated_cpu;   // Donate dedicated CPU cycles  x39-x39
        u8      fpregs_in_use;          // FP regs in use               x3A-x3A
        u8      pmcregs_in_use;         // PMC regs in use              x3B-x3B
        volatile u32 saved_decr;        // Saved Decr Value             x3C-x3F
index f733beeea63a914a778bd44576a58bcbe30d6b18..81713acf752997787b2ab58b7316debf10aec178 100644 (file)
@@ -238,6 +238,7 @@ LV1_CALL(destruct_virtual_address_space,                1, 0,  10 )
 LV1_CALL(configure_irq_state_bitmap,                    3, 0,  11 )
 LV1_CALL(connect_irq_plug_ext,                          5, 0,  12 )
 LV1_CALL(release_memory,                                1, 0,  13 )
+LV1_CALL(put_iopte,                                     5, 0,  15 )
 LV1_CALL(disconnect_irq_plug_ext,                       3, 0,  17 )
 LV1_CALL(construct_event_receive_port,                  0, 1,  18 )
 LV1_CALL(destruct_event_receive_port,                   1, 0,  19 )
@@ -268,6 +269,8 @@ LV1_CALL(remove_repository_node,                        4, 0,  93 )
 LV1_CALL(read_htab_entries,                             2, 5,  95 )
 LV1_CALL(set_dabr,                                      2, 0,  96 )
 LV1_CALL(get_total_execution_time,                      2, 1, 103 )
+LV1_CALL(allocate_io_segment,                           3, 1, 116 )
+LV1_CALL(release_io_segment,                            2, 0, 117 )
 LV1_CALL(construct_io_irq_outlet,                       1, 1, 120 )
 LV1_CALL(destruct_io_irq_outlet,                        1, 0, 121 )
 LV1_CALL(map_htab,                                      1, 1, 122 )
index 6cf1a831f550835692c2d06f63e10b540524adba..71c6e7eb2a266798d56e3c6676d528fa1fa8be3f 100644 (file)
@@ -218,7 +218,7 @@ struct machdep_calls {
        int  (*pcibios_enable_device_hook)(struct pci_dev *, int initial);
 
        /* Called in indirect_* to avoid touching devices */
-       int (*pci_exclude_device)(unsigned char, unsigned char);
+       int (*pci_exclude_device)(struct pci_controller *, unsigned char, unsigned char);
 
        /* Called at then very end of pcibios_init() */
        void (*pcibios_after_init)(void);
diff --git a/include/asm-powerpc/mmu-8xx.h b/include/asm-powerpc/mmu-8xx.h
new file mode 100644 (file)
index 0000000..952bd88
--- /dev/null
@@ -0,0 +1,147 @@
+#ifndef _ASM_POWERPC_MMU_8XX_H_
+#define _ASM_POWERPC_MMU_8XX_H_
+/*
+ * PPC8xx support
+ */
+
+/* Control/status registers for the MPC8xx.
+ * A write operation to these registers causes serialized access.
+ * During software tablewalk, the registers used perform mask/shift-add
+ * operations when written/read.  A TLB entry is created when the Mx_RPN
+ * is written, and the contents of several registers are used to
+ * create the entry.
+ */
+#define SPRN_MI_CTR    784     /* Instruction TLB control register */
+#define MI_GPM         0x80000000      /* Set domain manager mode */
+#define MI_PPM         0x40000000      /* Set subpage protection */
+#define MI_CIDEF       0x20000000      /* Set cache inhibit when MMU dis */
+#define MI_RSV4I       0x08000000      /* Reserve 4 TLB entries */
+#define MI_PPCS                0x02000000      /* Use MI_RPN prob/priv state */
+#define MI_IDXMASK     0x00001f00      /* TLB index to be loaded */
+#define MI_RESETVAL    0x00000000      /* Value of register at reset */
+
+/* These are the Ks and Kp from the PowerPC books.  For proper operation,
+ * Ks = 0, Kp = 1.
+ */
+#define SPRN_MI_AP     786
+#define MI_Ks          0x80000000      /* Should not be set */
+#define MI_Kp          0x40000000      /* Should always be set */
+
+/* The effective page number register.  When read, contains the information
+ * about the last instruction TLB miss.  When MI_RPN is written, bits in
+ * this register are used to create the TLB entry.
+ */
+#define SPRN_MI_EPN    787
+#define MI_EPNMASK     0xfffff000      /* Effective page number for entry */
+#define MI_EVALID      0x00000200      /* Entry is valid */
+#define MI_ASIDMASK    0x0000000f      /* ASID match value */
+                                       /* Reset value is undefined */
+
+/* A "level 1" or "segment" or whatever you want to call it register.
+ * For the instruction TLB, it contains bits that get loaded into the
+ * TLB entry when the MI_RPN is written.
+ */
+#define SPRN_MI_TWC    789
+#define MI_APG         0x000001e0      /* Access protection group (0) */
+#define MI_GUARDED     0x00000010      /* Guarded storage */
+#define MI_PSMASK      0x0000000c      /* Mask of page size bits */
+#define MI_PS8MEG      0x0000000c      /* 8M page size */
+#define MI_PS512K      0x00000004      /* 512K page size */
+#define MI_PS4K_16K    0x00000000      /* 4K or 16K page size */
+#define MI_SVALID      0x00000001      /* Segment entry is valid */
+                                       /* Reset value is undefined */
+
+/* Real page number.  Defined by the pte.  Writing this register
+ * causes a TLB entry to be created for the instruction TLB, using
+ * additional information from the MI_EPN, and MI_TWC registers.
+ */
+#define SPRN_MI_RPN    790
+
+/* Define an RPN value for mapping kernel memory to large virtual
+ * pages for boot initialization.  This has real page number of 0,
+ * large page size, shared page, cache enabled, and valid.
+ * Also mark all subpages valid and write access.
+ */
+#define MI_BOOTINIT    0x000001fd
+
+#define SPRN_MD_CTR    792     /* Data TLB control register */
+#define MD_GPM         0x80000000      /* Set domain manager mode */
+#define MD_PPM         0x40000000      /* Set subpage protection */
+#define MD_CIDEF       0x20000000      /* Set cache inhibit when MMU dis */
+#define MD_WTDEF       0x10000000      /* Set writethrough when MMU dis */
+#define MD_RSV4I       0x08000000      /* Reserve 4 TLB entries */
+#define MD_TWAM                0x04000000      /* Use 4K page hardware assist */
+#define MD_PPCS                0x02000000      /* Use MI_RPN prob/priv state */
+#define MD_IDXMASK     0x00001f00      /* TLB index to be loaded */
+#define MD_RESETVAL    0x04000000      /* Value of register at reset */
+
+#define SPRN_M_CASID   793     /* Address space ID (context) to match */
+#define MC_ASIDMASK    0x0000000f      /* Bits used for ASID value */
+
+
+/* These are the Ks and Kp from the PowerPC books.  For proper operation,
+ * Ks = 0, Kp = 1.
+ */
+#define SPRN_MD_AP     794
+#define MD_Ks          0x80000000      /* Should not be set */
+#define MD_Kp          0x40000000      /* Should always be set */
+
+/* The effective page number register.  When read, contains the information
+ * about the last instruction TLB miss.  When MD_RPN is written, bits in
+ * this register are used to create the TLB entry.
+ */
+#define SPRN_MD_EPN    795
+#define MD_EPNMASK     0xfffff000      /* Effective page number for entry */
+#define MD_EVALID      0x00000200      /* Entry is valid */
+#define MD_ASIDMASK    0x0000000f      /* ASID match value */
+                                       /* Reset value is undefined */
+
+/* The pointer to the base address of the first level page table.
+ * During a software tablewalk, reading this register provides the address
+ * of the entry associated with MD_EPN.
+ */
+#define SPRN_M_TWB     796
+#define        M_L1TB          0xfffff000      /* Level 1 table base address */
+#define M_L1INDX       0x00000ffc      /* Level 1 index, when read */
+                                       /* Reset value is undefined */
+
+/* A "level 1" or "segment" or whatever you want to call it register.
+ * For the data TLB, it contains bits that get loaded into the TLB entry
+ * when the MD_RPN is written.  It is also provides the hardware assist
+ * for finding the PTE address during software tablewalk.
+ */
+#define SPRN_MD_TWC    797
+#define MD_L2TB                0xfffff000      /* Level 2 table base address */
+#define MD_L2INDX      0xfffffe00      /* Level 2 index (*pte), when read */
+#define MD_APG         0x000001e0      /* Access protection group (0) */
+#define MD_GUARDED     0x00000010      /* Guarded storage */
+#define MD_PSMASK      0x0000000c      /* Mask of page size bits */
+#define MD_PS8MEG      0x0000000c      /* 8M page size */
+#define MD_PS512K      0x00000004      /* 512K page size */
+#define MD_PS4K_16K    0x00000000      /* 4K or 16K page size */
+#define MD_WT          0x00000002      /* Use writethrough page attribute */
+#define MD_SVALID      0x00000001      /* Segment entry is valid */
+                                       /* Reset value is undefined */
+
+
+/* Real page number.  Defined by the pte.  Writing this register
+ * causes a TLB entry to be created for the data TLB, using
+ * additional information from the MD_EPN, and MD_TWC registers.
+ */
+#define SPRN_MD_RPN    798
+
+/* This is a temporary storage register that could be used to save
+ * a processor working register during a tablewalk.
+ */
+#define SPRN_M_TW      799
+
+#ifndef __ASSEMBLY__
+typedef unsigned long phys_addr_t;
+
+typedef struct {
+       unsigned long id;
+       unsigned long vdso_base;
+} mm_context_t;
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_POWERPC_MMU_8XX_H_ */
diff --git a/include/asm-powerpc/mmu-fsl-booke.h b/include/asm-powerpc/mmu-fsl-booke.h
new file mode 100644 (file)
index 0000000..3758000
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef _ASM_POWERPC_MMU_FSL_BOOKE_H_
+#define _ASM_POWERPC_MMU_FSL_BOOKE_H_
+/*
+ * Freescale Book-E MMU support
+ */
+
+/* Book-E defined page sizes */
+#define BOOKE_PAGESZ_1K                0
+#define BOOKE_PAGESZ_4K                1
+#define BOOKE_PAGESZ_16K       2
+#define BOOKE_PAGESZ_64K       3
+#define BOOKE_PAGESZ_256K      4
+#define BOOKE_PAGESZ_1M                5
+#define BOOKE_PAGESZ_4M                6
+#define BOOKE_PAGESZ_16M       7
+#define BOOKE_PAGESZ_64M       8
+#define BOOKE_PAGESZ_256M      9
+#define BOOKE_PAGESZ_1GB       10
+#define BOOKE_PAGESZ_4GB       11
+#define BOOKE_PAGESZ_16GB      12
+#define BOOKE_PAGESZ_64GB      13
+#define BOOKE_PAGESZ_256GB     14
+#define BOOKE_PAGESZ_1TB       15
+
+#define MAS0_TLBSEL(x) ((x << 28) & 0x30000000)
+#define MAS0_ESEL(x)   ((x << 16) & 0x0FFF0000)
+#define MAS0_NV(x)     ((x) & 0x00000FFF)
+
+#define MAS1_VALID     0x80000000
+#define MAS1_IPROT     0x40000000
+#define MAS1_TID(x)    ((x << 16) & 0x3FFF0000)
+#define MAS1_TS                0x00001000
+#define MAS1_TSIZE(x)  ((x << 8) & 0x00000F00)
+
+#define MAS2_EPN       0xFFFFF000
+#define MAS2_X0                0x00000040
+#define MAS2_X1                0x00000020
+#define MAS2_W         0x00000010
+#define MAS2_I         0x00000008
+#define MAS2_M         0x00000004
+#define MAS2_G         0x00000002
+#define MAS2_E         0x00000001
+
+#define MAS3_RPN       0xFFFFF000
+#define MAS3_U0                0x00000200
+#define MAS3_U1                0x00000100
+#define MAS3_U2                0x00000080
+#define MAS3_U3                0x00000040
+#define MAS3_UX                0x00000020
+#define MAS3_SX                0x00000010
+#define MAS3_UW                0x00000008
+#define MAS3_SW                0x00000004
+#define MAS3_UR                0x00000002
+#define MAS3_SR                0x00000001
+
+#define MAS4_TLBSELD(x) MAS0_TLBSEL(x)
+#define MAS4_TIDDSEL   0x000F0000
+#define MAS4_TSIZED(x) MAS1_TSIZE(x)
+#define MAS4_X0D       0x00000040
+#define MAS4_X1D       0x00000020
+#define MAS4_WD                0x00000010
+#define MAS4_ID                0x00000008
+#define MAS4_MD                0x00000004
+#define MAS4_GD                0x00000002
+#define MAS4_ED                0x00000001
+
+#define MAS6_SPID0     0x3FFF0000
+#define MAS6_SPID1     0x00007FFE
+#define MAS6_SAS       0x00000001
+#define MAS6_SPID      MAS6_SPID0
+
+#define MAS7_RPN       0xFFFFFFFF
+
+#ifndef __ASSEMBLY__
+
+#ifndef CONFIG_PHYS_64BIT
+typedef unsigned long phys_addr_t;
+#else
+typedef unsigned long long phys_addr_t;
+#endif
+
+typedef struct {
+       unsigned long id;
+       unsigned long vdso_base;
+} mm_context_t;
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_POWERPC_MMU_FSL_BOOKE_H_ */
diff --git a/include/asm-powerpc/mmu-hash32.h b/include/asm-powerpc/mmu-hash32.h
new file mode 100644 (file)
index 0000000..4bd735b
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef _ASM_POWERPC_MMU_HASH32_H_
+#define _ASM_POWERPC_MMU_HASH32_H_
+/*
+ * 32-bit hash table MMU support
+ */
+
+/*
+ * BATs
+ */
+
+/* Block size masks */
+#define BL_128K        0x000
+#define BL_256K 0x001
+#define BL_512K 0x003
+#define BL_1M   0x007
+#define BL_2M   0x00F
+#define BL_4M   0x01F
+#define BL_8M   0x03F
+#define BL_16M  0x07F
+#define BL_32M  0x0FF
+#define BL_64M  0x1FF
+#define BL_128M 0x3FF
+#define BL_256M 0x7FF
+
+/* BAT Access Protection */
+#define BPP_XX 0x00            /* No access */
+#define BPP_RX 0x01            /* Read only */
+#define BPP_RW 0x02            /* Read/write */
+
+#ifndef __ASSEMBLY__
+struct ppc_bat {
+       struct {
+               unsigned long bepi:15;  /* Effective page index (virtual address) */
+               unsigned long :4;       /* Unused */
+               unsigned long bl:11;    /* Block size mask */
+               unsigned long vs:1;     /* Supervisor valid */
+               unsigned long vp:1;     /* User valid */
+       } batu;                 /* Upper register */
+       struct {
+               unsigned long brpn:15;  /* Real page index (physical address) */
+               unsigned long :10;      /* Unused */
+               unsigned long w:1;      /* Write-thru cache */
+               unsigned long i:1;      /* Cache inhibit */
+               unsigned long m:1;      /* Memory coherence */
+               unsigned long g:1;      /* Guarded (MBZ in IBAT) */
+               unsigned long :1;       /* Unused */
+               unsigned long pp:2;     /* Page access protections */
+       } batl;                 /* Lower register */
+};
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * Hash table
+ */
+
+/* Values for PP (assumes Ks=0, Kp=1) */
+#define PP_RWXX        0       /* Supervisor read/write, User none */
+#define PP_RWRX 1      /* Supervisor read/write, User read */
+#define PP_RWRW 2      /* Supervisor read/write, User read/write */
+#define PP_RXRX 3      /* Supervisor read,       User read */
+
+#ifndef __ASSEMBLY__
+
+/* Hardware Page Table Entry */
+struct hash_pte {
+       unsigned long v:1;      /* Entry is valid */
+       unsigned long vsid:24;  /* Virtual segment identifier */
+       unsigned long h:1;      /* Hash algorithm indicator */
+       unsigned long api:6;    /* Abbreviated page index */
+       unsigned long rpn:20;   /* Real (physical) page number */
+       unsigned long    :3;    /* Unused */
+       unsigned long r:1;      /* Referenced */
+       unsigned long c:1;      /* Changed */
+       unsigned long w:1;      /* Write-thru cache mode */
+       unsigned long i:1;      /* Cache inhibited */
+       unsigned long m:1;      /* Memory coherence */
+       unsigned long g:1;      /* Guarded */
+       unsigned long  :1;      /* Unused */
+       unsigned long pp:2;     /* Page protection */
+};
+
+typedef struct {
+       unsigned long id;
+       unsigned long vdso_base;
+} mm_context_t;
+
+typedef unsigned long phys_addr_t;
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_POWERPC_MMU_HASH32_H_ */
index b8dca30bd0b57436a4401608f57183e9a32caaac..695962f020597bc5f668ca5c5d06e272eaa0a4f6 100644 (file)
@@ -94,6 +94,9 @@ extern char initial_stab[];
 #define HPTE_R_C               ASM_CONST(0x0000000000000080)
 #define HPTE_R_R               ASM_CONST(0x0000000000000100)
 
+#define HPTE_V_1TB_SEG         ASM_CONST(0x4000000000000000)
+#define HPTE_V_VRMA_MASK       ASM_CONST(0x4001ffffff000000)
+
 /* Values for PP (assumes Ks=0, Kp=1) */
 /* pp0 will always be 0 for linux     */
 #define PP_RWXX        0       /* Supervisor read/write, User none */
@@ -103,12 +106,12 @@ extern char initial_stab[];
 
 #ifndef __ASSEMBLY__
 
-typedef struct {
+struct hash_pte {
        unsigned long v;
        unsigned long r;
-} hpte_t;
+};
 
-extern hpte_t *htab_address;
+extern struct hash_pte *htab_address;
 extern unsigned long htab_size_bytes;
 extern unsigned long htab_hash_mask;
 
index fe510fff89078e36a365543c406fff9a9d630fa8..d44d211e7588e587022c1d4550fbfcf16ea0a828 100644 (file)
@@ -5,13 +5,18 @@
 #ifdef CONFIG_PPC64
 /* 64-bit classic hash table MMU */
 #  include <asm/mmu-hash64.h>
+#elif defined(CONFIG_PPC_STD_MMU)
+/* 32-bit classic hash table MMU */
+#  include <asm/mmu-hash32.h>
 #elif defined(CONFIG_44x)
 /* 44x-style software loaded TLB */
 #  include <asm/mmu-44x.h>
-#else
-/* Other 32-bit.  FIXME: split up the other 32-bit MMU types, and
- * revise for arch/powerpc */
-#  include <asm-ppc/mmu.h>
+#elif defined(CONFIG_FSL_BOOKE)
+/* Freescale Book-E software loaded TLB */
+#  include <asm/mmu-fsl-booke.h>
+#elif defined (CONFIG_PPC_8xx)
+/* Motorola/Freescale 8xx software loaded TLB */
+#  include <asm/mmu-8xx.h>
 #endif
 
 #endif /* __KERNEL__ */
index 40c9e5a13ff11cef90afffff393ed536e07dcdb1..f863ac21409e7b4166add8e1fea65c4e8ab05ac7 100644 (file)
 #define __ASM_POWERPC_MMU_CONTEXT_H
 #ifdef __KERNEL__
 
+#include <asm/mmu.h>   
+#include <asm/cputable.h>
+#include <asm-generic/mm_hooks.h>
+
 #ifndef CONFIG_PPC64
-#include <asm-ppc/mmu_context.h>
+#include <asm/atomic.h>
+#include <asm/bitops.h>
+
+/*
+ * On 32-bit PowerPC 6xx/7xx/7xxx CPUs, we use a set of 16 VSIDs
+ * (virtual segment identifiers) for each context.  Although the
+ * hardware supports 24-bit VSIDs, and thus >1 million contexts,
+ * we only use 32,768 of them.  That is ample, since there can be
+ * at most around 30,000 tasks in the system anyway, and it means
+ * that we can use a bitmap to indicate which contexts are in use.
+ * Using a bitmap means that we entirely avoid all of the problems
+ * that we used to have when the context number overflowed,
+ * particularly on SMP systems.
+ *  -- paulus.
+ */
+
+/*
+ * This function defines the mapping from contexts to VSIDs (virtual
+ * segment IDs).  We use a skew on both the context and the high 4 bits
+ * of the 32-bit virtual address (the "effective segment ID") in order
+ * to spread out the entries in the MMU hash table.  Note, if this
+ * function is changed then arch/ppc/mm/hashtable.S will have to be
+ * changed to correspond.
+ */
+#define CTX_TO_VSID(ctx, va)   (((ctx) * (897 * 16) + ((va) >> 28) * 0x111) \
+                                & 0xffffff)
+
+/*
+   The MPC8xx has only 16 contexts.  We rotate through them on each
+   task switch.  A better way would be to keep track of tasks that
+   own contexts, and implement an LRU usage.  That way very active
+   tasks don't always have to pay the TLB reload overhead.  The
+   kernel pages are mapped shared, so the kernel can run on behalf
+   of any task that makes a kernel entry.  Shared does not mean they
+   are not protected, just that the ASID comparison is not performed.
+        -- Dan
+
+   The IBM4xx has 256 contexts, so we can just rotate through these
+   as a way of "switching" contexts.  If the TID of the TLB is zero,
+   the PID/TID comparison is disabled, so we can use a TID of zero
+   to represent all kernel pages as shared among all contexts.
+       -- Dan
+ */
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+}
+
+#ifdef CONFIG_8xx
+#define NO_CONTEXT             16
+#define LAST_CONTEXT           15
+#define FIRST_CONTEXT          0
+
+#elif defined(CONFIG_4xx)
+#define NO_CONTEXT             256
+#define LAST_CONTEXT           255
+#define FIRST_CONTEXT          1
+
+#elif defined(CONFIG_E200) || defined(CONFIG_E500)
+#define NO_CONTEXT             256
+#define LAST_CONTEXT           255
+#define FIRST_CONTEXT          1
+
+#else
+
+/* PPC 6xx, 7xx CPUs */
+#define NO_CONTEXT             ((unsigned long) -1)
+#define LAST_CONTEXT           32767
+#define FIRST_CONTEXT          1
+#endif
+
+/*
+ * Set the current MMU context.
+ * On 32-bit PowerPCs (other than the 8xx embedded chips), this is done by
+ * loading up the segment registers for the user part of the address space.
+ *
+ * Since the PGD is immediately available, it is much faster to simply
+ * pass this along as a second parameter, which is required for 8xx and
+ * can be used for debugging on all processors (if you happen to have
+ * an Abatron).
+ */
+extern void set_context(unsigned long contextid, pgd_t *pgd);
+
+/*
+ * Bitmap of contexts in use.
+ * The size of this bitmap is LAST_CONTEXT + 1 bits.
+ */
+extern unsigned long context_map[];
+
+/*
+ * This caches the next context number that we expect to be free.
+ * Its use is an optimization only, we can't rely on this context
+ * number to be free, but it usually will be.
+ */
+extern unsigned long next_mmu_context;
+
+/*
+ * If we don't have sufficient contexts to give one to every task
+ * that could be in the system, we need to be able to steal contexts.
+ * These variables support that.
+ */
+#if LAST_CONTEXT < 30000
+#define FEW_CONTEXTS   1
+extern atomic_t nr_free_contexts;
+extern struct mm_struct *context_mm[LAST_CONTEXT+1];
+extern void steal_context(void);
+#endif
+
+/*
+ * Get a new mmu context for the address space described by `mm'.
+ */
+static inline void get_mmu_context(struct mm_struct *mm)
+{
+       unsigned long ctx;
+
+       if (mm->context.id != NO_CONTEXT)
+               return;
+#ifdef FEW_CONTEXTS
+       while (atomic_dec_if_positive(&nr_free_contexts) < 0)
+               steal_context();
+#endif
+       ctx = next_mmu_context;
+       while (test_and_set_bit(ctx, context_map)) {
+               ctx = find_next_zero_bit(context_map, LAST_CONTEXT+1, ctx);
+               if (ctx > LAST_CONTEXT)
+                       ctx = 0;
+       }
+       next_mmu_context = (ctx + 1) & LAST_CONTEXT;
+       mm->context.id = ctx;
+#ifdef FEW_CONTEXTS
+       context_mm[ctx] = mm;
+#endif
+}
+
+/*
+ * Set up the context for a new address space.
+ */
+static inline int init_new_context(struct task_struct *t, struct mm_struct *mm)
+{
+       mm->context.id = NO_CONTEXT;
+       mm->context.vdso_base = 0;
+       return 0;
+}
+
+/*
+ * We're finished using the context for an address space.
+ */
+static inline void destroy_context(struct mm_struct *mm)
+{
+       preempt_disable();
+       if (mm->context.id != NO_CONTEXT) {
+               clear_bit(mm->context.id, context_map);
+               mm->context.id = NO_CONTEXT;
+#ifdef FEW_CONTEXTS
+               atomic_inc(&nr_free_contexts);
+#endif
+       }
+       preempt_enable();
+}
+
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+                            struct task_struct *tsk)
+{
+#ifdef CONFIG_ALTIVEC
+       if (cpu_has_feature(CPU_FTR_ALTIVEC))
+       asm volatile ("dssall;\n"
+#ifndef CONFIG_POWER4
+        "sync;\n" /* G4 needs a sync here, G5 apparently not */
+#endif
+        : : );
+#endif /* CONFIG_ALTIVEC */
+
+       tsk->thread.pgdir = next->pgd;
+
+       /* No need to flush userspace segments if the mm doesnt change */
+       if (prev == next)
+               return;
+
+       /* Setup new userspace context */
+       get_mmu_context(next);
+       set_context(next->context.id, next->pgd);
+}
+
+#define deactivate_mm(tsk,mm)  do { } while (0)
+
+/*
+ * After we have set current->mm to a new value, this activates
+ * the context for the new mm so we see the new mappings.
+ */
+#define activate_mm(active_mm, mm)   switch_mm(active_mm, mm, current)
+
+extern void mmu_context_init(void);
+
+
 #else
 
 #include <linux/kernel.h>      
 #include <linux/mm.h>  
 #include <linux/sched.h>
-#include <asm/mmu.h>   
-#include <asm/cputable.h>
-#include <asm-generic/mm_hooks.h>
 
 /*
  * Copyright (C) 2001 PPC 64 Team, IBM Corp
index b85df45b1a84dcbfc37b93ee74365eaa3fcc8b31..15f650f987e75ba6ecf5f0db3c3f6bccff7af08b 100644 (file)
 
 #ifdef CONFIG_PPC_86xx
 
-#define _IO_BASE        isa_io_base
-#define _ISA_MEM_BASE   isa_mem_base
-#ifdef CONFIG_PCI
-#define PCI_DRAM_OFFSET pci_dram_offset
-#endif
-
 #define CPU0_BOOT_RELEASE 0x01000000
 #define CPU1_BOOT_RELEASE 0x02000000
 #define CPU_ALL_RELEASED (CPU0_BOOT_RELEASE | CPU1_BOOT_RELEASE)
index 580371120e1aa57f37010e430da8692db868b9a4..2be014b6f57c52efce9b6a6faa214c791f6514c3 100644 (file)
 #include <platforms/8xx/mpc885ads.h>
 #endif
 
+#ifdef CONFIG_PCMCIA_M8XX
+extern struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops;
+#endif
+
 #endif /* CONFIG_8xx */
 #endif /* __CONFIG_8xx_DEFS */
 #endif /* __KERNEL__ */
index d9bf5aba96cbd25c262f634410c51275cdb9ecfc..e72c2a60853c14de8e9721d925f887067ec6fcde 100644 (file)
@@ -2,12 +2,91 @@
 #define _ASM_POWERPC_PCI_BRIDGE_H
 #ifdef __KERNEL__
 
+#include <linux/pci.h>
+#include <linux/list.h>
+#include <linux/ioport.h>
+
 #ifndef CONFIG_PPC64
-#include <asm-ppc/pci-bridge.h>
+
+struct device_node;
+struct pci_controller;
+
+/*
+ * Structure of a PCI controller (host bridge)
+ */
+struct pci_controller {
+       struct pci_bus *bus;
+       char is_dynamic;
+       void *arch_data;
+       struct list_head list_node;
+       struct device *parent;
+
+       int first_busno;
+       int last_busno;
+       int self_busno;
+
+       void __iomem *io_base_virt;
+       resource_size_t io_base_phys;
+
+       /* Some machines (PReP) have a non 1:1 mapping of
+        * the PCI memory space in the CPU bus space
+        */
+       resource_size_t pci_mem_offset;
+
+       struct pci_ops *ops;
+       volatile unsigned int __iomem *cfg_addr;
+       volatile void __iomem *cfg_data;
+
+       /*
+        * Used for variants of PCI indirect handling and possible quirks:
+        *  SET_CFG_TYPE - used on 4xx or any PHB that does explicit type0/1
+        *  EXT_REG - provides access to PCI-e extended registers
+        *  SURPRESS_PRIMARY_BUS - we surpress the setting of PCI_PRIMARY_BUS
+        *   on Freescale PCI-e controllers since they used the PCI_PRIMARY_BUS
+        *   to determine which bus number to match on when generating type0
+        *   config cycles
+        */
+#define PPC_INDIRECT_TYPE_SET_CFG_TYPE         (0x00000001)
+#define PPC_INDIRECT_TYPE_EXT_REG              (0x00000002)
+#define PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS (0x00000004)
+       u32 indirect_type;
+
+       /* Currently, we limit ourselves to 1 IO range and 3 mem
+        * ranges since the common pci_bus structure can't handle more
+        */
+       struct resource io_resource;
+       struct resource mem_resources[3];
+       int global_number;              /* PCI domain number */
+};
+
+static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
+{
+       return bus->sysdata;
+}
+
+/* These are used for config access before all the PCI probing
+   has been done. */
+int early_read_config_byte(struct pci_controller *hose, int bus, int dev_fn,
+                          int where, u8 *val);
+int early_read_config_word(struct pci_controller *hose, int bus, int dev_fn,
+                          int where, u16 *val);
+int early_read_config_dword(struct pci_controller *hose, int bus, int dev_fn,
+                           int where, u32 *val);
+int early_write_config_byte(struct pci_controller *hose, int bus, int dev_fn,
+                           int where, u8 val);
+int early_write_config_word(struct pci_controller *hose, int bus, int dev_fn,
+                           int where, u16 val);
+int early_write_config_dword(struct pci_controller *hose, int bus, int dev_fn,
+                            int where, u32 val);
+
+extern void setup_indirect_pci_nomap(struct pci_controller* hose,
+                              void __iomem *cfg_addr, void __iomem *cfg_data);
+extern void setup_indirect_pci(struct pci_controller* hose,
+                              u32 cfg_addr, u32 cfg_data);
+extern void setup_grackle(struct pci_controller *hose);
+
 #else
 
-#include <linux/pci.h>
-#include <linux/list.h>
 
 /*
  * This program is free software; you can redistribute it and/or
@@ -31,6 +110,7 @@ struct pci_controller {
        int last_busno;
 
        void __iomem *io_base_virt;
+       void *io_base_alloc;
        resource_size_t io_base_phys;
 
        /* Some machines have a non 1:1 mapping of
@@ -48,8 +128,7 @@ struct pci_controller {
         */
        struct resource io_resource;
        struct resource mem_resources[3];
-       int global_number;              
-       int local_number;               
+       int global_number;
        unsigned long buid;
        unsigned long dma_window_base_cur;
        unsigned long dma_window_size;
@@ -70,19 +149,22 @@ struct pci_dn {
        int     devfn;                  /* pci device and function number */
        int     class_code;             /* pci device class */
 
-#ifdef CONFIG_PPC_PSERIES
+       struct  pci_controller *phb;    /* for pci devices */
+       struct  iommu_table *iommu_table;       /* for phb's or bridges */
+       struct  pci_dev *pcidev;        /* back-pointer to the pci device */
+       struct  device_node *node;      /* back-pointer to the device_node */
+
+       int     pci_ext_config_space;   /* for pci devices */
+
+#ifdef CONFIG_EEH
        int     eeh_mode;               /* See eeh.h for possible EEH_MODEs */
        int     eeh_config_addr;
        int     eeh_pe_config_addr; /* new-style partition endpoint address */
        int     eeh_check_count;        /* # times driver ignored error */
        int     eeh_freeze_count;       /* # times this device froze up. */
-#endif
-       int     pci_ext_config_space;   /* for pci devices */
-       struct  pci_controller *phb;    /* for pci devices */
-       struct  iommu_table *iommu_table;       /* for phb's or bridges */
-       struct  pci_dev *pcidev;        /* back-pointer to the pci device */
-       struct  device_node *node;      /* back-pointer to the device_node */
+       int     eeh_false_positives;    /* # times this device reported #ff's */
        u32     config_space[16];       /* saved PCI config space */
+#endif
 };
 
 /* Get the pointer to a device_node's pci_dn */
@@ -128,9 +210,6 @@ static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
 /** Find the bus corresponding to the indicated device node */
 struct pci_bus * pcibios_find_pci_bus(struct device_node *dn);
 
-extern void pci_process_bridge_OF_ranges(struct pci_controller *hose,
-                                        struct device_node *dev, int primary);
-
 /** Remove all of the PCI devices under this bus */
 void pcibios_remove_pci_devices(struct pci_bus *bus);
 
@@ -148,13 +227,38 @@ static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
        return PCI_DN(busdn)->phb;
 }
 
+extern void pcibios_free_controller(struct pci_controller *phb);
+
+extern void isa_bridge_find_early(struct pci_controller *hose);
+
+extern int pcibios_unmap_io_space(struct pci_bus *bus);
+extern int pcibios_map_io_space(struct pci_bus *bus);
+
+/* Return values for ppc_md.pci_probe_mode function */
+#define PCI_PROBE_NONE         -1      /* Don't look at this bus at all */
+#define PCI_PROBE_NORMAL       0       /* Do normal PCI probing */
+#define PCI_PROBE_DEVTREE      1       /* Instantiate from device tree */
+
+#ifdef CONFIG_NUMA
+#define PHB_SET_NODE(PHB, NODE)                ((PHB)->node = (NODE))
+#else
+#define PHB_SET_NODE(PHB, NODE)                ((PHB)->node = -1)
+#endif
+
+#endif /* CONFIG_PPC64 */
+
+/* Get the PCI host controller for an OF device */
 extern struct pci_controller*
 pci_find_hose_for_OF_device(struct device_node* node);
 
+/* Fill up host controller resources from the OF node */
+extern void
+pci_process_bridge_OF_ranges(struct pci_controller *hose,
+                          struct device_node *dev, int primary);
+
+/* Allocate a new PCI host bridge structure */
 extern struct pci_controller *
 pcibios_alloc_controller(struct device_node *dev);
-extern void pcibios_free_controller(struct pci_controller *phb);
-
 #ifdef CONFIG_PCI
 extern unsigned long pci_address_to_pio(phys_addr_t address);
 #else
@@ -164,17 +268,7 @@ static inline unsigned long pci_address_to_pio(phys_addr_t address)
 }
 #endif
 
-/* Return values for ppc_md.pci_probe_mode function */
-#define PCI_PROBE_NONE         -1      /* Don't look at this bus at all */
-#define PCI_PROBE_NORMAL       0       /* Do normal PCI probing */
-#define PCI_PROBE_DEVTREE      1       /* Instantiate from device tree */
 
-#ifdef CONFIG_NUMA
-#define PHB_SET_NODE(PHB, NODE)                ((PHB)->node = (NODE))
-#else
-#define PHB_SET_NODE(PHB, NODE)                ((PHB)->node = -1)
-#endif
 
-#endif /* CONFIG_PPC64 */
 #endif /* __KERNEL__ */
 #endif
index e16e7bc9ab5cf2640364ea19586319edbc080025..7b11765c6865f31157dd30c6ee91ba5c1ecc9ad0 100644 (file)
@@ -95,8 +95,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 #define get_pci_dma_ops()      NULL
 #endif
 
-extern int pci_domain_nr(struct pci_bus *bus);
-
 /* Decide whether to display the domain number in /proc */
 extern int pci_proc_domain(struct pci_bus *bus);
 
@@ -112,9 +110,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 }
 #endif
 
-/* Return the index of the PCI controller for device PDEV. */
-#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
-
 /* Set the name of the bus as it appears in /proc/bus/pci */
 static inline int pci_proc_domain(struct pci_bus *bus)
 {
@@ -123,6 +118,8 @@ static inline int pci_proc_domain(struct pci_bus *bus)
 
 #endif /* CONFIG_PPC64 */
 
+extern int pci_domain_nr(struct pci_bus *bus);
+
 struct vm_area_struct;
 /* Map a range of PCI memory or I/O space for a device into user space */
 int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
@@ -202,10 +199,6 @@ static inline struct resource *pcibios_select_root(struct pci_dev *pdev,
        return root;
 }
 
-extern int unmap_bus_range(struct pci_bus *bus);
-
-extern int remap_bus_range(struct pci_bus *bus);
-
 extern void pcibios_fixup_device_resources(struct pci_dev *dev,
                        struct pci_bus *bus);
 
index 973c1c13bdc0aa171e4ed5b0baf08a2152c7c22c..6c236d4d626273b87276b7fd3f00055012e65311 100644 (file)
@@ -6,11 +6,7 @@
 #ifndef __ASSEMBLY__
 #include <linux/sched.h>
 #include <linux/threads.h>
-#include <asm/processor.h>             /* For TASK_SIZE */
-#include <asm/mmu.h>
-#include <asm/page.h>
 #include <asm/io.h>                    /* For sub-arch specific PPC_PIN_SIZE */
-struct mm_struct;
 
 extern unsigned long va_to_phys(unsigned long address);
 extern pte_t *va_to_pte(unsigned long address);
@@ -488,14 +484,6 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void);
 #define pfn_pte(pfn, prot)     __pte(((pte_basic_t)(pfn) << PFN_SHIFT_OFFSET) |\
                                        pgprot_val(prot))
 #define mk_pte(page, prot)     pfn_pte(page_to_pfn(page), prot)
-
-/*
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-extern unsigned long empty_zero_page[1024];
-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
-
 #endif /* __ASSEMBLY__ */
 
 #define pte_none(pte)          ((pte_val(pte) & ~_PTE_NONE_MASK) == 0)
@@ -724,10 +712,6 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
 #define pte_unmap(pte)         kunmap_atomic(pte, KM_PTE0)
 #define pte_unmap_nested(pte)  kunmap_atomic(pte, KM_PTE1)
 
-extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
-
-extern void paging_init(void);
-
 /*
  * Encode and decode a swap entry.
  * Note that the bits we use in a PTE for representing a swap entry
@@ -745,40 +729,6 @@ extern void paging_init(void);
 #define pte_to_pgoff(pte)      (pte_val(pte) >> 3)
 #define pgoff_to_pte(off)      ((pte_t) { ((off) << 3) | _PAGE_FILE })
 
-/* CONFIG_APUS */
-/* For virtual address to physical address conversion */
-extern void cache_clear(__u32 addr, int length);
-extern void cache_push(__u32 addr, int length);
-extern int mm_end_of_chunk (unsigned long addr, int len);
-extern unsigned long iopa(unsigned long addr);
-extern unsigned long mm_ptov(unsigned long addr) __attribute_const__;
-
-/* Values for nocacheflag and cmode */
-/* These are not used by the APUS kernel_map, but prevents
-   compilation errors. */
-#define        KERNELMAP_FULL_CACHING          0
-#define        KERNELMAP_NOCACHE_SER           1
-#define        KERNELMAP_NOCACHE_NONSER        2
-#define        KERNELMAP_NO_COPYBACK           3
-
-/*
- * Map some physical address range into the kernel address space.
- */
-extern unsigned long kernel_map(unsigned long paddr, unsigned long size,
-                               int nocacheflag, unsigned long *memavailp );
-
-/*
- * Set cache mode of (kernel space) address range.
- */
-extern void kernel_set_cachemode (unsigned long address, unsigned long size,
-                                 unsigned int cmode);
-
-/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
-#define kern_addr_valid(addr)  (1)
-
-#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
-               remap_pfn_range(vma, vaddr, pfn, size, prot)
-
 /*
  * No page table caches to initialise
  */
index 0c879121c8fcaf3ae0bfe3f790bb9faeddb3d2d6..7ca8b5c100191d0398f530a3134bc3b172682564 100644 (file)
@@ -7,11 +7,7 @@
 
 #ifndef __ASSEMBLY__
 #include <linux/stddef.h>
-#include <asm/processor.h>             /* For TASK_SIZE */
-#include <asm/mmu.h>
-#include <asm/page.h>
 #include <asm/tlbflush.h>
-struct mm_struct;
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_PPC_64K_PAGES
@@ -27,7 +23,7 @@ struct mm_struct;
  */
 #define PGTABLE_EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \
                            PUD_INDEX_SIZE + PGD_INDEX_SIZE + PAGE_SHIFT)
-#define PGTABLE_RANGE (1UL << PGTABLE_EADDR_SIZE)
+#define PGTABLE_RANGE (ASM_CONST(1) << PGTABLE_EADDR_SIZE)
 
 #if TASK_SIZE_USER64 > PGTABLE_RANGE
 #error TASK_SIZE_USER64 exceeds pagetable range
@@ -37,19 +33,28 @@ struct mm_struct;
 #error TASK_SIZE_USER64 exceeds user VSID range
 #endif
 
+
 /*
  * Define the address range of the vmalloc VM area.
  */
 #define VMALLOC_START ASM_CONST(0xD000000000000000)
-#define VMALLOC_SIZE  ASM_CONST(0x80000000000)
+#define VMALLOC_SIZE  (PGTABLE_RANGE >> 1)
 #define VMALLOC_END   (VMALLOC_START + VMALLOC_SIZE)
 
 /*
- * Define the address range of the imalloc VM area.
+ * Define the address ranges for MMIO and IO space :
+ *
+ *  ISA_IO_BASE = VMALLOC_END, 64K reserved area
+ *  PHB_IO_BASE = ISA_IO_BASE + 64K to ISA_IO_BASE + 2G, PHB IO spaces
+ * IOREMAP_BASE = ISA_IO_BASE + 2G to VMALLOC_START + PGTABLE_RANGE
  */
-#define PHBS_IO_BASE   VMALLOC_END
-#define IMALLOC_BASE   (PHBS_IO_BASE + 0x80000000ul)   /* Reserve 2 gigs for PHBs */
-#define IMALLOC_END    (VMALLOC_START + PGTABLE_RANGE)
+#define FULL_IO_SIZE   0x80000000ul
+#define  ISA_IO_BASE   (VMALLOC_END)
+#define  ISA_IO_END    (VMALLOC_END + 0x10000ul)
+#define  PHB_IO_BASE   (ISA_IO_END)
+#define  PHB_IO_END    (VMALLOC_END + FULL_IO_SIZE)
+#define IOREMAP_BASE   (PHB_IO_END)
+#define IOREMAP_END    (VMALLOC_START + PGTABLE_RANGE)
 
 /*
  * Region IDs
@@ -134,16 +139,6 @@ struct mm_struct;
 #define __S110 PAGE_SHARED_X
 #define __S111 PAGE_SHARED_X
 
-#ifndef __ASSEMBLY__
-
-/*
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
-#endif /* __ASSEMBLY__ */
-
 #ifdef CONFIG_HUGETLB_PAGE
 
 #define HAVE_ARCH_UNMAPPED_AREA
@@ -432,10 +427,6 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
 #define pgd_ERROR(e) \
        printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
 
-extern pgd_t swapper_pg_dir[];
-
-extern void paging_init(void);
-
 /* Encode and de-code a swap entry */
 #define __swp_type(entry)      (((entry).val >> 1) & 0x3f)
 #define __swp_offset(entry)    ((entry).val >> 8)
@@ -446,17 +437,6 @@ extern void paging_init(void);
 #define pgoff_to_pte(off)      ((pte_t) {((off) << PTE_RPN_SHIFT)|_PAGE_FILE})
 #define PTE_FILE_MAX_BITS      (BITS_PER_LONG - PTE_RPN_SHIFT)
 
-/*
- * kern_addr_valid is intended to indicate whether an address is a valid
- * kernel address.  Most 32-bit archs define it as always true (like this)
- * but most 64-bit archs actually perform a test.  What should we do here?
- * The only use is in fs/ncpfs/dir.c
- */
-#define kern_addr_valid(addr)  (1)
-
-#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
-               remap_pfn_range(vma, vaddr, pfn, size, prot)
-
 void pgtable_cache_init(void);
 
 /*
index 78bf4ae712a67ef4e6b00f8fca0859354ad1c102..d18ffe7bc7c4a498a038f0a96f64c81227ac067b 100644 (file)
@@ -2,6 +2,13 @@
 #define _ASM_POWERPC_PGTABLE_H
 #ifdef __KERNEL__
 
+#ifndef __ASSEMBLY__
+#include <asm/processor.h>             /* For TASK_SIZE */
+#include <asm/mmu.h>
+#include <asm/page.h>
+struct mm_struct;
+#endif /* !__ASSEMBLY__ */
+
 #if defined(CONFIG_PPC64)
 #  include <asm/pgtable-ppc64.h>
 #else
@@ -9,6 +16,27 @@
 #endif
 
 #ifndef __ASSEMBLY__
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern unsigned long empty_zero_page[];
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+extern pgd_t swapper_pg_dir[];
+
+extern void paging_init(void);
+
+/*
+ * kern_addr_valid is intended to indicate whether an address is a valid
+ * kernel address.  Most 32-bit archs define it as always true (like this)
+ * but most 64-bit archs actually perform a test.  What should we do here?
+ */
+#define kern_addr_valid(addr)  (1)
+
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
+               remap_pfn_range(vma, vaddr, pfn, size, prot)
+
 #include <asm-generic/pgtable.h>
 #endif /* __ASSEMBLY__ */
 
index 8e2005159ffd85e83aca379d785bc705e127f75e..b847aa10074be1d87878a40acbece6bb204644eb 100644 (file)
@@ -26,7 +26,7 @@ extern int global_phb_number;
 
 extern void find_and_init_phbs(void);
 
-extern struct pci_dev *ppc64_isabridge_dev;    /* may be NULL if no ISA bus */
+extern struct pci_dev *isa_bridge_pcidev;      /* may be NULL if no ISA bus */
 
 /** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */
 #define BUID_HI(buid) ((buid) >> 32)
@@ -47,8 +47,8 @@ extern void init_pci_config_tokens (void);
 extern unsigned long get_phb_buid (struct device_node *);
 extern int rtas_setup_phb(struct pci_controller *phb);
 
-/* From pSeries_pci.h */
-extern void pSeries_final_fixup(void);
+/* From iSeries PCI */
+extern void iSeries_pcibios_init(void);
 
 extern unsigned long pci_probe_only;
 
@@ -139,6 +139,9 @@ void eeh_clear_slot (struct device_node *dn, int mode_flag);
  */
 struct device_node * find_device_pe(struct device_node *dn);
 
+void eeh_sysfs_add_device(struct pci_dev *pdev);
+void eeh_sysfs_remove_device(struct pci_dev *pdev);
+
 #endif /* CONFIG_EEH */
 
 #else /* CONFIG_PCI */
index d947b160949115894a0bd38caa8d6467a4f2d291..e28b108051592d443c9f6da8982c2740be780424 100644 (file)
@@ -43,14 +43,6 @@ extern int _chrp_type;
 /* what kind of prep workstation we are */
 extern int _prep_type;
 
-/*
- * This is used to identify the board type from a given PReP board
- * vendor. Board revision is also made available. This will be moved
- * elsewhere soon
- */
-extern unsigned char ucBoardRev;
-extern unsigned char ucBoardRevMaj, ucBoardRevMin;
-
 #endif /* CONFIG_PPC_PREP */
 
 #endif /* defined(__KERNEL__) && defined(CONFIG_PPC32) */
index 6845af93ba91d89be5107f086b9e5034b21da553..1632baa17dc6964f0ae9bd7234b3bb350726bcec 100644 (file)
@@ -98,10 +98,19 @@ struct device_node {
 extern struct device_node *of_chosen;
 
 /* flag descriptions */
-#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */
+#define OF_DYNAMIC     1 /* node and properties were allocated via kmalloc */
+#define OF_DETACHED    2 /* node has been detached from the device tree */
+
+static inline int of_node_check_flag(struct device_node *n, unsigned long flag)
+{
+       return test_bit(flag, &n->_flags);
+}
+
+static inline void of_node_set_flag(struct device_node *n, unsigned long flag)
+{
+       set_bit(flag, &n->_flags);
+}
 
-#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
-#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
 
 #define HAVE_ARCH_DEVTREE_FIXUPS
 
@@ -124,6 +133,9 @@ extern struct device_node *of_find_node_by_type(struct device_node *from,
             dn = of_find_node_by_type(dn, type))
 extern struct device_node *of_find_compatible_node(struct device_node *from,
        const char *type, const char *compat);
+#define for_each_compatible_node(dn, type, compatible) \
+       for (dn = of_find_compatible_node(NULL, type, compatible); dn; \
+            dn = of_find_compatible_node(dn, type, compatible))
 extern struct device_node *of_find_node_by_path(const char *path);
 extern struct device_node *of_find_node_by_phandle(phandle handle);
 extern struct device_node *of_find_all_nodes(struct device_node *prev);
index 1e04651eedc4bbc7819b0e17549af58cd6181d49..a6f3f5ee7ca7f70a3ee592c0e173f91b40f3e53b 100644 (file)
@@ -35,7 +35,8 @@ union ps3_firmware_version {
        };
 };
 
-int ps3_get_firmware_version(union ps3_firmware_version *v);
+void ps3_get_firmware_version(union ps3_firmware_version *v);
+int ps3_compare_firmware_version(u16 major, u16 minor, u16 rev);
 
 /* 'Other OS' area */
 
@@ -48,18 +49,6 @@ enum ps3_param_av_multi_out {
 
 enum ps3_param_av_multi_out ps3_os_area_get_av_multi_out(void);
 
-/**
- * struct ps3_device_id - HV bus device identifier from the system repository
- * @bus_id: HV bus id, {1..} (zero invalid)
- * @dev_id: HV device id, {0..}
- */
-
-struct ps3_device_id {
-       unsigned int bus_id;
-       unsigned int dev_id;
-};
-
-
 /* dma routines */
 
 enum ps3_dma_page_size {
@@ -74,6 +63,8 @@ enum ps3_dma_region_type {
        PS3_DMA_INTERNAL = 2,
 };
 
+struct ps3_dma_region_ops;
+
 /**
  * struct ps3_dma_region - A per device dma state variables structure
  * @did: The HV device id.
@@ -81,21 +72,42 @@ enum ps3_dma_region_type {
  * @region_type: The HV region type.
  * @bus_addr: The 'translated' bus address of the region.
  * @len: The length in bytes of the region.
+ * @offset: The offset from the start of memory of the region.
+ * @ioid: The IOID of the device who owns this region
  * @chunk_list: Opaque variable used by the ioc page manager.
+ * @region_ops: struct ps3_dma_region_ops - dma region operations
  */
 
 struct ps3_dma_region {
-       struct ps3_device_id did;
+       struct ps3_system_bus_device *dev;
+       /* device variables */
+       const struct ps3_dma_region_ops *region_ops;
+       unsigned char ioid;
        enum ps3_dma_page_size page_size;
        enum ps3_dma_region_type region_type;
-       unsigned long bus_addr;
        unsigned long len;
+       unsigned long offset;
+
+       /* driver variables  (set by ps3_dma_region_create) */
+       unsigned long bus_addr;
        struct {
                spinlock_t lock;
                struct list_head head;
        } chunk_list;
 };
 
+struct ps3_dma_region_ops {
+       int (*create)(struct ps3_dma_region *);
+       int (*free)(struct ps3_dma_region *);
+       int (*map)(struct ps3_dma_region *,
+                  unsigned long virt_addr,
+                  unsigned long len,
+                  unsigned long *bus_addr,
+                  u64 iopte_pp);
+       int (*unmap)(struct ps3_dma_region *,
+                    unsigned long bus_addr,
+                    unsigned long len);
+};
 /**
  * struct ps3_dma_region_init - Helper to initialize structure variables
  *
@@ -103,18 +115,16 @@ struct ps3_dma_region {
  * ps3_system_bus_device_register.
  */
 
-static inline void ps3_dma_region_init(struct ps3_dma_region *r,
-       const struct ps3_device_id* did, enum ps3_dma_page_size page_size,
-       enum ps3_dma_region_type region_type)
-{
-       r->did = *did;
-       r->page_size = page_size;
-       r->region_type = region_type;
-}
+struct ps3_system_bus_device;
+
+int ps3_dma_region_init(struct ps3_system_bus_device *dev,
+       struct ps3_dma_region *r, enum ps3_dma_page_size page_size,
+       enum ps3_dma_region_type region_type, void *addr, unsigned long len);
 int ps3_dma_region_create(struct ps3_dma_region *r);
 int ps3_dma_region_free(struct ps3_dma_region *r);
 int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr,
-       unsigned long len, unsigned long *bus_addr);
+       unsigned long len, unsigned long *bus_addr,
+       u64 iopte_pp);
 int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr,
        unsigned long len);
 
@@ -125,6 +135,7 @@ enum ps3_mmio_page_size {
        PS3_MMIO_64K = 16U
 };
 
+struct ps3_mmio_region_ops;
 /**
  * struct ps3_mmio_region - a per device mmio state variables structure
  *
@@ -132,13 +143,18 @@ enum ps3_mmio_page_size {
  */
 
 struct ps3_mmio_region {
-       struct ps3_device_id did;
+       struct ps3_system_bus_device *dev;
+       const struct ps3_mmio_region_ops *mmio_ops;
        unsigned long bus_addr;
        unsigned long len;
        enum ps3_mmio_page_size page_size;
        unsigned long lpar_addr;
 };
 
+struct ps3_mmio_region_ops {
+       int (*create)(struct ps3_mmio_region *);
+       int (*free)(struct ps3_mmio_region *);
+};
 /**
  * struct ps3_mmio_region_init - Helper to initialize structure variables
  *
@@ -146,15 +162,9 @@ struct ps3_mmio_region {
  * ps3_system_bus_device_register.
  */
 
-static inline void ps3_mmio_region_init(struct ps3_mmio_region *r,
-       const struct ps3_device_id* did, unsigned long bus_addr,
-       unsigned long len, enum ps3_mmio_page_size page_size)
-{
-       r->did = *did;
-       r->bus_addr = bus_addr;
-       r->len = len;
-       r->page_size = page_size;
-}
+int ps3_mmio_region_init(struct ps3_system_bus_device *dev,
+       struct ps3_mmio_region *r, unsigned long bus_addr, unsigned long len,
+       enum ps3_mmio_page_size page_size);
 int ps3_mmio_region_create(struct ps3_mmio_region *r);
 int ps3_free_mmio_region(struct ps3_mmio_region *r);
 unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr);
@@ -187,11 +197,10 @@ int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id,
        unsigned int class, unsigned int *virq);
 int ps3_spe_irq_destroy(unsigned int virq);
 
-int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu,
-       const struct ps3_device_id *did, unsigned int interrupt_id,
-       unsigned int *virq);
-int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did,
-       unsigned int interrupt_id, unsigned int virq);
+int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev,
+       enum ps3_cpu_binding cpu, unsigned int *virq);
+int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev,
+       unsigned int virq);
 
 /* lv1 result codes */
 
@@ -289,11 +298,33 @@ static inline const char* ps3_result(int result)
 /* system bus routines */
 
 enum ps3_match_id {
-       PS3_MATCH_ID_EHCI = 1,
-       PS3_MATCH_ID_OHCI,
-       PS3_MATCH_ID_GELIC,
-       PS3_MATCH_ID_AV_SETTINGS,
-       PS3_MATCH_ID_SYSTEM_MANAGER,
+       PS3_MATCH_ID_EHCI           = 1,
+       PS3_MATCH_ID_OHCI           = 2,
+       PS3_MATCH_ID_GELIC          = 3,
+       PS3_MATCH_ID_AV_SETTINGS    = 4,
+       PS3_MATCH_ID_SYSTEM_MANAGER = 5,
+       PS3_MATCH_ID_STOR_DISK      = 6,
+       PS3_MATCH_ID_STOR_ROM       = 7,
+       PS3_MATCH_ID_STOR_FLASH     = 8,
+       PS3_MATCH_ID_SOUND          = 9,
+       PS3_MATCH_ID_GRAPHICS       = 10,
+};
+
+#define PS3_MODULE_ALIAS_EHCI           "ps3:1"
+#define PS3_MODULE_ALIAS_OHCI           "ps3:2"
+#define PS3_MODULE_ALIAS_GELIC          "ps3:3"
+#define PS3_MODULE_ALIAS_AV_SETTINGS    "ps3:4"
+#define PS3_MODULE_ALIAS_SYSTEM_MANAGER "ps3:5"
+#define PS3_MODULE_ALIAS_STOR_DISK      "ps3:6"
+#define PS3_MODULE_ALIAS_STOR_ROM       "ps3:7"
+#define PS3_MODULE_ALIAS_STOR_FLASH     "ps3:8"
+#define PS3_MODULE_ALIAS_SOUND          "ps3:9"
+#define PS3_MODULE_ALIAS_GRAPHICS       "ps3:10"
+
+enum ps3_system_bus_device_type {
+       PS3_DEVICE_TYPE_IOC0 = 1,
+       PS3_DEVICE_TYPE_SB,
+       PS3_DEVICE_TYPE_VUART,
 };
 
 /**
@@ -302,14 +333,23 @@ enum ps3_match_id {
 
 struct ps3_system_bus_device {
        enum ps3_match_id match_id;
-       struct ps3_device_id did;
-       unsigned int interrupt_id;
-/*     struct iommu_table *iommu_table; -- waiting for Ben's cleanups */
-       struct ps3_dma_region *d_region;
-       struct ps3_mmio_region *m_region;
+       enum ps3_system_bus_device_type dev_type;
+
+       unsigned int bus_id;              /* SB */
+       unsigned int dev_id;              /* SB */
+       unsigned int interrupt_id;        /* SB */
+       struct ps3_dma_region *d_region;  /* SB, IOC0 */
+       struct ps3_mmio_region *m_region; /* SB, IOC0*/
+       unsigned int port_number;         /* VUART */
+
+/*     struct iommu_table *iommu_table; -- waiting for BenH's cleanups */
        struct device core;
+       void *driver_priv; /* private driver variables */
 };
 
+int ps3_open_hv_device(struct ps3_system_bus_device *dev);
+int ps3_close_hv_device(struct ps3_system_bus_device *dev);
+
 /**
  * struct ps3_system_bus_driver - a driver for a device on the system bus
  */
@@ -319,6 +359,7 @@ struct ps3_system_bus_driver {
        struct device_driver core;
        int (*probe)(struct ps3_system_bus_device *);
        int (*remove)(struct ps3_system_bus_device *);
+       int (*shutdown)(struct ps3_system_bus_device *);
 /*     int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */
 /*     int (*resume)(struct ps3_system_bus_device *); */
 };
@@ -326,16 +367,24 @@ struct ps3_system_bus_driver {
 int ps3_system_bus_device_register(struct ps3_system_bus_device *dev);
 int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv);
 void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv);
-static inline struct ps3_system_bus_driver *to_ps3_system_bus_driver(
+
+static inline struct ps3_system_bus_driver *ps3_drv_to_system_bus_drv(
        struct device_driver *_drv)
 {
        return container_of(_drv, struct ps3_system_bus_driver, core);
 }
-static inline struct ps3_system_bus_device *to_ps3_system_bus_device(
+static inline struct ps3_system_bus_device *ps3_dev_to_system_bus_dev(
        struct device *_dev)
 {
        return container_of(_dev, struct ps3_system_bus_device, core);
 }
+static inline struct ps3_system_bus_driver *
+       ps3_system_bus_dev_to_system_bus_drv(struct ps3_system_bus_device *_dev)
+{
+       BUG_ON(!_dev);
+       BUG_ON(!_dev->core.driver);
+       return ps3_drv_to_system_bus_drv(_dev->core.driver);
+}
 
 /**
  * ps3_system_bus_set_drvdata -
@@ -358,32 +407,17 @@ static inline void *ps3_system_bus_get_driver_data(
 
 extern struct bus_type ps3_system_bus_type;
 
-/* vuart routines */
-
-struct ps3_vuart_port_priv;
-
-/**
- * struct ps3_vuart_port_device - a device on a vuart port
- */
-
-struct ps3_vuart_port_device {
-       enum ps3_match_id match_id;
-       struct device core;
-       struct ps3_vuart_port_priv* priv; /* private driver variables */
+/* system manager */
 
+struct ps3_sys_manager_ops {
+       struct ps3_system_bus_device *dev;
+       void (*power_off)(struct ps3_system_bus_device *dev);
+       void (*restart)(struct ps3_system_bus_device *dev);
 };
 
-int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev);
-
-/* system manager */
-
-#ifdef CONFIG_PS3_SYS_MANAGER
-void ps3_sys_manager_restart(void);
+void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops);
 void ps3_sys_manager_power_off(void);
-#else
-static inline void ps3_sys_manager_restart(void) {}
-static inline void ps3_sys_manager_power_off(void) {}
-#endif
+void ps3_sys_manager_restart(void);
 
 struct ps3_prealloc {
     const char *name;
@@ -393,5 +427,7 @@ struct ps3_prealloc {
 };
 
 extern struct ps3_prealloc ps3fb_videomemory;
+extern struct ps3_prealloc ps3flash_bounce_buffer;
+
 
 #endif
index 9efc40f1c7788311d9b40847588b6381c6baa51b..7df4250802dee3390cce8e0d871429d305ba3f35 100644 (file)
@@ -1,20 +1,23 @@
 /*
- * Copyright (C) 2006 Sony Computer Entertainment Inc.
- * Copyright 2006, 2007 Sony Corporation
+ *  PS3 AV backend support.
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; version 2 of the License.
+ *  Copyright (C) 2007 Sony Computer Entertainment Inc.
+ *  Copyright 2007 Sony Corp.
  *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
  *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+
 #ifndef _ASM_POWERPC_PS3AV_H_
 #define _ASM_POWERPC_PS3AV_H_
 
 #define PS3AV_CMD_VIDEO_FMT_X8R8G8B8                   0x0000
 /* video_out_format */
 #define PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT           0x0000
+/* video_cl_cnv */
+#define PS3AV_CMD_VIDEO_CL_CNV_ENABLE_LUT              0x0000
+#define PS3AV_CMD_VIDEO_CL_CNV_DISABLE_LUT             0x0010
 /* video_sync */
 #define PS3AV_CMD_VIDEO_SYNC_VSYNC                     0x0001
 #define PS3AV_CMD_VIDEO_SYNC_CSYNC                     0x0004
 #define PS3AV_MODE_MASK                                0x000F
 #define PS3AV_MODE_HDCP_OFF                    0x1000  /* Retail PS3 product doesn't support this */
 #define PS3AV_MODE_DITHER                      0x0800
+#define PS3AV_MODE_COLOR                       0x0400
+#define PS3AV_MODE_WHITE                       0x0200
 #define PS3AV_MODE_FULL                                0x0080
 #define PS3AV_MODE_DVI                         0x0040
 #define PS3AV_MODE_RGB                         0x0020
@@ -529,9 +537,9 @@ struct ps3av_pkt_video_mode {
        u32 video_out_format;   /* in: out format */
        u32 video_format;       /* in: input frame buffer format */
        u8 reserved3;
-       u8 reserved4;
+       u8 video_cl_cnv;        /* in: color conversion */
        u16 video_order;        /* in: input RGB order */
-       u32 reserved5;
+       u32 reserved4;
 };
 
 /* video: format */
@@ -539,7 +547,8 @@ struct ps3av_pkt_video_format {
        struct ps3av_send_hdr send_hdr;
        u32 video_head;         /* in: head */
        u32 video_format;       /* in: frame buffer format */
-       u16 reserved;
+       u8 reserved;
+       u8 video_cl_cnv;        /* in: color conversion */
        u16 video_order;        /* in: input RGB order */
 };
 
@@ -698,12 +707,6 @@ static inline void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_
 extern int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *,
                                            u32);
 
-struct ps3_vuart_port_device;
-extern int ps3av_vuart_write(struct ps3_vuart_port_device *dev,
-                            const void *buf, unsigned long size);
-extern int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
-                           unsigned long size, int timeout);
-
 extern int ps3av_set_video_mode(u32, int);
 extern int ps3av_set_audio_mode(u32, u32, u32, u32, u32);
 extern int ps3av_get_auto_mode(int);
@@ -716,5 +719,8 @@ extern int ps3av_video_mute(int);
 extern int ps3av_audio_mute(int);
 extern int ps3av_dev_open(void);
 extern int ps3av_dev_close(void);
+extern void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data),
+                                   void *flip_data);
+extern void ps3av_flip_ctl(int on);
 
 #endif /* _ASM_POWERPC_PS3AV_H_ */
index ad81cf4319645ae0a20f5602f8bc970e0a2f6ddd..3f121fe4010d02144b30a9eefe6840e4f0cbbc78 100644 (file)
@@ -41,16 +41,4 @@ struct ps3fb_ioctl_res {
        __u32 num_frames; /* num of frame buffers */
 };
 
-#ifdef __KERNEL__
-
-#ifdef CONFIG_FB_PS3
-extern void ps3fb_flip_ctl(int on);
-extern void ps3fb_cleanup(void);
-#else
-static inline void ps3fb_flip_ctl(int on) {}
-static inline void ps3fb_cleanup(void) {}
-#endif
-
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_POWERPC_PS3FB_H_ */
diff --git a/include/asm-powerpc/ps3stor.h b/include/asm-powerpc/ps3stor.h
new file mode 100644 (file)
index 0000000..6fcaf71
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * PS3 Storage Devices
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2007 Sony Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _ASM_POWERPC_PS3STOR_H_
+#define _ASM_POWERPC_PS3STOR_H_
+
+#include <linux/interrupt.h>
+
+#include <asm/ps3.h>
+
+
+struct ps3_storage_region {
+       unsigned int id;
+       u64 start;
+       u64 size;
+};
+
+struct ps3_storage_device {
+       struct ps3_system_bus_device sbd;
+
+       struct ps3_dma_region dma_region;
+       unsigned int irq;
+       u64 blk_size;
+
+       u64 tag;
+       u64 lv1_status;
+       struct completion done;
+
+       unsigned long bounce_size;
+       void *bounce_buf;
+       u64 bounce_lpar;
+       dma_addr_t bounce_dma;
+
+       unsigned int num_regions;
+       unsigned long accessible_regions;
+       unsigned int region_idx;                /* first accessible region */
+       struct ps3_storage_region regions[0];   /* Must be last */
+};
+
+static inline struct ps3_storage_device *to_ps3_storage_device(struct device *dev)
+{
+       return container_of(dev, struct ps3_storage_device, sbd.core);
+}
+
+extern int ps3stor_setup(struct ps3_storage_device *dev,
+                        irq_handler_t handler);
+extern void ps3stor_teardown(struct ps3_storage_device *dev);
+extern u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar,
+                                     u64 start_sector, u64 sectors,
+                                     int write);
+extern u64 ps3stor_send_command(struct ps3_storage_device *dev, u64 cmd,
+                               u64 arg1, u64 arg2, u64 arg3, u64 arg4);
+
+#endif /* _ASM_POWERPC_PS3STOR_H_ */
index 4ad77a13f8652ebdf69aa2225ceea03346916212..13fccc5a41197e96f1e1f8e4163df90583d2b0b9 100644 (file)
@@ -92,6 +92,11 @@ extern unsigned long profile_pc(struct pt_regs *regs);
                set_thread_flag(TIF_NOERROR); \
        } while(0)
 
+struct task_struct;
+extern unsigned long ptrace_get_reg(struct task_struct *task, int regno);
+extern int ptrace_put_reg(struct task_struct *task, int regno,
+                         unsigned long data);
+
 /*
  * We use the least-significant bit of the trap field to indicate
  * whether we have saved the full set of registers, or only a
@@ -158,9 +163,7 @@ do {                                                                              \
 
 #define PT_NIP 32
 #define PT_MSR 33
-#ifdef __KERNEL__
 #define PT_ORIG_R3 34
-#endif
 #define PT_CTR 35
 #define PT_LNK 36
 #define PT_XER 37
@@ -169,11 +172,12 @@ do {                                                                            \
 #define PT_MQ  39
 #else
 #define PT_SOFTE 39
+#endif
 #define PT_TRAP        40
 #define PT_DAR 41
 #define PT_DSISR 42
 #define PT_RESULT 43
-#endif
+#define PT_REGS_COUNT 44
 
 #define PT_FPR0        48      /* each FP reg occupies 2 slots in this space */
 
@@ -229,7 +233,17 @@ do {                                                                             \
 #define PTRACE_GET_DEBUGREG    25
 #define PTRACE_SET_DEBUGREG    26
 
-/* Additional PTRACE requests implemented on PowerPC. */
+/* (new) PTRACE requests using the same numbers as x86 and the same
+ * argument ordering. Additionally, they support more registers too
+ */
+#define PTRACE_GETREGS            12
+#define PTRACE_SETREGS            13
+#define PTRACE_GETFPREGS          14
+#define PTRACE_SETFPREGS          15
+#define PTRACE_GETREGS64         22
+#define PTRACE_SETREGS64         23
+
+/* (old) PTRACE requests with inverted arguments */
 #define PPC_PTRACE_GETREGS     0x99    /* Get GPRs 0 - 31 */
 #define PPC_PTRACE_SETREGS     0x98    /* Set GPRs 0 - 31 */
 #define PPC_PTRACE_GETFPREGS   0x97    /* Get FPRs 0 - 31 */
index 749c7f953b58f126eff6df7708fc2ebad3084028..281011e953ec1ea7e2be43b09101c4cdc2d186fa 100644 (file)
 #define SPRN_MMCRA     0x312
 #define   MMCRA_SIHV   0x10000000UL /* state of MSR HV when SIAR set */
 #define   MMCRA_SIPR   0x08000000UL /* state of MSR PR when SIAR set */
+#define   MMCRA_SLOT   0x07000000UL /* SLOT bits (37-39) */
+#define   MMCRA_SLOT_SHIFT     24
 #define   MMCRA_SAMPLE_ENABLE 0x00000001UL /* enable sampling */
 #define   POWER6_MMCRA_SIHV   0x0000040000000000ULL
 #define   POWER6_MMCRA_SIPR   0x0000020000000000ULL
index 31d5054be20f2587327fc69b3fd6547e6ec0ff84..eedc828cef2dc31a9fcbec613a99590017e1da9c 100644 (file)
@@ -106,6 +106,14 @@ struct spu_context;
 struct spu_runqueue;
 struct device_node;
 
+enum spu_utilization_state {
+       SPU_UTIL_SYSTEM,
+       SPU_UTIL_USER,
+       SPU_UTIL_IOWAIT,
+       SPU_UTIL_IDLE,
+       SPU_UTIL_MAX
+};
+
 struct spu {
        const char *name;
        unsigned long local_store_phys;
@@ -156,6 +164,21 @@ struct spu {
        u64 shadow_int_mask_RW[3];
 
        struct sys_device sysdev;
+
+       struct {
+               /* protected by interrupt reentrancy */
+               enum spu_utilization_state utilization_state;
+               unsigned long tstamp;           /* time of last ctx switch */
+               unsigned long times[SPU_UTIL_MAX];
+               unsigned long long vol_ctx_switch;
+               unsigned long long invol_ctx_switch;
+               unsigned long long min_flt;
+               unsigned long long maj_flt;
+               unsigned long long hash_flt;
+               unsigned long long slb_flt;
+               unsigned long long class2_intr;
+               unsigned long long libassist;
+       } stats;
 };
 
 struct spu *spu_alloc(void);
@@ -448,6 +471,7 @@ struct spu_priv1 {
 #define MFC_STATE1_PROBLEM_STATE_MASK          0x08ull
 #define MFC_STATE1_RELOCATE_MASK               0x10ull
 #define MFC_STATE1_MASTER_RUN_CONTROL_MASK     0x20ull
+#define MFC_STATE1_TABLE_SEARCH_MASK           0x40ull
        u64 mfc_lpid_RW;                                        /* 0x008 */
        u64 spu_idr_RW;                                         /* 0x010 */
        u64 mfc_vr_RO;                                          /* 0x018 */
index c2fe79d4f90fc4be47b2812cbd0a3ba9fe91ac7f..b3ca41fc8bb149c78667f132a855f2a1a28ad029 100644 (file)
@@ -43,16 +43,9 @@ asmlinkage long ppc_newuname(struct new_utsname __user * name);
 
 asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset,
                size_t sigsetsize);
-
-#ifndef __powerpc64__
-asmlinkage long sys_sigaltstack(const stack_t __user *uss,
-               stack_t __user *uoss, int r5, int r6, int r7, int r8,
-               struct pt_regs *regs);
-#else /* __powerpc64__ */
 asmlinkage long sys_sigaltstack(const stack_t __user *uss,
                stack_t __user *uoss, unsigned long r5, unsigned long r6,
                unsigned long r7, unsigned long r8, struct pt_regs *regs);
-#endif /* __powerpc64__ */
 
 #endif /* __KERNEL__ */
 #endif /* __ASM_POWERPC_SYSCALLS_H */
index 09621f611dbc8d018d722edc39f45f5945e8844e..32aa42b748bedbe90200d27ae1003f467c3ef5db 100644 (file)
@@ -43,7 +43,7 @@
 #ifdef CONFIG_SMP
 #define smp_mb()       mb()
 #define smp_rmb()      rmb()
-#define smp_wmb()      __asm__ __volatile__ ("eieio" : : : "memory")
+#define smp_wmb()      eieio()
 #define smp_read_barrier_depends()     read_barrier_depends()
 #else
 #define smp_mb()       barrier()
@@ -559,5 +559,7 @@ static inline void create_function_call(unsigned long addr, void * func)
 extern void account_system_vtime(struct task_struct *);
 #endif
 
+extern struct dentry *powerpc_debugfs_root;
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_SYSTEM_H */
index 5e79198f7d18d2ad6223bc0f6aeea191ee6190ea..6698188ca550aabc84ecadb7b0e7019be336734d 100644 (file)
@@ -152,6 +152,10 @@ struct ktermios {
 #define B3000000  00034
 #define B3500000  00035
 #define B4000000  00036
+#define   BOTHER  00037
+
+#define CIBAUD 077600000
+#define IBSHIFT        16              /* Shift from CBAUD to CIBAUD */
 
 #define CSIZE  00001400
 #define   CS5  00000000
index 3f32ca8bfec9ddfc31056df20962d0b9f2e05211..9d9aeca8ad225f631f6f5e5343801a0ce043158c 100644 (file)
@@ -113,8 +113,8 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_POLLING_NRFLAG     4       /* true if poll_idle() is polling
                                           TIF_NEED_RESCHED */
 #define TIF_32BIT              5       /* 32 bit binary */
-#define TIF_RUNLATCH           6       /* Is the runlatch enabled? */
-#define TIF_ABI_PENDING                7       /* 32/64 bit switch needed */
+#define TIF_PERFMON_WORK       6       /* work for pfm_handle_work() */
+#define TIF_PERFMON_CTXSW      7       /* perfmon needs ctxsw calls */
 #define TIF_SYSCALL_AUDIT      8       /* syscall auditing active */
 #define TIF_SINGLESTEP         9       /* singlestepping active */
 #define TIF_MEMDIE             10
@@ -123,6 +123,8 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_NOERROR            14      /* Force successful syscall return */
 #define TIF_RESTORE_SIGMASK    15      /* Restore signal mask in do_signal */
 #define TIF_FREEZE             16      /* Freezing for suspend */
+#define TIF_RUNLATCH           17      /* Is the runlatch enabled? */
+#define TIF_ABI_PENDING                18      /* 32/64 bit switch needed */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
@@ -131,8 +133,8 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 #define _TIF_32BIT             (1<<TIF_32BIT)
-#define _TIF_RUNLATCH          (1<<TIF_RUNLATCH)
-#define _TIF_ABI_PENDING       (1<<TIF_ABI_PENDING)
+#define _TIF_PERFMON_WORK      (1<<TIF_PERFMON_WORK)
+#define _TIF_PERFMON_CTXSW     (1<<TIF_PERFMON_CTXSW)
 #define _TIF_SYSCALL_AUDIT     (1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SINGLESTEP                (1<<TIF_SINGLESTEP)
 #define _TIF_SECCOMP           (1<<TIF_SECCOMP)
@@ -140,6 +142,8 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_NOERROR           (1<<TIF_NOERROR)
 #define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
 #define _TIF_FREEZE            (1<<TIF_FREEZE)
+#define _TIF_RUNLATCH          (1<<TIF_RUNLATCH)
+#define _TIF_ABI_PENDING       (1<<TIF_ABI_PENDING)
 #define _TIF_SYSCALL_T_OR_A    (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
 
 #define _TIF_USER_WORK_MASK    (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
index 3fd57c048f5908cec68aa96e20c1dc7b9a7b2dab..d7f5ddfbaac77f5f69c32643a6ef1691bb6e7820 100644 (file)
@@ -232,7 +232,7 @@ extern void account_process_vtime(struct task_struct *tsk);
 #define account_process_vtime(tsk)             do { } while (0)
 #endif
 
-#if defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(CONFIG_PPC_SPLPAR)
+#if defined(CONFIG_VIRT_CPU_ACCOUNTING)
 extern void calculate_steal_time(void);
 extern void snapshot_timebases(void);
 #else
@@ -240,5 +240,7 @@ extern void snapshot_timebases(void);
 #define snapshot_timebases()                   do { } while (0)
 #endif
 
+extern void iSeries_time_init_early(void);
+
 #endif /* __KERNEL__ */
 #endif /* __POWERPC_TIME_H */
index 86e6266a028bb9a69ad1217b4c5005ffa264156c..99a0439baa501b6def238c670428e2b5a06d1610 100644 (file)
@@ -155,6 +155,11 @@ static inline void flush_tlb_kernel_range(unsigned long start,
 {
 }
 
+/* Private function for use by PCI IO mapping code */
+extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
+                                    unsigned long end);
+
+
 #endif
 
 /*
index 73710d617775e6f953f9513fb4a99dcdab29abba..12e631f0fb77262c09e019c5dad0166e33cd46c7 100644 (file)
@@ -120,5 +120,10 @@ struct fsl_spi_platform_data {
        u32     sysclk;
 };
 
+struct mpc8xx_pcmcia_ops {
+       void(*hw_ctrl)(int slot, int enable);
+       int(*voltage_set)(int slot, int vcc, int vpp);
+};
+
 #endif /* _FSL_DEVICE_H_ */
 #endif /* __KERNEL__ */
index 4b7ee83787c1fb18e24720743262910d0b464b58..132b260aef1e5afeee3529eed8d282a9342e6bbe 100644 (file)
@@ -65,9 +65,10 @@ extern struct vm_struct *get_vm_area_node(unsigned long size,
                                          unsigned long flags, int node,
                                          gfp_t gfp_mask);
 extern struct vm_struct *remove_vm_area(void *addr);
+
 extern int map_vm_area(struct vm_struct *area, pgprot_t prot,
                        struct page ***pages);
-extern void unmap_vm_area(struct vm_struct *area);
+extern void unmap_kernel_range(unsigned long addr, unsigned long size);
 
 /*
  *     Internals.  Dont't use..
index d3a9c5368257afd6243c81c26881b25f67ff65f4..ddf87145cc49e0dc3d4e6e74f157b6a5e2e08f5c 100644 (file)
@@ -68,12 +68,12 @@ static inline void vunmap_pud_range(pgd_t *pgd, unsigned long addr,
        } while (pud++, addr = next, addr != end);
 }
 
-void unmap_vm_area(struct vm_struct *area)
+void unmap_kernel_range(unsigned long addr, unsigned long size)
 {
        pgd_t *pgd;
        unsigned long next;
-       unsigned long addr = (unsigned long) area->addr;
-       unsigned long end = addr + area->size;
+       unsigned long start = addr;
+       unsigned long end = addr + size;
 
        BUG_ON(addr >= end);
        pgd = pgd_offset_k(addr);
@@ -84,7 +84,12 @@ void unmap_vm_area(struct vm_struct *area)
                        continue;
                vunmap_pud_range(pgd, addr, next);
        } while (pgd++, addr = next, addr != end);
-       flush_tlb_kernel_range((unsigned long) area->addr, end);
+       flush_tlb_kernel_range(start, end);
+}
+
+static void unmap_vm_area(struct vm_struct *area)
+{
+       unmap_kernel_range((unsigned long)area->addr, area->size);
 }
 
 static int vmap_pte_range(pmd_t *pmd, unsigned long addr,