Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 7 Nov 2011 01:12:03 +0000 (17:12 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 7 Nov 2011 01:12:03 +0000 (17:12 -0800)
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (106 commits)
  powerpc/p3060qds: Add support for P3060QDS board
  powerpc/83xx: Add shutdown request support to MCU handling on MPC8349 MITX
  powerpc/85xx: Make kexec to interate over online cpus
  powerpc/fsl_booke: Fix comment in head_fsl_booke.S
  powerpc/85xx: issue 15 EOI after core reset for FSL CoreNet devices
  powerpc/8xxx: Fix interrupt handling in MPC8xxx GPIO driver
  powerpc/85xx: Add 'fsl,pq3-gpio' compatiable for GPIO driver
  powerpc/86xx: Correct Gianfar support for GE boards
  powerpc/cpm: Clear muram before it is in use.
  drivers/virt: add ioctl for 32-bit compat on 64-bit to fsl-hv-manager
  powerpc/fsl_msi: add support for "msi-address-64" property
  powerpc/85xx: Setup secondary cores PIR with hard SMP id
  powerpc/fsl-booke: Fix settlbcam for 64-bit
  powerpc/85xx: Adding DCSR node to dtsi device trees
  powerpc/85xx: clean up FPGA device tree nodes for Freecsale QorIQ boards
  powerpc/85xx: fix PHYS_64BIT selection for P1022DS
  powerpc/fsl-booke: Fix setup_initial_memory_limit to not blindly map
  powerpc: respect mem= setting for early memory limit setup
  powerpc: Update corenet64_smp_defconfig
  powerpc: Update mpc85xx/corenet 32-bit defconfigs
  ...

Fix up trivial conflicts in:
 - arch/powerpc/configs/40x/hcu4_defconfig
removed stale file, edited elsewhere
 - arch/powerpc/include/asm/udbg.h, arch/powerpc/kernel/udbg.c:
added opal and gelic drivers vs added ePAPR driver
 - drivers/tty/serial/8250.c
moved UPIO_TSI to powerpc vs removed UPIO_DWAPB support

189 files changed:
Documentation/devicetree/bindings/powerpc/fsl/board.txt
Documentation/devicetree/bindings/powerpc/fsl/dcsr.txt [new file with mode: 0644]
Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt
arch/powerpc/Kconfig
arch/powerpc/Kconfig.debug
arch/powerpc/boot/Makefile
arch/powerpc/boot/dts/digsy_mtc.dts
arch/powerpc/boot/dts/gef_ppc9a.dts
arch/powerpc/boot/dts/gef_sbc310.dts
arch/powerpc/boot/dts/gef_sbc610.dts
arch/powerpc/boot/dts/hcu4.dts [deleted file]
arch/powerpc/boot/dts/ksi8560.dts
arch/powerpc/boot/dts/mgcoge.dts
arch/powerpc/boot/dts/mpc5200b.dtsi
arch/powerpc/boot/dts/mpc8349emitx.dts
arch/powerpc/boot/dts/p1022ds.dts
arch/powerpc/boot/dts/p2020ds.dts
arch/powerpc/boot/dts/p2041rdb.dts [moved from arch/powerpc/boot/dts/p2040rdb.dts with 95% similarity]
arch/powerpc/boot/dts/p2041si.dtsi [moved from arch/powerpc/boot/dts/p2040si.dtsi with 80% similarity]
arch/powerpc/boot/dts/p3041ds.dts
arch/powerpc/boot/dts/p3041si.dtsi
arch/powerpc/boot/dts/p3060qds.dts [new file with mode: 0644]
arch/powerpc/boot/dts/p3060si.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/p4080ds.dts
arch/powerpc/boot/dts/p4080si.dtsi
arch/powerpc/boot/dts/p5020ds.dts
arch/powerpc/boot/dts/p5020si.dtsi
arch/powerpc/boot/dts/sbc8560.dts
arch/powerpc/boot/dts/yosemite.dts
arch/powerpc/configs/40x/hcu4_defconfig [deleted file]
arch/powerpc/configs/85xx/p1023rds_defconfig
arch/powerpc/configs/85xx/xes_mpc85xx_defconfig
arch/powerpc/configs/corenet32_smp_defconfig
arch/powerpc/configs/corenet64_smp_defconfig
arch/powerpc/configs/mgcoge_defconfig
arch/powerpc/configs/mpc512x_defconfig
arch/powerpc/configs/mpc5200_defconfig
arch/powerpc/configs/mpc85xx_defconfig
arch/powerpc/configs/mpc85xx_smp_defconfig
arch/powerpc/configs/ppc40x_defconfig
arch/powerpc/configs/ppc6xx_defconfig
arch/powerpc/include/asm/device.h
arch/powerpc/include/asm/firmware.h
arch/powerpc/include/asm/hugetlb.h
arch/powerpc/include/asm/kexec.h
arch/powerpc/include/asm/machdep.h
arch/powerpc/include/asm/mmu-book3e.h
arch/powerpc/include/asm/mmu-hash64.h
arch/powerpc/include/asm/mmu.h
arch/powerpc/include/asm/mpic.h
arch/powerpc/include/asm/opal.h [new file with mode: 0644]
arch/powerpc/include/asm/paca.h
arch/powerpc/include/asm/page.h
arch/powerpc/include/asm/page_64.h
arch/powerpc/include/asm/pte-book3e.h
arch/powerpc/include/asm/reg_booke.h
arch/powerpc/include/asm/rtas.h
arch/powerpc/include/asm/smp.h
arch/powerpc/include/asm/sparsemem.h
arch/powerpc/include/asm/topology.h
arch/powerpc/include/asm/udbg.h
arch/powerpc/include/asm/xics.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/dma-iommu.c
arch/powerpc/kernel/dma-swiotlb.c
arch/powerpc/kernel/dma.c
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/head_32.S
arch/powerpc/kernel/head_40x.S
arch/powerpc/kernel/head_44x.S
arch/powerpc/kernel/head_64.S
arch/powerpc/kernel/head_8xx.S
arch/powerpc/kernel/head_fsl_booke.S
arch/powerpc/kernel/ibmebus.c
arch/powerpc/kernel/idle_e500.S
arch/powerpc/kernel/iommu.c
arch/powerpc/kernel/legacy_serial.c
arch/powerpc/kernel/machine_kexec_64.c
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/pci-common.c
arch/powerpc/kernel/power6-pmu.c
arch/powerpc/kernel/power7-pmu.c
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/prom_init_check.sh
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/swsusp.c
arch/powerpc/kernel/traps.c
arch/powerpc/kernel/udbg.c
arch/powerpc/kernel/vio.c
arch/powerpc/math-emu/math_efp.c
arch/powerpc/mm/Makefile
arch/powerpc/mm/fsl_booke_mmu.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/hugetlbpage-book3e.c [new file with mode: 0644]
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/init_32.c
arch/powerpc/mm/mem.c
arch/powerpc/mm/mmu_context_hash64.c
arch/powerpc/mm/mmu_context_nohash.c
arch/powerpc/mm/mmu_decl.h
arch/powerpc/mm/numa.c
arch/powerpc/mm/pgtable.c
arch/powerpc/mm/tlb_low_64e.S
arch/powerpc/mm/tlb_nohash.c
arch/powerpc/platforms/40x/Kconfig
arch/powerpc/platforms/40x/Makefile
arch/powerpc/platforms/40x/hcu4.c [deleted file]
arch/powerpc/platforms/512x/Kconfig
arch/powerpc/platforms/82xx/km82xx.c
arch/powerpc/platforms/83xx/Kconfig
arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
arch/powerpc/platforms/85xx/Kconfig
arch/powerpc/platforms/85xx/Makefile
arch/powerpc/platforms/85xx/p1022_ds.c
arch/powerpc/platforms/85xx/p2041_rdb.c [moved from arch/powerpc/platforms/85xx/p2040_rdb.c with 82% similarity]
arch/powerpc/platforms/85xx/p3060_qds.c [new file with mode: 0644]
arch/powerpc/platforms/85xx/sbc8560.c
arch/powerpc/platforms/85xx/smp.c
arch/powerpc/platforms/86xx/Kconfig
arch/powerpc/platforms/Kconfig
arch/powerpc/platforms/Kconfig.cputype
arch/powerpc/platforms/Makefile
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/platforms/powernv/Kconfig [new file with mode: 0644]
arch/powerpc/platforms/powernv/Makefile [new file with mode: 0644]
arch/powerpc/platforms/powernv/opal-nvram.c [new file with mode: 0644]
arch/powerpc/platforms/powernv/opal-rtc.c [new file with mode: 0644]
arch/powerpc/platforms/powernv/opal-takeover.S [new file with mode: 0644]
arch/powerpc/platforms/powernv/opal-wrappers.S [new file with mode: 0644]
arch/powerpc/platforms/powernv/opal.c [new file with mode: 0644]
arch/powerpc/platforms/powernv/pci-p5ioc2.c [new file with mode: 0644]
arch/powerpc/platforms/powernv/pci.c [new file with mode: 0644]
arch/powerpc/platforms/powernv/pci.h [new file with mode: 0644]
arch/powerpc/platforms/powernv/powernv.h [new file with mode: 0644]
arch/powerpc/platforms/powernv/setup.c [new file with mode: 0644]
arch/powerpc/platforms/powernv/smp.c [new file with mode: 0644]
arch/powerpc/platforms/ps3/Kconfig
arch/powerpc/platforms/ps3/Makefile
arch/powerpc/platforms/ps3/gelic_udbg.c [new file with mode: 0644]
arch/powerpc/platforms/ps3/system-bus.c
arch/powerpc/platforms/pseries/Kconfig
arch/powerpc/platforms/pseries/dlpar.c
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/iommu.c
arch/powerpc/platforms/pseries/nvram.c
arch/powerpc/platforms/wsp/Kconfig
arch/powerpc/platforms/wsp/Makefile
arch/powerpc/platforms/wsp/ics.c
arch/powerpc/platforms/wsp/ics.h
arch/powerpc/platforms/wsp/msi.c [new file with mode: 0644]
arch/powerpc/platforms/wsp/msi.h [new file with mode: 0644]
arch/powerpc/platforms/wsp/psr2.c
arch/powerpc/platforms/wsp/wsp.h
arch/powerpc/platforms/wsp/wsp_pci.c [new file with mode: 0644]
arch/powerpc/platforms/wsp/wsp_pci.h [new file with mode: 0644]
arch/powerpc/sysdev/Makefile
arch/powerpc/sysdev/cpm_common.c
arch/powerpc/sysdev/fsl_msi.c
arch/powerpc/sysdev/fsl_msi.h
arch/powerpc/sysdev/mpic.c
arch/powerpc/sysdev/ppc4xx_pci.c
arch/powerpc/sysdev/ppc4xx_pci.h
arch/powerpc/sysdev/xics/Makefile
arch/powerpc/sysdev/xics/icp-native.c
arch/powerpc/sysdev/xics/ics-opal.c [new file with mode: 0644]
arch/powerpc/sysdev/xics/xics-common.c
arch/powerpc/xmon/xmon.c
drivers/edac/cpc925_edac.c
drivers/edac/ppc4xx_edac.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-mpc8xxx.c [moved from arch/powerpc/sysdev/mpc8xxx_gpio.c with 98% similarity]
drivers/net/ethernet/toshiba/ps3_gelic_net.c
drivers/net/ethernet/toshiba/ps3_gelic_net.h
drivers/of/fdt.c
drivers/tty/hvc/Kconfig
drivers/tty/hvc/Makefile
drivers/tty/hvc/hvc_opal.c [new file with mode: 0644]
drivers/tty/hvc/hvcs.c
drivers/tty/hvc/hvsi_lib.c
drivers/tty/serial/8250.c
drivers/virt/fsl_hypervisor.c
include/linux/dma-mapping.h
include/linux/topology.h
kernel/sched.c

index 39e9415..380914e 100644 (file)
@@ -1,3 +1,8 @@
+Freescale Reference Board Bindings
+
+This document describes device tree bindings for various devices that
+exist on some Freescale reference boards.
+
 * Board Control and Status (BCSR)
 
 Required properties:
@@ -12,25 +17,26 @@ Example:
                reg = <f8000000 8000>;
        };
 
-* Freescale on board FPGA
+* Freescale on-board FPGA
 
 This is the memory-mapped registers for on board FPGA.
 
 Required properities:
-- compatible : should be "fsl,fpga-pixis".
-- reg : should contain the address and the length of the FPPGA register
-  set.
+- compatible: should be a board-specific string followed by a string
+  indicating the type of FPGA.  Example:
+       "fsl,<board>-fpga", "fsl,fpga-pixis"
+- reg: should contain the address and the length of the FPGA register set.
 - interrupt-parent: should specify phandle for the interrupt controller.
-- interrupts : should specify event (wakeup) IRQ.
+- interrupts: should specify event (wakeup) IRQ.
 
-Example (MPC8610HPCD):
+Example (P1022DS):
 
-       board-control@e8000000 {
-               compatible = "fsl,fpga-pixis";
-               reg = <0xe8000000 32>;
-               interrupt-parent = <&mpic>;
-               interrupts = <8 8>;
-       };
+        board-control@3,0 {
+                compatible = "fsl,p1022ds-fpga", "fsl,fpga-ngpixis";
+                reg = <3 0 0x30>;
+                interrupt-parent = <&mpic>;
+                interrupts = <8 8 0 0>;
+        };
 
 * Freescale BCSR GPIO banks
 
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/dcsr.txt b/Documentation/devicetree/bindings/powerpc/fsl/dcsr.txt
new file mode 100644 (file)
index 0000000..9d54eb5
--- /dev/null
@@ -0,0 +1,395 @@
+===================================================================
+Debug Control and Status Register (DCSR) Binding
+Copyright 2011 Freescale Semiconductor Inc.
+
+NOTE: The bindings described in this document are preliminary and subject
+to change.  Some of the compatible strings that contain only generic names
+may turn out to be inappropriate, or need additional properties to describe
+the integration of the block with the rest of the chip.
+
+=====================================================================
+Debug Control and Status Register Memory Map
+
+Description
+
+This node defines the base address and range for the
+defined DCSR Memory Map. Child nodes will describe the individual
+debug blocks defined within this memory space.
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include "fsl,dcsr" and "simple-bus".
+       The DCSR space exists in the memory-mapped bus.
+
+       - #address-cells
+       Usage: required
+       Value type: <u32>
+       Definition: A standard property.  Defines the number of cells
+       or representing physical addresses in child nodes.
+
+       - #size-cells
+       Usage: required
+       Value type: <u32>
+       Definition: A standard property.  Defines the number of cells
+       or representing the size of physical addresses in
+       child nodes.
+
+       - ranges
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property. Specifies the physical address
+       range of the DCSR space.
+
+EXAMPLE
+       dcsr: dcsr@f00000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "fsl,dcsr", "simple-bus";
+               ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+       };
+
+=====================================================================
+Event Processing Unit
+
+This node represents the region of DCSR space allocated to the EPU
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include "fsl,dcsr-epu"
+
+       - interrupts
+       Usage: required
+       Value type: <prop_encoded-array>
+       Definition:  Specifies the interrupts generated by the EPU.
+       The value of the interrupts property consists of three
+       interrupt specifiers. The format of the specifier is defined
+       by the binding document describing the node's interrupt parent.
+
+       The EPU counters can be configured to assert the performance
+       monitor interrupt signal based on either counter overflow or value
+       match. Which counter asserted the interrupt is captured in an EPU
+       Counter Interrupt Status Register (EPCPUISR).
+
+       The EPU unit can also be configured to assert either or both of
+       two interrupt signals based on debug event sources within the SoC.
+       The interrupt signals are epu_xt_int0 and epu_xt_int1.
+       Which event source asserted the interrupt is captured in an EPU
+       Interrupt Status Register (EPISR0,EPISR1).
+
+       Interrupt numbers are lised in order (perfmon, event0, event1).
+
+       - interrupt-parent
+       Usage: required
+       Value type: <phandle>
+       Definition: A single <phandle> value that points
+       to the interrupt parent to which the child domain
+       is being mapped. Value must be "&mpic"
+
+       - reg
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+       offset and length of the DCSR space registers of the device
+       configuration block.
+
+EXAMPLE
+       dcsr-epu@0 {
+               compatible = "fsl,dcsr-epu";
+               interrupts = <52 2 0 0
+                             84 2 0 0
+                             85 2 0 0>;
+               interrupt-parent = <&mpic>;
+               reg = <0x0 0x1000>;
+       };
+
+=======================================================================
+Nexus Port Controller
+
+This node represents the region of DCSR space allocated to the NPC
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include "fsl,dcsr-npc"
+
+       - reg
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+       offset and length of the DCSR space registers of the device
+       configuration block.
+       The Nexus Port controller occupies two regions in the DCSR space
+       with distinct functionality.
+
+       The first register range describes the Nexus Port Controller
+       control and status registers.
+
+       The second register range describes the Nexus Port Controller
+       internal trace buffer. The NPC trace buffer is a small memory buffer
+       which stages the nexus trace data for transmission via the Aurora port
+       or to a DDR based trace buffer. In some configurations the NPC trace
+       buffer can be the only trace buffer used.
+
+
+EXAMPLE
+               dcsr-npc {
+                       compatible = "fsl,dcsr-npc";
+                       reg = <0x1000 0x1000 0x1000000 0x8000>;
+               };
+
+=======================================================================
+Nexus Concentrator
+
+This node represents the region of DCSR space allocated to the NXC
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include "fsl,dcsr-nxc"
+
+       - reg
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+       offset and length of the DCSR space registers of the device
+       configuration block.
+
+EXAMPLE
+               dcsr-nxc@2000 {
+                       compatible = "fsl,dcsr-nxc";
+                       reg = <0x2000 0x1000>;
+               };
+=======================================================================
+CoreNet Debug Controller
+
+This node represents the region of DCSR space allocated to
+the CoreNet Debug controller.
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include "fsl,dcsr-corenet"
+
+       - reg
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+       offset and length of the DCSR space registers of the device
+       configuration block.
+       The CoreNet Debug controller occupies two regions in the DCSR space
+       with distinct functionality.
+
+       The first register range describes the CoreNet Debug Controller
+       functionalty to perform transaction and transaction attribute matches.
+
+       The second register range describes the CoreNet Debug Controller
+       functionalty to trigger event notifications and debug traces.
+
+EXAMPLE
+               dcsr-corenet {
+                       compatible = "fsl,dcsr-corenet";
+                       reg = <0x8000 0x1000 0xB0000 0x1000>;
+               };
+
+=======================================================================
+Data Path Debug controller
+
+This node represents the region of DCSR space allocated to
+the DPAA Debug Controller. This controller controls debug configuration
+for the QMAN and FMAN blocks.
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include both an identifier specific to the SoC
+       or Debug IP of the form "fsl,<soc>-dcsr-dpaa" in addition to the
+       generic compatible string "fsl,dcsr-dpaa".
+
+       - reg
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+       offset and length of the DCSR space registers of the device
+       configuration block.
+
+EXAMPLE
+               dcsr-dpaa@9000 {
+                       compatible = "fsl,p4080-dcsr-dpaa", "fsl,dcsr-dpaa";
+                       reg = <0x9000 0x1000>;
+               };
+
+=======================================================================
+OCeaN Debug controller
+
+This node represents the region of DCSR space allocated to
+the OCN Debug Controller.
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include both an identifier specific to the SoC
+       or Debug IP of the form "fsl,<soc>-dcsr-ocn" in addition to the
+       generic compatible string "fsl,dcsr-ocn".
+
+       - reg
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+       offset and length of the DCSR space registers of the device
+       configuration block.
+
+EXAMPLE
+               dcsr-ocn@11000 {
+                       compatible = "fsl,p4080-dcsr-ocn", "fsl,dcsr-ocn";
+                       reg = <0x11000 0x1000>;
+               };
+
+=======================================================================
+DDR Controller Debug controller
+
+This node represents the region of DCSR space allocated to
+the OCN Debug Controller.
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include "fsl,dcsr-ddr"
+
+       - dev-handle
+       Usage: required
+       Definition: A phandle to associate this debug node with its
+       component controller.
+
+       - reg
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+       offset and length of the DCSR space registers of the device
+       configuration block.
+
+EXAMPLE
+               dcsr-ddr@12000 {
+                       compatible = "fsl,dcsr-ddr";
+                       dev-handle = <&ddr1>;
+                       reg = <0x12000 0x1000>;
+               };
+
+=======================================================================
+Nexus Aurora Link Controller
+
+This node represents the region of DCSR space allocated to
+the NAL Controller.
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include both an identifier specific to the SoC
+       or Debug IP of the form "fsl,<soc>-dcsr-nal" in addition to the
+       generic compatible string "fsl,dcsr-nal".
+
+       - reg
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+       offset and length of the DCSR space registers of the device
+       configuration block.
+
+EXAMPLE
+               dcsr-nal@18000 {
+                       compatible = "fsl,p4080-dcsr-nal", "fsl,dcsr-nal";
+                       reg = <0x18000 0x1000>;
+               };
+
+
+=======================================================================
+Run Control and Power Management
+
+This node represents the region of DCSR space allocated to
+the RCPM Debug Controller. This functionlity is limited to the
+control the debug operations of the SoC and cores.
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include both an identifier specific to the SoC
+       or Debug IP of the form "fsl,<soc>-dcsr-rcpm" in addition to the
+       generic compatible string "fsl,dcsr-rcpm".
+
+       - reg
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+       offset and length of the DCSR space registers of the device
+       configuration block.
+
+EXAMPLE
+               dcsr-rcpm@22000 {
+                       compatible = "fsl,p4080-dcsr-rcpm", "fsl,dcsr-rcpm";
+                       reg = <0x22000 0x1000>;
+               };
+
+=======================================================================
+Core Service Bridge Proxy
+
+This node represents the region of DCSR space allocated to
+the Core Service Bridge Proxies.
+There is one Core Service Bridge Proxy device for each CPU in the system.
+This functionlity provides access to the debug operations of the CPU.
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include both an identifier specific to the cpu
+       of the form "fsl,dcsr-<cpu>-sb-proxy" in addition to the
+       generic compatible string "fsl,dcsr-cpu-sb-proxy".
+
+       - cpu-handle
+       Usage: required
+       Definition: A phandle to associate this debug node with its cpu.
+
+       - reg
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+       offset and length of the DCSR space registers of the device
+       configuration block.
+
+EXAMPLE
+               dcsr-cpu-sb-proxy@40000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy",
+                                    "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu0>;
+                       reg = <0x40000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@41000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy",
+                                    "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu1>;
+                       reg = <0x41000 0x1000>;
+               };
+
+=======================================================================
index 70558c3..5d586e1 100644 (file)
@@ -25,6 +25,16 @@ Required properties:
   are routed to IPIC, and for 85xx/86xx cpu the interrupts are routed
   to MPIC.
 
+Optional properties:
+- msi-address-64: 64-bit PCI address of the MSIIR register. The MSIIR register
+  is used for MSI messaging.  The address of MSIIR in PCI address space is
+  the MSI message address.
+
+  This property may be used in virtualized environments where the hypervisor
+  has created an alternate mapping for the MSIR block.  See below for an
+  explanation.
+
+
 Example:
        msi@41600 {
                compatible = "fsl,mpc8610-msi", "fsl,mpic-msi";
@@ -41,3 +51,35 @@ Example:
                        0xe7 0>;
                interrupt-parent = <&mpic>;
        };
+
+The Freescale hypervisor and msi-address-64
+-------------------------------------------
+Normally, PCI devices have access to all of CCSR via an ATMU mapping.  The
+Freescale MSI driver calculates the address of MSIIR (in the MSI register
+block) and sets that address as the MSI message address.
+
+In a virtualized environment, the hypervisor may need to create an IOMMU
+mapping for MSIIR.  The Freescale ePAPR hypervisor has this requirement
+because of hardware limitations of the Peripheral Access Management Unit
+(PAMU), which is currently the only IOMMU that the hypervisor supports.
+The ATMU is programmed with the guest physical address, and the PAMU
+intercepts transactions and reroutes them to the true physical address.
+
+In the PAMU, each PCI controller is given only one primary window.  The
+PAMU restricts DMA operations so that they can only occur within a window.
+Because PCI devices must be able to DMA to memory, the primary window must
+be used to cover all of the guest's memory space.
+
+PAMU primary windows can be divided into 256 subwindows, and each
+subwindow can have its own address mapping ("guest physical" to "true
+physical").  However, each subwindow has to have the same alignment, which
+means they cannot be located at just any address.  Because of these
+restrictions, it is usually impossible to create a 4KB subwindow that
+covers MSIIR where it's normally located.
+
+Therefore, the hypervisor has to create a subwindow inside the same
+primary window used for memory, but mapped to the MSIR block (where MSIIR
+lives).  The first subwindow after the end of guest memory is used for
+this.  The address specified in the msi-address-64 property is the PCI
+address of MSIIR.  The hypervisor configures the PAMU to map that address to
+the true physical address of MSIIR.
index 47682b6..85195e4 100644 (file)
@@ -323,7 +323,7 @@ config SWIOTLB
 
 config HOTPLUG_CPU
        bool "Support for enabling/disabling CPUs"
-       depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
+       depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC || PPC_POWERNV)
        ---help---
          Say Y here to be able to disable and re-enable individual
          CPUs at runtime on SMP machines.
@@ -345,7 +345,7 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE
 
 config KEXEC
        bool "kexec system call (EXPERIMENTAL)"
-       depends on (PPC_BOOK3S || FSL_BOOKE) && EXPERIMENTAL
+       depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP && !47x)) && EXPERIMENTAL
        help
          kexec is a system call that implements the ability to shutdown your
          current kernel, and to start another kernel.  It is like a reboot
@@ -429,8 +429,7 @@ config ARCH_POPULATES_NODE_MAP
        def_bool y
 
 config SYS_SUPPORTS_HUGETLBFS
-       def_bool y
-       depends on PPC_BOOK3S_64
+       bool
 
 source "mm/Kconfig"
 
index 067cb84..1b8a9c9 100644 (file)
@@ -141,9 +141,6 @@ config BOOTX_TEXT
 
 config PPC_EARLY_DEBUG
        bool "Early debugging (dangerous)"
-       # PPC_EARLY_DEBUG on 440 leaves AS=1 mappings above the TLB high water
-       # mark, which doesn't work with current 440 KVM.
-       depends on !KVM
        help
          Say Y to enable some early debugging facilities that may be available
          for your processor/board combination. Those facilities are hacks
@@ -222,7 +219,9 @@ config PPC_EARLY_DEBUG_BEAT
 
 config PPC_EARLY_DEBUG_44x
        bool "Early serial debugging for IBM/AMCC 44x CPUs"
-       depends on 44x
+       # PPC_EARLY_DEBUG on 440 leaves AS=1 mappings above the TLB high water
+       # mark, which doesn't work with current 440 KVM.
+       depends on 44x && !KVM
        help
          Select this to enable early debugging for IBM 44x chips via the
          inbuilt serial port.  If you enable this, ensure you set
@@ -258,8 +257,35 @@ config PPC_EARLY_DEBUG_WSP
        depends on PPC_WSP
        select PPC_UDBG_16550
 
+config PPC_EARLY_DEBUG_PS3GELIC
+       bool "Early debugging through the PS3 Ethernet port"
+       depends on PPC_PS3
+       select PS3GELIC_UDBG
+       help
+         Select this to enable early debugging for the PlayStation3 via
+         UDP broadcasts sent out through the Ethernet port.
+
+config PPC_EARLY_DEBUG_OPAL_RAW
+       bool "OPAL raw console"
+       depends on HVC_OPAL
+       help
+         Select this to enable early debugging for the PowerNV platform
+         using a "raw" console
+
+config PPC_EARLY_DEBUG_OPAL_HVSI
+       bool "OPAL hvsi console"
+       depends on HVC_OPAL
+       help
+         Select this to enable early debugging for the PowerNV platform
+         using an "hvsi" console
+
 endchoice
 
+config PPC_EARLY_DEBUG_OPAL
+       def_bool y
+       depends on PPC_EARLY_DEBUG_OPAL_RAW || PPC_EARLY_DEBUG_OPAL_HVSI
+
+
 config PPC_EARLY_DEBUG_HVSI_VTERMNO
        hex "vterm number to use with early debug HVSI"
        depends on PPC_EARLY_DEBUG_LPAR_HVSI
@@ -268,6 +294,18 @@ config PPC_EARLY_DEBUG_HVSI_VTERMNO
          You probably want 0x30000000 for your first serial port and
          0x30000001 for your second one
 
+config PPC_EARLY_DEBUG_OPAL_VTERMNO
+       hex "vterm number to use with OPAL early debug"
+       depends on PPC_EARLY_DEBUG_OPAL
+       default "0"
+       help
+         This correspond to which /dev/hvcN you want to use for early
+         debug.
+
+         On OPAL v1 (takeover) this should always be 0
+         On OPAL v2, this will be 0 for network console and 1 or 2 for
+         the machine built-in serial ports.
+
 config PPC_EARLY_DEBUG_44x_PHYSLOW
        hex "Low 32 bits of early debug UART physical address"
        depends on PPC_EARLY_DEBUG_44x
index c26200b..72ee8c1 100644 (file)
@@ -58,7 +58,7 @@ $(addprefix $(obj)/,$(zlib) cuboot-c2k.o gunzip_util.o main.o prpmc2800.o): \
 libfdt       := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
 libfdtheader := fdt.h libfdt.h libfdt_internal.h
 
-$(addprefix $(obj)/,$(libfdt) libfdt-wrapper.o simpleboot.o): \
+$(addprefix $(obj)/,$(libfdt) libfdt-wrapper.o simpleboot.o epapr.o): \
        $(addprefix $(obj)/,$(libfdtheader))
 
 src-wlib := string.S crt0.S crtsavres.S stdio.c main.c \
@@ -171,6 +171,7 @@ quiet_cmd_wrap      = WRAP    $@
                $(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) vmlinux
 
 image-$(CONFIG_PPC_PSERIES)            += zImage.pseries
+image-$(CONFIG_PPC_POWERNV)            += zImage.pseries
 image-$(CONFIG_PPC_MAPLE)              += zImage.maple
 image-$(CONFIG_PPC_IBM_CELL_BLADE)     += zImage.pseries
 image-$(CONFIG_PPC_PS3)                        += dtbImage.ps3
index 27bd267..a7511f2 100644 (file)
 
        soc5200@f0000000 {
                timer@600 {     // General Purpose Timer
+                       #gpio-cells = <2>;
                        fsl,has-wdt;
+                       gpio-controller;
                };
 
-               rtc@800 {
-                       status = "disabled";
+               timer@610 {
+                       #gpio-cells = <2>;
+                       gpio-controller;
                };
 
-               can@900 {
+               rtc@800 {
                        status = "disabled";
                };
 
-               can@980 {
-                       status = "disabled";
+               spi@f00 {
+                       msp430@0 {
+                               compatible = "spidev";
+                               spi-max-frequency = <32000>;
+                               reg = <0>;
+                       };
                };
 
                psc@2000 {              // PSC1
                };
 
                i2c@3d00 {
-                       rtc@50 {
+                       eeprom@50 {
                                compatible = "at,24c08";
                                reg = <0x50>;
                        };
 
+                       rtc@56 {
+                               compatible = "mc,rv3029c2";
+                               reg = <0x56>;
+                       };
+
                        rtc@68 {
                                compatible = "dallas,ds1339";
                                reg = <0x68>;
        };
 
        pci@f0000d00 {
-               status = "disabled";
+               interrupt-map-mask = <0xf800 0 0 7>;
+               interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3
+                                0xc000 0 0 2 &mpc5200_pic 0 0 3
+                                0xc000 0 0 3 &mpc5200_pic 0 0 3
+                                0xc000 0 0 4 &mpc5200_pic 0 0 3>;
+               clock-frequency = <0>; // From boot loader
+               interrupts = <2 8 0 2 9 0 2 10 0>;
+               bus-range = <0 0>;
+               ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000
+                         0x02000000 0 0x90000000 0x90000000 0 0x10000000
+                         0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
        };
 
        localbus {
-               ranges = <0 0 0xff000000 0x1000000>;
+               ranges = <0 0 0xff000000 0x1000000
+                         4 0 0x60000000 0x0001000>;
 
                // 16-bit flash device at LocalPlus Bus CS0
                flash@0,0 {
                                reg = <0x00f00000 0x100000>;
                        };
                };
+
+               can@4,0 {
+                       compatible = "nxp,sja1000";
+                       reg = <4 0x000 0x80>;
+                       nxp,external-clock-frequency = <24000000>;
+                       interrupts = <1 2 3>; // Level-low
+               };
+
+               can@4,100 {
+                       compatible = "nxp,sja1000";
+                       reg = <4 0x100 0x80>;
+                       nxp,external-clock-frequency = <24000000>;
+                       interrupts = <1 2 3>;  // Level-low
+               };
+
+               serial@4,200 {
+                       compatible = "nxp,sc28l92";
+                       reg = <4 0x200 0x10>;
+                       interrupts = <1 3 3>;
+               };
        };
 };
index 83f4b79..2266bbb 100644 (file)
                enet0: ethernet@24000 {
                        #address-cells = <1>;
                        #size-cells = <1>;
+                       cell-index = <0>;
                        device_type = "network";
-                       model = "eTSEC";
+                       model = "TSEC";
                        compatible = "gianfar";
                        reg = <0x24000 0x1000>;
                        ranges = <0x0 0x24000 0x1000>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
+                       interrupts = <29 2 30  2 34 2>;
                        interrupt-parent = <&mpic>;
+                       tbi-handle = <&tbi0>;
                        phy-handle = <&phy0>;
                        phy-connection-type = "gmii";
 
                                        interrupt-parent = <&gef_pic>;
                                        interrupts = <0x9 0x4>;
                                        reg = <1>;
+                                       device_type = "ethernet-phy";
                                };
                                phy2: ethernet-phy@2 {
                                        interrupt-parent = <&gef_pic>;
                                        interrupts = <0x8 0x4>;
                                        reg = <3>;
+                                       device_type = "ethernet-phy";
+                               };
+                               tbi0: tbi-phy@11 {
+                                       reg = <0x11>;
+                                       device_type = "tbi-phy";
                                };
                        };
                };
 
                enet1: ethernet@26000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       cell-index = <2>;
                        device_type = "network";
-                       model = "eTSEC";
+                       model = "TSEC";
                        compatible = "gianfar";
                        reg = <0x26000 0x1000>;
+                       ranges = <0x0 0x26000 0x1000>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <0x1f 0x2 0x20 0x2 0x21 0x2>;
+                       interrupts = <31 2 32 2 33 2>;
                        interrupt-parent = <&mpic>;
+                       tbi-handle = <&tbi2>;
                        phy-handle = <&phy2>;
                        phy-connection-type = "gmii";
+
+                       mdio@520 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fsl,gianfar-tbi";
+                               reg = <0x520 0x20>;
+
+                               tbi2: tbi-phy@11 {
+                                       reg = <0x11>;
+                                       device_type = "tbi-phy";
+                               };
+                       };
                };
 
                serial0: serial@4500 {
index fc3a331..429e87d 100644 (file)
                enet0: ethernet@24000 {
                        #address-cells = <1>;
                        #size-cells = <1>;
+                       cell-index = <0>;
                        device_type = "network";
-                       model = "eTSEC";
+                       model = "TSEC";
                        compatible = "gianfar";
                        reg = <0x24000 0x1000>;
                        ranges = <0x0 0x24000 0x1000>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
+                       interrupts = <29 2 30  2 34 2>;
                        interrupt-parent = <&mpic>;
+                       tbi-handle = <&tbi0>;
                        phy-handle = <&phy0>;
                        phy-connection-type = "gmii";
 
                                        interrupt-parent = <&gef_pic>;
                                        interrupts = <0x9 0x4>;
                                        reg = <1>;
+                                       device_type = "ethernet-phy";
                                };
                                phy2: ethernet-phy@2 {
                                        interrupt-parent = <&gef_pic>;
                                        interrupts = <0x8 0x4>;
                                        reg = <3>;
+                                       device_type = "ethernet-phy";
+                               };
+                               tbi0: tbi-phy@11 {
+                                       reg = <0x11>;
+                                       device_type = "tbi-phy";
                                };
                        };
                };
 
                enet1: ethernet@26000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       cell-index = <2>;
                        device_type = "network";
-                       model = "eTSEC";
+                       model = "TSEC";
                        compatible = "gianfar";
                        reg = <0x26000 0x1000>;
+                       ranges = <0x0 0x26000 0x1000>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <0x1f 0x2 0x20 0x2 0x21 0x2>;
+                       interrupts = <31 2 32 2 33 2>;
                        interrupt-parent = <&mpic>;
+                       tbi-handle = <&tbi2>;
                        phy-handle = <&phy2>;
                        phy-connection-type = "gmii";
+
+                       mdio@520 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fsl,gianfar-tbi";
+                               reg = <0x520 0x20>;
+
+                               tbi2: tbi-phy@11 {
+                                       reg = <0x11>;
+                                       device_type = "tbi-phy";
+                               };
+                       };
                };
 
                serial0: serial@4500 {
index c0671cc..d81201a 100644 (file)
                enet0: ethernet@24000 {
                        #address-cells = <1>;
                        #size-cells = <1>;
+                       cell-index = <0>;
                        device_type = "network";
-                       model = "eTSEC";
+                       model = "TSEC";
                        compatible = "gianfar";
                        reg = <0x24000 0x1000>;
                        ranges = <0x0 0x24000 0x1000>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
+                       interrupts = <29 2 30  2 34 2>;
                        interrupt-parent = <&mpic>;
+                       tbi-handle = <&tbi0>;
                        phy-handle = <&phy0>;
                        phy-connection-type = "gmii";
 
                                        interrupt-parent = <&gef_pic>;
                                        interrupts = <0x9 0x4>;
                                        reg = <1>;
+                                       device_type = "ethernet-phy";
                                };
                                phy2: ethernet-phy@2 {
                                        interrupt-parent = <&gef_pic>;
                                        interrupts = <0x8 0x4>;
                                        reg = <3>;
+                                       device_type = "ethernet-phy";
+                               };
+                               tbi0: tbi-phy@11 {
+                                       reg = <0x11>;
+                                       device_type = "tbi-phy";
                                };
                        };
                };
 
                enet1: ethernet@26000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       cell-index = <2>;
                        device_type = "network";
-                       model = "eTSEC";
+                       model = "TSEC";
                        compatible = "gianfar";
                        reg = <0x26000 0x1000>;
+                       ranges = <0x0 0x26000 0x1000>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <0x1f 0x2 0x20 0x2 0x21 0x2>;
+                       interrupts = <31 2 32 2 33 2>;
                        interrupt-parent = <&mpic>;
+                       tbi-handle = <&tbi2>;
                        phy-handle = <&phy2>;
                        phy-connection-type = "gmii";
+
+                       mdio@520 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fsl,gianfar-tbi";
+                               reg = <0x520 0x20>;
+
+                               tbi2: tbi-phy@11 {
+                                       reg = <0x11>;
+                                       device_type = "tbi-phy";
+                               };
+                       };
                };
 
                serial0: serial@4500 {
diff --git a/arch/powerpc/boot/dts/hcu4.dts b/arch/powerpc/boot/dts/hcu4.dts
deleted file mode 100644 (file)
index 7988598..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
-* Device Tree Source for Netstal Maschinen HCU4
-* based on the IBM Walnut
-*
-* Copyright 2008
-* Niklaus Giger <niklaus.giger@member.fsf.org>
-*
-* Copyright 2007 IBM Corp.
-* Josh Boyer <jwboyer@linux.vnet.ibm.com>
-*
-* 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.
-*/
-
-/dts-v1/;
-
-/ {
-       #address-cells = <0x1>;
-       #size-cells = <0x1>;
-       model = "netstal,hcu4";
-       compatible = "netstal,hcu4";
-       dcr-parent = <0x1>;
-
-       aliases {
-               ethernet0 = "/plb/opb/ethernet@ef600800";
-               serial0 = "/plb/opb/serial@ef600300";
-       };
-
-       cpus {
-               #address-cells = <0x1>;
-               #size-cells = <0x0>;
-
-               cpu@0 {
-                       device_type = "cpu";
-                       model = "PowerPC,405GPr";
-                       reg = <0x0>;
-                       clock-frequency = <0>;          /* Filled in by U-Boot */
-                       timebase-frequency = <0x0>;     /* Filled in by U-Boot */
-                       i-cache-line-size = <0x20>;
-                       d-cache-line-size = <0x20>;
-                       i-cache-size = <0x4000>;
-                       d-cache-size = <0x4000>;
-                       dcr-controller;
-                       dcr-access-method = "native";
-                       linux,phandle = <0x1>;
-               };
-       };
-
-       memory {
-               device_type = "memory";
-               reg = <0x0 0x0>;        /* Filled in by U-Boot */
-       };
-
-       UIC0: interrupt-controller {
-               compatible = "ibm,uic";
-               interrupt-controller;
-               cell-index = <0x0>;
-               dcr-reg = <0xc0 0x9>;
-               #address-cells = <0x0>;
-               #size-cells = <0x0>;
-               #interrupt-cells = <0x2>;
-               linux,phandle = <0x2>;
-       };
-
-       plb {
-               compatible = "ibm,plb3";
-               #address-cells = <0x1>;
-               #size-cells = <0x1>;
-               ranges;
-               clock-frequency = <0x0>;        /* Filled in by U-Boot */
-
-               SDRAM0: memory-controller {
-                       compatible = "ibm,sdram-405gp";
-                       dcr-reg = <0x10 0x2>;
-               };
-
-               MAL: mcmal {
-                       compatible = "ibm,mcmal-405gp", "ibm,mcmal";
-                       dcr-reg = <0x180 0x62>;
-                       num-tx-chans = <0x1>;
-                       num-rx-chans = <0x1>;
-                       interrupt-parent = <0x2>;
-                       interrupts = <0xb 0x4 0xc 0x4 0xa 0x4 0xd 0x4 0xe 0x4>;
-                       linux,phandle = <0x3>;
-               };
-
-               POB0: opb {
-                       compatible = "ibm,opb-405gp", "ibm,opb";
-                       #address-cells = <0x1>;
-                       #size-cells = <0x1>;
-                       ranges = <0xef600000 0xef600000 0xa00000>;
-                       dcr-reg = <0xa0 0x5>;
-                       clock-frequency = <0x0>;        /* Filled in by U-Boot */
-
-                       UART0: serial@ef600300 {
-                               device_type = "serial";
-                               compatible = "ns16550";
-                               reg = <0xef600300 0x8>;
-                               virtual-reg = <0xef600300>;
-                               clock-frequency = <0x0>;/* Filled in by U-Boot */
-                               current-speed = <0>;    /* Filled in by U-Boot */
-                               interrupt-parent = <0x2>;
-                               interrupts = <0x0 0x4>;
-                       };
-
-                       IIC: i2c@ef600500 {
-                               compatible = "ibm,iic-405gp", "ibm,iic";
-                               reg = <0xef600500 0x11>;
-                               interrupt-parent = <0x2>;
-                               interrupts = <0x2 0x4>;
-                       };
-
-                       GPIO: gpio@ef600700 {
-                               compatible = "ibm,gpio-405gp";
-                               reg = <0xef600700 0x20>;
-                       };
-
-                       EMAC: ethernet@ef600800 {
-                               device_type = "network";
-                               compatible = "ibm,emac-405gp", "ibm,emac";
-                               interrupt-parent = <0x2>;
-                               interrupts = <0xf 0x4 0x9 0x4>;
-                               local-mac-address = [00 00 00 00 00 00];
-                               reg = <0xef600800 0x70>;
-                               mal-device = <0x3>;
-                               mal-tx-channel = <0x0>;
-                               mal-rx-channel = <0x0>;
-                               cell-index = <0x0>;
-                               max-frame-size = <0x5dc>;
-                               rx-fifo-size = <0x1000>;
-                               tx-fifo-size = <0x800>;
-                               phy-mode = "rmii";
-                               phy-map = <0x1>;
-                       };
-               };
-
-               EBC0: ebc {
-                       compatible = "ibm,ebc-405gp", "ibm,ebc";
-                       dcr-reg = <0x12 0x2>;
-                       #address-cells = <0x2>;
-                       #size-cells = <0x1>;
-                       clock-frequency = <0x0>;        /* Filled in by U-Boot */
-
-                       sram@0,0 {
-                               reg = <0x0 0x0 0x80000>;
-                       };
-
-                       flash@0,80000 {
-                               compatible = "jedec-flash";
-                               bank-width = <0x1>;
-                               reg = <0x0 0x80000 0x80000>;
-                               #address-cells = <0x1>;
-                               #size-cells = <0x1>;
-
-                               partition@0 {
-                                       label = "OpenBIOS";
-                                       reg = <0x0 0x80000>;
-                                       read-only;
-                               };
-                       };
-               };
-       };
-
-       chosen {
-               linux,stdout-path = "/plb/opb/serial@ef600300";
-       };
-};
index bdb7fc0..296c572 100644 (file)
        localbus@fdf05000 {
                #address-cells = <2>;
                #size-cells = <1>;
-               compatible = "fsl,mpc8560-localbus";
+               compatible = "fsl,mpc8560-localbus", "simple-bus";
                reg = <0xfdf05000 0x68>;
 
                ranges = <0x0 0x0 0xe0000000 0x00800000
index 1360d2f..ededaf5 100644 (file)
                                linux,network-index = <2>;
                                fsl,cpm-command = <0x16200300>;
                        };
+
+                       usb@11b60 {
+                               compatible = "fsl,mpc8272-cpm-usb";
+                               mode = "peripheral";
+                               reg = <0x11b60 0x40 0x8b00 0x100>;
+                               interrupts = <11 8>;
+                               interrupt-parent = <&PIC>;
+                               usb-clock = <5>;
+                       };
                };
 
                cpm2_pio_c: gpio-controller@10d40 {
index bc27548..7ab286a 100644 (file)
                };
 
                spi@f00 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
                        compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
                        reg = <0xf00 0x20>;
                        interrupts = <2 13 0 2 14 0>;
index b53d1df..505dc84 100644 (file)
                #address-cells = <2>;
                #size-cells = <1>;
                compatible = "fsl,mpc8349e-localbus",
-                            "fsl,pq2pro-localbus";
+                            "fsl,pq2pro-localbus",
+                            "simple-bus";
                reg = <0xe0005000 0xd8>;
                ranges = <0x0 0x0 0xfe000000 0x1000000  /* flash */
                          0x1 0x0 0xf8000000 0x20000    /* VSC 7385 */
index 1be9743..b9b8719 100644 (file)
                };
 
                board-control@3,0 {
-                       compatible = "fsl,p1022ds-pixis";
+                       compatible = "fsl,p1022ds-fpga", "fsl,fpga-ngpixis";
                        reg = <3 0 0x30>;
                        interrupt-parent = <&mpic>;
                        /*
index dae4031..66f03d6 100644 (file)
                        };
                };
 
+               board-control@3,0 {
+                       compatible = "fsl,p2020ds-fpga", "fsl,fpga-ngpixis";
+                       reg = <0x3 0x0 0x30>;
+               };
+
                nand@4,0 {
                        compatible = "fsl,elbc-fcm-nand";
                        reg = <0x4 0x0 0x40000>;
similarity index 95%
rename from arch/powerpc/boot/dts/p2040rdb.dts
rename to arch/powerpc/boot/dts/p2041rdb.dts
index 7d84e39..79b6895 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * P2040RDB Device Tree Source
+ * P2041RDB Device Tree Source
  *
  * Copyright 2011 Freescale Semiconductor Inc.
  *
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-/include/ "p2040si.dtsi"
+/include/ "p2041si.dtsi"
 
 / {
-       model = "fsl,P2040RDB";
-       compatible = "fsl,P2040RDB";
+       model = "fsl,P2041RDB";
+       compatible = "fsl,P2041RDB";
        #address-cells = <2>;
        #size-cells = <2>;
        interrupt-parent = <&mpic>;
                device_type = "memory";
        };
 
+       dcsr: dcsr@f00000000 {
+               ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+       };
+
        soc: soc@ffe000000 {
                spi@110000 {
                        flash@0 {
                        };
                };
 
-               usb0: usb@210000 {
-                       phy_type = "utmi";
-               };
-
                usb1: usb@211000 {
                        dr_mode = "host";
-                       phy_type = "utmi";
                };
        };
 
similarity index 80%
rename from arch/powerpc/boot/dts/p2040si.dtsi
rename to arch/powerpc/boot/dts/p2041si.dtsi
index 5fdbb24..f7492ed 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * P2040 Silicon Device Tree Source
+ * P2041 Silicon Device Tree Source
  *
  * Copyright 2011 Freescale Semiconductor Inc.
  *
 /dts-v1/;
 
 / {
-       compatible = "fsl,P2040";
+       compatible = "fsl,P2041";
        #address-cells = <2>;
        #size-cells = <2>;
        interrupt-parent = <&mpic>;
 
        aliases {
                ccsr = &soc;
+               dcsr = &dcsr;
 
                serial0 = &serial0;
                serial1 = &serial1;
                };
        };
 
+       dcsr: dcsr@f00000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "fsl,dcsr", "simple-bus";
+
+               dcsr-epu@0 {
+                       compatible = "fsl,dcsr-epu";
+                       interrupts = <52 2 0 0
+                                     84 2 0 0
+                                     85 2 0 0>;
+                       interrupt-parent = <&mpic>;
+                       reg = <0x0 0x1000>;
+               };
+               dcsr-npc {
+                       compatible = "fsl,dcsr-npc";
+                       reg = <0x1000 0x1000 0x1000000 0x8000>;
+               };
+               dcsr-nxc@2000 {
+                       compatible = "fsl,dcsr-nxc";
+                       reg = <0x2000 0x1000>;
+               };
+               dcsr-corenet {
+                       compatible = "fsl,dcsr-corenet";
+                       reg = <0x8000 0x1000 0xB0000 0x1000>;
+               };
+               dcsr-dpaa@9000 {
+                       compatible = "fsl,p2041-dcsr-dpaa", "fsl,dcsr-dpaa";
+                       reg = <0x9000 0x1000>;
+               };
+               dcsr-ocn@11000 {
+                       compatible = "fsl,p2041-dcsr-ocn", "fsl,dcsr-ocn";
+                       reg = <0x11000 0x1000>;
+               };
+               dcsr-ddr@12000 {
+                       compatible = "fsl,dcsr-ddr";
+                       dev-handle = <&ddr>;
+                       reg = <0x12000 0x1000>;
+               };
+               dcsr-nal@18000 {
+                       compatible = "fsl,p2041-dcsr-nal", "fsl,dcsr-nal";
+                       reg = <0x18000 0x1000>;
+               };
+               dcsr-rcpm@22000 {
+                       compatible = "fsl,p2041-dcsr-rcpm", "fsl,dcsr-rcpm";
+                       reg = <0x22000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@40000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu0>;
+                       reg = <0x40000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@41000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu1>;
+                       reg = <0x41000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@42000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu2>;
+                       reg = <0x42000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@43000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu3>;
+                       reg = <0x43000 0x1000>;
+               };
+       };
+
        soc: soc@ffe000000 {
                #address-cells = <1>;
                #size-cells = <1>;
                        fsl,num-laws = <32>;
                };
 
-               memory-controller@8000 {
+               ddr: memory-controller@8000 {
                        compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
                        reg = <0x8000 0x1000>;
                        interrupts = <16 2 1 23>;
                };
 
                cpc: l3-cache-controller@10000 {
-                       compatible = "fsl,p2040-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache";
+                       compatible = "fsl,p2041-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache";
                        reg = <0x10000 0x1000>;
                        interrupts = <16 2 1 27>;
                };
                };
 
                clockgen: global-utilities@e1000 {
-                       compatible = "fsl,p2040-clockgen", "fsl,qoriq-clockgen-1.0";
+                       compatible = "fsl,p2041-clockgen", "fsl,qoriq-clockgen-1.0";
                        reg = <0xe1000 0x1000>;
                        clock-frequency = <0>;
                };
                };
 
                sfp: sfp@e8000 {
-                       compatible = "fsl,p2040-sfp", "fsl,qoriq-sfp-1.0";
+                       compatible = "fsl,p2041-sfp", "fsl,qoriq-sfp-1.0";
                        reg        = <0xe8000 0x1000>;
                };
 
                serdes: serdes@ea000 {
-                       compatible = "fsl,p2040-serdes";
+                       compatible = "fsl,p2041-serdes";
                        reg        = <0xea000 0x1000>;
                };
 
                dma0: dma@100300 {
                        #address-cells = <1>;
                        #size-cells = <1>;
-                       compatible = "fsl,p2040-dma", "fsl,eloplus-dma";
+                       compatible = "fsl,p2041-dma", "fsl,eloplus-dma";
                        reg = <0x100300 0x4>;
                        ranges = <0x0 0x100100 0x200>;
                        cell-index = <0>;
                        dma-channel@0 {
-                               compatible = "fsl,p2040-dma-channel",
+                               compatible = "fsl,p2041-dma-channel",
                                                "fsl,eloplus-dma-channel";
                                reg = <0x0 0x80>;
                                cell-index = <0>;
                                interrupts = <28 2 0 0>;
                        };
                        dma-channel@80 {
-                               compatible = "fsl,p2040-dma-channel",
+                               compatible = "fsl,p2041-dma-channel",
                                                "fsl,eloplus-dma-channel";
                                reg = <0x80 0x80>;
                                cell-index = <1>;
                                interrupts = <29 2 0 0>;
                        };
                        dma-channel@100 {
-                               compatible = "fsl,p2040-dma-channel",
+                               compatible = "fsl,p2041-dma-channel",
                                                "fsl,eloplus-dma-channel";
                                reg = <0x100 0x80>;
                                cell-index = <2>;
                                interrupts = <30 2 0 0>;
                        };
                        dma-channel@180 {
-                               compatible = "fsl,p2040-dma-channel",
+                               compatible = "fsl,p2041-dma-channel",
                                                "fsl,eloplus-dma-channel";
                                reg = <0x180 0x80>;
                                cell-index = <3>;
                dma1: dma@101300 {
                        #address-cells = <1>;
                        #size-cells = <1>;
-                       compatible = "fsl,p2040-dma", "fsl,eloplus-dma";
+                       compatible = "fsl,p2041-dma", "fsl,eloplus-dma";
                        reg = <0x101300 0x4>;
                        ranges = <0x0 0x101100 0x200>;
                        cell-index = <1>;
                        dma-channel@0 {
-                               compatible = "fsl,p2040-dma-channel",
+                               compatible = "fsl,p2041-dma-channel",
                                                "fsl,eloplus-dma-channel";
                                reg = <0x0 0x80>;
                                cell-index = <0>;
                                interrupts = <32 2 0 0>;
                        };
                        dma-channel@80 {
-                               compatible = "fsl,p2040-dma-channel",
+                               compatible = "fsl,p2041-dma-channel",
                                                "fsl,eloplus-dma-channel";
                                reg = <0x80 0x80>;
                                cell-index = <1>;
                                interrupts = <33 2 0 0>;
                        };
                        dma-channel@100 {
-                               compatible = "fsl,p2040-dma-channel",
+                               compatible = "fsl,p2041-dma-channel",
                                                "fsl,eloplus-dma-channel";
                                reg = <0x100 0x80>;
                                cell-index = <2>;
                                interrupts = <34 2 0 0>;
                        };
                        dma-channel@180 {
-                               compatible = "fsl,p2040-dma-channel",
+                               compatible = "fsl,p2041-dma-channel",
                                                "fsl,eloplus-dma-channel";
                                reg = <0x180 0x80>;
                                cell-index = <3>;
                spi@110000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       compatible = "fsl,p2040-espi", "fsl,mpc8536-espi";
+                       compatible = "fsl,p2041-espi", "fsl,mpc8536-espi";
                        reg = <0x110000 0x1000>;
                        interrupts = <53 0x2 0 0>;
                        fsl,espi-num-chipselects = <4>;
-
                };
 
                sdhc: sdhc@114000 {
-                       compatible = "fsl,p2040-esdhc", "fsl,esdhc";
+                       compatible = "fsl,p2041-esdhc", "fsl,esdhc";
                        reg = <0x114000 0x1000>;
                        interrupts = <48 2 0 0>;
                        sdhci,auto-cmd12;
                        clock-frequency = <0>;
                };
 
-
                i2c@118000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                };
 
                gpio0: gpio@130000 {
-                       compatible = "fsl,p2040-gpio", "fsl,qoriq-gpio";
+                       compatible = "fsl,p2041-gpio", "fsl,qoriq-gpio";
                        reg = <0x130000 0x1000>;
                        interrupts = <55 2 0 0>;
                        #gpio-cells = <2>;
                };
 
                usb0: usb@210000 {
-                       compatible = "fsl,p2040-usb2-mph",
+                       compatible = "fsl,p2041-usb2-mph",
                                        "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
                        reg = <0x210000 0x1000>;
                        #address-cells = <1>;
                        #size-cells = <0>;
                        interrupts = <44 0x2 0 0>;
+                       phy_type = "utmi";
                        port0;
                };
 
                usb1: usb@211000 {
-                       compatible = "fsl,p2040-usb2-dr",
+                       compatible = "fsl,p2041-usb2-dr",
                                        "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
                        reg = <0x211000 0x1000>;
                        #address-cells = <1>;
                        #size-cells = <0>;
                        interrupts = <45 0x2 0 0>;
+                       phy_type = "utmi";
                };
 
                sata@220000 {
-                       compatible = "fsl,p2040-sata", "fsl,pq-sata-v2";
+                       compatible = "fsl,p2041-sata", "fsl,pq-sata-v2";
                        reg = <0x220000 0x1000>;
                        interrupts = <68 0x2 0 0>;
                };
 
                sata@221000 {
-                       compatible = "fsl,p2040-sata", "fsl,pq-sata-v2";
+                       compatible = "fsl,p2041-sata", "fsl,pq-sata-v2";
                        reg = <0x221000 0x1000>;
                        interrupts = <69 0x2 0 0>;
                };
        };
 
        localbus@ffe124000 {
-               compatible = "fsl,p2040-elbc", "fsl,elbc", "simple-bus";
+               compatible = "fsl,p2041-elbc", "fsl,elbc", "simple-bus";
                interrupts = <25 2 0 0>;
                #address-cells = <2>;
                #size-cells = <1>;
        };
 
        pci0: pcie@ffe200000 {
-               compatible = "fsl,p2040-pcie", "fsl,qoriq-pcie-v2.2";
+               compatible = "fsl,p2041-pcie", "fsl,qoriq-pcie-v2.2";
                device_type = "pci";
                #size-cells = <2>;
                #address-cells = <3>;
                bus-range = <0x0 0xff>;
-               clock-frequency = <0x1fca055>;
+               clock-frequency = <33333333>;
                fsl,msi = <&msi0>;
                interrupts = <16 2 1 15>;
                pcie@0 {
        };
 
        pci1: pcie@ffe201000 {
-               compatible = "fsl,p2040-pcie", "fsl,qoriq-pcie-v2.2";
+               compatible = "fsl,p2041-pcie", "fsl,qoriq-pcie-v2.2";
                device_type = "pci";
                #size-cells = <2>;
                #address-cells = <3>;
                bus-range = <0 0xff>;
-               clock-frequency = <0x1fca055>;
+               clock-frequency = <33333333>;
                fsl,msi = <&msi1>;
                interrupts = <16 2 1 14>;
                pcie@0 {
        };
 
        pci2: pcie@ffe202000 {
-               compatible = "fsl,p2040-pcie", "fsl,qoriq-pcie-v2.2";
+               compatible = "fsl,p2041-pcie", "fsl,qoriq-pcie-v2.2";
                device_type = "pci";
                #size-cells = <2>;
                #address-cells = <3>;
                bus-range = <0x0 0xff>;
-               clock-frequency = <0x1fca055>;
+               clock-frequency = <33333333>;
                fsl,msi = <&msi2>;
                interrupts = <16 2 1 13>;
                pcie@0 {
index 69cae67..bbd113b 100644 (file)
                device_type = "memory";
        };
 
+       dcsr: dcsr@f00000000 {
+               ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+       };
+
        soc: soc@ffe000000 {
                spi@110000 {
                        flash@0 {
                };
 
                board-control@3,0 {
-                       compatible = "fsl,p3041ds-pixis";
-                       reg = <3 0 0x20>;
+                       compatible = "fsl,p3041ds-fpga", "fsl,fpga-ngpixis";
+                       reg = <3 0 0x30>;
                };
        };
 
index 8b69580..87130b7 100644 (file)
@@ -42,6 +42,7 @@
 
        aliases {
                ccsr = &soc;
+               dcsr = &dcsr;
 
                serial0 = &serial0;
                serial1 = &serial1;
                };
        };
 
+       dcsr: dcsr@f00000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "fsl,dcsr", "simple-bus";
+
+               dcsr-epu@0 {
+                       compatible = "fsl,dcsr-epu";
+                       interrupts = <52 2 0 0
+                                     84 2 0 0
+                                     85 2 0 0>;
+                       interrupt-parent = <&mpic>;
+                       reg = <0x0 0x1000>;
+               };
+               dcsr-npc {
+                       compatible = "fsl,dcsr-npc";
+                       reg = <0x1000 0x1000 0x1000000 0x8000>;
+               };
+               dcsr-nxc@2000 {
+                       compatible = "fsl,dcsr-nxc";
+                       reg = <0x2000 0x1000>;
+               };
+               dcsr-corenet {
+                       compatible = "fsl,dcsr-corenet";
+                       reg = <0x8000 0x1000 0xB0000 0x1000>;
+               };
+               dcsr-dpaa@9000 {
+                       compatible = "fsl,p43041-dcsr-dpaa", "fsl,dcsr-dpaa";
+                       reg = <0x9000 0x1000>;
+               };
+               dcsr-ocn@11000 {
+                       compatible = "fsl,p43041-dcsr-ocn", "fsl,dcsr-ocn";
+                       reg = <0x11000 0x1000>;
+               };
+               dcsr-ddr@12000 {
+                       compatible = "fsl,dcsr-ddr";
+                       dev-handle = <&ddr>;
+                       reg = <0x12000 0x1000>;
+               };
+               dcsr-nal@18000 {
+                       compatible = "fsl,p43041-dcsr-nal", "fsl,dcsr-nal";
+                       reg = <0x18000 0x1000>;
+               };
+               dcsr-rcpm@22000 {
+                       compatible = "fsl,p43041-dcsr-rcpm", "fsl,dcsr-rcpm";
+                       reg = <0x22000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@40000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu0>;
+                       reg = <0x40000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@41000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu1>;
+                       reg = <0x41000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@42000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu2>;
+                       reg = <0x42000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@43000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu3>;
+                       reg = <0x43000 0x1000>;
+               };
+       };
+
        soc: soc@ffe000000 {
                #address-cells = <1>;
                #size-cells = <1>;
                        fsl,num-laws = <32>;
                };
 
-               memory-controller@8000 {
+               ddr: memory-controller@8000 {
                        compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
                        reg = <0x8000 0x1000>;
                        interrupts = <16 2 1 23>;
diff --git a/arch/powerpc/boot/dts/p3060qds.dts b/arch/powerpc/boot/dts/p3060qds.dts
new file mode 100644 (file)
index 0000000..08b9193
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * P3060QDS Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "p3060si.dtsi"
+
+/ {
+       model = "fsl,P3060QDS";
+       compatible = "fsl,P3060QDS";
+       #address-cells = <2>;
+       #size-cells = <2>;
+       interrupt-parent = <&mpic>;
+
+       memory {
+               device_type = "memory";
+       };
+
+       dcsr: dcsr@f00000000 {
+               ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+       };
+
+       soc: soc@ffe000000 {
+               spi@110000 {
+                       flash@0 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               compatible = "spansion,s25sl12801";
+                               reg = <0>;
+                               spi-max-frequency = <40000000>; /* input clock */
+                               partition@u-boot {
+                                       label = "u-boot";
+                                       reg = <0x00000000 0x00100000>;
+                                       read-only;
+                               };
+                               partition@kernel {
+                                       label = "kernel";
+                                       reg = <0x00100000 0x00500000>;
+                                       read-only;
+                               };
+                               partition@dtb {
+                                       label = "dtb";
+                                       reg = <0x00600000 0x00100000>;
+                                       read-only;
+                               };
+                               partition@fs {
+                                       label = "file system";
+                                       reg = <0x00700000 0x00900000>;
+                               };
+                       };
+                       flash@1 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               compatible = "spansion,en25q32b";
+                               reg = <1>;
+                               spi-max-frequency = <40000000>; /* input clock */
+                               partition@spi1 {
+                                       label = "spi1";
+                                       reg = <0x00000000 0x00400000>;
+                               };
+                       };
+                       flash@2 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               compatible = "atmel,at45db081d";
+                               reg = <2>;
+                               spi-max-frequency = <40000000>; /* input clock */
+                               partition@spi1 {
+                                       label = "spi2";
+                                       reg = <0x00000000 0x00100000>;
+                               };
+                       };
+                       flash@3 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               compatible = "spansion,sst25wf040";
+                               reg = <3>;
+                               spi-max-frequency = <40000000>; /* input clock */
+                               partition@spi3 {
+                                       label = "spi3";
+                                       reg = <0x00000000 0x00080000>;
+                               };
+                       };
+               };
+
+               i2c@118000 {
+                       eeprom@51 {
+                               compatible = "at24,24c256";
+                               reg = <0x51>;
+                       };
+                       eeprom@53 {
+                               compatible = "at24,24c256";
+                               reg = <0x53>;
+                       };
+                       rtc@68 {
+                               compatible = "dallas,ds3232";
+                               reg = <0x68>;
+                               interrupts = <0x1 0x1 0 0>;
+                       };
+               };
+
+               usb0: usb@210000 {
+                       phy_type = "ulpi";
+               };
+
+               usb1: usb@211000 {
+                       dr_mode = "host";
+                       phy_type = "ulpi";
+               };
+       };
+
+       rapidio@ffe0c0000 {
+               reg = <0xf 0xfe0c0000 0 0x11000>;
+
+               port1 {
+                       ranges = <0 0 0xc 0x20000000 0 0x10000000>;
+               };
+               port2 {
+                       ranges = <0 0 0xc 0x30000000 0 0x10000000>;
+               };
+       };
+
+       localbus@ffe124000 {
+               reg = <0xf 0xfe124000 0 0x1000>;
+               ranges = <0 0 0xf 0xe8000000 0x08000000
+                         2 0 0xf 0xffa00000 0x00040000
+                         3 0 0xf 0xffdf0000 0x00008000>;
+
+               flash@0,0 {
+                       compatible = "cfi-flash";
+                       reg = <0 0 0x08000000>;
+                       bank-width = <2>;
+                       device-width = <2>;
+               };
+
+               nand@2,0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "fsl,elbc-fcm-nand";
+                       reg = <0x2 0x0 0x40000>;
+
+                       partition@0 {
+                               label = "NAND U-Boot Image";
+                               reg = <0x0 0x02000000>;
+                               read-only;
+                       };
+
+                       partition@2000000 {
+                               label = "NAND Root File System";
+                               reg = <0x02000000 0x10000000>;
+                       };
+
+                       partition@12000000 {
+                               label = "NAND Compressed RFS Image";
+                               reg = <0x12000000 0x08000000>;
+                       };
+
+                       partition@1a000000 {
+                               label = "NAND Linux Kernel Image";
+                               reg = <0x1a000000 0x04000000>;
+                       };
+
+                       partition@1e000000 {
+                               label = "NAND DTB Image";
+                               reg = <0x1e000000 0x01000000>;
+                       };
+
+                       partition@1f000000 {
+                               label = "NAND Writable User area";
+                               reg = <0x1f000000 0x21000000>;
+                       };
+               };
+
+               board-control@3,0 {
+                       compatible = "fsl,p3060qds-fpga", "fsl,fpga-qixis";
+                       reg = <3 0 0x100>;
+               };
+       };
+
+       pci0: pcie@ffe200000 {
+               reg = <0xf 0xfe200000 0 0x1000>;
+               ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+                         0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
+               pcie@0 {
+                       ranges = <0x02000000 0 0xe0000000
+                                 0x02000000 0 0xe0000000
+                                 0 0x20000000
+
+                                 0x01000000 0 0x00000000
+                                 0x01000000 0 0x00000000
+                                 0 0x00010000>;
+               };
+       };
+
+       pci1: pcie@ffe201000 {
+               reg = <0xf 0xfe201000 0 0x1000>;
+               ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
+                         0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
+               pcie@0 {
+                       ranges = <0x02000000 0 0xe0000000
+                                 0x02000000 0 0xe0000000
+                                 0 0x20000000
+
+                                 0x01000000 0 0x00000000
+                                 0x01000000 0 0x00000000
+                                 0 0x00010000>;
+               };
+       };
+};
diff --git a/arch/powerpc/boot/dts/p3060si.dtsi b/arch/powerpc/boot/dts/p3060si.dtsi
new file mode 100644 (file)
index 0000000..68947e1
--- /dev/null
@@ -0,0 +1,719 @@
+/*
+ * P3060 Silicon Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+
+/ {
+       compatible = "fsl,P3060";
+       #address-cells = <2>;
+       #size-cells = <2>;
+       interrupt-parent = <&mpic>;
+
+       aliases {
+               ccsr = &soc;
+               dcsr = &dcsr;
+
+               serial0 = &serial0;
+               serial1 = &serial1;
+               serial2 = &serial2;
+               serial3 = &serial3;
+               pci0 = &pci0;
+               pci1 = &pci1;
+               usb0 = &usb0;
+               usb1 = &usb1;
+               dma0 = &dma0;
+               dma1 = &dma1;
+               msi0 = &msi0;
+               msi1 = &msi1;
+               msi2 = &msi2;
+
+               crypto = &crypto;
+               sec_jr0 = &sec_jr0;
+               sec_jr1 = &sec_jr1;
+               sec_jr2 = &sec_jr2;
+               sec_jr3 = &sec_jr3;
+               rtic_a = &rtic_a;
+               rtic_b = &rtic_b;
+               rtic_c = &rtic_c;
+               rtic_d = &rtic_d;
+               sec_mon = &sec_mon;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu0: PowerPC,e500mc@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       next-level-cache = <&L2_0>;
+                       L2_0: l2-cache {
+                               next-level-cache = <&cpc>;
+                       };
+               };
+               cpu1: PowerPC,e500mc@1 {
+                       device_type = "cpu";
+                       reg = <1>;
+                       next-level-cache = <&L2_1>;
+                       L2_1: l2-cache {
+                               next-level-cache = <&cpc>;
+                       };
+               };
+               cpu4: PowerPC,e500mc@4 {
+                       device_type = "cpu";
+                       reg = <4>;
+                       next-level-cache = <&L2_4>;
+                       L2_4: l2-cache {
+                               next-level-cache = <&cpc>;
+                       };
+               };
+               cpu5: PowerPC,e500mc@5 {
+                       device_type = "cpu";
+                       reg = <5>;
+                       next-level-cache = <&L2_5>;
+                       L2_5: l2-cache {
+                               next-level-cache = <&cpc>;
+                       };
+               };
+               cpu6: PowerPC,e500mc@6 {
+                       device_type = "cpu";
+                       reg = <6>;
+                       next-level-cache = <&L2_6>;
+                       L2_6: l2-cache {
+                               next-level-cache = <&cpc>;
+                       };
+               };
+               cpu7: PowerPC,e500mc@7 {
+                       device_type = "cpu";
+                       reg = <7>;
+                       next-level-cache = <&L2_7>;
+                       L2_7: l2-cache {
+                               next-level-cache = <&cpc>;
+                       };
+               };
+       };
+
+       dcsr: dcsr@f00000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "fsl,dcsr", "simple-bus";
+
+               dcsr-epu@0 {
+                       compatible = "fsl,dcsr-epu";
+                       interrupts = <52 2 0 0
+                                     84 2 0 0
+                                     85 2 0 0>;
+                       interrupt-parent = <&mpic>;
+                       reg = <0x0 0x1000>;
+               };
+               dcsr-npc {
+                       compatible = "fsl,dcsr-npc";
+                       reg = <0x1000 0x1000 0x1000000 0x8000>;
+               };
+               dcsr-nxc@2000 {
+                       compatible = "fsl,dcsr-nxc";
+                       reg = <0x2000 0x1000>;
+               };
+               dcsr-corenet {
+                       compatible = "fsl,dcsr-corenet";
+                       reg = <0x8000 0x1000 0xB0000 0x1000>;
+               };
+               dcsr-dpaa@9000 {
+                       compatible = "fsl,p3060-dcsr-dpaa", "fsl,dcsr-dpaa";
+                       reg = <0x9000 0x1000>;
+               };
+               dcsr-ocn@11000 {
+                       compatible = "fsl,p3060-dcsr-ocn", "fsl,dcsr-ocn";
+                       reg = <0x11000 0x1000>;
+               };
+               dcsr-ddr@12000 {
+                       compatible = "fsl,dcsr-ddr";
+                       dev-handle = <&ddr>;
+                       reg = <0x12000 0x1000>;
+               };
+               dcsr-nal@18000 {
+                       compatible = "fsl,p3060-dcsr-nal", "fsl,dcsr-nal";
+                       reg = <0x18000 0x1000>;
+               };
+               dcsr-rcpm@22000 {
+                       compatible = "fsl,p3060-dcsr-rcpm", "fsl,dcsr-rcpm";
+                       reg = <0x22000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@40000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu0>;
+                       reg = <0x40000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@41000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu1>;
+                       reg = <0x41000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@44000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu4>;
+                       reg = <0x44000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@45000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu5>;
+                       reg = <0x45000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@46000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu6>;
+                       reg = <0x46000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@47000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu7>;
+                       reg = <0x47000 0x1000>;
+               };
+       };
+
+       soc: soc@ffe000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               device_type = "soc";
+               compatible = "simple-bus";
+               ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+               reg = <0xf 0xfe000000 0 0x00001000>;
+
+               soc-sram-error {
+                       compatible = "fsl,soc-sram-error";
+                       interrupts = <16 2 1 29>;
+               };
+
+               corenet-law@0 {
+                       compatible = "fsl,corenet-law";
+                       reg = <0x0 0x1000>;
+                       fsl,num-laws = <32>;
+               };
+
+               ddr: memory-controller@8000 {
+                       compatible = "fsl,qoriq-memory-controller-v4.4", "fsl,qoriq-memory-controller";
+                       reg = <0x8000 0x1000>;
+                       interrupts = <16 2 1 23>;
+               };
+
+               cpc: l3-cache-controller@10000 {
+                       compatible = "fsl,p3060-l3-cache-controller", "cache";
+                       reg = <0x10000 0x1000
+                              0x11000 0x1000>;
+                       interrupts = <16 2 1 27>;
+               };
+
+               corenet-cf@18000 {
+                       compatible = "fsl,corenet-cf";
+                       reg = <0x18000 0x1000>;
+                       interrupts = <16 2 1 31>;
+                       fsl,ccf-num-csdids = <32>;
+                       fsl,ccf-num-snoopids = <32>;
+               };
+
+               iommu@20000 {
+                       compatible = "fsl,pamu-v1.0", "fsl,pamu";
+                       reg = <0x20000 0x5000>;
+                       interrupts = <
+                               24 2 0 0
+                               16 2 1 30>;
+               };
+
+               mpic: pic@40000 {
+                       clock-frequency = <0>;
+                       interrupt-controller;
+                       #address-cells = <0>;
+                       #interrupt-cells = <4>;
+                       reg = <0x40000 0x40000>;
+                       compatible = "fsl,mpic", "chrp,open-pic";
+                       device_type = "open-pic";
+               };
+
+               msi0: msi@41600 {
+                       compatible = "fsl,mpic-msi";
+                       reg = <0x41600 0x200>;
+                       msi-available-ranges = <0 0x100>;
+                       interrupts = <
+                               0xe0 0 0 0
+                               0xe1 0 0 0
+                               0xe2 0 0 0
+                               0xe3 0 0 0
+                               0xe4 0 0 0
+                               0xe5 0 0 0
+                               0xe6 0 0 0
+                               0xe7 0 0 0>;
+               };
+
+               msi1: msi@41800 {
+                       compatible = "fsl,mpic-msi";
+                       reg = <0x41800 0x200>;
+                       msi-available-ranges = <0 0x100>;
+                       interrupts = <
+                               0xe8 0 0 0
+                               0xe9 0 0 0
+                               0xea 0 0 0
+                               0xeb 0 0 0
+                               0xec 0 0 0
+                               0xed 0 0 0
+                               0xee 0 0 0
+                               0xef 0 0 0>;
+               };
+
+               msi2: msi@41a00 {
+                       compatible = "fsl,mpic-msi";
+                       reg = <0x41a00 0x200>;
+                       msi-available-ranges = <0 0x100>;
+                       interrupts = <
+                               0xf0 0 0 0
+                               0xf1 0 0 0
+                               0xf2 0 0 0
+                               0xf3 0 0 0
+                               0xf4 0 0 0
+                               0xf5 0 0 0
+                               0xf6 0 0 0
+                               0xf7 0 0 0>;
+               };
+
+               rmu: rmu@d3000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "fsl,srio-rmu";
+                       reg = <0xd3000 0x500>;
+                       ranges = <0x0 0xd3000 0x500>;
+
+                       message-unit@0 {
+                               compatible = "fsl,srio-msg-unit";
+                               reg = <0x0 0x100>;
+                               interrupts = <
+                                       60 2 0 0  /* msg1_tx_irq */
+                                       61 2 0 0>;/* msg1_rx_irq */
+                       };
+                       message-unit@100 {
+                               compatible = "fsl,srio-msg-unit";
+                               reg = <0x100 0x100>;
+                               interrupts = <
+                                       62 2 0 0  /* msg2_tx_irq */
+                                       63 2 0 0>;/* msg2_rx_irq */
+                       };
+                       doorbell-unit@400 {
+                               compatible = "fsl,srio-dbell-unit";
+                               reg = <0x400 0x80>;
+                               interrupts = <
+                                       56 2 0 0  /* bell_outb_irq */
+                                       57 2 0 0>;/* bell_inb_irq */
+                       };
+                       port-write-unit@4e0 {
+                               compatible = "fsl,srio-port-write-unit";
+                               reg = <0x4e0 0x20>;
+                               interrupts = <16 2 1 11>;
+                       };
+               };
+
+               guts: global-utilities@e0000 {
+                       compatible = "fsl,qoriq-device-config-1.0";
+                       reg = <0xe0000 0xe00>;
+                       fsl,has-rstcr;
+                       #sleep-cells = <1>;
+                       fsl,liodn-bits = <12>;
+               };
+
+               pins: global-utilities@e0e00 {
+                       compatible = "fsl,qoriq-pin-control-1.0";
+                       reg = <0xe0e00 0x200>;
+                       #sleep-cells = <2>;
+               };
+
+               clockgen: global-utilities@e1000 {
+                       compatible = "fsl,p3060-clockgen", "fsl,qoriq-clockgen-1.0";
+                       reg = <0xe1000 0x1000>;
+                       clock-frequency = <0>;
+               };
+
+               rcpm: global-utilities@e2000 {
+                       compatible = "fsl,qoriq-rcpm-1.0";
+                       reg = <0xe2000 0x1000>;
+                       #sleep-cells = <1>;
+               };
+
+               sfp: sfp@e8000 {
+                       compatible = "fsl,p3060-sfp", "fsl,qoriq-sfp-1.0";
+                       reg        = <0xe8000 0x1000>;
+               };
+
+               serdes: serdes@ea000 {
+                       compatible = "fsl,p3060-serdes";
+                       reg        = <0xea000 0x1000>;
+               };
+
+               dma0: dma@100300 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "fsl,p3060-dma", "fsl,eloplus-dma";
+                       reg = <0x100300 0x4>;
+                       ranges = <0x0 0x100100 0x200>;
+                       cell-index = <0>;
+                       dma-channel@0 {
+                               compatible = "fsl,p3060-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x0 0x80>;
+                               cell-index = <0>;
+                               interrupts = <28 2 0 0>;
+                       };
+                       dma-channel@80 {
+                               compatible = "fsl,p3060-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x80 0x80>;
+                               cell-index = <1>;
+                               interrupts = <29 2 0 0>;
+                       };
+                       dma-channel@100 {
+                               compatible = "fsl,p3060-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x100 0x80>;
+                               cell-index = <2>;
+                               interrupts = <30 2 0 0>;
+                       };
+                       dma-channel@180 {
+                               compatible = "fsl,p3060-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x180 0x80>;
+                               cell-index = <3>;
+                               interrupts = <31 2 0 0>;
+                       };
+               };
+
+               dma1: dma@101300 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "fsl,p3060-dma", "fsl,eloplus-dma";
+                       reg = <0x101300 0x4>;
+                       ranges = <0x0 0x101100 0x200>;
+                       cell-index = <1>;
+                       dma-channel@0 {
+                               compatible = "fsl,p3060-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x0 0x80>;
+                               cell-index = <0>;
+                               interrupts = <32 2 0 0>;
+                       };
+                       dma-channel@80 {
+                               compatible = "fsl,p3060-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x80 0x80>;
+                               cell-index = <1>;
+                               interrupts = <33 2 0 0>;
+                       };
+                       dma-channel@100 {
+                               compatible = "fsl,p3060-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x100 0x80>;
+                               cell-index = <2>;
+                               interrupts = <34 2 0 0>;
+                       };
+                       dma-channel@180 {
+                               compatible = "fsl,p3060-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x180 0x80>;
+                               cell-index = <3>;
+                               interrupts = <35 2 0 0>;
+                       };
+               };
+
+               spi@110000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl,p3060-espi", "fsl,mpc8536-espi";
+                       reg = <0x110000 0x1000>;
+                       interrupts = <53 0x2 0 0>;
+                       fsl,espi-num-chipselects = <4>;
+               };
+
+               i2c@118000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <0>;
+                       compatible = "fsl-i2c";
+                       reg = <0x118000 0x100>;
+                       interrupts = <38 2 0 0>;
+                       dfsrr;
+               };
+
+               i2c@118100 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <1>;
+                       compatible = "fsl-i2c";
+                       reg = <0x118100 0x100>;
+                       interrupts = <38 2 0 0>;
+                       dfsrr;
+               };
+
+               i2c@119000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <2>;
+                       compatible = "fsl-i2c";
+                       reg = <0x119000 0x100>;
+                       interrupts = <39 2 0 0>;
+                       dfsrr;
+               };
+
+               i2c@119100 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <3>;
+                       compatible = "fsl-i2c";
+                       reg = <0x119100 0x100>;
+                       interrupts = <39 2 0 0>;
+                       dfsrr;
+               };
+
+               serial0: serial@11c500 {
+                       cell-index = <0>;
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <0x11c500 0x100>;
+                       clock-frequency = <0>;
+                       interrupts = <36 2 0 0>;
+               };
+
+               serial1: serial@11c600 {
+                       cell-index = <1>;
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <0x11c600 0x100>;
+                       clock-frequency = <0>;
+                       interrupts = <36 2 0 0>;
+               };
+
+               serial2: serial@11d500 {
+                       cell-index = <2>;
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <0x11d500 0x100>;
+                       clock-frequency = <0>;
+                       interrupts = <37 2 0 0>;
+               };
+
+               serial3: serial@11d600 {
+                       cell-index = <3>;
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <0x11d600 0x100>;
+                       clock-frequency = <0>;
+                       interrupts = <37 2 0 0>;
+               };
+
+               gpio0: gpio@130000 {
+                       compatible = "fsl,p3060-gpio", "fsl,qoriq-gpio";
+                       reg = <0x130000 0x1000>;
+                       interrupts = <55 2 0 0>;
+                       #gpio-cells = <2>;
+                       gpio-controller;
+               };
+
+               usb0: usb@210000 {
+                       compatible = "fsl,p3060-usb2-mph",
+                                       "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+                       reg = <0x210000 0x1000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupts = <44 0x2 0 0>;
+               };
+
+               usb1: usb@211000 {
+                       compatible = "fsl,p3060-usb2-dr",
+                                       "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+                       reg = <0x211000 0x1000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupts = <45 0x2 0 0>;
+               };
+
+               crypto: crypto@300000 {
+                       compatible = "fsl,sec-v4.1", "fsl,sec-v4.0";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0x300000 0x10000>;
+                       ranges = <0 0x300000 0x10000>;
+                       interrupt-parent = <&mpic>;
+                       interrupts = <92 2 0 0>;
+
+                       sec_jr0: jr@1000 {
+                               compatible = "fsl,sec-v4.1-job-ring", "fsl,sec-v4.0-job-ring";
+                               reg = <0x1000 0x1000>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <88 2 0 0>;
+                       };
+
+                       sec_jr1: jr@2000 {
+                               compatible = "fsl,sec-v4.1-job-ring", "fsl,sec-v4.0-job-ring";
+                               reg = <0x2000 0x1000>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <89 2 0 0>;
+                       };
+
+                       sec_jr2: jr@3000 {
+                               compatible = "fsl,sec-v4.1-job-ring", "fsl,sec-v4.0-job-ring";
+                               reg = <0x3000 0x1000>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <90 2 0 0>;
+                       };
+
+                       sec_jr3: jr@4000 {
+                               compatible = "fsl,sec-v4.1-job-ring", "fsl,sec-v4.0-job-ring";
+                               reg = <0x4000 0x1000>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <91 2 0 0>;
+                       };
+
+                       rtic@6000 {
+                               compatible = "fsl,sec-v4.1-rtic", "fsl,sec-v4.0-rtic";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               reg = <0x6000 0x100>;
+                               ranges = <0x0 0x6100 0xe00>;
+
+                               rtic_a: rtic-a@0 {
+                                       compatible = "fsl,sec-v4.1-rtic-memory", "fsl,sec-v4.0-rtic-memory";
+                                       reg = <0x00 0x20 0x100 0x80>;
+                               };
+
+                               rtic_b: rtic-b@20 {
+                                       compatible = "fsl,sec-v4.1-rtic-memory", "fsl,sec-v4.0-rtic-memory";
+                                       reg = <0x20 0x20 0x200 0x80>;
+                               };
+
+                               rtic_c: rtic-c@40 {
+                                       compatible = "fsl,sec-v4.1-rtic-memory", "fsl,sec-v4.0-rtic-memory";
+                                       reg = <0x40 0x20 0x300 0x80>;
+                               };
+
+                               rtic_d: rtic-d@60 {
+                                       compatible = "fsl,sec-v4.1-rtic-memory", "fsl,sec-v4.0-rtic-memory";
+                                       reg = <0x60 0x20 0x500 0x80>;
+                               };
+                       };
+               };
+
+               sec_mon: sec_mon@314000 {
+                       compatible = "fsl,sec-v4.1-mon", "fsl,sec-v4.0-mon";
+                       reg = <0x314000 0x1000>;
+                       interrupt-parent = <&mpic>;
+                       interrupts = <93 2 0 0>;
+               };
+       };
+
+       rapidio@ffe0c0000 {
+               compatible = "fsl,srio";
+               interrupts = <16 2 1 11>;
+               #address-cells = <2>;
+               #size-cells = <2>;
+               fsl,srio-rmu-handle = <&rmu>;
+               ranges;
+
+               port1 {
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+                       cell-index = <1>;
+               };
+
+               port2 {
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+                       cell-index = <2>;
+               };
+       };
+
+       localbus@ffe124000 {
+               compatible = "fsl,p3060-elbc", "fsl,elbc", "simple-bus";
+               interrupts = <25 2 0 0>;
+               #address-cells = <2>;
+               #size-cells = <1>;
+       };
+
+       pci0: pcie@ffe200000 {
+               compatible = "fsl,p3060-pcie", "fsl,qoriq-pcie-v2.2";
+               device_type = "pci";
+               #size-cells = <2>;
+               #address-cells = <3>;
+               bus-range = <0x0 0xff>;
+               clock-frequency = <33333333>;
+               fsl,msi = <&msi0>;
+               interrupts = <16 2 1 15>;
+               pcie@0 {
+                       reg = <0 0 0 0 0>;
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       device_type = "pci";
+                       interrupts = <16 2 1 15>;
+                       interrupt-map-mask = <0xf800 0 0 7>;
+                       interrupt-map = <
+                               /* IDSEL 0x0 */
+                               0000 0 0 1 &mpic 40 1 0 0
+                               0000 0 0 2 &mpic 1 1 0 0
+                               0000 0 0 3 &mpic 2 1 0 0
+                               0000 0 0 4 &mpic 3 1 0 0
+                               >;
+               };
+       };
+
+       pci1: pcie@ffe201000 {
+               compatible = "fsl,p3060-pcie", "fsl,qoriq-pcie-v2.2";
+               device_type = "pci";
+               #size-cells = <2>;
+               #address-cells = <3>;
+               bus-range = <0 0xff>;
+               clock-frequency = <33333333>;
+               fsl,msi = <&msi1>;
+               interrupts = <16 2 1 14>;
+               pcie@0 {
+                       reg = <0 0 0 0 0>;
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       device_type = "pci";
+                       interrupts = <16 2 1 14>;
+                       interrupt-map-mask = <0xf800 0 0 7>;
+                       interrupt-map = <
+                               /* IDSEL 0x0 */
+                               0000 0 0 1 &mpic 41 1 0 0
+                               0000 0 0 2 &mpic 5 1 0 0
+                               0000 0 0 3 &mpic 6 1 0 0
+                               0000 0 0 4 &mpic 7 1 0 0
+                               >;
+               };
+       };
+};
index eb11098..c7916dc 100644 (file)
                device_type = "memory";
        };
 
+       dcsr: dcsr@f00000000 {
+               ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+       };
+
        soc: soc@ffe000000 {
                spi@110000 {
                        flash@0 {
 
        localbus@ffe124000 {
                reg = <0xf 0xfe124000 0 0x1000>;
-               ranges = <0 0 0xf 0xe8000000 0x08000000>;
+               ranges = <0 0 0xf 0xe8000000 0x08000000
+                         3 0 0xf 0xffdf0000 0x00008000>;
 
                flash@0,0 {
                        compatible = "cfi-flash";
                        bank-width = <2>;
                        device-width = <2>;
                };
+
+               board-control@3,0 {
+                       compatible = "fsl,p4080ds-fpga", "fsl,fpga-ngpixis";
+                       reg = <3 0 0x30>;
+               };
        };
 
        pci0: pcie@ffe200000 {
index b71051f..f20c01a 100644 (file)
@@ -42,6 +42,7 @@
 
        aliases {
                ccsr = &soc;
+               dcsr = &dcsr;
 
                serial0 = &serial0;
                serial1 = &serial1;
@@ -77,7 +78,7 @@
                #address-cells = <1>;
                #size-cells = <0>;
 
-               cpu0: PowerPC,4080@0 {
+               cpu0: PowerPC,e500mc@0 {
                        device_type = "cpu";
                        reg = <0>;
                        next-level-cache = <&L2_0>;
@@ -85,7 +86,7 @@
                                next-level-cache = <&cpc>;
                        };
                };
-               cpu1: PowerPC,4080@1 {
+               cpu1: PowerPC,e500mc@1 {
                        device_type = "cpu";
                        reg = <1>;
                        next-level-cache = <&L2_1>;
@@ -93,7 +94,7 @@
                                next-level-cache = <&cpc>;
                        };
                };
-               cpu2: PowerPC,4080@2 {
+               cpu2: PowerPC,e500mc@2 {
                        device_type = "cpu";
                        reg = <2>;
                        next-level-cache = <&L2_2>;
                                next-level-cache = <&cpc>;
                        };
                };
-               cpu3: PowerPC,4080@3 {
+               cpu3: PowerPC,e500mc@3 {
                        device_type = "cpu";
                        reg = <3>;
                        next-level-cache = <&L2_3>;
                                next-level-cache = <&cpc>;
                        };
                };
-               cpu4: PowerPC,4080@4 {
+               cpu4: PowerPC,e500mc@4 {
                        device_type = "cpu";
                        reg = <4>;
                        next-level-cache = <&L2_4>;
                                next-level-cache = <&cpc>;
                        };
                };
-               cpu5: PowerPC,4080@5 {
+               cpu5: PowerPC,e500mc@5 {
                        device_type = "cpu";
                        reg = <5>;
                        next-level-cache = <&L2_5>;
                                next-level-cache = <&cpc>;
                        };
                };
-               cpu6: PowerPC,4080@6 {
+               cpu6: PowerPC,e500mc@6 {
                        device_type = "cpu";
                        reg = <6>;
                        next-level-cache = <&L2_6>;
                                next-level-cache = <&cpc>;
                        };
                };
-               cpu7: PowerPC,4080@7 {
+               cpu7: PowerPC,e500mc@7 {
                        device_type = "cpu";
                        reg = <7>;
                        next-level-cache = <&L2_7>;
                };
        };
 
+       dcsr: dcsr@f00000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "fsl,dcsr", "simple-bus";
+
+               dcsr-epu@0 {
+                       compatible = "fsl,dcsr-epu";
+                       interrupts = <52 2 0 0
+                                     84 2 0 0
+                                     85 2 0 0>;
+                       interrupt-parent = <&mpic>;
+                       reg = <0x0 0x1000>;
+               };
+               dcsr-npc {
+                       compatible = "fsl,dcsr-npc";
+                       reg = <0x1000 0x1000 0x1000000 0x8000>;
+               };
+               dcsr-nxc@2000 {
+                       compatible = "fsl,dcsr-nxc";
+                       reg = <0x2000 0x1000>;
+               };
+               dcsr-corenet {
+                       compatible = "fsl,dcsr-corenet";
+                       reg = <0x8000 0x1000 0xB0000 0x1000>;
+               };
+               dcsr-dpaa@9000 {
+                       compatible = "fsl,p4080-dcsr-dpaa", "fsl,dcsr-dpaa";
+                       reg = <0x9000 0x1000>;
+               };
+               dcsr-ocn@11000 {
+                       compatible = "fsl,p4080-dcsr-ocn", "fsl,dcsr-ocn";
+                       reg = <0x11000 0x1000>;
+               };
+               dcsr-ddr@12000 {
+                       compatible = "fsl,dcsr-ddr";
+                       dev-handle = <&ddr1>;
+                       reg = <0x12000 0x1000>;
+               };
+               dcsr-ddr@13000 {
+                       compatible = "fsl,dcsr-ddr";
+                       dev-handle = <&ddr2>;
+                       reg = <0x13000 0x1000>;
+               };
+               dcsr-nal@18000 {
+                       compatible = "fsl,p4080-dcsr-nal", "fsl,dcsr-nal";
+                       reg = <0x18000 0x1000>;
+               };
+               dcsr-rcpm@22000 {
+                       compatible = "fsl,p4080-dcsr-rcpm", "fsl,dcsr-rcpm";
+                       reg = <0x22000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@40000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu0>;
+                       reg = <0x40000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@41000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu1>;
+                       reg = <0x41000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@42000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu2>;
+                       reg = <0x42000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@43000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu3>;
+                       reg = <0x43000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@44000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu4>;
+                       reg = <0x44000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@45000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu5>;
+                       reg = <0x45000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@46000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu6>;
+                       reg = <0x46000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@47000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu7>;
+                       reg = <0x47000 0x1000>;
+               };
+       };
+
        soc: soc@ffe000000 {
                #address-cells = <1>;
                #size-cells = <1>;
                        fsl,num-laws = <32>;
                };
 
-               memory-controller@8000 {
+               ddr1: memory-controller@8000 {
                        compatible = "fsl,qoriq-memory-controller-v4.4", "fsl,qoriq-memory-controller";
                        reg = <0x8000 0x1000>;
                        interrupts = <16 2 1 23>;
                };
 
-               memory-controller@9000 {
+               ddr2: memory-controller@9000 {
                        compatible = "fsl,qoriq-memory-controller-v4.4","fsl,qoriq-memory-controller";
                        reg = <0x9000 0x1000>;
                        interrupts = <16 2 1 22>;
index 8366e2f..e6d4099 100644 (file)
                device_type = "memory";
        };
 
+       dcsr: dcsr@f00000000 {
+               ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+       };
+
        soc: soc@ffe000000 {
                spi@110000 {
                        flash@0 {
                };
 
                board-control@3,0 {
-                       compatible = "fsl,p5020ds-pixis";
-                       reg = <3 0 0x20>;
+                       compatible = "fsl,p5020ds-fpga", "fsl,fpga-ngpixis";
+                       reg = <3 0 0x30>;
                };
        };
 
index 5e6048e..e7948ad 100644 (file)
@@ -42,6 +42,7 @@
 
        aliases {
                ccsr = &soc;
+               dcsr = &dcsr;
 
                serial0 = &serial0;
                serial1 = &serial1;
                };
        };
 
+       dcsr: dcsr@f00000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "fsl,dcsr", "simple-bus";
+
+               dcsr-epu@0 {
+                       compatible = "fsl,dcsr-epu";
+                       interrupts = <52 2 0 0
+                                     84 2 0 0
+                                     85 2 0 0>;
+                       interrupt-parent = <&mpic>;
+                       reg = <0x0 0x1000>;
+               };
+               dcsr-npc {
+                       compatible = "fsl,dcsr-npc";
+                       reg = <0x1000 0x1000 0x1000000 0x8000>;
+               };
+               dcsr-nxc@2000 {
+                       compatible = "fsl,dcsr-nxc";
+                       reg = <0x2000 0x1000>;
+               };
+               dcsr-corenet {
+                       compatible = "fsl,dcsr-corenet";
+                       reg = <0x8000 0x1000 0xB0000 0x1000>;
+               };
+               dcsr-dpaa@9000 {
+                       compatible = "fsl,p5020-dcsr-dpaa", "fsl,dcsr-dpaa";
+                       reg = <0x9000 0x1000>;
+               };
+               dcsr-ocn@11000 {
+                       compatible = "fsl,p5020-dcsr-ocn", "fsl,dcsr-ocn";
+                       reg = <0x11000 0x1000>;
+               };
+               dcsr-ddr@12000 {
+                       compatible = "fsl,dcsr-ddr";
+                       dev-handle = <&ddr1>;
+                       reg = <0x12000 0x1000>;
+               };
+               dcsr-ddr@13000 {
+                       compatible = "fsl,dcsr-ddr";
+                       dev-handle = <&ddr2>;
+                       reg = <0x13000 0x1000>;
+               };
+               dcsr-nal@18000 {
+                       compatible = "fsl,p5020-dcsr-nal", "fsl,dcsr-nal";
+                       reg = <0x18000 0x1000>;
+               };
+               dcsr-rcpm@22000 {
+                       compatible = "fsl,p5020-dcsr-rcpm", "fsl,dcsr-rcpm";
+                       reg = <0x22000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@40000 {
+                       compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu0>;
+                       reg = <0x40000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@41000 {
+                       compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu1>;
+                       reg = <0x41000 0x1000>;
+               };
+       };
+
        soc: soc@ffe000000 {
                #address-cells = <1>;
                #size-cells = <1>;
                        fsl,num-laws = <32>;
                };
 
-               memory-controller@8000 {
+               ddr1: memory-controller@8000 {
                        compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
                        reg = <0x8000 0x1000>;
                        interrupts = <16 2 1 23>;
                };
 
-               memory-controller@9000 {
+               ddr2: memory-controller@9000 {
                        compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
                        reg = <0x9000 0x1000>;
                        interrupts = <16 2 1 22>;
index 9e13ed8..72078eb 100644 (file)
        };
 
        localbus@ff705000 {
-               compatible = "fsl,mpc8560-localbus";
+               compatible = "fsl,mpc8560-localbus", "simple-bus";
                #address-cells = <2>;
                #size-cells = <1>;
                reg = <0xff705000 0x100>;       // BRx, ORx, etc.
index 6492324..30bb475 100644 (file)
                                clock-frequency = <0>; /* Filled in by zImage */
                                interrupts = <0x5 0x1>;
                                interrupt-parent = <&UIC1>;
+
+                               nor_flash@0,0 {
+                                       compatible = "amd,s29gl256n", "cfi-flash";
+                                       bank-width = <2>;
+                                       reg = <0x00000000 0x00000000 0x04000000>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+                                       partition@0 {
+                                               label = "kernel";
+                                               reg = <0x00000000 0x001e0000>;
+                                       };
+                                       partition@1e0000 {
+                                               label = "dtb";
+                                               reg = <0x001e0000 0x00020000>;
+                                       };
+                                       partition@200000 {
+                                               label = "ramdisk";
+                                               reg = <0x00200000 0x01400000>;
+                                       };
+                                       partition@1600000 {
+                                               label = "jffs2";
+                                               reg = <0x01600000 0x00400000>;
+                                       };
+                                       partition@1a00000 {
+                                               label = "user";
+                                               reg = <0x01a00000 0x02540000>;
+                                       };
+                                       partition@3f40000 {
+                                               label = "env";
+                                               reg = <0x03f40000 0x00040000>;
+                                       };
+                                       partition@3f80000 {
+                                               label = "u-boot";
+                                               reg = <0x03f80000 0x00080000>;
+                                       };
+                               };
                        };
 
                        UART0: serial@ef600300 {
diff --git a/arch/powerpc/configs/40x/hcu4_defconfig b/arch/powerpc/configs/40x/hcu4_defconfig
deleted file mode 100644 (file)
index dba263c..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-CONFIG_40x=y
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_HCU4=y
-# CONFIG_WALNUT is not set
-CONFIG_SPARSE_IRQ=y
-CONFIG_PCI=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_CONNECTOR=y
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_OF_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=m
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_PROC_DEVICETREE=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=35000
-CONFIG_NETDEVICES=y
-CONFIG_ETHERNET=y
-CONFIG_NET_VENDOR_IBM=y
-CONFIG_IBM_EMAC=y
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_OF_PLATFORM=y
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-# CONFIG_USB_SUPPORT is not set
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DETECT_HUNG_TASK=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_DES=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
index 3ff5a81..c091aaf 100644 (file)
@@ -24,7 +24,7 @@ CONFIG_P1023_RDS=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
 CONFIG_CPM2=y
-CONFIG_MPC8xxx_GPIO=y
+CONFIG_GPIO_MPC8XXX=y
 CONFIG_HIGHMEM=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
index 5ea3124..1cd6fcb 100644 (file)
@@ -20,7 +20,7 @@ CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_XES_MPC85xx=y
-CONFIG_MPC8xxx_GPIO=y
+CONFIG_GPIO_MPC8XXX=y
 CONFIG_HIGHMEM=y
 CONFIG_MATH_EMULATION=y
 CONFIG_SPARSE_IRQ=y
index 4311d02..f087de6 100644 (file)
@@ -12,9 +12,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_EMBEDDED=y
 CONFIG_PERF_EVENTS=y
 CONFIG_SLAB=y
@@ -23,8 +21,9 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
-CONFIG_P2040_RDB=y
+CONFIG_P2041_RDB=y
 CONFIG_P3041_DS=y
+CONFIG_P3060_QDS=y
 CONFIG_P4080_DS=y
 CONFIG_P5020_DS=y
 CONFIG_HIGHMEM=y
@@ -69,7 +68,6 @@ CONFIG_IPV6=y
 CONFIG_IP_SCTP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
@@ -107,7 +105,6 @@ CONFIG_FSL_PQ_MDIO=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_SERIO_LIBPS2=y
 # CONFIG_LEGACY_PTYS is not set
-CONFIG_PPC_EPAPR_HV_BYTECHAN=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_EXTENDED=y
@@ -136,8 +133,6 @@ CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
 CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
-CONFIG_MMC_SDHCI_OF=y
-CONFIG_MMC_SDHCI_OF_ESDHC=y
 CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_EDAC_MPC85XX=y
@@ -146,7 +141,6 @@ CONFIG_RTC_DRV_DS3232=y
 CONFIG_RTC_DRV_CMOS=y
 CONFIG_UIO=y
 CONFIG_STAGING=y
-# CONFIG_STAGING_EXCLUDE_BUILD is not set
 CONFIG_VIRT_DRIVERS=y
 CONFIG_FSL_HV_MANAGER=y
 CONFIG_EXT2_FS=y
@@ -173,7 +167,6 @@ CONFIG_MAC_PARTITION=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_UTF8=m
 CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
index c92c204..782822c 100644 (file)
@@ -11,10 +11,8 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
@@ -25,7 +23,6 @@ CONFIG_P5020_DS=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BINFMT_MISC=m
-# CONFIG_PCI is not set
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -93,10 +90,8 @@ CONFIG_CRC_T10DIF=y
 CONFIG_CRC_ITU_T=m
 CONFIG_FRAME_WARN=1024
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_VIRQ_DEBUG=y
 CONFIG_CRYPTO_PCBC=m
index 6cb588a..0d36b0e 100644 (file)
@@ -1,15 +1,22 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
 CONFIG_SPARSE_IRQ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EXPERT=y
+# CONFIG_RD_GZIP is not set
 CONFIG_KALLSYMS_ALL=y
+# CONFIG_PCSPKR_PLATFORM is not set
+CONFIG_EMBEDDED=y
 CONFIG_SLAB=y
 # CONFIG_IOSCHED_CFQ is not set
+# CONFIG_PPC_PMAC is not set
 CONFIG_PPC_82xx=y
 CONFIG_MGCOGE=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BINFMT_MISC=y
 # CONFIG_SECCOMP is not set
 CONFIG_NET=y
@@ -24,11 +31,10 @@ CONFIG_SYN_COOKIES=y
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
 CONFIG_NETFILTER=y
+CONFIG_TIPC=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLKDEVS=y
@@ -42,7 +48,6 @@ CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
-# CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
 CONFIG_FIXED_PHY=y
 CONFIG_NET_ETHERNET=y
@@ -50,6 +55,7 @@ CONFIG_FS_ENET=y
 CONFIG_FS_ENET_MDIO_FCC=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -57,24 +63,24 @@ CONFIG_SERIAL_CPM=y
 CONFIG_SERIAL_CPM_CONSOLE=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
-# CONFIG_I2C_POWERMAC is not set
 CONFIG_I2C_CPM=y
 # CONFIG_HWMON is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB_GADGET=y
+CONFIG_USB_FSL_USB2=y
+CONFIG_USB_G_SERIAL=y
+CONFIG_UIO=y
+CONFIG_UIO_PDRV=y
 CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-# CONFIG_EXT3_FS_XATTR is not set
 CONFIG_AUTOFS4_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_CRAMFS=y
+CONFIG_SQUASHFS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
 CONFIG_PARTITION_ADVANCED=y
-# CONFIG_MAC_PARTITION is not set
 CONFIG_NLS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
@@ -82,7 +88,6 @@ CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_UTF8=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_DEBUG_INFO=y
 CONFIG_SYSCTL_SYSCALL_CHECK=y
index c02bbb2..211fcc9 100644 (file)
@@ -1,9 +1,9 @@
 CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
+CONFIG_SPARSE_IRQ=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
@@ -13,10 +13,11 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_PPC_CHRP is not set
 CONFIG_PPC_MPC512x=y
 CONFIG_MPC5121_ADS=y
+CONFIG_MPC5121_GENERIC=y
+CONFIG_PDM360NG=y
 # CONFIG_PPC_PMAC is not set
 CONFIG_NO_HZ=y
 CONFIG_HZ_1000=y
-CONFIG_SPARSE_IRQ=y
 # CONFIG_MIGRATION is not set
 # CONFIG_SECCOMP is not set
 # CONFIG_PCI is not set
@@ -35,18 +36,16 @@ CONFIG_CAN=y
 CONFIG_CAN_RAW=y
 CONFIG_CAN_BCM=y
 CONFIG_CAN_VCAN=y
-CONFIG_CAN_DEV=y
 CONFIG_CAN_MSCAN=y
 CONFIG_CAN_DEBUG_DEVICES=y
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_OF_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
@@ -63,6 +62,7 @@ CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_BLK_DEV_XIP=y
 CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
@@ -99,10 +99,14 @@ CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MPC=y
+CONFIG_SPI=y
+CONFIG_SPI_MPC512x_PSC=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_MPC8XXX=y
 # CONFIG_HWMON is not set
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_VIDEO_DEV=y
-# CONFIG_VIDEO_ALLOW_V4L1 is not set
 CONFIG_VIDEO_ADV_DEBUG=y
 # CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
 CONFIG_VIDEO_SAA711X=y
@@ -132,6 +136,5 @@ CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
index e63f537..2a1320f 100644 (file)
@@ -88,6 +88,18 @@ CONFIG_FB_RADEON=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_PCI is not set
+# CONFIG_SND_PPC is not set
+# CONFIG_SND_SPI is not set
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_MPC5200_I2S=y
+CONFIG_SND_MPC52xx_SOC_PCM030=y
+CONFIG_SND_MPC52xx_SOC_EFIKA=y
 CONFIG_HID_DRAGONRISE=y
 CONFIG_HID_GYRATION=y
 CONFIG_HID_TWINHAN=y
index a3467bf..a1e5a17 100644 (file)
@@ -10,10 +10,8 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
@@ -41,7 +39,6 @@ CONFIG_TQM8560=y
 CONFIG_SBC8548=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
-CONFIG_MPC8xxx_GPIO=y
 CONFIG_HIGHMEM=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -123,6 +120,7 @@ CONFIG_NVRAM=y
 CONFIG_I2C=y
 CONFIG_I2C_CPM=m
 CONFIG_I2C_MPC=y
+CONFIG_GPIO_MPC8XXX=y
 # CONFIG_HWMON is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_FB=y
@@ -206,7 +204,6 @@ CONFIG_PARTITION_ADVANCED=y
 CONFIG_MAC_PARTITION=y
 CONFIG_CRC_T10DIF=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
 CONFIG_SYSCTL_SYSCALL_CHECK=y
index 9693f6e..dd1e413 100644 (file)
@@ -12,10 +12,8 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
@@ -42,7 +40,6 @@ CONFIG_TQM8560=y
 CONFIG_SBC8548=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
-CONFIG_MPC8xxx_GPIO=y
 CONFIG_HIGHMEM=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -124,6 +121,7 @@ CONFIG_NVRAM=y
 CONFIG_I2C=y
 CONFIG_I2C_CPM=m
 CONFIG_I2C_MPC=y
+CONFIG_GPIO_MPC8XXX=y
 # CONFIG_HWMON is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_FB=y
@@ -207,10 +205,8 @@ CONFIG_PARTITION_ADVANCED=y
 CONFIG_MAC_PARTITION=y
 CONFIG_CRC_T10DIF=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_VIRQ_DEBUG=y
 CONFIG_CRYPTO_PCBC=m
index 7cb703b..1eb19ac 100644 (file)
@@ -14,7 +14,6 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_PPC4xx_GPIO=y
 CONFIG_ACADIA=y
 CONFIG_EP405=y
-CONFIG_HCU4=y
 CONFIG_HOTFOOT=y
 CONFIG_KILAUEA=y
 CONFIG_MAKALU=y
index 04360f9..c47f2be 100644 (file)
@@ -70,7 +70,7 @@ CONFIG_TAU_AVERAGE=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
 CONFIG_PPC_BESTCOMM=y
-CONFIG_MPC8xxx_GPIO=y
+CONFIG_GPIO_MPC8XXX=y
 CONFIG_MCU_MPC8349EMITX=m
 CONFIG_HIGHMEM=y
 CONFIG_NO_HZ=y
index 16d25c0..d57c08a 100644 (file)
@@ -37,4 +37,6 @@ struct pdev_archdata {
        u64 dma_mask;
 };
 
+#define ARCH_HAS_DMA_GET_REQUIRED_MASK
+
 #endif /* _ASM_POWERPC_DEVICE_H */
index 3a6c586..14db29b 100644 (file)
@@ -48,6 +48,8 @@
 #define FW_FEATURE_CMO         ASM_CONST(0x0000000002000000)
 #define FW_FEATURE_VPHN                ASM_CONST(0x0000000004000000)
 #define FW_FEATURE_XCMO                ASM_CONST(0x0000000008000000)
+#define FW_FEATURE_OPAL                ASM_CONST(0x0000000010000000)
+#define FW_FEATURE_OPALv2      ASM_CONST(0x0000000020000000)
 
 #ifndef __ASSEMBLY__
 
@@ -65,6 +67,8 @@ enum {
        FW_FEATURE_PSERIES_ALWAYS = 0,
        FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
        FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
+       FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_OPALv2,
+       FW_FEATURE_POWERNV_ALWAYS = 0,
        FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
        FW_FEATURE_PS3_ALWAYS = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
        FW_FEATURE_CELLEB_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_BEAT,
@@ -78,6 +82,9 @@ enum {
 #ifdef CONFIG_PPC_ISERIES
                FW_FEATURE_ISERIES_POSSIBLE |
 #endif
+#ifdef CONFIG_PPC_POWERNV
+               FW_FEATURE_POWERNV_POSSIBLE |
+#endif
 #ifdef CONFIG_PPC_PS3
                FW_FEATURE_PS3_POSSIBLE |
 #endif
@@ -95,6 +102,9 @@ enum {
 #ifdef CONFIG_PPC_ISERIES
                FW_FEATURE_ISERIES_ALWAYS &
 #endif
+#ifdef CONFIG_PPC_POWERNV
+               FW_FEATURE_POWERNV_ALWAYS &
+#endif
 #ifdef CONFIG_PPC_PS3
                FW_FEATURE_PS3_ALWAYS &
 #endif
index 5856a66..8600493 100644 (file)
@@ -1,15 +1,60 @@
 #ifndef _ASM_POWERPC_HUGETLB_H
 #define _ASM_POWERPC_HUGETLB_H
 
+#ifdef CONFIG_HUGETLB_PAGE
 #include <asm/page.h>
 
+extern struct kmem_cache *hugepte_cache;
+extern void __init reserve_hugetlb_gpages(void);
+
+static inline pte_t *hugepd_page(hugepd_t hpd)
+{
+       BUG_ON(!hugepd_ok(hpd));
+       return (pte_t *)((hpd.pd & ~HUGEPD_SHIFT_MASK) | PD_HUGE);
+}
+
+static inline unsigned int hugepd_shift(hugepd_t hpd)
+{
+       return hpd.pd & HUGEPD_SHIFT_MASK;
+}
+
+static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr,
+                                   unsigned pdshift)
+{
+       /*
+        * On 32-bit, we have multiple higher-level table entries that point to
+        * the same hugepte.  Just use the first one since they're all
+        * identical.  So for that case, idx=0.
+        */
+       unsigned long idx = 0;
+
+       pte_t *dir = hugepd_page(*hpdp);
+#ifdef CONFIG_PPC64
+       idx = (addr & ((1UL << pdshift) - 1)) >> hugepd_shift(*hpdp);
+#endif
+
+       return dir + idx;
+}
+
 pte_t *huge_pte_offset_and_shift(struct mm_struct *mm,
                                 unsigned long addr, unsigned *shift);
 
 void flush_dcache_icache_hugepage(struct page *page);
 
+#if defined(CONFIG_PPC_MM_SLICES) || defined(CONFIG_PPC_SUBPAGE_PROT)
 int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
                           unsigned long len);
+#else
+static inline int is_hugepage_only_range(struct mm_struct *mm,
+                                        unsigned long addr,
+                                        unsigned long len)
+{
+       return 0;
+}
+#endif
+
+void book3e_hugetlb_preload(struct mm_struct *mm, unsigned long ea, pte_t pte);
+void flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
 
 void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
                            unsigned long end, unsigned long floor,
@@ -50,8 +95,11 @@ static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
 static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
                                            unsigned long addr, pte_t *ptep)
 {
-       unsigned long old = pte_update(mm, addr, ptep, ~0UL, 1);
-       return __pte(old);
+#ifdef CONFIG_PPC64
+       return __pte(pte_update(mm, addr, ptep, ~0UL, 1));
+#else
+       return __pte(pte_update(ptep, ~0UL, 0));
+#endif
 }
 
 static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
@@ -93,4 +141,15 @@ static inline void arch_release_hugepage(struct page *page)
 {
 }
 
+#else /* ! CONFIG_HUGETLB_PAGE */
+static inline void reserve_hugetlb_gpages(void)
+{
+       pr_err("Cannot reserve gpages without hugetlb enabled\n");
+}
+static inline void flush_hugetlb_page(struct vm_area_struct *vma,
+                                     unsigned long vmaddr)
+{
+}
+#endif
+
 #endif /* _ASM_POWERPC_HUGETLB_H */
index 8a33698..f921eb1 100644 (file)
@@ -2,7 +2,7 @@
 #define _ASM_POWERPC_KEXEC_H
 #ifdef __KERNEL__
 
-#ifdef CONFIG_FSL_BOOKE
+#if defined(CONFIG_FSL_BOOKE) || defined(CONFIG_44x)
 
 /*
  * On FSL-BookE we setup a 1:1 mapping which covers the first 2GiB of memory
index 47cacdd..58fc216 100644 (file)
@@ -85,8 +85,9 @@ struct machdep_calls {
        void            (*pci_dma_dev_setup)(struct pci_dev *dev);
        void            (*pci_dma_bus_setup)(struct pci_bus *bus);
 
-       /* Platform set_dma_mask override */
+       /* Platform set_dma_mask and dma_get_required_mask overrides */
        int             (*dma_set_mask)(struct device *dev, u64 dma_mask);
+       u64             (*dma_get_required_mask)(struct device *dev);
 
        int             (*probe)(void);
        void            (*setup_arch)(void); /* Optional, may be NULL */
index 3ea0f9a..0260ea5 100644 (file)
@@ -66,6 +66,7 @@
 #define MAS2_M                 0x00000004
 #define MAS2_G                 0x00000002
 #define MAS2_E                 0x00000001
+#define MAS2_WIMGE_MASK                0x0000001f
 #define MAS2_EPN_MASK(size)            (~0 << (size + 10))
 #define MAS2_VAL(addr, size, flags)    ((addr) & MAS2_EPN_MASK(size) | (flags))
 
@@ -80,6 +81,7 @@
 #define MAS3_SW                        0x00000004
 #define MAS3_UR                        0x00000002
 #define MAS3_SR                        0x00000001
+#define MAS3_BAP_MASK          0x0000003f
 #define MAS3_SPSIZE            0x0000003e
 #define MAS3_SPSIZE_SHIFT      1
 
@@ -212,6 +214,11 @@ typedef struct {
        unsigned int    id;
        unsigned int    active;
        unsigned long   vdso_base;
+#ifdef CONFIG_PPC_MM_SLICES
+       u64 low_slices_psize;   /* SLB page size encodings */
+       u64 high_slices_psize;  /* 4 bits per slice for now */
+       u16 user_psize;         /* page size index */
+#endif
 } mm_context_t;
 
 /* Page size definitions, common between 32 and 64-bit
index b445e0a..db645ec 100644 (file)
@@ -262,8 +262,7 @@ extern void hash_failure_debug(unsigned long ea, unsigned long access,
 extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
                             unsigned long pstart, unsigned long prot,
                             int psize, int ssize);
-extern void add_gpage(unsigned long addr, unsigned long page_size,
-                         unsigned long number_of_pages);
+extern void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages);
 extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr);
 
 extern void hpte_init_native(void);
index 698b306..f014552 100644 (file)
@@ -175,14 +175,16 @@ extern u64 ppc64_rma_size;
 #define MMU_PAGE_64K_AP        3       /* "Admixed pages" (hash64 only) */
 #define MMU_PAGE_256K  4
 #define MMU_PAGE_1M    5
-#define MMU_PAGE_8M    6
-#define MMU_PAGE_16M   7
-#define MMU_PAGE_256M  8
-#define MMU_PAGE_1G    9
-#define MMU_PAGE_16G   10
-#define MMU_PAGE_64G   11
-#define MMU_PAGE_COUNT 12
-
+#define MMU_PAGE_4M    6
+#define MMU_PAGE_8M    7
+#define MMU_PAGE_16M   8
+#define MMU_PAGE_64M   9
+#define MMU_PAGE_256M  10
+#define MMU_PAGE_1G    11
+#define MMU_PAGE_16G   12
+#define MMU_PAGE_64G   13
+
+#define MMU_PAGE_COUNT 14
 
 #if defined(CONFIG_PPC_STD_MMU_64)
 /* 64-bit classic hash table MMU */
index df18989..e6fae49 100644 (file)
@@ -273,8 +273,6 @@ struct mpic
        unsigned int            irq_count;
        /* Number of sources */
        unsigned int            num_sources;
-       /* Number of CPUs */
-       unsigned int            num_cpus;
        /* default senses array */
        unsigned char           *senses;
        unsigned int            senses_count;
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
new file mode 100644 (file)
index 0000000..2893e8f
--- /dev/null
@@ -0,0 +1,443 @@
+/*
+ * PowerNV OPAL definitions.
+ *
+ * Copyright 2011 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.
+ */
+
+#ifndef __OPAL_H
+#define __OPAL_H
+
+/****** Takeover interface ********/
+
+/* PAPR H-Call used to querty the HAL existence and/or instanciate
+ * it from within pHyp (tech preview only).
+ *
+ * This is exclusively used in prom_init.c
+ */
+
+#ifndef __ASSEMBLY__
+
+struct opal_takeover_args {
+       u64     k_image;                /* r4 */
+       u64     k_size;                 /* r5 */
+       u64     k_entry;                /* r6 */
+       u64     k_entry2;               /* r7 */
+       u64     hal_addr;               /* r8 */
+       u64     rd_image;               /* r9 */
+       u64     rd_size;                /* r10 */
+       u64     rd_loc;                 /* r11 */
+};
+
+extern long opal_query_takeover(u64 *hal_size, u64 *hal_align);
+
+extern long opal_do_takeover(struct opal_takeover_args *args);
+
+struct rtas_args;
+extern int opal_enter_rtas(struct rtas_args *args,
+                          unsigned long data,
+                          unsigned long entry);
+
+#endif /* __ASSEMBLY__ */
+
+/****** OPAL APIs ******/
+
+/* Return codes */
+#define OPAL_SUCCESS           0
+#define OPAL_PARAMETER         -1
+#define OPAL_BUSY              -2
+#define OPAL_PARTIAL           -3
+#define OPAL_CONSTRAINED       -4
+#define OPAL_CLOSED            -5
+#define OPAL_HARDWARE          -6
+#define OPAL_UNSUPPORTED       -7
+#define OPAL_PERMISSION                -8
+#define OPAL_NO_MEM            -9
+#define OPAL_RESOURCE          -10
+#define OPAL_INTERNAL_ERROR    -11
+#define OPAL_BUSY_EVENT                -12
+#define OPAL_HARDWARE_FROZEN   -13
+
+/* API Tokens (in r0) */
+#define OPAL_CONSOLE_WRITE                     1
+#define OPAL_CONSOLE_READ                      2
+#define OPAL_RTC_READ                          3
+#define OPAL_RTC_WRITE                         4
+#define OPAL_CEC_POWER_DOWN                    5
+#define OPAL_CEC_REBOOT                                6
+#define OPAL_READ_NVRAM                                7
+#define OPAL_WRITE_NVRAM                       8
+#define OPAL_HANDLE_INTERRUPT                  9
+#define OPAL_POLL_EVENTS                       10
+#define OPAL_PCI_SET_HUB_TCE_MEMORY            11
+#define OPAL_PCI_SET_PHB_TCE_MEMORY            12
+#define OPAL_PCI_CONFIG_READ_BYTE              13
+#define OPAL_PCI_CONFIG_READ_HALF_WORD         14
+#define OPAL_PCI_CONFIG_READ_WORD              15
+#define OPAL_PCI_CONFIG_WRITE_BYTE             16
+#define OPAL_PCI_CONFIG_WRITE_HALF_WORD                17
+#define OPAL_PCI_CONFIG_WRITE_WORD             18
+#define OPAL_SET_XIVE                          19
+#define OPAL_GET_XIVE                          20
+#define OPAL_GET_COMPLETION_TOKEN_STATUS       21 /* obsolete */
+#define OPAL_REGISTER_OPAL_EXCEPTION_HANDLER   22
+#define OPAL_PCI_EEH_FREEZE_STATUS             23
+#define OPAL_PCI_SHPC                          24
+#define OPAL_CONSOLE_WRITE_BUFFER_SPACE                25
+#define OPAL_PCI_EEH_FREEZE_CLEAR              26
+#define OPAL_PCI_PHB_MMIO_ENABLE               27
+#define OPAL_PCI_SET_PHB_MEM_WINDOW            28
+#define OPAL_PCI_MAP_PE_MMIO_WINDOW            29
+#define OPAL_PCI_SET_PHB_TABLE_MEMORY          30
+#define OPAL_PCI_SET_PE                                31
+#define OPAL_PCI_SET_PELTV                     32
+#define OPAL_PCI_SET_MVE                       33
+#define OPAL_PCI_SET_MVE_ENABLE                        34
+#define OPAL_PCI_GET_XIVE_REISSUE              35
+#define OPAL_PCI_SET_XIVE_REISSUE              36
+#define OPAL_PCI_SET_XIVE_PE                   37
+#define OPAL_GET_XIVE_SOURCE                   38
+#define OPAL_GET_MSI_32                                39
+#define OPAL_GET_MSI_64                                40
+#define OPAL_START_CPU                         41
+#define OPAL_QUERY_CPU_STATUS                  42
+#define OPAL_WRITE_OPPANEL                     43
+#define OPAL_PCI_MAP_PE_DMA_WINDOW             44
+#define OPAL_PCI_MAP_PE_DMA_WINDOW_REAL                45
+#define OPAL_PCI_RESET                         49
+
+#ifndef __ASSEMBLY__
+
+/* Other enums */
+enum OpalVendorApiTokens {
+       OPAL_START_VENDOR_API_RANGE = 1000, OPAL_END_VENDOR_API_RANGE = 1999
+};
+enum OpalFreezeState {
+       OPAL_EEH_STOPPED_NOT_FROZEN = 0,
+       OPAL_EEH_STOPPED_MMIO_FREEZE = 1,
+       OPAL_EEH_STOPPED_DMA_FREEZE = 2,
+       OPAL_EEH_STOPPED_MMIO_DMA_FREEZE = 3,
+       OPAL_EEH_STOPPED_RESET = 4,
+       OPAL_EEH_STOPPED_TEMP_UNAVAIL = 5,
+       OPAL_EEH_STOPPED_PERM_UNAVAIL = 6
+};
+enum OpalEehFreezeActionToken {
+       OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO = 1,
+       OPAL_EEH_ACTION_CLEAR_FREEZE_DMA = 2,
+       OPAL_EEH_ACTION_CLEAR_FREEZE_ALL = 3
+};
+enum OpalPciStatusToken {
+       OPAL_EEH_PHB_NO_ERROR = 0,
+       OPAL_EEH_PHB_FATAL = 1,
+       OPAL_EEH_PHB_RECOVERABLE = 2,
+       OPAL_EEH_PHB_BUS_ERROR = 3,
+       OPAL_EEH_PCI_NO_DEVSEL = 4,
+       OPAL_EEH_PCI_TA = 5,
+       OPAL_EEH_PCIEX_UR = 6,
+       OPAL_EEH_PCIEX_CA = 7,
+       OPAL_EEH_PCI_MMIO_ERROR = 8,
+       OPAL_EEH_PCI_DMA_ERROR = 9
+};
+enum OpalShpcAction {
+       OPAL_SHPC_GET_LINK_STATE = 0,
+       OPAL_SHPC_GET_SLOT_STATE = 1
+};
+enum OpalShpcLinkState {
+       OPAL_SHPC_LINK_DOWN = 0,
+       OPAL_SHPC_LINK_UP = 1
+};
+enum OpalMmioWindowType {
+       OPAL_M32_WINDOW_TYPE = 1,
+       OPAL_M64_WINDOW_TYPE = 2,
+       OPAL_IO_WINDOW_TYPE = 3
+};
+enum OpalShpcSlotState {
+       OPAL_SHPC_DEV_NOT_PRESENT = 0,
+       OPAL_SHPC_DEV_PRESENT = 1
+};
+enum OpalExceptionHandler {
+       OPAL_MACHINE_CHECK_HANDLER = 1,
+       OPAL_HYPERVISOR_MAINTENANCE_HANDLER = 2,
+       OPAL_SOFTPATCH_HANDLER = 3
+};
+enum OpalPendingState {
+       OPAL_EVENT_OPAL_INTERNAL = 0x1,
+       OPAL_EVENT_NVRAM = 0x2,
+       OPAL_EVENT_RTC = 0x4,
+       OPAL_EVENT_CONSOLE_OUTPUT = 0x8,
+       OPAL_EVENT_CONSOLE_INPUT = 0x10
+};
+
+/* Machine check related definitions */
+enum OpalMCE_Version {
+       OpalMCE_V1 = 1,
+};
+
+enum OpalMCE_Severity {
+       OpalMCE_SEV_NO_ERROR = 0,
+       OpalMCE_SEV_WARNING = 1,
+       OpalMCE_SEV_ERROR_SYNC = 2,
+       OpalMCE_SEV_FATAL = 3,
+};
+
+enum OpalMCE_Disposition {
+       OpalMCE_DISPOSITION_RECOVERED = 0,
+       OpalMCE_DISPOSITION_NOT_RECOVERED = 1,
+};
+
+enum OpalMCE_Initiator {
+       OpalMCE_INITIATOR_UNKNOWN = 0,
+       OpalMCE_INITIATOR_CPU = 1,
+};
+
+enum OpalMCE_ErrorType {
+       OpalMCE_ERROR_TYPE_UNKNOWN = 0,
+       OpalMCE_ERROR_TYPE_UE = 1,
+       OpalMCE_ERROR_TYPE_SLB = 2,
+       OpalMCE_ERROR_TYPE_ERAT = 3,
+       OpalMCE_ERROR_TYPE_TLB = 4,
+};
+
+enum OpalMCE_UeErrorType {
+       OpalMCE_UE_ERROR_INDETERMINATE = 0,
+       OpalMCE_UE_ERROR_IFETCH = 1,
+       OpalMCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH = 2,
+       OpalMCE_UE_ERROR_LOAD_STORE = 3,
+       OpalMCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 4,
+};
+
+enum OpalMCE_SlbErrorType {
+       OpalMCE_SLB_ERROR_INDETERMINATE = 0,
+       OpalMCE_SLB_ERROR_PARITY = 1,
+       OpalMCE_SLB_ERROR_MULTIHIT = 2,
+};
+
+enum OpalMCE_EratErrorType {
+       OpalMCE_ERAT_ERROR_INDETERMINATE = 0,
+       OpalMCE_ERAT_ERROR_PARITY = 1,
+       OpalMCE_ERAT_ERROR_MULTIHIT = 2,
+};
+
+enum OpalMCE_TlbErrorType {
+       OpalMCE_TLB_ERROR_INDETERMINATE = 0,
+       OpalMCE_TLB_ERROR_PARITY = 1,
+       OpalMCE_TLB_ERROR_MULTIHIT = 2,
+};
+
+enum OpalThreadStatus {
+       OPAL_THREAD_INACTIVE = 0x0,
+       OPAL_THREAD_STARTED = 0x1
+};
+
+enum OpalPciBusCompare {
+       OpalPciBusAny   = 0,    /* Any bus number match */
+       OpalPciBus3Bits = 2,    /* Match top 3 bits of bus number */
+       OpalPciBus4Bits = 3,    /* Match top 4 bits of bus number */
+       OpalPciBus5Bits = 4,    /* Match top 5 bits of bus number */
+       OpalPciBus6Bits = 5,    /* Match top 6 bits of bus number */
+       OpalPciBus7Bits = 6,    /* Match top 7 bits of bus number */
+       OpalPciBusAll   = 7,    /* Match bus number exactly */
+};
+
+enum OpalDeviceCompare {
+       OPAL_IGNORE_RID_DEVICE_NUMBER = 0,
+       OPAL_COMPARE_RID_DEVICE_NUMBER = 1
+};
+
+enum OpalFuncCompare {
+       OPAL_IGNORE_RID_FUNCTION_NUMBER = 0,
+       OPAL_COMPARE_RID_FUNCTION_NUMBER = 1
+};
+
+enum OpalPeAction {
+       OPAL_UNMAP_PE = 0,
+       OPAL_MAP_PE = 1
+};
+
+enum OpalPciResetAndReinitScope {
+       OPAL_PHB_COMPLETE = 1, OPAL_PCI_LINK = 2, OPAL_PHB_ERROR = 3,
+       OPAL_PCI_HOT_RESET = 4, OPAL_PCI_FUNDAMENTAL_RESET = 5,
+       OPAL_PCI_IODA_RESET = 6,
+};
+
+enum OpalPciResetState { OPAL_DEASSERT_RESET = 0, OPAL_ASSERT_RESET = 1 };
+
+struct opal_machine_check_event {
+       enum OpalMCE_Version    version:8;      /* 0x00 */
+       uint8_t                 in_use;         /* 0x01 */
+       enum OpalMCE_Severity   severity:8;     /* 0x02 */
+       enum OpalMCE_Initiator  initiator:8;    /* 0x03 */
+       enum OpalMCE_ErrorType  error_type:8;   /* 0x04 */
+       enum OpalMCE_Disposition disposition:8; /* 0x05 */
+       uint8_t                 reserved_1[2];  /* 0x06 */
+       uint64_t                gpr3;           /* 0x08 */
+       uint64_t                srr0;           /* 0x10 */
+       uint64_t                srr1;           /* 0x18 */
+       union {                                 /* 0x20 */
+               struct {
+                       enum OpalMCE_UeErrorType ue_error_type:8;
+                       uint8_t         effective_address_provided;
+                       uint8_t         physical_address_provided;
+                       uint8_t         reserved_1[5];
+                       uint64_t        effective_address;
+                       uint64_t        physical_address;
+                       uint8_t         reserved_2[8];
+               } ue_error;
+
+               struct {
+                       enum OpalMCE_SlbErrorType slb_error_type:8;
+                       uint8_t         effective_address_provided;
+                       uint8_t         reserved_1[6];
+                       uint64_t        effective_address;
+                       uint8_t         reserved_2[16];
+               } slb_error;
+
+               struct {
+                       enum OpalMCE_EratErrorType erat_error_type:8;
+                       uint8_t         effective_address_provided;
+                       uint8_t         reserved_1[6];
+                       uint64_t        effective_address;
+                       uint8_t         reserved_2[16];
+               } erat_error;
+
+               struct {
+                       enum OpalMCE_TlbErrorType tlb_error_type:8;
+                       uint8_t         effective_address_provided;
+                       uint8_t         reserved_1[6];
+                       uint64_t        effective_address;
+                       uint8_t         reserved_2[16];
+               } tlb_error;
+       } u;
+};
+
+typedef struct oppanel_line {
+       /* XXX */
+} oppanel_line_t;
+
+/* API functions */
+int64_t opal_console_write(int64_t term_number, int64_t *length,
+                          const uint8_t *buffer);
+int64_t opal_console_read(int64_t term_number, int64_t *length,
+                         uint8_t *buffer);
+int64_t opal_console_write_buffer_space(int64_t term_number,
+                                       int64_t *length);
+int64_t opal_rtc_read(uint32_t *year_month_day,
+                     uint64_t *hour_minute_second_millisecond);
+int64_t opal_rtc_write(uint32_t year_month_day,
+                      uint64_t hour_minute_second_millisecond);
+int64_t opal_cec_power_down(uint64_t request);
+int64_t opal_cec_reboot(void);
+int64_t opal_read_nvram(uint64_t buffer, uint64_t size, uint64_t offset);
+int64_t opal_write_nvram(uint64_t buffer, uint64_t size, uint64_t offset);
+int64_t opal_handle_interrupt(uint64_t isn, uint64_t *outstanding_event_mask);
+int64_t opal_poll_events(uint64_t *outstanding_event_mask);
+int64_t opal_pci_set_hub_tce_memory(uint64_t hub_id, uint64_t tce_mem_addr,
+                                   uint64_t tce_mem_size);
+int64_t opal_pci_set_phb_tce_memory(uint64_t phb_id, uint64_t tce_mem_addr,
+                                   uint64_t tce_mem_size);
+int64_t opal_pci_config_read_byte(uint64_t phb_id, uint64_t bus_dev_func,
+                                 uint64_t offset, uint8_t *data);
+int64_t opal_pci_config_read_half_word(uint64_t phb_id, uint64_t bus_dev_func,
+                                      uint64_t offset, uint16_t *data);
+int64_t opal_pci_config_read_word(uint64_t phb_id, uint64_t bus_dev_func,
+                                 uint64_t offset, uint32_t *data);
+int64_t opal_pci_config_write_byte(uint64_t phb_id, uint64_t bus_dev_func,
+                                  uint64_t offset, uint8_t data);
+int64_t opal_pci_config_write_half_word(uint64_t phb_id, uint64_t bus_dev_func,
+                                       uint64_t offset, uint16_t data);
+int64_t opal_pci_config_write_word(uint64_t phb_id, uint64_t bus_dev_func,
+                                  uint64_t offset, uint32_t data);
+int64_t opal_set_xive(uint32_t isn, uint16_t server, uint8_t priority);
+int64_t opal_get_xive(uint32_t isn, uint16_t *server, uint8_t *priority);
+int64_t opal_register_exception_handler(uint64_t opal_exception,
+                                       uint64_t handler_address,
+                                       uint64_t glue_cache_line);
+int64_t opal_pci_eeh_freeze_status(uint64_t phb_id, uint64_t pe_number,
+                                  uint8_t *freeze_state,
+                                  uint16_t *pci_error_type,
+                                  uint64_t *phb_status);
+int64_t opal_pci_eeh_freeze_clear(uint64_t phb_id, uint64_t pe_number,
+                                 uint64_t eeh_action_token);
+int64_t opal_pci_shpc(uint64_t phb_id, uint64_t shpc_action, uint8_t *state);
+
+
+
+int64_t opal_pci_phb_mmio_enable(uint64_t phb_id, uint16_t window_type,
+                                uint16_t window_num, uint16_t enable);
+int64_t opal_pci_set_phb_mem_window(uint64_t phb_id, uint16_t window_type,
+                                   uint16_t window_num,
+                                   uint64_t starting_real_address,
+                                   uint64_t starting_pci_address,
+                                   uint16_t segment_size);
+int64_t opal_pci_map_pe_mmio_window(uint64_t phb_id, uint16_t pe_number,
+                                   uint16_t window_type, uint16_t window_num,
+                                   uint16_t segment_num);
+int64_t opal_pci_set_phb_table_memory(uint64_t phb_id, uint64_t rtt_addr,
+                                     uint64_t ivt_addr, uint64_t ivt_len,
+                                     uint64_t reject_array_addr,
+                                     uint64_t peltv_addr);
+int64_t opal_pci_set_pe(uint64_t phb_id, uint64_t pe_number, uint64_t bus_dev_func,
+                       uint8_t bus_compare, uint8_t dev_compare, uint8_t func_compare,
+                       uint8_t pe_action);
+int64_t opal_pci_set_peltv(uint64_t phb_id, uint32_t parent_pe, uint32_t child_pe,
+                          uint8_t state);
+int64_t opal_pci_set_mve(uint64_t phb_id, uint32_t mve_number, uint32_t pe_number);
+int64_t opal_pci_set_mve_enable(uint64_t phb_id, uint32_t mve_number,
+                               uint32_t state);
+int64_t opal_pci_get_xive_reissue(uint64_t phb_id, uint32_t xive_number,
+                                 uint8_t *p_bit, uint8_t *q_bit);
+int64_t opal_pci_set_xive_reissue(uint64_t phb_id, uint32_t xive_number,
+                                 uint8_t p_bit, uint8_t q_bit);
+int64_t opal_pci_set_xive_pe(uint64_t phb_id, uint32_t pe_number,
+                            uint32_t xive_num);
+int64_t opal_get_xive_source(uint64_t phb_id, uint32_t xive_num,
+                            int32_t *interrupt_source_number);
+int64_t opal_get_msi_32(uint64_t phb_id, uint32_t mve_number, uint32_t xive_num,
+                       uint8_t msi_range, uint32_t *msi_address,
+                       uint32_t *message_data);
+int64_t opal_get_msi_64(uint64_t phb_id, uint32_t mve_number,
+                       uint32_t xive_num, uint8_t msi_range,
+                       uint64_t *msi_address, uint32_t *message_data);
+int64_t opal_start_cpu(uint64_t thread_number, uint64_t start_address);
+int64_t opal_query_cpu_status(uint64_t thread_number, uint8_t *thread_status);
+int64_t opal_write_oppanel(oppanel_line_t *lines, uint64_t num_lines);
+int64_t opal_pci_map_pe_dma_window(uint64_t phb_id, uint16_t pe_number, uint16_t window_id,
+                                  uint16_t tce_levels, uint64_t tce_table_addr,
+                                  uint64_t tce_table_size, uint64_t tce_page_size);
+int64_t opal_pci_map_pe_dma_window_real(uint64_t phb_id, uint16_t pe_number,
+                                       uint16_t dma_window_number, uint64_t pci_start_addr,
+                                       uint64_t pci_mem_size);
+int64_t opal_pci_reset(uint64_t phb_id, uint8_t reset_scope, uint8_t assert_state);
+
+/* Internal functions */
+extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
+
+extern int opal_get_chars(uint32_t vtermno, char *buf, int count);
+extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len);
+
+extern void hvc_opal_init_early(void);
+
+/* Internal functions */
+extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
+                                  int depth, void *data);
+
+extern int opal_get_chars(uint32_t vtermno, char *buf, int count);
+extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len);
+
+extern void hvc_opal_init_early(void);
+
+struct rtc_time;
+extern int opal_set_rtc_time(struct rtc_time *tm);
+extern void opal_get_rtc_time(struct rtc_time *tm);
+extern unsigned long opal_get_boot_time(void);
+extern void opal_nvram_init(void);
+
+extern int opal_machine_check(struct pt_regs *regs);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __OPAL_H */
index 516bfb3..17722c7 100644 (file)
@@ -43,6 +43,7 @@ extern unsigned int debug_smp_processor_id(void); /* from linux/smp.h */
 #define get_slb_shadow()       (get_paca()->slb_shadow_ptr)
 
 struct task_struct;
+struct opal_machine_check_event;
 
 /*
  * Defines the layout of the paca.
@@ -135,6 +136,13 @@ struct paca_struct {
        u8 io_sync;                     /* writel() needs spin_unlock sync */
        u8 irq_work_pending;            /* IRQ_WORK interrupt while soft-disable */
 
+#ifdef CONFIG_PPC_POWERNV
+       /* Pointer to OPAL machine check event structure set by the
+        * early exception handler for use by high level C handler
+        */
+       struct opal_machine_check_event *opal_mc_evt;
+#endif
+
        /* Stuff for accurate time accounting */
        u64 user_time;                  /* accumulated usermode TB ticks */
        u64 system_time;                /* accumulated system TB ticks */
index 2cd664e..dd9c4fd 100644 (file)
 
 #define PAGE_SIZE              (ASM_CONST(1) << PAGE_SHIFT)
 
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_HUGETLB_PAGE
+extern unsigned int HPAGE_SHIFT;
+#else
+#define HPAGE_SHIFT PAGE_SHIFT
+#endif
+#define HPAGE_SIZE             ((1UL) << HPAGE_SHIFT)
+#define HPAGE_MASK             (~(HPAGE_SIZE - 1))
+#define HUGETLB_PAGE_ORDER     (HPAGE_SHIFT - PAGE_SHIFT)
+#define HUGE_MAX_HSTATE                (MMU_PAGE_COUNT-1)
+#endif
+
 /* We do define AT_SYSINFO_EHDR but don't use the gate mechanism */
 #define __HAVE_ARCH_GATE_AREA          1
 
@@ -158,6 +170,24 @@ extern phys_addr_t kernstart_addr;
 #define is_kernel_addr(x)      ((x) >= PAGE_OFFSET)
 #endif
 
+/*
+ * Use the top bit of the higher-level page table entries to indicate whether
+ * the entries we point to contain hugepages.  This works because we know that
+ * the page tables live in kernel space.  If we ever decide to support having
+ * page tables at arbitrary addresses, this breaks and will have to change.
+ */
+#ifdef CONFIG_PPC64
+#define PD_HUGE 0x8000000000000000
+#else
+#define PD_HUGE 0x80000000
+#endif
+
+/*
+ * Some number of bits at the level of the page table that points to
+ * a hugepte are used to encode the size.  This masks those bits.
+ */
+#define HUGEPD_SHIFT_MASK     0x3f
+
 #ifndef __ASSEMBLY__
 
 #undef STRICT_MM_TYPECHECKS
@@ -243,7 +273,6 @@ typedef unsigned long pgprot_t;
 #endif
 
 typedef struct { signed long pd; } hugepd_t;
-#define HUGEPD_SHIFT_MASK     0x3f
 
 #ifdef CONFIG_HUGETLB_PAGE
 static inline int hugepd_ok(hugepd_t hpd)
index 9356262..fb40ede 100644 (file)
@@ -64,17 +64,6 @@ extern void copy_page(void *to, void *from);
 /* Log 2 of page table size */
 extern u64 ppc64_pft_size;
 
-/* Large pages size */
-#ifdef CONFIG_HUGETLB_PAGE
-extern unsigned int HPAGE_SHIFT;
-#else
-#define HPAGE_SHIFT PAGE_SHIFT
-#endif
-#define HPAGE_SIZE             ((1UL) << HPAGE_SHIFT)
-#define HPAGE_MASK             (~(HPAGE_SIZE - 1))
-#define HUGETLB_PAGE_ORDER     (HPAGE_SHIFT - PAGE_SHIFT)
-#define HUGE_MAX_HSTATE                (MMU_PAGE_COUNT-1)
-
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_PPC_MM_SLICES
index 082d515..0156702 100644 (file)
@@ -72,6 +72,9 @@
 #define        PTE_RPN_SHIFT   (24)
 #endif
 
+#define PTE_WIMGE_SHIFT (19)
+#define PTE_BAP_SHIFT  (2)
+
 /* On 32-bit, we never clear the top part of the PTE */
 #ifdef CONFIG_PPC32
 #define _PTE_NONE_MASK 0xffffffff00000000ULL
index 9ec0b39..28cdbd9 100644 (file)
 #define L1CSR1_ICFI    0x00000002      /* Instr Cache Flash Invalidate */
 #define L1CSR1_ICE     0x00000001      /* Instr Cache Enable */
 
+/* Bit definitions for L1CSR2. */
+#define L1CSR2_DCWS    0x40000000      /* Data Cache write shadow */
+
 /* Bit definitions for L2CSR0. */
 #define L2CSR0_L2E     0x80000000      /* L2 Cache Enable */
 #define L2CSR0_L2PE    0x40000000      /* L2 Cache Parity/ECC Enable */
index 58625d1..41f69ae 100644 (file)
@@ -249,10 +249,12 @@ extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal);
 #define ERR_FLAG_ALREADY_LOGGED        0x0
 #define ERR_FLAG_BOOT          0x1     /* log was pulled from NVRAM on boot */
 #define ERR_TYPE_RTAS_LOG      0x2     /* from rtas event-scan */
-#define ERR_TYPE_KERNEL_PANIC  0x4     /* from panic() */
+#define ERR_TYPE_KERNEL_PANIC  0x4     /* from die()/panic() */
+#define ERR_TYPE_KERNEL_PANIC_GZ 0x8   /* ditto, compressed */
 
 /* All the types and not flags */
-#define ERR_TYPE_MASK  (ERR_TYPE_RTAS_LOG | ERR_TYPE_KERNEL_PANIC)
+#define ERR_TYPE_MASK \
+       (ERR_TYPE_RTAS_LOG | ERR_TYPE_KERNEL_PANIC | ERR_TYPE_KERNEL_PANIC_GZ)
 
 #define RTAS_DEBUG KERN_DEBUG "RTAS: "
  
index 15a70b7..adba970 100644 (file)
@@ -65,6 +65,7 @@ int generic_cpu_disable(void);
 void generic_cpu_die(unsigned int cpu);
 void generic_mach_cpu_die(void);
 void generic_set_cpu_dead(unsigned int cpu);
+int generic_check_cpu_restart(unsigned int cpu);
 #endif
 
 #ifdef CONFIG_PPC64
index 54a47ea..0c5fa31 100644 (file)
@@ -16,7 +16,7 @@
 #endif /* CONFIG_SPARSEMEM */
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-extern void create_section_mapping(unsigned long start, unsigned long end);
+extern int create_section_mapping(unsigned long start, unsigned long end);
 extern int remove_section_mapping(unsigned long start, unsigned long end);
 #ifdef CONFIG_NUMA
 extern int hot_add_scn_to_nid(unsigned long scn_addr);
index 7ef0d90..1e104af 100644 (file)
@@ -19,14 +19,10 @@ struct device_node;
 #define RECLAIM_DISTANCE 10
 
 /*
- * Before going off node we want the VM to try and reclaim from the local
- * node. It does this if the remote distance is larger than RECLAIM_DISTANCE.
- * With the default REMOTE_DISTANCE of 20 and the default RECLAIM_DISTANCE of
- * 20, we never reclaim and go off node straight away.
- *
- * To fix this we choose a smaller value of RECLAIM_DISTANCE.
+ * Avoid creating an extra level of balancing (SD_ALLNODES) on the largest
+ * POWER7 boxes which have a maximum of 32 nodes.
  */
-#define RECLAIM_DISTANCE 10
+#define SD_NODES_PER_DOMAIN 32
 
 #include <asm/mmzone.h>
 
@@ -69,11 +65,11 @@ static inline int pcibus_to_node(struct pci_bus *bus)
        .forkexec_idx           = 0,                                    \
                                                                        \
        .flags                  = 1*SD_LOAD_BALANCE                     \
-                               | 1*SD_BALANCE_NEWIDLE                  \
+                               | 0*SD_BALANCE_NEWIDLE                  \
                                | 1*SD_BALANCE_EXEC                     \
                                | 1*SD_BALANCE_FORK                     \
                                | 0*SD_BALANCE_WAKE                     \
-                               | 0*SD_WAKE_AFFINE                      \
+                               | 1*SD_WAKE_AFFINE                      \
                                | 0*SD_PREFER_LOCAL                     \
                                | 0*SD_SHARE_CPUPOWER                   \
                                | 0*SD_POWERSAVINGS_BALANCE             \
index 5354ae9..8338aef 100644 (file)
@@ -55,6 +55,9 @@ extern void __init udbg_init_cpm(void);
 extern void __init udbg_init_usbgecko(void);
 extern void __init udbg_init_wsp(void);
 extern void __init udbg_init_ehv_bc(void);
+extern void __init udbg_init_ps3gelic(void);
+extern void __init udbg_init_debug_opal_raw(void);
+extern void __init udbg_init_debug_opal_hvsi(void);
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_UDBG_H */
index b183a40..bd6c401 100644 (file)
 #define MAX_NUM_PRIORITIES     3
 
 /* Native ICP */
+#ifdef CONFIG_PPC_ICP_NATIVE
 extern int icp_native_init(void);
+#else
+static inline int icp_native_init(void) { return -ENODEV; }
+#endif
 
 /* PAPR ICP */
+#ifdef CONFIG_PPC_ICP_HV
 extern int icp_hv_init(void);
+#else
+static inline int icp_hv_init(void) { return -ENODEV; }
+#endif
 
 /* ICP ops */
 struct icp_ops {
@@ -51,7 +59,18 @@ extern const struct icp_ops *icp_ops;
 extern int ics_native_init(void);
 
 /* RTAS ICS */
+#ifdef CONFIG_PPC_ICS_RTAS
 extern int ics_rtas_init(void);
+#else
+static inline int ics_rtas_init(void) { return -ENODEV; }
+#endif
+
+/* HAL ICS */
+#ifdef CONFIG_PPC_POWERNV
+extern int ics_opal_init(void);
+#else
+static inline int ics_opal_init(void) { return -ENODEV; }
+#endif
 
 /* ICS instance, hooked up to chip_data of an irq */
 struct ics {
index 69f7ffe..7c5324f 100644 (file)
@@ -49,6 +49,9 @@
 #ifdef CONFIG_PPC_ISERIES
 #include <asm/iseries/alpaca.h>
 #endif
+#ifdef CONFIG_PPC_POWERNV
+#include <asm/opal.h>
+#endif
 #if defined(CONFIG_KVM) || defined(CONFIG_KVM_GUEST)
 #include <linux/kvm_host.h>
 #endif
@@ -610,5 +613,12 @@ int main(void)
                                        arch.timing_last_enter.tv32.tbl));
 #endif
 
+#ifdef CONFIG_PPC_POWERNV
+       DEFINE(OPAL_MC_GPR3, offsetof(struct opal_machine_check_event, gpr3));
+       DEFINE(OPAL_MC_SRR0, offsetof(struct opal_machine_check_event, srr0));
+       DEFINE(OPAL_MC_SRR1, offsetof(struct opal_machine_check_event, srr1));
+       DEFINE(PACA_OPAL_MC_EVT, offsetof(struct paca_struct, opal_mc_evt));
+#endif
+
        return 0;
 }
index e755415..6f04b9c 100644 (file)
@@ -90,13 +90,27 @@ static int dma_iommu_dma_supported(struct device *dev, u64 mask)
                return 1;
 }
 
+static u64 dma_iommu_get_required_mask(struct device *dev)
+{
+       struct iommu_table *tbl = get_iommu_table_base(dev);
+       u64 mask;
+       if (!tbl)
+               return 0;
+
+       mask = 1ULL < (fls_long(tbl->it_offset + tbl->it_size) - 1);
+       mask += mask - 1;
+
+       return mask;
+}
+
 struct dma_map_ops dma_iommu_ops = {
-       .alloc_coherent = dma_iommu_alloc_coherent,
-       .free_coherent  = dma_iommu_free_coherent,
-       .map_sg         = dma_iommu_map_sg,
-       .unmap_sg       = dma_iommu_unmap_sg,
-       .dma_supported  = dma_iommu_dma_supported,
-       .map_page       = dma_iommu_map_page,
-       .unmap_page     = dma_iommu_unmap_page,
+       .alloc_coherent         = dma_iommu_alloc_coherent,
+       .free_coherent          = dma_iommu_free_coherent,
+       .map_sg                 = dma_iommu_map_sg,
+       .unmap_sg               = dma_iommu_unmap_sg,
+       .dma_supported          = dma_iommu_dma_supported,
+       .map_page               = dma_iommu_map_page,
+       .unmap_page             = dma_iommu_unmap_page,
+       .get_required_mask      = dma_iommu_get_required_mask,
 };
 EXPORT_SYMBOL(dma_iommu_ops);
index 4295e0b..1ebc918 100644 (file)
 
 unsigned int ppc_swiotlb_enable;
 
+static u64 swiotlb_powerpc_get_required(struct device *dev)
+{
+       u64 end, mask, max_direct_dma_addr = dev->archdata.max_direct_dma_addr;
+
+       end = memblock_end_of_DRAM();
+       if (max_direct_dma_addr && end > max_direct_dma_addr)
+               end = max_direct_dma_addr;
+       end += get_dma_offset(dev);
+
+       mask = 1ULL << (fls64(end) - 1);
+       mask += mask - 1;
+
+       return mask;
+}
+
 /*
  * At the moment, all platforms that use this code only require
  * swiotlb to be used if we're operating on HIGHMEM.  Since
@@ -44,6 +59,7 @@ struct dma_map_ops swiotlb_dma_ops = {
        .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
        .sync_sg_for_device = swiotlb_sync_sg_for_device,
        .mapping_error = swiotlb_dma_mapping_error,
+       .get_required_mask = swiotlb_powerpc_get_required,
 };
 
 void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev)
index 4f0959f..8593f53 100644 (file)
@@ -96,6 +96,18 @@ static int dma_direct_dma_supported(struct device *dev, u64 mask)
 #endif
 }
 
+static u64 dma_direct_get_required_mask(struct device *dev)
+{
+       u64 end, mask;
+
+       end = memblock_end_of_DRAM() + get_dma_offset(dev);
+
+       mask = 1ULL << (fls64(end) - 1);
+       mask += mask - 1;
+
+       return mask;
+}
+
 static inline dma_addr_t dma_direct_map_page(struct device *dev,
                                             struct page *page,
                                             unsigned long offset,
@@ -137,13 +149,14 @@ static inline void dma_direct_sync_single(struct device *dev,
 #endif
 
 struct dma_map_ops dma_direct_ops = {
-       .alloc_coherent = dma_direct_alloc_coherent,
-       .free_coherent  = dma_direct_free_coherent,
-       .map_sg         = dma_direct_map_sg,
-       .unmap_sg       = dma_direct_unmap_sg,
-       .dma_supported  = dma_direct_dma_supported,
-       .map_page       = dma_direct_map_page,
-       .unmap_page     = dma_direct_unmap_page,
+       .alloc_coherent                 = dma_direct_alloc_coherent,
+       .free_coherent                  = dma_direct_free_coherent,
+       .map_sg                         = dma_direct_map_sg,
+       .unmap_sg                       = dma_direct_unmap_sg,
+       .dma_supported                  = dma_direct_dma_supported,
+       .map_page                       = dma_direct_map_page,
+       .unmap_page                     = dma_direct_unmap_page,
+       .get_required_mask              = dma_direct_get_required_mask,
 #ifdef CONFIG_NOT_COHERENT_CACHE
        .sync_single_for_cpu            = dma_direct_sync_single,
        .sync_single_for_device         = dma_direct_sync_single,
@@ -170,6 +183,23 @@ int dma_set_mask(struct device *dev, u64 dma_mask)
 }
 EXPORT_SYMBOL(dma_set_mask);
 
+u64 dma_get_required_mask(struct device *dev)
+{
+       struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+       if (ppc_md.dma_get_required_mask)
+               return ppc_md.dma_get_required_mask(dev);
+
+       if (unlikely(dma_ops == NULL))
+               return 0;
+
+       if (dma_ops->get_required_mask)
+               return dma_ops->get_required_mask(dev);
+
+       return DMA_BIT_MASK(8 * sizeof(dma_addr_t));
+}
+EXPORT_SYMBOL_GPL(dma_get_required_mask);
+
 static int __init dma_init(void)
 {
        dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
index 29ddd8b..a54d92f 100644 (file)
@@ -1133,7 +1133,7 @@ _GLOBAL(do_stab_bolted)
        rfid
        b       .       /* prevent speculative execution */
 
-#ifdef CONFIG_PPC_PSERIES
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
 /*
  * Data area reserved for FWNMI option.
  * This address (0x7000) is fixed by the RPA.
@@ -1141,7 +1141,7 @@ _GLOBAL(do_stab_bolted)
        .= 0x7000
        .globl fwnmi_data_area
 fwnmi_data_area:
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */
 
        /* iSeries does not use the FWNMI stuff, so it is safe to put
         * this here, even if we later allow kernels that will boot on
@@ -1166,9 +1166,12 @@ xLparMap:
 
 #endif /* CONFIG_PPC_ISERIES */
 
-#ifdef CONFIG_PPC_PSERIES
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
+       /* pseries and powernv need to keep the whole page from
+        * 0x7000 to 0x8000 free for use by the firmware
+        */
         . = 0x8000
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */
 
 /*
  * Space for CPU0's segment table.
@@ -1183,3 +1186,19 @@ xLparMap:
        .globl initial_stab
 initial_stab:
        .space  4096
+#ifdef CONFIG_PPC_POWERNV
+_GLOBAL(opal_mc_secondary_handler)
+       HMT_MEDIUM
+       SET_SCRATCH0(r13)
+       GET_PACA(r13)
+       clrldi  r3,r3,2
+       tovirt(r3,r3)
+       std     r3,PACA_OPAL_MC_EVT(r13)
+       ld      r13,OPAL_MC_SRR0(r3)
+       mtspr   SPRN_SRR0,r13
+       ld      r13,OPAL_MC_SRR1(r3)
+       mtspr   SPRN_SRR1,r13
+       ld      r3,OPAL_MC_GPR3(r3)
+       GET_SCRATCH0(r13)
+       b       machine_check_pSeries
+#endif /* CONFIG_PPC_POWERNV */
index ba250d5..0654dba 100644 (file)
@@ -139,8 +139,7 @@ __start:
        trap
 #endif /* CONFIG_PPC_PMAC */
 
-1:     mr      r31,r3                  /* save parameters */
-       mr      r30,r4
+1:     mr      r31,r3                  /* save device tree ptr */
        li      r24,0                   /* cpu # */
 
 /*
@@ -964,8 +963,8 @@ start_here:
  * Do early platform-specific initialization,
  * and set up the MMU.
  */
-       mr      r3,r31
-       mr      r4,r30
+       li      r3,0
+       mr      r4,r31
        bl      machine_init
        bl      __save_cpu_setup
        bl      MMU_init
index a91626d..872a6af 100644 (file)
 _ENTRY(_stext);
 _ENTRY(_start);
 
-       /* Save parameters we are passed.
-       */
-       mr      r31,r3
-       mr      r30,r4
-       mr      r29,r5
-       mr      r28,r6
-       mr      r27,r7
+       mr      r31,r3                  /* save device tree ptr */
 
        /* We have to turn on the MMU right away so we get cache modes
         * set correctly.
@@ -849,11 +843,8 @@ start_here:
 /*
  * Decide what sort of machine this is and initialize the MMU.
  */
-       mr      r3,r31
-       mr      r4,r30
-       mr      r5,r29
-       mr      r6,r28
-       mr      r7,r27
+       li      r3,0
+       mr      r4,r31
        bl      machine_init
        bl      MMU_init
 
index f8e971b..b725dab 100644 (file)
@@ -61,14 +61,7 @@ _ENTRY(_start);
         * of abatron_pteptrs
         */
        nop
-/*
- * Save parameters we are passed
- */
-       mr      r31,r3
-       mr      r30,r4
-       mr      r29,r5
-       mr      r28,r6
-       mr      r27,r7
+       mr      r31,r3          /* save device tree ptr */
        li      r24,0           /* CPU number */
 
        bl      init_cpu_state
@@ -120,11 +113,8 @@ _ENTRY(_start);
 /*
  * Decide what sort of machine this is and initialize the MMU.
  */
-       mr      r3,r31
-       mr      r4,r30
-       mr      r5,r29
-       mr      r6,r28
-       mr      r7,r27
+       li      r3,0
+       mr      r4,r31
        bl      machine_init
        bl      MMU_init
 
index 3564c49..06c7251 100644 (file)
  *  For pSeries or server processors:
  *   1. The MMU is off & open firmware is running in real mode.
  *   2. The kernel is entered at __start
+ * -or- For OPAL entry:
+ *   1. The MMU is off, processor in HV mode, primary CPU enters at 0
+ *      with device-tree in gpr3. We also get OPAL base in r8 and
+ *     entry in r9 for debugging purposes
+ *   2. Secondary processors enter at 0x60 with PIR in gpr3
  *
  *  For iSeries:
  *   1. The MMU is on (as it always is for iSeries)
@@ -331,6 +336,11 @@ _GLOBAL(__start_initialization_multiplatform)
        /* Save parameters */
        mr      r31,r3
        mr      r30,r4
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+       /* Save OPAL entry */
+       mr      r28,r8
+       mr      r29,r9
+#endif
 
 #ifdef CONFIG_PPC_BOOK3E
        bl      .start_initialization_book3e
@@ -674,9 +684,9 @@ _GLOBAL(enable_64b_mode)
 _GLOBAL(relative_toc)
        mflr    r0
        bcl     20,31,$+4
-0:     mflr    r9
-       ld      r2,(p_toc - 0b)(r9)
-       add     r2,r2,r9
+0:     mflr    r11
+       ld      r2,(p_toc - 0b)(r11)
+       add     r2,r2,r11
        mtlr    r0
        blr
 
@@ -707,6 +717,12 @@ _INIT_STATIC(start_here_multiplatform)
        bdnz    3b
 4:
 
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+       /* Setup OPAL entry */
+       std     r28,0(r11);
+       std     r29,8(r11);
+#endif
+
 #ifndef CONFIG_PPC_BOOK3E
        mfmsr   r6
        ori     r6,r6,MSR_RI
index 1cbf64e..b68cb17 100644 (file)
@@ -76,11 +76,7 @@ _ENTRY(_start);
  */
        .globl  __start
 __start:
-       mr      r31,r3                  /* save parameters */
-       mr      r30,r4
-       mr      r29,r5
-       mr      r28,r6
-       mr      r27,r7
+       mr      r31,r3                  /* save device tree ptr */
 
        /* We have to turn on the MMU right away so we get cache modes
         * set correctly.
@@ -723,11 +719,8 @@ start_here:
 /*
  * Decide what sort of machine this is and initialize the MMU.
  */
-       mr      r3,r31
-       mr      r4,r30
-       mr      r5,r29
-       mr      r6,r28
-       mr      r7,r27
+       li      r3,0
+       mr      r4,r31
        bl      machine_init
        bl      MMU_init
 
index 5084592..9f5d210 100644 (file)
@@ -63,17 +63,30 @@ _ENTRY(_start);
         * of abatron_pteptrs
         */
        nop
-/*
- * Save parameters we are passed
- */
-       mr      r31,r3
-       mr      r30,r4
-       mr      r29,r5
-       mr      r28,r6
-       mr      r27,r7
-       li      r25,0           /* phys kernel start (low) */
-       li      r24,0           /* CPU number */
-       li      r23,0           /* phys kernel start (high) */
+
+       /* Translate device tree address to physical, save in r30/r31 */
+       mfmsr   r16
+       mfspr   r17,SPRN_PID
+       rlwinm  r17,r17,16,0x3fff0000   /* turn PID into MAS6[SPID] */
+       rlwimi  r17,r16,28,0x00000001   /* turn MSR[DS] into MAS6[SAS] */
+       mtspr   SPRN_MAS6,r17
+
+       tlbsx   0,r3                    /* must succeed */
+
+       mfspr   r16,SPRN_MAS1
+       mfspr   r20,SPRN_MAS3
+       rlwinm  r17,r16,25,0x1f         /* r17 = log2(page size) */
+       li      r18,1024
+       slw     r18,r18,r17             /* r18 = page size */
+       addi    r18,r18,-1
+       and     r19,r3,r18              /* r19 = page offset */
+       andc    r31,r20,r18             /* r31 = page base */
+       or      r31,r31,r19             /* r31 = devtree phys addr */
+       mfspr   r30,SPRN_MAS7
+
+       li      r25,0                   /* phys kernel start (low) */
+       li      r24,0                   /* CPU number */
+       li      r23,0                   /* phys kernel start (high) */
 
 /* We try to not make any assumptions about how the boot loader
  * setup or used the TLBs.  We invalidate all mappings from the
@@ -198,11 +211,8 @@ _ENTRY(__early_start)
 /*
  * Decide what sort of machine this is and initialize the MMU.
  */
-       mr      r3,r31
-       mr      r4,r30
-       mr      r5,r29
-       mr      r6,r28
-       mr      r7,r27
+       mr      r3,r30
+       mr      r4,r31
        bl      machine_init
        bl      MMU_init
 
@@ -236,8 +246,24 @@ _ENTRY(__early_start)
  * if we find the pte (fall through):
  *   r11 is low pte word
  *   r12 is pointer to the pte
+ *   r10 is the pshift from the PGD, if we're a hugepage
  */
 #ifdef CONFIG_PTE_64BIT
+#ifdef CONFIG_HUGETLB_PAGE
+#define FIND_PTE       \
+       rlwinm  r12, r10, 13, 19, 29;   /* Compute pgdir/pmd offset */  \
+       lwzx    r11, r12, r11;          /* Get pgd/pmd entry */         \
+       rlwinm. r12, r11, 0, 0, 20;     /* Extract pt base address */   \
+       blt     1000f;                  /* Normal non-huge page */      \
+       beq     2f;                     /* Bail if no table */          \
+       oris    r11, r11, PD_HUGE@h;    /* Put back address bit */      \
+       andi.   r10, r11, HUGEPD_SHIFT_MASK@l; /* extract size field */ \
+       xor     r12, r10, r11;          /* drop size bits from pointer */ \
+       b       1001f;                                                  \
+1000:  rlwimi  r12, r10, 23, 20, 28;   /* Compute pte address */       \
+       li      r10, 0;                 /* clear r10 */                 \
+1001:  lwz     r11, 4(r12);            /* Get pte entry */
+#else
 #define FIND_PTE       \
        rlwinm  r12, r10, 13, 19, 29;   /* Compute pgdir/pmd offset */  \
        lwzx    r11, r12, r11;          /* Get pgd/pmd entry */         \
@@ -245,7 +271,8 @@ _ENTRY(__early_start)
        beq     2f;                     /* Bail if no table */          \
        rlwimi  r12, r10, 23, 20, 28;   /* Compute pte address */       \
        lwz     r11, 4(r12);            /* Get pte entry */
-#else
+#endif /* HUGEPAGE */
+#else /* !PTE_64BIT */
 #define FIND_PTE       \
        rlwimi  r11, r10, 12, 20, 29;   /* Create L1 (pgdir/pmd) address */     \
        lwz     r11, 0(r11);            /* Get L1 entry */                      \
@@ -402,8 +429,8 @@ interrupt_base:
 
 #ifdef CONFIG_PTE_64BIT
 #ifdef CONFIG_SMP
-       subf    r10,r11,r12             /* create false data dep */
-       lwzx    r13,r11,r10             /* Get upper pte bits */
+       subf    r13,r11,r12             /* create false data dep */
+       lwzx    r13,r11,r13             /* Get upper pte bits */
 #else
        lwz     r13,0(r12)              /* Get upper pte bits */
 #endif
@@ -483,8 +510,8 @@ interrupt_base:
 
 #ifdef CONFIG_PTE_64BIT
 #ifdef CONFIG_SMP
-       subf    r10,r11,r12             /* create false data dep */
-       lwzx    r13,r11,r10             /* Get upper pte bits */
+       subf    r13,r11,r12             /* create false data dep */
+       lwzx    r13,r11,r13             /* Get upper pte bits */
 #else
        lwz     r13,0(r12)              /* Get upper pte bits */
 #endif
@@ -548,7 +575,7 @@ interrupt_base:
 /*
  * Both the instruction and data TLB miss get to this
  * point to load the TLB.
- *     r10 - available to use
+ *     r10 - tsize encoding (if HUGETLB_PAGE) or available to use
  *     r11 - TLB (info from Linux PTE)
  *     r12 - available to use
  *     r13 - upper bits of PTE (if PTE_64BIT) or available to use
@@ -558,21 +585,73 @@ interrupt_base:
  *     Upon exit, we reload everything and RFI.
  */
 finish_tlb_load:
+#ifdef CONFIG_HUGETLB_PAGE
+       cmpwi   6, r10, 0                       /* check for huge page */
+       beq     6, finish_tlb_load_cont         /* !huge */
+
+       /* Alas, we need more scratch registers for hugepages */
+       mfspr   r12, SPRN_SPRG_THREAD
+       stw     r14, THREAD_NORMSAVE(4)(r12)
+       stw     r15, THREAD_NORMSAVE(5)(r12)
+       stw     r16, THREAD_NORMSAVE(6)(r12)
+       stw     r17, THREAD_NORMSAVE(7)(r12)
+
+       /* Get the next_tlbcam_idx percpu var */
+#ifdef CONFIG_SMP
+       lwz     r12, THREAD_INFO-THREAD(r12)
+       lwz     r15, TI_CPU(r12)
+       lis     r14, __per_cpu_offset@h
+       ori     r14, r14, __per_cpu_offset@l
+       rlwinm  r15, r15, 2, 0, 29
+       lwzx    r16, r14, r15
+#else
+       li      r16, 0
+#endif
+       lis     r17, next_tlbcam_idx@h
+       ori     r17, r17, next_tlbcam_idx@l
+       add     r17, r17, r16                   /* r17 = *next_tlbcam_idx */
+       lwz     r15, 0(r17)                     /* r15 = next_tlbcam_idx */
+
+       lis     r14, MAS0_TLBSEL(1)@h           /* select TLB1 (TLBCAM) */
+       rlwimi  r14, r15, 16, 4, 15             /* next_tlbcam_idx entry */
+       mtspr   SPRN_MAS0, r14
+
+       /* Extract TLB1CFG(NENTRY) */
+       mfspr   r16, SPRN_TLB1CFG
+       andi.   r16, r16, 0xfff
+
+       /* Update next_tlbcam_idx, wrapping when necessary */
+       addi    r15, r15, 1
+       cmpw    r15, r16
+       blt     100f
+       lis     r14, tlbcam_index@h
+       ori     r14, r14, tlbcam_index@l
+       lwz     r15, 0(r14)
+100:   stw     r15, 0(r17)
+
+       /*
+        * Calc MAS1_TSIZE from r10 (which has pshift encoded)
+        * tlb_enc = (pshift - 10).
+        */
+       subi    r15, r10, 10
+       mfspr   r16, SPRN_MAS1
+       rlwimi  r16, r15, 7, 20, 24
+       mtspr   SPRN_MAS1, r16
+
+       /* copy the pshift for use later */
+       mr      r14, r10
+
+       /* fall through */
+
+#endif /* CONFIG_HUGETLB_PAGE */
+
        /*
         * We set execute, because we don't have the granularity to
         * properly set this at the page level (Linux problem).
         * Many of these bits are software only.  Bits we don't set
         * here we (properly should) assume have the appropriate value.
         */
-
-       mfspr   r12, SPRN_MAS2
-#ifdef CONFIG_PTE_64BIT
-       rlwimi  r12, r11, 32-19, 27, 31 /* extract WIMGE from pte */
-#else
-       rlwimi  r12, r11, 26, 27, 31    /* extract WIMGE from pte */
-#endif
-       mtspr   SPRN_MAS2, r12
-
+finish_tlb_load_cont:
 #ifdef CONFIG_PTE_64BIT
        rlwinm  r12, r11, 32-2, 26, 31  /* Move in perm bits */
        andi.   r10, r11, _PAGE_DIRTY
@@ -581,22 +660,40 @@ finish_tlb_load:
        andc    r12, r12, r10
 1:     rlwimi  r12, r13, 20, 0, 11     /* grab RPN[32:43] */
        rlwimi  r12, r11, 20, 12, 19    /* grab RPN[44:51] */
-       mtspr   SPRN_MAS3, r12
+2:     mtspr   SPRN_MAS3, r12
 BEGIN_MMU_FTR_SECTION
        srwi    r10, r13, 12            /* grab RPN[12:31] */
        mtspr   SPRN_MAS7, r10
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS)
 #else
        li      r10, (_PAGE_EXEC | _PAGE_PRESENT)
+       mr      r13, r11
        rlwimi  r10, r11, 31, 29, 29    /* extract _PAGE_DIRTY into SW */
        and     r12, r11, r10
        andi.   r10, r11, _PAGE_USER    /* Test for _PAGE_USER */
        slwi    r10, r12, 1
        or      r10, r10, r12
        iseleq  r12, r12, r10
-       rlwimi  r11, r12, 0, 20, 31     /* Extract RPN from PTE and merge with perms */
-       mtspr   SPRN_MAS3, r11
+       rlwimi  r13, r12, 0, 20, 31     /* Get RPN from PTE, merge w/ perms */
+       mtspr   SPRN_MAS3, r13
 #endif
+
+       mfspr   r12, SPRN_MAS2
+#ifdef CONFIG_PTE_64BIT
+       rlwimi  r12, r11, 32-19, 27, 31 /* extract WIMGE from pte */
+#else
+       rlwimi  r12, r11, 26, 27, 31    /* extract WIMGE from pte */
+#endif
+#ifdef CONFIG_HUGETLB_PAGE
+       beq     6, 3f                   /* don't mask if page isn't huge */
+       li      r13, 1
+       slw     r13, r13, r14
+       subi    r13, r13, 1
+       rlwinm  r13, r13, 0, 0, 19      /* bottom bits used for WIMGE/etc */
+       andc    r12, r12, r13           /* mask off ea bits within the page */
+#endif
+3:     mtspr   SPRN_MAS2, r12
+
 #ifdef CONFIG_E200
        /* Round robin TLB1 entries assignment */
        mfspr   r12, SPRN_MAS0
@@ -622,11 +719,19 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS)
        mtspr   SPRN_MAS0,r12
 #endif /* CONFIG_E200 */
 
+tlb_write_entry:
        tlbwe
 
        /* Done...restore registers and get out of here.  */
        mfspr   r10, SPRN_SPRG_THREAD
-       lwz     r11, THREAD_NORMSAVE(3)(r10)
+#ifdef CONFIG_HUGETLB_PAGE
+       beq     6, 8f /* skip restore for 4k page faults */
+       lwz     r14, THREAD_NORMSAVE(4)(r10)
+       lwz     r15, THREAD_NORMSAVE(5)(r10)
+       lwz     r16, THREAD_NORMSAVE(6)(r10)
+       lwz     r17, THREAD_NORMSAVE(7)(r10)
+#endif
+8:     lwz     r11, THREAD_NORMSAVE(3)(r10)
        mtcr    r11
        lwz     r13, THREAD_NORMSAVE(2)(r10)
        lwz     r12, THREAD_NORMSAVE(1)(r10)
index 28581f1..73110fb 100644 (file)
@@ -125,17 +125,23 @@ static void ibmebus_unmap_sg(struct device *dev,
 
 static int ibmebus_dma_supported(struct device *dev, u64 mask)
 {
-       return 1;
+       return mask == DMA_BIT_MASK(64);
+}
+
+static u64 ibmebus_dma_get_required_mask(struct device *dev)
+{
+       return DMA_BIT_MASK(64);
 }
 
 static struct dma_map_ops ibmebus_dma_ops = {
-       .alloc_coherent = ibmebus_alloc_coherent,
-       .free_coherent  = ibmebus_free_coherent,
-       .map_sg         = ibmebus_map_sg,
-       .unmap_sg       = ibmebus_unmap_sg,
-       .dma_supported  = ibmebus_dma_supported,
-       .map_page       = ibmebus_map_page,
-       .unmap_page     = ibmebus_unmap_page,
+       .alloc_coherent     = ibmebus_alloc_coherent,
+       .free_coherent      = ibmebus_free_coherent,
+       .map_sg             = ibmebus_map_sg,
+       .unmap_sg           = ibmebus_unmap_sg,
+       .dma_supported      = ibmebus_dma_supported,
+       .get_required_mask  = ibmebus_dma_get_required_mask,
+       .map_page           = ibmebus_map_page,
+       .unmap_page         = ibmebus_unmap_page,
 };
 
 static int ibmebus_match_path(struct device *dev, void *data)
index 3e2b95c..4f0ab85 100644 (file)
@@ -26,7 +26,7 @@ _GLOBAL(e500_idle)
        ori     r4,r4,_TLF_NAPPING      /* so when we take an exception */
        stw     r4,TI_LOCAL_FLAGS(r3)   /* it will return to our caller */
 
-#ifdef CONFIG_E500MC
+#ifdef CONFIG_PPC_E500MC
        wrteei  1
 1:     wait
 
index 961bb03..0cfcf98 100644 (file)
@@ -501,6 +501,14 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
        tbl->it_map = page_address(page);
        memset(tbl->it_map, 0, sz);
 
+       /*
+        * Reserve page 0 so it will not be used for any mappings.
+        * This avoids buggy drivers that consider page 0 to be invalid
+        * to crash the machine or even lose data.
+        */
+       if (tbl->it_offset == 0)
+               set_bit(0, tbl->it_map);
+
        tbl->it_hint = 0;
        tbl->it_largehint = tbl->it_halfpoint;
        spin_lock_init(&tbl->it_lock);
index 2b97b80..c7b5afe 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/pci.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
+#include <linux/serial_reg.h>
 #include <asm/io.h>
 #include <asm/mmu.h>
 #include <asm/prom.h>
@@ -47,6 +48,24 @@ static struct __initdata of_device_id legacy_serial_parents[] = {
 static unsigned int legacy_serial_count;
 static int legacy_serial_console = -1;
 
+static unsigned int tsi_serial_in(struct uart_port *p, int offset)
+{
+       unsigned int tmp;
+       offset = offset << p->regshift;
+       if (offset == UART_IIR) {
+               tmp = readl(p->membase + (UART_IIR & ~3));
+               return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */
+       } else
+               return readb(p->membase + offset);
+}
+
+static void tsi_serial_out(struct uart_port *p, int offset, int value)
+{
+       offset = offset << p->regshift;
+       if (!((offset == UART_IER) && (value & UART_IER_UUE)))
+               writeb(value, p->membase + offset);
+}
+
 static int __init add_legacy_port(struct device_node *np, int want_index,
                                  int iotype, phys_addr_t base,
                                  phys_addr_t taddr, unsigned long irq,
@@ -102,6 +121,7 @@ static int __init add_legacy_port(struct device_node *np, int want_index,
                legacy_serial_ports[index].iobase = base;
        else
                legacy_serial_ports[index].mapbase = base;
+
        legacy_serial_ports[index].iotype = iotype;
        legacy_serial_ports[index].uartclk = clock;
        legacy_serial_ports[index].irq = irq;
@@ -112,6 +132,11 @@ static int __init add_legacy_port(struct device_node *np, int want_index,
        legacy_serial_infos[index].speed = spd ? be32_to_cpup(spd) : 0;
        legacy_serial_infos[index].irq_check_parent = irq_check_parent;
 
+       if (iotype == UPIO_TSI) {
+               legacy_serial_ports[index].serial_in = tsi_serial_in;
+               legacy_serial_ports[index].serial_out = tsi_serial_out;
+       }
+
        printk(KERN_DEBUG "Found legacy serial port %d for %s\n",
               index, np->full_name);
        printk(KERN_DEBUG "  %s=%llx, taddr=%llx, irq=%lx, clk=%d, speed=%d\n",
index 583af70..26ccbf7 100644 (file)
@@ -74,8 +74,7 @@ int default_machine_kexec_prepare(struct kimage *image)
        }
 
        /* We also should not overwrite the tce tables */
-       for (node = of_find_node_by_type(NULL, "pci"); node != NULL;
-                       node = of_find_node_by_type(node, "pci")) {
+       for_each_node_by_type(node, "pci") {
                basep = of_get_property(node, "linux,tce-base", NULL);
                sizep = of_get_property(node, "linux,tce-size", NULL);
                if (basep == NULL || sizep == NULL)
index 998a100..f7d760a 100644 (file)
@@ -8,6 +8,8 @@
  * kexec bits:
  * Copyright (C) 2002-2003 Eric Biederman  <ebiederm@xmission.com>
  * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
+ * PPC44x port. Copyright (C) 2011,  IBM Corporation
+ *             Author: Suzuki Poulose <suzuki@in.ibm.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -735,6 +737,175 @@ relocate_new_kernel:
        mr      r4, r30
        mr      r5, r31
 
+       li      r0, 0
+#elif defined(CONFIG_44x)  && !defined(CONFIG_47x)
+
+/*
+ * Code for setting up 1:1 mapping for PPC440x for KEXEC
+ *
+ * We cannot switch off the MMU on PPC44x.
+ * So we:
+ * 1) Invalidate all the mappings except the one we are running from.
+ * 2) Create a tmp mapping for our code in the other address space(TS) and
+ *    jump to it. Invalidate the entry we started in.
+ * 3) Create a 1:1 mapping for 0-2GiB in chunks of 256M in original TS.
+ * 4) Jump to the 1:1 mapping in original TS.
+ * 5) Invalidate the tmp mapping.
+ *
+ * - Based on the kexec support code for FSL BookE
+ * - Doesn't support 47x yet.
+ *
+ */
+       /* Save our parameters */
+       mr      r29, r3
+       mr      r30, r4
+       mr      r31, r5
+
+       /* Load our MSR_IS and TID to MMUCR for TLB search */
+       mfspr   r3,SPRN_PID
+       mfmsr   r4
+       andi.   r4,r4,MSR_IS@l
+       beq     wmmucr
+       oris    r3,r3,PPC44x_MMUCR_STS@h
+wmmucr:
+       mtspr   SPRN_MMUCR,r3
+       sync
+
+       /*
+        * Invalidate all the TLB entries except the current entry
+        * where we are running from
+        */
+       bl      0f                              /* Find our address */
+0:     mflr    r5                              /* Make it accessible */
+       tlbsx   r23,0,r5                        /* Find entry we are in */
+       li      r4,0                            /* Start at TLB entry 0 */
+       li      r3,0                            /* Set PAGEID inval value */
+1:     cmpw    r23,r4                          /* Is this our entry? */
+       beq     skip                            /* If so, skip the inval */
+       tlbwe   r3,r4,PPC44x_TLB_PAGEID         /* If not, inval the entry */
+skip:
+       addi    r4,r4,1                         /* Increment */
+       cmpwi   r4,64                           /* Are we done? */
+       bne     1b                              /* If not, repeat */
+       isync
+
+       /* Create a temp mapping and jump to it */
+       andi.   r6, r23, 1              /* Find the index to use */
+       addi    r24, r6, 1              /* r24 will contain 1 or 2 */
+
+       mfmsr   r9                      /* get the MSR */
+       rlwinm  r5, r9, 27, 31, 31      /* Extract the MSR[IS] */
+       xori    r7, r5, 1               /* Use the other address space */
+
+       /* Read the current mapping entries */
+       tlbre   r3, r23, PPC44x_TLB_PAGEID
+       tlbre   r4, r23, PPC44x_TLB_XLAT
+       tlbre   r5, r23, PPC44x_TLB_ATTRIB
+
+       /* Save our current XLAT entry */
+       mr      r25, r4
+
+       /* Extract the TLB PageSize */
+       li      r10, 1                  /* r10 will hold PageSize */
+       rlwinm  r11, r3, 0, 24, 27      /* bits 24-27 */
+
+       /* XXX: As of now we use 256M, 4K pages */
+       cmpwi   r11, PPC44x_TLB_256M
+       bne     tlb_4k
+       rotlwi  r10, r10, 28            /* r10 = 256M */
+       b       write_out
+tlb_4k:
+       cmpwi   r11, PPC44x_TLB_4K
+       bne     default
+       rotlwi  r10, r10, 12            /* r10 = 4K */
+       b       write_out
+default:
+       rotlwi  r10, r10, 10            /* r10 = 1K */
+
+write_out:
+       /*
+        * Write out the tmp 1:1 mapping for this code in other address space
+        * Fixup  EPN = RPN , TS=other address space
+        */
+       insrwi  r3, r7, 1, 23           /* Bit 23 is TS for PAGEID field */
+
+       /* Write out the tmp mapping entries */
+       tlbwe   r3, r24, PPC44x_TLB_PAGEID
+       tlbwe   r4, r24, PPC44x_TLB_XLAT
+       tlbwe   r5, r24, PPC44x_TLB_ATTRIB
+
+       subi    r11, r10, 1             /* PageOffset Mask = PageSize - 1 */
+       not     r10, r11                /* Mask for PageNum */
+
+       /* Switch to other address space in MSR */
+       insrwi  r9, r7, 1, 26           /* Set MSR[IS] = r7 */
+
+       bl      1f
+1:     mflr    r8
+       addi    r8, r8, (2f-1b)         /* Find the target offset */
+
+       /* Jump to the tmp mapping */
+       mtspr   SPRN_SRR0, r8
+       mtspr   SPRN_SRR1, r9
+       rfi
+
+2:
+       /* Invalidate the entry we were executing from */
+       li      r3, 0
+       tlbwe   r3, r23, PPC44x_TLB_PAGEID
+
+       /* attribute fields. rwx for SUPERVISOR mode */
+       li      r5, 0
+       ori     r5, r5, (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G)
+
+       /* Create 1:1 mapping in 256M pages */
+       xori    r7, r7, 1                       /* Revert back to Original TS */
+
+       li      r8, 0                           /* PageNumber */
+       li      r6, 3                           /* TLB Index, start at 3  */
+
+next_tlb:
+       rotlwi  r3, r8, 28                      /* Create EPN (bits 0-3) */
+       mr      r4, r3                          /* RPN = EPN  */
+       ori     r3, r3, (PPC44x_TLB_VALID | PPC44x_TLB_256M) /* SIZE = 256M, Valid */
+       insrwi  r3, r7, 1, 23                   /* Set TS from r7 */
+
+       tlbwe   r3, r6, PPC44x_TLB_PAGEID       /* PageID field : EPN, V, SIZE */
+       tlbwe   r4, r6, PPC44x_TLB_XLAT         /* Address translation : RPN   */
+       tlbwe   r5, r6, PPC44x_TLB_ATTRIB       /* Attributes */
+
+       addi    r8, r8, 1                       /* Increment PN */
+       addi    r6, r6, 1                       /* Increment TLB Index */
+       cmpwi   r8, 8                           /* Are we done ? */
+       bne     next_tlb
+       isync
+
+       /* Jump to the new mapping 1:1 */
+       li      r9,0
+       insrwi  r9, r7, 1, 26                   /* Set MSR[IS] = r7 */
+
+       bl      1f
+1:     mflr    r8
+       and     r8, r8, r11                     /* Get our offset within page */
+       addi    r8, r8, (2f-1b)
+
+       and     r5, r25, r10                    /* Get our target PageNum */
+       or      r8, r8, r5                      /* Target jump address */
+
+       mtspr   SPRN_SRR0, r8
+       mtspr   SPRN_SRR1, r9
+       rfi
+2:
+       /* Invalidate the tmp entry we used */
+       li      r3, 0
+       tlbwe   r3, r24, PPC44x_TLB_PAGEID
+       sync
+
+       /* Restore the parameters */
+       mr      r3, r29
+       mr      r4, r30
+       mr      r5, r31
+
        li      r0, 0
 #else
        li      r0, 0
index 32656f1..677eccc 100644 (file)
@@ -1730,6 +1730,17 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
 
        if (mode == PCI_PROBE_NORMAL)
                hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
+
+       /* Configure PCI Express settings */
+       if (bus && !pci_has_flag(PCI_PROBE_ONLY)) {
+               struct pci_bus *child;
+               list_for_each_entry(child, &bus->children, node) {
+                       struct pci_dev *self = child->self;
+                       if (!self)
+                               continue;
+                       pcie_bus_configure_settings(child, self->pcie_mpss);
+               }
+       }
 }
 
 static void fixup_hide_host_resource_fsl(struct pci_dev *dev)
index 03b95e2..0bbc901 100644 (file)
@@ -487,8 +487,8 @@ static int power6_generic_events[] = {
  */
 static int power6_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
        [C(L1D)] = {            /*      RESULT_ACCESS   RESULT_MISS */
-               [C(OP_READ)] = {        0x80082,        0x80080         },
-               [C(OP_WRITE)] = {       0x80086,        0x80088         },
+               [C(OP_READ)] = {        0x280030,       0x80080         },
+               [C(OP_WRITE)] = {       0x180032,       0x80088         },
                [C(OP_PREFETCH)] = {    0x810a4,        0               },
        },
        [C(L1I)] = {            /*      RESULT_ACCESS   RESULT_MISS */
index de83d60..1251e4d 100644 (file)
@@ -297,6 +297,8 @@ static void power7_disable_pmc(unsigned int pmc, unsigned long mmcr[])
 
 static int power7_generic_events[] = {
        [PERF_COUNT_HW_CPU_CYCLES] = 0x1e,
+       [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x100f8, /* GCT_NOSLOT_CYC */
+       [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x4000a,  /* CMPLU_STALL */
        [PERF_COUNT_HW_INSTRUCTIONS] = 2,
        [PERF_COUNT_HW_CACHE_REFERENCES] = 0xc880,      /* LD_REF_L1_LSU*/
        [PERF_COUNT_HW_CACHE_MISSES] = 0x400f0,         /* LD_MISS_L1   */
index 174e1e9..8ad825c 100644 (file)
@@ -54,6 +54,8 @@
 #include <asm/pci-bridge.h>
 #include <asm/phyp_dump.h>
 #include <asm/kexec.h>
+#include <asm/opal.h>
+
 #include <mm/mmu_decl.h>
 
 #ifdef DEBUG
@@ -707,11 +709,23 @@ void __init early_init_devtree(void *params)
        of_scan_flat_dt(early_init_dt_scan_rtas, NULL);
 #endif
 
+#ifdef CONFIG_PPC_POWERNV
+       /* Some machines might need OPAL info for debugging, grab it now. */
+       of_scan_flat_dt(early_init_dt_scan_opal, NULL);
+#endif
+
 #ifdef CONFIG_PHYP_DUMP
        /* scan tree to see if dump occurred during last boot */
        of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL);
 #endif
 
+       /* Pre-initialize the cmd_line with the content of boot_commmand_line,
+        * which will be empty except when the content of the variable has
+        * been overriden by a bootloading mechanism. This happens typically
+        * with HAL takeover
+        */
+       strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
+
        /* Retrieve various informations from the /chosen node of the
         * device-tree, including the platform type, initrd location and
         * size, TCE reserve, and more ...
@@ -723,12 +737,15 @@ void __init early_init_devtree(void *params)
 
        of_scan_flat_dt(early_init_dt_scan_root, NULL);
        of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL);
-       setup_initial_memory_limit(memstart_addr, first_memblock_size);
 
        /* Save command line for /proc/cmdline and then parse parameters */
        strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
        parse_early_param();
 
+       /* make sure we've parsed cmdline for mem= before this */
+       if (memory_limit)
+               first_memblock_size = min(first_memblock_size, memory_limit);
+       setup_initial_memory_limit(memstart_addr, first_memblock_size);
        /* Reserve MEMBLOCK regions used by kernel, initrd, dt, etc... */
        memblock_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
        /* If relocatable, reserve first 32k for interrupt vectors etc. */
index a909f4e..b4fa661 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/btext.h>
 #include <asm/sections.h>
 #include <asm/machdep.h>
+#include <asm/opal.h>
 
 #include <linux/linux_logo.h>
 
@@ -139,7 +140,9 @@ struct mem_map_entry {
 
 typedef u32 cell_t;
 
-extern void __start(unsigned long r3, unsigned long r4, unsigned long r5);
+extern void __start(unsigned long r3, unsigned long r4, unsigned long r5,
+                   unsigned long r6, unsigned long r7, unsigned long r8,
+                   unsigned long r9);
 
 #ifdef CONFIG_PPC64
 extern int enter_prom(struct prom_args *args, unsigned long entry);
@@ -185,6 +188,7 @@ static unsigned long __initdata prom_tce_alloc_end;
 #define PLATFORM_LPAR          0x0001
 #define PLATFORM_POWERMAC      0x0400
 #define PLATFORM_GENERIC       0x0500
+#define PLATFORM_OPAL          0x0600
 
 static int __initdata of_platform;
 
@@ -644,7 +648,7 @@ static void __init early_cmdline_parse(void)
        }
 }
 
-#ifdef CONFIG_PPC_PSERIES
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
 /*
  * There are two methods for telling firmware what our capabilities are.
  * Newer machines have an "ibm,client-architecture-support" method on the
@@ -1274,6 +1278,284 @@ static void __init prom_init_mem(void)
        prom_printf("  ram_top      : %x\n", RELOC(ram_top));
 }
 
+static void __init prom_close_stdin(void)
+{
+       struct prom_t *_prom = &RELOC(prom);
+       ihandle val;
+
+       if (prom_getprop(_prom->chosen, "stdin", &val, sizeof(val)) > 0)
+               call_prom("close", 1, 0, val);
+}
+
+#ifdef CONFIG_PPC_POWERNV
+
+static u64 __initdata prom_opal_size;
+static u64 __initdata prom_opal_align;
+static int __initdata prom_rtas_start_cpu;
+static u64 __initdata prom_rtas_data;
+static u64 __initdata prom_rtas_entry;
+
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+static u64 __initdata prom_opal_base;
+static u64 __initdata prom_opal_entry;
+#endif
+
+/* XXX Don't change this structure without updating opal-takeover.S */
+static struct opal_secondary_data {
+       s64                             ack;    /*  0 */
+       u64                             go;     /*  8 */
+       struct opal_takeover_args       args;   /* 16 */
+} opal_secondary_data;
+
+extern char opal_secondary_entry;
+
+static void prom_query_opal(void)
+{
+       long rc;
+
+       /* We must not query for OPAL presence on a machine that
+        * supports TNK takeover (970 blades), as this uses the same
+        * h-call with different arguments and will crash
+        */
+       if (PHANDLE_VALID(call_prom("finddevice", 1, 1,
+                                   ADDR("/tnk-memory-map")))) {
+               prom_printf("TNK takeover detected, skipping OPAL check\n");
+               return;
+       }
+
+       prom_printf("Querying for OPAL presence... ");
+       rc = opal_query_takeover(&RELOC(prom_opal_size),
+                                &RELOC(prom_opal_align));
+       prom_debug("(rc = %ld) ", rc);
+       if (rc != 0) {
+               prom_printf("not there.\n");
+               return;
+       }
+       RELOC(of_platform) = PLATFORM_OPAL;
+       prom_printf(" there !\n");
+       prom_debug("  opal_size  = 0x%lx\n", RELOC(prom_opal_size));
+       prom_debug("  opal_align = 0x%lx\n", RELOC(prom_opal_align));
+       if (RELOC(prom_opal_align) < 0x10000)
+               RELOC(prom_opal_align) = 0x10000;
+}
+
+static int prom_rtas_call(int token, int nargs, int nret, int *outputs, ...)
+{
+       struct rtas_args rtas_args;
+       va_list list;
+       int i;
+
+       rtas_args.token = token;
+       rtas_args.nargs = nargs;
+       rtas_args.nret  = nret;
+       rtas_args.rets  = (rtas_arg_t *)&(rtas_args.args[nargs]);
+       va_start(list, outputs);
+       for (i = 0; i < nargs; ++i)
+               rtas_args.args[i] = va_arg(list, rtas_arg_t);
+       va_end(list);
+
+       for (i = 0; i < nret; ++i)
+               rtas_args.rets[i] = 0;
+
+       opal_enter_rtas(&rtas_args, RELOC(prom_rtas_data),
+                       RELOC(prom_rtas_entry));
+
+       if (nret > 1 && outputs != NULL)
+               for (i = 0; i < nret-1; ++i)
+                       outputs[i] = rtas_args.rets[i+1];
+       return (nret > 0)? rtas_args.rets[0]: 0;
+}
+
+static void __init prom_opal_hold_cpus(void)
+{
+       int i, cnt, cpu, rc;
+       long j;
+       phandle node;
+       char type[64];
+       u32 servers[8];
+       struct prom_t *_prom = &RELOC(prom);
+       void *entry = (unsigned long *)&RELOC(opal_secondary_entry);
+       struct opal_secondary_data *data = &RELOC(opal_secondary_data);
+
+       prom_debug("prom_opal_hold_cpus: start...\n");
+       prom_debug("    - entry       = 0x%x\n", entry);
+       prom_debug("    - data        = 0x%x\n", data);
+
+       data->ack = -1;
+       data->go = 0;
+
+       /* look for cpus */
+       for (node = 0; prom_next_node(&node); ) {
+               type[0] = 0;
+               prom_getprop(node, "device_type", type, sizeof(type));
+               if (strcmp(type, RELOC("cpu")) != 0)
+                       continue;
+
+               /* Skip non-configured cpus. */
+               if (prom_getprop(node, "status", type, sizeof(type)) > 0)
+                       if (strcmp(type, RELOC("okay")) != 0)
+                               continue;
+
+               cnt = prom_getprop(node, "ibm,ppc-interrupt-server#s", servers,
+                            sizeof(servers));
+               if (cnt == PROM_ERROR)
+                       break;
+               cnt >>= 2;
+               for (i = 0; i < cnt; i++) {
+                       cpu = servers[i];
+                       prom_debug("CPU %d ... ", cpu);
+                       if (cpu == _prom->cpu) {
+                               prom_debug("booted !\n");
+                               continue;
+                       }
+                       prom_debug("starting ... ");
+
+                       /* Init the acknowledge var which will be reset by
+                        * the secondary cpu when it awakens from its OF
+                        * spinloop.
+                        */
+                       data->ack = -1;
+                       rc = prom_rtas_call(RELOC(prom_rtas_start_cpu), 3, 1,
+                                           NULL, cpu, entry, data);
+                       prom_debug("rtas rc=%d ...", rc);
+
+                       for (j = 0; j < 100000000 && data->ack == -1; j++) {
+                               HMT_low();
+                               mb();
+                       }
+                       HMT_medium();
+                       if (data->ack != -1)
+                               prom_debug("done, PIR=0x%x\n", data->ack);
+                       else
+                               prom_debug("timeout !\n");
+               }
+       }
+       prom_debug("prom_opal_hold_cpus: end...\n");
+}
+
+static void prom_opal_takeover(void)
+{
+       struct opal_secondary_data *data = &RELOC(opal_secondary_data);
+       struct opal_takeover_args *args = &data->args;
+       u64 align = RELOC(prom_opal_align);
+       u64 top_addr, opal_addr;
+
+       args->k_image   = (u64)RELOC(_stext);
+       args->k_size    = _end - _stext;
+       args->k_entry   = 0;
+       args->k_entry2  = 0x60;
+
+       top_addr = _ALIGN_UP(args->k_size, align);
+
+       if (RELOC(prom_initrd_start) != 0) {
+               args->rd_image = RELOC(prom_initrd_start);
+               args->rd_size = RELOC(prom_initrd_end) - args->rd_image;
+               args->rd_loc = top_addr;
+               top_addr = _ALIGN_UP(args->rd_loc + args->rd_size, align);
+       }
+
+       /* Pickup an address for the HAL. We want to go really high
+        * up to avoid problem with future kexecs. On the other hand
+        * we don't want to be all over the TCEs on P5IOC2 machines
+        * which are going to be up there too. We assume the machine
+        * has plenty of memory, and we ask for the HAL for now to
+        * be just below the 1G point, or above the initrd
+        */
+       opal_addr = _ALIGN_DOWN(0x40000000 - RELOC(prom_opal_size), align);
+       if (opal_addr < top_addr)
+               opal_addr = top_addr;
+       args->hal_addr = opal_addr;
+
+       /* Copy the command line to the kernel image */
+       strlcpy(RELOC(boot_command_line), RELOC(prom_cmd_line),
+               COMMAND_LINE_SIZE);
+
+       prom_debug("  k_image    = 0x%lx\n", args->k_image);
+       prom_debug("  k_size     = 0x%lx\n", args->k_size);
+       prom_debug("  k_entry    = 0x%lx\n", args->k_entry);
+       prom_debug("  k_entry2   = 0x%lx\n", args->k_entry2);
+       prom_debug("  hal_addr   = 0x%lx\n", args->hal_addr);
+       prom_debug("  rd_image   = 0x%lx\n", args->rd_image);
+       prom_debug("  rd_size    = 0x%lx\n", args->rd_size);
+       prom_debug("  rd_loc     = 0x%lx\n", args->rd_loc);
+       prom_printf("Performing OPAL takeover,this can take a few minutes..\n");
+       prom_close_stdin();
+       mb();
+       data->go = 1;
+       for (;;)
+               opal_do_takeover(args);
+}
+
+/*
+ * Allocate room for and instantiate OPAL
+ */
+static void __init prom_instantiate_opal(void)
+{
+       phandle opal_node;
+       ihandle opal_inst;
+       u64 base, entry;
+       u64 size = 0, align = 0x10000;
+       u32 rets[2];
+
+       prom_debug("prom_instantiate_opal: start...\n");
+
+       opal_node = call_prom("finddevice", 1, 1, ADDR("/ibm,opal"));
+       prom_debug("opal_node: %x\n", opal_node);
+       if (!PHANDLE_VALID(opal_node))
+               return;
+
+       prom_getprop(opal_node, "opal-runtime-size", &size, sizeof(size));
+       if (size == 0)
+               return;
+       prom_getprop(opal_node, "opal-runtime-alignment", &align,
+                    sizeof(align));
+
+       base = alloc_down(size, align, 0);
+       if (base == 0) {
+               prom_printf("OPAL allocation failed !\n");
+               return;
+       }
+
+       opal_inst = call_prom("open", 1, 1, ADDR("/ibm,opal"));
+       if (!IHANDLE_VALID(opal_inst)) {
+               prom_printf("opening opal package failed (%x)\n", opal_inst);
+               return;
+       }
+
+       prom_printf("instantiating opal at 0x%x...", base);
+
+       if (call_prom_ret("call-method", 4, 3, rets,
+                         ADDR("load-opal-runtime"),
+                         opal_inst,
+                         base >> 32, base & 0xffffffff) != 0
+           || (rets[0] == 0 && rets[1] == 0)) {
+               prom_printf(" failed\n");
+               return;
+       }
+       entry = (((u64)rets[0]) << 32) | rets[1];
+
+       prom_printf(" done\n");
+
+       reserve_mem(base, size);
+
+       prom_debug("opal base     = 0x%x\n", base);
+       prom_debug("opal align    = 0x%x\n", align);
+       prom_debug("opal entry    = 0x%x\n", entry);
+       prom_debug("opal size     = 0x%x\n", (long)size);
+
+       prom_setprop(opal_node, "/ibm,opal", "opal-base-address",
+                    &base, sizeof(base));
+       prom_setprop(opal_node, "/ibm,opal", "opal-entry-address",
+                    &entry, sizeof(entry));
+
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+       RELOC(prom_opal_base) = base;
+       RELOC(prom_opal_entry) = entry;
+#endif
+       prom_debug("prom_instantiate_opal: end...\n");
+}
+
+#endif /* CONFIG_PPC_POWERNV */
 
 /*
  * Allocate room for and instantiate RTAS
@@ -1326,6 +1608,12 @@ static void __init prom_instantiate_rtas(void)
        prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
                     &entry, sizeof(entry));
 
+#ifdef CONFIG_PPC_POWERNV
+       /* PowerVN takeover hack */
+       RELOC(prom_rtas_data) = base;
+       RELOC(prom_rtas_entry) = entry;
+       prom_getprop(rtas_node, "start-cpu", &RELOC(prom_rtas_start_cpu), 4);
+#endif
        prom_debug("rtas base     = 0x%x\n", base);
        prom_debug("rtas entry    = 0x%x\n", entry);
        prom_debug("rtas size     = 0x%x\n", (long)size);
@@ -1543,7 +1831,7 @@ static void __init prom_hold_cpus(void)
                *acknowledge = (unsigned long)-1;
 
                if (reg != _prom->cpu) {
-                       /* Primary Thread of non-boot cpu */
+                       /* Primary Thread of non-boot cpu or any thread */
                        prom_printf("starting cpu hw idx %lu... ", reg);
                        call_prom("start-cpu", 3, 0, node,
                                  secondary_hold, reg);
@@ -1652,15 +1940,6 @@ static void __init prom_init_stdout(void)
                prom_setprop(val, path, "linux,boot-display", NULL, 0);
 }
 
-static void __init prom_close_stdin(void)
-{
-       struct prom_t *_prom = &RELOC(prom);
-       ihandle val;
-
-       if (prom_getprop(_prom->chosen, "stdin", &val, sizeof(val)) > 0)
-               call_prom("close", 1, 0, val);
-}
-
 static int __init prom_find_machine_type(void)
 {
        struct prom_t *_prom = &RELOC(prom);
@@ -1671,7 +1950,7 @@ static int __init prom_find_machine_type(void)
        int x;
 #endif
 
-       /* Look for a PowerMac */
+       /* Look for a PowerMac or a Cell */
        len = prom_getprop(_prom->root, "compatible",
                           compat, sizeof(compat)-1);
        if (len > 0) {
@@ -1697,7 +1976,11 @@ static int __init prom_find_machine_type(void)
                }
        }
 #ifdef CONFIG_PPC64
-       /* If not a mac, try to figure out if it's an IBM pSeries or any other
+       /* Try to detect OPAL */
+       if (PHANDLE_VALID(call_prom("finddevice", 1, 1, ADDR("/ibm,opal"))))
+               return PLATFORM_OPAL;
+
+       /* Try to figure out if it's an IBM pSeries or any other
         * PAPR compliant platform. We assume it is if :
         *  - /device_type is "chrp" (please, do NOT use that for future
         *    non-IBM designs !
@@ -1924,7 +2207,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
        unsigned long soff;
        unsigned char *valp;
        static char pname[MAX_PROPERTY_NAME];
-       int l, room;
+       int l, room, has_phandle = 0;
 
        dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
 
@@ -2008,19 +2291,26 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
                valp = make_room(mem_start, mem_end, l, 4);
                call_prom("getprop", 4, 1, node, RELOC(pname), valp, l);
                *mem_start = _ALIGN(*mem_start, 4);
+
+               if (!strcmp(RELOC(pname), RELOC("phandle")))
+                       has_phandle = 1;
        }
 
-       /* Add a "linux,phandle" property. */
-       soff = dt_find_string(RELOC("linux,phandle"));
-       if (soff == 0)
-               prom_printf("WARNING: Can't find string index for"
-                           " <linux-phandle> node %s\n", path);
-       else {
-               dt_push_token(OF_DT_PROP, mem_start, mem_end);
-               dt_push_token(4, mem_start, mem_end);
-               dt_push_token(soff, mem_start, mem_end);
-               valp = make_room(mem_start, mem_end, 4, 4);
-               *(u32 *)valp = node;
+       /* Add a "linux,phandle" property if no "phandle" property already
+        * existed (can happen with OPAL)
+        */
+       if (!has_phandle) {
+               soff = dt_find_string(RELOC("linux,phandle"));
+               if (soff == 0)
+                       prom_printf("WARNING: Can't find string index for"
+                                   " <linux-phandle> node %s\n", path);
+               else {
+                       dt_push_token(OF_DT_PROP, mem_start, mem_end);
+                       dt_push_token(4, mem_start, mem_end);
+                       dt_push_token(soff, mem_start, mem_end);
+                       valp = make_room(mem_start, mem_end, 4, 4);
+                       *(u32 *)valp = node;
+               }
        }
 
        /* do all our children */
@@ -2504,6 +2794,7 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
 #endif /* CONFIG_BLK_DEV_INITRD */
 }
 
+
 /*
  * We enter here early on, when the Open Firmware prom is still
  * handling exceptions and the MMU hash table for us.
@@ -2553,6 +2844,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
         * between pSeries SMP and pSeries LPAR
         */
        RELOC(of_platform) = prom_find_machine_type();
+       prom_printf("Detected machine type: %x\n", RELOC(of_platform));
 
 #ifndef CONFIG_RELOCATABLE
        /* Bail if this is a kdump kernel. */
@@ -2565,7 +2857,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
         */
        prom_check_initrd(r3, r4);
 
-#ifdef CONFIG_PPC_PSERIES
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
        /*
         * On pSeries, inform the firmware about our capabilities
         */
@@ -2611,14 +2903,33 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
 #endif
 
        /*
-        * On non-powermacs, try to instantiate RTAS and puts all CPUs
-        * in spin-loops. PowerMacs don't have a working RTAS and use
-        * a different way to spin CPUs
+        * On non-powermacs, try to instantiate RTAS. PowerMacs don't
+        * have a usable RTAS implementation.
         */
-       if (RELOC(of_platform) != PLATFORM_POWERMAC) {
+       if (RELOC(of_platform) != PLATFORM_POWERMAC &&
+           RELOC(of_platform) != PLATFORM_OPAL)
                prom_instantiate_rtas();
+
+#ifdef CONFIG_PPC_POWERNV
+       /* Detect HAL and try instanciating it & doing takeover */
+       if (RELOC(of_platform) == PLATFORM_PSERIES_LPAR) {
+               prom_query_opal();
+               if (RELOC(of_platform) == PLATFORM_OPAL) {
+                       prom_opal_hold_cpus();
+                       prom_opal_takeover();
+               }
+       } else if (RELOC(of_platform) == PLATFORM_OPAL)
+               prom_instantiate_opal();
+#endif
+
+       /*
+        * On non-powermacs, put all CPUs in spin-loops.
+        *
+        * PowerMacs use a different mechanism to spin CPUs
+        */
+       if (RELOC(of_platform) != PLATFORM_POWERMAC &&
+           RELOC(of_platform) != PLATFORM_OPAL)
                prom_hold_cpus();
-       }
 
        /*
         * Fill in some infos for use by the kernel later on
@@ -2685,7 +2996,13 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
        reloc_got2(-offset);
 #endif
 
-       __start(hdr, kbase, 0);
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+       /* OPAL early debug gets the OPAL base & entry in r8 and r9 */
+       __start(hdr, kbase, 0, 0, 0,
+               RELOC(prom_opal_base), RELOC(prom_opal_entry));
+#else
+       __start(hdr, kbase, 0, 0, 0, 0, 0);
+#endif
 
        return 0;
 }
index 9f82f49..70f4286 100644 (file)
@@ -20,7 +20,9 @@ WHITELIST="add_reloc_offset __bss_start __bss_stop copy_and_flush
 _end enter_prom memcpy memset reloc_offset __secondary_hold
 __secondary_hold_acknowledge __secondary_hold_spinloop __start
 strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224
-reloc_got2 kernstart_addr memstart_addr linux_banner"
+reloc_got2 kernstart_addr memstart_addr linux_banner _stext
+opal_query_takeover opal_do_takeover opal_enter_rtas opal_secondary_entry
+boot_command_line"
 
 NM="$1"
 OBJ="$2"
index 05b7dd2..18447c4 100644 (file)
@@ -1497,9 +1497,14 @@ long arch_ptrace(struct task_struct *child, long request,
                if (index < PT_FPR0) {
                        tmp = ptrace_get_reg(child, (int) index);
                } else {
+                       unsigned int fpidx = index - PT_FPR0;
+
                        flush_fp_to_thread(child);
-                       tmp = ((unsigned long *)child->thread.fpr)
-                               [TS_FPRWIDTH * (index - PT_FPR0)];
+                       if (fpidx < (PT_FPSCR - PT_FPR0))
+                               tmp = ((unsigned long *)child->thread.fpr)
+                                       [fpidx * TS_FPRWIDTH];
+                       else
+                               tmp = child->thread.fpscr.val;
                }
                ret = put_user(tmp, datalp);
                break;
@@ -1525,9 +1530,14 @@ long arch_ptrace(struct task_struct *child, long request,
                if (index < PT_FPR0) {
                        ret = ptrace_put_reg(child, index, data);
                } else {
+                       unsigned int fpidx = index - PT_FPR0;
+
                        flush_fp_to_thread(child);
-                       ((unsigned long *)child->thread.fpr)
-                               [TS_FPRWIDTH * (index - PT_FPR0)] = data;
+                       if (fpidx < (PT_FPSCR - PT_FPR0))
+                               ((unsigned long *)child->thread.fpr)
+                                       [fpidx * TS_FPRWIDTH] = data;
+                       else
+                               child->thread.fpscr.val = data;
                        ret = 0;
                }
                break;
index 209135a..c1ce863 100644 (file)
@@ -117,7 +117,7 @@ notrace unsigned long __init early_init(unsigned long dt_ptr)
  * This is called very early on the boot process, after a minimal
  * MMU environment has been set up but before MMU_init is called.
  */
-notrace void __init machine_init(unsigned long dt_ptr)
+notrace void __init machine_init(u64 dt_ptr)
 {
        lockdep_init();
 
index aebef13..d4168c9 100644 (file)
@@ -278,14 +278,14 @@ static void __init initialize_cache_info(void)
 
        DBG(" -> initialize_cache_info()\n");
 
-       for (np = NULL; (np = of_find_node_by_type(np, "cpu"));) {
+       for_each_node_by_type(np, "cpu") {
                num_cpus += 1;
 
-               /* We're assuming *all* of the CPUs have the same
+               /*
+                * We're assuming *all* of the CPUs have the same
                 * d-cache and i-cache sizes... -Peter
                 */
-
-               if ( num_cpus == 1 ) {
+               if (num_cpus == 1) {
                        const u32 *sizep, *lsizep;
                        u32 size, lsize;
 
@@ -294,10 +294,13 @@ static void __init initialize_cache_info(void)
                        sizep = of_get_property(np, "d-cache-size", NULL);
                        if (sizep != NULL)
                                size = *sizep;
-                       lsizep = of_get_property(np, "d-cache-block-size", NULL);
+                       lsizep = of_get_property(np, "d-cache-block-size",
+                                                NULL);
                        /* fallback if block size missing */
                        if (lsizep == NULL)
-                               lsizep = of_get_property(np, "d-cache-line-size", NULL);
+                               lsizep = of_get_property(np,
+                                                        "d-cache-line-size",
+                                                        NULL);
                        if (lsizep != NULL)
                                lsize = *lsizep;
                        if (sizep == 0 || lsizep == 0)
@@ -314,9 +317,12 @@ static void __init initialize_cache_info(void)
                        sizep = of_get_property(np, "i-cache-size", NULL);
                        if (sizep != NULL)
                                size = *sizep;
-                       lsizep = of_get_property(np, "i-cache-block-size", NULL);
+                       lsizep = of_get_property(np, "i-cache-block-size",
+                                                NULL);
                        if (lsizep == NULL)
-                               lsizep = of_get_property(np, "i-cache-line-size", NULL);
+                               lsizep = of_get_property(np,
+                                                        "i-cache-line-size",
+                                                        NULL);
                        if (lsizep != NULL)
                                lsize = *lsizep;
                        if (sizep == 0 || lsizep == 0)
index 7bf2187..af7e772 100644 (file)
 static DEFINE_PER_CPU(struct task_struct *, idle_thread_array);
 #define get_idle_for_cpu(x)      (per_cpu(idle_thread_array, x))
 #define set_idle_for_cpu(x, p)   (per_cpu(idle_thread_array, x) = (p))
+
+/* State of each CPU during hotplug phases */
+static DEFINE_PER_CPU(int, cpu_state) = { 0 };
+
 #else
 static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;
 #define get_idle_for_cpu(x)      (idle_thread_array[(x)])
@@ -104,12 +108,25 @@ int __devinit smp_generic_kick_cpu(int nr)
         * cpu_start field to become non-zero After we set cpu_start,
         * the processor will continue on to secondary_start
         */
-       paca[nr].cpu_start = 1;
-       smp_mb();
+       if (!paca[nr].cpu_start) {
+               paca[nr].cpu_start = 1;
+               smp_mb();
+               return 0;
+       }
+
+#ifdef CONFIG_HOTPLUG_CPU
+       /*
+        * Ok it's not there, so it might be soft-unplugged, let's
+        * try to bring it back
+        */
+       per_cpu(cpu_state, nr) = CPU_UP_PREPARE;
+       smp_wmb();
+       smp_send_reschedule(nr);
+#endif /* CONFIG_HOTPLUG_CPU */
 
        return 0;
 }
-#endif
+#endif /* CONFIG_PPC64 */
 
 static irqreturn_t call_function_action(int irq, void *data)
 {
@@ -357,8 +374,6 @@ void __devinit smp_prepare_boot_cpu(void)
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-/* State of each CPU during hotplug phases */
-static DEFINE_PER_CPU(int, cpu_state) = { 0 };
 
 int generic_cpu_disable(void)
 {
@@ -406,6 +421,11 @@ void generic_set_cpu_dead(unsigned int cpu)
 {
        per_cpu(cpu_state, cpu) = CPU_DEAD;
 }
+
+int generic_check_cpu_restart(unsigned int cpu)
+{
+       return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE;
+}
 #endif
 
 struct create_idle {
index aa17b76..641f9ad 100644 (file)
@@ -33,6 +33,6 @@ void save_processor_state(void)
 void restore_processor_state(void)
 {
 #ifdef CONFIG_PPC32
-       switch_mmu_context(NULL, current->active_mm);
+       switch_mmu_context(current->active_mm, current->active_mm);
 #endif
 }
index f19d977..4e59082 100644 (file)
@@ -457,7 +457,14 @@ int machine_check_e500mc(struct pt_regs *regs)
 
        if (reason & MCSR_DCPERR_MC) {
                printk("Data Cache Parity Error\n");
-               recoverable = 0;
+
+               /*
+                * In write shadow mode we auto-recover from the error, but it
+                * may still get logged and cause a machine check.  We should
+                * only treat the non-write shadow case as non-recoverable.
+                */
+               if (!(mfspr(SPRN_L1CSR2) & L1CSR2_DCWS))
+                       recoverable = 0;
        }
 
        if (reason & MCSR_L2MMU_MHIT) {
index b4607a9..57fa2c0 100644 (file)
@@ -69,6 +69,12 @@ void __init udbg_early_init(void)
        udbg_init_wsp();
 #elif defined(CONFIG_PPC_EARLY_DEBUG_EHV_BC)
        udbg_init_ehv_bc();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_PS3GELIC)
+       udbg_init_ps3gelic();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_OPAL_RAW)
+       udbg_init_debug_opal_raw();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_OPAL_HVSI)
+       udbg_init_debug_opal_hvsi();
 #endif
 
 #ifdef CONFIG_PPC_EARLY_DEBUG
index 1b695fd..34d291d 100644 (file)
@@ -605,15 +605,20 @@ static int vio_dma_iommu_dma_supported(struct device *dev, u64 mask)
         return dma_iommu_ops.dma_supported(dev, mask);
 }
 
-struct dma_map_ops vio_dma_mapping_ops = {
-       .alloc_coherent = vio_dma_iommu_alloc_coherent,
-       .free_coherent  = vio_dma_iommu_free_coherent,
-       .map_sg         = vio_dma_iommu_map_sg,
-       .unmap_sg       = vio_dma_iommu_unmap_sg,
-       .map_page       = vio_dma_iommu_map_page,
-       .unmap_page     = vio_dma_iommu_unmap_page,
-       .dma_supported  = vio_dma_iommu_dma_supported,
+static u64 vio_dma_get_required_mask(struct device *dev)
+{
+        return dma_iommu_ops.get_required_mask(dev);
+}
 
+struct dma_map_ops vio_dma_mapping_ops = {
+       .alloc_coherent    = vio_dma_iommu_alloc_coherent,
+       .free_coherent     = vio_dma_iommu_free_coherent,
+       .map_sg            = vio_dma_iommu_map_sg,
+       .unmap_sg          = vio_dma_iommu_unmap_sg,
+       .map_page          = vio_dma_iommu_map_page,
+       .unmap_page        = vio_dma_iommu_unmap_page,
+       .dma_supported     = vio_dma_iommu_dma_supported,
+       .get_required_mask = vio_dma_get_required_mask,
 };
 
 /**
index 6227920..a73f088 100644 (file)
@@ -171,10 +171,6 @@ static unsigned long insn_type(unsigned long speinsn)
        case EFDNABS:   ret = XA;       break;
        case EFDNEG:    ret = XA;       break;
        case EFDSUB:    ret = AB;       break;
-
-       default:
-               printk(KERN_ERR "\nOoops! SPE instruction no type found.");
-               printk(KERN_ERR "\ninst code: %08lx\n", speinsn);
        }
 
        return ret;
@@ -195,7 +191,7 @@ int do_spe_mathemu(struct pt_regs *regs)
 
        type = insn_type(speinsn);
        if (type == NOTYPE)
-               return -ENOSYS;
+               goto illegal;
 
        func = speinsn & 0x7ff;
        fc = (speinsn >> 21) & 0x1f;
@@ -212,12 +208,10 @@ int do_spe_mathemu(struct pt_regs *regs)
 
        __FPU_FPSCR = mfspr(SPRN_SPEFSCR);
 
-#ifdef DEBUG
-       printk("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR);
-       printk("vc: %08x  %08x\n", vc.wp[0], vc.wp[1]);
-       printk("va: %08x  %08x\n", va.wp[0], va.wp[1]);
-       printk("vb: %08x  %08x\n", vb.wp[0], vb.wp[1]);
-#endif
+       pr_debug("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR);
+       pr_debug("vc: %08x  %08x\n", vc.wp[0], vc.wp[1]);
+       pr_debug("va: %08x  %08x\n", va.wp[0], va.wp[1]);
+       pr_debug("vb: %08x  %08x\n", vb.wp[0], vb.wp[1]);
 
        switch (src) {
        case SPFP: {
@@ -235,10 +229,8 @@ int do_spe_mathemu(struct pt_regs *regs)
                        break;
                }
 
-#ifdef DEBUG
-               printk("SA: %ld %08lx %ld (%ld)\n", SA_s, SA_f, SA_e, SA_c);
-               printk("SB: %ld %08lx %ld (%ld)\n", SB_s, SB_f, SB_e, SB_c);
-#endif
+               pr_debug("SA: %ld %08lx %ld (%ld)\n", SA_s, SA_f, SA_e, SA_c);
+               pr_debug("SB: %ld %08lx %ld (%ld)\n", SB_s, SB_f, SB_e, SB_c);
 
                switch (func) {
                case EFSABS:
@@ -305,10 +297,10 @@ int do_spe_mathemu(struct pt_regs *regs)
                        FP_DECL_D(DB);
                        FP_CLEAR_EXCEPTIONS;
                        FP_UNPACK_DP(DB, vb.dp);
-#ifdef DEBUG
-                       printk("DB: %ld %08lx %08lx %ld (%ld)\n",
+
+                       pr_debug("DB: %ld %08lx %08lx %ld (%ld)\n",
                                        DB_s, DB_f1, DB_f0, DB_e, DB_c);
-#endif
+
                        FP_CONV(S, D, 1, 2, SR, DB);
                        goto pack_s;
                }
@@ -332,9 +324,8 @@ int do_spe_mathemu(struct pt_regs *regs)
                break;
 
 pack_s:
-#ifdef DEBUG
-               printk("SR: %ld %08lx %ld (%ld)\n", SR_s, SR_f, SR_e, SR_c);
-#endif
+               pr_debug("SR: %ld %08lx %ld (%ld)\n", SR_s, SR_f, SR_e, SR_c);
+
                FP_PACK_SP(vc.wp + 1, SR);
                goto update_regs;
 
@@ -365,12 +356,10 @@ cmp_s:
                        break;
                }
 
-#ifdef DEBUG
-               printk("DA: %ld %08lx %08lx %ld (%ld)\n",
+               pr_debug("DA: %ld %08lx %08lx %ld (%ld)\n",
                                DA_s, DA_f1, DA_f0, DA_e, DA_c);
-               printk("DB: %ld %08lx %08lx %ld (%ld)\n",
+               pr_debug("DB: %ld %08lx %08lx %ld (%ld)\n",
                                DB_s, DB_f1, DB_f0, DB_e, DB_c);
-#endif
 
                switch (func) {
                case EFDABS:
@@ -438,10 +427,10 @@ cmp_s:
                        FP_DECL_S(SB);
                        FP_CLEAR_EXCEPTIONS;
                        FP_UNPACK_SP(SB, vb.wp + 1);
-#ifdef DEBUG
-                       printk("SB: %ld %08lx %ld (%ld)\n",
+
+                       pr_debug("SB: %ld %08lx %ld (%ld)\n",
                                        SB_s, SB_f, SB_e, SB_c);
-#endif
+
                        FP_CONV(D, S, 2, 1, DR, SB);
                        goto pack_d;
                }
@@ -471,10 +460,9 @@ cmp_s:
                break;
 
 pack_d:
-#ifdef DEBUG
-               printk("DR: %ld %08lx %08lx %ld (%ld)\n",
+               pr_debug("DR: %ld %08lx %08lx %ld (%ld)\n",
                                DR_s, DR_f1, DR_f0, DR_e, DR_c);
-#endif
+
                FP_PACK_DP(vc.dp, DR);
                goto update_regs;
 
@@ -511,12 +499,14 @@ cmp_d:
                        break;
                }
 
-#ifdef DEBUG
-               printk("SA0: %ld %08lx %ld (%ld)\n", SA0_s, SA0_f, SA0_e, SA0_c);
-               printk("SA1: %ld %08lx %ld (%ld)\n", SA1_s, SA1_f, SA1_e, SA1_c);
-               printk("SB0: %ld %08lx %ld (%ld)\n", SB0_s, SB0_f, SB0_e, SB0_c);
-               printk("SB1: %ld %08lx %ld (%ld)\n", SB1_s, SB1_f, SB1_e, SB1_c);
-#endif
+               pr_debug("SA0: %ld %08lx %ld (%ld)\n",
+                               SA0_s, SA0_f, SA0_e, SA0_c);
+               pr_debug("SA1: %ld %08lx %ld (%ld)\n",
+                               SA1_s, SA1_f, SA1_e, SA1_c);
+               pr_debug("SB0: %ld %08lx %ld (%ld)\n",
+                               SB0_s, SB0_f, SB0_e, SB0_c);
+               pr_debug("SB1: %ld %08lx %ld (%ld)\n",
+                               SB1_s, SB1_f, SB1_e, SB1_c);
 
                switch (func) {
                case EVFSABS:
@@ -605,10 +595,11 @@ cmp_d:
                break;
 
 pack_vs:
-#ifdef DEBUG
-               printk("SR0: %ld %08lx %ld (%ld)\n", SR0_s, SR0_f, SR0_e, SR0_c);
-               printk("SR1: %ld %08lx %ld (%ld)\n", SR1_s, SR1_f, SR1_e, SR1_c);
-#endif
+               pr_debug("SR0: %ld %08lx %ld (%ld)\n",
+                               SR0_s, SR0_f, SR0_e, SR0_c);
+               pr_debug("SR1: %ld %08lx %ld (%ld)\n",
+                               SR1_s, SR1_f, SR1_e, SR1_c);
+
                FP_PACK_SP(vc.wp, SR0);
                FP_PACK_SP(vc.wp + 1, SR1);
                goto update_regs;
@@ -646,14 +637,12 @@ update_regs:
        current->thread.evr[fc] = vc.wp[0];
        regs->gpr[fc] = vc.wp[1];
 
-#ifdef DEBUG
-       printk("ccr = %08lx\n", regs->ccr);
-       printk("cur exceptions = %08x spefscr = %08lx\n",
+       pr_debug("ccr = %08lx\n", regs->ccr);
+       pr_debug("cur exceptions = %08x spefscr = %08lx\n",
                        FP_CUR_EXCEPTIONS, __FPU_FPSCR);
-       printk("vc: %08x  %08x\n", vc.wp[0], vc.wp[1]);
-       printk("va: %08x  %08x\n", va.wp[0], va.wp[1]);
-       printk("vb: %08x  %08x\n", vb.wp[0], vb.wp[1]);
-#endif
+       pr_debug("vc: %08x  %08x\n", vc.wp[0], vc.wp[1]);
+       pr_debug("va: %08x  %08x\n", va.wp[0], va.wp[1]);
+       pr_debug("vb: %08x  %08x\n", vb.wp[0], vb.wp[1]);
 
        return 0;
 
@@ -661,9 +650,7 @@ illegal:
        if (have_e500_cpu_a005_erratum) {
                /* according to e500 cpu a005 erratum, reissue efp inst */
                regs->nip -= 4;
-#ifdef DEBUG
-               printk(KERN_DEBUG "re-issue efp inst: %08lx\n", speinsn);
-#endif
+               pr_debug("re-issue efp inst: %08lx\n", speinsn);
                return 0;
        }
 
@@ -685,13 +672,20 @@ int speround_handler(struct pt_regs *regs)
        type = insn_type(speinsn & 0x7ff);
        if (type == XCR) return -ENOSYS;
 
+       __FPU_FPSCR = mfspr(SPRN_SPEFSCR);
+       pr_debug("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR);
+
+       /* No need to round if the result is exact */
+       if (!(__FPU_FPSCR & FP_EX_INEXACT))
+               return 0;
+
        fc = (speinsn >> 21) & 0x1f;
        s_lo = regs->gpr[fc] & SIGN_BIT_S;
        s_hi = current->thread.evr[fc] & SIGN_BIT_S;
        fgpr.wp[0] = current->thread.evr[fc];
        fgpr.wp[1] = regs->gpr[fc];
 
-       __FPU_FPSCR = mfspr(SPRN_SPEFSCR);
+       pr_debug("round fgpr: %08x  %08x\n", fgpr.wp[0], fgpr.wp[1]);
 
        switch ((speinsn >> 5) & 0x7) {
        /* Since SPE instructions on E500 core can handle round to nearest
@@ -731,6 +725,8 @@ int speround_handler(struct pt_regs *regs)
        current->thread.evr[fc] = fgpr.wp[0];
        regs->gpr[fc] = fgpr.wp[1];
 
+       pr_debug("  to fgpr: %08x  %08x\n", fgpr.wp[0], fgpr.wp[1]);
+
        return 0;
 }
 
index bdca46e..991ee81 100644 (file)
@@ -29,6 +29,7 @@ obj-$(CONFIG_PPC_MM_SLICES)   += slice.o
 ifeq ($(CONFIG_HUGETLB_PAGE),y)
 obj-y                          += hugetlbpage.o
 obj-$(CONFIG_PPC_STD_MMU_64)   += hugetlbpage-hash64.o
+obj-$(CONFIG_PPC_BOOK3E_MMU)   += hugetlbpage-book3e.o
 endif
 obj-$(CONFIG_PPC_SUBPAGE_PROT) += subpage-prot.o
 obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o
index f7802c8..66a6fd3 100644 (file)
@@ -101,17 +101,17 @@ unsigned long p_mapped_by_tlbcam(phys_addr_t pa)
 
 /*
  * Set up a variable-size TLB entry (tlbcam). The parameters are not checked;
- * in particular size must be a power of 4 between 4k and 256M (or 1G, for cpus
- * that support extended page sizes).  Note that while some cpus support a
- * page size of 4G, we don't allow its use here.
+ * in particular size must be a power of 4 between 4k and the max supported by
+ * an implementation; max may further be limited by what can be represented in
+ * an unsigned long (for example, 32-bit implementations cannot support a 4GB
+ * size).
  */
 static void settlbcam(int index, unsigned long virt, phys_addr_t phys,
                unsigned long size, unsigned long flags, unsigned int pid)
 {
-       unsigned int tsize, lz;
+       unsigned int tsize;
 
-       asm (PPC_CNTLZL "%0,%1" : "=r" (lz) : "r" (size));
-       tsize = 21 - lz;
+       tsize = __ilog2(size) - 10;
 
 #ifdef CONFIG_SMP
        if ((flags & _PAGE_NO_CACHE) == 0)
@@ -146,29 +146,36 @@ static void settlbcam(int index, unsigned long virt, phys_addr_t phys,
        loadcam_entry(index);
 }
 
+unsigned long calc_cam_sz(unsigned long ram, unsigned long virt,
+                         phys_addr_t phys)
+{
+       unsigned int camsize = __ilog2(ram) & ~1U;
+       unsigned int align = __ffs(virt | phys) & ~1U;
+       unsigned long max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xf;
+
+       /* Convert (4^max) kB to (2^max) bytes */
+       max_cam = max_cam * 2 + 10;
+
+       if (camsize > align)
+               camsize = align;
+       if (camsize > max_cam)
+               camsize = max_cam;
+
+       return 1UL << camsize;
+}
+
 unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx)
 {
        int i;
        unsigned long virt = PAGE_OFFSET;
        phys_addr_t phys = memstart_addr;
        unsigned long amount_mapped = 0;
-       unsigned long max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xf;
-
-       /* Convert (4^max) kB to (2^max) bytes */
-       max_cam = max_cam * 2 + 10;
 
        /* Calculate CAM values */
        for (i = 0; ram && i < max_cam_idx; i++) {
-               unsigned int camsize = __ilog2(ram) & ~1U;
-               unsigned int align = __ffs(virt | phys) & ~1U;
                unsigned long cam_sz;
 
-               if (camsize > align)
-                       camsize = align;
-               if (camsize > max_cam)
-                       camsize = max_cam;
-
-               cam_sz = 1UL << camsize;
+               cam_sz = calc_cam_sz(ram, virt, phys);
                settlbcam(i, virt, phys, cam_sz, PAGE_KERNEL_X, 0);
 
                ram -= cam_sz;
index 26b2872..1628201 100644 (file)
@@ -105,9 +105,6 @@ int mmu_kernel_ssize = MMU_SEGSIZE_256M;
 int mmu_highuser_ssize = MMU_SEGSIZE_256M;
 u16 mmu_slb_size = 64;
 EXPORT_SYMBOL_GPL(mmu_slb_size);
-#ifdef CONFIG_HUGETLB_PAGE
-unsigned int HPAGE_SHIFT;
-#endif
 #ifdef CONFIG_PPC_64K_PAGES
 int mmu_ci_restrictions;
 #endif
@@ -534,11 +531,11 @@ static unsigned long __init htab_get_table_size(void)
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-void create_section_mapping(unsigned long start, unsigned long end)
+int create_section_mapping(unsigned long start, unsigned long end)
 {
-       BUG_ON(htab_bolt_mapping(start, end, __pa(start),
+       return htab_bolt_mapping(start, end, __pa(start),
                                 pgprot_val(PAGE_KERNEL), mmu_linear_psize,
-                                mmu_kernel_ssize));
+                                mmu_kernel_ssize);
 }
 
 int remove_section_mapping(unsigned long start, unsigned long end)
diff --git a/arch/powerpc/mm/hugetlbpage-book3e.c b/arch/powerpc/mm/hugetlbpage-book3e.c
new file mode 100644 (file)
index 0000000..343ad0b
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * PPC Huge TLB Page Support for Book3E MMU
+ *
+ * Copyright (C) 2009 David Gibson, IBM Corporation.
+ * Copyright (C) 2011 Becky Bruce, Freescale Semiconductor
+ *
+ */
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+
+static inline int mmu_get_tsize(int psize)
+{
+       return mmu_psize_defs[psize].enc;
+}
+
+static inline int book3e_tlb_exists(unsigned long ea, unsigned long pid)
+{
+       int found = 0;
+
+       mtspr(SPRN_MAS6, pid << 16);
+       if (mmu_has_feature(MMU_FTR_USE_TLBRSRV)) {
+               asm volatile(
+                       "li     %0,0\n"
+                       "tlbsx. 0,%1\n"
+                       "bne    1f\n"
+                       "li     %0,1\n"
+                       "1:\n"
+                       : "=&r"(found) : "r"(ea));
+       } else {
+               asm volatile(
+                       "tlbsx  0,%1\n"
+                       "mfspr  %0,0x271\n"
+                       "srwi   %0,%0,31\n"
+                       : "=&r"(found) : "r"(ea));
+       }
+
+       return found;
+}
+
+void book3e_hugetlb_preload(struct mm_struct *mm, unsigned long ea, pte_t pte)
+{
+       unsigned long mas1, mas2;
+       u64 mas7_3;
+       unsigned long psize, tsize, shift;
+       unsigned long flags;
+
+#ifdef CONFIG_PPC_FSL_BOOK3E
+       int index, lz, ncams;
+       struct vm_area_struct *vma;
+#endif
+
+       if (unlikely(is_kernel_addr(ea)))
+               return;
+
+#ifdef CONFIG_PPC_MM_SLICES
+       psize = mmu_get_tsize(get_slice_psize(mm, ea));
+       tsize = mmu_get_psize(psize);
+       shift = mmu_psize_defs[psize].shift;
+#else
+       vma = find_vma(mm, ea);
+       psize = vma_mmu_pagesize(vma);  /* returns actual size in bytes */
+       asm (PPC_CNTLZL "%0,%1" : "=r" (lz) : "r" (psize));
+       shift = 31 - lz;
+       tsize = 21 - lz;
+#endif
+
+       /*
+        * We can't be interrupted while we're setting up the MAS
+        * regusters or after we've confirmed that no tlb exists.
+        */
+       local_irq_save(flags);
+
+       if (unlikely(book3e_tlb_exists(ea, mm->context.id))) {
+               local_irq_restore(flags);
+               return;
+       }
+
+#ifdef CONFIG_PPC_FSL_BOOK3E
+       ncams = mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY;
+
+       /* We have to use the CAM(TLB1) on FSL parts for hugepages */
+       index = __get_cpu_var(next_tlbcam_idx);
+       mtspr(SPRN_MAS0, MAS0_ESEL(index) | MAS0_TLBSEL(1));
+
+       /* Just round-robin the entries and wrap when we hit the end */
+       if (unlikely(index == ncams - 1))
+               __get_cpu_var(next_tlbcam_idx) = tlbcam_index;
+       else
+               __get_cpu_var(next_tlbcam_idx)++;
+#endif
+       mas1 = MAS1_VALID | MAS1_TID(mm->context.id) | MAS1_TSIZE(tsize);
+       mas2 = ea & ~((1UL << shift) - 1);
+       mas2 |= (pte_val(pte) >> PTE_WIMGE_SHIFT) & MAS2_WIMGE_MASK;
+       mas7_3 = (u64)pte_pfn(pte) << PAGE_SHIFT;
+       mas7_3 |= (pte_val(pte) >> PTE_BAP_SHIFT) & MAS3_BAP_MASK;
+       if (!pte_dirty(pte))
+               mas7_3 &= ~(MAS3_SW|MAS3_UW);
+
+       mtspr(SPRN_MAS1, mas1);
+       mtspr(SPRN_MAS2, mas2);
+
+       if (mmu_has_feature(MMU_FTR_USE_PAIRED_MAS)) {
+               mtspr(SPRN_MAS7_MAS3, mas7_3);
+       } else {
+               mtspr(SPRN_MAS7, upper_32_bits(mas7_3));
+               mtspr(SPRN_MAS3, lower_32_bits(mas7_3));
+       }
+
+       asm volatile ("tlbwe");
+
+       local_irq_restore(flags);
+}
+
+void flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
+{
+       struct hstate *hstate = hstate_file(vma->vm_file);
+       unsigned long tsize = huge_page_shift(hstate) - 10;
+
+       __flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr, tsize, 0);
+
+}
index da5eb38..5964371 100644 (file)
@@ -1,7 +1,8 @@
 /*
- * PPC64 (POWER4) Huge TLB Page Support for Kernel.
+ * PPC Huge TLB Page Support for Kernel.
  *
  * Copyright (C) 2003 David Gibson, IBM Corporation.
+ * Copyright (C) 2011 Becky Bruce, Freescale Semiconductor
  *
  * Based on the IA-32 version:
  * Copyright (C) 2002, Rohit Seth <rohit.seth@intel.com>
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/hugetlb.h>
+#include <linux/of_fdt.h>
+#include <linux/memblock.h>
+#include <linux/bootmem.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/tlb.h>
+#include <asm/setup.h>
 
 #define PAGE_SHIFT_64K 16
 #define PAGE_SHIFT_16M 24
 #define PAGE_SHIFT_16G 34
 
-#define MAX_NUMBER_GPAGES      1024
+unsigned int HPAGE_SHIFT;
 
-/* Tracks the 16G pages after the device tree is scanned and before the
- * huge_boot_pages list is ready.  */
-static unsigned long gpage_freearray[MAX_NUMBER_GPAGES];
+/*
+ * Tracks gpages after the device tree is scanned and before the
+ * huge_boot_pages list is ready.  On 64-bit implementations, this is
+ * just used to track 16G pages and so is a single array.  32-bit
+ * implementations may have more than one gpage size due to limitations
+ * of the memory allocators, so we need multiple arrays
+ */
+#ifdef CONFIG_PPC64
+#define MAX_NUMBER_GPAGES      1024
+static u64 gpage_freearray[MAX_NUMBER_GPAGES];
 static unsigned nr_gpages;
-
-/* Flag to mark huge PD pointers.  This means pmd_bad() and pud_bad()
- * will choke on pointers to hugepte tables, which is handy for
- * catching screwups early. */
+#else
+#define MAX_NUMBER_GPAGES      128
+struct psize_gpages {
+       u64 gpage_list[MAX_NUMBER_GPAGES];
+       unsigned int nr_gpages;
+};
+static struct psize_gpages gpage_freearray[MMU_PAGE_COUNT];
+#endif
 
 static inline int shift_to_mmu_psize(unsigned int shift)
 {
@@ -49,25 +65,6 @@ static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
 
 #define hugepd_none(hpd)       ((hpd).pd == 0)
 
-static inline pte_t *hugepd_page(hugepd_t hpd)
-{
-       BUG_ON(!hugepd_ok(hpd));
-       return (pte_t *)((hpd.pd & ~HUGEPD_SHIFT_MASK) | 0xc000000000000000);
-}
-
-static inline unsigned int hugepd_shift(hugepd_t hpd)
-{
-       return hpd.pd & HUGEPD_SHIFT_MASK;
-}
-
-static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr, unsigned pdshift)
-{
-       unsigned long idx = (addr & ((1UL << pdshift) - 1)) >> hugepd_shift(*hpdp);
-       pte_t *dir = hugepd_page(*hpdp);
-
-       return dir + idx;
-}
-
 pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift)
 {
        pgd_t *pg;
@@ -93,7 +90,7 @@ pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift
                        if (is_hugepd(pm))
                                hpdp = (hugepd_t *)pm;
                        else if (!pmd_none(*pm)) {
-                               return pte_offset_map(pm, ea);
+                               return pte_offset_kernel(pm, ea);
                        }
                }
        }
@@ -114,8 +111,18 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
                           unsigned long address, unsigned pdshift, unsigned pshift)
 {
-       pte_t *new = kmem_cache_zalloc(PGT_CACHE(pdshift - pshift),
-                                      GFP_KERNEL|__GFP_REPEAT);
+       struct kmem_cache *cachep;
+       pte_t *new;
+
+#ifdef CONFIG_PPC64
+       cachep = PGT_CACHE(pdshift - pshift);
+#else
+       int i;
+       int num_hugepd = 1 << (pshift - pdshift);
+       cachep = hugepte_cache;
+#endif
+
+       new = kmem_cache_zalloc(cachep, GFP_KERNEL|__GFP_REPEAT);
 
        BUG_ON(pshift > HUGEPD_SHIFT_MASK);
        BUG_ON((unsigned long)new & HUGEPD_SHIFT_MASK);
@@ -124,10 +131,31 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
                return -ENOMEM;
 
        spin_lock(&mm->page_table_lock);
+#ifdef CONFIG_PPC64
        if (!hugepd_none(*hpdp))
-               kmem_cache_free(PGT_CACHE(pdshift - pshift), new);
+               kmem_cache_free(cachep, new);
        else
-               hpdp->pd = ((unsigned long)new & ~0x8000000000000000) | pshift;
+               hpdp->pd = ((unsigned long)new & ~PD_HUGE) | pshift;
+#else
+       /*
+        * We have multiple higher-level entries that point to the same
+        * actual pte location.  Fill in each as we go and backtrack on error.
+        * We need all of these so the DTLB pgtable walk code can find the
+        * right higher-level entry without knowing if it's a hugepage or not.
+        */
+       for (i = 0; i < num_hugepd; i++, hpdp++) {
+               if (unlikely(!hugepd_none(*hpdp)))
+                       break;
+               else
+                       hpdp->pd = ((unsigned long)new & ~PD_HUGE) | pshift;
+       }
+       /* If we bailed from the for loop early, an error occurred, clean up */
+       if (i < num_hugepd) {
+               for (i = i - 1 ; i >= 0; i--, hpdp--)
+                       hpdp->pd = 0;
+               kmem_cache_free(cachep, new);
+       }
+#endif
        spin_unlock(&mm->page_table_lock);
        return 0;
 }
@@ -169,11 +197,132 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz
        return hugepte_offset(hpdp, addr, pdshift);
 }
 
+#ifdef CONFIG_PPC32
 /* Build list of addresses of gigantic pages.  This function is used in early
  * boot before the buddy or bootmem allocator is setup.
  */
-void add_gpage(unsigned long addr, unsigned long page_size,
-       unsigned long number_of_pages)
+void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages)
+{
+       unsigned int idx = shift_to_mmu_psize(__ffs(page_size));
+       int i;
+
+       if (addr == 0)
+               return;
+
+       gpage_freearray[idx].nr_gpages = number_of_pages;
+
+       for (i = 0; i < number_of_pages; i++) {
+               gpage_freearray[idx].gpage_list[i] = addr;
+               addr += page_size;
+       }
+}
+
+/*
+ * Moves the gigantic page addresses from the temporary list to the
+ * huge_boot_pages list.
+ */
+int alloc_bootmem_huge_page(struct hstate *hstate)
+{
+       struct huge_bootmem_page *m;
+       int idx = shift_to_mmu_psize(hstate->order + PAGE_SHIFT);
+       int nr_gpages = gpage_freearray[idx].nr_gpages;
+
+       if (nr_gpages == 0)
+               return 0;
+
+#ifdef CONFIG_HIGHMEM
+       /*
+        * If gpages can be in highmem we can't use the trick of storing the
+        * data structure in the page; allocate space for this
+        */
+       m = alloc_bootmem(sizeof(struct huge_bootmem_page));
+       m->phys = gpage_freearray[idx].gpage_list[--nr_gpages];
+#else
+       m = phys_to_virt(gpage_freearray[idx].gpage_list[--nr_gpages]);
+#endif
+
+       list_add(&m->list, &huge_boot_pages);
+       gpage_freearray[idx].nr_gpages = nr_gpages;
+       gpage_freearray[idx].gpage_list[nr_gpages] = 0;
+       m->hstate = hstate;
+
+       return 1;
+}
+/*
+ * Scan the command line hugepagesz= options for gigantic pages; store those in
+ * a list that we use to allocate the memory once all options are parsed.
+ */
+
+unsigned long gpage_npages[MMU_PAGE_COUNT];
+
+static int __init do_gpage_early_setup(char *param, char *val)
+{
+       static phys_addr_t size;
+       unsigned long npages;
+
+       /*
+        * The hugepagesz and hugepages cmdline options are interleaved.  We
+        * use the size variable to keep track of whether or not this was done
+        * properly and skip over instances where it is incorrect.  Other
+        * command-line parsing code will issue warnings, so we don't need to.
+        *
+        */
+       if ((strcmp(param, "default_hugepagesz") == 0) ||
+           (strcmp(param, "hugepagesz") == 0)) {
+               size = memparse(val, NULL);
+       } else if (strcmp(param, "hugepages") == 0) {
+               if (size != 0) {
+                       if (sscanf(val, "%lu", &npages) <= 0)
+                               npages = 0;
+                       gpage_npages[shift_to_mmu_psize(__ffs(size))] = npages;
+                       size = 0;
+               }
+       }
+       return 0;
+}
+
+
+/*
+ * This function allocates physical space for pages that are larger than the
+ * buddy allocator can handle.  We want to allocate these in highmem because
+ * the amount of lowmem is limited.  This means that this function MUST be
+ * called before lowmem_end_addr is set up in MMU_init() in order for the lmb
+ * allocate to grab highmem.
+ */
+void __init reserve_hugetlb_gpages(void)
+{
+       static __initdata char cmdline[COMMAND_LINE_SIZE];
+       phys_addr_t size, base;
+       int i;
+
+       strlcpy(cmdline, boot_command_line, COMMAND_LINE_SIZE);
+       parse_args("hugetlb gpages", cmdline, NULL, 0, &do_gpage_early_setup);
+
+       /*
+        * Walk gpage list in reverse, allocating larger page sizes first.
+        * Skip over unsupported sizes, or sizes that have 0 gpages allocated.
+        * When we reach the point in the list where pages are no longer
+        * considered gpages, we're done.
+        */
+       for (i = MMU_PAGE_COUNT-1; i >= 0; i--) {
+               if (mmu_psize_defs[i].shift == 0 || gpage_npages[i] == 0)
+                       continue;
+               else if (mmu_psize_to_shift(i) < (MAX_ORDER + PAGE_SHIFT))
+                       break;
+
+               size = (phys_addr_t)(1ULL << mmu_psize_to_shift(i));
+               base = memblock_alloc_base(size * gpage_npages[i], size,
+                                          MEMBLOCK_ALLOC_ANYWHERE);
+               add_gpage(base, size, gpage_npages[i]);
+       }
+}
+
+#else /* PPC64 */
+
+/* Build list of addresses of gigantic pages.  This function is used in early
+ * boot before the buddy or bootmem allocator is setup.
+ */
+void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages)
 {
        if (!addr)
                return;
@@ -199,19 +348,79 @@ int alloc_bootmem_huge_page(struct hstate *hstate)
        m->hstate = hstate;
        return 1;
 }
+#endif
 
 int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
 {
        return 0;
 }
 
+#ifdef CONFIG_PPC32
+#define HUGEPD_FREELIST_SIZE \
+       ((PAGE_SIZE - sizeof(struct hugepd_freelist)) / sizeof(pte_t))
+
+struct hugepd_freelist {
+       struct rcu_head rcu;
+       unsigned int index;
+       void *ptes[0];
+};
+
+static DEFINE_PER_CPU(struct hugepd_freelist *, hugepd_freelist_cur);
+
+static void hugepd_free_rcu_callback(struct rcu_head *head)
+{
+       struct hugepd_freelist *batch =
+               container_of(head, struct hugepd_freelist, rcu);
+       unsigned int i;
+
+       for (i = 0; i < batch->index; i++)
+               kmem_cache_free(hugepte_cache, batch->ptes[i]);
+
+       free_page((unsigned long)batch);
+}
+
+static void hugepd_free(struct mmu_gather *tlb, void *hugepte)
+{
+       struct hugepd_freelist **batchp;
+
+       batchp = &__get_cpu_var(hugepd_freelist_cur);
+
+       if (atomic_read(&tlb->mm->mm_users) < 2 ||
+           cpumask_equal(mm_cpumask(tlb->mm),
+                         cpumask_of(smp_processor_id()))) {
+               kmem_cache_free(hugepte_cache, hugepte);
+               return;
+       }
+
+       if (*batchp == NULL) {
+               *batchp = (struct hugepd_freelist *)__get_free_page(GFP_ATOMIC);
+               (*batchp)->index = 0;
+       }
+
+       (*batchp)->ptes[(*batchp)->index++] = hugepte;
+       if ((*batchp)->index == HUGEPD_FREELIST_SIZE) {
+               call_rcu_sched(&(*batchp)->rcu, hugepd_free_rcu_callback);
+               *batchp = NULL;
+       }
+}
+#endif
+
 static void free_hugepd_range(struct mmu_gather *tlb, hugepd_t *hpdp, int pdshift,
                              unsigned long start, unsigned long end,
                              unsigned long floor, unsigned long ceiling)
 {
        pte_t *hugepte = hugepd_page(*hpdp);
-       unsigned shift = hugepd_shift(*hpdp);
+       int i;
+
        unsigned long pdmask = ~((1UL << pdshift) - 1);
+       unsigned int num_hugepd = 1;
+
+#ifdef CONFIG_PPC64
+       unsigned int shift = hugepd_shift(*hpdp);
+#else
+       /* Note: On 32-bit the hpdp may be the first of several */
+       num_hugepd = (1 << (hugepd_shift(*hpdp) - pdshift));
+#endif
 
        start &= pdmask;
        if (start < floor)
@@ -224,9 +433,15 @@ static void free_hugepd_range(struct mmu_gather *tlb, hugepd_t *hpdp, int pdshif
        if (end - 1 > ceiling - 1)
                return;
 
-       hpdp->pd = 0;
+       for (i = 0; i < num_hugepd; i++, hpdp++)
+               hpdp->pd = 0;
+
        tlb->need_flush = 1;
+#ifdef CONFIG_PPC64
        pgtable_free_tlb(tlb, hugepte, pdshift - shift);
+#else
+       hugepd_free(tlb, hugepte);
+#endif
 }
 
 static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud,
@@ -331,18 +546,27 @@ void hugetlb_free_pgd_range(struct mmu_gather *tlb,
         * too.
         */
 
-       pgd = pgd_offset(tlb->mm, addr);
        do {
                next = pgd_addr_end(addr, end);
+               pgd = pgd_offset(tlb->mm, addr);
                if (!is_hugepd(pgd)) {
                        if (pgd_none_or_clear_bad(pgd))
                                continue;
                        hugetlb_free_pud_range(tlb, pgd, addr, next, floor, ceiling);
                } else {
+#ifdef CONFIG_PPC32
+                       /*
+                        * Increment next by the size of the huge mapping since
+                        * on 32-bit there may be more than one entry at the pgd
+                        * level for a single hugepage, but all of them point to
+                        * the same kmem cache that holds the hugepte.
+                        */
+                       next = addr + (1 << hugepd_shift(*(hugepd_t *)pgd));
+#endif
                        free_hugepd_range(tlb, (hugepd_t *)pgd, PGDIR_SHIFT,
                                          addr, next, floor, ceiling);
                }
-       } while (pgd++, addr = next, addr != end);
+       } while (addr = next, addr != end);
 }
 
 struct page *
@@ -477,17 +701,35 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
                                        unsigned long len, unsigned long pgoff,
                                        unsigned long flags)
 {
+#ifdef CONFIG_PPC_MM_SLICES
        struct hstate *hstate = hstate_file(file);
        int mmu_psize = shift_to_mmu_psize(huge_page_shift(hstate));
 
        return slice_get_unmapped_area(addr, len, flags, mmu_psize, 1, 0);
+#else
+       return get_unmapped_area(file, addr, len, pgoff, flags);
+#endif
 }
 
 unsigned long vma_mmu_pagesize(struct vm_area_struct *vma)
 {
+#ifdef CONFIG_PPC_MM_SLICES
        unsigned int psize = get_slice_psize(vma->vm_mm, vma->vm_start);
 
        return 1UL << mmu_psize_to_shift(psize);
+#else
+       if (!is_vm_hugetlb_page(vma))
+               return PAGE_SIZE;
+
+       return huge_page_size(hstate_vma(vma));
+#endif
+}
+
+static inline bool is_power_of_4(unsigned long x)
+{
+       if (is_power_of_2(x))
+               return (__ilog2(x) % 2) ? false : true;
+       return false;
 }
 
 static int __init add_huge_page_size(unsigned long long size)
@@ -497,9 +739,14 @@ static int __init add_huge_page_size(unsigned long long size)
 
        /* Check that it is a page size supported by the hardware and
         * that it fits within pagetable and slice limits. */
+#ifdef CONFIG_PPC_FSL_BOOK3E
+       if ((size < PAGE_SIZE) || !is_power_of_4(size))
+               return -EINVAL;
+#else
        if (!is_power_of_2(size)
            || (shift > SLICE_HIGH_SHIFT) || (shift <= PAGE_SHIFT))
                return -EINVAL;
+#endif
 
        if ((mmu_psize = shift_to_mmu_psize(shift)) < 0)
                return -EINVAL;
@@ -536,6 +783,46 @@ static int __init hugepage_setup_sz(char *str)
 }
 __setup("hugepagesz=", hugepage_setup_sz);
 
+#ifdef CONFIG_FSL_BOOKE
+struct kmem_cache *hugepte_cache;
+static int __init hugetlbpage_init(void)
+{
+       int psize;
+
+       for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
+               unsigned shift;
+
+               if (!mmu_psize_defs[psize].shift)
+                       continue;
+
+               shift = mmu_psize_to_shift(psize);
+
+               /* Don't treat normal page sizes as huge... */
+               if (shift != PAGE_SHIFT)
+                       if (add_huge_page_size(1ULL << shift) < 0)
+                               continue;
+       }
+
+       /*
+        * Create a kmem cache for hugeptes.  The bottom bits in the pte have
+        * size information encoded in them, so align them to allow this
+        */
+       hugepte_cache =  kmem_cache_create("hugepte-cache", sizeof(pte_t),
+                                          HUGEPD_SHIFT_MASK + 1, 0, NULL);
+       if (hugepte_cache == NULL)
+               panic("%s: Unable to create kmem cache for hugeptes\n",
+                     __func__);
+
+       /* Default hpage size = 4M */
+       if (mmu_psize_defs[MMU_PAGE_4M].shift)
+               HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_4M].shift;
+       else
+               panic("%s: Unable to set default huge page size\n", __func__);
+
+
+       return 0;
+}
+#else
 static int __init hugetlbpage_init(void)
 {
        int psize;
@@ -578,15 +865,23 @@ static int __init hugetlbpage_init(void)
 
        return 0;
 }
-
+#endif
 module_init(hugetlbpage_init);
 
 void flush_dcache_icache_hugepage(struct page *page)
 {
        int i;
+       void *start;
 
        BUG_ON(!PageCompound(page));
 
-       for (i = 0; i < (1UL << compound_order(page)); i++)
-               __flush_dcache_icache(page_address(page+i));
+       for (i = 0; i < (1UL << compound_order(page)); i++) {
+               if (!PageHighMem(page)) {
+                       __flush_dcache_icache(page_address(page+i));
+               } else {
+                       start = kmap_atomic(page+i, KM_PPC_SYNC_ICACHE);
+                       __flush_dcache_icache(start);
+                       kunmap_atomic(start, KM_PPC_SYNC_ICACHE);
+               }
+       }
 }
index c77fef5..161cefd 100644 (file)
@@ -32,6 +32,8 @@
 #include <linux/pagemap.h>
 #include <linux/memblock.h>
 #include <linux/gfp.h>
+#include <linux/slab.h>
+#include <linux/hugetlb.h>
 
 #include <asm/pgalloc.h>
 #include <asm/prom.h>
@@ -44,6 +46,7 @@
 #include <asm/tlb.h>
 #include <asm/sections.h>
 #include <asm/system.h>
+#include <asm/hugetlb.h>
 
 #include "mmu_decl.h"
 
@@ -123,6 +126,12 @@ void __init MMU_init(void)
        /* parse args from command line */
        MMU_setup();
 
+       /*
+        * Reserve gigantic pages for hugetlb.  This MUST occur before
+        * lowmem_end_addr is initialized below.
+        */
+       reserve_hugetlb_gpages();
+
        if (memblock.memory.cnt > 1) {
 #ifndef CONFIG_WII
                memblock.memory.cnt = 1;
index c781bbc..5db316c 100644 (file)
@@ -123,7 +123,8 @@ int arch_add_memory(int nid, u64 start, u64 size)
        pgdata = NODE_DATA(nid);
 
        start = (unsigned long)__va(start);
-       create_section_mapping(start, start + size);
+       if (create_section_mapping(start, start + size))
+               return -EINVAL;
 
        /* this should work for most non-highmem platforms */
        zone = pgdata->node_zones;
@@ -548,4 +549,9 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
                return;
        hash_preload(vma->vm_mm, address, access, trap);
 #endif /* CONFIG_PPC_STD_MMU */
+#if (defined(CONFIG_PPC_BOOK3E_64) || defined(CONFIG_PPC_FSL_BOOK3E)) \
+       && defined(CONFIG_HUGETLB_PAGE)
+       if (is_vm_hugetlb_page(vma))
+               book3e_hugetlb_preload(vma->vm_mm, address, *ptep);
+#endif
 }
index 3bafc3d..4ff587e 100644 (file)
@@ -136,8 +136,8 @@ int use_cop(unsigned long acop, struct mm_struct *mm)
        if (!mm || !acop)
                return -EINVAL;
 
-       /* We need to make sure mm_users doesn't change */
-       down_read(&mm->mmap_sem);
+       /* The page_table_lock ensures mm_users won't change under us */
+       spin_lock(&mm->page_table_lock);
        spin_lock(mm->context.cop_lockp);
 
        if (mm->context.cop_pid == COP_PID_NONE) {
@@ -164,7 +164,7 @@ int use_cop(unsigned long acop, struct mm_struct *mm)
 
 out:
        spin_unlock(mm->context.cop_lockp);
-       up_read(&mm->mmap_sem);
+       spin_unlock(&mm->page_table_lock);
 
        return ret;
 }
@@ -185,8 +185,8 @@ void drop_cop(unsigned long acop, struct mm_struct *mm)
        if (WARN_ON_ONCE(!mm))
                return;
 
-       /* We need to make sure mm_users doesn't change */
-       down_read(&mm->mmap_sem);
+       /* The page_table_lock ensures mm_users won't change under us */
+       spin_lock(&mm->page_table_lock);
        spin_lock(mm->context.cop_lockp);
 
        mm->context.acop &= ~acop;
@@ -213,7 +213,7 @@ void drop_cop(unsigned long acop, struct mm_struct *mm)
        }
 
        spin_unlock(mm->context.cop_lockp);
-       up_read(&mm->mmap_sem);
+       spin_unlock(&mm->page_table_lock);
 }
 EXPORT_SYMBOL_GPL(drop_cop);
 
index 336807d..5b63bd3 100644 (file)
@@ -292,6 +292,11 @@ int init_new_context(struct task_struct *t, struct mm_struct *mm)
        mm->context.id = MMU_NO_CONTEXT;
        mm->context.active = 0;
 
+#ifdef CONFIG_PPC_MM_SLICES
+       if (slice_mm_new_context(mm))
+               slice_set_user_psize(mm, mmu_virtual_psize);
+#endif
+
        return 0;
 }
 
index dd0a258..83eb5d5 100644 (file)
@@ -142,6 +142,8 @@ extern unsigned long mmu_mapin_ram(unsigned long top);
 
 #elif defined(CONFIG_PPC_FSL_BOOK3E)
 extern unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx);
+extern unsigned long calc_cam_sz(unsigned long ram, unsigned long virt,
+                                phys_addr_t phys);
 #ifdef CONFIG_PPC32
 extern void MMU_init_hw(void);
 extern unsigned long mmu_mapin_ram(unsigned long top);
index 2164006..0bfb90c 100644 (file)
@@ -709,8 +709,7 @@ static void __init parse_drconf_memory(struct device_node *memory)
 
 static int __init parse_numa_properties(void)
 {
-       struct device_node *cpu = NULL;
-       struct device_node *memory = NULL;
+       struct device_node *memory;
        int default_nid = 0;
        unsigned long i;
 
@@ -732,6 +731,7 @@ static int __init parse_numa_properties(void)
         * each node to be onlined must have NODE_DATA etc backing it.
         */
        for_each_present_cpu(i) {
+               struct device_node *cpu;
                int nid;
 
                cpu = of_get_cpu_node(i, NULL);
@@ -750,8 +750,8 @@ static int __init parse_numa_properties(void)
        }
 
        get_n_mem_cells(&n_mem_addr_cells, &n_mem_size_cells);
-       memory = NULL;
-       while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
+
+       for_each_node_by_type(memory, "memory") {
                unsigned long start;
                unsigned long size;
                int nid;
@@ -800,8 +800,9 @@ new_range:
        }
 
        /*
-        * Now do the same thing for each MEMBLOCK listed in the ibm,dynamic-memory
-        * property in the ibm,dynamic-reconfiguration-memory node.
+        * Now do the same thing for each MEMBLOCK listed in the
+        * ibm,dynamic-memory property in the
+        * ibm,dynamic-reconfiguration-memory node.
         */
        memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
        if (memory)
@@ -1187,10 +1188,10 @@ static int hot_add_drconf_scn_to_nid(struct device_node *memory,
  */
 int hot_add_node_scn_to_nid(unsigned long scn_addr)
 {
-       struct device_node *memory = NULL;
+       struct device_node *memory;
        int nid = -1;
 
-       while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
+       for_each_node_by_type(memory, "memory") {
                unsigned long start, size;
                int ranges;
                const unsigned int *memcell_buf;
@@ -1214,11 +1215,12 @@ int hot_add_node_scn_to_nid(unsigned long scn_addr)
                        break;
                }
 
-               of_node_put(memory);
                if (nid >= 0)
                        break;
        }
 
+       of_node_put(memory);
+
        return nid;
 }
 
index af40c87..214130a 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/percpu.h>
 #include <linux/hardirq.h>
+#include <linux/hugetlb.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
@@ -212,7 +213,7 @@ int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address,
        entry = set_access_flags_filter(entry, vma, dirty);
        changed = !pte_same(*(ptep), entry);
        if (changed) {
-               if (!(vma->vm_flags & VM_HUGETLB))
+               if (!is_vm_hugetlb_page(vma))
                        assert_pte_locked(vma->vm_mm, address);
                __ptep_set_access_flags(ptep, entry);
                flush_tlb_page_nohash(vma, address);
index 4ebb34b..dc4a5f3 100644 (file)
@@ -553,24 +553,24 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_TLBRSRV)
        rldicl  r11,r16,64-VPTE_PGD_SHIFT,64-PGD_INDEX_SIZE-3
        clrrdi  r10,r11,3
        ldx     r15,r10,r15
-       cmpldi  cr0,r15,0
-       beq     virt_page_table_tlb_miss_fault
+       cmpdi   cr0,r15,0
+       bge     virt_page_table_tlb_miss_fault
 
 #ifndef CONFIG_PPC_64K_PAGES
        /* Get to PUD entry */
        rldicl  r11,r16,64-VPTE_PUD_SHIFT,64-PUD_INDEX_SIZE-3
        clrrdi  r10,r11,3
        ldx     r15,r10,r15
-       cmpldi  cr0,r15,0
-       beq     virt_page_table_tlb_miss_fault
+       cmpdi   cr0,r15,0
+       bge     virt_page_table_tlb_miss_fault
 #endif /* CONFIG_PPC_64K_PAGES */
 
        /* Get to PMD entry */
        rldicl  r11,r16,64-VPTE_PMD_SHIFT,64-PMD_INDEX_SIZE-3
        clrrdi  r10,r11,3
        ldx     r15,r10,r15
-       cmpldi  cr0,r15,0
-       beq     virt_page_table_tlb_miss_fault
+       cmpdi   cr0,r15,0
+       bge     virt_page_table_tlb_miss_fault
 
        /* Ok, we're all right, we can now create a kernel translation for
         * a 4K or 64K page from r16 -> r15.
@@ -802,24 +802,24 @@ htw_tlb_miss:
        rldicl  r11,r16,64-(PGDIR_SHIFT-3),64-PGD_INDEX_SIZE-3
        clrrdi  r10,r11,3
        ldx     r15,r10,r15
-       cmpldi  cr0,r15,0
-       beq     htw_tlb_miss_fault
+       cmpdi   cr0,r15,0
+       bge     htw_tlb_miss_fault
 
 #ifndef CONFIG_PPC_64K_PAGES
        /* Get to PUD entry */
        rldicl  r11,r16,64-(PUD_SHIFT-3),64-PUD_INDEX_SIZE-3
        clrrdi  r10,r11,3
        ldx     r15,r10,r15
-       cmpldi  cr0,r15,0
-       beq     htw_tlb_miss_fault
+       cmpdi   cr0,r15,0
+       bge     htw_tlb_miss_fault
 #endif /* CONFIG_PPC_64K_PAGES */
 
        /* Get to PMD entry */
        rldicl  r11,r16,64-(PMD_SHIFT-3),64-PMD_INDEX_SIZE-3
        clrrdi  r10,r11,3
        ldx     r15,r10,r15
-       cmpldi  cr0,r15,0
-       beq     htw_tlb_miss_fault
+       cmpdi   cr0,r15,0
+       bge     htw_tlb_miss_fault
 
        /* Ok, we're all right, we can now create an indirect entry for
         * a 1M or 256M page.
index d32ec64..6c2eabf 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/memblock.h>
 #include <linux/of_fdt.h>
+#include <linux/hugetlb.h>
 
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
 #include <asm/code-patching.h>
+#include <asm/hugetlb.h>
 
 #include "mmu_decl.h"
 
-#ifdef CONFIG_PPC_BOOK3E
+/*
+ * This struct lists the sw-supported page sizes.  The hardawre MMU may support
+ * other sizes not listed here.   The .ind field is only used on MMUs that have
+ * indirect page table entries.
+ */
+#ifdef CONFIG_PPC_BOOK3E_MMU
+#ifdef CONFIG_FSL_BOOKE
+struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = {
+       [MMU_PAGE_4K] = {
+               .shift  = 12,
+               .enc    = BOOK3E_PAGESZ_4K,
+       },
+       [MMU_PAGE_4M] = {
+               .shift  = 22,
+               .enc    = BOOK3E_PAGESZ_4M,
+       },
+       [MMU_PAGE_16M] = {
+               .shift  = 24,
+               .enc    = BOOK3E_PAGESZ_16M,
+       },
+       [MMU_PAGE_64M] = {
+               .shift  = 26,
+               .enc    = BOOK3E_PAGESZ_64M,
+       },
+       [MMU_PAGE_256M] = {
+               .shift  = 28,
+               .enc    = BOOK3E_PAGESZ_256M,
+       },
+       [MMU_PAGE_1G] = {
+               .shift  = 30,
+               .enc    = BOOK3E_PAGESZ_1GB,
+       },
+};
+#else
 struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = {
        [MMU_PAGE_4K] = {
                .shift  = 12,
@@ -77,6 +112,8 @@ struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = {
                .enc    = BOOK3E_PAGESZ_1GB,
        },
 };
+#endif /* CONFIG_FSL_BOOKE */
+
 static inline int mmu_get_tsize(int psize)
 {
        return mmu_psize_defs[psize].enc;
@@ -87,7 +124,7 @@ static inline int mmu_get_tsize(int psize)
        /* This isn't used on !Book3E for now */
        return 0;
 }
-#endif
+#endif /* CONFIG_PPC_BOOK3E_MMU */
 
 /* The variables below are currently only used on 64-bit Book3E
  * though this will probably be made common with other nohash
@@ -266,6 +303,11 @@ void __flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
 
 void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
 {
+#ifdef CONFIG_HUGETLB_PAGE
+       if (is_vm_hugetlb_page(vma))
+               flush_hugetlb_page(vma, vmaddr);
+#endif
+
        __flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr,
                         mmu_get_tsize(mmu_virtual_psize), 0);
 }
@@ -600,13 +642,28 @@ void __cpuinit early_init_mmu_secondary(void)
 void setup_initial_memory_limit(phys_addr_t first_memblock_base,
                                phys_addr_t first_memblock_size)
 {
-       /* On Embedded 64-bit, we adjust the RMA size to match
+       /* On non-FSL Embedded 64-bit, we adjust the RMA size to match
         * the bolted TLB entry. We know for now that only 1G
         * entries are supported though that may eventually
-        * change. We crop it to the size of the first MEMBLOCK to
+        * change.
+        *
+        * on FSL Embedded 64-bit, we adjust the RMA size to match the
+        * first bolted TLB entry size.  We still limit max to 1G even if
+        * the TLB could cover more.  This is due to what the early init
+        * code is setup to do.
+        *
+        * We crop it to the size of the first MEMBLOCK to
         * avoid going over total available memory just in case...
         */
-       ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
+#ifdef CONFIG_PPC_FSL_BOOK3E
+       if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) {
+               unsigned long linear_sz;
+               linear_sz = calc_cam_sz(first_memblock_size, PAGE_OFFSET,
+                                       first_memblock_base);
+               ppc64_rma_size = min_t(u64, linear_sz, 0x40000000);
+       } else
+#endif
+               ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
 
        /* Finally limit subsequent allocations */
        memblock_set_current_limit(first_memblock_base + ppc64_rma_size);
index b5d8706..8f9c3e2 100644 (file)
@@ -32,14 +32,6 @@ config EP405
        help
          This option enables support for the EP405/EP405PC boards.
 
-config HCU4
-       bool "Hcu4"
-       depends on 40x
-       default n
-       select 405GPR
-       help
-         This option enables support for the Nestal Maschinen HCU4 board.
-
 config HOTFOOT
         bool "Hotfoot"
        depends on 40x
index 56e8900..88c22de 100644 (file)
@@ -1,4 +1,3 @@
-obj-$(CONFIG_HCU4)                             += hcu4.o
 obj-$(CONFIG_WALNUT)                           += walnut.o
 obj-$(CONFIG_XILINX_VIRTEX_GENERIC_BOARD)      += virtex.o
 obj-$(CONFIG_EP405)                            += ep405.o
diff --git a/arch/powerpc/platforms/40x/hcu4.c b/arch/powerpc/platforms/40x/hcu4.c
deleted file mode 100644 (file)
index 60b2afe..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Architecture- / platform-specific boot-time initialization code for
- * IBM PowerPC 4xx based boards. Adapted from original
- * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
- * <dan@net4x.com>.
- *
- * Copyright(c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- * Rewritten and ported to the merged powerpc tree:
- * Copyright 2007 IBM Corporation
- * Josh Boyer <jwboyer@linux.vnet.ibm.com>
- *
- * 2002 (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/init.h>
-#include <linux/of_platform.h>
-
-#include <asm/machdep.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/time.h>
-#include <asm/uic.h>
-#include <asm/ppc4xx.h>
-
-static __initdata struct of_device_id hcu4_of_bus[] = {
-       { .compatible = "ibm,plb3", },
-       { .compatible = "ibm,opb", },
-       { .compatible = "ibm,ebc", },
-       {},
-};
-
-static int __init hcu4_device_probe(void)
-{
-       of_platform_bus_probe(NULL, hcu4_of_bus, NULL);
-       return 0;
-}
-machine_device_initcall(hcu4, hcu4_device_probe);
-
-static int __init hcu4_probe(void)
-{
-       unsigned long root = of_get_flat_dt_root();
-
-       if (!of_flat_dt_is_compatible(root, "netstal,hcu4"))
-               return 0;
-
-       return 1;
-}
-
-define_machine(hcu4) {
-       .name                   = "HCU4",
-       .probe                  = hcu4_probe,
-       .progress               = udbg_progress,
-       .init_IRQ               = uic_init_tree,
-       .get_irq                = uic_get_irq,
-       .restart                = ppc4xx_reset_system,
-       .calibrate_decr         = generic_calibrate_decr,
-};
index 27b0651..b3ebce1 100644 (file)
@@ -6,6 +6,7 @@ config PPC_MPC512x
        select PPC_CLOCK
        select PPC_PCI_CHOICE
        select FSL_PCI if PCI
+       select ARCH_WANT_OPTIONAL_GPIOLIB
 
 config MPC5121_ADS
        bool "Freescale MPC5121E ADS"
index 428c5e0..3661bcd 100644 (file)
@@ -49,6 +49,9 @@ struct cpm_pin {
 };
 
 static __initdata struct cpm_pin km82xx_pins[] = {
+       /* SMC1 */
+       {2, 4, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+       {2, 5, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
 
        /* SMC2 */
        {0, 8, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
@@ -137,6 +140,7 @@ static void __init init_ioports(void)
        }
 
        cpm2_smc_clk_setup(CPM_CLK_SMC2, CPM_BRG8);
+       cpm2_smc_clk_setup(CPM_CLK_SMC1, CPM_BRG7);
        cpm2_clk_setup(CPM_CLK_SCC1, CPM_CLK11, CPM_CLK_RX);
        cpm2_clk_setup(CPM_CLK_SCC1, CPM_CLK11, CPM_CLK_TX);
        cpm2_clk_setup(CPM_CLK_SCC3, CPM_CLK5, CPM_CLK_RTX);
index 73f4135..670a033 100644 (file)
@@ -114,18 +114,21 @@ config KMETER1
 
 endif
 
-# used for usb
+# used for usb & gpio
 config PPC_MPC831x
        bool
+       select ARCH_WANT_OPTIONAL_GPIOLIB
 
 # used for math-emu
 config PPC_MPC832x
        bool
 
-# used for usb
+# used for usb & gpio
 config PPC_MPC834x
        bool
+       select ARCH_WANT_OPTIONAL_GPIOLIB
 
-# used for usb
+# used for usb & gpio
 config PPC_MPC837x
        bool
+       select ARCH_WANT_OPTIONAL_GPIOLIB
index 70798ac..ef6537b 100644 (file)
@@ -21,6 +21,8 @@
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/reboot.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 
@@ -30,6 +32,7 @@
  */
 #define MCU_REG_CTRL   0x20
 #define MCU_CTRL_POFF  0x40
+#define MCU_CTRL_BTN   0x80
 
 #define MCU_NUM_GPIO   2
 
@@ -42,13 +45,55 @@ struct mcu {
 
 static struct mcu *glob_mcu;
 
+struct task_struct *shutdown_thread;
+static int shutdown_thread_fn(void *data)
+{
+       int ret;
+       struct mcu *mcu = glob_mcu;
+
+       while (!kthread_should_stop()) {
+               ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL);
+               if (ret < 0)
+                       pr_err("MCU status reg read failed.\n");
+               mcu->reg_ctrl = ret;
+
+
+               if (mcu->reg_ctrl & MCU_CTRL_BTN) {
+                       i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL,
+                                                 mcu->reg_ctrl & ~MCU_CTRL_BTN);
+
+                       ctrl_alt_del();
+               }
+
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule_timeout(HZ);
+       }
+
+       return 0;
+}
+
+static ssize_t show_status(struct device *d,
+                          struct device_attribute *attr, char *buf)
+{
+       int ret;
+       struct mcu *mcu = glob_mcu;
+
+       ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL);
+       if (ret < 0)
+               return -ENODEV;
+       mcu->reg_ctrl = ret;
+
+       return sprintf(buf, "%02x\n", ret);
+}
+static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
+
 static void mcu_power_off(void)
 {
        struct mcu *mcu = glob_mcu;
 
        pr_info("Sending power-off request to the MCU...\n");
        mutex_lock(&mcu->lock);
-       i2c_smbus_write_byte_data(glob_mcu->client, MCU_REG_CTRL,
+       i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL,
                                  mcu->reg_ctrl | MCU_CTRL_POFF);
        mutex_unlock(&mcu->lock);
 }
@@ -130,6 +175,13 @@ static int __devinit mcu_probe(struct i2c_client *client,
                dev_info(&client->dev, "will provide power-off service\n");
        }
 
+       if (device_create_file(&client->dev, &dev_attr_status))
+               dev_err(&client->dev,
+                       "couldn't create device file for status\n");
+
+       shutdown_thread = kthread_run(shutdown_thread_fn, NULL,
+                                     "mcu-i2c-shdn");
+
        return 0;
 err:
        kfree(mcu);
@@ -141,6 +193,10 @@ static int __devexit mcu_remove(struct i2c_client *client)
        struct mcu *mcu = i2c_get_clientdata(client);
        int ret;
 
+       kthread_stop(shutdown_thread);
+
+       device_remove_file(&client->dev, &dev_attr_status);
+
        if (glob_mcu == mcu) {
                ppc_md.power_off = NULL;
                glob_mcu = NULL;
index 12f5932..45023e2 100644 (file)
@@ -171,17 +171,18 @@ config SBC8560
        help
          This option enables support for the Wind River SBC8560 board
 
-config P2040_RDB
-       bool "Freescale P2040 RDB"
+config P2041_RDB
+       bool "Freescale P2041 RDB"
        select DEFAULT_UIMAGE
        select PPC_E500MC
        select PHYS_64BIT
        select SWIOTLB
-       select MPC8xxx_GPIO
+       select ARCH_REQUIRE_GPIOLIB
+       select GPIO_MPC8XXX
        select HAS_RAPIDIO
        select PPC_EPAPR_HV_PIC
        help
-         This option enables support for the P2040 RDB board
+         This option enables support for the P2041 RDB board
 
 config P3041_DS
        bool "Freescale P3041 DS"
@@ -189,19 +190,33 @@ config P3041_DS
        select PPC_E500MC
        select PHYS_64BIT
        select SWIOTLB
-       select MPC8xxx_GPIO
+       select ARCH_REQUIRE_GPIOLIB
+       select GPIO_MPC8XXX
        select HAS_RAPIDIO
        select PPC_EPAPR_HV_PIC
        help
          This option enables support for the P3041 DS board
 
+config P3060_QDS
+       bool "Freescale P3060 QDS"
+       select DEFAULT_UIMAGE
+       select PPC_E500MC
+       select PHYS_64BIT
+       select SWIOTLB
+       select MPC8xxx_GPIO
+       select HAS_RAPIDIO
+       select PPC_EPAPR_HV_PIC
+       help
+         This option enables support for the P3060 QDS board
+
 config P4080_DS
        bool "Freescale P4080 DS"
        select DEFAULT_UIMAGE
        select PPC_E500MC
        select PHYS_64BIT
        select SWIOTLB
-       select MPC8xxx_GPIO
+       select ARCH_REQUIRE_GPIOLIB
+       select GPIO_MPC8XXX
        select HAS_RAPIDIO
        select PPC_EPAPR_HV_PIC
        help
@@ -216,7 +231,8 @@ config P5020_DS
        select PPC_E500MC
        select PHYS_64BIT
        select SWIOTLB
-       select MPC8xxx_GPIO
+       select ARCH_REQUIRE_GPIOLIB
+       select GPIO_MPC8XXX
        select HAS_RAPIDIO
        select PPC_EPAPR_HV_PIC
        help
index a971b32..bc5acb9 100644 (file)
@@ -13,8 +13,9 @@ obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o
 obj-$(CONFIG_P1010_RDB)   += p1010rdb.o
 obj-$(CONFIG_P1022_DS)    += p1022_ds.o
 obj-$(CONFIG_P1023_RDS)   += p1023_rds.o
-obj-$(CONFIG_P2040_RDB)   += p2040_rdb.o corenet_ds.o
+obj-$(CONFIG_P2041_RDB)   += p2041_rdb.o corenet_ds.o
 obj-$(CONFIG_P3041_DS)    += p3041_ds.o corenet_ds.o
+obj-$(CONFIG_P3060_QDS)   += p3060_qds.o corenet_ds.o
 obj-$(CONFIG_P4080_DS)    += p4080_ds.o corenet_ds.o
 obj-$(CONFIG_P5020_DS)    += p5020_ds.o corenet_ds.o
 obj-$(CONFIG_STX_GP3)    += stx_gp3.o
index c01c727..fda1571 100644 (file)
@@ -129,17 +129,20 @@ static void p1022ds_set_gamma_table(enum fsl_diu_monitor_port port,
  */
 static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
 {
-       struct device_node *pixis_node;
+       struct device_node *np;
        void __iomem *pixis;
        u8 __iomem *brdcfg1;
 
-       pixis_node = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-pixis");
-       if (!pixis_node) {
+       np = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-fpga");
+       if (!np)
+               /* older device trees used "fsl,p1022ds-pixis" */
+               np = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-pixis");
+       if (!np) {
                pr_err("p1022ds: missing ngPIXIS node\n");
                return;
        }
 
-       pixis = of_iomap(pixis_node, 0);
+       pixis = of_iomap(np, 0);
        if (!pixis) {
                pr_err("p1022ds: could not map ngPIXIS registers\n");
                return;
similarity index 82%
rename from arch/powerpc/platforms/85xx/p2040_rdb.c
rename to arch/powerpc/platforms/85xx/p2041_rdb.c
index 32b56ac..eda6ed5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * P2040 RDB Setup
+ * P2041 RDB Setup
  *
  * Copyright 2011 Freescale Semiconductor Inc.
  *
 /*
  * Called very early, device-tree isn't unflattened
  */
-static int __init p2040_rdb_probe(void)
+static int __init p2041_rdb_probe(void)
 {
        unsigned long root = of_get_flat_dt_root();
 #ifdef CONFIG_SMP
        extern struct smp_ops_t smp_85xx_ops;
 #endif
 
-       if (of_flat_dt_is_compatible(root, "fsl,P2040RDB"))
+       if (of_flat_dt_is_compatible(root, "fsl,P2041RDB"))
                return 1;
 
        /* Check if we're running under the Freescale hypervisor */
-       if (of_flat_dt_is_compatible(root, "fsl,P2040RDB-hv")) {
+       if (of_flat_dt_is_compatible(root, "fsl,P2041RDB-hv")) {
                ppc_md.init_IRQ = ehv_pic_init;
                ppc_md.get_irq = ehv_pic_get_irq;
                ppc_md.restart = fsl_hv_restart;
@@ -66,9 +66,9 @@ static int __init p2040_rdb_probe(void)
        return 0;
 }
 
-define_machine(p2040_rdb) {
-       .name                   = "P2040 RDB",
-       .probe                  = p2040_rdb_probe,
+define_machine(p2041_rdb) {
+       .name                   = "P2041 RDB",
+       .probe                  = p2041_rdb_probe,
        .setup_arch             = corenet_ds_setup_arch,
        .init_IRQ               = corenet_ds_pic_init,
 #ifdef CONFIG_PCI
@@ -81,8 +81,8 @@ define_machine(p2040_rdb) {
        .power_save             = e500_idle,
 };
 
-machine_device_initcall(p2040_rdb, corenet_ds_publish_devices);
+machine_device_initcall(p2041_rdb, corenet_ds_publish_devices);
 
 #ifdef CONFIG_SWIOTLB
-machine_arch_initcall(p2040_rdb, swiotlb_setup_bus_notifier);
+machine_arch_initcall(p2041_rdb, swiotlb_setup_bus_notifier);
 #endif
diff --git a/arch/powerpc/platforms/85xx/p3060_qds.c b/arch/powerpc/platforms/85xx/p3060_qds.c
new file mode 100644 (file)
index 0000000..01dcf44
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * P3060 QDS Setup
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/phy.h>
+#include <asm/machdep.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+#include <linux/of_platform.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+#include <asm/ehv_pic.h>
+#include "corenet_ds.h"
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p3060_qds_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+#ifdef CONFIG_SMP
+       extern struct smp_ops_t smp_85xx_ops;
+#endif
+
+       if (of_flat_dt_is_compatible(root, "fsl,P3060QDS"))
+               return 1;
+
+       /* Check if we're running under the Freescale hypervisor */
+       if (of_flat_dt_is_compatible(root, "fsl,P3060QDS-hv")) {
+               ppc_md.init_IRQ = ehv_pic_init;
+               ppc_md.get_irq = ehv_pic_get_irq;
+               ppc_md.restart = fsl_hv_restart;
+               ppc_md.power_off = fsl_hv_halt;
+               ppc_md.halt = fsl_hv_halt;
+#ifdef CONFIG_SMP
+               /*
+                * Disable the timebase sync operations because we can't write
+                * to the timebase registers under the hypervisor.
+                */
+               smp_85xx_ops.give_timebase = NULL;
+               smp_85xx_ops.take_timebase = NULL;
+#endif
+               return 1;
+       }
+
+       return 0;
+}
+
+define_machine(p3060_qds) {
+       .name                   = "P3060 QDS",
+       .probe                  = p3060_qds_probe,
+       .setup_arch             = corenet_ds_setup_arch,
+       .init_IRQ               = corenet_ds_pic_init,
+#ifdef CONFIG_PCI
+       .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
+#endif
+       .get_irq                = mpic_get_coreint_irq,
+       .restart                = fsl_rstcr_restart,
+       .calibrate_decr         = generic_calibrate_decr,
+       .progress               = udbg_progress,
+       .power_save             = e500_idle,
+};
+
+machine_device_initcall(p3060_qds, declare_of_platform_devices);
+
+#ifdef CONFIG_SWIOTLB
+machine_arch_initcall(p3060_qds, swiotlb_setup_bus_notifier);
+#endif
index 09ced72..cebd786 100644 (file)
@@ -283,7 +283,7 @@ static int __init sbc8560_bdrstcr_init(void)
 
        of_address_to_resource(np, 0, &res);
 
-       printk(KERN_INFO "sbc8560: Found BRSTCR at i/o 0x%x\n", res.start);
+       printk(KERN_INFO "sbc8560: Found BRSTCR at %pR\n", &res);
 
        brstcr = ioremap(res.start, resource_size(&res));
        if(!brstcr)
index 5b9b901..2df4785 100644 (file)
@@ -48,10 +48,11 @@ smp_85xx_kick_cpu(int nr)
        const u64 *cpu_rel_addr;
        __iomem u32 *bptr_vaddr;
        struct device_node *np;
-       int n = 0;
+       int n = 0, hw_cpu = get_hard_smp_processor_id(nr);
        int ioremappable;
 
-       WARN_ON (nr < 0 || nr >= NR_CPUS);
+       WARN_ON(nr < 0 || nr >= NR_CPUS);
+       WARN_ON(hw_cpu < 0 || hw_cpu >= NR_CPUS);
 
        pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr);
 
@@ -79,7 +80,7 @@ smp_85xx_kick_cpu(int nr)
 
        local_irq_save(flags);
 
-       out_be32(bptr_vaddr + BOOT_ENTRY_PIR, nr);
+       out_be32(bptr_vaddr + BOOT_ENTRY_PIR, hw_cpu);
 #ifdef CONFIG_PPC32
        out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start));
 
@@ -88,7 +89,7 @@ smp_85xx_kick_cpu(int nr)
                                (ulong)(bptr_vaddr + SIZE_BOOT_ENTRY));
 
        /* Wait a bit for the CPU to ack. */
-       while ((__secondary_hold_acknowledge != nr) && (++n < 1000))
+       while ((__secondary_hold_acknowledge != hw_cpu) && (++n < 1000))
                mdelay(1);
 #else
        smp_generic_kick_cpu(nr);
@@ -206,7 +207,7 @@ static void mpc85xx_smp_machine_kexec(struct kimage *image)
        if ( !timeout )
                printk(KERN_ERR "Unable to bring down secondary cpu(s)");
 
-       for (i = 0; i < num_cpus; i++)
+       for_each_online_cpu(i)
        {
                if ( i == smp_processor_id() ) continue;
                mpic_reset_core(i);
@@ -243,6 +244,7 @@ void __init mpc85xx_smp_init(void)
                 * If left NULL, .message_pass defaults to
                 * smp_muxed_ipi_message_pass
                 */
+               smp_85xx_ops.message_pass = NULL;
                smp_85xx_ops.cause_ipi = doorbell_cause_ipi;
        }
 
index a0b5638..8d6599d 100644 (file)
@@ -4,6 +4,7 @@ menuconfig PPC_86xx
        depends on 6xx
        select FSL_SOC
        select ALTIVEC
+       select ARCH_WANT_OPTIONAL_GPIOLIB
        help
          The Freescale E600 SoCs have 74xx cores.
 
index b9ba861..e458872 100644 (file)
@@ -1,5 +1,6 @@
 menu "Platform support"
 
+source "arch/powerpc/platforms/powernv/Kconfig"
 source "arch/powerpc/platforms/pseries/Kconfig"
 source "arch/powerpc/platforms/iseries/Kconfig"
 source "arch/powerpc/platforms/chrp/Kconfig"
@@ -333,16 +334,6 @@ config OF_RTC
 
 source "arch/powerpc/sysdev/bestcomm/Kconfig"
 
-config MPC8xxx_GPIO
-       bool "MPC512x/MPC8xxx GPIO support"
-       depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \
-                  FSL_SOC_BOOKE || PPC_86xx
-       select GENERIC_GPIO
-       select ARCH_REQUIRE_GPIOLIB
-       help
-         Say Y here if you're going to use hardware that connects to the
-         MPC512x/831x/834x/837x/8572/8610 GPIOs.
-
 config SIMPLE_GPIO
        bool "Support for simple, memory-mapped GPIO controllers"
        depends on PPC
@@ -355,7 +346,7 @@ config SIMPLE_GPIO
          on-board peripherals.
 
 config MCU_MPC8349EMITX
-       tristate "MPC8349E-mITX MCU driver"
+       bool "MPC8349E-mITX MCU driver"
        depends on I2C && PPC_83xx
        select GENERIC_GPIO
        select ARCH_REQUIRE_GPIOLIB
index e06e395..a85990c 100644 (file)
@@ -69,6 +69,7 @@ config PPC_BOOK3S_64
        bool "Server processors"
        select PPC_FPU
        select PPC_HAVE_PMU_SUPPORT
+       select SYS_SUPPORTS_HUGETLBFS
 
 config PPC_BOOK3E_64
        bool "Embedded processors"
@@ -173,6 +174,7 @@ config BOOKE
 config FSL_BOOKE
        bool
        depends on (E200 || E500) && PPC32
+       select SYS_SUPPORTS_HUGETLBFS if PHYS_64BIT
        default y
 
 # this is for common code between PPC32 & PPC64 FSL BOOKE
@@ -296,7 +298,7 @@ config PPC_BOOK3E_MMU
 
 config PPC_MM_SLICES
        bool
-       default y if HUGETLB_PAGE || (PPC_STD_MMU_64 && PPC_64K_PAGES)
+       default y if (PPC64 && HUGETLB_PAGE) || (PPC_STD_MMU_64 && PPC_64K_PAGES)
        default n
 
 config VIRT_CPU_ACCOUNTING
index 73e2116..2635a22 100644 (file)
@@ -14,6 +14,7 @@ obj-$(CONFIG_PPC_82xx)                += 82xx/
 obj-$(CONFIG_PPC_83xx)         += 83xx/
 obj-$(CONFIG_FSL_SOC_BOOKE)    += 85xx/
 obj-$(CONFIG_PPC_86xx)         += 86xx/
+obj-$(CONFIG_PPC_POWERNV)      += powernv/
 obj-$(CONFIG_PPC_PSERIES)      += pseries/
 obj-$(CONFIG_PPC_ISERIES)      += iseries/
 obj-$(CONFIG_PPC_MAPLE)                += maple/
index 26a0671..fc46fca 100644 (file)
@@ -1159,6 +1159,26 @@ static int __init setup_iommu_fixed(char *str)
 }
 __setup("iommu_fixed=", setup_iommu_fixed);
 
+static u64 cell_dma_get_required_mask(struct device *dev)
+{
+       struct dma_map_ops *dma_ops;
+
+       if (!dev->dma_mask)
+               return 0;
+
+       if (!iommu_fixed_disabled &&
+                       cell_iommu_get_fixed_address(dev) != OF_BAD_ADDR)
+               return DMA_BIT_MASK(64);
+
+       dma_ops = get_dma_ops(dev);
+       if (dma_ops->get_required_mask)
+               return dma_ops->get_required_mask(dev);
+
+       WARN_ONCE(1, "no get_required_mask in %p ops", dma_ops);
+
+       return DMA_BIT_MASK(64);
+}
+
 static int __init cell_iommu_init(void)
 {
        struct device_node *np;
@@ -1175,6 +1195,7 @@ static int __init cell_iommu_init(void)
 
        /* Setup various ppc_md. callbacks */
        ppc_md.pci_dma_dev_setup = cell_pci_dma_dev_setup;
+       ppc_md.dma_get_required_mask = cell_dma_get_required_mask;
        ppc_md.tce_build = tce_build_cell;
        ppc_md.tce_free = tce_free_cell;
 
diff --git a/arch/powerpc/platforms/powernv/Kconfig b/arch/powerpc/platforms/powernv/Kconfig
new file mode 100644 (file)
index 0000000..74fea5c
--- /dev/null
@@ -0,0 +1,16 @@
+config PPC_POWERNV
+       depends on PPC64 && PPC_BOOK3S
+       bool "IBM PowerNV (Non-Virtualized) platform support"
+       select PPC_NATIVE
+       select PPC_XICS
+       select PPC_ICP_NATIVE
+       select PPC_P7_NAP
+       select PPC_PCI_CHOICE if EMBEDDED
+       default y
+
+config PPC_POWERNV_RTAS
+       depends on PPC_POWERNV
+       bool "Support for RTAS based PowerNV platforms such as BML"
+       default y
+       select PPC_ICS_RTAS
+       select PPC_RTAS
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
new file mode 100644 (file)
index 0000000..3185300
--- /dev/null
@@ -0,0 +1,5 @@
+obj-y                  += setup.o opal-takeover.o opal-wrappers.o opal.o
+obj-y                  += opal-rtc.o opal-nvram.o
+
+obj-$(CONFIG_SMP)      += smp.o
+obj-$(CONFIG_PCI)      += pci.o pci-p5ioc2.o
diff --git a/arch/powerpc/platforms/powernv/opal-nvram.c b/arch/powerpc/platforms/powernv/opal-nvram.c
new file mode 100644 (file)
index 0000000..3f83e1a
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * PowerNV nvram code.
+ *
+ * Copyright 2011 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/init.h>
+#include <linux/of.h>
+
+#include <asm/opal.h>
+#include <asm/machdep.h>
+
+static unsigned int nvram_size;
+
+static ssize_t opal_nvram_size(void)
+{
+       return nvram_size;
+}
+
+static ssize_t opal_nvram_read(char *buf, size_t count, loff_t *index)
+{
+       s64 rc;
+       int off;
+
+       if (*index >= nvram_size)
+               return 0;
+       off = *index;
+       if ((off + count) > nvram_size)
+               count = nvram_size - off;
+       rc = opal_read_nvram(__pa(buf), count, off);
+       if (rc != OPAL_SUCCESS)
+               return -EIO;
+       *index += count;
+       return count;
+}
+
+static ssize_t opal_nvram_write(char *buf, size_t count, loff_t *index)
+{
+       s64 rc = OPAL_BUSY;
+       int off;
+
+       if (*index >= nvram_size)
+               return 0;
+       off = *index;
+       if ((off + count) > nvram_size)
+               count = nvram_size - off;
+
+       while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+               rc = opal_write_nvram(__pa(buf), count, off);
+               if (rc == OPAL_BUSY_EVENT)
+                       opal_poll_events(NULL);
+       }
+       *index += count;
+       return count;
+}
+
+void __init opal_nvram_init(void)
+{
+       struct device_node *np;
+       const u32 *nbytes_p;
+
+       np = of_find_compatible_node(NULL, NULL, "ibm,opal-nvram");
+       if (np == NULL)
+               return;
+
+       nbytes_p = of_get_property(np, "#bytes", NULL);
+       if (!nbytes_p) {
+               of_node_put(np);
+               return;
+       }
+       nvram_size = *nbytes_p;
+
+       printk(KERN_INFO "OPAL nvram setup, %u bytes\n", nvram_size);
+       of_node_put(np);
+
+       ppc_md.nvram_read = opal_nvram_read;
+       ppc_md.nvram_write = opal_nvram_write;
+       ppc_md.nvram_size = opal_nvram_size;
+}
+
diff --git a/arch/powerpc/platforms/powernv/opal-rtc.c b/arch/powerpc/platforms/powernv/opal-rtc.c
new file mode 100644 (file)
index 0000000..2aa7641
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * PowerNV Real Time Clock.
+ *
+ * Copyright 2011 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/kernel.h>
+#include <linux/time.h>
+#include <linux/bcd.h>
+#include <linux/rtc.h>
+#include <linux/delay.h>
+
+#include <asm/opal.h>
+#include <asm/firmware.h>
+
+static void opal_to_tm(u32 y_m_d, u64 h_m_s_ms, struct rtc_time *tm)
+{
+       tm->tm_year     = ((bcd2bin(y_m_d >> 24) * 100) +
+                          bcd2bin((y_m_d >> 16) & 0xff)) - 1900;
+       tm->tm_mon      = bcd2bin((y_m_d >> 8) & 0xff) - 1;
+       tm->tm_mday     = bcd2bin(y_m_d & 0xff);
+       tm->tm_hour     = bcd2bin((h_m_s_ms >> 56) & 0xff);
+       tm->tm_min      = bcd2bin((h_m_s_ms >> 48) & 0xff);
+       tm->tm_sec      = bcd2bin((h_m_s_ms >> 40) & 0xff);
+
+        GregorianDay(tm);
+}
+
+unsigned long __init opal_get_boot_time(void)
+{
+       struct rtc_time tm;
+       u32 y_m_d;
+       u64 h_m_s_ms;
+       long rc = OPAL_BUSY;
+
+       while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+               rc = opal_rtc_read(&y_m_d, &h_m_s_ms);
+               if (rc == OPAL_BUSY_EVENT)
+                       opal_poll_events(NULL);
+               else
+                       mdelay(10);
+       }
+       if (rc != OPAL_SUCCESS)
+               return 0;
+       opal_to_tm(y_m_d, h_m_s_ms, &tm);
+       return mktime(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+                     tm.tm_hour, tm.tm_min, tm.tm_sec);
+}
+
+void opal_get_rtc_time(struct rtc_time *tm)
+{
+       long rc = OPAL_BUSY;
+       u32 y_m_d;
+       u64 h_m_s_ms;
+
+       while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+               rc = opal_rtc_read(&y_m_d, &h_m_s_ms);
+               if (rc == OPAL_BUSY_EVENT)
+                       opal_poll_events(NULL);
+               else
+                       mdelay(10);
+       }
+       if (rc != OPAL_SUCCESS)
+               return;
+       opal_to_tm(y_m_d, h_m_s_ms, tm);
+}
+
+int opal_set_rtc_time(struct rtc_time *tm)
+{
+       long rc = OPAL_BUSY;
+       u32 y_m_d = 0;
+       u64 h_m_s_ms = 0;
+
+       y_m_d |= ((u32)bin2bcd((tm->tm_year + 1900) / 100)) << 24;
+       y_m_d |= ((u32)bin2bcd((tm->tm_year + 1900) % 100)) << 16;
+       y_m_d |= ((u32)bin2bcd((tm->tm_mon + 1))) << 8;
+       y_m_d |= ((u32)bin2bcd(tm->tm_mday));
+
+       h_m_s_ms |= ((u64)bin2bcd(tm->tm_hour)) << 56;
+       h_m_s_ms |= ((u64)bin2bcd(tm->tm_min)) << 48;
+       h_m_s_ms |= ((u64)bin2bcd(tm->tm_sec)) << 40;
+
+       while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+               rc = opal_rtc_write(y_m_d, h_m_s_ms);
+               if (rc == OPAL_BUSY_EVENT)
+                       opal_poll_events(NULL);
+               else
+                       mdelay(10);
+       }
+       return rc == OPAL_SUCCESS ? 0 : -EIO;
+}
diff --git a/arch/powerpc/platforms/powernv/opal-takeover.S b/arch/powerpc/platforms/powernv/opal-takeover.S
new file mode 100644 (file)
index 0000000..77b48b2
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * PowerNV OPAL takeover assembly code, for use by prom_init.c
+ *
+ * Copyright 2011 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 <asm/ppc_asm.h>
+#include <asm/hvcall.h>
+#include <asm/asm-offsets.h>
+#include <asm/opal.h>
+
+#define STK_PARAM(i)   (48 + ((i)-3)*8)
+
+#define H_HAL_TAKEOVER                 0x5124
+#define H_HAL_TAKEOVER_QUERY_MAGIC     -1
+
+       .text
+_GLOBAL(opal_query_takeover)
+       mfcr    r0
+       stw     r0,8(r1)
+       std     r3,STK_PARAM(r3)(r1)
+       std     r4,STK_PARAM(r4)(r1)
+       li      r3,H_HAL_TAKEOVER
+       li      r4,H_HAL_TAKEOVER_QUERY_MAGIC
+       HVSC
+       ld      r10,STK_PARAM(r3)(r1)
+       std     r4,0(r10)
+       ld      r10,STK_PARAM(r4)(r1)
+       std     r5,0(r10)
+       lwz     r0,8(r1)
+       mtcrf   0xff,r0
+       blr
+
+_GLOBAL(opal_do_takeover)
+       mfcr    r0
+       stw     r0,8(r1)
+       mflr    r0
+       std     r0,16(r1)
+       bl      __opal_do_takeover
+       ld      r0,16(r1)
+       mtlr    r0
+       lwz     r0,8(r1)
+       mtcrf   0xff,r0
+       blr
+
+__opal_do_takeover:
+       ld      r4,0(r3)
+       ld      r5,0x8(r3)
+       ld      r6,0x10(r3)
+       ld      r7,0x18(r3)
+       ld      r8,0x20(r3)
+       ld      r9,0x28(r3)
+       ld      r10,0x30(r3)
+       ld      r11,0x38(r3)
+       li      r3,H_HAL_TAKEOVER
+       HVSC
+       blr
+
+       .globl opal_secondary_entry
+opal_secondary_entry:
+       mr      r31,r3
+       mfmsr   r11
+       li      r12,(MSR_SF | MSR_ISF)@highest
+       sldi    r12,r12,48
+       or      r11,r11,r12
+       mtmsrd  r11
+       isync
+       mfspr   r4,SPRN_PIR
+       std     r4,0(r3)
+1:     HMT_LOW
+       ld      r4,8(r3)
+       cmpli   cr0,r4,0
+       beq     1b
+       HMT_MEDIUM
+1:     addi    r3,r31,16
+       bl      __opal_do_takeover
+       b       1b
+
+_GLOBAL(opal_enter_rtas)
+       mflr    r0
+       std     r0,16(r1)
+        stdu   r1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */
+
+       /* Because PROM is running in 32b mode, it clobbers the high order half
+        * of all registers that it saves.  We therefore save those registers
+        * PROM might touch to the stack.  (r0, r3-r13 are caller saved)
+       */
+       SAVE_GPR(2, r1)
+       SAVE_GPR(13, r1)
+       SAVE_8GPRS(14, r1)
+       SAVE_10GPRS(22, r1)
+       mfcr    r10
+       mfmsr   r11
+       std     r10,_CCR(r1)
+       std     r11,_MSR(r1)
+
+       /* Get the PROM entrypoint */
+       mtlr    r5
+
+       /* Switch MSR to 32 bits mode
+        */
+        li      r12,1
+        rldicr  r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
+        andc    r11,r11,r12
+        li      r12,1
+        rldicr  r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
+        andc    r11,r11,r12
+        mtmsrd  r11
+        isync
+
+       /* Enter RTAS here... */
+       blrl
+
+       /* Just make sure that r1 top 32 bits didn't get
+        * corrupt by OF
+        */
+       rldicl  r1,r1,0,32
+
+       /* Restore the MSR (back to 64 bits) */
+       ld      r0,_MSR(r1)
+       MTMSRD(r0)
+        isync
+
+       /* Restore other registers */
+       REST_GPR(2, r1)
+       REST_GPR(13, r1)
+       REST_8GPRS(14, r1)
+       REST_10GPRS(22, r1)
+       ld      r4,_CCR(r1)
+       mtcr    r4
+
+        addi   r1,r1,PROM_FRAME_SIZE
+       ld      r0,16(r1)
+       mtlr    r0
+       blr
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S
new file mode 100644 (file)
index 0000000..4a3f46d
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * PowerNV OPAL API wrappers
+ *
+ * Copyright 2011 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 <asm/ppc_asm.h>
+#include <asm/hvcall.h>
+#include <asm/asm-offsets.h>
+#include <asm/opal.h>
+
+/* TODO:
+ *
+ * - Trace irqs in/off (needs saving/restoring all args, argh...)
+ * - Get r11 feed up by Dave so I can have better register usage
+ */
+#define OPAL_CALL(name, token)         \
+ _GLOBAL(name);                                \
+       mflr    r0;                     \
+       mfcr    r12;                    \
+       std     r0,16(r1);              \
+       std     r12,8(r1);              \
+       std     r1,PACAR1(r13);         \
+       li      r0,0;                   \
+       mfmsr   r12;                    \
+       ori     r0,r0,MSR_EE;           \
+       std     r12,PACASAVEDMSR(r13);  \
+       andc    r12,r12,r0;             \
+       mtmsrd  r12,1;                  \
+       LOAD_REG_ADDR(r0,.opal_return); \
+       mtlr    r0;                     \
+       li      r0,MSR_DR|MSR_IR;       \
+       andc    r12,r12,r0;             \
+       li      r0,token;               \
+       mtspr   SPRN_HSRR1,r12;         \
+       LOAD_REG_ADDR(r11,opal);        \
+       ld      r12,8(r11);             \
+       ld      r2,0(r11);              \
+       mtspr   SPRN_HSRR0,r12;         \
+       hrfid
+
+_STATIC(opal_return)
+       ld      r2,PACATOC(r13);
+       ld      r4,8(r1);
+       ld      r5,16(r1);
+       ld      r6,PACASAVEDMSR(r13);
+       mtspr   SPRN_SRR0,r5;
+       mtspr   SPRN_SRR1,r6;
+       mtcr    r4;
+       rfid
+
+OPAL_CALL(opal_console_write,                  OPAL_CONSOLE_WRITE);
+OPAL_CALL(opal_console_read,                   OPAL_CONSOLE_READ);
+OPAL_CALL(opal_console_write_buffer_space,     OPAL_CONSOLE_WRITE_BUFFER_SPACE);
+OPAL_CALL(opal_rtc_read,                       OPAL_RTC_READ);
+OPAL_CALL(opal_rtc_write,                      OPAL_RTC_WRITE);
+OPAL_CALL(opal_cec_power_down,                 OPAL_CEC_POWER_DOWN);
+OPAL_CALL(opal_cec_reboot,                     OPAL_CEC_REBOOT);
+OPAL_CALL(opal_read_nvram,                     OPAL_READ_NVRAM);
+OPAL_CALL(opal_write_nvram,                    OPAL_WRITE_NVRAM);
+OPAL_CALL(opal_handle_interrupt,               OPAL_HANDLE_INTERRUPT);
+OPAL_CALL(opal_poll_events,                    OPAL_POLL_EVENTS);
+OPAL_CALL(opal_pci_set_hub_tce_memory,         OPAL_PCI_SET_HUB_TCE_MEMORY);
+OPAL_CALL(opal_pci_set_phb_tce_memory,         OPAL_PCI_SET_PHB_TCE_MEMORY);
+OPAL_CALL(opal_pci_config_read_byte,           OPAL_PCI_CONFIG_READ_BYTE);
+OPAL_CALL(opal_pci_config_read_half_word,      OPAL_PCI_CONFIG_READ_HALF_WORD);
+OPAL_CALL(opal_pci_config_read_word,           OPAL_PCI_CONFIG_READ_WORD);
+OPAL_CALL(opal_pci_config_write_byte,          OPAL_PCI_CONFIG_WRITE_BYTE);
+OPAL_CALL(opal_pci_config_write_half_word,     OPAL_PCI_CONFIG_WRITE_HALF_WORD);
+OPAL_CALL(opal_pci_config_write_word,          OPAL_PCI_CONFIG_WRITE_WORD);
+OPAL_CALL(opal_set_xive,                       OPAL_SET_XIVE);
+OPAL_CALL(opal_get_xive,                       OPAL_GET_XIVE);
+OPAL_CALL(opal_register_exception_handler,     OPAL_REGISTER_OPAL_EXCEPTION_HANDLER);
+OPAL_CALL(opal_pci_eeh_freeze_status,          OPAL_PCI_EEH_FREEZE_STATUS);
+OPAL_CALL(opal_pci_eeh_freeze_clear,           OPAL_PCI_EEH_FREEZE_CLEAR);
+OPAL_CALL(opal_pci_shpc,                       OPAL_PCI_SHPC);
+OPAL_CALL(opal_pci_phb_mmio_enable,            OPAL_PCI_PHB_MMIO_ENABLE);
+OPAL_CALL(opal_pci_set_phb_mem_window,         OPAL_PCI_SET_PHB_MEM_WINDOW);
+OPAL_CALL(opal_pci_map_pe_mmio_window,         OPAL_PCI_MAP_PE_MMIO_WINDOW);
+OPAL_CALL(opal_pci_set_phb_table_memory,       OPAL_PCI_SET_PHB_TABLE_MEMORY);
+OPAL_CALL(opal_pci_set_pe,                     OPAL_PCI_SET_PE);
+OPAL_CALL(opal_pci_set_peltv,                  OPAL_PCI_SET_PELTV);
+OPAL_CALL(opal_pci_set_mve,                    OPAL_PCI_SET_MVE);
+OPAL_CALL(opal_pci_set_mve_enable,             OPAL_PCI_SET_MVE_ENABLE);
+OPAL_CALL(opal_pci_get_xive_reissue,           OPAL_PCI_GET_XIVE_REISSUE);
+OPAL_CALL(opal_pci_set_xive_reissue,           OPAL_PCI_SET_XIVE_REISSUE);
+OPAL_CALL(opal_pci_set_xive_pe,                        OPAL_PCI_SET_XIVE_PE);
+OPAL_CALL(opal_get_xive_source,                        OPAL_GET_XIVE_SOURCE);
+OPAL_CALL(opal_get_msi_32,                     OPAL_GET_MSI_32);
+OPAL_CALL(opal_get_msi_64,                     OPAL_GET_MSI_64);
+OPAL_CALL(opal_start_cpu,                      OPAL_START_CPU);
+OPAL_CALL(opal_query_cpu_status,               OPAL_QUERY_CPU_STATUS);
+OPAL_CALL(opal_write_oppanel,                  OPAL_WRITE_OPPANEL);
+OPAL_CALL(opal_pci_map_pe_dma_window,          OPAL_PCI_MAP_PE_DMA_WINDOW);
+OPAL_CALL(opal_pci_map_pe_dma_window_real,     OPAL_PCI_MAP_PE_DMA_WINDOW_REAL);
+OPAL_CALL(opal_pci_reset,                      OPAL_PCI_RESET);
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
new file mode 100644 (file)
index 0000000..aaa0dba
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * PowerNV OPAL high level interfaces
+ *
+ * Copyright 2011 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.
+ */
+
+#undef DEBUG
+
+#include <linux/types.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/interrupt.h>
+#include <asm/opal.h>
+#include <asm/firmware.h>
+
+#include "powernv.h"
+
+struct opal {
+       u64 base;
+       u64 entry;
+} opal;
+
+static struct device_node *opal_node;
+static DEFINE_SPINLOCK(opal_write_lock);
+extern u64 opal_mc_secondary_handler[];
+
+int __init early_init_dt_scan_opal(unsigned long node,
+                                  const char *uname, int depth, void *data)
+{
+       const void *basep, *entryp;
+       unsigned long basesz, entrysz;
+       u64 glue;
+
+       if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
+               return 0;
+
+       basep  = of_get_flat_dt_prop(node, "opal-base-address", &basesz);
+       entryp = of_get_flat_dt_prop(node, "opal-entry-address", &entrysz);
+
+       if (!basep || !entryp)
+               return 1;
+
+       opal.base = of_read_number(basep, basesz/4);
+       opal.entry = of_read_number(entryp, entrysz/4);
+
+       pr_debug("OPAL Base  = 0x%llx (basep=%p basesz=%ld)\n",
+                opal.base, basep, basesz);
+       pr_debug("OPAL Entry = 0x%llx (entryp=%p basesz=%ld)\n",
+                opal.entry, entryp, entrysz);
+
+       powerpc_firmware_features |= FW_FEATURE_OPAL;
+       if (of_flat_dt_is_compatible(node, "ibm,opal-v2")) {
+               powerpc_firmware_features |= FW_FEATURE_OPALv2;
+               printk("OPAL V2 detected !\n");
+       } else {
+               printk("OPAL V1 detected !\n");
+       }
+
+       /* Hookup some exception handlers. We use the fwnmi area at 0x7000
+        * to provide the glue space to OPAL
+        */
+       glue = 0x7000;
+       opal_register_exception_handler(OPAL_MACHINE_CHECK_HANDLER,
+                                       __pa(opal_mc_secondary_handler[0]),
+                                       glue);
+       glue += 128;
+       opal_register_exception_handler(OPAL_HYPERVISOR_MAINTENANCE_HANDLER,
+                                       0, glue);
+       glue += 128;
+       opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue);
+
+       return 1;
+}
+
+int opal_get_chars(uint32_t vtermno, char *buf, int count)
+{
+       s64 len, rc;
+       u64 evt;
+
+       if (!opal.entry)
+               return -ENODEV;
+       opal_poll_events(&evt);
+       if ((evt & OPAL_EVENT_CONSOLE_INPUT) == 0)
+               return 0;
+       len = count;
+       rc = opal_console_read(vtermno, &len, buf);
+       if (rc == OPAL_SUCCESS)
+               return len;
+       return 0;
+}
+
+int opal_put_chars(uint32_t vtermno, const char *data, int total_len)
+{
+       int written = 0;
+       s64 len, rc;
+       unsigned long flags;
+       u64 evt;
+
+       if (!opal.entry)
+               return -ENODEV;
+
+       /* We want put_chars to be atomic to avoid mangling of hvsi
+        * packets. To do that, we first test for room and return
+        * -EAGAIN if there isn't enough.
+        *
+        * Unfortunately, opal_console_write_buffer_space() doesn't
+        * appear to work on opal v1, so we just assume there is
+        * enough room and be done with it
+        */
+       spin_lock_irqsave(&opal_write_lock, flags);
+       if (firmware_has_feature(FW_FEATURE_OPALv2)) {
+               rc = opal_console_write_buffer_space(vtermno, &len);
+               if (rc || len < total_len) {
+                       spin_unlock_irqrestore(&opal_write_lock, flags);
+                       /* Closed -> drop characters */
+                       if (rc)
+                               return total_len;
+                       opal_poll_events(&evt);
+                       return -EAGAIN;
+               }
+       }
+
+       /* We still try to handle partial completions, though they
+        * should no longer happen.
+        */
+       rc = OPAL_BUSY;
+       while(total_len > 0 && (rc == OPAL_BUSY ||
+                               rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) {
+               len = total_len;
+               rc = opal_console_write(vtermno, &len, data);
+               if (rc == OPAL_SUCCESS) {
+                       total_len -= len;
+                       data += len;
+                       written += len;
+               }
+               /* This is a bit nasty but we need that for the console to
+                * flush when there aren't any interrupts. We will clean
+                * things a bit later to limit that to synchronous path
+                * such as the kernel console and xmon/udbg
+                */
+               do
+                       opal_poll_events(&evt);
+               while(rc == OPAL_SUCCESS && (evt & OPAL_EVENT_CONSOLE_OUTPUT));
+       }
+       spin_unlock_irqrestore(&opal_write_lock, flags);
+       return written;
+}
+
+int opal_machine_check(struct pt_regs *regs)
+{
+       struct opal_machine_check_event *opal_evt = get_paca()->opal_mc_evt;
+       struct opal_machine_check_event evt;
+       const char *level, *sevstr, *subtype;
+       static const char *opal_mc_ue_types[] = {
+               "Indeterminate",
+               "Instruction fetch",
+               "Page table walk ifetch",
+               "Load/Store",
+               "Page table walk Load/Store",
+       };
+       static const char *opal_mc_slb_types[] = {
+               "Indeterminate",
+               "Parity",
+               "Multihit",
+       };
+       static const char *opal_mc_erat_types[] = {
+               "Indeterminate",
+               "Parity",
+               "Multihit",
+       };
+       static const char *opal_mc_tlb_types[] = {
+               "Indeterminate",
+               "Parity",
+               "Multihit",
+       };
+
+       /* Copy the event structure and release the original */
+       evt = *opal_evt;
+       opal_evt->in_use = 0;
+
+       /* Print things out */
+       if (evt.version != OpalMCE_V1) {
+               pr_err("Machine Check Exception, Unknown event version %d !\n",
+                      evt.version);
+               return 0;
+       }
+       switch(evt.severity) {
+       case OpalMCE_SEV_NO_ERROR:
+               level = KERN_INFO;
+               sevstr = "Harmless";
+               break;
+       case OpalMCE_SEV_WARNING:
+               level = KERN_WARNING;
+               sevstr = "";
+               break;
+       case OpalMCE_SEV_ERROR_SYNC:
+               level = KERN_ERR;
+               sevstr = "Severe";
+               break;
+       case OpalMCE_SEV_FATAL:
+       default:
+               level = KERN_ERR;
+               sevstr = "Fatal";
+               break;
+       }
+
+       printk("%s%s Machine check interrupt [%s]\n", level, sevstr,
+              evt.disposition == OpalMCE_DISPOSITION_RECOVERED ?
+              "Recovered" : "[Not recovered");
+       printk("%s  Initiator: %s\n", level,
+              evt.initiator == OpalMCE_INITIATOR_CPU ? "CPU" : "Unknown");
+       switch(evt.error_type) {
+       case OpalMCE_ERROR_TYPE_UE:
+               subtype = evt.u.ue_error.ue_error_type <
+                       ARRAY_SIZE(opal_mc_ue_types) ?
+                       opal_mc_ue_types[evt.u.ue_error.ue_error_type]
+                       : "Unknown";
+               printk("%s  Error type: UE [%s]\n", level, subtype);
+               if (evt.u.ue_error.effective_address_provided)
+                       printk("%s    Effective address: %016llx\n",
+                              level, evt.u.ue_error.effective_address);
+               if (evt.u.ue_error.physical_address_provided)
+                       printk("%s      Physial address: %016llx\n",
+                              level, evt.u.ue_error.physical_address);
+               break;
+       case OpalMCE_ERROR_TYPE_SLB:
+               subtype = evt.u.slb_error.slb_error_type <
+                       ARRAY_SIZE(opal_mc_slb_types) ?
+                       opal_mc_slb_types[evt.u.slb_error.slb_error_type]
+                       : "Unknown";
+               printk("%s  Error type: SLB [%s]\n", level, subtype);
+               if (evt.u.slb_error.effective_address_provided)
+                       printk("%s    Effective address: %016llx\n",
+                              level, evt.u.slb_error.effective_address);
+               break;
+       case OpalMCE_ERROR_TYPE_ERAT:
+               subtype = evt.u.erat_error.erat_error_type <
+                       ARRAY_SIZE(opal_mc_erat_types) ?
+                       opal_mc_erat_types[evt.u.erat_error.erat_error_type]
+                       : "Unknown";
+               printk("%s  Error type: ERAT [%s]\n", level, subtype);
+               if (evt.u.erat_error.effective_address_provided)
+                       printk("%s    Effective address: %016llx\n",
+                              level, evt.u.erat_error.effective_address);
+               break;
+       case OpalMCE_ERROR_TYPE_TLB:
+               subtype = evt.u.tlb_error.tlb_error_type <
+                       ARRAY_SIZE(opal_mc_tlb_types) ?
+                       opal_mc_tlb_types[evt.u.tlb_error.tlb_error_type]
+                       : "Unknown";
+               printk("%s  Error type: TLB [%s]\n", level, subtype);
+               if (evt.u.tlb_error.effective_address_provided)
+                       printk("%s    Effective address: %016llx\n",
+                              level, evt.u.tlb_error.effective_address);
+               break;
+       default:
+       case OpalMCE_ERROR_TYPE_UNKNOWN:
+               printk("%s  Error type: Unknown\n", level);
+               break;
+       }
+       return evt.severity == OpalMCE_SEV_FATAL ? 0 : 1;
+}
+
+static irqreturn_t opal_interrupt(int irq, void *data)
+{
+       uint64_t events;
+
+       opal_handle_interrupt(virq_to_hw(irq), &events);
+
+       /* XXX TODO: Do something with the events */
+
+       return IRQ_HANDLED;
+}
+
+static int __init opal_init(void)
+{
+       struct device_node *np, *consoles;
+       const u32 *irqs;
+       int rc, i, irqlen;
+
+       opal_node = of_find_node_by_path("/ibm,opal");
+       if (!opal_node) {
+               pr_warn("opal: Node not found\n");
+               return -ENODEV;
+       }
+       if (firmware_has_feature(FW_FEATURE_OPALv2))
+               consoles = of_find_node_by_path("/ibm,opal/consoles");
+       else
+               consoles = of_node_get(opal_node);
+
+       /* Register serial ports */
+       for_each_child_of_node(consoles, np) {
+               if (strcmp(np->name, "serial"))
+                       continue;
+               of_platform_device_create(np, NULL, NULL);
+       }
+       of_node_put(consoles);
+
+       /* Find all OPAL interrupts and request them */
+       irqs = of_get_property(opal_node, "opal-interrupts", &irqlen);
+       pr_debug("opal: Found %d interrupts reserved for OPAL\n",
+                irqs ? (irqlen / 4) : 0);
+       for (i = 0; irqs && i < (irqlen / 4); i++, irqs++) {
+               unsigned int hwirq = be32_to_cpup(irqs);
+               unsigned int irq = irq_create_mapping(NULL, hwirq);
+               if (irq == NO_IRQ) {
+                       pr_warning("opal: Failed to map irq 0x%x\n", hwirq);
+                       continue;
+               }
+               rc = request_irq(irq, opal_interrupt, 0, "opal", NULL);
+               if (rc)
+                       pr_warning("opal: Error %d requesting irq %d"
+                                  " (0x%x)\n", rc, irq, hwirq);
+       }
+       return 0;
+}
+subsys_initcall(opal_init);
diff --git a/arch/powerpc/platforms/powernv/pci-p5ioc2.c b/arch/powerpc/platforms/powernv/pci-p5ioc2.c
new file mode 100644 (file)
index 0000000..4c80f7c
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * Support PCI/PCIe on PowerNV platforms
+ *
+ * Currently supports only P5IOC2
+ *
+ * Copyright 2011 Benjamin Herrenschmidt, 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/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/msi.h>
+
+#include <asm/sections.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/opal.h>
+#include <asm/iommu.h>
+#include <asm/tce.h>
+#include <asm/abs_addr.h>
+
+#include "powernv.h"
+#include "pci.h"
+
+/* For now, use a fixed amount of TCE memory for each p5ioc2
+ * hub, 16M will do
+ */
+#define P5IOC2_TCE_MEMORY      0x01000000
+
+#ifdef CONFIG_PCI_MSI
+static int pnv_pci_p5ioc2_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
+                                   unsigned int hwirq, unsigned int is_64,
+                                   struct msi_msg *msg)
+{
+       if (WARN_ON(!is_64))
+               return -ENXIO;
+       msg->data = hwirq - phb->msi_base;
+       msg->address_hi = 0x10000000;
+       msg->address_lo = 0;
+
+       return 0;
+}
+
+static void pnv_pci_init_p5ioc2_msis(struct pnv_phb *phb)
+{
+       unsigned int bmap_size;
+       const __be32 *prop = of_get_property(phb->hose->dn,
+                                            "ibm,opal-msi-ranges", NULL);
+       if (!prop)
+               return;
+
+       /* Don't do MSI's on p5ioc2 PCI-X are they are not properly
+        * verified in HW
+        */
+       if (of_device_is_compatible(phb->hose->dn, "ibm,p5ioc2-pcix"))
+               return;
+       phb->msi_base = be32_to_cpup(prop);
+       phb->msi_count = be32_to_cpup(prop + 1);
+       bmap_size = BITS_TO_LONGS(phb->msi_count) * sizeof(unsigned long);
+       phb->msi_map = zalloc_maybe_bootmem(bmap_size, GFP_KERNEL);
+       if (!phb->msi_map) {
+               pr_err("PCI %d: Failed to allocate MSI bitmap !\n",
+                      phb->hose->global_number);
+               return;
+       }
+       phb->msi_setup = pnv_pci_p5ioc2_msi_setup;
+       phb->msi32_support = 0;
+       pr_info(" Allocated bitmap for %d MSIs (base IRQ 0x%x)\n",
+               phb->msi_count, phb->msi_base);
+}
+#else
+static void pnv_pci_init_p5ioc2_msis(struct pnv_phb *phb) { }
+#endif /* CONFIG_PCI_MSI */
+
+static void __devinit pnv_pci_p5ioc2_dma_dev_setup(struct pnv_phb *phb,
+                                                  struct pci_dev *pdev)
+{
+       if (phb->p5ioc2.iommu_table.it_map == NULL)
+               iommu_init_table(&phb->p5ioc2.iommu_table, phb->hose->node);
+
+       set_iommu_table_base(&pdev->dev, &phb->p5ioc2.iommu_table);
+}
+
+static void __init pnv_pci_init_p5ioc2_phb(struct device_node *np,
+                                          void *tce_mem, u64 tce_size)
+{
+       struct pnv_phb *phb;
+       const u64 *prop64;
+       u64 phb_id;
+       int64_t rc;
+       static int primary = 1;
+
+       pr_info(" Initializing p5ioc2 PHB %s\n", np->full_name);
+
+       prop64 = of_get_property(np, "ibm,opal-phbid", NULL);
+       if (!prop64) {
+               pr_err("  Missing \"ibm,opal-phbid\" property !\n");
+               return;
+       }
+       phb_id = be64_to_cpup(prop64);
+       pr_devel("  PHB-ID  : 0x%016llx\n", phb_id);
+       pr_devel("  TCE AT  : 0x%016lx\n", __pa(tce_mem));
+       pr_devel("  TCE SZ  : 0x%016llx\n", tce_size);
+
+       rc = opal_pci_set_phb_tce_memory(phb_id, __pa(tce_mem), tce_size);
+       if (rc != OPAL_SUCCESS) {
+               pr_err("  Failed to set TCE memory, OPAL error %lld\n", rc);
+               return;
+       }
+
+       phb = alloc_bootmem(sizeof(struct pnv_phb));
+       if (phb) {
+               memset(phb, 0, sizeof(struct pnv_phb));
+               phb->hose = pcibios_alloc_controller(np);
+       }
+       if (!phb || !phb->hose) {
+               pr_err("  Failed to allocate PCI controller\n");
+               return;
+       }
+
+       spin_lock_init(&phb->lock);
+       phb->hose->first_busno = 0;
+       phb->hose->last_busno = 0xff;
+       phb->hose->private_data = phb;
+       phb->opal_id = phb_id;
+       phb->type = PNV_PHB_P5IOC2;
+
+       phb->regs = of_iomap(np, 0);
+
+       if (phb->regs == NULL)
+               pr_err("  Failed to map registers !\n");
+       else {
+               pr_devel("  P_BUID     = 0x%08x\n", in_be32(phb->regs + 0x100));
+               pr_devel("  P_IOSZ     = 0x%08x\n", in_be32(phb->regs + 0x1b0));
+               pr_devel("  P_IO_ST    = 0x%08x\n", in_be32(phb->regs + 0x1e0));
+               pr_devel("  P_MEM1_H   = 0x%08x\n", in_be32(phb->regs + 0x1a0));
+               pr_devel("  P_MEM1_L   = 0x%08x\n", in_be32(phb->regs + 0x190));
+               pr_devel("  P_MSZ1_L   = 0x%08x\n", in_be32(phb->regs + 0x1c0));
+               pr_devel("  P_MEM_ST   = 0x%08x\n", in_be32(phb->regs + 0x1d0));
+               pr_devel("  P_MEM2_H   = 0x%08x\n", in_be32(phb->regs + 0x2c0));
+               pr_devel("  P_MEM2_L   = 0x%08x\n", in_be32(phb->regs + 0x2b0));
+               pr_devel("  P_MSZ2_H   = 0x%08x\n", in_be32(phb->regs + 0x2d0));
+               pr_devel("  P_MSZ2_L   = 0x%08x\n", in_be32(phb->regs + 0x2e0));
+       }
+
+       /* Interpret the "ranges" property */
+       /* This also maps the I/O region and sets isa_io/mem_base */
+       pci_process_bridge_OF_ranges(phb->hose, np, primary);
+       primary = 0;
+
+       phb->hose->ops = &pnv_pci_ops;
+
+       /* Setup MSI support */
+       pnv_pci_init_p5ioc2_msis(phb);
+
+       /* Setup TCEs */
+       phb->dma_dev_setup = pnv_pci_p5ioc2_dma_dev_setup;
+       pnv_pci_setup_iommu_table(&phb->p5ioc2.iommu_table,
+                                 tce_mem, tce_size, 0);
+}
+
+void __init pnv_pci_init_p5ioc2_hub(struct device_node *np)
+{
+       struct device_node *phbn;
+       const u64 *prop64;
+       u64 hub_id;
+       void *tce_mem;
+       uint64_t tce_per_phb;
+       int64_t rc;
+       int phb_count = 0;
+
+       pr_info("Probing p5ioc2 IO-Hub %s\n", np->full_name);
+
+       prop64 = of_get_property(np, "ibm,opal-hubid", NULL);
+       if (!prop64) {
+               pr_err(" Missing \"ibm,opal-hubid\" property !\n");
+               return;
+       }
+       hub_id = be64_to_cpup(prop64);
+       pr_info(" HUB-ID : 0x%016llx\n", hub_id);
+
+       /* Currently allocate 16M of TCE memory for every Hub
+        *
+        * XXX TODO: Make it chip local if possible
+        */
+       tce_mem = __alloc_bootmem(P5IOC2_TCE_MEMORY, P5IOC2_TCE_MEMORY,
+                                 __pa(MAX_DMA_ADDRESS));
+       if (!tce_mem) {
+               pr_err(" Failed to allocate TCE Memory !\n");
+               return;
+       }
+       pr_debug(" TCE    : 0x%016lx..0x%016lx\n",
+               __pa(tce_mem), __pa(tce_mem) + P5IOC2_TCE_MEMORY - 1);
+       rc = opal_pci_set_hub_tce_memory(hub_id, __pa(tce_mem),
+                                       P5IOC2_TCE_MEMORY);
+       if (rc != OPAL_SUCCESS) {
+               pr_err(" Failed to allocate TCE memory, OPAL error %lld\n", rc);
+               return;
+       }
+
+       /* Count child PHBs */
+       for_each_child_of_node(np, phbn) {
+               if (of_device_is_compatible(phbn, "ibm,p5ioc2-pcix") ||
+                   of_device_is_compatible(phbn, "ibm,p5ioc2-pciex"))
+                       phb_count++;
+       }
+
+       /* Calculate how much TCE space we can give per PHB */
+       tce_per_phb = __rounddown_pow_of_two(P5IOC2_TCE_MEMORY / phb_count);
+       pr_info(" Allocating %lld MB of TCE memory per PHB\n",
+               tce_per_phb >> 20);
+
+       /* Initialize PHBs */
+       for_each_child_of_node(np, phbn) {
+               if (of_device_is_compatible(phbn, "ibm,p5ioc2-pcix") ||
+                   of_device_is_compatible(phbn, "ibm,p5ioc2-pciex")) {
+                       pnv_pci_init_p5ioc2_phb(phbn, tce_mem, tce_per_phb);
+                       tce_mem += tce_per_phb;
+               }
+       }
+}
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
new file mode 100644 (file)
index 0000000..85bb66d
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+ * Support PCI/PCIe on PowerNV platforms
+ *
+ * Currently supports only P5IOC2
+ *
+ * Copyright 2011 Benjamin Herrenschmidt, 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/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/msi.h>
+
+#include <asm/sections.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/opal.h>
+#include <asm/iommu.h>
+#include <asm/tce.h>
+#include <asm/abs_addr.h>
+
+#include "powernv.h"
+#include "pci.h"
+
+/* Delay in usec */
+#define PCI_RESET_DELAY_US     3000000
+
+#define cfg_dbg(fmt...)        do { } while(0)
+//#define cfg_dbg(fmt...)      printk(fmt)
+
+#ifdef CONFIG_PCI_MSI
+static int pnv_msi_check_device(struct pci_dev* pdev, int nvec, int type)
+{
+       struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+       struct pnv_phb *phb = hose->private_data;
+
+       return (phb && phb->msi_map) ? 0 : -ENODEV;
+}
+
+static unsigned int pnv_get_one_msi(struct pnv_phb *phb)
+{
+       unsigned int id;
+
+       spin_lock(&phb->lock);
+       id = find_next_zero_bit(phb->msi_map, phb->msi_count, phb->msi_next);
+       if (id >= phb->msi_count && phb->msi_next)
+               id = find_next_zero_bit(phb->msi_map, phb->msi_count, 0);
+       if (id >= phb->msi_count) {
+               spin_unlock(&phb->lock);
+               return 0;
+       }
+       __set_bit(id, phb->msi_map);
+       spin_unlock(&phb->lock);
+       return id + phb->msi_base;
+}
+
+static void pnv_put_msi(struct pnv_phb *phb, unsigned int hwirq)
+{
+       unsigned int id;
+
+       if (WARN_ON(hwirq < phb->msi_base ||
+                   hwirq >= (phb->msi_base + phb->msi_count)))
+               return;
+       id = hwirq - phb->msi_base;
+       spin_lock(&phb->lock);
+       __clear_bit(id, phb->msi_map);
+       spin_unlock(&phb->lock);
+}
+
+static int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
+{
+       struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+       struct pnv_phb *phb = hose->private_data;
+       struct msi_desc *entry;
+       struct msi_msg msg;
+       unsigned int hwirq, virq;
+       int rc;
+
+       if (WARN_ON(!phb))
+               return -ENODEV;
+
+       list_for_each_entry(entry, &pdev->msi_list, list) {
+               if (!entry->msi_attrib.is_64 && !phb->msi32_support) {
+                       pr_warn("%s: Supports only 64-bit MSIs\n",
+                               pci_name(pdev));
+                       return -ENXIO;
+               }
+               hwirq = pnv_get_one_msi(phb);
+               if (!hwirq) {
+                       pr_warn("%s: Failed to find a free MSI\n",
+                               pci_name(pdev));
+                       return -ENOSPC;
+               }
+               virq = irq_create_mapping(NULL, hwirq);
+               if (virq == NO_IRQ) {
+                       pr_warn("%s: Failed to map MSI to linux irq\n",
+                               pci_name(pdev));
+                       pnv_put_msi(phb, hwirq);
+                       return -ENOMEM;
+               }
+               rc = phb->msi_setup(phb, pdev, hwirq, entry->msi_attrib.is_64,
+                                   &msg);
+               if (rc) {
+                       pr_warn("%s: Failed to setup MSI\n", pci_name(pdev));
+                       irq_dispose_mapping(virq);
+                       pnv_put_msi(phb, hwirq);
+                       return rc;
+               }
+               irq_set_msi_desc(virq, entry);
+               write_msi_msg(virq, &msg);
+       }
+       return 0;
+}
+
+static void pnv_teardown_msi_irqs(struct pci_dev *pdev)
+{
+       struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+       struct pnv_phb *phb = hose->private_data;
+       struct msi_desc *entry;
+
+       if (WARN_ON(!phb))
+               return;
+
+       list_for_each_entry(entry, &pdev->msi_list, list) {
+               if (entry->irq == NO_IRQ)
+                       continue;
+               irq_set_msi_desc(entry->irq, NULL);
+               pnv_put_msi(phb, virq_to_hw(entry->irq));
+               irq_dispose_mapping(entry->irq);
+       }
+}
+#endif /* CONFIG_PCI_MSI */
+
+static void pnv_pci_config_check_eeh(struct pnv_phb *phb, struct pci_bus *bus,
+                                    u32 bdfn)
+{
+       s64     rc;
+       u8      fstate;
+       u16     pcierr;
+       u32     pe_no;
+
+       /* Get PE# if we support IODA */
+       pe_no = phb->bdfn_to_pe ? phb->bdfn_to_pe(phb, bus, bdfn & 0xff) : 0;
+
+       /* Read freeze status */
+       rc = opal_pci_eeh_freeze_status(phb->opal_id, pe_no, &fstate, &pcierr,
+                                       NULL);
+       if (rc) {
+               pr_warning("PCI %d: Failed to read EEH status for PE#%d,"
+                          " err %lld\n", phb->hose->global_number, pe_no, rc);
+               return;
+       }
+       cfg_dbg(" -> EEH check, bdfn=%04x PE%d fstate=%x\n",
+               bdfn, pe_no, fstate);
+       if (fstate != 0) {
+               rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no,
+                                             OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
+               if (rc) {
+                       pr_warning("PCI %d: Failed to clear EEH freeze state"
+                                  " for PE#%d, err %lld\n",
+                                  phb->hose->global_number, pe_no, rc);
+               }
+       }
+}
+
+static int pnv_pci_read_config(struct pci_bus *bus,
+                              unsigned int devfn,
+                              int where, int size, u32 *val)
+{
+       struct pci_controller *hose = pci_bus_to_host(bus);
+       struct pnv_phb *phb = hose->private_data;
+       u32 bdfn = (((uint64_t)bus->number) << 8) | devfn;
+       s64 rc;
+
+       if (hose == NULL)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       switch (size) {
+       case 1: {
+               u8 v8;
+               rc = opal_pci_config_read_byte(phb->opal_id, bdfn, where, &v8);
+               *val = (rc == OPAL_SUCCESS) ? v8 : 0xff;
+               break;
+       }
+       case 2: {
+               u16 v16;
+               rc = opal_pci_config_read_half_word(phb->opal_id, bdfn, where,
+                                                  &v16);
+               *val = (rc == OPAL_SUCCESS) ? v16 : 0xffff;
+               break;
+       }
+       case 4: {
+               u32 v32;
+               rc = opal_pci_config_read_word(phb->opal_id, bdfn, where, &v32);
+               *val = (rc == OPAL_SUCCESS) ? v32 : 0xffffffff;
+               break;
+       }
+       default:
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+       }
+       cfg_dbg("pnv_pci_read_config bus: %x devfn: %x +%x/%x -> %08x\n",
+               bus->number, devfn, where, size, *val);
+
+       /* Check if the PHB got frozen due to an error (no response) */
+       pnv_pci_config_check_eeh(phb, bus, bdfn);
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int pnv_pci_write_config(struct pci_bus *bus,
+                               unsigned int devfn,
+                               int where, int size, u32 val)
+{
+       struct pci_controller *hose = pci_bus_to_host(bus);
+       struct pnv_phb *phb = hose->private_data;
+       u32 bdfn = (((uint64_t)bus->number) << 8) | devfn;
+
+       if (hose == NULL)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       cfg_dbg("pnv_pci_write_config bus: %x devfn: %x +%x/%x -> %08x\n",
+               bus->number, devfn, where, size, val);
+       switch (size) {
+       case 1:
+               opal_pci_config_write_byte(phb->opal_id, bdfn, where, val);
+               break;
+       case 2:
+               opal_pci_config_write_half_word(phb->opal_id, bdfn, where, val);
+               break;
+       case 4:
+               opal_pci_config_write_word(phb->opal_id, bdfn, where, val);
+               break;
+       default:
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+       }
+       /* Check if the PHB got frozen due to an error (no response) */
+       pnv_pci_config_check_eeh(phb, bus, bdfn);
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops pnv_pci_ops = {
+       .read = pnv_pci_read_config,
+       .write = pnv_pci_write_config,
+};
+
+static int pnv_tce_build(struct iommu_table *tbl, long index, long npages,
+                        unsigned long uaddr, enum dma_data_direction direction,
+                        struct dma_attrs *attrs)
+{
+       u64 proto_tce;
+       u64 *tcep;
+       u64 rpn;
+
+       proto_tce = TCE_PCI_READ; // Read allowed
+
+       if (direction != DMA_TO_DEVICE)
+               proto_tce |= TCE_PCI_WRITE;
+
+       tcep = ((u64 *)tbl->it_base) + index;
+
+       while (npages--) {
+               /* can't move this out since we might cross LMB boundary */
+               rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
+               *tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
+
+               uaddr += TCE_PAGE_SIZE;
+               tcep++;
+       }
+       return 0;
+}
+
+static void pnv_tce_free(struct iommu_table *tbl, long index, long npages)
+{
+       u64 *tcep = ((u64 *)tbl->it_base) + index;
+
+       while (npages--)
+               *(tcep++) = 0;
+}
+
+void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
+                              void *tce_mem, u64 tce_size,
+                              u64 dma_offset)
+{
+       tbl->it_blocksize = 16;
+       tbl->it_base = (unsigned long)tce_mem;
+       tbl->it_offset = dma_offset >> IOMMU_PAGE_SHIFT;
+       tbl->it_index = 0;
+       tbl->it_size = tce_size >> 3;
+       tbl->it_busno = 0;
+       tbl->it_type = TCE_PCI;
+}
+
+static struct iommu_table * __devinit
+pnv_pci_setup_bml_iommu(struct pci_controller *hose)
+{
+       struct iommu_table *tbl;
+       const __be64 *basep;
+       const __be32 *sizep;
+
+       basep = of_get_property(hose->dn, "linux,tce-base", NULL);
+       sizep = of_get_property(hose->dn, "linux,tce-size", NULL);
+       if (basep == NULL || sizep == NULL) {
+               pr_err("PCI: %s has missing tce entries !\n", hose->dn->full_name);
+               return NULL;
+       }
+       tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL, hose->node);
+       if (WARN_ON(!tbl))
+               return NULL;
+       pnv_pci_setup_iommu_table(tbl, __va(be64_to_cpup(basep)),
+                                 be32_to_cpup(sizep), 0);
+       iommu_init_table(tbl, hose->node);
+       return tbl;
+}
+
+static void __devinit pnv_pci_dma_fallback_setup(struct pci_controller *hose,
+                                                struct pci_dev *pdev)
+{
+       struct device_node *np = pci_bus_to_OF_node(hose->bus);
+       struct pci_dn *pdn;
+
+       if (np == NULL)
+               return;
+       pdn = PCI_DN(np);
+       if (!pdn->iommu_table)
+               pdn->iommu_table = pnv_pci_setup_bml_iommu(hose);
+       if (!pdn->iommu_table)
+               return;
+       set_iommu_table_base(&pdev->dev, pdn->iommu_table);
+}
+
+static void __devinit pnv_pci_dma_dev_setup(struct pci_dev *pdev)
+{
+       struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+       struct pnv_phb *phb = hose->private_data;
+
+       /* If we have no phb structure, try to setup a fallback based on
+        * the device-tree (RTAS PCI for example)
+        */
+       if (phb && phb->dma_dev_setup)
+               phb->dma_dev_setup(phb, pdev);
+       else
+               pnv_pci_dma_fallback_setup(hose, pdev);
+}
+
+static int pnv_pci_probe_mode(struct pci_bus *bus)
+{
+       struct pci_controller *hose = pci_bus_to_host(bus);
+       const __be64 *tstamp;
+       u64 now, target;
+
+
+       /* We hijack this as a way to ensure we have waited long
+        * enough since the reset was lifted on the PCI bus
+        */
+       if (bus != hose->bus)
+               return PCI_PROBE_NORMAL;
+       tstamp = of_get_property(hose->dn, "reset-clear-timestamp", NULL);
+       if (!tstamp || !*tstamp)
+               return PCI_PROBE_NORMAL;
+
+       now = mftb() / tb_ticks_per_usec;
+       target = (be64_to_cpup(tstamp) / tb_ticks_per_usec)
+               + PCI_RESET_DELAY_US;
+
+       pr_devel("pci %04d: Reset target: 0x%llx now: 0x%llx\n",
+                hose->global_number, target, now);
+
+       if (now < target)
+               msleep((target - now + 999) / 1000);
+
+       return PCI_PROBE_NORMAL;
+}
+
+void __init pnv_pci_init(void)
+{
+       struct device_node *np;
+
+       pci_set_flags(PCI_CAN_SKIP_ISA_ALIGN);
+
+       /* We do not want to just probe */
+       pci_probe_only = 0;
+
+       /* OPAL absent, try POPAL first then RTAS detection of PHBs */
+       if (!firmware_has_feature(FW_FEATURE_OPAL)) {
+#ifdef CONFIG_PPC_POWERNV_RTAS
+               init_pci_config_tokens();
+               find_and_init_phbs();
+#endif /* CONFIG_PPC_POWERNV_RTAS */
+       } else {
+               /* OPAL is here, do our normal stuff */
+
+               /* Look for p5ioc2 IO-Hubs */
+               for_each_compatible_node(np, NULL, "ibm,p5ioc2")
+                       pnv_pci_init_p5ioc2_hub(np);
+       }
+
+       /* Setup the linkage between OF nodes and PHBs */
+       pci_devs_phb_init();
+
+       /* Configure IOMMU DMA hooks */
+       ppc_md.pci_dma_dev_setup = pnv_pci_dma_dev_setup;
+       ppc_md.tce_build = pnv_tce_build;
+       ppc_md.tce_free = pnv_tce_free;
+       ppc_md.pci_probe_mode = pnv_pci_probe_mode;
+       set_pci_dma_ops(&dma_iommu_ops);
+
+       /* Configure MSIs */
+#ifdef CONFIG_PCI_MSI
+       ppc_md.msi_check_device = pnv_msi_check_device;
+       ppc_md.setup_msi_irqs = pnv_setup_msi_irqs;
+       ppc_md.teardown_msi_irqs = pnv_teardown_msi_irqs;
+#endif
+}
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
new file mode 100644 (file)
index 0000000..d4dbc49
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __POWERNV_PCI_H
+#define __POWERNV_PCI_H
+
+struct pci_dn;
+
+enum pnv_phb_type {
+       PNV_PHB_P5IOC2,
+       PNV_PHB_IODA1,
+       PNV_PHB_IODA2,
+};
+
+struct pnv_phb {
+       struct pci_controller   *hose;
+       enum pnv_phb_type       type;
+       u64                     opal_id;
+       void __iomem            *regs;
+       spinlock_t              lock;
+
+#ifdef CONFIG_PCI_MSI
+       unsigned long           *msi_map;
+       unsigned int            msi_base;
+       unsigned int            msi_count;
+       unsigned int            msi_next;
+       unsigned int            msi32_support;
+#endif
+       int (*msi_setup)(struct pnv_phb *phb, struct pci_dev *dev,
+                        unsigned int hwirq, unsigned int is_64,
+                        struct msi_msg *msg);
+       void (*dma_dev_setup)(struct pnv_phb *phb, struct pci_dev *pdev);
+       void (*fixup_phb)(struct pci_controller *hose);
+       u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn);
+
+       union {
+               struct {
+                       struct iommu_table iommu_table;
+               } p5ioc2;
+       };
+};
+
+extern struct pci_ops pnv_pci_ops;
+
+extern void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
+                                     void *tce_mem, u64 tce_size,
+                                     u64 dma_offset);
+extern void pnv_pci_init_p5ioc2_hub(struct device_node *np);
+
+
+#endif /* __POWERNV_PCI_H */
diff --git a/arch/powerpc/platforms/powernv/powernv.h b/arch/powerpc/platforms/powernv/powernv.h
new file mode 100644 (file)
index 0000000..8a9df7f
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _POWERNV_H
+#define _POWERNV_H
+
+#ifdef CONFIG_SMP
+extern void pnv_smp_init(void);
+#else
+static inline void pnv_smp_init(void) { }
+#endif
+
+#ifdef CONFIG_PCI
+extern void pnv_pci_init(void);
+#else
+static inline void pnv_pci_init(void) { }
+#endif
+
+#endif /* _POWERNV_H */
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
new file mode 100644 (file)
index 0000000..467bd4a
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * PowerNV setup code.
+ *
+ * Copyright 2011 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.
+ */
+
+#undef DEBUG
+
+#include <linux/cpu.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/of.h>
+#include <linux/interrupt.h>
+#include <linux/bug.h>
+
+#include <asm/machdep.h>
+#include <asm/firmware.h>
+#include <asm/xics.h>
+#include <asm/rtas.h>
+#include <asm/opal.h>
+#include <asm/xics.h>
+
+#include "powernv.h"
+
+static void __init pnv_setup_arch(void)
+{
+       /* Initialize SMP */
+       pnv_smp_init();
+
+       /* Setup PCI */
+       pnv_pci_init();
+
+       /* Setup RTC and NVRAM callbacks */
+       if (firmware_has_feature(FW_FEATURE_OPAL))
+               opal_nvram_init();
+
+       /* Enable NAP mode */
+       powersave_nap = 1;
+
+       /* XXX PMCS */
+}
+
+static void __init pnv_init_early(void)
+{
+#ifdef CONFIG_HVC_OPAL
+       if (firmware_has_feature(FW_FEATURE_OPAL))
+               hvc_opal_init_early();
+       else
+#endif
+               add_preferred_console("hvc", 0, NULL);
+}
+
+static void __init pnv_init_IRQ(void)
+{
+       xics_init();
+
+       WARN_ON(!ppc_md.get_irq);
+}
+
+static void pnv_show_cpuinfo(struct seq_file *m)
+{
+       struct device_node *root;
+       const char *model = "";
+
+       root = of_find_node_by_path("/");
+       if (root)
+               model = of_get_property(root, "model", NULL);
+       seq_printf(m, "machine\t\t: PowerNV %s\n", model);
+       if (firmware_has_feature(FW_FEATURE_OPALv2))
+               seq_printf(m, "firmware\t: OPAL v2\n");
+       else if (firmware_has_feature(FW_FEATURE_OPAL))
+               seq_printf(m, "firmware\t: OPAL v1\n");
+       else
+               seq_printf(m, "firmware\t: BML\n");
+       of_node_put(root);
+}
+
+static void  __noreturn pnv_restart(char *cmd)
+{
+       long rc = OPAL_BUSY;
+
+       while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+               rc = opal_cec_reboot();
+               if (rc == OPAL_BUSY_EVENT)
+                       opal_poll_events(NULL);
+               else
+                       mdelay(10);
+       }
+       for (;;)
+               opal_poll_events(NULL);
+}
+
+static void __noreturn pnv_power_off(void)
+{
+       long rc = OPAL_BUSY;
+
+       while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+               rc = opal_cec_power_down(0);
+               if (rc == OPAL_BUSY_EVENT)
+                       opal_poll_events(NULL);
+               else
+                       mdelay(10);
+       }
+       for (;;)
+               opal_poll_events(NULL);
+}
+
+static void __noreturn pnv_halt(void)
+{
+       pnv_power_off();
+}
+
+static void pnv_progress(char *s, unsigned short hex)
+{
+}
+
+#ifdef CONFIG_KEXEC
+static void pnv_kexec_cpu_down(int crash_shutdown, int secondary)
+{
+       xics_kexec_teardown_cpu(secondary);
+}
+#endif /* CONFIG_KEXEC */
+
+static void __init pnv_setup_machdep_opal(void)
+{
+       ppc_md.get_boot_time = opal_get_boot_time;
+       ppc_md.get_rtc_time = opal_get_rtc_time;
+       ppc_md.set_rtc_time = opal_set_rtc_time;
+       ppc_md.restart = pnv_restart;
+       ppc_md.power_off = pnv_power_off;
+       ppc_md.halt = pnv_halt;
+       ppc_md.machine_check_exception = opal_machine_check;
+}
+
+#ifdef CONFIG_PPC_POWERNV_RTAS
+static void __init pnv_setup_machdep_rtas(void)
+{
+       if (rtas_token("get-time-of-day") != RTAS_UNKNOWN_SERVICE) {
+               ppc_md.get_boot_time = rtas_get_boot_time;
+               ppc_md.get_rtc_time = rtas_get_rtc_time;
+               ppc_md.set_rtc_time = rtas_set_rtc_time;
+       }
+       ppc_md.restart = rtas_restart;
+       ppc_md.power_off = rtas_power_off;
+       ppc_md.halt = rtas_halt;
+}
+#endif /* CONFIG_PPC_POWERNV_RTAS */
+
+static int __init pnv_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+
+       if (!of_flat_dt_is_compatible(root, "ibm,powernv"))
+               return 0;
+
+       hpte_init_native();
+
+       if (firmware_has_feature(FW_FEATURE_OPAL))
+               pnv_setup_machdep_opal();
+#ifdef CONFIG_PPC_POWERNV_RTAS
+       else if (rtas.base)
+               pnv_setup_machdep_rtas();
+#endif /* CONFIG_PPC_POWERNV_RTAS */
+
+       pr_debug("PowerNV detected !\n");
+
+       return 1;
+}
+
+define_machine(powernv) {
+       .name                   = "PowerNV",
+       .probe                  = pnv_probe,
+       .init_early             = pnv_init_early,
+       .setup_arch             = pnv_setup_arch,
+       .init_IRQ               = pnv_init_IRQ,
+       .show_cpuinfo           = pnv_show_cpuinfo,
+       .progress               = pnv_progress,
+       .power_save             = power7_idle,
+       .calibrate_decr         = generic_calibrate_decr,
+#ifdef CONFIG_KEXEC
+       .kexec_cpu_down         = pnv_kexec_cpu_down,
+#endif
+};
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c
new file mode 100644 (file)
index 0000000..e877366
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * SMP support for PowerNV machines.
+ *
+ * Copyright 2011 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/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/cpu.h>
+
+#include <asm/irq.h>
+#include <asm/smp.h>
+#include <asm/paca.h>
+#include <asm/machdep.h>
+#include <asm/cputable.h>
+#include <asm/firmware.h>
+#include <asm/system.h>
+#include <asm/rtas.h>
+#include <asm/vdso_datapage.h>
+#include <asm/cputhreads.h>
+#include <asm/xics.h>
+#include <asm/opal.h>
+
+#include "powernv.h"
+
+#ifdef DEBUG
+#include <asm/udbg.h>
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+static void __cpuinit pnv_smp_setup_cpu(int cpu)
+{
+       if (cpu != boot_cpuid)
+               xics_setup_cpu();
+}
+
+static int pnv_smp_cpu_bootable(unsigned int nr)
+{
+       /* Special case - we inhibit secondary thread startup
+        * during boot if the user requests it.
+        */
+       if (system_state < SYSTEM_RUNNING && cpu_has_feature(CPU_FTR_SMT)) {
+               if (!smt_enabled_at_boot && cpu_thread_in_core(nr) != 0)
+                       return 0;
+               if (smt_enabled_at_boot
+                   && cpu_thread_in_core(nr) >= smt_enabled_at_boot)
+                       return 0;
+       }
+
+       return 1;
+}
+
+int __devinit pnv_smp_kick_cpu(int nr)
+{
+       unsigned int pcpu = get_hard_smp_processor_id(nr);
+       unsigned long start_here = __pa(*((unsigned long *)
+                                         generic_secondary_smp_init));
+       long rc;
+
+       BUG_ON(nr < 0 || nr >= NR_CPUS);
+
+       /* On OPAL v2 the CPU are still spinning inside OPAL itself,
+        * get them back now
+        */
+       if (firmware_has_feature(FW_FEATURE_OPALv2)) {
+               pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n", nr, pcpu);
+               rc = opal_start_cpu(pcpu, start_here);
+               if (rc != OPAL_SUCCESS)
+                       pr_warn("OPAL Error %ld starting CPU %d\n",
+                               rc, nr);
+       }
+       return smp_generic_kick_cpu(nr);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+static int pnv_smp_cpu_disable(void)
+{
+       int cpu = smp_processor_id();
+
+       /* This is identical to pSeries... might consolidate by
+        * moving migrate_irqs_away to a ppc_md with default to
+        * the generic fixup_irqs. --BenH.
+        */
+       set_cpu_online(cpu, false);
+       vdso_data->processorCount--;
+       if (cpu == boot_cpuid)
+               boot_cpuid = cpumask_any(cpu_online_mask);
+       xics_migrate_irqs_away();
+       return 0;
+}
+
+static void pnv_smp_cpu_kill_self(void)
+{
+       unsigned int cpu;
+
+       /* If powersave_nap is enabled, use NAP mode, else just
+        * spin aimlessly
+        */
+       if (!powersave_nap) {
+               generic_mach_cpu_die();
+               return;
+       }
+
+       /* Standard hot unplug procedure */
+       local_irq_disable();
+       idle_task_exit();
+       current->active_mm = NULL; /* for sanity */
+       cpu = smp_processor_id();
+       DBG("CPU%d offline\n", cpu);
+       generic_set_cpu_dead(cpu);
+       smp_wmb();
+
+       /* We don't want to take decrementer interrupts while we are offline,
+        * so clear LPCR:PECE1. We keep PECE2 enabled.
+        */
+       mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1);
+       while (!generic_check_cpu_restart(cpu)) {
+               power7_idle();
+               if (!generic_check_cpu_restart(cpu)) {
+                       DBG("CPU%d Unexpected exit while offline !\n", cpu);
+                       /* We may be getting an IPI, so we re-enable
+                        * interrupts to process it, it will be ignored
+                        * since we aren't online (hopefully)
+                        */
+                       local_irq_enable();
+                       local_irq_disable();
+               }
+       }
+       mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_PECE1);
+       DBG("CPU%d coming online...\n", cpu);
+}
+
+#endif /* CONFIG_HOTPLUG_CPU */
+
+static struct smp_ops_t pnv_smp_ops = {
+       .message_pass   = smp_muxed_ipi_message_pass,
+       .cause_ipi      = NULL, /* Filled at runtime by xics_smp_probe() */
+       .probe          = xics_smp_probe,
+       .kick_cpu       = pnv_smp_kick_cpu,
+       .setup_cpu      = pnv_smp_setup_cpu,
+       .cpu_bootable   = pnv_smp_cpu_bootable,
+#ifdef CONFIG_HOTPLUG_CPU
+       .cpu_disable    = pnv_smp_cpu_disable,
+       .cpu_die        = generic_cpu_die,
+#endif /* CONFIG_HOTPLUG_CPU */
+};
+
+/* This is called very early during platform setup_arch */
+void __init pnv_smp_init(void)
+{
+       smp_ops = &pnv_smp_ops;
+
+       /* XXX We don't yet have a proper entry point from HAL, for
+        * now we rely on kexec-style entry from BML
+        */
+
+#ifdef CONFIG_PPC_RTAS
+       /* Non-lpar has additional take/give timebase */
+       if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
+               smp_ops->give_timebase = rtas_give_timebase;
+               smp_ops->take_timebase = rtas_take_timebase;
+       }
+#endif /* CONFIG_PPC_RTAS */
+
+#ifdef CONFIG_HOTPLUG_CPU
+       ppc_md.cpu_die  = pnv_smp_cpu_kill_self;
+#endif
+}
index dfe316b..476d9d9 100644 (file)
@@ -148,4 +148,16 @@ config PS3_LPM
          profiling support of the Cell processor with programs like
          oprofile and perfmon2, then say Y or M, otherwise say N.
 
+config PS3GELIC_UDBG
+       bool "PS3 udbg output via UDP broadcasts on Ethernet"
+       depends on PPC_PS3
+       help
+         Enables udbg early debugging output by sending broadcast UDP
+         via the Ethernet port (UDP port number 18194).
+
+         This driver uses a trivial implementation and is independent
+         from the main network driver.
+
+         If in doubt, say N here.
+
 endmenu
index ac1bdf8..02b9e63 100644 (file)
@@ -2,6 +2,7 @@ obj-y += setup.o mm.o time.o hvcall.o htab.o repository.o
 obj-y += interrupt.o exports.o os-area.o
 obj-y += system-bus.o
 
+obj-$(CONFIG_PS3GELIC_UDBG) += gelic_udbg.o
 obj-$(CONFIG_SMP) += smp.o
 obj-$(CONFIG_SPU_BASE) += spu.o
 obj-y += device-init.o
diff --git a/arch/powerpc/platforms/ps3/gelic_udbg.c b/arch/powerpc/platforms/ps3/gelic_udbg.c
new file mode 100644 (file)
index 0000000..20b46a1
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * udbg debug output routine via GELIC UDP broadcasts
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2006, 2007 Sony Corporation
+ * Copyright (C) 2010 Hector Martin <hector@marcansoft.com>
+ * Copyright (C) 2011 Andre Heider <a.heider@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ */
+
+#include <asm/io.h>
+#include <asm/udbg.h>
+#include <asm/lv1call.h>
+
+#define GELIC_BUS_ID 1
+#define GELIC_DEVICE_ID 0
+#define GELIC_DEBUG_PORT 18194
+#define GELIC_MAX_MESSAGE_SIZE 1000
+
+#define GELIC_LV1_GET_MAC_ADDRESS 1
+#define GELIC_LV1_GET_VLAN_ID 4
+#define GELIC_LV1_VLAN_TX_ETHERNET_0 2
+
+#define GELIC_DESCR_DMA_STAT_MASK 0xf0000000
+#define GELIC_DESCR_DMA_CARDOWNED 0xa0000000
+
+#define GELIC_DESCR_TX_DMA_IKE 0x00080000
+#define GELIC_DESCR_TX_DMA_NO_CHKSUM 0x00000000
+#define GELIC_DESCR_TX_DMA_FRAME_TAIL 0x00040000
+
+#define GELIC_DESCR_DMA_CMD_NO_CHKSUM (GELIC_DESCR_DMA_CARDOWNED | \
+                                      GELIC_DESCR_TX_DMA_IKE | \
+                                      GELIC_DESCR_TX_DMA_NO_CHKSUM)
+
+static u64 bus_addr;
+
+struct gelic_descr {
+       /* as defined by the hardware */
+       __be32 buf_addr;
+       __be32 buf_size;
+       __be32 next_descr_addr;
+       __be32 dmac_cmd_status;
+       __be32 result_size;
+       __be32 valid_size;      /* all zeroes for tx */
+       __be32 data_status;
+       __be32 data_error;      /* all zeroes for tx */
+} __attribute__((aligned(32)));
+
+struct debug_block {
+       struct gelic_descr descr;
+       u8 pkt[1520];
+} __packed;
+
+struct ethhdr {
+       u8 dest[6];
+       u8 src[6];
+       u16 type;
+} __packed;
+
+struct vlantag {
+       u16 vlan;
+       u16 subtype;
+} __packed;
+
+struct iphdr {
+       u8 ver_len;
+       u8 dscp_ecn;
+       u16 total_length;
+       u16 ident;
+       u16 frag_off_flags;
+       u8 ttl;
+       u8 proto;
+       u16 checksum;
+       u32 src;
+       u32 dest;
+} __packed;
+
+struct udphdr {
+       u16 src;
+       u16 dest;
+       u16 len;
+       u16 checksum;
+} __packed;
+
+static __iomem struct ethhdr *h_eth;
+static __iomem struct vlantag *h_vlan;
+static __iomem struct iphdr *h_ip;
+static __iomem struct udphdr *h_udp;
+
+static __iomem char *pmsg;
+static __iomem char *pmsgc;
+
+static __iomem struct debug_block dbg __attribute__((aligned(32)));
+
+static int header_size;
+
+static void map_dma_mem(int bus_id, int dev_id, void *start, size_t len,
+                       u64 *real_bus_addr)
+{
+       s64 result;
+       u64 real_addr = ((u64)start) & 0x0fffffffffffffffUL;
+       u64 real_end = real_addr + len;
+       u64 map_start = real_addr & ~0xfff;
+       u64 map_end = (real_end + 0xfff) & ~0xfff;
+       u64 bus_addr = 0;
+
+       u64 flags = 0xf800000000000000UL;
+
+       result = lv1_allocate_device_dma_region(bus_id, dev_id,
+                                               map_end - map_start, 12, 0,
+                                               &bus_addr);
+       if (result)
+               lv1_panic(0);
+
+       result = lv1_map_device_dma_region(bus_id, dev_id, map_start,
+                                          bus_addr, map_end - map_start,
+                                          flags);
+       if (result)
+               lv1_panic(0);
+
+       *real_bus_addr = bus_addr + real_addr - map_start;
+}
+
+static int unmap_dma_mem(int bus_id, int dev_id, u64 bus_addr, size_t len)
+{
+       s64 result;
+       u64 real_bus_addr;
+
+       real_bus_addr = bus_addr & ~0xfff;
+       len += bus_addr - real_bus_addr;
+       len = (len + 0xfff) & ~0xfff;
+
+       result = lv1_unmap_device_dma_region(bus_id, dev_id, real_bus_addr,
+                                            len);
+       if (result)
+               return result;
+
+       return lv1_free_device_dma_region(bus_id, dev_id, real_bus_addr);
+}
+
+static void gelic_debug_init(void)
+{
+       s64 result;
+       u64 v2;
+       u64 mac;
+       u64 vlan_id;
+
+       result = lv1_open_device(GELIC_BUS_ID, GELIC_DEVICE_ID, 0);
+       if (result)
+               lv1_panic(0);
+
+       map_dma_mem(GELIC_BUS_ID, GELIC_DEVICE_ID, &dbg, sizeof(dbg),
+                   &bus_addr);
+
+       memset(&dbg, 0, sizeof(dbg));
+
+       dbg.descr.buf_addr = bus_addr + offsetof(struct debug_block, pkt);
+
+       wmb();
+
+       result = lv1_net_control(GELIC_BUS_ID, GELIC_DEVICE_ID,
+                                GELIC_LV1_GET_MAC_ADDRESS, 0, 0, 0,
+                                &mac, &v2);
+       if (result)
+               lv1_panic(0);
+
+       mac <<= 16;
+
+       h_eth = (struct ethhdr *)dbg.pkt;
+
+       memset(&h_eth->dest, 0xff, 6);
+       memcpy(&h_eth->src, &mac, 6);
+
+       header_size = sizeof(struct ethhdr);
+
+       result = lv1_net_control(GELIC_BUS_ID, GELIC_DEVICE_ID,
+                                GELIC_LV1_GET_VLAN_ID,
+                                GELIC_LV1_VLAN_TX_ETHERNET_0, 0, 0,
+                                &vlan_id, &v2);
+       if (!result) {
+               h_eth->type = 0x8100;
+
+               header_size += sizeof(struct vlantag);
+               h_vlan = (struct vlantag *)(h_eth + 1);
+               h_vlan->vlan = vlan_id;
+               h_vlan->subtype = 0x0800;
+               h_ip = (struct iphdr *)(h_vlan + 1);
+       } else {
+               h_eth->type = 0x0800;
+               h_ip = (struct iphdr *)(h_eth + 1);
+       }
+
+       header_size += sizeof(struct iphdr);
+       h_ip->ver_len = 0x45;
+       h_ip->ttl = 10;
+       h_ip->proto = 0x11;
+       h_ip->src = 0x00000000;
+       h_ip->dest = 0xffffffff;
+
+       header_size += sizeof(struct udphdr);
+       h_udp = (struct udphdr *)(h_ip + 1);
+       h_udp->src = GELIC_DEBUG_PORT;
+       h_udp->dest = GELIC_DEBUG_PORT;
+
+       pmsgc = pmsg = (char *)(h_udp + 1);
+}
+
+static void gelic_debug_shutdown(void)
+{
+       if (bus_addr)
+               unmap_dma_mem(GELIC_BUS_ID, GELIC_DEVICE_ID,
+                             bus_addr, sizeof(dbg));
+       lv1_close_device(GELIC_BUS_ID, GELIC_DEVICE_ID);
+}
+
+static void gelic_sendbuf(int msgsize)
+{
+       u16 *p;
+       u32 sum;
+       int i;
+
+       dbg.descr.buf_size = header_size + msgsize;
+       h_ip->total_length = msgsize + sizeof(struct udphdr) +
+                            sizeof(struct iphdr);
+       h_udp->len = msgsize + sizeof(struct udphdr);
+
+       h_ip->checksum = 0;
+       sum = 0;
+       p = (u16 *)h_ip;
+       for (i = 0; i < 5; i++)
+               sum += *p++;
+       h_ip->checksum = ~(sum + (sum >> 16));
+
+       dbg.descr.dmac_cmd_status = GELIC_DESCR_DMA_CMD_NO_CHKSUM |
+                                   GELIC_DESCR_TX_DMA_FRAME_TAIL;
+       dbg.descr.result_size = 0;
+       dbg.descr.data_status = 0;
+
+       wmb();
+
+       lv1_net_start_tx_dma(GELIC_BUS_ID, GELIC_DEVICE_ID, bus_addr, 0);
+
+       while ((dbg.descr.dmac_cmd_status & GELIC_DESCR_DMA_STAT_MASK) ==
+              GELIC_DESCR_DMA_CARDOWNED)
+               cpu_relax();
+}
+
+static void ps3gelic_udbg_putc(char ch)
+{
+       *pmsgc++ = ch;
+       if (ch == '\n' || (pmsgc-pmsg) >= GELIC_MAX_MESSAGE_SIZE) {
+               gelic_sendbuf(pmsgc-pmsg);
+               pmsgc = pmsg;
+       }
+}
+
+void __init udbg_init_ps3gelic(void)
+{
+       gelic_debug_init();
+       udbg_putc = ps3gelic_udbg_putc;
+}
+
+void udbg_shutdown_ps3gelic(void)
+{
+       udbg_putc = NULL;
+       gelic_debug_shutdown();
+}
+EXPORT_SYMBOL(udbg_shutdown_ps3gelic);
index 23083c3..688141c 100644 (file)
@@ -695,12 +695,18 @@ static int ps3_dma_supported(struct device *_dev, u64 mask)
        return mask >= DMA_BIT_MASK(32);
 }
 
+static u64 ps3_dma_get_required_mask(struct device *_dev)
+{
+       return DMA_BIT_MASK(32);
+}
+
 static struct dma_map_ops ps3_sb_dma_ops = {
        .alloc_coherent = ps3_alloc_coherent,
        .free_coherent = ps3_free_coherent,
        .map_sg = ps3_sb_map_sg,
        .unmap_sg = ps3_sb_unmap_sg,
        .dma_supported = ps3_dma_supported,
+       .get_required_mask = ps3_dma_get_required_mask,
        .map_page = ps3_sb_map_page,
        .unmap_page = ps3_unmap_page,
 };
@@ -711,6 +717,7 @@ static struct dma_map_ops ps3_ioc0_dma_ops = {
        .map_sg = ps3_ioc0_map_sg,
        .unmap_sg = ps3_ioc0_unmap_sg,
        .dma_supported = ps3_dma_supported,
+       .get_required_mask = ps3_dma_get_required_mask,
        .map_page = ps3_ioc0_map_page,
        .unmap_page = ps3_unmap_page,
 };
index 05cf476..c81f6bb 100644 (file)
@@ -15,6 +15,7 @@ config PPC_PSERIES
        select PPC_UDBG_16550
        select PPC_NATIVE
        select PPC_PCI_CHOICE if EXPERT
+       select ZLIB_DEFLATE
        default y
 
 config PPC_SPLPAR
index e9be25b..0f1b706 100644 (file)
@@ -112,6 +112,7 @@ void dlpar_free_cc_nodes(struct device_node *dn)
        dlpar_free_one_cc_node(dn);
 }
 
+#define COMPLETE       0
 #define NEXT_SIBLING    1
 #define NEXT_CHILD      2
 #define NEXT_PROPERTY   3
@@ -158,6 +159,9 @@ struct device_node *dlpar_configure_connector(u32 drc_index)
                spin_unlock(&rtas_data_buf_lock);
 
                switch (rc) {
+               case COMPLETE:
+                       break;
+
                case NEXT_SIBLING:
                        dn = dlpar_parse_cc_node(ccwa);
                        if (!dn)
index ada6e07..d42f37d 100644 (file)
@@ -1338,7 +1338,7 @@ static const struct file_operations proc_eeh_operations = {
 static int __init eeh_init_proc(void)
 {
        if (machine_is(pseries))
-               proc_create("ppc64/eeh", 0, NULL, &proc_eeh_operations);
+               proc_create("powerpc/eeh", 0, NULL, &proc_eeh_operations);
        return 0;
 }
 __initcall(eeh_init_proc);
index 01faab9..5905a3b 100644 (file)
@@ -939,14 +939,14 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
        if (ret) {
                dev_info(&dev->dev, "failed to map direct window for %s: %d\n",
                         dn->full_name, ret);
-               goto out_clear_window;
+               goto out_free_window;
        }
 
        ret = prom_add_property(pdn, win64);
        if (ret) {
                dev_err(&dev->dev, "unable to add dma window property for %s: %d",
                         pdn->full_name, ret);
-               goto out_clear_window;
+               goto out_free_window;
        }
 
        window->device = pdn;
@@ -958,6 +958,9 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
        dma_addr = of_read_number(&create.addr_hi, 2);
        goto out_unlock;
 
+out_free_window:
+       kfree(window);
+
 out_clear_window:
        remove_ddw(pdn);
 
@@ -1077,12 +1080,38 @@ check_mask:
        return 0;
 }
 
+static u64 dma_get_required_mask_pSeriesLP(struct device *dev)
+{
+       if (!dev->dma_mask)
+               return 0;
+
+       if (!disable_ddw && dev_is_pci(dev)) {
+               struct pci_dev *pdev = to_pci_dev(dev);
+               struct device_node *dn;
+
+               dn = pci_device_to_OF_node(pdev);
+
+               /* search upwards for ibm,dma-window */
+               for (; dn && PCI_DN(dn) && !PCI_DN(dn)->iommu_table;
+                               dn = dn->parent)
+                       if (of_get_property(dn, "ibm,dma-window", NULL))
+                               break;
+               /* if there is a ibm,ddw-applicable property require 64 bits */
+               if (dn && PCI_DN(dn) &&
+                               of_get_property(dn, "ibm,ddw-applicable", NULL))
+                       return DMA_BIT_MASK(64);
+       }
+
+       return dma_iommu_ops.get_required_mask(dev);
+}
+
 #else  /* CONFIG_PCI */
 #define pci_dma_bus_setup_pSeries      NULL
 #define pci_dma_dev_setup_pSeries      NULL
 #define pci_dma_bus_setup_pSeriesLP    NULL
 #define pci_dma_dev_setup_pSeriesLP    NULL
 #define dma_set_mask_pSeriesLP         NULL
+#define dma_get_required_mask_pSeriesLP        NULL
 #endif /* !CONFIG_PCI */
 
 static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action,
@@ -1186,6 +1215,7 @@ void iommu_init_early_pSeries(void)
                ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP;
                ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP;
                ppc_md.dma_set_mask = dma_set_mask_pSeriesLP;
+               ppc_md.dma_get_required_mask = dma_get_required_mask_pSeriesLP;
        } else {
                ppc_md.tce_build = tce_build_pSeries;
                ppc_md.tce_free  = tce_free_pSeries;
index 00cc3a0..a76b228 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/kmsg_dump.h>
+#include <linux/ctype.h>
+#include <linux/zlib.h>
 #include <asm/uaccess.h>
 #include <asm/nvram.h>
 #include <asm/rtas.h>
@@ -78,8 +80,41 @@ static struct kmsg_dumper nvram_kmsg_dumper = {
 #define NVRAM_RTAS_READ_TIMEOUT 5              /* seconds */
 static unsigned long last_unread_rtas_event;   /* timestamp */
 
-/* We preallocate oops_buf during init to avoid kmalloc during oops/panic. */
-static char *oops_buf;
+/*
+ * For capturing and compressing an oops or panic report...
+
+ * big_oops_buf[] holds the uncompressed text we're capturing.
+ *
+ * oops_buf[] holds the compressed text, preceded by a prefix.
+ * The prefix is just a u16 holding the length of the compressed* text.
+ * (*Or uncompressed, if compression fails.)  oops_buf[] gets written
+ * to NVRAM.
+ *
+ * oops_len points to the prefix.  oops_data points to the compressed text.
+ *
+ * +- oops_buf
+ * |           +- oops_data
+ * v           v
+ * +------------+-----------------------------------------------+
+ * | length    | text                                          |
+ * | (2 bytes) | (oops_data_sz bytes)                          |
+ * +------------+-----------------------------------------------+
+ * ^
+ * +- oops_len
+ *
+ * We preallocate these buffers during init to avoid kmalloc during oops/panic.
+ */
+static size_t big_oops_buf_sz;
+static char *big_oops_buf, *oops_buf;
+static u16 *oops_len;
+static char *oops_data;
+static size_t oops_data_sz;
+
+/* Compression parameters */
+#define COMPR_LEVEL 6
+#define WINDOW_BITS 12
+#define MEM_LEVEL 4
+static struct z_stream_s stream;
 
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
 {
@@ -387,11 +422,44 @@ static void __init nvram_init_oops_partition(int rtas_partition_exists)
                                                sizeof(rtas_log_partition));
        }
        oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL);
+       if (!oops_buf) {
+               pr_err("nvram: No memory for %s partition\n",
+                                               oops_log_partition.name);
+               return;
+       }
+       oops_len = (u16*) oops_buf;
+       oops_data = oops_buf + sizeof(u16);
+       oops_data_sz = oops_log_partition.size - sizeof(u16);
+
+       /*
+        * Figure compression (preceded by elimination of each line's <n>
+        * severity prefix) will reduce the oops/panic report to at most
+        * 45% of its original size.
+        */
+       big_oops_buf_sz = (oops_data_sz * 100) / 45;
+       big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
+       if (big_oops_buf) {
+               stream.workspace = kmalloc(zlib_deflate_workspacesize(
+                               WINDOW_BITS, MEM_LEVEL), GFP_KERNEL);
+               if (!stream.workspace) {
+                       pr_err("nvram: No memory for compression workspace; "
+                               "skipping compression of %s partition data\n",
+                               oops_log_partition.name);
+                       kfree(big_oops_buf);
+                       big_oops_buf = NULL;
+               }
+       } else {
+               pr_err("No memory for uncompressed %s data; "
+                       "skipping compression\n", oops_log_partition.name);
+               stream.workspace = NULL;
+       }
+
        rc = kmsg_dump_register(&nvram_kmsg_dumper);
        if (rc != 0) {
                pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
                kfree(oops_buf);
-               return;
+               kfree(big_oops_buf);
+               kfree(stream.workspace);
        }
 }
 
@@ -473,7 +541,83 @@ static int clobbering_unread_rtas_event(void)
                                                NVRAM_RTAS_READ_TIMEOUT);
 }
 
-/* our kmsg_dump callback */
+/* Squeeze out each line's <n> severity prefix. */
+static size_t elide_severities(char *buf, size_t len)
+{
+       char *in, *out, *buf_end = buf + len;
+       /* Assume a <n> at the very beginning marks the start of a line. */
+       int newline = 1;
+
+       in = out = buf;
+       while (in < buf_end) {
+               if (newline && in+3 <= buf_end &&
+                               *in == '<' && isdigit(in[1]) && in[2] == '>') {
+                       in += 3;
+                       newline = 0;
+               } else {
+                       newline = (*in == '\n');
+                       *out++ = *in++;
+               }
+       }
+       return out - buf;
+}
+
+/* Derived from logfs_compress() */
+static int nvram_compress(const void *in, void *out, size_t inlen,
+                                                       size_t outlen)
+{
+       int err, ret;
+
+       ret = -EIO;
+       err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
+                                               MEM_LEVEL, Z_DEFAULT_STRATEGY);
+       if (err != Z_OK)
+               goto error;
+
+       stream.next_in = in;
+       stream.avail_in = inlen;
+       stream.total_in = 0;
+       stream.next_out = out;
+       stream.avail_out = outlen;
+       stream.total_out = 0;
+
+       err = zlib_deflate(&stream, Z_FINISH);
+       if (err != Z_STREAM_END)
+               goto error;
+
+       err = zlib_deflateEnd(&stream);
+       if (err != Z_OK)
+               goto error;
+
+       if (stream.total_out >= stream.total_in)
+               goto error;
+
+       ret = stream.total_out;
+error:
+       return ret;
+}
+
+/* Compress the text from big_oops_buf into oops_buf. */
+static int zip_oops(size_t text_len)
+{
+       int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len,
+                                                               oops_data_sz);
+       if (zipped_len < 0) {
+               pr_err("nvram: compression failed; returned %d\n", zipped_len);
+               pr_err("nvram: logging uncompressed oops/panic report\n");
+               return -1;
+       }
+       *oops_len = (u16) zipped_len;
+       return 0;
+}
+
+/*
+ * This is our kmsg_dump callback, called after an oops or panic report
+ * has been written to the printk buffer.  We want to capture as much
+ * of the printk buffer as possible.  First, capture as much as we can
+ * that we think will compress sufficiently to fit in the lnx,oops-log
+ * partition.  If that's too much, go back and capture uncompressed text.
+ */
 static void oops_to_nvram(struct kmsg_dumper *dumper,
                enum kmsg_dump_reason reason,
                const char *old_msgs, unsigned long old_len,
@@ -482,6 +626,8 @@ static void oops_to_nvram(struct kmsg_dumper *dumper,
        static unsigned int oops_count = 0;
        static bool panicking = false;
        size_t text_len;
+       unsigned int err_type = ERR_TYPE_KERNEL_PANIC_GZ;
+       int rc = -1;
 
        switch (reason) {
        case KMSG_DUMP_RESTART:
@@ -509,8 +655,19 @@ static void oops_to_nvram(struct kmsg_dumper *dumper,
        if (clobbering_unread_rtas_event())
                return;
 
-       text_len = capture_last_msgs(old_msgs, old_len, new_msgs, new_len,
-                                       oops_buf, oops_log_partition.size);
+       if (big_oops_buf) {
+               text_len = capture_last_msgs(old_msgs, old_len,
+                       new_msgs, new_len, big_oops_buf, big_oops_buf_sz);
+               text_len = elide_severities(big_oops_buf, text_len);
+               rc = zip_oops(text_len);
+       }
+       if (rc != 0) {
+               text_len = capture_last_msgs(old_msgs, old_len,
+                               new_msgs, new_len, oops_data, oops_data_sz);
+               err_type = ERR_TYPE_KERNEL_PANIC;
+               *oops_len = (u16) text_len;
+       }
+
        (void) nvram_write_os_partition(&oops_log_partition, oops_buf,
-               (int) text_len, ERR_TYPE_KERNEL_PANIC, ++oops_count);
+               (int) (sizeof(*oops_len) + *oops_len), err_type, ++oops_count);
 }
index c3c48eb..f4fb837 100644 (file)
@@ -1,5 +1,12 @@
 config PPC_WSP
        bool
+       select PPC_A2
+       select PPC_SCOM
+       select PPC_XICS
+       select PPC_ICP_NATIVE
+       select PCI
+       select PPC_IO_WORKAROUNDS if PCI
+       select PPC_INDIRECT_PIO if PCI
        default n
 
 menu "WSP platform selection"
@@ -7,13 +14,9 @@ menu "WSP platform selection"
 
 config PPC_PSR2
        bool "PSR-2 platform"
-       select PPC_A2
        select GENERIC_TBSYNC
-       select PPC_SCOM
        select EPAPR_BOOT
        select PPC_WSP
-       select PPC_XICS
-       select PPC_ICP_NATIVE
        default y
 
 endmenu
index 095be73..a1486b4 100644 (file)
@@ -4,3 +4,5 @@ obj-y                           += setup.o ics.o
 obj-$(CONFIG_PPC_PSR2)         += psr2.o opb_pic.o
 obj-$(CONFIG_PPC_WSP)          += scom_wsp.o
 obj-$(CONFIG_SMP)              += smp.o scom_smp.o
+obj-$(CONFIG_PCI)              += wsp_pci.o
+obj-$(CONFIG_PCI_MSI)          += msi.o
\ No newline at end of file
index e53bd9e..5768743 100644 (file)
@@ -710,3 +710,51 @@ void __init wsp_init_irq(void)
        /* We need to patch our irq chip's EOI to point to the right ICP */
        wsp_irq_chip.irq_eoi = icp_ops->eoi;
 }
+
+#ifdef CONFIG_PCI_MSI
+static void wsp_ics_msi_unmask_irq(struct irq_data *d)
+{
+       wsp_chip_unmask_irq(d);
+       unmask_msi_irq(d);
+}
+
+static unsigned int wsp_ics_msi_startup(struct irq_data *d)
+{
+       wsp_ics_msi_unmask_irq(d);
+       return 0;
+}
+
+static void wsp_ics_msi_mask_irq(struct irq_data *d)
+{
+       mask_msi_irq(d);
+       wsp_chip_mask_irq(d);
+}
+
+/*
+ * we do it this way because we reassinge default EOI handling in
+ * irq_init() above
+ */
+static void wsp_ics_eoi(struct irq_data *data)
+{
+       wsp_irq_chip.irq_eoi(data);
+}
+
+static struct irq_chip wsp_ics_msi = {
+       .name = "WSP ICS MSI",
+       .irq_startup = wsp_ics_msi_startup,
+       .irq_mask = wsp_ics_msi_mask_irq,
+       .irq_unmask = wsp_ics_msi_unmask_irq,
+       .irq_eoi = wsp_ics_eoi,
+       .irq_set_affinity = wsp_chip_set_affinity
+};
+
+void wsp_ics_set_msi_chip(unsigned int irq)
+{
+       irq_set_chip(irq, &wsp_ics_msi);
+}
+
+void wsp_ics_set_std_chip(unsigned int irq)
+{
+       irq_set_chip(irq, &wsp_irq_chip);
+}
+#endif /* CONFIG_PCI_MSI */
index e34d531..07b644e 100644 (file)
@@ -17,4 +17,9 @@ extern void wsp_init_irq(void);
 extern int wsp_ics_alloc_irq(struct device_node *dn, int num);
 extern void wsp_ics_free_irq(struct device_node *dn, unsigned int irq);
 
+#ifdef CONFIG_PCI_MSI
+extern void wsp_ics_set_msi_chip(unsigned int irq);
+extern void wsp_ics_set_std_chip(unsigned int irq);
+#endif /* CONFIG_PCI_MSI */
+
 #endif /* __ICS_H */
diff --git a/arch/powerpc/platforms/wsp/msi.c b/arch/powerpc/platforms/wsp/msi.c
new file mode 100644 (file)
index 0000000..380882f
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2011 Michael Ellerman, 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/kernel.h>
+#include <linux/pci.h>
+#include <linux/msi.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include "msi.h"
+#include "ics.h"
+#include "wsp_pci.h"
+
+/* Magic addresses for 32 & 64-bit MSIs with hardcoded MVE 0 */
+#define MSI_ADDR_32            0xFFFF0000ul
+#define MSI_ADDR_64            0x1000000000000000ul
+
+int wsp_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+       struct pci_controller *phb;
+       struct msi_desc *entry;
+       struct msi_msg msg;
+       unsigned int virq;
+       int hwirq;
+
+       phb = pci_bus_to_host(dev->bus);
+       if (!phb)
+               return -ENOENT;
+
+       entry = list_first_entry(&dev->msi_list, struct msi_desc, list);
+       if (entry->msi_attrib.is_64) {
+               msg.address_lo = 0;
+               msg.address_hi = MSI_ADDR_64 >> 32;
+       } else {
+               msg.address_lo = MSI_ADDR_32;
+               msg.address_hi = 0;
+       }
+
+       list_for_each_entry(entry, &dev->msi_list, list) {
+               hwirq = wsp_ics_alloc_irq(phb->dn, 1);
+               if (hwirq < 0) {
+                       dev_warn(&dev->dev, "wsp_msi: hwirq alloc failed!\n");
+                       return hwirq;
+               }
+
+               virq = irq_create_mapping(NULL, hwirq);
+               if (virq == NO_IRQ) {
+                       dev_warn(&dev->dev, "wsp_msi: virq alloc failed!\n");
+                       return -1;
+               }
+
+               dev_dbg(&dev->dev, "wsp_msi: allocated irq %#x/%#x\n",
+                       hwirq, virq);
+
+               wsp_ics_set_msi_chip(virq);
+               irq_set_msi_desc(virq, entry);
+               msg.data = hwirq & XIVE_ADDR_MASK;
+               write_msi_msg(virq, &msg);
+       }
+
+       return 0;
+}
+
+void wsp_teardown_msi_irqs(struct pci_dev *dev)
+{
+       struct pci_controller *phb;
+       struct msi_desc *entry;
+       int hwirq;
+
+       phb = pci_bus_to_host(dev->bus);
+
+       dev_dbg(&dev->dev, "wsp_msi: tearing down msi irqs\n");
+
+       list_for_each_entry(entry, &dev->msi_list, list) {
+               if (entry->irq == NO_IRQ)
+                       continue;
+
+               irq_set_msi_desc(entry->irq, NULL);
+               wsp_ics_set_std_chip(entry->irq);
+
+               hwirq = virq_to_hw(entry->irq);
+               /* In this order to avoid racing with irq_create_mapping() */
+               irq_dispose_mapping(entry->irq);
+               wsp_ics_free_irq(phb->dn, hwirq);
+       }
+}
+
+void wsp_setup_phb_msi(struct pci_controller *phb)
+{
+       /* Create a single MVE at offset 0 that matches everything */
+       out_be64(phb->cfg_data + PCIE_REG_IODA_ADDR, PCIE_REG_IODA_AD_TBL_MVT);
+       out_be64(phb->cfg_data + PCIE_REG_IODA_DATA0, 1ull << 63);
+
+       ppc_md.setup_msi_irqs = wsp_setup_msi_irqs;
+       ppc_md.teardown_msi_irqs = wsp_teardown_msi_irqs;
+}
diff --git a/arch/powerpc/platforms/wsp/msi.h b/arch/powerpc/platforms/wsp/msi.h
new file mode 100644 (file)
index 0000000..0ab27b7
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2011 Michael Ellerman, 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.
+ */
+
+#ifndef __WSP_MSI_H
+#define __WSP_MSI_H
+
+#ifdef CONFIG_PCI_MSI
+extern void wsp_setup_phb_msi(struct pci_controller *phb);
+#else
+static inline void wsp_setup_phb_msi(struct pci_controller *phb) { }
+#endif
+
+#endif /* __WSP_MSI_H */
index 40f2891..166f2e4 100644 (file)
@@ -63,6 +63,10 @@ static void __init psr2_setup_arch(void)
 #ifdef CONFIG_SMP
        a2_setup_smp();
 #endif
+#ifdef CONFIG_PCI
+       wsp_setup_pci();
+#endif
+
 }
 
 static int __init psr2_probe(void)
index 7c3e087..3347981 100644 (file)
@@ -3,6 +3,9 @@
 
 #include <asm/wsp.h>
 
+/* Devtree compatible strings for major devices */
+#define PCIE_COMPATIBLE     "ibm,wsp-pciex"
+
 extern void wsp_setup_pci(void);
 extern void scom_init_wsp(void);
 
diff --git a/arch/powerpc/platforms/wsp/wsp_pci.c b/arch/powerpc/platforms/wsp/wsp_pci.c
new file mode 100644 (file)
index 0000000..e0262cd
--- /dev/null
@@ -0,0 +1,1133 @@
+/*
+ * Copyright 2010 Ben Herrenschmidt, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; 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/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/debugfs.h>
+
+#include <asm/sections.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/iommu.h>
+#include <asm/io-workarounds.h>
+
+#include "wsp.h"
+#include "wsp_pci.h"
+#include "msi.h"
+
+
+/* Max number of TVTs for one table. Only 32-bit tables can use
+ * multiple TVTs and so the max currently supported is thus 8
+ * since only 2G of DMA space is supported
+ */
+#define MAX_TABLE_TVT_COUNT            8
+
+struct wsp_dma_table {
+       struct list_head        link;
+       struct iommu_table      table;
+       struct wsp_phb  *phb;
+       struct page             *tces[MAX_TABLE_TVT_COUNT];
+};
+
+/* We support DMA regions from 0...2G in 32bit space (no support for
+ * 64-bit DMA just yet). Each device gets a separate TCE table (TVT
+ * entry) with validation enabled (though not supported by SimiCS
+ * just yet).
+ *
+ * To simplify things, we divide this 2G space into N regions based
+ * on the constant below which could be turned into a tunable eventually
+ *
+ * We then assign dynamically those regions to devices as they show up.
+ *
+ * We use a bitmap as an allocator for these.
+ *
+ * Tables are allocated/created dynamically as devices are discovered,
+ * multiple TVT entries are used if needed
+ *
+ * When 64-bit DMA support is added we should simply use a separate set
+ * of larger regions (the HW supports 64 TVT entries). We can
+ * additionally create a bypass region in 64-bit space for performances
+ * though that would have a cost in term of security.
+ *
+ * If you set NUM_DMA32_REGIONS to 1, then a single table is shared
+ * for all devices and bus/dev/fn validation is disabled
+ *
+ * Note that a DMA32 region cannot be smaller than 256M so the max
+ * supported here for now is 8. We don't yet support sharing regions
+ * between multiple devices so the max number of devices supported
+ * is MAX_TABLE_TVT_COUNT.
+ */
+#define NUM_DMA32_REGIONS      1
+
+struct wsp_phb {
+       struct pci_controller   *hose;
+
+       /* Lock controlling access to the list of dma tables.
+        * It does -not- protect against dma_* operations on
+        * those tables, those should be stopped before an entry
+        * is removed from the list.
+        *
+        * The lock is also used for error handling operations
+        */
+       spinlock_t              lock;
+       struct list_head        dma_tables;
+       unsigned long           dma32_map;
+       unsigned long           dma32_base;
+       unsigned int            dma32_num_regions;
+       unsigned long           dma32_region_size;
+
+       /* Debugfs stuff */
+       struct dentry           *ddir;
+
+       struct list_head        all;
+};
+static LIST_HEAD(wsp_phbs);
+
+//#define cfg_debug(fmt...)    pr_debug(fmt)
+#define cfg_debug(fmt...)
+
+
+static int wsp_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
+                                 int offset, int len, u32 *val)
+{
+       struct pci_controller *hose;
+       int suboff;
+       u64 addr;
+
+       hose = pci_bus_to_host(bus);
+       if (hose == NULL)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       if (offset >= 0x1000)
+               return  PCIBIOS_BAD_REGISTER_NUMBER;
+       addr = PCIE_REG_CA_ENABLE |
+               ((u64)bus->number) << PCIE_REG_CA_BUS_SHIFT |
+               ((u64)devfn) << PCIE_REG_CA_FUNC_SHIFT |
+               ((u64)offset & ~3) << PCIE_REG_CA_REG_SHIFT;
+       suboff = offset & 3;
+
+       /*
+        * Note: the caller has already checked that offset is
+        * suitably aligned and that len is 1, 2 or 4.
+        */
+
+       switch (len) {
+       case 1:
+               addr |= (0x8ul >> suboff) << PCIE_REG_CA_BE_SHIFT;
+               out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+               *val = (in_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA)
+                       >> (suboff << 3)) & 0xff;
+               cfg_debug("read 1 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%02x\n",
+                         bus->number, devfn >> 3, devfn & 7,
+                         offset, suboff, addr, *val);
+               break;
+       case 2:
+               addr |= (0xcul >> suboff) << PCIE_REG_CA_BE_SHIFT;
+               out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+               *val = (in_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA)
+                       >> (suboff << 3)) & 0xffff;
+               cfg_debug("read 2 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%04x\n",
+                         bus->number, devfn >> 3, devfn & 7,
+                         offset, suboff, addr, *val);
+               break;
+       default:
+               addr |= 0xful << PCIE_REG_CA_BE_SHIFT;
+               out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+               *val = in_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA);
+               cfg_debug("read 4 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%08x\n",
+                         bus->number, devfn >> 3, devfn & 7,
+                         offset, suboff, addr, *val);
+               break;
+       }
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int wsp_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
+                                  int offset, int len, u32 val)
+{
+       struct pci_controller *hose;
+       int suboff;
+       u64 addr;
+
+       hose = pci_bus_to_host(bus);
+       if (hose == NULL)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       if (offset >= 0x1000)
+               return  PCIBIOS_BAD_REGISTER_NUMBER;
+       addr = PCIE_REG_CA_ENABLE |
+               ((u64)bus->number) << PCIE_REG_CA_BUS_SHIFT |
+               ((u64)devfn) << PCIE_REG_CA_FUNC_SHIFT |
+               ((u64)offset & ~3) << PCIE_REG_CA_REG_SHIFT;
+       suboff = offset & 3;
+
+       /*
+        * Note: the caller has already checked that offset is
+        * suitably aligned and that len is 1, 2 or 4.
+        */
+       switch (len) {
+       case 1:
+               addr |= (0x8ul >> suboff) << PCIE_REG_CA_BE_SHIFT;
+               val <<= suboff << 3;
+               out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+               out_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA, val);
+               cfg_debug("write 1 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%02x\n",
+                         bus->number, devfn >> 3, devfn & 7,
+                         offset, suboff, addr, val);
+               break;
+       case 2:
+               addr |= (0xcul >> suboff) << PCIE_REG_CA_BE_SHIFT;
+               val <<= suboff << 3;
+               out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+               out_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA, val);
+               cfg_debug("write 2 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%04x\n",
+                         bus->number, devfn >> 3, devfn & 7,
+                         offset, suboff, addr, val);
+               break;
+       default:
+               addr |= 0xful << PCIE_REG_CA_BE_SHIFT;
+               out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+               out_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA, val);
+               cfg_debug("write 4 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%08x\n",
+                         bus->number, devfn >> 3, devfn & 7,
+                         offset, suboff, addr, val);
+               break;
+       }
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops wsp_pcie_pci_ops =
+{
+       .read = wsp_pcie_read_config,
+       .write = wsp_pcie_write_config,
+};
+
+#define TCE_SHIFT              12
+#define TCE_PAGE_SIZE          (1 << TCE_SHIFT)
+#define TCE_PCI_WRITE          0x2              /* write from PCI allowed */
+#define TCE_PCI_READ           0x1              /* read from PCI allowed */
+#define TCE_RPN_MASK           0x3fffffffffful  /* 42-bit RPN (4K pages) */
+#define TCE_RPN_SHIFT          12
+
+//#define dma_debug(fmt...)    pr_debug(fmt)
+#define dma_debug(fmt...)
+
+static int tce_build_wsp(struct iommu_table *tbl, long index, long npages,
+                          unsigned long uaddr, enum dma_data_direction direction,
+                          struct dma_attrs *attrs)
+{
+       struct wsp_dma_table *ptbl = container_of(tbl,
+                                                   struct wsp_dma_table,
+                                                   table);
+       u64 proto_tce;
+       u64 *tcep;
+       u64 rpn;
+
+       proto_tce = TCE_PCI_READ;
+#ifdef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS
+       proto_tce |= TCE_PCI_WRITE;
+#else
+       if (direction != DMA_TO_DEVICE)
+               proto_tce |= TCE_PCI_WRITE;
+#endif
+
+       /* XXX Make this faster by factoring out the page address for
+        * within a TCE table
+        */
+       while (npages--) {
+               /* We don't use it->base as the table can be scattered */
+               tcep = (u64 *)page_address(ptbl->tces[index >> 16]);
+               tcep += (index & 0xffff);
+
+               /* can't move this out since we might cross LMB boundary */
+               rpn = __pa(uaddr) >> TCE_SHIFT;
+               *tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
+
+               dma_debug("[DMA] TCE %p set to 0x%016llx (dma addr: 0x%lx)\n",
+                         tcep, *tcep, (tbl->it_offset + index) << IOMMU_PAGE_SHIFT);
+
+               uaddr += TCE_PAGE_SIZE;
+               index++;
+       }
+       return 0;
+}
+
+static void tce_free_wsp(struct iommu_table *tbl, long index, long npages)
+{
+       struct wsp_dma_table *ptbl = container_of(tbl,
+                                                   struct wsp_dma_table,
+                                                   table);
+#ifndef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS
+       struct pci_controller *hose = ptbl->phb->hose;
+#endif
+       u64 *tcep;
+
+       /* XXX Make this faster by factoring out the page address for
+        * within a TCE table. Also use line-kill option to kill multiple
+        * TCEs at once
+        */
+       while (npages--) {
+               /* We don't use it->base as the table can be scattered */
+               tcep = (u64 *)page_address(ptbl->tces[index >> 16]);
+               tcep += (index & 0xffff);
+               dma_debug("[DMA] TCE %p cleared\n", tcep);
+               *tcep = 0;
+#ifndef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS
+               /* Don't write there since it would pollute other MMIO accesses */
+               out_be64(hose->cfg_data + PCIE_REG_TCE_KILL,
+                        PCIE_REG_TCEKILL_SINGLE | PCIE_REG_TCEKILL_PS_4K |
+                        (__pa(tcep) & PCIE_REG_TCEKILL_ADDR_MASK));
+#endif
+               index++;
+       }
+}
+
+static struct wsp_dma_table *wsp_pci_create_dma32_table(struct wsp_phb *phb,
+                                                           unsigned int region,
+                                                           struct pci_dev *validate)
+{
+       struct pci_controller *hose = phb->hose;
+       unsigned long size = phb->dma32_region_size;
+       unsigned long addr = phb->dma32_region_size * region + phb->dma32_base;
+       struct wsp_dma_table *tbl;
+       int tvts_per_table, i, tvt, nid;
+       unsigned long flags;
+
+       nid = of_node_to_nid(phb->hose->dn);
+
+       /* Calculate how many TVTs are needed */
+       tvts_per_table = size / 0x10000000;
+       if (tvts_per_table == 0)
+               tvts_per_table = 1;
+
+       /* Calculate the base TVT index. We know all tables have the same
+        * size so we just do a simple multiply here
+        */
+       tvt = region * tvts_per_table;
+
+       pr_debug("         Region : %d\n", region);
+       pr_debug("      DMA range : 0x%08lx..0x%08lx\n", addr, addr + size - 1);
+       pr_debug(" Number of TVTs : %d\n", tvts_per_table);
+       pr_debug("       Base TVT : %d\n", tvt);
+       pr_debug("         Node   : %d\n", nid);
+
+       tbl = kzalloc_node(sizeof(struct wsp_dma_table), GFP_KERNEL, nid);
+       if (!tbl)
+               return ERR_PTR(-ENOMEM);
+       tbl->phb = phb;
+
+       /* Create as many TVTs as needed, each represents 256M at most */
+       for (i = 0; i < tvts_per_table; i++) {
+               u64 tvt_data1, tvt_data0;
+
+               /* Allocate table. We use a 4K TCE size for now always so
+                * one table is always 8 * (258M / 4K) == 512K
+                */
+               tbl->tces[i] = alloc_pages_node(nid, GFP_KERNEL, get_order(0x80000));
+               if (tbl->tces[i] == NULL)
+                       goto fail;
+               memset(page_address(tbl->tces[i]), 0, 0x80000);
+
+               pr_debug(" TCE table %d at : %p\n", i, page_address(tbl->tces[i]));
+
+               /* Table size. We currently set it to be the whole 256M region */
+               tvt_data0 = 2ull << IODA_TVT0_TCE_TABLE_SIZE_SHIFT;
+               /* IO page size set to 4K */
+               tvt_data1 = 1ull << IODA_TVT1_IO_PAGE_SIZE_SHIFT;
+               /* Shift in the address */
+               tvt_data0 |= __pa(page_address(tbl->tces[i])) << IODA_TVT0_TTA_SHIFT;
+
+               /* Validation stuff. We only validate fully bus/dev/fn for now
+                * one day maybe we can group devices but that isn't the case
+                * at the moment
+                */
+               if (validate) {
+                       tvt_data0 |= IODA_TVT0_BUSNUM_VALID_MASK;
+                       tvt_data0 |= validate->bus->number;
+                       tvt_data1 |= IODA_TVT1_DEVNUM_VALID;
+                       tvt_data1 |= ((u64)PCI_SLOT(validate->devfn))
+                               << IODA_TVT1_DEVNUM_VALUE_SHIFT;
+                       tvt_data1 |= IODA_TVT1_FUNCNUM_VALID;
+                       tvt_data1 |= ((u64)PCI_FUNC(validate->devfn))
+                               << IODA_TVT1_FUNCNUM_VALUE_SHIFT;
+               }
+
+               /* XX PE number is always 0 for now */
+
+               /* Program the values using the PHB lock */
+               spin_lock_irqsave(&phb->lock, flags);
+               out_be64(hose->cfg_data + PCIE_REG_IODA_ADDR,
+                        (tvt + i) | PCIE_REG_IODA_AD_TBL_TVT);
+               out_be64(hose->cfg_data + PCIE_REG_IODA_DATA1, tvt_data1);
+               out_be64(hose->cfg_data + PCIE_REG_IODA_DATA0, tvt_data0);
+               spin_unlock_irqrestore(&phb->lock, flags);
+       }
+
+       /* Init bits and pieces */
+       tbl->table.it_blocksize = 16;
+       tbl->table.it_offset = addr >> IOMMU_PAGE_SHIFT;
+       tbl->table.it_size = size >> IOMMU_PAGE_SHIFT;
+
+       /*
+        * It's already blank but we clear it anyway.
+        * Consider an aditiona interface that makes cleaing optional
+        */
+       iommu_init_table(&tbl->table, nid);
+
+       list_add(&tbl->link, &phb->dma_tables);
+       return tbl;
+
+ fail:
+       pr_debug("  Failed to allocate a 256M TCE table !\n");
+       for (i = 0; i < tvts_per_table; i++)
+               if (tbl->tces[i])
+                       __free_pages(tbl->tces[i], get_order(0x80000));
+       kfree(tbl);
+       return ERR_PTR(-ENOMEM);
+}
+
+static void __devinit wsp_pci_dma_dev_setup(struct pci_dev *pdev)
+{
+       struct dev_archdata *archdata = &pdev->dev.archdata;
+       struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+       struct wsp_phb *phb = hose->private_data;
+       struct wsp_dma_table *table = NULL;
+       unsigned long flags;
+       int i;
+
+       /* Don't assign an iommu table to a bridge */
+       if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
+               return;
+
+       pr_debug("%s: Setting up DMA...\n", pci_name(pdev));
+
+       spin_lock_irqsave(&phb->lock, flags);
+
+       /* If only one region, check if it already exist */
+       if (phb->dma32_num_regions == 1) {
+               spin_unlock_irqrestore(&phb->lock, flags);
+               if (list_empty(&phb->dma_tables))
+                       table = wsp_pci_create_dma32_table(phb, 0, NULL);
+               else
+                       table = list_first_entry(&phb->dma_tables,
+                                                struct wsp_dma_table,
+                                                link);
+       } else {
+               /* else find a free region */
+               for (i = 0; i < phb->dma32_num_regions && !table; i++) {
+                       if (__test_and_set_bit(i, &phb->dma32_map))
+                               continue;
+                       spin_unlock_irqrestore(&phb->lock, flags);
+                       table = wsp_pci_create_dma32_table(phb, i, pdev);
+               }
+       }
+
+       /* Check if we got an error */
+       if (IS_ERR(table)) {
+               pr_err("%s: Failed to create DMA table, err %ld !\n",
+                      pci_name(pdev), PTR_ERR(table));
+               return;
+       }
+
+       /* Or a valid table */
+       if (table) {
+               pr_info("%s: Setup iommu: 32-bit DMA region 0x%08lx..0x%08lx\n",
+                       pci_name(pdev),
+                       table->table.it_offset << IOMMU_PAGE_SHIFT,
+                       (table->table.it_offset << IOMMU_PAGE_SHIFT)
+                       + phb->dma32_region_size - 1);
+               archdata->dma_data.iommu_table_base = &table->table;
+               return;
+       }
+
+       /* Or no room */
+       spin_unlock_irqrestore(&phb->lock, flags);
+       pr_err("%s: Out of DMA space !\n", pci_name(pdev));
+}
+
+static void __init wsp_pcie_configure_hw(struct pci_controller *hose)
+{
+       u64 val;
+       int i;
+
+#define DUMP_REG(x) \
+       pr_debug("%-30s : 0x%016llx\n", #x, in_be64(hose->cfg_data + x))
+
+#ifdef CONFIG_WSP_DD1_WORKAROUND_BAD_PCIE_CLASS
+       /* WSP DD1 has a bogus class code by default in the PCI-E
+        * root complex's built-in P2P bridge */
+       val = in_be64(hose->cfg_data + PCIE_REG_SYS_CFG1);
+       pr_debug("PCI-E SYS_CFG1 : 0x%llx\n", val);
+       out_be64(hose->cfg_data + PCIE_REG_SYS_CFG1,
+                (val & ~PCIE_REG_SYS_CFG1_CLASS_CODE) | (PCI_CLASS_BRIDGE_PCI << 8));
+       pr_debug("PCI-E SYS_CFG1 : 0x%llx\n", in_be64(hose->cfg_data + PCIE_REG_SYS_CFG1));
+#endif /* CONFIG_WSP_DD1_WORKAROUND_BAD_PCIE_CLASS */
+
+#ifdef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS
+       /* XXX Disable TCE caching, it doesn't work on DD1 */
+       out_be64(hose->cfg_data + 0xe50,
+                in_be64(hose->cfg_data + 0xe50) | (3ull << 62));
+       printk("PCI-E DEBUG CONTROL 5 = 0x%llx\n", in_be64(hose->cfg_data + 0xe50));
+#endif
+
+       /* Configure M32A and IO. IO is hard wired to be 1M for now */
+       out_be64(hose->cfg_data + PCIE_REG_IO_BASE_ADDR, hose->io_base_phys);
+       out_be64(hose->cfg_data + PCIE_REG_IO_BASE_MASK,
+                (~(hose->io_resource.end - hose->io_resource.start)) &
+                0x3fffffff000ul);
+       out_be64(hose->cfg_data + PCIE_REG_IO_START_ADDR, 0 | 1);
+
+       out_be64(hose->cfg_data + PCIE_REG_M32A_BASE_ADDR,
+                hose->mem_resources[0].start);
+       printk("Want to write to M32A_BASE_MASK : 0x%llx\n",
+                (~(hose->mem_resources[0].end -
+                   hose->mem_resources[0].start)) & 0x3ffffff0000ul);
+       out_be64(hose->cfg_data + PCIE_REG_M32A_BASE_MASK,
+                (~(hose->mem_resources[0].end -
+                   hose->mem_resources[0].start)) & 0x3ffffff0000ul);
+       out_be64(hose->cfg_data + PCIE_REG_M32A_START_ADDR,
+                (hose->mem_resources[0].start - hose->pci_mem_offset) | 1);
+
+       /* Clear all TVT entries
+        *
+        * XX Might get TVT count from device-tree
+        */
+       for (i = 0; i < IODA_TVT_COUNT; i++) {
+               out_be64(hose->cfg_data + PCIE_REG_IODA_ADDR,
+                        PCIE_REG_IODA_AD_TBL_TVT | i);
+               out_be64(hose->cfg_data + PCIE_REG_IODA_DATA1, 0);
+               out_be64(hose->cfg_data + PCIE_REG_IODA_DATA0, 0);
+       }
+
+       /* Kill the TCE cache */
+       out_be64(hose->cfg_data + PCIE_REG_PHB_CONFIG,
+                in_be64(hose->cfg_data + PCIE_REG_PHB_CONFIG) |
+                PCIE_REG_PHBC_64B_TCE_EN);
+
+       /* Enable 32 & 64-bit MSIs, IO space and M32A */
+       val = PCIE_REG_PHBC_32BIT_MSI_EN |
+             PCIE_REG_PHBC_IO_EN |
+             PCIE_REG_PHBC_64BIT_MSI_EN |
+             PCIE_REG_PHBC_M32A_EN;
+       if (iommu_is_off)
+               val |= PCIE_REG_PHBC_DMA_XLATE_BYPASS;
+       pr_debug("Will write config: 0x%llx\n", val);
+       out_be64(hose->cfg_data + PCIE_REG_PHB_CONFIG, val);
+
+       /* Enable error reporting */
+       out_be64(hose->cfg_data + 0xe00,
+                in_be64(hose->cfg_data + 0xe00) | 0x0008000000000000ull);
+
+       /* Mask an error that's generated when doing config space probe
+        *
+        * XXX Maybe we should only mask it around config space cycles... that or
+        * ignore it when we know we had a config space cycle recently ?
+        */
+       out_be64(hose->cfg_data + PCIE_REG_DMA_ERR_STATUS_MASK, 0x8000000000000000ull);
+       out_be64(hose->cfg_data + PCIE_REG_DMA_ERR1_STATUS_MASK, 0x8000000000000000ull);
+
+       /* Enable UTL errors, for now, all of them got to UTL irq 1
+        *
+        * We similarily mask one UTL error caused apparently during normal
+        * probing. We also mask the link up error
+        */
+       out_be64(hose->cfg_data + PCIE_UTL_SYS_BUS_AGENT_ERR_SEV, 0);
+       out_be64(hose->cfg_data + PCIE_UTL_RC_ERR_SEVERITY, 0);
+       out_be64(hose->cfg_data + PCIE_UTL_PCIE_PORT_ERROR_SEV, 0);
+       out_be64(hose->cfg_data + PCIE_UTL_SYS_BUS_AGENT_IRQ_EN, 0xffffffff00000000ull);
+       out_be64(hose->cfg_data + PCIE_UTL_PCIE_PORT_IRQ_EN, 0xff5fffff00000000ull);
+       out_be64(hose->cfg_data + PCIE_UTL_EP_ERR_IRQ_EN, 0xffffffff00000000ull);
+
+       DUMP_REG(PCIE_REG_IO_BASE_ADDR);
+       DUMP_REG(PCIE_REG_IO_BASE_MASK);
+       DUMP_REG(PCIE_REG_IO_START_ADDR);
+       DUMP_REG(PCIE_REG_M32A_BASE_ADDR);
+       DUMP_REG(PCIE_REG_M32A_BASE_MASK);
+       DUMP_REG(PCIE_REG_M32A_START_ADDR);
+       DUMP_REG(PCIE_REG_M32B_BASE_ADDR);
+       DUMP_REG(PCIE_REG_M32B_BASE_MASK);
+       DUMP_REG(PCIE_REG_M32B_START_ADDR);
+       DUMP_REG(PCIE_REG_M64_BASE_ADDR);
+       DUMP_REG(PCIE_REG_M64_BASE_MASK);
+       DUMP_REG(PCIE_REG_M64_START_ADDR);
+       DUMP_REG(PCIE_REG_PHB_CONFIG);
+}
+
+static void wsp_pci_wait_io_idle(struct wsp_phb *phb, unsigned long port)
+{
+       u64 val;
+       int i;
+
+       for (i = 0; i < 10000; i++) {
+               val = in_be64(phb->hose->cfg_data + 0xe08);
+               if ((val & 0x1900000000000000ull) == 0x0100000000000000ull)
+                       return;
+               udelay(1);
+       }
+       pr_warning("PCI IO timeout on domain %d port 0x%lx\n",
+                  phb->hose->global_number, port);
+}
+
+#define DEF_PCI_AC_RET_pio(name, ret, at, al, aa)              \
+static ret wsp_pci_##name at                                   \
+{                                                              \
+       struct iowa_bus *bus;                                   \
+       struct wsp_phb *phb;                                    \
+       unsigned long flags;                                    \
+       ret rval;                                               \
+       bus = iowa_pio_find_bus(aa);                            \
+       WARN_ON(!bus);                                          \
+       phb = bus->private;                                     \
+       spin_lock_irqsave(&phb->lock, flags);                   \
+       wsp_pci_wait_io_idle(phb, aa);                          \
+       rval = __do_##name al;                                  \
+       spin_unlock_irqrestore(&phb->lock, flags);              \
+       return rval;                                            \
+}
+
+#define DEF_PCI_AC_NORET_pio(name, at, al, aa)                 \
+static void wsp_pci_##name at                                  \
+{                                                              \
+       struct iowa_bus *bus;                                   \
+       struct wsp_phb *phb;                                    \
+       unsigned long flags;                                    \
+       bus = iowa_pio_find_bus(aa);                            \
+       WARN_ON(!bus);                                          \
+       phb = bus->private;                                     \
+       spin_lock_irqsave(&phb->lock, flags);                   \
+       wsp_pci_wait_io_idle(phb, aa);                          \
+       __do_##name al;                                         \
+       spin_unlock_irqrestore(&phb->lock, flags);              \
+}
+
+#define DEF_PCI_AC_RET_mem(name, ret, at, al, aa)
+#define DEF_PCI_AC_NORET_mem(name, at, al, aa)
+
+#define DEF_PCI_AC_RET(name, ret, at, al, space, aa)           \
+       DEF_PCI_AC_RET_##space(name, ret, at, al, aa)
+
+#define DEF_PCI_AC_NORET(name, at, al, space, aa)              \
+       DEF_PCI_AC_NORET_##space(name, at, al, aa)              \
+
+
+#include <asm/io-defs.h>
+
+#undef DEF_PCI_AC_RET
+#undef DEF_PCI_AC_NORET
+
+static struct ppc_pci_io wsp_pci_iops = {
+       .inb = wsp_pci_inb,
+       .inw = wsp_pci_inw,
+       .inl = wsp_pci_inl,
+       .outb = wsp_pci_outb,
+       .outw = wsp_pci_outw,
+       .outl = wsp_pci_outl,
+       .insb = wsp_pci_insb,
+       .insw = wsp_pci_insw,
+       .insl = wsp_pci_insl,
+       .outsb = wsp_pci_outsb,
+       .outsw = wsp_pci_outsw,
+       .outsl = wsp_pci_outsl,
+};
+
+static int __init wsp_setup_one_phb(struct device_node *np)
+{
+       struct pci_controller *hose;
+       struct wsp_phb *phb;
+
+       pr_info("PCI: Setting up PCIe host bridge 0x%s\n", np->full_name);
+
+       phb = zalloc_maybe_bootmem(sizeof(struct wsp_phb), GFP_KERNEL);
+       if (!phb)
+               return -ENOMEM;
+       hose = pcibios_alloc_controller(np);
+       if (!hose) {
+               /* Can't really free the phb */
+               return -ENOMEM;
+       }
+       hose->private_data = phb;
+       phb->hose = hose;
+
+       INIT_LIST_HEAD(&phb->dma_tables);
+       spin_lock_init(&phb->lock);
+
+       /* XXX Use bus-range property ? */
+       hose->first_busno = 0;
+       hose->last_busno = 0xff;
+
+       /* We use cfg_data as the address for the whole bridge MMIO space
+        */
+       hose->cfg_data = of_iomap(hose->dn, 0);
+
+       pr_debug("PCIe registers mapped at 0x%p\n", hose->cfg_data);
+
+       /* Get the ranges of the device-tree */
+       pci_process_bridge_OF_ranges(hose, np, 0);
+
+       /* XXX Force re-assigning of everything for now */
+       pci_add_flags(PCI_REASSIGN_ALL_BUS | PCI_REASSIGN_ALL_RSRC |
+                     PCI_ENABLE_PROC_DOMAINS);
+       pci_probe_only = 0;
+
+       /* Calculate how the TCE space is divided */
+       phb->dma32_base         = 0;
+       phb->dma32_num_regions  = NUM_DMA32_REGIONS;
+       if (phb->dma32_num_regions > MAX_TABLE_TVT_COUNT) {
+               pr_warning("IOMMU: Clamped to %d DMA32 regions\n",
+                          MAX_TABLE_TVT_COUNT);
+               phb->dma32_num_regions = MAX_TABLE_TVT_COUNT;
+       }
+       phb->dma32_region_size  = 0x80000000 / phb->dma32_num_regions;
+
+       BUG_ON(!is_power_of_2(phb->dma32_region_size));
+
+       /* Setup config ops */
+       hose->ops = &wsp_pcie_pci_ops;
+
+       /* Configure the HW */
+       wsp_pcie_configure_hw(hose);
+
+       /* Instanciate IO workarounds */
+       iowa_register_bus(hose, &wsp_pci_iops, NULL, phb);
+#ifdef CONFIG_PCI_MSI
+       wsp_setup_phb_msi(hose);
+#endif
+
+       /* Add to global list */
+       list_add(&phb->all, &wsp_phbs);
+
+       return 0;
+}
+
+void __init wsp_setup_pci(void)
+{
+       struct device_node *np;
+       int rc;
+
+       /* Find host bridges */
+       for_each_compatible_node(np, "pciex", PCIE_COMPATIBLE) {
+               rc = wsp_setup_one_phb(np);
+               if (rc)
+                       pr_err("Failed to setup PCIe bridge %s, rc=%d\n",
+                              np->full_name, rc);
+       }
+
+       /* Establish device-tree linkage */
+       pci_devs_phb_init();
+
+       /* Set DMA ops to use TCEs */
+       if (iommu_is_off) {
+               pr_info("PCI-E: Disabled TCEs, using direct DMA\n");
+               set_pci_dma_ops(&dma_direct_ops);
+       } else {
+               ppc_md.pci_dma_dev_setup = wsp_pci_dma_dev_setup;
+               ppc_md.tce_build = tce_build_wsp;
+               ppc_md.tce_free = tce_free_wsp;
+               set_pci_dma_ops(&dma_iommu_ops);
+       }
+}
+
+#define err_debug(fmt...)      pr_debug(fmt)
+//#define err_debug(fmt...)
+
+static int __init wsp_pci_get_err_irq_no_dt(struct device_node *np)
+{
+       const u32 *prop;
+       int hw_irq;
+
+       /* Ok, no interrupts property, let's try to find our child P2P */
+       np = of_get_next_child(np, NULL);
+       if (np == NULL)
+               return 0;
+
+       /* Grab it's interrupt map */
+       prop = of_get_property(np, "interrupt-map", NULL);
+       if (prop == NULL)
+               return 0;
+
+       /* Grab one of the interrupts in there, keep the low 4 bits */
+       hw_irq = prop[5] & 0xf;
+
+       /* 0..4 for PHB 0 and 5..9 for PHB 1 */
+       if (hw_irq < 5)
+               hw_irq = 4;
+       else
+               hw_irq = 9;
+       hw_irq |= prop[5] & ~0xf;
+
+       err_debug("PCI: Using 0x%x as error IRQ for %s\n",
+                 hw_irq, np->parent->full_name);
+       return irq_create_mapping(NULL, hw_irq);
+}
+
+static const struct {
+       u32 offset;
+       const char *name;
+} wsp_pci_regs[] = {
+#define DREG(x) { PCIE_REG_##x, #x }
+#define DUTL(x) { PCIE_UTL_##x, "UTL_" #x }
+       /* Architected registers except CONFIG_ and IODA
+         * to avoid side effects
+        */
+       DREG(DMA_CHAN_STATUS),
+       DREG(CPU_LOADSTORE_STATUS),
+       DREG(LOCK0),
+       DREG(LOCK1),
+       DREG(PHB_CONFIG),
+       DREG(IO_BASE_ADDR),
+       DREG(IO_BASE_MASK),
+       DREG(IO_START_ADDR),
+       DREG(M32A_BASE_ADDR),
+       DREG(M32A_BASE_MASK),
+       DREG(M32A_START_ADDR),
+       DREG(M32B_BASE_ADDR),
+       DREG(M32B_BASE_MASK),
+       DREG(M32B_START_ADDR),
+       DREG(M64_BASE_ADDR),
+       DREG(M64_BASE_MASK),
+       DREG(M64_START_ADDR),
+       DREG(TCE_KILL),
+       DREG(LOCK2),
+       DREG(PHB_GEN_CAP),
+       DREG(PHB_TCE_CAP),
+       DREG(PHB_IRQ_CAP),
+       DREG(PHB_EEH_CAP),
+       DREG(PAPR_ERR_INJ_CONTROL),
+       DREG(PAPR_ERR_INJ_ADDR),
+       DREG(PAPR_ERR_INJ_MASK),
+
+       /* UTL core regs */
+       DUTL(SYS_BUS_CONTROL),
+       DUTL(STATUS),
+       DUTL(SYS_BUS_AGENT_STATUS),
+       DUTL(SYS_BUS_AGENT_ERR_SEV),
+       DUTL(SYS_BUS_AGENT_IRQ_EN),
+       DUTL(SYS_BUS_BURST_SZ_CONF),
+       DUTL(REVISION_ID),
+       DUTL(OUT_POST_HDR_BUF_ALLOC),
+       DUTL(OUT_POST_DAT_BUF_ALLOC),
+       DUTL(IN_POST_HDR_BUF_ALLOC),
+       DUTL(IN_POST_DAT_BUF_ALLOC),
+       DUTL(OUT_NP_BUF_ALLOC),
+       DUTL(IN_NP_BUF_ALLOC),
+       DUTL(PCIE_TAGS_ALLOC),
+       DUTL(GBIF_READ_TAGS_ALLOC),
+
+       DUTL(PCIE_PORT_CONTROL),
+       DUTL(PCIE_PORT_STATUS),
+       DUTL(PCIE_PORT_ERROR_SEV),
+       DUTL(PCIE_PORT_IRQ_EN),
+       DUTL(RC_STATUS),
+       DUTL(RC_ERR_SEVERITY),
+       DUTL(RC_IRQ_EN),
+       DUTL(EP_STATUS),
+       DUTL(EP_ERR_SEVERITY),
+       DUTL(EP_ERR_IRQ_EN),
+       DUTL(PCI_PM_CTRL1),
+       DUTL(PCI_PM_CTRL2),
+
+       /* PCIe stack regs */
+       DREG(SYSTEM_CONFIG1),
+       DREG(SYSTEM_CONFIG2),
+       DREG(EP_SYSTEM_CONFIG),
+       DREG(EP_FLR),
+       DREG(EP_BAR_CONFIG),
+       DREG(LINK_CONFIG),
+       DREG(PM_CONFIG),
+       DREG(DLP_CONTROL),
+       DREG(DLP_STATUS),
+       DREG(ERR_REPORT_CONTROL),
+       DREG(SLOT_CONTROL1),
+       DREG(SLOT_CONTROL2),
+       DREG(UTL_CONFIG),
+       DREG(BUFFERS_CONFIG),
+       DREG(ERROR_INJECT),
+       DREG(SRIOV_CONFIG),
+       DREG(PF0_SRIOV_STATUS),
+       DREG(PF1_SRIOV_STATUS),
+       DREG(PORT_NUMBER),
+       DREG(POR_SYSTEM_CONFIG),
+
+       /* Internal logic regs */
+       DREG(PHB_VERSION),
+       DREG(RESET),
+       DREG(PHB_CONTROL),
+       DREG(PHB_TIMEOUT_CONTROL1),
+       DREG(PHB_QUIESCE_DMA),
+       DREG(PHB_DMA_READ_TAG_ACTV),
+       DREG(PHB_TCE_READ_TAG_ACTV),
+
+       /* FIR registers */
+       DREG(LEM_FIR_ACCUM),
+       DREG(LEM_FIR_AND_MASK),
+       DREG(LEM_FIR_OR_MASK),
+       DREG(LEM_ACTION0),
+       DREG(LEM_ACTION1),
+       DREG(LEM_ERROR_MASK),
+       DREG(LEM_ERROR_AND_MASK),
+       DREG(LEM_ERROR_OR_MASK),
+
+       /* Error traps registers */
+       DREG(PHB_ERR_STATUS),
+       DREG(PHB_ERR_STATUS),
+       DREG(PHB_ERR1_STATUS),
+       DREG(PHB_ERR_INJECT),
+       DREG(PHB_ERR_LEM_ENABLE),
+       DREG(PHB_ERR_IRQ_ENABLE),
+       DREG(PHB_ERR_FREEZE_ENABLE),
+       DREG(PHB_ERR_SIDE_ENABLE),
+       DREG(PHB_ERR_LOG_0),
+       DREG(PHB_ERR_LOG_1),
+       DREG(PHB_ERR_STATUS_MASK),
+       DREG(PHB_ERR1_STATUS_MASK),
+       DREG(MMIO_ERR_STATUS),
+       DREG(MMIO_ERR1_STATUS),
+       DREG(MMIO_ERR_INJECT),
+       DREG(MMIO_ERR_LEM_ENABLE),
+       DREG(MMIO_ERR_IRQ_ENABLE),
+       DREG(MMIO_ERR_FREEZE_ENABLE),
+       DREG(MMIO_ERR_SIDE_ENABLE),
+       DREG(MMIO_ERR_LOG_0),
+       DREG(MMIO_ERR_LOG_1),
+       DREG(MMIO_ERR_STATUS_MASK),
+       DREG(MMIO_ERR1_STATUS_MASK),
+       DREG(DMA_ERR_STATUS),
+       DREG(DMA_ERR1_STATUS),
+       DREG(DMA_ERR_INJECT),
+       DREG(DMA_ERR_LEM_ENABLE),
+       DREG(DMA_ERR_IRQ_ENABLE),
+       DREG(DMA_ERR_FREEZE_ENABLE),
+       DREG(DMA_ERR_SIDE_ENABLE),
+       DREG(DMA_ERR_LOG_0),
+       DREG(DMA_ERR_LOG_1),
+       DREG(DMA_ERR_STATUS_MASK),
+       DREG(DMA_ERR1_STATUS_MASK),
+
+       /* Debug and Trace registers */
+       DREG(PHB_DEBUG_CONTROL0),
+       DREG(PHB_DEBUG_STATUS0),
+       DREG(PHB_DEBUG_CONTROL1),
+       DREG(PHB_DEBUG_STATUS1),
+       DREG(PHB_DEBUG_CONTROL2),
+       DREG(PHB_DEBUG_STATUS2),
+       DREG(PHB_DEBUG_CONTROL3),
+       DREG(PHB_DEBUG_STATUS3),
+       DREG(PHB_DEBUG_CONTROL4),
+       DREG(PHB_DEBUG_STATUS4),
+       DREG(PHB_DEBUG_CONTROL5),
+       DREG(PHB_DEBUG_STATUS5),
+
+       /* Don't seem to exist ...
+       DREG(PHB_DEBUG_CONTROL6),
+       DREG(PHB_DEBUG_STATUS6),
+       */
+};
+
+static int wsp_pci_regs_show(struct seq_file *m, void *private)
+{
+       struct wsp_phb *phb = m->private;
+       struct pci_controller *hose = phb->hose;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(wsp_pci_regs); i++) {
+               /* Skip write-only regs */
+               if (wsp_pci_regs[i].offset == 0xc08 ||
+                   wsp_pci_regs[i].offset == 0xc10 ||
+                   wsp_pci_regs[i].offset == 0xc38 ||
+                   wsp_pci_regs[i].offset == 0xc40)
+                       continue;
+               seq_printf(m, "0x%03x: 0x%016llx %s\n",
+                          wsp_pci_regs[i].offset,
+                          in_be64(hose->cfg_data + wsp_pci_regs[i].offset),
+                          wsp_pci_regs[i].name);
+       }
+       return 0;
+}
+
+static int wsp_pci_regs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, wsp_pci_regs_show, inode->i_private);
+}
+
+static const struct file_operations wsp_pci_regs_fops = {
+       .open = wsp_pci_regs_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+static int wsp_pci_reg_set(void *data, u64 val)
+{
+       out_be64((void __iomem *)data, val);
+       return 0;
+}
+
+static int wsp_pci_reg_get(void *data, u64 *val)
+{
+       *val = in_be64((void __iomem *)data);
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(wsp_pci_reg_fops, wsp_pci_reg_get, wsp_pci_reg_set, "0x%llx\n");
+
+static irqreturn_t wsp_pci_err_irq(int irq, void *dev_id)
+{
+       struct wsp_phb *phb = dev_id;
+       struct pci_controller *hose = phb->hose;
+       irqreturn_t handled = IRQ_NONE;
+       struct wsp_pcie_err_log_data ed;
+
+       pr_err("PCI: Error interrupt on %s (PHB %d)\n",
+              hose->dn->full_name, hose->global_number);
+ again:
+       memset(&ed, 0, sizeof(ed));
+
+       /* Read and clear UTL errors */
+       ed.utl_sys_err = in_be64(hose->cfg_data + PCIE_UTL_SYS_BUS_AGENT_STATUS);
+       if (ed.utl_sys_err)
+               out_be64(hose->cfg_data + PCIE_UTL_SYS_BUS_AGENT_STATUS, ed.utl_sys_err);
+       ed.utl_port_err = in_be64(hose->cfg_data + PCIE_UTL_PCIE_PORT_STATUS);
+       if (ed.utl_port_err)
+               out_be64(hose->cfg_data + PCIE_UTL_PCIE_PORT_STATUS, ed.utl_port_err);
+       ed.utl_rc_err = in_be64(hose->cfg_data + PCIE_UTL_RC_STATUS);
+       if (ed.utl_rc_err)
+               out_be64(hose->cfg_data + PCIE_UTL_RC_STATUS, ed.utl_rc_err);
+
+       /* Read and clear main trap errors */
+       ed.phb_err = in_be64(hose->cfg_data + PCIE_REG_PHB_ERR_STATUS);
+       if (ed.phb_err) {
+               ed.phb_err1 = in_be64(hose->cfg_data + PCIE_REG_PHB_ERR1_STATUS);
+               ed.phb_log0 = in_be64(hose->cfg_data + PCIE_REG_PHB_ERR_LOG_0);
+               ed.phb_log1 = in_be64(hose->cfg_data + PCIE_REG_PHB_ERR_LOG_1);
+               out_be64(hose->cfg_data + PCIE_REG_PHB_ERR1_STATUS, 0);
+               out_be64(hose->cfg_data + PCIE_REG_PHB_ERR_STATUS, 0);
+       }
+       ed.mmio_err = in_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_STATUS);
+       if (ed.mmio_err) {
+               ed.mmio_err1 = in_be64(hose->cfg_data + PCIE_REG_MMIO_ERR1_STATUS);
+               ed.mmio_log0 = in_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_LOG_0);
+               ed.mmio_log1 = in_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_LOG_1);
+               out_be64(hose->cfg_data + PCIE_REG_MMIO_ERR1_STATUS, 0);
+               out_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_STATUS, 0);
+       }
+       ed.dma_err = in_be64(hose->cfg_data + PCIE_REG_DMA_ERR_STATUS);
+       if (ed.dma_err) {
+               ed.dma_err1 = in_be64(hose->cfg_data + PCIE_REG_DMA_ERR1_STATUS);
+               ed.dma_log0 = in_be64(hose->cfg_data + PCIE_REG_DMA_ERR_LOG_0);
+               ed.dma_log1 = in_be64(hose->cfg_data + PCIE_REG_DMA_ERR_LOG_1);
+               out_be64(hose->cfg_data + PCIE_REG_DMA_ERR1_STATUS, 0);
+               out_be64(hose->cfg_data + PCIE_REG_DMA_ERR_STATUS, 0);
+       }
+
+       /* Now print things out */
+       if (ed.phb_err) {
+               pr_err("   PHB Error Status      : 0x%016llx\n", ed.phb_err);
+               pr_err("   PHB First Error Status: 0x%016llx\n", ed.phb_err1);
+               pr_err("   PHB Error Log 0       : 0x%016llx\n", ed.phb_log0);
+               pr_err("   PHB Error Log 1       : 0x%016llx\n", ed.phb_log1);
+       }
+       if (ed.mmio_err) {
+               pr_err("  MMIO Error Status      : 0x%016llx\n", ed.mmio_err);
+               pr_err("  MMIO First Error Status: 0x%016llx\n", ed.mmio_err1);
+               pr_err("  MMIO Error Log 0       : 0x%016llx\n", ed.mmio_log0);
+               pr_err("  MMIO Error Log 1       : 0x%016llx\n", ed.mmio_log1);
+       }
+       if (ed.dma_err) {
+               pr_err("   DMA Error Status      : 0x%016llx\n", ed.dma_err);
+               pr_err("   DMA First Error Status: 0x%016llx\n", ed.dma_err1);
+               pr_err("   DMA Error Log 0       : 0x%016llx\n", ed.dma_log0);
+               pr_err("   DMA Error Log 1       : 0x%016llx\n", ed.dma_log1);
+       }
+       if (ed.utl_sys_err)
+               pr_err("   UTL Sys Error Status  : 0x%016llx\n", ed.utl_sys_err);
+       if (ed.utl_port_err)
+               pr_err("   UTL Port Error Status : 0x%016llx\n", ed.utl_port_err);
+       if (ed.utl_rc_err)
+               pr_err("   UTL RC Error Status   : 0x%016llx\n", ed.utl_rc_err);
+
+       /* Interrupts are caused by the error traps. If we had any error there
+        * we loop again in case the UTL buffered some new stuff between
+        * going there and going to the traps
+        */
+       if (ed.dma_err || ed.mmio_err || ed.phb_err) {
+               handled = IRQ_HANDLED;
+               goto again;
+       }
+       return handled;
+}
+
+static void __init wsp_setup_pci_err_reporting(struct wsp_phb *phb)
+{
+       struct pci_controller *hose = phb->hose;
+       int err_irq, i, rc;
+       char fname[16];
+
+       /* Create a debugfs file for that PHB */
+       sprintf(fname, "phb%d", phb->hose->global_number);
+       phb->ddir = debugfs_create_dir(fname, powerpc_debugfs_root);
+
+       /* Some useful debug output */
+       if (phb->ddir) {
+               struct dentry *d = debugfs_create_dir("regs", phb->ddir);
+               char tmp[64];
+
+               for (i = 0; i < ARRAY_SIZE(wsp_pci_regs); i++) {
+                       sprintf(tmp, "%03x_%s", wsp_pci_regs[i].offset,
+                               wsp_pci_regs[i].name);
+                       debugfs_create_file(tmp, 0600, d,
+                                           hose->cfg_data + wsp_pci_regs[i].offset,
+                                           &wsp_pci_reg_fops);
+               }
+               debugfs_create_file("all_regs", 0600, phb->ddir, phb, &wsp_pci_regs_fops);
+       }
+
+       /* Find the IRQ number for that PHB */
+       err_irq = irq_of_parse_and_map(hose->dn, 0);
+       if (err_irq == 0)
+               /* XXX Error IRQ lacking from device-tree */
+               err_irq = wsp_pci_get_err_irq_no_dt(hose->dn);
+       if (err_irq == 0) {
+               pr_err("PCI: Failed to fetch error interrupt for %s\n",
+                      hose->dn->full_name);
+               return;
+       }
+       /* Request it */
+       rc = request_irq(err_irq, wsp_pci_err_irq, 0, "wsp_pci error", phb);
+       if (rc) {
+               pr_err("PCI: Failed to request interrupt for %s\n",
+                      hose->dn->full_name);
+       }
+       /* Enable interrupts for all errors for now */
+       out_be64(hose->cfg_data + PCIE_REG_PHB_ERR_IRQ_ENABLE, 0xffffffffffffffffull);
+       out_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_IRQ_ENABLE, 0xffffffffffffffffull);
+       out_be64(hose->cfg_data + PCIE_REG_DMA_ERR_IRQ_ENABLE, 0xffffffffffffffffull);
+}
+
+/*
+ * This is called later to hookup with the error interrupt
+ */
+static int __init wsp_setup_pci_late(void)
+{
+       struct wsp_phb *phb;
+
+       list_for_each_entry(phb, &wsp_phbs, all)
+               wsp_setup_pci_err_reporting(phb);
+
+       return 0;
+}
+arch_initcall(wsp_setup_pci_late);
diff --git a/arch/powerpc/platforms/wsp/wsp_pci.h b/arch/powerpc/platforms/wsp/wsp_pci.h
new file mode 100644 (file)
index 0000000..52e9bd9
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2010 Ben Herrenschmidt, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef __WSP_PCI_H
+#define __WSP_PCI_H
+
+/* Architected registers */
+#define PCIE_REG_DMA_CHAN_STATUS       0x110
+#define PCIE_REG_CPU_LOADSTORE_STATUS  0x120
+
+#define PCIE_REG_CONFIG_DATA           0x130
+#define PCIE_REG_LOCK0                 0x138
+#define PCIE_REG_CONFIG_ADDRESS                0x140
+#define   PCIE_REG_CA_ENABLE                   0x8000000000000000ull
+#define          PCIE_REG_CA_BUS_MASK                  0x0ff0000000000000ull
+#define   PCIE_REG_CA_BUS_SHIFT                        (20+32)
+#define   PCIE_REG_CA_DEV_MASK                 0x000f800000000000ull
+#define   PCIE_REG_CA_DEV_SHIFT                        (15+32)
+#define   PCIE_REG_CA_FUNC_MASK                        0x0000700000000000ull
+#define   PCIE_REG_CA_FUNC_SHIFT               (12+32)
+#define   PCIE_REG_CA_REG_MASK                 0x00000fff00000000ull
+#define   PCIE_REG_CA_REG_SHIFT                        ( 0+32)
+#define   PCIE_REG_CA_BE_MASK                  0x00000000f0000000ull
+#define   PCIE_REG_CA_BE_SHIFT                 (   28)
+#define PCIE_REG_LOCK1                 0x148
+
+#define PCIE_REG_PHB_CONFIG            0x160
+#define   PCIE_REG_PHBC_64B_TCE_EN             0x2000000000000000ull
+#define   PCIE_REG_PHBC_MMIO_DMA_FREEZE_EN     0x1000000000000000ull
+#define   PCIE_REG_PHBC_32BIT_MSI_EN           0x0080000000000000ull
+#define   PCIE_REG_PHBC_M64_EN                 0x0040000000000000ull
+#define   PCIE_REG_PHBC_IO_EN                  0x0008000000000000ull
+#define   PCIE_REG_PHBC_64BIT_MSI_EN           0x0002000000000000ull
+#define   PCIE_REG_PHBC_M32A_EN                        0x0000800000000000ull
+#define   PCIE_REG_PHBC_M32B_EN                        0x0000400000000000ull
+#define   PCIE_REG_PHBC_MSI_PE_VALIDATE                0x0000200000000000ull
+#define   PCIE_REG_PHBC_DMA_XLATE_BYPASS       0x0000100000000000ull
+
+#define PCIE_REG_IO_BASE_ADDR          0x170
+#define PCIE_REG_IO_BASE_MASK          0x178
+#define PCIE_REG_IO_START_ADDR         0x180
+
+#define PCIE_REG_M32A_BASE_ADDR                0x190
+#define PCIE_REG_M32A_BASE_MASK                0x198
+#define PCIE_REG_M32A_START_ADDR       0x1a0
+
+#define PCIE_REG_M32B_BASE_ADDR                0x1b0
+#define PCIE_REG_M32B_BASE_MASK                0x1b8
+#define PCIE_REG_M32B_START_ADDR       0x1c0
+
+#define PCIE_REG_M64_BASE_ADDR         0x1e0
+#define PCIE_REG_M64_BASE_MASK         0x1e8
+#define PCIE_REG_M64_START_ADDR                0x1f0
+
+#define PCIE_REG_TCE_KILL              0x210
+#define   PCIE_REG_TCEKILL_SINGLE      0x8000000000000000ull
+#define   PCIE_REG_TCEKILL_ADDR_MASK   0x000003fffffffff8ull
+#define   PCIE_REG_TCEKILL_PS_4K       0
+#define   PCIE_REG_TCEKILL_PS_64K      1
+#define   PCIE_REG_TCEKILL_PS_16M      2
+#define   PCIE_REG_TCEKILL_PS_16G      3
+
+#define PCIE_REG_IODA_ADDR             0x220
+#define   PCIE_REG_IODA_AD_AUTOINC     0x8000000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_MVT     0x0005000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_PELT    0x0006000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_PESTA   0x0007000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_PESTB   0x0008000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_TVT     0x0009000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_TCE     0x000a000000000000ull
+#define PCIE_REG_IODA_DATA0            0x228
+#define PCIE_REG_IODA_DATA1            0x230
+
+#define PCIE_REG_LOCK2                 0x240
+
+#define PCIE_REG_PHB_GEN_CAP           0x250
+#define PCIE_REG_PHB_TCE_CAP           0x258
+#define PCIE_REG_PHB_IRQ_CAP           0x260
+#define PCIE_REG_PHB_EEH_CAP           0x268
+
+#define PCIE_REG_PAPR_ERR_INJ_CONTROL  0x2b0
+#define PCIE_REG_PAPR_ERR_INJ_ADDR     0x2b8
+#define PCIE_REG_PAPR_ERR_INJ_MASK     0x2c0
+
+
+#define PCIE_REG_SYS_CFG1              0x600
+#define   PCIE_REG_SYS_CFG1_CLASS_CODE 0x0000000000ffffffull
+
+#define IODA_TVT0_TTA_MASK             0x000fffffffff0000ull
+#define IODA_TVT0_TTA_SHIFT            4
+#define IODA_TVT0_BUSNUM_VALID_MASK    0x000000000000e000ull
+#define IODA_TVT0_TCE_TABLE_SIZE_MASK  0x0000000000001f00ull
+#define IODA_TVT0_TCE_TABLE_SIZE_SHIFT 8
+#define IODA_TVT0_BUSNUM_VALUE_MASK    0x00000000000000ffull
+#define IODA_TVT0_BUSNUM_VALID_SHIFT   0
+#define IODA_TVT1_DEVNUM_VALID         0x2000000000000000ull
+#define IODA_TVT1_DEVNUM_VALUE_MASK    0x1f00000000000000ull
+#define IODA_TVT1_DEVNUM_VALUE_SHIFT   56
+#define IODA_TVT1_FUNCNUM_VALID                0x0008000000000000ull
+#define IODA_TVT1_FUNCNUM_VALUE_MASK   0x0007000000000000ull
+#define IODA_TVT1_FUNCNUM_VALUE_SHIFT  48
+#define IODA_TVT1_IO_PAGE_SIZE_MASK    0x00001f0000000000ull
+#define IODA_TVT1_IO_PAGE_SIZE_SHIFT   40
+#define IODA_TVT1_PE_NUMBER_MASK       0x000000000000003full
+#define IODA_TVT1_PE_NUMBER_SHIFT      0
+
+#define IODA_TVT_COUNT                 64
+
+/* UTL Core registers */
+#define PCIE_UTL_SYS_BUS_CONTROL       0x400
+#define PCIE_UTL_STATUS                        0x408
+#define PCIE_UTL_SYS_BUS_AGENT_STATUS  0x410
+#define PCIE_UTL_SYS_BUS_AGENT_ERR_SEV 0x418
+#define PCIE_UTL_SYS_BUS_AGENT_IRQ_EN  0x420
+#define PCIE_UTL_SYS_BUS_BURST_SZ_CONF 0x440
+#define PCIE_UTL_REVISION_ID           0x448
+
+#define PCIE_UTL_OUT_POST_HDR_BUF_ALLOC        0x4c0
+#define PCIE_UTL_OUT_POST_DAT_BUF_ALLOC        0x4d0
+#define PCIE_UTL_IN_POST_HDR_BUF_ALLOC 0x4e0
+#define PCIE_UTL_IN_POST_DAT_BUF_ALLOC 0x4f0
+#define PCIE_UTL_OUT_NP_BUF_ALLOC      0x500
+#define PCIE_UTL_IN_NP_BUF_ALLOC       0x510
+#define PCIE_UTL_PCIE_TAGS_ALLOC       0x520
+#define PCIE_UTL_GBIF_READ_TAGS_ALLOC  0x530
+
+#define PCIE_UTL_PCIE_PORT_CONTROL     0x540
+#define PCIE_UTL_PCIE_PORT_STATUS      0x548
+#define PCIE_UTL_PCIE_PORT_ERROR_SEV   0x550
+#define PCIE_UTL_PCIE_PORT_IRQ_EN      0x558
+#define PCIE_UTL_RC_STATUS             0x560
+#define PCIE_UTL_RC_ERR_SEVERITY       0x568
+#define PCIE_UTL_RC_IRQ_EN             0x570
+#define PCIE_UTL_EP_STATUS             0x578
+#define PCIE_UTL_EP_ERR_SEVERITY       0x580
+#define PCIE_UTL_EP_ERR_IRQ_EN         0x588
+
+#define PCIE_UTL_PCI_PM_CTRL1          0x590
+#define PCIE_UTL_PCI_PM_CTRL2          0x598
+
+/* PCIe stack registers */
+#define PCIE_REG_SYSTEM_CONFIG1                0x600
+#define PCIE_REG_SYSTEM_CONFIG2                0x608
+#define PCIE_REG_EP_SYSTEM_CONFIG      0x618
+#define PCIE_REG_EP_FLR                        0x620
+#define PCIE_REG_EP_BAR_CONFIG         0x628
+#define PCIE_REG_LINK_CONFIG           0x630
+#define PCIE_REG_PM_CONFIG             0x640
+#define PCIE_REG_DLP_CONTROL           0x650
+#define PCIE_REG_DLP_STATUS            0x658
+#define PCIE_REG_ERR_REPORT_CONTROL    0x660
+#define PCIE_REG_SLOT_CONTROL1         0x670
+#define PCIE_REG_SLOT_CONTROL2         0x678
+#define PCIE_REG_UTL_CONFIG            0x680
+#define PCIE_REG_BUFFERS_CONFIG                0x690
+#define PCIE_REG_ERROR_INJECT          0x698
+#define PCIE_REG_SRIOV_CONFIG          0x6a0
+#define PCIE_REG_PF0_SRIOV_STATUS      0x6a8
+#define PCIE_REG_PF1_SRIOV_STATUS      0x6b0
+#define PCIE_REG_PORT_NUMBER           0x700
+#define PCIE_REG_POR_SYSTEM_CONFIG     0x708
+
+/* PHB internal logic registers */
+#define PCIE_REG_PHB_VERSION           0x800
+#define PCIE_REG_RESET                 0x808
+#define PCIE_REG_PHB_CONTROL           0x810
+#define PCIE_REG_PHB_TIMEOUT_CONTROL1  0x878
+#define PCIE_REG_PHB_QUIESCE_DMA       0x888
+#define PCIE_REG_PHB_DMA_READ_TAG_ACTV 0x900
+#define PCIE_REG_PHB_TCE_READ_TAG_ACTV 0x908
+
+/* FIR registers */
+#define PCIE_REG_LEM_FIR_ACCUM         0xc00
+#define PCIE_REG_LEM_FIR_AND_MASK      0xc08
+#define PCIE_REG_LEM_FIR_OR_MASK       0xc10
+#define PCIE_REG_LEM_ACTION0           0xc18
+#define PCIE_REG_LEM_ACTION1           0xc20
+#define PCIE_REG_LEM_ERROR_MASK                0xc30
+#define PCIE_REG_LEM_ERROR_AND_MASK    0xc38
+#define PCIE_REG_LEM_ERROR_OR_MASK     0xc40
+
+/* PHB Error registers */
+#define PCIE_REG_PHB_ERR_STATUS                0xc80
+#define PCIE_REG_PHB_ERR1_STATUS       0xc88
+#define PCIE_REG_PHB_ERR_INJECT                0xc90
+#define PCIE_REG_PHB_ERR_LEM_ENABLE    0xc98
+#define PCIE_REG_PHB_ERR_IRQ_ENABLE    0xca0
+#define PCIE_REG_PHB_ERR_FREEZE_ENABLE 0xca8
+#define PCIE_REG_PHB_ERR_SIDE_ENABLE   0xcb8
+#define PCIE_REG_PHB_ERR_LOG_0         0xcc0
+#define PCIE_REG_PHB_ERR_LOG_1         0xcc8
+#define PCIE_REG_PHB_ERR_STATUS_MASK   0xcd0
+#define PCIE_REG_PHB_ERR1_STATUS_MASK  0xcd8
+
+#define PCIE_REG_MMIO_ERR_STATUS       0xd00
+#define PCIE_REG_MMIO_ERR1_STATUS      0xd08
+#define PCIE_REG_MMIO_ERR_INJECT       0xd10
+#define PCIE_REG_MMIO_ERR_LEM_ENABLE   0xd18
+#define PCIE_REG_MMIO_ERR_IRQ_ENABLE   0xd20
+#define PCIE_REG_MMIO_ERR_FREEZE_ENABLE        0xd28
+#define PCIE_REG_MMIO_ERR_SIDE_ENABLE  0xd38
+#define PCIE_REG_MMIO_ERR_LOG_0                0xd40
+#define PCIE_REG_MMIO_ERR_LOG_1                0xd48
+#define PCIE_REG_MMIO_ERR_STATUS_MASK  0xd50
+#define PCIE_REG_MMIO_ERR1_STATUS_MASK 0xd58
+
+#define PCIE_REG_DMA_ERR_STATUS                0xd80
+#define PCIE_REG_DMA_ERR1_STATUS       0xd88
+#define PCIE_REG_DMA_ERR_INJECT                0xd90
+#define PCIE_REG_DMA_ERR_LEM_ENABLE    0xd98
+#define PCIE_REG_DMA_ERR_IRQ_ENABLE    0xda0
+#define PCIE_REG_DMA_ERR_FREEZE_ENABLE 0xda8
+#define PCIE_REG_DMA_ERR_SIDE_ENABLE   0xdb8
+#define PCIE_REG_DMA_ERR_LOG_0         0xdc0
+#define PCIE_REG_DMA_ERR_LOG_1         0xdc8
+#define PCIE_REG_DMA_ERR_STATUS_MASK   0xdd0
+#define PCIE_REG_DMA_ERR1_STATUS_MASK  0xdd8
+
+/* Shortcuts for access to the above using the PHB definitions
+ * with an offset
+ */
+#define PCIE_REG_ERR_PHB_OFFSET                0x0
+#define PCIE_REG_ERR_MMIO_OFFSET       0x80
+#define PCIE_REG_ERR_DMA_OFFSET                0x100
+
+/* Debug and Trace registers */
+#define PCIE_REG_PHB_DEBUG_CONTROL0    0xe00
+#define PCIE_REG_PHB_DEBUG_STATUS0     0xe08
+#define PCIE_REG_PHB_DEBUG_CONTROL1    0xe10
+#define PCIE_REG_PHB_DEBUG_STATUS1     0xe18
+#define PCIE_REG_PHB_DEBUG_CONTROL2    0xe20
+#define PCIE_REG_PHB_DEBUG_STATUS2     0xe28
+#define PCIE_REG_PHB_DEBUG_CONTROL3    0xe30
+#define PCIE_REG_PHB_DEBUG_STATUS3     0xe38
+#define PCIE_REG_PHB_DEBUG_CONTROL4    0xe40
+#define PCIE_REG_PHB_DEBUG_STATUS4     0xe48
+#define PCIE_REG_PHB_DEBUG_CONTROL5    0xe50
+#define PCIE_REG_PHB_DEBUG_STATUS5     0xe58
+#define PCIE_REG_PHB_DEBUG_CONTROL6    0xe60
+#define PCIE_REG_PHB_DEBUG_STATUS6     0xe68
+
+/* Definition for PCIe errors */
+struct wsp_pcie_err_log_data {
+       __u64   phb_err;
+       __u64   phb_err1;
+       __u64   phb_log0;
+       __u64   phb_log1;
+       __u64   mmio_err;
+       __u64   mmio_err1;
+       __u64   mmio_log0;
+       __u64   mmio_log1;
+       __u64   dma_err;
+       __u64   dma_err1;
+       __u64   dma_log0;
+       __u64   dma_log1;
+       __u64   utl_sys_err;
+       __u64   utl_port_err;
+       __u64   utl_rc_err;
+       __u64   unused;
+};
+
+#endif /* __WSP_PCI_H */
index cf736ca..84e1325 100644 (file)
@@ -18,7 +18,6 @@ obj-$(CONFIG_FSL_PCI)         += fsl_pci.o $(fsl-msi-obj-y)
 obj-$(CONFIG_FSL_PMC)          += fsl_pmc.o
 obj-$(CONFIG_FSL_LBC)          += fsl_lbc.o
 obj-$(CONFIG_FSL_GTM)          += fsl_gtm.o
-obj-$(CONFIG_MPC8xxx_GPIO)     += mpc8xxx_gpio.o
 obj-$(CONFIG_FSL_85XX_CACHE_SRAM)      += fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o
 obj-$(CONFIG_SIMPLE_GPIO)      += simple_gpio.o
 obj-$(CONFIG_FSL_RIO)          += fsl_rio.o
index d55d0ad..8db10bb 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Author: Scott Wood <scottwood@freescale.com>
  *
- * Copyright 2007 Freescale Semiconductor, Inc.
+ * Copyright 2007-2008,2010 Freescale Semiconductor, Inc.
  *
  * Some parts derived from commproc.c/cpm2_common.c, which is:
  * Copyright (c) 1997 Dan error_act (dmalek@jlc.net)
@@ -146,6 +146,7 @@ unsigned long cpm_muram_alloc(unsigned long size, unsigned long align)
        spin_lock_irqsave(&cpm_muram_lock, flags);
        cpm_muram_info.alignment = align;
        start = rh_alloc(&cpm_muram_info, size, "commproc");
+       memset(cpm_muram_addr(start), 0, size);
        spin_unlock_irqrestore(&cpm_muram_lock, flags);
 
        return start;
index 419a772..e5c344d 100644 (file)
@@ -30,7 +30,7 @@ LIST_HEAD(msi_head);
 
 struct fsl_msi_feature {
        u32 fsl_pic_ip;
-       u32 msiir_offset;
+       u32 msiir_offset; /* Offset of MSIIR, relative to start of MSIR bank */
 };
 
 struct fsl_msi_cascade_data {
@@ -126,10 +126,19 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
 {
        struct fsl_msi *msi_data = fsl_msi_data;
        struct pci_controller *hose = pci_bus_to_host(pdev->bus);
-       u64 base = fsl_pci_immrbar_base(hose);
+       u64 address; /* Physical address of the MSIIR */
+       int len;
+       const u64 *reg;
+
+       /* If the msi-address-64 property exists, then use it */
+       reg = of_get_property(hose->dn, "msi-address-64", &len);
+       if (reg && (len == sizeof(u64)))
+               address = be64_to_cpup(reg);
+       else
+               address = fsl_pci_immrbar_base(hose) + msi_data->msiir_offset;
 
-       msg->address_lo = msi_data->msi_addr_lo + lower_32_bits(base);
-       msg->address_hi = msi_data->msi_addr_hi + upper_32_bits(base);
+       msg->address_lo = lower_32_bits(address);
+       msg->address_hi = upper_32_bits(address);
 
        msg->data = hwirq;
 
@@ -296,7 +305,7 @@ static int __devinit fsl_msi_setup_hwirq(struct fsl_msi *msi,
        }
 
        msi->msi_virqs[irq_index] = virt_msir;
-       cascade_data->index = offset + irq_index;
+       cascade_data->index = offset;
        cascade_data->msi_data = msi;
        irq_set_handler_data(virt_msir, cascade_data);
        irq_set_chained_handler(virt_msir, fsl_msi_cascade);
@@ -359,8 +368,7 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev)
 
        msi->irqhost->host_data = msi;
 
-       msi->msi_addr_hi = 0x0;
-       msi->msi_addr_lo = features->msiir_offset + (res.start & 0xfffff);
+       msi->msiir_offset = features->msiir_offset + (res.start & 0xfffff);
 
        rc = fsl_msi_init_allocator(msi);
        if (rc) {
@@ -376,8 +384,10 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev)
                goto error_out;
        }
 
-       if (!p)
+       if (!p) {
                p = all_avail;
+               len = sizeof(all_avail);
+       }
 
        for (irq_index = 0, i = 0; i < len / (2 * sizeof(u32)); i++) {
                if (p[i * 2] % IRQS_PER_MSI_REG ||
@@ -393,7 +403,7 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev)
                count = p[i * 2 + 1] / IRQS_PER_MSI_REG;
 
                for (j = 0; j < count; j++, irq_index++) {
-                       err = fsl_msi_setup_hwirq(msi, dev, offset, irq_index);
+                       err = fsl_msi_setup_hwirq(msi, dev, offset + j, irq_index);
                        if (err)
                                goto error_out;
                }
index 624580c..1313abb 100644 (file)
@@ -28,8 +28,7 @@ struct fsl_msi {
 
        unsigned long cascade_irq;
 
-       u32 msi_addr_lo;
-       u32 msi_addr_hi;
+       u32 msiir_offset; /* Offset of MSIIR, relative to start of CCSR */
        void __iomem *msi_regs;
        u32 feature;
        int msi_virqs[NR_MSI_REG];
index d5d3ff3..0842c6f 100644 (file)
@@ -1285,13 +1285,11 @@ struct mpic * __init mpic_alloc(struct device_node *node,
                           mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
                           | MPIC_GREG_GCONF_MCK);
 
-       /* Read feature register, calculate num CPUs and, for non-ISU
-        * MPICs, num sources as well. On ISU MPICs, sources are counted
-        * as ISUs are added
+       /*
+        * Read feature register.  For non-ISU MPICs, num sources as well. On
+        * ISU MPICs, sources are counted as ISUs are added
         */
        greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
-       mpic->num_cpus = ((greg_feature & MPIC_GREG_FEATURE_LAST_CPU_MASK)
-                         >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
        if (isu_size == 0) {
                if (flags & MPIC_BROKEN_FRR_NIRQS)
                        mpic->num_sources = mpic->irq_count;
@@ -1301,10 +1299,18 @@ struct mpic * __init mpic_alloc(struct device_node *node,
                                 >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
        }
 
+       /*
+        * The MPIC driver will crash if there are more cores than we
+        * can initialize, so we may as well catch that problem here.
+        */
+       BUG_ON(num_possible_cpus() > MPIC_MAX_CPUS);
+
        /* Map the per-CPU registers */
-       for (i = 0; i < mpic->num_cpus; i++) {
-               mpic_map(mpic, node, paddr, &mpic->cpuregs[i],
-                        MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE),
+       for_each_possible_cpu(i) {
+               unsigned int cpu = get_hard_smp_processor_id(i);
+
+               mpic_map(mpic, node, paddr, &mpic->cpuregs[cpu],
+                        MPIC_INFO(CPU_BASE) + cpu * MPIC_INFO(CPU_STRIDE),
                         0x1000);
        }
 
@@ -1343,7 +1349,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
        }
        printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %llx,"
               " max %d CPUs\n",
-              name, vers, (unsigned long long)paddr, mpic->num_cpus);
+              name, vers, (unsigned long long)paddr, num_possible_cpus());
        printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n",
               mpic->isu_size, mpic->isu_shift, mpic->isu_mask);
 
@@ -1742,6 +1748,7 @@ void mpic_reset_core(int cpu)
        struct mpic *mpic = mpic_primary;
        u32 pir;
        int cpuid = get_hard_smp_processor_id(cpu);
+       int i;
 
        /* Set target bit for core reset */
        pir = mpic_read(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT));
@@ -1753,6 +1760,15 @@ void mpic_reset_core(int cpu)
        pir &= ~(1 << cpuid);
        mpic_write(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT), pir);
        mpic_read(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT));
+
+       /* Perform 15 EOI on each reset core to clear pending interrupts.
+        * This is required for FSL CoreNet based devices */
+       if (mpic->flags & MPIC_FSL) {
+               for (i = 0; i < 15; i++) {
+                       _mpic_write(mpic->reg_type, &mpic->cpuregs[cpuid],
+                                     MPIC_CPU_EOI, 0);
+               }
+       }
 }
 #endif /* CONFIG_SMP */
 
index dbfe96b..862f11b 100644 (file)
@@ -834,7 +834,7 @@ static int __init ppc440spe_pciex_core_init(struct device_node *np)
        return 3;
 }
 
-static int ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
        u32 val = 1 << 24;
 
@@ -872,12 +872,12 @@ static int ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
        return ppc4xx_pciex_port_reset_sdr(port);
 }
 
-static int ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
        return ppc440spe_pciex_init_port_hw(port);
 }
 
-static int ppc440speB_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc440speB_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
        int rc = ppc440spe_pciex_init_port_hw(port);
 
@@ -936,7 +936,7 @@ static int __init ppc460ex_pciex_core_init(struct device_node *np)
        return 2;
 }
 
-static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
        u32 val;
        u32 utlset1;
@@ -1092,6 +1092,10 @@ static int __init ppc460sx_pciex_core_init(struct device_node *np)
        mtdcri(SDR0, PESDR1_460SX_HSSSLEW, 0xFFFF0000);
        mtdcri(SDR0, PESDR2_460SX_HSSSLEW, 0xFFFF0000);
 
+       /* Set HSS PRBS enabled */
+       mtdcri(SDR0, PESDR0_460SX_HSSCTLSET, 0x00001130);
+       mtdcri(SDR0, PESDR2_460SX_HSSCTLSET, 0x00001130);
+
        udelay(100);
 
        /* De-assert PLLRESET */
@@ -1122,7 +1126,7 @@ static int __init ppc460sx_pciex_core_init(struct device_node *np)
        return 2;
 }
 
-static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
 
        if (port->endpoint)
@@ -1132,9 +1136,6 @@ static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
                dcri_clrset(SDR0, port->sdr_base + PESDRn_UTLSET2,
                                0, 0x01000000);
 
-       /*Gen-1*/
-       mtdcri(SDR0, port->sdr_base + PESDRn_460SX_RCEI, 0x08000000);
-
        dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET,
                        (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL),
                        PESDRx_RCSSET_RSTPYN);
@@ -1148,14 +1149,42 @@ static int ppc460sx_pciex_init_utl(struct ppc4xx_pciex_port *port)
 {
        /* Max 128 Bytes */
        out_be32 (port->utl_base + PEUTL_PBBSZ,   0x00000000);
+       /* Assert VRB and TXE - per datasheet turn off addr validation */
+       out_be32(port->utl_base + PEUTL_PCTL,  0x80800000);
        return 0;
 }
 
+static void __init ppc460sx_pciex_check_link(struct ppc4xx_pciex_port *port)
+{
+       void __iomem *mbase;
+       int attempt = 50;
+
+       port->link = 0;
+
+       mbase = ioremap(port->cfg_space.start + 0x10000000, 0x1000);
+       if (mbase == NULL) {
+               printk(KERN_ERR "%s: Can't map internal config space !",
+                       port->node->full_name);
+               goto done;
+       }
+
+       while (attempt && (0 == (in_le32(mbase + PECFG_460SX_DLLSTA)
+                       & PECFG_460SX_DLLSTA_LINKUP))) {
+               attempt--;
+               mdelay(10);
+       }
+       if (attempt)
+               port->link = 1;
+done:
+       iounmap(mbase);
+
+}
+
 static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = {
        .core_init      = ppc460sx_pciex_core_init,
        .port_init_hw   = ppc460sx_pciex_init_port_hw,
        .setup_utl      = ppc460sx_pciex_init_utl,
-       .check_link     = ppc4xx_pciex_check_link_sdr,
+       .check_link     = ppc460sx_pciex_check_link,
 };
 
 #endif /* CONFIG_44x */
@@ -1189,7 +1218,7 @@ static void ppc405ex_pcie_phy_reset(struct ppc4xx_pciex_port *port)
        mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, 0x00101000);
 }
 
-static int ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
        u32 val;
 
@@ -1338,15 +1367,15 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)
        if (rc != 0)
                return rc;
 
-       if (ppc4xx_pciex_hwops->check_link)
-               ppc4xx_pciex_hwops->check_link(port);
-
        /*
         * Initialize mapping: disable all regions and configure
         * CFG and REG regions based on resources in the device tree
         */
        ppc4xx_pciex_port_init_mapping(port);
 
+       if (ppc4xx_pciex_hwops->check_link)
+               ppc4xx_pciex_hwops->check_link(port);
+
        /*
         * Map UTL
         */
@@ -1360,13 +1389,23 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)
                ppc4xx_pciex_hwops->setup_utl(port);
 
        /*
-        * Check for VC0 active and assert RDY.
+        * Check for VC0 active or PLL Locked and assert RDY.
         */
        if (port->sdr_base) {
-               if (port->link &&
-                   ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS,
-                                            1 << 16, 1 << 16, 5000)) {
-                       printk(KERN_INFO "PCIE%d: VC0 not active\n", port->index);
+               if (of_device_is_compatible(port->node,
+                               "ibm,plb-pciex-460sx")){
+                       if (port->link && ppc4xx_pciex_wait_on_sdr(port,
+                                       PESDRn_RCSSTS,
+                                       1 << 12, 1 << 12, 5000)) {
+                               printk(KERN_INFO "PCIE%d: PLL not locked\n",
+                                               port->index);
+                               port->link = 0;
+                       }
+               } else if (port->link &&
+                       ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS,
+                               1 << 16, 1 << 16, 5000)) {
+                       printk(KERN_INFO "PCIE%d: VC0 not active\n",
+                                       port->index);
                        port->link = 0;
                }
 
@@ -1573,8 +1612,15 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port    *port,
                dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah);
                dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal);
                dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff);
-               /* Note that 3 here means enabled | single region */
-               dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, sa | 3);
+               /*Enabled and single region */
+               if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx"))
+                       dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
+                               sa | DCRO_PEGPL_460SX_OMR1MSKL_UOT
+                                       | DCRO_PEGPL_OMRxMSKL_VAL);
+               else
+                       dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
+                               sa | DCRO_PEGPL_OMR1MSKL_UOT
+                                       | DCRO_PEGPL_OMRxMSKL_VAL);
                break;
        case 1:
                out_le32(mbase + PECFG_POM1LAH, pciah);
@@ -1582,8 +1628,8 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port     *port,
                dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah);
                dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal);
                dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff);
-               /* Note that 3 here means enabled | single region */
-               dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, sa | 3);
+               dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL,
+                               sa | DCRO_PEGPL_OMRxMSKL_VAL);
                break;
        case 2:
                out_le32(mbase + PECFG_POM2LAH, pciah);
@@ -1592,7 +1638,9 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port     *port,
                dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal);
                dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff);
                /* Note that 3 here means enabled | IO space !!! */
-               dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, sa | 3);
+               dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL,
+                               sa | DCRO_PEGPL_OMR3MSKL_IO
+                                       | DCRO_PEGPL_OMRxMSKL_VAL);
                break;
        }
 
@@ -1693,6 +1741,9 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port,
                if (res->flags & IORESOURCE_PREFETCH)
                        sa |= 0x8;
 
+               if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx"))
+                       sa |= PCI_BASE_ADDRESS_MEM_TYPE_64;
+
                out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa));
                out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa));
 
@@ -1854,6 +1905,10 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port)
        }
        out_le16(mbase + 0x202, val);
 
+       /* Enable Bus master, memory, and io space */
+       if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx"))
+               out_le16(mbase + 0x204, 0x7);
+
        if (!port->endpoint) {
                /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */
                out_le32(mbase + 0x208, 0x06040001);
index c39a134..32ce763 100644 (file)
 #define PECFG_POM2LAL          0x390
 #define PECFG_POM2LAH          0x394
 
+/* 460sx only */
+#define PECFG_460SX_DLLSTA     0x3f8
+
+/* 460sx Bit Mappings */
+#define PECFG_460SX_DLLSTA_LINKUP       0x00000010
+#define DCRO_PEGPL_460SX_OMR1MSKL_UOT   0x00000004
+
+/* PEGPL Bit Mappings */
+#define DCRO_PEGPL_OMRxMSKL_VAL         0x00000001
+#define DCRO_PEGPL_OMR1MSKL_UOT         0x00000002
+#define DCRO_PEGPL_OMR3MSKL_IO  0x00000002
+
 /* SDR Bit Mappings */
 #define PESDRx_RCSSET_HLDPLB   0x10000000
 #define PESDRx_RCSSET_RSTGU    0x01000000
index b75a605..c606aa8 100644 (file)
@@ -4,3 +4,4 @@ obj-y                           += xics-common.o
 obj-$(CONFIG_PPC_ICP_NATIVE)   += icp-native.o
 obj-$(CONFIG_PPC_ICP_HV)       += icp-hv.o
 obj-$(CONFIG_PPC_ICS_RTAS)     += ics-rtas.o
+obj-$(CONFIG_PPC_POWERNV)      += ics-opal.o
index 50e32af..4c79b6f 100644 (file)
@@ -276,7 +276,7 @@ static const struct icp_ops icp_native_ops = {
 #endif
 };
 
-int icp_native_init(void)
+int __init icp_native_init(void)
 {
        struct device_node *np;
        u32 indx = 0;
diff --git a/arch/powerpc/sysdev/xics/ics-opal.c b/arch/powerpc/sysdev/xics/ics-opal.c
new file mode 100644 (file)
index 0000000..f7e8609
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * ICS backend for OPAL managed interrupts.
+ *
+ * Copyright 2011 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.
+ */
+
+#undef DEBUG
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/of.h>
+#include <linux/spinlock.h>
+#include <linux/msi.h>
+
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/errno.h>
+#include <asm/xics.h>
+#include <asm/opal.h>
+#include <asm/firmware.h>
+
+static int ics_opal_mangle_server(int server)
+{
+       /* No link for now */
+       return server << 2;
+}
+
+static int ics_opal_unmangle_server(int server)
+{
+       /* No link for now */
+       return server >> 2;
+}
+
+static void ics_opal_unmask_irq(struct irq_data *d)
+{
+       unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
+       int64_t rc;
+       int server;
+
+       pr_devel("ics-hal: unmask virq %d [hw 0x%x]\n", d->irq, hw_irq);
+
+       if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
+               return;
+
+       server = xics_get_irq_server(d->irq, d->affinity, 0);
+       server = ics_opal_mangle_server(server);
+
+       rc = opal_set_xive(hw_irq, server, DEFAULT_PRIORITY);
+       if (rc != OPAL_SUCCESS)
+               pr_err("%s: opal_set_xive(irq=%d [hw 0x%x] server=%x)"
+                      " error %lld\n",
+                      __func__, d->irq, hw_irq, server, rc);
+}
+
+static unsigned int ics_opal_startup(struct irq_data *d)
+{
+#ifdef CONFIG_PCI_MSI
+       /*
+        * The generic MSI code returns with the interrupt disabled on the
+        * card, using the MSI mask bits. Firmware doesn't appear to unmask
+        * at that level, so we do it here by hand.
+        */
+       if (d->msi_desc)
+               unmask_msi_irq(d);
+#endif
+
+       /* unmask it */
+       ics_opal_unmask_irq(d);
+       return 0;
+}
+
+static void ics_opal_mask_real_irq(unsigned int hw_irq)
+{
+       int server = ics_opal_mangle_server(xics_default_server);
+       int64_t rc;
+
+       if (hw_irq == XICS_IPI)
+               return;
+
+       /* Have to set XIVE to 0xff to be able to remove a slot */
+       rc = opal_set_xive(hw_irq, server, 0xff);
+       if (rc != OPAL_SUCCESS)
+               pr_err("%s: opal_set_xive(0xff) irq=%u returned %lld\n",
+                      __func__, hw_irq, rc);
+}
+
+static void ics_opal_mask_irq(struct irq_data *d)
+{
+       unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
+
+       pr_devel("ics-hal: mask virq %d [hw 0x%x]\n", d->irq, hw_irq);
+
+       if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
+               return;
+       ics_opal_mask_real_irq(hw_irq);
+}
+
+static int ics_opal_set_affinity(struct irq_data *d,
+                                const struct cpumask *cpumask,
+                                bool force)
+{
+       unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
+       int16_t server;
+       int8_t priority;
+       int64_t rc;
+       int wanted_server;
+
+       if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
+               return -1;
+
+       rc = opal_get_xive(hw_irq, &server, &priority);
+       if (rc != OPAL_SUCCESS) {
+               pr_err("%s: opal_set_xive(irq=%d [hw 0x%x] server=%x)"
+                      " error %lld\n",
+                      __func__, d->irq, hw_irq, server, rc);
+               return -1;
+       }
+
+       wanted_server = xics_get_irq_server(d->irq, cpumask, 1);
+       if (wanted_server < 0) {
+               char cpulist[128];
+               cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
+               pr_warning("%s: No online cpus in the mask %s for irq %d\n",
+                          __func__, cpulist, d->irq);
+               return -1;
+       }
+       server = ics_opal_mangle_server(wanted_server);
+
+       pr_devel("ics-hal: set-affinity irq %d [hw 0x%x] server: 0x%x/0x%x\n",
+                d->irq, hw_irq, wanted_server, server);
+
+       rc = opal_set_xive(hw_irq, server, priority);
+       if (rc != OPAL_SUCCESS) {
+               pr_err("%s: opal_set_xive(irq=%d [hw 0x%x] server=%x)"
+                      " error %lld\n",
+                      __func__, d->irq, hw_irq, server, rc);
+               return -1;
+       }
+       return 0;
+}
+
+static struct irq_chip ics_opal_irq_chip = {
+       .name = "OPAL ICS",
+       .irq_startup = ics_opal_startup,
+       .irq_mask = ics_opal_mask_irq,
+       .irq_unmask = ics_opal_unmask_irq,
+       .irq_eoi = NULL, /* Patched at init time */
+       .irq_set_affinity = ics_opal_set_affinity
+};
+
+static int ics_opal_map(struct ics *ics, unsigned int virq);
+static void ics_opal_mask_unknown(struct ics *ics, unsigned long vec);
+static long ics_opal_get_server(struct ics *ics, unsigned long vec);
+
+static int ics_opal_host_match(struct ics *ics, struct device_node *node)
+{
+       return 1;
+}
+
+/* Only one global & state struct ics */
+static struct ics ics_hal = {
+       .map            = ics_opal_map,
+       .mask_unknown   = ics_opal_mask_unknown,
+       .get_server     = ics_opal_get_server,
+       .host_match     = ics_opal_host_match,
+};
+
+static int ics_opal_map(struct ics *ics, unsigned int virq)
+{
+       unsigned int hw_irq = (unsigned int)virq_to_hw(virq);
+       int64_t rc;
+       int16_t server;
+       int8_t priority;
+
+       if (WARN_ON(hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS))
+               return -EINVAL;
+
+       /* Check if HAL knows about this interrupt */
+       rc = opal_get_xive(hw_irq, &server, &priority);
+       if (rc != OPAL_SUCCESS)
+               return -ENXIO;
+
+       irq_set_chip_and_handler(virq, &ics_opal_irq_chip, handle_fasteoi_irq);
+       irq_set_chip_data(virq, &ics_hal);
+
+       return 0;
+}
+
+static void ics_opal_mask_unknown(struct ics *ics, unsigned long vec)
+{
+       int64_t rc;
+       int16_t server;
+       int8_t priority;
+
+       /* Check if HAL knows about this interrupt */
+       rc = opal_get_xive(vec, &server, &priority);
+       if (rc != OPAL_SUCCESS)
+               return;
+
+       ics_opal_mask_real_irq(vec);
+}
+
+static long ics_opal_get_server(struct ics *ics, unsigned long vec)
+{
+       int64_t rc;
+       int16_t server;
+       int8_t priority;
+
+       /* Check if HAL knows about this interrupt */
+       rc = opal_get_xive(vec, &server, &priority);
+       if (rc != OPAL_SUCCESS)
+               return -1;
+       return ics_opal_unmangle_server(server);
+}
+
+int __init ics_opal_init(void)
+{
+       if (!firmware_has_feature(FW_FEATURE_OPAL))
+               return -ENODEV;
+
+       /* We need to patch our irq chip's EOI to point to the
+        * right ICP
+        */
+       ics_opal_irq_chip.irq_eoi = icp_ops->eoi;
+
+       /* Register ourselves */
+       xics_register_ics(&ics_hal);
+
+       pr_info("ICS OPAL backend registered\n");
+
+       return 0;
+}
index 445c5a0..3d93a8d 100644 (file)
@@ -409,14 +409,10 @@ void __init xics_init(void)
        int rc = -1;
 
        /* Fist locate ICP */
-#ifdef CONFIG_PPC_ICP_HV
        if (firmware_has_feature(FW_FEATURE_LPAR))
                rc = icp_hv_init();
-#endif
-#ifdef CONFIG_PPC_ICP_NATIVE
        if (rc < 0)
                rc = icp_native_init();
-#endif
        if (rc < 0) {
                pr_warning("XICS: Cannot find a Presentation Controller !\n");
                return;
@@ -429,9 +425,9 @@ void __init xics_init(void)
        xics_ipi_chip.irq_eoi = icp_ops->eoi;
 
        /* Now locate ICS */
-#ifdef CONFIG_PPC_ICS_RTAS
        rc = ics_rtas_init();
-#endif
+       if (rc < 0)
+               rc = ics_opal_init();
        if (rc < 0)
                pr_warning("XICS: Cannot find a Source Controller !\n");
 
index 42541bb..13f82f8 100644 (file)
@@ -340,8 +340,8 @@ int cpus_are_in_xmon(void)
 
 static inline int unrecoverable_excp(struct pt_regs *regs)
 {
-#ifdef CONFIG_4xx
-       /* We have no MSR_RI bit on 4xx, so we simply return false */
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOK3E)
+       /* We have no MSR_RI bit on 4xx or Book3e, so we simply return false */
        return 0;
 #else
        return ((regs->msr & MSR_RI) == 0);
index a687a0d..a774c0d 100644 (file)
@@ -90,6 +90,7 @@ enum apimask_bits {
        ECC_MASK_ENABLE = (APIMASK_ECC_UE_H | APIMASK_ECC_CE_H |
                           APIMASK_ECC_UE_L | APIMASK_ECC_CE_L),
 };
+#define APIMASK_ADI(n)         CPC925_BIT(((n)+1))
 
 /************************************************************
  *     Processor Interface Exception Register (APIEXCP)
@@ -581,16 +582,73 @@ static void cpc925_mc_check(struct mem_ctl_info *mci)
 }
 
 /******************** CPU err device********************************/
+static u32 cpc925_cpu_mask_disabled(void)
+{
+       struct device_node *cpus;
+       struct device_node *cpunode = NULL;
+       static u32 mask = 0;
+
+       /* use cached value if available */
+       if (mask != 0)
+               return mask;
+
+       mask = APIMASK_ADI0 | APIMASK_ADI1;
+
+       cpus = of_find_node_by_path("/cpus");
+       if (cpus == NULL) {
+               cpc925_printk(KERN_DEBUG, "No /cpus node !\n");
+               return 0;
+       }
+
+       while ((cpunode = of_get_next_child(cpus, cpunode)) != NULL) {
+               const u32 *reg = of_get_property(cpunode, "reg", NULL);
+
+               if (strcmp(cpunode->type, "cpu")) {
+                       cpc925_printk(KERN_ERR, "Not a cpu node in /cpus: %s\n", cpunode->name);
+                       continue;
+               }
+
+               if (reg == NULL || *reg > 2) {
+                       cpc925_printk(KERN_ERR, "Bad reg value at %s\n", cpunode->full_name);
+                       continue;
+               }
+
+               mask &= ~APIMASK_ADI(*reg);
+       }
+
+       if (mask != (APIMASK_ADI0 | APIMASK_ADI1)) {
+               /* We assume that each CPU sits on it's own PI and that
+                * for present CPUs the reg property equals to the PI
+                * interface id */
+               cpc925_printk(KERN_WARNING,
+                               "Assuming PI id is equal to CPU MPIC id!\n");
+       }
+
+       of_node_put(cpunode);
+       of_node_put(cpus);
+
+       return mask;
+}
+
 /* Enable CPU Errors detection */
 static void cpc925_cpu_init(struct cpc925_dev_info *dev_info)
 {
        u32 apimask;
+       u32 cpumask;
 
        apimask = __raw_readl(dev_info->vbase + REG_APIMASK_OFFSET);
-       if ((apimask & CPU_MASK_ENABLE) == 0) {
-               apimask |= CPU_MASK_ENABLE;
-               __raw_writel(apimask, dev_info->vbase + REG_APIMASK_OFFSET);
+
+       cpumask = cpc925_cpu_mask_disabled();
+       if (apimask & cpumask) {
+               cpc925_printk(KERN_WARNING, "CPU(s) not present, "
+                               "but enabled in APIMASK, disabling\n");
+               apimask &= ~cpumask;
        }
+
+       if ((apimask & CPU_MASK_ENABLE) == 0)
+               apimask |= CPU_MASK_ENABLE;
+
+       __raw_writel(apimask, dev_info->vbase + REG_APIMASK_OFFSET);
 }
 
 /* Disable CPU Errors detection */
@@ -622,6 +680,9 @@ static void cpc925_cpu_check(struct edac_device_ctl_info *edac_dev)
        if ((apiexcp & CPU_EXCP_DETECTED) == 0)
                return;
 
+       if ((apiexcp & ~cpc925_cpu_mask_disabled()) == 0)
+               return;
+
        apimask = __raw_readl(dev_info->vbase + REG_APIMASK_OFFSET);
        cpc925_printk(KERN_INFO, "Processor Interface Fault\n"
                                 "Processor Interface register dump:\n");
index 0de7d87..3840096 100644 (file)
@@ -205,7 +205,7 @@ static struct platform_driver ppc4xx_edac_driver = {
        .remove                 = ppc4xx_edac_remove,
        .driver = {
                .owner = THIS_MODULE,
-               .name = PPC4XX_EDAC_MODULE_NAME
+               .name = PPC4XX_EDAC_MODULE_NAME,
                .of_match_table = ppc4xx_edac_match,
        },
 };
index 74603ca..8482a23 100644 (file)
@@ -99,6 +99,14 @@ config GPIO_MPC5200
        def_bool y
        depends on PPC_MPC52xx
 
+config GPIO_MPC8XXX
+       bool "MPC512x/MPC8xxx GPIO support"
+       depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \
+                  FSL_SOC_BOOKE || PPC_86xx
+       help
+         Say Y here if you're going to use hardware that connects to the
+         MPC512x/831x/834x/837x/8572/8610 GPIOs.
+
 config GPIO_MSM_V1
        tristate "Qualcomm MSM GPIO v1"
        depends on GPIOLIB && ARCH_MSM
index 4a9ad2f..dbcb0bc 100644 (file)
@@ -29,6 +29,7 @@ obj-$(CONFIG_GPIO_MC33880)    += gpio-mc33880.o
 obj-$(CONFIG_GPIO_MCP23S08)    += gpio-mcp23s08.o
 obj-$(CONFIG_GPIO_ML_IOH)      += gpio-ml-ioh.o
 obj-$(CONFIG_GPIO_MPC5200)     += gpio-mpc5200.o
+obj-$(CONFIG_GPIO_MPC8XXX)     += gpio-mpc8xxx.o
 obj-$(CONFIG_GPIO_MSM_V1)      += gpio-msm-v1.o
 obj-$(CONFIG_GPIO_MSM_V2)      += gpio-msm-v2.o
 obj-$(CONFIG_GPIO_MXC)         += gpio-mxc.o
similarity index 98%
rename from arch/powerpc/sysdev/mpc8xxx_gpio.c
rename to drivers/gpio/gpio-mpc8xxx.c
index fb4963a..ec3fcf0 100644 (file)
@@ -146,6 +146,7 @@ static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
 static void mpc8xxx_gpio_irq_cascade(unsigned int irq, struct irq_desc *desc)
 {
        struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_desc_get_handler_data(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
        unsigned int mask;
 
@@ -153,6 +154,7 @@ static void mpc8xxx_gpio_irq_cascade(unsigned int irq, struct irq_desc *desc)
        if (mask)
                generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq,
                                                     32 - ffs(mask)));
+       chip->irq_eoi(&desc->irq_data);
 }
 
 static void mpc8xxx_irq_unmask(struct irq_data *d)
@@ -310,6 +312,7 @@ static struct of_device_id mpc8xxx_gpio_ids[] __initdata = {
        { .compatible = "fsl,mpc8572-gpio", },
        { .compatible = "fsl,mpc8610-gpio", },
        { .compatible = "fsl,mpc5121-gpio", .data = mpc512x_irq_set_type, },
+       { .compatible = "fsl,pq3-gpio",     },
        { .compatible = "fsl,qoriq-gpio",   },
        {}
 };
index ddb33cf..7bf1e20 100644 (file)
@@ -1674,6 +1674,9 @@ static int __devinit ps3_gelic_driver_probe(struct ps3_system_bus_device *dev)
        int result;
 
        pr_debug("%s: called\n", __func__);
+
+       udbg_shutdown_ps3gelic();
+
        result = ps3_open_hv_device(dev);
 
        if (result) {
index d3fadfb..a93df6a 100644 (file)
@@ -359,6 +359,12 @@ static inline void *port_priv(struct gelic_port *port)
        return port->priv;
 }
 
+#ifdef CONFIG_PPC_EARLY_DEBUG_PS3GELIC
+extern void udbg_shutdown_ps3gelic(void);
+#else
+static inline void udbg_shutdown_ps3gelic(void) {}
+#endif
+
 extern int gelic_card_set_irq_mask(struct gelic_card *card, u64 mask);
 /* shared netdev ops */
 extern void gelic_card_up(struct gelic_card *card);
index aeec35b..fd85fa2 100644 (file)
@@ -681,9 +681,14 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
        if (p != NULL && l > 0)
                strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE));
 
+       /*
+        * CONFIG_CMDLINE is meant to be a default in case nothing else
+        * managed to set the command line, unless CONFIG_CMDLINE_FORCE
+        * is set in which case we override whatever was found earlier.
+        */
 #ifdef CONFIG_CMDLINE
 #ifndef CONFIG_CMDLINE_FORCE
-       if (p == NULL || l == 0 || (l == 1 && (*p) == 0))
+       if (!((char *)data)[0])
 #endif
                strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
 #endif /* CONFIG_CMDLINE */
index e371753..4222035 100644 (file)
@@ -34,6 +34,15 @@ config HVC_ISERIES
        help
          iSeries machines support a hypervisor virtual console.
 
+config HVC_OPAL
+       bool "OPAL Console support"
+       depends on PPC_POWERNV
+       select HVC_DRIVER
+       select HVC_IRQ
+       default y
+       help
+         PowerNV machines running under OPAL need that driver to get a console
+
 config HVC_RTAS
        bool "IBM RTAS Console support"
        depends on PPC_RTAS
index e292053..89abf40 100644 (file)
@@ -1,4 +1,5 @@
 obj-$(CONFIG_HVC_CONSOLE)      += hvc_vio.o hvsi_lib.o
+obj-$(CONFIG_HVC_OPAL)         += hvc_opal.o hvsi_lib.o
 obj-$(CONFIG_HVC_OLD_HVSI)     += hvsi.o
 obj-$(CONFIG_HVC_ISERIES)      += hvc_iseries.o
 obj-$(CONFIG_HVC_RTAS)         += hvc_rtas.o
diff --git a/drivers/tty/hvc/hvc_opal.c b/drivers/tty/hvc/hvc_opal.c
new file mode 100644 (file)
index 0000000..7b38512
--- /dev/null
@@ -0,0 +1,424 @@
+/*
+ * opal driver interface to hvc_console.c
+ *
+ * Copyright 2011 Benjamin Herrenschmidt <benh@kernel.crashing.org>, 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.
+ *
+ * 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
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/console.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+
+#include <asm/hvconsole.h>
+#include <asm/prom.h>
+#include <asm/firmware.h>
+#include <asm/hvsi.h>
+#include <asm/udbg.h>
+#include <asm/opal.h>
+
+#include "hvc_console.h"
+
+static const char hvc_opal_name[] = "hvc_opal";
+
+static struct of_device_id hvc_opal_match[] __devinitdata = {
+       { .name = "serial", .compatible = "ibm,opal-console-raw" },
+       { .name = "serial", .compatible = "ibm,opal-console-hvsi" },
+       { },
+};
+
+typedef enum hv_protocol {
+       HV_PROTOCOL_RAW,
+       HV_PROTOCOL_HVSI
+} hv_protocol_t;
+
+struct hvc_opal_priv {
+       hv_protocol_t           proto;  /* Raw data or HVSI packets */
+       struct hvsi_priv        hvsi;   /* HVSI specific data */
+};
+static struct hvc_opal_priv *hvc_opal_privs[MAX_NR_HVC_CONSOLES];
+
+/* For early boot console */
+static struct hvc_opal_priv hvc_opal_boot_priv;
+static u32 hvc_opal_boot_termno;
+
+static const struct hv_ops hvc_opal_raw_ops = {
+       .get_chars = opal_get_chars,
+       .put_chars = opal_put_chars,
+       .notifier_add = notifier_add_irq,
+       .notifier_del = notifier_del_irq,
+       .notifier_hangup = notifier_hangup_irq,
+};
+
+static int hvc_opal_hvsi_get_chars(uint32_t vtermno, char *buf, int count)
+{
+       struct hvc_opal_priv *pv = hvc_opal_privs[vtermno];
+
+       if (WARN_ON(!pv))
+               return -ENODEV;
+
+       return hvsilib_get_chars(&pv->hvsi, buf, count);
+}
+
+static int hvc_opal_hvsi_put_chars(uint32_t vtermno, const char *buf, int count)
+{
+       struct hvc_opal_priv *pv = hvc_opal_privs[vtermno];
+
+       if (WARN_ON(!pv))
+               return -ENODEV;
+
+       return hvsilib_put_chars(&pv->hvsi, buf, count);
+}
+
+static int hvc_opal_hvsi_open(struct hvc_struct *hp, int data)
+{
+       struct hvc_opal_priv *pv = hvc_opal_privs[hp->vtermno];
+       int rc;
+
+       pr_devel("HVSI@%x: do open !\n", hp->vtermno);
+
+       rc = notifier_add_irq(hp, data);
+       if (rc)
+               return rc;
+
+       return hvsilib_open(&pv->hvsi, hp);
+}
+
+static void hvc_opal_hvsi_close(struct hvc_struct *hp, int data)
+{
+       struct hvc_opal_priv *pv = hvc_opal_privs[hp->vtermno];
+
+       pr_devel("HVSI@%x: do close !\n", hp->vtermno);
+
+       hvsilib_close(&pv->hvsi, hp);
+
+       notifier_del_irq(hp, data);
+}
+
+void hvc_opal_hvsi_hangup(struct hvc_struct *hp, int data)
+{
+       struct hvc_opal_priv *pv = hvc_opal_privs[hp->vtermno];
+
+       pr_devel("HVSI@%x: do hangup !\n", hp->vtermno);
+
+       hvsilib_close(&pv->hvsi, hp);
+
+       notifier_hangup_irq(hp, data);
+}
+
+static int hvc_opal_hvsi_tiocmget(struct hvc_struct *hp)
+{
+       struct hvc_opal_priv *pv = hvc_opal_privs[hp->vtermno];
+
+       if (!pv)
+               return -EINVAL;
+       return pv->hvsi.mctrl;
+}
+
+static int hvc_opal_hvsi_tiocmset(struct hvc_struct *hp, unsigned int set,
+                               unsigned int clear)
+{
+       struct hvc_opal_priv *pv = hvc_opal_privs[hp->vtermno];
+
+       pr_devel("HVSI@%x: Set modem control, set=%x,clr=%x\n",
+                hp->vtermno, set, clear);
+
+       if (set & TIOCM_DTR)
+               hvsilib_write_mctrl(&pv->hvsi, 1);
+       else if (clear & TIOCM_DTR)
+               hvsilib_write_mctrl(&pv->hvsi, 0);
+
+       return 0;
+}
+
+static const struct hv_ops hvc_opal_hvsi_ops = {
+       .get_chars = hvc_opal_hvsi_get_chars,
+       .put_chars = hvc_opal_hvsi_put_chars,
+       .notifier_add = hvc_opal_hvsi_open,
+       .notifier_del = hvc_opal_hvsi_close,
+       .notifier_hangup = hvc_opal_hvsi_hangup,
+       .tiocmget = hvc_opal_hvsi_tiocmget,
+       .tiocmset = hvc_opal_hvsi_tiocmset,
+};
+
+static int __devinit hvc_opal_probe(struct platform_device *dev)
+{
+       const struct hv_ops *ops;
+       struct hvc_struct *hp;
+       struct hvc_opal_priv *pv;
+       hv_protocol_t proto;
+       unsigned int termno, boot = 0;
+       const __be32 *reg;
+
+       if (of_device_is_compatible(dev->dev.of_node, "ibm,opal-console-raw")) {
+               proto = HV_PROTOCOL_RAW;
+               ops = &hvc_opal_raw_ops;
+       } else if (of_device_is_compatible(dev->dev.of_node,
+                                          "ibm,opal-console-hvsi")) {
+               proto = HV_PROTOCOL_HVSI;
+               ops = &hvc_opal_hvsi_ops;
+       } else {
+               pr_err("hvc_opal: Unkown protocol for %s\n",
+                      dev->dev.of_node->full_name);
+               return -ENXIO;
+       }
+
+       reg = of_get_property(dev->dev.of_node, "reg", NULL);
+       termno = reg ? be32_to_cpup(reg) : 0;
+
+       /* Is it our boot one ? */
+       if (hvc_opal_privs[termno] == &hvc_opal_boot_priv) {
+               pv = hvc_opal_privs[termno];
+               boot = 1;
+       } else if (hvc_opal_privs[termno] == NULL) {
+               pv = kzalloc(sizeof(struct hvc_opal_priv), GFP_KERNEL);
+               if (!pv)
+                       return -ENOMEM;
+               pv->proto = proto;
+               hvc_opal_privs[termno] = pv;
+               if (proto == HV_PROTOCOL_HVSI)
+                       hvsilib_init(&pv->hvsi, opal_get_chars, opal_put_chars,
+                                    termno, 0);
+
+               /* Instanciate now to establish a mapping index==vtermno */
+               hvc_instantiate(termno, termno, ops);
+       } else {
+               pr_err("hvc_opal: Device %s has duplicate terminal number #%d\n",
+                      dev->dev.of_node->full_name, termno);
+               return -ENXIO;
+       }
+
+       pr_info("hvc%d: %s protocol on %s%s\n", termno,
+               proto == HV_PROTOCOL_RAW ? "raw" : "hvsi",
+               dev->dev.of_node->full_name,
+               boot ? " (boot console)" : "");
+
+       /* We don't do IRQ yet */
+       hp = hvc_alloc(termno, 0, ops, MAX_VIO_PUT_CHARS);
+       if (IS_ERR(hp))
+               return PTR_ERR(hp);
+       dev_set_drvdata(&dev->dev, hp);
+
+       return 0;
+}
+
+static int __devexit hvc_opal_remove(struct platform_device *dev)
+{
+       struct hvc_struct *hp = dev_get_drvdata(&dev->dev);
+       int rc, termno;
+
+       termno = hp->vtermno;
+       rc = hvc_remove(hp);
+       if (rc == 0) {
+               if (hvc_opal_privs[termno] != &hvc_opal_boot_priv)
+                       kfree(hvc_opal_privs[termno]);
+               hvc_opal_privs[termno] = NULL;
+       }
+       return rc;
+}
+
+static struct platform_driver hvc_opal_driver = {
+       .probe          = hvc_opal_probe,
+       .remove         = __devexit_p(hvc_opal_remove),
+       .driver         = {
+               .name   = hvc_opal_name,
+               .owner  = THIS_MODULE,
+               .of_match_table = hvc_opal_match,
+       }
+};
+
+static int __init hvc_opal_init(void)
+{
+       if (!firmware_has_feature(FW_FEATURE_OPAL))
+               return -ENODEV;
+
+       /* Register as a vio device to receive callbacks */
+       return platform_driver_register(&hvc_opal_driver);
+}
+module_init(hvc_opal_init);
+
+static void __exit hvc_opal_exit(void)
+{
+       platform_driver_unregister(&hvc_opal_driver);
+}
+module_exit(hvc_opal_exit);
+
+static void udbg_opal_putc(char c)
+{
+       unsigned int termno = hvc_opal_boot_termno;
+       int count = -1;
+
+       if (c == '\n')
+               udbg_opal_putc('\r');
+
+       do {
+               switch(hvc_opal_boot_priv.proto) {
+               case HV_PROTOCOL_RAW:
+                       count = opal_put_chars(termno, &c, 1);
+                       break;
+               case HV_PROTOCOL_HVSI:
+                       count = hvc_opal_hvsi_put_chars(termno, &c, 1);
+                       break;
+               }
+       } while(count == 0 || count == -EAGAIN);
+}
+
+static int udbg_opal_getc_poll(void)
+{
+       unsigned int termno = hvc_opal_boot_termno;
+       int rc = 0;
+       char c;
+
+       switch(hvc_opal_boot_priv.proto) {
+       case HV_PROTOCOL_RAW:
+               rc = opal_get_chars(termno, &c, 1);
+               break;
+       case HV_PROTOCOL_HVSI:
+               rc = hvc_opal_hvsi_get_chars(termno, &c, 1);
+               break;
+       }
+       if (!rc)
+               return -1;
+       return c;
+}
+
+static int udbg_opal_getc(void)
+{
+       int ch;
+       for (;;) {
+               ch = udbg_opal_getc_poll();
+               if (ch == -1) {
+                       /* This shouldn't be needed...but... */
+                       volatile unsigned long delay;
+                       for (delay=0; delay < 2000000; delay++)
+                               ;
+               } else {
+                       return ch;
+               }
+       }
+}
+
+static void udbg_init_opal_common(void)
+{
+       udbg_putc = udbg_opal_putc;
+       udbg_getc = udbg_opal_getc;
+       udbg_getc_poll = udbg_opal_getc_poll;
+       tb_ticks_per_usec = 0x200; /* Make udelay not suck */
+}
+
+void __init hvc_opal_init_early(void)
+{
+       struct device_node *stdout_node = NULL;
+       const u32 *termno;
+       const char *name = NULL;
+       const struct hv_ops *ops;
+       u32 index;
+
+       /* find the boot console from /chosen/stdout */
+       if (of_chosen)
+               name = of_get_property(of_chosen, "linux,stdout-path", NULL);
+       if (name) {
+               stdout_node = of_find_node_by_path(name);
+               if (!stdout_node) {
+                       pr_err("hvc_opal: Failed to locate default console!\n");
+                       return;
+               }
+       } else {
+               struct device_node *opal, *np;
+
+               /* Current OPAL takeover doesn't provide the stdout
+                * path, so we hard wire it
+                */
+               opal = of_find_node_by_path("/ibm,opal/consoles");
+               if (opal)
+                       pr_devel("hvc_opal: Found consoles in new location\n");
+               if (!opal) {
+                       opal = of_find_node_by_path("/ibm,opal");
+                       if (opal)
+                               pr_devel("hvc_opal: "
+                                        "Found consoles in old location\n");
+               }
+               if (!opal)
+                       return;
+               for_each_child_of_node(opal, np) {
+                       if (!strcmp(np->name, "serial")) {
+                               stdout_node = np;
+                               break;
+                       }
+               }
+               of_node_put(opal);
+       }
+       if (!stdout_node)
+               return;
+       termno = of_get_property(stdout_node, "reg", NULL);
+       index = termno ? *termno : 0;
+       if (index >= MAX_NR_HVC_CONSOLES)
+               return;
+       hvc_opal_privs[index] = &hvc_opal_boot_priv;
+
+       /* Check the protocol */
+       if (of_device_is_compatible(stdout_node, "ibm,opal-console-raw")) {
+               hvc_opal_boot_priv.proto = HV_PROTOCOL_RAW;
+               ops = &hvc_opal_raw_ops;
+               pr_devel("hvc_opal: Found RAW console\n");
+       }
+       else if (of_device_is_compatible(stdout_node,"ibm,opal-console-hvsi")) {
+               hvc_opal_boot_priv.proto = HV_PROTOCOL_HVSI;
+               ops = &hvc_opal_hvsi_ops;
+               hvsilib_init(&hvc_opal_boot_priv.hvsi, opal_get_chars,
+                            opal_put_chars, index, 1);
+               /* HVSI, perform the handshake now */
+               hvsilib_establish(&hvc_opal_boot_priv.hvsi);
+               pr_devel("hvc_opal: Found HVSI console\n");
+       } else
+               goto out;
+       hvc_opal_boot_termno = index;
+       udbg_init_opal_common();
+       add_preferred_console("hvc", index, NULL);
+       hvc_instantiate(index, index, ops);
+out:
+       of_node_put(stdout_node);
+}
+
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL_RAW
+void __init udbg_init_debug_opal(void)
+{
+       u32 index = CONFIG_PPC_EARLY_DEBUG_OPAL_VTERMNO;
+       hvc_opal_privs[index] = &hvc_opal_boot_priv;
+       hvc_opal_boot_priv.proto = HV_PROTOCOL_RAW;
+       hvc_opal_boot_termno = index;
+       udbg_init_opal_common();
+}
+#endif /* CONFIG_PPC_EARLY_DEBUG_OPAL_RAW */
+
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL_HVSI
+void __init udbg_init_debug_opal_hvsi(void)
+{
+       u32 index = CONFIG_PPC_EARLY_DEBUG_OPAL_VTERMNO;
+       hvc_opal_privs[index] = &hvc_opal_boot_priv;
+       hvc_opal_boot_termno = index;
+       udbg_init_opal_common();
+       hvsilib_init(&hvc_opal_boot_priv.hvsi, opal_get_chars, opal_put_chars,
+                    index, 1);
+       hvsilib_establish(&hvc_opal_boot_priv.hvsi);
+}
+#endif /* CONFIG_PPC_EARLY_DEBUG_OPAL_HVSI */
index 55882b5..b9040be 100644 (file)
@@ -1532,7 +1532,7 @@ static int __devinit hvcs_initialize(void)
                goto register_fail;
        }
 
-       hvcs_pi_buff = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       hvcs_pi_buff = (unsigned long *) __get_free_page(GFP_KERNEL);
        if (!hvcs_pi_buff) {
                rc = -ENOMEM;
                goto buff_alloc_fail;
@@ -1548,7 +1548,7 @@ static int __devinit hvcs_initialize(void)
        return 0;
 
 kthread_fail:
-       kfree(hvcs_pi_buff);
+       free_page((unsigned long)hvcs_pi_buff);
 buff_alloc_fail:
        tty_unregister_driver(hvcs_tty_driver);
 register_fail:
@@ -1597,7 +1597,7 @@ static void __exit hvcs_module_exit(void)
        kthread_stop(hvcs_task);
 
        spin_lock(&hvcs_pi_lock);
-       kfree(hvcs_pi_buff);
+       free_page((unsigned long)hvcs_pi_buff);
        hvcs_pi_buff = NULL;
        spin_unlock(&hvcs_pi_lock);
 
index bd9b098..6f4dd83 100644 (file)
@@ -183,7 +183,7 @@ int hvsilib_get_chars(struct hvsi_priv *pv, char *buf, int count)
        unsigned int tries, read = 0;
 
        if (WARN_ON(!pv))
-               return 0;
+               return -ENXIO;
 
        /* If we aren't open, don't do anything in order to avoid races
         * with connection establishment. The hvc core will call this
@@ -234,7 +234,7 @@ int hvsilib_put_chars(struct hvsi_priv *pv, const char *buf, int count)
        int rc, adjcount = min(count, HVSI_MAX_OUTGOING_DATA);
 
        if (WARN_ON(!pv))
-               return 0;
+               return -ENODEV;
 
        dp.hdr.type = VS_DATA_PACKET_HEADER;
        dp.hdr.len = adjcount + sizeof(struct hvsi_header);
index a87a56c..eeadf1b 100644 (file)
@@ -450,24 +450,6 @@ static void au_serial_out(struct uart_port *p, int offset, int value)
        __raw_writel(value, p->membase + offset);
 }
 
-static unsigned int tsi_serial_in(struct uart_port *p, int offset)
-{
-       unsigned int tmp;
-       offset = map_8250_in_reg(p, offset) << p->regshift;
-       if (offset == UART_IIR) {
-               tmp = readl(p->membase + (UART_IIR & ~3));
-               return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */
-       } else
-               return readb(p->membase + offset);
-}
-
-static void tsi_serial_out(struct uart_port *p, int offset, int value)
-{
-       offset = map_8250_out_reg(p, offset) << p->regshift;
-       if (!((offset == UART_IER) && (value & UART_IER_UUE)))
-               writeb(value, p->membase + offset);
-}
-
 static unsigned int io_serial_in(struct uart_port *p, int offset)
 {
        offset = map_8250_in_reg(p, offset) << p->regshift;
@@ -508,11 +490,6 @@ static void set_io_from_upio(struct uart_port *p)
                p->serial_out = au_serial_out;
                break;
 
-       case UPIO_TSI:
-               p->serial_in = tsi_serial_in;
-               p->serial_out = tsi_serial_out;
-               break;
-
        default:
                p->serial_in = io_serial_in;
                p->serial_out = io_serial_out;
index 3d91621..4939e0c 100644 (file)
@@ -706,6 +706,7 @@ static const struct file_operations fsl_hv_fops = {
        .poll = fsl_hv_poll,
        .read = fsl_hv_read,
        .unlocked_ioctl = fsl_hv_ioctl,
+       .compat_ioctl = fsl_hv_ioctl,
 };
 
 static struct miscdevice fsl_hv_misc_dev = {
index be86ae1..e13117c 100644 (file)
@@ -42,6 +42,9 @@ struct dma_map_ops {
        int (*mapping_error)(struct device *dev, dma_addr_t dma_addr);
        int (*dma_supported)(struct device *dev, u64 mask);
        int (*set_dma_mask)(struct device *dev, u64 mask);
+#ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK
+       u64 (*get_required_mask)(struct device *dev);
+#endif
        int is_phys;
 };
 
index fc839bf..e26db03 100644 (file)
@@ -201,6 +201,10 @@ int arch_update_cpu_topology(void);
        .balance_interval       = 64,                                   \
 }
 
+#ifndef SD_NODES_PER_DOMAIN
+#define SD_NODES_PER_DOMAIN 16
+#endif
+
 #ifdef CONFIG_SCHED_BOOK
 #ifndef SD_BOOK_INIT
 #error Please define an appropriate SD_BOOK_INIT in include/asm/topology.h!!!
index d87c6e5..0e9344a 100644 (file)
@@ -7087,8 +7087,6 @@ static int __init isolated_cpu_setup(char *str)
 
 __setup("isolcpus=", isolated_cpu_setup);
 
-#define SD_NODES_PER_DOMAIN 16
-
 #ifdef CONFIG_NUMA
 
 /**