Browse Source

Merge commit 'kumar/kumar-next'

Benjamin Herrenschmidt 16 years ago
parent
commit
1263965f29
66 changed files with 900 additions and 174 deletions
  1. 40 0
      Documentation/powerpc/dts-bindings/fsl/83xx-512x-pci.txt
  2. 11 2
      Documentation/powerpc/dts-bindings/fsl/dma.txt
  3. 14 6
      Documentation/powerpc/dts-bindings/fsl/ssi.txt
  4. 37 4
      arch/powerpc/boot/dts/gef_sbc610.dts
  5. 2 1
      arch/powerpc/boot/dts/mpc5121ads.dts
  6. 2 1
      arch/powerpc/boot/dts/mpc8313erdb.dts
  7. 2 1
      arch/powerpc/boot/dts/mpc8315erdb.dts
  8. 2 1
      arch/powerpc/boot/dts/mpc832x_mds.dts
  9. 2 1
      arch/powerpc/boot/dts/mpc832x_rdb.dts
  10. 4 2
      arch/powerpc/boot/dts/mpc8349emitx.dts
  11. 2 1
      arch/powerpc/boot/dts/mpc8349emitxgp.dts
  12. 4 2
      arch/powerpc/boot/dts/mpc834x_mds.dts
  13. 2 1
      arch/powerpc/boot/dts/mpc836x_mds.dts
  14. 14 1
      arch/powerpc/boot/dts/mpc836x_rdk.dts
  15. 9 1
      arch/powerpc/boot/dts/mpc8377_mds.dts
  16. 2 1
      arch/powerpc/boot/dts/mpc8377_rdb.dts
  17. 9 1
      arch/powerpc/boot/dts/mpc8378_mds.dts
  18. 2 1
      arch/powerpc/boot/dts/mpc8378_rdb.dts
  19. 9 1
      arch/powerpc/boot/dts/mpc8379_mds.dts
  20. 2 1
      arch/powerpc/boot/dts/mpc8379_rdb.dts
  21. 2 0
      arch/powerpc/boot/dts/mpc8536ds.dts
  22. 2 2
      arch/powerpc/boot/dts/mpc8610_hpcd.dts
  23. 2 1
      arch/powerpc/boot/dts/sbc8349.dts
  24. 2 0
      arch/powerpc/configs/83xx/asp8347_defconfig
  25. 2 0
      arch/powerpc/configs/83xx/mpc8313_rdb_defconfig
  26. 2 0
      arch/powerpc/configs/83xx/mpc8315_rdb_defconfig
  27. 2 0
      arch/powerpc/configs/83xx/mpc832x_mds_defconfig
  28. 2 0
      arch/powerpc/configs/83xx/mpc832x_rdb_defconfig
  29. 2 0
      arch/powerpc/configs/83xx/mpc834x_itx_defconfig
  30. 2 0
      arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig
  31. 2 0
      arch/powerpc/configs/83xx/mpc834x_mds_defconfig
  32. 2 0
      arch/powerpc/configs/83xx/mpc836x_mds_defconfig
  33. 2 0
      arch/powerpc/configs/83xx/mpc836x_rdk_defconfig
  34. 2 0
      arch/powerpc/configs/83xx/mpc837x_mds_defconfig
  35. 2 0
      arch/powerpc/configs/83xx/mpc837x_rdb_defconfig
  36. 2 0
      arch/powerpc/configs/83xx/sbc834x_defconfig
  37. 4 1
      arch/powerpc/configs/86xx/gef_sbc610_defconfig
  38. 2 0
      arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
  39. 2 0
      arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig
  40. 2 0
      arch/powerpc/configs/86xx/sbc8641d_defconfig
  41. 2 0
      arch/powerpc/configs/ep8248e_defconfig
  42. 2 0
      arch/powerpc/configs/mpc8272_ads_defconfig
  43. 2 0
      arch/powerpc/configs/mpc83xx_defconfig
  44. 2 0
      arch/powerpc/configs/pq2fads_defconfig
  45. 4 44
      arch/powerpc/include/asm/fsl_lbc.h
  46. 0 4
      arch/powerpc/kernel/head_fsl_booke.S
  47. 3 2
      arch/powerpc/kernel/pci_32.c
  48. 2 0
      arch/powerpc/platforms/512x/Kconfig
  49. 10 0
      arch/powerpc/platforms/512x/mpc5121_ads.c
  50. 0 5
      arch/powerpc/platforms/83xx/Kconfig
  51. 7 1
      arch/powerpc/platforms/83xx/mpc837x_mds.c
  52. 0 1
      arch/powerpc/platforms/85xx/Kconfig
  53. 1 1
      arch/powerpc/platforms/86xx/Makefile
  54. 258 0
      arch/powerpc/platforms/86xx/gef_pic.c
  55. 11 0
      arch/powerpc/platforms/86xx/gef_pic.h
  56. 64 1
      arch/powerpc/platforms/86xx/gef_sbc610.c
  57. 0 1
      arch/powerpc/platforms/86xx/mpc8610_hpcd.c
  58. 11 1
      arch/powerpc/platforms/Kconfig
  59. 49 4
      arch/powerpc/sysdev/fsl_lbc.c
  60. 37 21
      arch/powerpc/sysdev/fsl_pci.c
  61. 1 37
      arch/powerpc/sysdev/fsl_soc.c
  62. 0 8
      arch/powerpc/sysdev/fsl_soc.h
  63. 0 9
      arch/powerpc/sysdev/qe_lib/Kconfig
  64. 11 0
      drivers/i2c/chips/Kconfig
  65. 1 0
      drivers/i2c/chips/Makefile
  66. 209 0
      drivers/i2c/chips/mcu_mpc8349emitx.c

+ 40 - 0
Documentation/powerpc/dts-bindings/fsl/83xx-512x-pci.txt

@@ -0,0 +1,40 @@
+* Freescale 83xx and 512x PCI bridges
+
+Freescale 83xx and 512x SOCs include the same pci bridge core.
+
+83xx/512x specific notes:
+- reg: should contain two address length tuples
+    The first is for the internal pci bridge registers
+    The second is for the pci config space access registers
+
+Example (MPC8313ERDB)
+	pci0: pci@e0008500 {
+		cell-index = <1>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+				/* IDSEL 0x0E -mini PCI */
+				 0x7000 0x0 0x0 0x1 &ipic 18 0x8
+				 0x7000 0x0 0x0 0x2 &ipic 18 0x8
+				 0x7000 0x0 0x0 0x3 &ipic 18 0x8
+				 0x7000 0x0 0x0 0x4 &ipic 18 0x8
+
+				/* IDSEL 0x0F - PCI slot */
+				 0x7800 0x0 0x0 0x1 &ipic 17 0x8
+				 0x7800 0x0 0x0 0x2 &ipic 18 0x8
+				 0x7800 0x0 0x0 0x3 &ipic 17 0x8
+				 0x7800 0x0 0x0 0x4 &ipic 18 0x8>;
+		interrupt-parent = <&ipic>;
+		interrupts = <66 0x8>;
+		bus-range = <0x0 0x0>;
+		ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000
+			  0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000
+			  0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
+		clock-frequency = <66666666>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xe0008500 0x100		/* internal registers */
+		       0xe0008300 0x8>;		/* config space access registers */
+		compatible = "fsl,mpc8349-pci";
+		device_type = "pci";
+	};

+ 11 - 2
Documentation/powerpc/dts-bindings/fsl/dma.txt

@@ -20,7 +20,7 @@ Required properties:
         - compatible        : compatible list, contains 2 entries, first is
 			 "fsl,CHIP-dma-channel", where CHIP is the processor
 			 (mpc8349, mpc8350, etc.) and the second is
-			 "fsl,elo-dma-channel"
+			 "fsl,elo-dma-channel". However, see note below.
         - reg               : <registers mapping for channel>
         - cell-index        : dma channel index starts at 0.
 
@@ -82,7 +82,7 @@ Required properties:
         - compatible        : compatible list, contains 2 entries, first is
 			 "fsl,CHIP-dma-channel", where CHIP is the processor
 			 (mpc8540, mpc8560, etc.) and the second is
-			 "fsl,eloplus-dma-channel"
+			 "fsl,eloplus-dma-channel". However, see note below.
         - cell-index        : dma channel index starts at 0.
         - reg               : <registers mapping for channel>
         - interrupts        : <interrupt mapping for DMA channel IRQ>
@@ -125,3 +125,12 @@ Example:
 			interrupts = <17 2>;
 		};
 	};
+
+Note on DMA channel compatible properties: The compatible property must say
+"fsl,elo-dma-channel" or "fsl,eloplus-dma-channel" to be used by the Elo DMA
+driver (fsldma).  Any DMA channel used by fsldma cannot be used by another
+DMA driver, such as the SSI sound drivers for the MPC8610.  Therefore, any DMA
+channel that should be used for another driver should not use
+"fsl,elo-dma-channel" or "fsl,eloplus-dma-channel".  For the SSI drivers, for
+example, the compatible property should be "fsl,ssi-dma-channel".  See ssi.txt
+for more information.

+ 14 - 6
Documentation/powerpc/dts-bindings/fsl/ssi.txt

@@ -24,12 +24,12 @@ Required properties:
 		    "rj-master" - r.j., SSI is clock master
 		    "ac97-slave" - AC97 mode, SSI is clock slave
 		    "ac97-master" - AC97 mode, SSI is clock master
-- fsl,playback-dma: phandle to a DMA node for the DMA channel to use for
-		    playback of audio.  This is typically dictated by SOC
-		    design.  See the notes below.
-- fsl,capture-dma:  phandle to a DMA node for the DMA channel to use for
-		    capture (recording) of audio.  This is typically dictated
-		    by SOC design.  See the notes below.
+- fsl,playback-dma: phandle to a node for the DMA channel to use for
+                    playback of audio.  This is typically dictated by SOC
+                    design.  See the notes below.
+- fsl,capture-dma:  phandle to a node for the DMA channel to use for
+                    capture (recording) of audio.  This is typically dictated
+                    by SOC design.  See the notes below.
 
 Optional properties:
 - codec-handle	  : phandle to a 'codec' node that defines an audio
@@ -51,3 +51,11 @@ playback and DMA channel 1 for capture.  SSI2 must use DMA channel 2 for
 playback and DMA channel 3 for capture.  The developer can choose which
 DMA controller to use, but the channels themselves are hard-wired.  The
 purpose of these two properties is to represent this hardware design.
+
+The device tree nodes for the DMA channels that are referenced by
+"fsl,playback-dma" and "fsl,capture-dma" must be marked as compatible with
+"fsl,ssi-dma-channel".  The SOC-specific compatible string (e.g.
+"fsl,mpc8610-dma-channel") can remain.  If these nodes are left as
+"fsl,elo-dma-channel" or "fsl,eloplus-dma-channel", then the generic Elo DMA
+drivers (fsldma) will attempt to use them, and it will conflict with the
+sound drivers.

+ 37 - 4
arch/powerpc/boot/dts/gef_sbc610.dts

@@ -67,6 +67,39 @@
 		reg = <0x0 0x40000000>;	// set by uboot
 	};
 
+	localbus@fef05000 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc8641-localbus", "simple-bus";
+		reg = <0xf8005000 0x1000>;
+		interrupts = <19 2>;
+		interrupt-parent = <&mpic>;
+
+		ranges = <0 0 0xff000000 0x01000000     // 16MB Boot flash
+			  1 0 0xe8000000 0x08000000     // Paged Flash 0
+			  2 0 0xe0000000 0x08000000     // Paged Flash 1
+			  3 0 0xfc100000 0x00020000     // NVRAM
+			  4 0 0xfc000000 0x00008000     // FPGA
+			  5 0 0xfc008000 0x00008000     // AFIX FPGA
+			  6 0 0xfd000000 0x00800000     // IO FPGA (8-bit)
+			  7 0 0xfd800000 0x00800000>;   // IO FPGA (32-bit)
+
+		fpga@4,0 {
+			compatible = "gef,fpga-regs";
+			reg = <0x4 0x0 0x40>;
+		};
+		gef_pic: pic@4,4000 {
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			compatible = "gef,fpga-pic";
+			reg = <0x4 0x4000 0x20>;
+			interrupts = <0x8
+				      0x9>;
+			interrupt-parent = <&mpic>;
+
+		};
+	};
+
 	soc@fef00000 {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -150,13 +183,13 @@
 			reg = <0x24520 0x20>;
 
 			phy0: ethernet-phy@0 {
-				interrupt-parent = <&mpic>;
-				interrupts = <0x0 0x1>;
+				interrupt-parent = <&gef_pic>;
+				interrupts = <0x9 0x4>;
 				reg = <1>;
 			};
 			phy2: ethernet-phy@2 {
-				interrupt-parent = <&mpic>;
-				interrupts = <0x0 0x1>;
+				interrupt-parent = <&gef_pic>;
+				interrupts = <0x8 0x4>;
 				reg = <3>;
 			};
 		};

+ 2 - 1
arch/powerpc/boot/dts/mpc5121ads.dts

@@ -403,7 +403,8 @@
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
-		reg = <0x80008500 0x100>;
+		reg = <0x80008500 0x100		/* internal registers */
+		       0x80008300 0x8>;		/* config space access registers */
 		compatible = "fsl,mpc5121-pci";
 		device_type = "pci";
 	};

+ 2 - 1
arch/powerpc/boot/dts/mpc8313erdb.dts

@@ -363,7 +363,8 @@
 			#interrupt-cells = <1>;
 			#size-cells = <2>;
 			#address-cells = <3>;
-			reg = <0xe0008500 0x100>;
+			reg = <0xe0008500 0x100		/* internal registers */
+			       0xe0008300 0x8>;		/* config space access registers */
 			compatible = "fsl,mpc8349-pci";
 			device_type = "pci";
 		};

+ 2 - 1
arch/powerpc/boot/dts/mpc8315erdb.dts

@@ -318,7 +318,8 @@
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
-		reg = <0xe0008500 0x100>;
+		reg = <0xe0008500 0x100		/* internal registers */
+		       0xe0008300 0x8>;		/* config space access registers */
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};

+ 2 - 1
arch/powerpc/boot/dts/mpc832x_mds.dts

@@ -423,7 +423,8 @@
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
-		reg = <0xe0008500 0x100>;
+		reg = <0xe0008500 0x100		/* internal registers */
+		       0xe0008300 0x8>;		/* config space access registers */
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};

+ 2 - 1
arch/powerpc/boot/dts/mpc832x_rdb.dts

@@ -331,7 +331,8 @@
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
-		reg = <0xe0008500 0x100>;
+		reg = <0xe0008500 0x100		/* internal registers */
+		       0xe0008300 0x8>;		/* config space access registers */
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};

+ 4 - 2
arch/powerpc/boot/dts/mpc8349emitx.dts

@@ -254,7 +254,8 @@
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
-		reg = <0xe0008500 0x100>;
+		reg = <0xe0008500 0x100		/* internal registers */
+		       0xe0008300 0x8>;		/* config space access registers */
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};
@@ -280,7 +281,8 @@
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
-		reg = <0xe0008600 0x100>;
+		reg = <0xe0008600 0x100		/* internal registers */
+		       0xe0008380 0x8>;		/* config space access registers */
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};

+ 2 - 1
arch/powerpc/boot/dts/mpc8349emitxgp.dts

@@ -228,7 +228,8 @@
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
-		reg = <0xe0008600 0x100>;
+		reg = <0xe0008600 0x100		/* internal registers */
+		       0xe0008380 0x8>;		/* config space access registers */
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};

+ 4 - 2
arch/powerpc/boot/dts/mpc834x_mds.dts

@@ -315,7 +315,8 @@
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
-		reg = <0xe0008500 0x100>;
+		reg = <0xe0008500 0x100		/* internal registers */
+		       0xe0008300 0x8>;		/* config space access registers */
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};
@@ -376,7 +377,8 @@
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
-		reg = <0xe0008600 0x100>;
+		reg = <0xe0008600 0x100		/* internal registers */
+		       0xe0008380 0x8>;		/* config space access registers */
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};

+ 2 - 1
arch/powerpc/boot/dts/mpc836x_mds.dts

@@ -426,7 +426,8 @@
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
-		reg = <0xe0008500 0x100>;
+		reg = <0xe0008500 0x100		/* internal registers */
+		       0xe0008300 0x8>;		/* config space access registers */
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};

+ 14 - 1
arch/powerpc/boot/dts/mpc836x_rdk.dts

@@ -387,6 +387,18 @@
 			device-width = <1>;
 		};
 
+		upm@1,0 {
+			compatible = "fsl,upm-nand";
+			reg = <1 0 1>;
+			fsl,upm-addr-offset = <16>;
+			fsl,upm-cmd-offset = <8>;
+			gpios = <&qe_pio_e 18 0>;
+
+			flash {
+				compatible = "stm,nand512-a";
+			};
+		};
+
 		display@2,0 {
 			device_type = "display";
 			compatible = "fujitsu,MB86277", "fujitsu,mint";
@@ -409,7 +421,8 @@
 		#interrupt-cells = <1>;
 		device_type = "pci";
 		compatible = "fsl,mpc8360-pci", "fsl,mpc8349-pci";
-		reg = <0xe0008500 0x100>;
+		reg = <0xe0008500 0x100		/* internal registers */
+		       0xe0008300 0x8>;		/* config space access registers */
 		ranges = <0x02000000 0 0x90000000 0x90000000 0 0x10000000
 			  0x42000000 0 0x80000000 0x80000000 0 0x10000000
 			  0x01000000 0 0xe0300000 0xe0300000 0 0x00100000>;

+ 9 - 1
arch/powerpc/boot/dts/mpc8377_mds.dts

@@ -136,6 +136,13 @@
 			interrupts = <14 0x8>;
 			interrupt-parent = <&ipic>;
 			dfsrr;
+
+			rtc@68 {
+				compatible = "dallas,ds1374";
+				reg = <0x68>;
+				interrupts = <19 0x8>;
+				interrupt-parent = <&ipic>;
+			};
 		};
 
 		i2c@3100 {
@@ -378,7 +385,8 @@
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
-		reg = <0xe0008500 0x100>;
+		reg = <0xe0008500 0x100		/* internal registers */
+		       0xe0008300 0x8>;		/* config space access registers */
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};

+ 2 - 1
arch/powerpc/boot/dts/mpc8377_rdb.dts

@@ -319,7 +319,8 @@
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
-		reg = <0xe0008500 0x100>;
+		reg = <0xe0008500 0x100		/* internal registers */
+		       0xe0008300 0x8>;		/* config space access registers */
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};

+ 9 - 1
arch/powerpc/boot/dts/mpc8378_mds.dts

@@ -136,6 +136,13 @@
 			interrupts = <14 0x8>;
 			interrupt-parent = <&ipic>;
 			dfsrr;
+
+			rtc@68 {
+				compatible = "dallas,ds1374";
+				reg = <0x68>;
+				interrupts = <19 0x8>;
+				interrupt-parent = <&ipic>;
+			};
 		};
 
 		i2c@3100 {
@@ -364,7 +371,8 @@
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
-		reg = <0xe0008500 0x100>;
+		reg = <0xe0008500 0x100		/* internal registers */
+		       0xe0008300 0x8>;		/* config space access registers */
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};

+ 2 - 1
arch/powerpc/boot/dts/mpc8378_rdb.dts

@@ -305,7 +305,8 @@
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
-		reg = <0xe0008500 0x100>;
+		reg = <0xe0008500 0x100		/* internal registers */
+		       0xe0008300 0x8>;		/* config space access registers */
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};

+ 9 - 1
arch/powerpc/boot/dts/mpc8379_mds.dts

@@ -136,6 +136,13 @@
 			interrupts = <14 0x8>;
 			interrupt-parent = <&ipic>;
 			dfsrr;
+
+			rtc@68 {
+				compatible = "dallas,ds1374";
+				reg = <0x68>;
+				interrupts = <19 0x8>;
+				interrupt-parent = <&ipic>;
+			};
 		};
 
 		i2c@3100 {
@@ -392,7 +399,8 @@
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
-		reg = <0xe0008500 0x100>;
+		reg = <0xe0008500 0x100		/* internal registers */
+		       0xe0008300 0x8>;		/* config space access registers */
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};

+ 2 - 1
arch/powerpc/boot/dts/mpc8379_rdb.dts

@@ -333,7 +333,8 @@
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
-		reg = <0xe0008500 0x100>;
+		reg = <0xe0008500 0x100		/* internal registers */
+		       0xe0008300 0x8>;		/* config space access registers */
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};

+ 2 - 0
arch/powerpc/boot/dts/mpc8536ds.dts

@@ -91,6 +91,8 @@
 			rtc@68 {
 				compatible = "dallas,ds3232";
 				reg = <0x68>;
+				interrupts = <0 0x1>;
+				interrupt-parent = <&mpic>;
 			};
 		};
 

+ 2 - 2
arch/powerpc/boot/dts/mpc8610_hpcd.dts

@@ -237,7 +237,7 @@
 
 			dma00: dma-channel@0 {
 				compatible = "fsl,mpc8610-dma-channel",
-					"fsl,eloplus-dma-channel";
+					"fsl,ssi-dma-channel";
 				cell-index = <0>;
 				reg = <0x0 0x80>;
 				interrupt-parent = <&mpic>;
@@ -245,7 +245,7 @@
 			};
 			dma01: dma-channel@1 {
 				compatible = "fsl,mpc8610-dma-channel",
-					"fsl,eloplus-dma-channel";
+					"fsl,ssi-dma-channel";
 				cell-index = <1>;
 				reg = <0x80 0x80>;
 				interrupt-parent = <&mpic>;

+ 2 - 1
arch/powerpc/boot/dts/sbc8349.dts

@@ -272,7 +272,8 @@
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
-		reg = <0xe0008500 0x100>;
+		reg = <0xe0008500 0x100		/* internal registers */
+		       0xe0008300 0x8>;		/* config space access registers */
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};

+ 2 - 0
arch/powerpc/configs/83xx/asp8347_defconfig

@@ -164,6 +164,8 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set

+ 2 - 0
arch/powerpc/configs/83xx/mpc8313_rdb_defconfig

@@ -163,6 +163,8 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set

+ 2 - 0
arch/powerpc/configs/83xx/mpc8315_rdb_defconfig

@@ -163,6 +163,8 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set

+ 2 - 0
arch/powerpc/configs/83xx/mpc832x_mds_defconfig

@@ -163,6 +163,8 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set

+ 2 - 0
arch/powerpc/configs/83xx/mpc832x_rdb_defconfig

@@ -163,6 +163,8 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set

+ 2 - 0
arch/powerpc/configs/83xx/mpc834x_itx_defconfig

@@ -163,6 +163,8 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set

+ 2 - 0
arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig

@@ -163,6 +163,8 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set

+ 2 - 0
arch/powerpc/configs/83xx/mpc834x_mds_defconfig

@@ -163,6 +163,8 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set

+ 2 - 0
arch/powerpc/configs/83xx/mpc836x_mds_defconfig

@@ -163,6 +163,8 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set

+ 2 - 0
arch/powerpc/configs/83xx/mpc836x_rdk_defconfig

@@ -164,6 +164,8 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set

+ 2 - 0
arch/powerpc/configs/83xx/mpc837x_mds_defconfig

@@ -164,6 +164,8 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set

+ 2 - 0
arch/powerpc/configs/83xx/mpc837x_rdb_defconfig

@@ -164,6 +164,8 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set

+ 2 - 0
arch/powerpc/configs/83xx/sbc834x_defconfig

@@ -162,6 +162,8 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set

+ 4 - 1
arch/powerpc/configs/86xx/gef_sbc610_defconfig

@@ -156,7 +156,10 @@ CONFIG_CLASSIC_RCU=y
 #
 # Platform support
 #
-# CONFIG_PPC_MULTIPLATFORM is not set
+CONFIG_PPC_MULTIPLATFORM=y
+CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_PPC_82xx is not set
 # CONFIG_PPC_83xx is not set
 CONFIG_PPC_86xx=y

+ 2 - 0
arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig

@@ -165,6 +165,8 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set

+ 2 - 0
arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig

@@ -167,6 +167,8 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set

+ 2 - 0
arch/powerpc/configs/86xx/sbc8641d_defconfig

@@ -166,6 +166,8 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set

+ 2 - 0
arch/powerpc/configs/ep8248e_defconfig

@@ -150,6 +150,8 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set

+ 2 - 0
arch/powerpc/configs/mpc8272_ads_defconfig

@@ -151,6 +151,8 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set

+ 2 - 0
arch/powerpc/configs/mpc83xx_defconfig

@@ -166,6 +166,8 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set

+ 2 - 0
arch/powerpc/configs/pq2fads_defconfig

@@ -152,6 +152,8 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set

+ 4 - 44
arch/powerpc/include/asm/fsl_lbc.h

@@ -23,9 +23,9 @@
 #ifndef __ASM_FSL_LBC_H
 #define __ASM_FSL_LBC_H
 
+#include <linux/compiler.h>
 #include <linux/types.h>
-#include <linux/spinlock.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 struct fsl_lbc_bank {
 	__be32 br;             /**< Base Register  */
@@ -227,9 +227,6 @@ struct fsl_lbc_regs {
 	u8 res8[0xF00];
 };
 
-extern struct fsl_lbc_regs __iomem *fsl_lbc_regs;
-extern spinlock_t fsl_lbc_lock;
-
 /*
  * FSL UPM routines
  */
@@ -268,44 +265,7 @@ static inline void fsl_upm_end_pattern(struct fsl_upm *upm)
 		cpu_relax();
 }
 
-/**
- * fsl_upm_run_pattern - actually run an UPM pattern
- * @upm:	pointer to the fsl_upm structure obtained via fsl_upm_find
- * @io_base:	remapped pointer to where memory access should happen
- * @mar:	MAR register content during pattern execution
- *
- * This function triggers dummy write to the memory specified by the io_base,
- * thus UPM pattern actually executed. Note that mar usage depends on the
- * pre-programmed AMX bits in the UPM RAM.
- */
-static inline int fsl_upm_run_pattern(struct fsl_upm *upm,
-				      void __iomem *io_base, u32 mar)
-{
-	int ret = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&fsl_lbc_lock, flags);
-
-	out_be32(&fsl_lbc_regs->mar, mar << (32 - upm->width));
-
-	switch (upm->width) {
-	case 8:
-		out_8(io_base, 0x0);
-		break;
-	case 16:
-		out_be16(io_base, 0x0);
-		break;
-	case 32:
-		out_be32(io_base, 0x0);
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	spin_unlock_irqrestore(&fsl_lbc_lock, flags);
-
-	return ret;
-}
+extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base,
+			       u32 mar);
 
 #endif /* __ASM_FSL_LBC_H */

+ 0 - 4
arch/powerpc/kernel/head_fsl_booke.S

@@ -656,10 +656,6 @@ interrupt_base:
 
 	bne	2f			/* Bail if permission mismach */
 
-#ifdef CONFIG_PTE_64BIT
-	lwz	r13,0(r12)
-#endif
-
 	/* Jump to common TLB load point */
 	b	finish_tlb_load
 

+ 3 - 2
arch/powerpc/kernel/pci_32.c

@@ -54,11 +54,12 @@ LIST_HEAD(hose_list);
 static int pci_bus_count;
 
 static void
-fixup_hide_host_resource_fsl(struct pci_dev* dev)
+fixup_hide_host_resource_fsl(struct pci_dev *dev)
 {
 	int i, class = dev->class >> 8;
 
-	if ((class == PCI_CLASS_PROCESSOR_POWERPC) &&
+	if ((class == PCI_CLASS_PROCESSOR_POWERPC ||
+	     class == PCI_CLASS_BRIDGE_OTHER) &&
 		(dev->hdr_type == PCI_HEADER_TYPE_NORMAL) &&
 		(dev->bus->parent == NULL)) {
 		for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {

+ 2 - 0
arch/powerpc/platforms/512x/Kconfig

@@ -3,6 +3,8 @@ config PPC_MPC512x
 	select FSL_SOC
 	select IPIC
 	select PPC_CLOCK
+	select PPC_PCI_CHOICE
+	select FSL_PCI if PCI
 
 config PPC_MPC5121
 	bool

+ 10 - 0
arch/powerpc/platforms/512x/mpc5121_ads.c

@@ -22,16 +22,26 @@
 #include <asm/prom.h>
 #include <asm/time.h>
 
+#include <sysdev/fsl_pci.h>
+
 #include "mpc512x.h"
 #include "mpc5121_ads.h"
 
 static void __init mpc5121_ads_setup_arch(void)
 {
+#ifdef CONFIG_PCI
+	struct device_node *np;
+#endif
 	printk(KERN_INFO "MPC5121 ADS board from Freescale Semiconductor\n");
 	/*
 	 * cpld regs are needed early
 	 */
 	mpc5121_ads_cpld_map();
+
+#ifdef CONFIG_PCI
+	for_each_compatible_node(np, "pci", "fsl,mpc5121-pci")
+		mpc83xx_add_bridge(np);
+#endif
 }
 
 static void __init mpc5121_ads_init_IRQ(void)

+ 0 - 5
arch/powerpc/platforms/83xx/Kconfig

@@ -19,7 +19,6 @@ config MPC831x_RDB
 config MPC832x_MDS
 	bool "Freescale MPC832x MDS"
 	select DEFAULT_UIMAGE
-	select QUICC_ENGINE
 	select PPC_MPC832x
 	help
 	  This option enables support for the MPC832x MDS evaluation board.
@@ -27,7 +26,6 @@ config MPC832x_MDS
 config MPC832x_RDB
 	bool "Freescale MPC832x RDB"
 	select DEFAULT_UIMAGE
-	select QUICC_ENGINE
 	select PPC_MPC832x
 	help
 	  This option enables support for the MPC8323 RDB board.
@@ -57,15 +55,12 @@ config MPC834x_ITX
 config MPC836x_MDS
 	bool "Freescale MPC836x MDS"
 	select DEFAULT_UIMAGE
-	select QUICC_ENGINE
 	help
 	  This option enables support for the MPC836x MDS Processor Board.
 
 config MPC836x_RDK
 	bool "Freescale/Logic MPC836x RDK"
 	select DEFAULT_UIMAGE
-	select QUICC_ENGINE
-	select QE_GPIO
 	select FSL_GTM
 	select FSL_LBC
 	help

+ 7 - 1
arch/powerpc/platforms/83xx/mpc837x_mds.c

@@ -85,8 +85,14 @@ static void __init mpc837x_mds_setup_arch(void)
 		ppc_md.progress("mpc837x_mds_setup_arch()", 0);
 
 #ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
+	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+		if (!of_device_is_available(np)) {
+			pr_warning("%s: disabled by the firmware.\n",
+				   np->full_name);
+			continue;
+		}
 		mpc83xx_add_bridge(np);
+	}
 #endif
 	mpc837xmds_usb_cfg();
 }

+ 0 - 1
arch/powerpc/platforms/85xx/Kconfig

@@ -33,7 +33,6 @@ config MPC85xx_CDS
 config MPC85xx_MDS
 	bool "Freescale MPC85xx MDS"
 	select DEFAULT_UIMAGE
-	select QUICC_ENGINE
 	select PHYLIB
 	help
 	  This option enables support for the MPC85xx MDS board

+ 1 - 1
arch/powerpc/platforms/86xx/Makefile

@@ -7,4 +7,4 @@ obj-$(CONFIG_SMP)		+= mpc86xx_smp.o
 obj-$(CONFIG_MPC8641_HPCN)	+= mpc86xx_hpcn.o
 obj-$(CONFIG_SBC8641D)		+= sbc8641d.o
 obj-$(CONFIG_MPC8610_HPCD)	+= mpc8610_hpcd.o
-obj-$(CONFIG_GEF_SBC610)	+= gef_sbc610.o
+obj-$(CONFIG_GEF_SBC610)	+= gef_sbc610.o gef_pic.o

+ 258 - 0
arch/powerpc/platforms/86xx/gef_pic.c

@@ -0,0 +1,258 @@
+/*
+ * Interrupt handling for GE Fanuc's FPGA based PIC
+ *
+ * Author: Martyn Welch <martyn.welch@gefanuc.com>
+ *
+ * 2008 (c) GE Fanuc Intelligent Platforms Embedded Systems, 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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/irq.h>
+
+#include "gef_pic.h"
+
+#define DEBUG
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt...) do { printk(KERN_DEBUG "gef_pic: " fmt); } while (0)
+#else
+#define DBG(fmt...) do { } while (0)
+#endif
+
+#define GEF_PIC_NUM_IRQS	32
+
+/* Interrupt Controller Interface Registers */
+#define GEF_PIC_INTR_STATUS	0x0000
+
+#define GEF_PIC_INTR_MASK(cpu)	(0x0010 + (0x4 * cpu))
+#define GEF_PIC_CPU0_INTR_MASK	GEF_PIC_INTR_MASK(0)
+#define GEF_PIC_CPU1_INTR_MASK	GEF_PIC_INTR_MASK(1)
+
+#define GEF_PIC_MCP_MASK(cpu)	(0x0018 + (0x4 * cpu))
+#define GEF_PIC_CPU0_MCP_MASK	GEF_PIC_MCP_MASK(0)
+#define GEF_PIC_CPU1_MCP_MASK	GEF_PIC_MCP_MASK(1)
+
+#define gef_irq_to_hw(virq)    ((unsigned int)irq_map[virq].hwirq)
+
+
+static DEFINE_SPINLOCK(gef_pic_lock);
+
+static void __iomem *gef_pic_irq_reg_base;
+static struct irq_host *gef_pic_irq_host;
+static int gef_pic_cascade_irq;
+
+/*
+ * Interrupt Controller Handling
+ *
+ * The interrupt controller handles interrupts for most on board interrupts,
+ * apart from PCI interrupts. For example on SBC610:
+ *
+ * 17:31 RO Reserved
+ * 16    RO PCI Express Doorbell 3 Status
+ * 15    RO PCI Express Doorbell 2 Status
+ * 14    RO PCI Express Doorbell 1 Status
+ * 13    RO PCI Express Doorbell 0 Status
+ * 12    RO Real Time Clock Interrupt Status
+ * 11    RO Temperature Interrupt Status
+ * 10    RO Temperature Critical Interrupt Status
+ * 9     RO Ethernet PHY1 Interrupt Status
+ * 8     RO Ethernet PHY3 Interrupt Status
+ * 7     RO PEX8548 Interrupt Status
+ * 6     RO Reserved
+ * 5     RO Watchdog 0 Interrupt Status
+ * 4     RO Watchdog 1 Interrupt Status
+ * 3     RO AXIS Message FIFO A Interrupt Status
+ * 2     RO AXIS Message FIFO B Interrupt Status
+ * 1     RO AXIS Message FIFO C Interrupt Status
+ * 0     RO AXIS Message FIFO D Interrupt Status
+ *
+ * Interrupts can be forwarded to one of two output lines. Nothing
+ * clever is done, so if the masks are incorrectly set, a single input
+ * interrupt could generate interrupts on both output lines!
+ *
+ * The dual lines are there to allow the chained interrupts to be easily
+ * passed into two different cores. We currently do not use this functionality
+ * in this driver.
+ *
+ * Controller can also be configured to generate Machine checks (MCP), again on
+ * two lines, to be attached to two different cores. It is suggested that these
+ * should be masked out.
+ */
+
+void gef_pic_cascade(unsigned int irq, struct irq_desc *desc)
+{
+	unsigned int cascade_irq;
+
+	/*
+	 * See if we actually have an interrupt, call generic handling code if
+	 * we do.
+	 */
+	cascade_irq = gef_pic_get_irq();
+
+	if (cascade_irq != NO_IRQ)
+		generic_handle_irq(cascade_irq);
+
+	desc->chip->eoi(irq);
+
+}
+
+static void gef_pic_mask(unsigned int virq)
+{
+	unsigned long flags;
+	unsigned int hwirq;
+	u32 mask;
+
+	hwirq = gef_irq_to_hw(virq);
+
+	spin_lock_irqsave(&gef_pic_lock, flags);
+	mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
+	mask &= ~(1 << hwirq);
+	out_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0), mask);
+	spin_unlock_irqrestore(&gef_pic_lock, flags);
+}
+
+static void gef_pic_mask_ack(unsigned int virq)
+{
+	/* Don't think we actually have to do anything to ack an interrupt,
+	 * we just need to clear down the devices interrupt and it will go away
+	 */
+	gef_pic_mask(virq);
+}
+
+static void gef_pic_unmask(unsigned int virq)
+{
+	unsigned long flags;
+	unsigned int hwirq;
+	u32 mask;
+
+	hwirq = gef_irq_to_hw(virq);
+
+	spin_lock_irqsave(&gef_pic_lock, flags);
+	mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
+	mask |= (1 << hwirq);
+	out_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0), mask);
+	spin_unlock_irqrestore(&gef_pic_lock, flags);
+}
+
+static struct irq_chip gef_pic_chip = {
+	.typename	= "gefp",
+	.mask		= gef_pic_mask,
+	.mask_ack	= gef_pic_mask_ack,
+	.unmask		= gef_pic_unmask,
+};
+
+
+/* When an interrupt is being configured, this call allows some flexibilty
+ * in deciding which irq_chip structure is used
+ */
+static int gef_pic_host_map(struct irq_host *h, unsigned int virq,
+			  irq_hw_number_t hwirq)
+{
+	/* All interrupts are LEVEL sensitive */
+	get_irq_desc(virq)->status |= IRQ_LEVEL;
+	set_irq_chip_and_handler(virq, &gef_pic_chip, handle_level_irq);
+
+	return 0;
+}
+
+static int gef_pic_host_xlate(struct irq_host *h, struct device_node *ct,
+			    u32 *intspec, unsigned int intsize,
+			    irq_hw_number_t *out_hwirq, unsigned int *out_flags)
+{
+
+	*out_hwirq = intspec[0];
+	if (intsize > 1)
+		*out_flags = intspec[1];
+	else
+		*out_flags = IRQ_TYPE_LEVEL_HIGH;
+
+	return 0;
+}
+
+static struct irq_host_ops gef_pic_host_ops = {
+	.map	= gef_pic_host_map,
+	.xlate	= gef_pic_host_xlate,
+};
+
+
+/*
+ * Initialisation of PIC, this should be called in BSP
+ */
+void __init gef_pic_init(struct device_node *np)
+{
+	unsigned long flags;
+
+	/* Map the devices registers into memory */
+	gef_pic_irq_reg_base = of_iomap(np, 0);
+
+	spin_lock_irqsave(&gef_pic_lock, flags);
+
+	/* Initialise everything as masked. */
+	out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU0_INTR_MASK, 0);
+	out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU1_INTR_MASK, 0);
+
+	out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU0_MCP_MASK, 0);
+	out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU1_MCP_MASK, 0);
+
+	spin_unlock_irqrestore(&gef_pic_lock, flags);
+
+	/* Map controller */
+	gef_pic_cascade_irq = irq_of_parse_and_map(np, 0);
+	if (gef_pic_cascade_irq == NO_IRQ) {
+		printk(KERN_ERR "SBC610: failed to map cascade interrupt");
+		return;
+	}
+
+	/* Setup an irq_host structure */
+	gef_pic_irq_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR,
+					  GEF_PIC_NUM_IRQS,
+					  &gef_pic_host_ops, NO_IRQ);
+	if (gef_pic_irq_host == NULL)
+		return;
+
+	/* Chain with parent controller */
+	set_irq_chained_handler(gef_pic_cascade_irq, gef_pic_cascade);
+}
+
+/*
+ * This is called when we receive an interrupt with apparently comes from this
+ * chip - check, returning the highest interrupt generated or return NO_IRQ
+ */
+unsigned int gef_pic_get_irq(void)
+{
+	u32 cause, mask, active;
+	unsigned int virq = NO_IRQ;
+	int hwirq;
+
+	cause = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_STATUS);
+
+	mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
+
+	active = cause & mask;
+
+	if (active) {
+		for (hwirq = GEF_PIC_NUM_IRQS - 1; hwirq > -1; hwirq--) {
+			if (active & (0x1 << hwirq))
+				break;
+		}
+		virq = irq_linear_revmap(gef_pic_irq_host,
+			(irq_hw_number_t)hwirq);
+	}
+
+	return virq;
+}
+

+ 11 - 0
arch/powerpc/platforms/86xx/gef_pic.h

@@ -0,0 +1,11 @@
+#ifndef __GEF_PIC_H__
+#define __GEF_PIC_H__
+
+#include <linux/init.h>
+
+void gef_pic_cascade(unsigned int, struct irq_desc *);
+unsigned int gef_pic_get_irq(void);
+void gef_pic_init(struct device_node *);
+
+#endif /* __GEF_PIC_H__ */
+

+ 64 - 1
arch/powerpc/platforms/86xx/gef_sbc610.c

@@ -39,6 +39,7 @@
 #include <sysdev/fsl_soc.h>
 
 #include "mpc86xx.h"
+#include "gef_pic.h"
 
 #undef DEBUG
 
@@ -48,8 +49,31 @@
 #define DBG (fmt...) do { } while (0)
 #endif
 
+void __iomem *sbc610_regs;
+
+static void __init gef_sbc610_init_irq(void)
+{
+	struct device_node *cascade_node = NULL;
+
+	mpc86xx_init_irq();
+
+	/*
+	 * There is a simple interrupt handler in the main FPGA, this needs
+	 * to be cascaded into the MPIC
+	 */
+	cascade_node = of_find_compatible_node(NULL, NULL, "gef,fpga-pic");
+	if (!cascade_node) {
+		printk(KERN_WARNING "SBC610: No FPGA PIC\n");
+		return;
+	}
+
+	gef_pic_init(cascade_node);
+	of_node_put(cascade_node);
+}
+
 static void __init gef_sbc610_setup_arch(void)
 {
+	struct device_node *regs;
 #ifdef CONFIG_PCI
 	struct device_node *np;
 
@@ -63,8 +87,43 @@ static void __init gef_sbc610_setup_arch(void)
 #ifdef CONFIG_SMP
 	mpc86xx_smp_init();
 #endif
+
+	/* Remap basic board registers */
+	regs = of_find_compatible_node(NULL, NULL, "gef,fpga-regs");
+	if (regs) {
+		sbc610_regs = of_iomap(regs, 0);
+		if (sbc610_regs == NULL)
+			printk(KERN_WARNING "Unable to map board registers\n");
+		of_node_put(regs);
+	}
+}
+
+/* Return the PCB revision */
+static unsigned int gef_sbc610_get_pcb_rev(void)
+{
+	unsigned int reg;
+
+	reg = ioread32(sbc610_regs);
+	return (reg >> 8) & 0xff;
+}
+
+/* Return the board (software) revision */
+static unsigned int gef_sbc610_get_board_rev(void)
+{
+	unsigned int reg;
+
+	reg = ioread32(sbc610_regs);
+	return (reg >> 16) & 0xff;
 }
 
+/* Return the FPGA revision */
+static unsigned int gef_sbc610_get_fpga_rev(void)
+{
+	unsigned int reg;
+
+	reg = ioread32(sbc610_regs);
+	return (reg >> 24) & 0xf;
+}
 
 static void gef_sbc610_show_cpuinfo(struct seq_file *m)
 {
@@ -73,6 +132,10 @@ static void gef_sbc610_show_cpuinfo(struct seq_file *m)
 
 	seq_printf(m, "Vendor\t\t: GE Fanuc Intelligent Platforms\n");
 
+	seq_printf(m, "Revision\t: %u%c\n", gef_sbc610_get_pcb_rev(),
+		('A' + gef_sbc610_get_board_rev() - 1));
+	seq_printf(m, "FPGA Revision\t: %u\n", gef_sbc610_get_fpga_rev());
+
 	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
 	seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
 }
@@ -145,7 +208,7 @@ define_machine(gef_sbc610) {
 	.name			= "GE Fanuc SBC610",
 	.probe			= gef_sbc610_probe,
 	.setup_arch		= gef_sbc610_setup_arch,
-	.init_IRQ		= mpc86xx_init_irq,
+	.init_IRQ		= gef_sbc610_init_irq,
 	.show_cpuinfo		= gef_sbc610_show_cpuinfo,
 	.get_irq		= mpic_get_irq,
 	.restart		= fsl_rstcr_restart,

+ 0 - 1
arch/powerpc/platforms/86xx/mpc8610_hpcd.c

@@ -238,7 +238,6 @@ static void __init mpc86xx_hpcd_setup_arch(void)
         }
 #endif
 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
-	preallocate_diu_videomemory();
 	diu_ops.get_pixel_format	= mpc8610hpcd_get_pixel_format;
 	diu_ops.set_gamma_table		= mpc8610hpcd_set_gamma_table;
 	diu_ops.set_monitor_port	= mpc8610hpcd_set_monitor_port;

+ 11 - 1
arch/powerpc/platforms/Kconfig

@@ -239,7 +239,8 @@ config TAU_AVERAGE
 	  If in doubt, say N here.
 
 config QUICC_ENGINE
-	bool
+	bool "Freescale QUICC Engine (QE) Support"
+	depends on FSL_SOC
 	select PPC_LIB_RHEAP
 	select CRC32
 	help
@@ -248,6 +249,15 @@ config QUICC_ENGINE
 	  Selecting this option means that you wish to build a kernel
 	  for a machine with a QE coprocessor.
 
+config QE_GPIO
+	bool "QE GPIO support"
+	depends on QUICC_ENGINE
+	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	help
+	  Say Y here if you're going to use hardware that connects to the
+	  QE GPIOs.
+
 config CPM2
 	bool "Enable support for the CPM2 (Communications Processor Module)"
 	depends on MPC85xx || 8260

+ 49 - 4
arch/powerpc/sysdev/fsl_lbc.c

@@ -11,14 +11,19 @@
  * (at your option) any later version.
  */
 
+#include <linux/init.h>
+#include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/io.h>
 #include <linux/of.h>
+#include <asm/prom.h>
 #include <asm/fsl_lbc.h>
 
-spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
-
-struct fsl_lbc_regs __iomem *fsl_lbc_regs;
-EXPORT_SYMBOL(fsl_lbc_regs);
+static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
+static struct fsl_lbc_regs __iomem *fsl_lbc_regs;
 
 static char __initdata *compat_lbc[] = {
 	"fsl,pq2-localbus",
@@ -127,3 +132,43 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm)
 	return 0;
 }
 EXPORT_SYMBOL(fsl_upm_find);
+
+/**
+ * fsl_upm_run_pattern - actually run an UPM pattern
+ * @upm:	pointer to the fsl_upm structure obtained via fsl_upm_find
+ * @io_base:	remapped pointer to where memory access should happen
+ * @mar:	MAR register content during pattern execution
+ *
+ * This function triggers dummy write to the memory specified by the io_base,
+ * thus UPM pattern actually executed. Note that mar usage depends on the
+ * pre-programmed AMX bits in the UPM RAM.
+ */
+int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
+{
+	int ret = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&fsl_lbc_lock, flags);
+
+	out_be32(&fsl_lbc_regs->mar, mar << (32 - upm->width));
+
+	switch (upm->width) {
+	case 8:
+		out_8(io_base, 0x0);
+		break;
+	case 16:
+		out_be16(io_base, 0x0);
+		break;
+	case 32:
+		out_be32(io_base, 0x0);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	spin_unlock_irqrestore(&fsl_lbc_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(fsl_upm_run_pattern);

+ 37 - 21
arch/powerpc/sysdev/fsl_pci.c

@@ -1,7 +1,7 @@
 /*
- * MPC85xx/86xx PCI/PCIE support routing.
+ * MPC83xx/85xx/86xx PCI/PCIE support routing.
  *
- * Copyright 2007 Freescale Semiconductor, Inc
+ * Copyright 2007,2008 Freescale Semiconductor, Inc
  *
  * Initial author: Xianghua Xiao <x.xiao@freescale.com>
  * Recode: ZHANG WEI <wei.zhang@freescale.com>
@@ -251,20 +251,47 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, quirk_fsl_pcie_header);
 #endif /* CONFIG_PPC_85xx || CONFIG_PPC_86xx */
 
-#if defined(CONFIG_PPC_83xx)
+#if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)
 int __init mpc83xx_add_bridge(struct device_node *dev)
 {
 	int len;
 	struct pci_controller *hose;
-	struct resource rsrc;
+	struct resource rsrc_reg;
+	struct resource rsrc_cfg;
 	const int *bus_range;
-	int primary = 1, has_address = 0;
-	phys_addr_t immr = get_immrbase();
+	int primary;
 
 	pr_debug("Adding PCI host bridge %s\n", dev->full_name);
 
 	/* Fetch host bridge registers address */
-	has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
+	if (of_address_to_resource(dev, 0, &rsrc_reg)) {
+		printk(KERN_WARNING "Can't get pci register base!\n");
+		return -ENOMEM;
+	}
+
+	memset(&rsrc_cfg, 0, sizeof(rsrc_cfg));
+
+	if (of_address_to_resource(dev, 1, &rsrc_cfg)) {
+		printk(KERN_WARNING
+			"No pci config register base in dev tree, "
+			"using default\n");
+		/*
+		 * MPC83xx supports up to two host controllers
+		 * 	one at 0x8500 has config space registers at 0x8300
+		 * 	one at 0x8600 has config space registers at 0x8380
+		 */
+		if ((rsrc_reg.start & 0xfffff) == 0x8500)
+			rsrc_cfg.start = (rsrc_reg.start & 0xfff00000) + 0x8300;
+		else if ((rsrc_reg.start & 0xfffff) == 0x8600)
+			rsrc_cfg.start = (rsrc_reg.start & 0xfff00000) + 0x8380;
+	}
+	/*
+	 * Controller at offset 0x8500 is primary
+	 */
+	if ((rsrc_reg.start & 0xfffff) == 0x8500)
+		primary = 1;
+	else
+		primary = 0;
 
 	/* Get bus range if any */
 	bus_range = of_get_property(dev, "bus-range", &len);
@@ -281,22 +308,11 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
 	hose->first_busno = bus_range ? bus_range[0] : 0;
 	hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
-	/* MPC83xx supports up to two host controllers one at 0x8500 from immrbar
-	 * the other at 0x8600, we consider the 0x8500 the primary controller
-	 */
-	/* PCI 1 */
-	if ((rsrc.start & 0xfffff) == 0x8500) {
-		setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304, 0);
-	}
-	/* PCI 2 */
-	if ((rsrc.start & 0xfffff) == 0x8600) {
-		setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384, 0);
-		primary = 0;
-	}
+	setup_indirect_pci(hose, rsrc_cfg.start, rsrc_cfg.start + 4, 0);
 
-	printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. "
+	printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. "
 	       "Firmware bus number: %d->%d\n",
-	       (unsigned long long)rsrc.start, hose->first_busno,
+	       (unsigned long long)rsrc_reg.start, hose->first_busno,
 	       hose->last_busno);
 
 	pr_debug(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",

+ 1 - 37
arch/powerpc/sysdev/fsl_soc.c

@@ -720,42 +720,6 @@ void fsl_rstcr_restart(char *cmd)
 #endif
 
 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
-struct platform_diu_data_ops diu_ops = {
-	.diu_size = 1280 * 1024 * 4,	/* default one 1280x1024 buffer */
-};
+struct platform_diu_data_ops diu_ops;
 EXPORT_SYMBOL(diu_ops);
-
-int __init preallocate_diu_videomemory(void)
-{
-	pr_debug("diu_size=%lu\n", diu_ops.diu_size);
-
-	diu_ops.diu_mem = __alloc_bootmem(diu_ops.diu_size, 8, 0);
-	if (!diu_ops.diu_mem) {
-		printk(KERN_ERR "fsl-diu: cannot allocate %lu bytes\n",
-			diu_ops.diu_size);
-		return -ENOMEM;
-	}
-
-	pr_debug("diu_mem=%p\n", diu_ops.diu_mem);
-
-	rh_init(&diu_ops.diu_rh_info, 4096, ARRAY_SIZE(diu_ops.diu_rh_block),
-		diu_ops.diu_rh_block);
-	return rh_attach_region(&diu_ops.diu_rh_info,
-				(unsigned long) diu_ops.diu_mem,
-				diu_ops.diu_size);
-}
-
-static int __init early_parse_diufb(char *p)
-{
-	if (!p)
-		return 1;
-
-	diu_ops.diu_size = _ALIGN_UP(memparse(p, &p), 8);
-
-	pr_debug("diu_size=%lu\n", diu_ops.diu_size);
-
-	return 0;
-}
-early_param("diufb", early_parse_diufb);
-
 #endif

+ 0 - 8
arch/powerpc/sysdev/fsl_soc.h

@@ -20,14 +20,7 @@ extern int fsl_spi_init(struct spi_board_info *board_infos,
 extern void fsl_rstcr_restart(char *cmd);
 
 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
-#include <linux/bootmem.h>
-#include <asm/rheap.h>
 struct platform_diu_data_ops {
-	rh_block_t diu_rh_block[16];
-	rh_info_t diu_rh_info;
-	unsigned long diu_size;
-	void *diu_mem;
-
 	unsigned int (*get_pixel_format) (unsigned int bits_per_pixel,
 		int monitor_port);
 	void (*set_gamma_table) (int monitor_port, char *gamma_table_base);
@@ -38,7 +31,6 @@ struct platform_diu_data_ops {
 };
 
 extern struct platform_diu_data_ops diu_ops;
-int __init preallocate_diu_videomemory(void);
 #endif
 
 #endif

+ 0 - 9
arch/powerpc/sysdev/qe_lib/Kconfig

@@ -24,12 +24,3 @@ config QE_USB
 	bool
 	help
 	  QE USB Host Controller support
-
-config QE_GPIO
-	bool "QE GPIO support"
-	depends on QUICC_ENGINE
-	select GENERIC_GPIO
-	select ARCH_REQUIRE_GPIOLIB
-	help
-	  Say Y here if you're going to use hardware that connects to the
-	  QE GPIOs.

+ 11 - 0
drivers/i2c/chips/Kconfig

@@ -172,4 +172,15 @@ config MENELAUS
 	  and other features that are often used in portable devices like
 	  cell phones and PDAs.
 
+config MCU_MPC8349EMITX
+	tristate "MPC8349E-mITX MCU driver"
+	depends on I2C && PPC_83xx
+	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	help
+	  Say Y here to enable soft power-off functionality on the Freescale
+	  boards with the MPC8349E-mITX-compatible MCU chips. This driver will
+	  also register MCU GPIOs with the generic GPIO API, so you'll able
+	  to use MCU pins as GPIOs.
+
 endmenu

+ 1 - 0
drivers/i2c/chips/Makefile

@@ -21,6 +21,7 @@ obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
 obj-$(CONFIG_TPS65010)		+= tps65010.o
 obj-$(CONFIG_MENELAUS)		+= menelaus.o
 obj-$(CONFIG_SENSORS_TSL2550)	+= tsl2550.o
+obj-$(CONFIG_MCU_MPC8349EMITX)	+= mcu_mpc8349emitx.o
 
 ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
 EXTRA_CFLAGS += -DDEBUG

+ 209 - 0
drivers/i2c/chips/mcu_mpc8349emitx.c

@@ -0,0 +1,209 @@
+/*
+ * Power Management and GPIO expander driver for MPC8349E-mITX-compatible MCU
+ *
+ * Copyright (c) 2008  MontaVista Software, Inc.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+
+/*
+ * I don't have specifications for the MCU firmware, I found this register
+ * and bits positions by the trial&error method.
+ */
+#define MCU_REG_CTRL	0x20
+#define MCU_CTRL_POFF	0x40
+
+#define MCU_NUM_GPIO	2
+
+struct mcu {
+	struct mutex lock;
+	struct device_node *np;
+	struct i2c_client *client;
+	struct of_gpio_chip of_gc;
+	u8 reg_ctrl;
+};
+
+static struct mcu *glob_mcu;
+
+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,
+				  mcu->reg_ctrl | MCU_CTRL_POFF);
+	mutex_unlock(&mcu->lock);
+}
+
+static void mcu_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	struct of_gpio_chip *of_gc = to_of_gpio_chip(gc);
+	struct mcu *mcu = container_of(of_gc, struct mcu, of_gc);
+	u8 bit = 1 << (4 + gpio);
+
+	mutex_lock(&mcu->lock);
+	if (val)
+		mcu->reg_ctrl &= ~bit;
+	else
+		mcu->reg_ctrl |= bit;
+
+	i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL, mcu->reg_ctrl);
+	mutex_unlock(&mcu->lock);
+}
+
+static int mcu_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	mcu_gpio_set(gc, gpio, val);
+	return 0;
+}
+
+static int mcu_gpiochip_add(struct mcu *mcu)
+{
+	struct device_node *np;
+	struct of_gpio_chip *of_gc = &mcu->of_gc;
+	struct gpio_chip *gc = &of_gc->gc;
+	int ret;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,mcu-mpc8349emitx");
+	if (!np)
+		return -ENODEV;
+
+	gc->owner = THIS_MODULE;
+	gc->label = np->full_name;
+	gc->can_sleep = 1;
+	gc->ngpio = MCU_NUM_GPIO;
+	gc->base = -1;
+	gc->set = mcu_gpio_set;
+	gc->direction_output = mcu_gpio_dir_out;
+	of_gc->gpio_cells = 2;
+	of_gc->xlate = of_gpio_simple_xlate;
+
+	np->data = of_gc;
+	mcu->np = np;
+
+	/*
+	 * We don't want to lose the node, its ->data and ->full_name...
+	 * So, if succeeded, we don't put the node here.
+	 */
+	ret = gpiochip_add(gc);
+	if (ret)
+		of_node_put(np);
+	return ret;
+}
+
+static int mcu_gpiochip_remove(struct mcu *mcu)
+{
+	int ret;
+
+	ret = gpiochip_remove(&mcu->of_gc.gc);
+	if (ret)
+		return ret;
+	of_node_put(mcu->np);
+
+	return 0;
+}
+
+static int __devinit mcu_probe(struct i2c_client *client,
+			       const struct i2c_device_id *id)
+{
+	struct mcu *mcu;
+	int ret;
+
+	mcu = kzalloc(sizeof(*mcu), GFP_KERNEL);
+	if (!mcu)
+		return -ENOMEM;
+
+	mutex_init(&mcu->lock);
+	mcu->client = client;
+	i2c_set_clientdata(client, mcu);
+
+	ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL);
+	if (ret < 0)
+		goto err;
+	mcu->reg_ctrl = ret;
+
+	ret = mcu_gpiochip_add(mcu);
+	if (ret)
+		goto err;
+
+	/* XXX: this is potentially racy, but there is no lock for ppc_md */
+	if (!ppc_md.power_off) {
+		glob_mcu = mcu;
+		ppc_md.power_off = mcu_power_off;
+		dev_info(&client->dev, "will provide power-off service\n");
+	}
+
+	return 0;
+err:
+	kfree(mcu);
+	return ret;
+}
+
+static int __devexit mcu_remove(struct i2c_client *client)
+{
+	struct mcu *mcu = i2c_get_clientdata(client);
+	int ret;
+
+	if (glob_mcu == mcu) {
+		ppc_md.power_off = NULL;
+		glob_mcu = NULL;
+	}
+
+	ret = mcu_gpiochip_remove(mcu);
+	if (ret)
+		return ret;
+	i2c_set_clientdata(client, NULL);
+	kfree(mcu);
+	return 0;
+}
+
+static const struct i2c_device_id mcu_ids[] = {
+	{ "mcu-mpc8349emitx", },
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, mcu_ids);
+
+static struct i2c_driver mcu_driver = {
+	.driver = {
+		.name = "mcu-mpc8349emitx",
+		.owner = THIS_MODULE,
+	},
+	.probe = mcu_probe,
+	.remove	= __devexit_p(mcu_remove),
+	.id_table = mcu_ids,
+};
+
+static int __init mcu_init(void)
+{
+	return i2c_add_driver(&mcu_driver);
+}
+module_init(mcu_init);
+
+static void __exit mcu_exit(void)
+{
+	i2c_del_driver(&mcu_driver);
+}
+module_exit(mcu_exit);
+
+MODULE_DESCRIPTION("Power Management and GPIO expander driver for "
+		   "MPC8349E-mITX-compatible MCU");
+MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
+MODULE_LICENSE("GPL");