summary refs log tree commit diff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-07-29 23:32:02 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2011-07-29 23:32:02 -0700
commitcb7dee8d22f3e9320424e769d860fbd9712a0666 (patch)
tree58f33d70453e7cd26ec78e96f33ca7a9673df26e
parent49267fc82ad2825132be3b016d8eb58a90cb0c36 (diff)
parent6124a4e430b64d1577438c8648c59e996d02e73e (diff)
downloadlinux-cb7dee8d22f3e9320424e769d860fbd9712a0666.tar.gz
Merge branch 'next/dt' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/linux-arm-soc
* 'next/dt' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/linux-arm-soc: (21 commits)
  arm/dt: tegra devicetree support
  arm/versatile: Add device tree support
  dt/irq: add irq_domain_generate_simple() helper
  irq: add irq_domain translation infrastructure
  dmaengine: imx-sdma: add device tree probe support
  dmaengine: imx-sdma: sdma_get_firmware does not need to copy fw_name
  dmaengine: imx-sdma: use platform_device_id to identify sdma version
  mmc: sdhci-esdhc-imx: add device tree probe support
  mmc: sdhci-pltfm: dt device does not pass parent to sdhci_alloc_host
  mmc: sdhci-esdhc-imx: get rid of the uses of cpu_is_mx()
  mmc: sdhci-esdhc-imx: do not reference platform data after probe
  mmc: sdhci-esdhc-imx: extend card_detect and write_protect support for mx5
  net/fec: add device tree probe support
  net: ibm_newemac: convert it to use of_get_phy_mode
  dt/net: add helper function of_get_phy_mode
  net/fec: gasket needs to be enabled for some i.mx
  serial/imx: add device tree probe support
  serial/imx: get rid of the uses of cpu_is_mx1()
  arm/dt: Add dtb make rule
  arm/dt: Add skeleton dtsi file
  ...
-rw-r--r--Documentation/devicetree/bindings/arm/arm-boards20
-rw-r--r--Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt17
-rw-r--r--Documentation/devicetree/bindings/i2c/arm-versatile.txt10
-rw-r--r--Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt34
-rw-r--r--Documentation/devicetree/bindings/mtd/arm-versatile.txt8
-rw-r--r--Documentation/devicetree/bindings/net/fsl-fec.txt24
-rw-r--r--Documentation/devicetree/bindings/net/smsc-lan91c111.txt10
-rw-r--r--Documentation/devicetree/bindings/tty/serial/fsl-imx-uart.txt19
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/Makefile7
-rw-r--r--arch/arm/boot/Makefile6
-rw-r--r--arch/arm/boot/dts/skeleton.dtsi13
-rw-r--r--arch/arm/boot/dts/tegra-harmony.dts70
-rw-r--r--arch/arm/boot/dts/tegra-seaboard.dts28
-rw-r--r--arch/arm/boot/dts/tegra20.dtsi139
-rw-r--r--arch/arm/boot/dts/versatile-ab.dts192
-rw-r--r--arch/arm/boot/dts/versatile-pb.dts48
-rw-r--r--arch/arm/include/asm/mach/arch.h7
-rw-r--r--arch/arm/include/asm/prom.h5
-rw-r--r--arch/arm/kernel/devtree.c14
-rw-r--r--arch/arm/mach-imx/clock-imx1.c6
-rw-r--r--arch/arm/mach-imx/clock-imx21.c8
-rw-r--r--arch/arm/mach-imx/clock-imx25.c20
-rw-r--r--arch/arm/mach-imx/clock-imx27.c15
-rw-r--r--arch/arm/mach-imx/clock-imx31.c13
-rw-r--r--arch/arm/mach-imx/clock-imx35.c18
-rw-r--r--arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c3
-rw-r--r--arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c3
-rw-r--r--arch/arm/mach-imx/mach-mx25_3ds.c2
-rw-r--r--arch/arm/mach-imx/mach-pcm043.c2
-rw-r--r--arch/arm/mach-imx/mm-imx25.c4
-rw-r--r--arch/arm/mach-imx/mm-imx31.c3
-rw-r--r--arch/arm/mach-imx/mm-imx35.c3
-rw-r--r--arch/arm/mach-mx5/board-mx51_babbage.c14
-rw-r--r--arch/arm/mach-mx5/board-mx53_loco.c4
-rw-r--r--arch/arm/mach-mx5/clock-mx51-mx53.c46
-rw-r--r--arch/arm/mach-mx5/mm.c8
-rw-r--r--arch/arm/mach-mx5/mx51_efika.c4
-rw-r--r--arch/arm/mach-tegra/Kconfig6
-rw-r--r--arch/arm/mach-tegra/Makefile3
-rw-r--r--arch/arm/mach-tegra/Makefile.boot3
-rw-r--r--arch/arm/mach-tegra/board-dt.c119
-rw-r--r--arch/arm/mach-versatile/Kconfig8
-rw-r--r--arch/arm/mach-versatile/Makefile1
-rw-r--r--arch/arm/mach-versatile/core.c62
-rw-r--r--arch/arm/mach-versatile/core.h4
-rw-r--r--arch/arm/mach-versatile/versatile_dt.c51
-rw-r--r--arch/arm/plat-mxc/devices/platform-fec.c21
-rw-r--r--arch/arm/plat-mxc/devices/platform-imx-dma.c4
-rw-r--r--arch/arm/plat-mxc/devices/platform-imx-uart.c7
-rw-r--r--arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c29
-rw-r--r--arch/arm/plat-mxc/include/mach/devices-common.h4
-rw-r--r--arch/arm/plat-mxc/include/mach/dma.h3
-rw-r--r--arch/arm/plat-mxc/include/mach/esdhc.h25
-rw-r--r--arch/arm/plat-mxc/include/mach/sdma.h2
-rw-r--r--drivers/dma/imx-sdma.c94
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c261
-rw-r--r--drivers/mmc/host/sdhci-pltfm.c3
-rw-r--r--drivers/net/fec.c125
-rw-r--r--drivers/net/ibm_newemac/core.c33
-rw-r--r--drivers/net/ibm_newemac/emac.h19
-rw-r--r--drivers/net/ibm_newemac/phy.c7
-rw-r--r--drivers/of/of_net.c45
-rw-r--r--drivers/tty/serial/imx.c166
-rw-r--r--include/linux/irq.h6
-rw-r--r--include/linux/irqdomain.h91
-rw-r--r--include/linux/of_irq.h4
-rw-r--r--include/linux/of_net.h1
-rw-r--r--include/linux/phy.h4
-rw-r--r--kernel/irq/Kconfig4
-rw-r--r--kernel/irq/Makefile1
-rw-r--r--kernel/irq/irqdomain.c180
72 files changed, 1963 insertions, 281 deletions
diff --git a/Documentation/devicetree/bindings/arm/arm-boards b/Documentation/devicetree/bindings/arm/arm-boards
new file mode 100644
index 000000000000..91f26148af79
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/arm-boards
@@ -0,0 +1,20 @@
+ARM Versatile Application and Platform Baseboards
+-------------------------------------------------
+ARM's development hardware platform with connectors for customizable
+core tiles.  The hardware configuration of the Versatile boards is
+highly customizable.
+
+Required properties (in root node):
+	compatible = "arm,versatile-ab";  /* Application baseboard */
+	compatible = "arm,versatile-pb";  /* Platform baseboard */
+
+Interrupt controllers:
+- VIC required properties:
+	compatible = "arm,versatile-vic";
+	interrupt-controller;
+	#interrupt-cells = <1>;
+
+- SIC required properties:
+	compatible = "arm,versatile-sic";
+	interrupt-controller;
+	#interrupt-cells = <1>;
diff --git a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
new file mode 100644
index 000000000000..d1e3f443e205
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
@@ -0,0 +1,17 @@
+* Freescale Smart Direct Memory Access (SDMA) Controller for i.MX
+
+Required properties:
+- compatible : Should be "fsl,<chip>-sdma"
+- reg : Should contain SDMA registers location and length
+- interrupts : Should contain SDMA interrupt
+- fsl,sdma-ram-script-name : Should contain the full path of SDMA RAM
+  scripts firmware
+
+Examples:
+
+sdma@83fb0000 {
+	compatible = "fsl,imx51-sdma", "fsl,imx35-sdma";
+	reg = <0x83fb0000 0x4000>;
+	interrupts = <6>;
+	fsl,sdma-ram-script-name = "sdma-imx51.bin";
+};
diff --git a/Documentation/devicetree/bindings/i2c/arm-versatile.txt b/Documentation/devicetree/bindings/i2c/arm-versatile.txt
new file mode 100644
index 000000000000..361d31c51b6f
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/arm-versatile.txt
@@ -0,0 +1,10 @@
+i2c Controller on ARM Versatile platform:
+
+Required properties:
+- compatible : Must be "arm,versatile-i2c";
+- reg
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Optional properties:
+- Child nodes conforming to i2c bus binding
diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
new file mode 100644
index 000000000000..ab22fe6e73ab
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
@@ -0,0 +1,34 @@
+* Freescale Enhanced Secure Digital Host Controller (eSDHC) for i.MX
+
+The Enhanced Secure Digital Host Controller on Freescale i.MX family
+provides an interface for MMC, SD, and SDIO types of memory cards.
+
+Required properties:
+- compatible : Should be "fsl,<chip>-esdhc"
+- reg : Should contain eSDHC registers location and length
+- interrupts : Should contain eSDHC interrupt
+
+Optional properties:
+- fsl,card-wired : Indicate the card is wired to host permanently
+- fsl,cd-internal : Indicate to use controller internal card detection
+- fsl,wp-internal : Indicate to use controller internal write protection
+- cd-gpios : Specify GPIOs for card detection
+- wp-gpios : Specify GPIOs for write protection
+
+Examples:
+
+esdhc@70004000 {
+	compatible = "fsl,imx51-esdhc";
+	reg = <0x70004000 0x4000>;
+	interrupts = <1>;
+	fsl,cd-internal;
+	fsl,wp-internal;
+};
+
+esdhc@70008000 {
+	compatible = "fsl,imx51-esdhc";
+	reg = <0x70008000 0x4000>;
+	interrupts = <2>;
+	cd-gpios = <&gpio0 6 0>; /* GPIO1_6 */
+	wp-gpios = <&gpio0 5 0>; /* GPIO1_5 */
+};
diff --git a/Documentation/devicetree/bindings/mtd/arm-versatile.txt b/Documentation/devicetree/bindings/mtd/arm-versatile.txt
new file mode 100644
index 000000000000..476845db94d0
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/arm-versatile.txt
@@ -0,0 +1,8 @@
+Flash device on ARM Versatile board
+
+Required properties:
+- compatible : must be "arm,versatile-flash";
+- bank-width : width in bytes of flash interface.
+
+Optional properties:
+- Subnode partition map from mtd flash binding
diff --git a/Documentation/devicetree/bindings/net/fsl-fec.txt b/Documentation/devicetree/bindings/net/fsl-fec.txt
new file mode 100644
index 000000000000..de439517dff0
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/fsl-fec.txt
@@ -0,0 +1,24 @@
+* Freescale Fast Ethernet Controller (FEC)
+
+Required properties:
+- compatible : Should be "fsl,<soc>-fec"
+- reg : Address and length of the register set for the device
+- interrupts : Should contain fec interrupt
+- phy-mode : String, operation mode of the PHY interface.
+  Supported values are: "mii", "gmii", "sgmii", "tbi", "rmii",
+  "rgmii", "rgmii-id", "rgmii-rxid", "rgmii-txid", "rtbi", "smii".
+- phy-reset-gpios : Should specify the gpio for phy reset
+
+Optional properties:
+- local-mac-address : 6 bytes, mac address
+
+Example:
+
+fec@83fec000 {
+	compatible = "fsl,imx51-fec", "fsl,imx27-fec";
+	reg = <0x83fec000 0x4000>;
+	interrupts = <87>;
+	phy-mode = "mii";
+	phy-reset-gpios = <&gpio1 14 0>; /* GPIO2_14 */
+	local-mac-address = [00 04 9F 01 1B B9];
+};
diff --git a/Documentation/devicetree/bindings/net/smsc-lan91c111.txt b/Documentation/devicetree/bindings/net/smsc-lan91c111.txt
new file mode 100644
index 000000000000..953049b4248a
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/smsc-lan91c111.txt
@@ -0,0 +1,10 @@
+SMSC LAN91c111 Ethernet mac
+
+Required properties:
+- compatible = "smsc,lan91c111";
+- reg : physical address and size of registers
+- interrupts : interrupt connection
+
+Optional properties:
+- phy-device : phandle to Ethernet phy
+- local-mac-address : Ethernet mac address to use
diff --git a/Documentation/devicetree/bindings/tty/serial/fsl-imx-uart.txt b/Documentation/devicetree/bindings/tty/serial/fsl-imx-uart.txt
new file mode 100644
index 000000000000..a9c0406280e8
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/fsl-imx-uart.txt
@@ -0,0 +1,19 @@
+* Freescale i.MX Universal Asynchronous Receiver/Transmitter (UART)
+
+Required properties:
+- compatible : Should be "fsl,<soc>-uart"
+- reg : Address and length of the register set for the device
+- interrupts : Should contain uart interrupt
+
+Optional properties:
+- fsl,uart-has-rtscts : Indicate the uart has rts and cts
+- fsl,irda-mode : Indicate the uart supports irda mode
+
+Example:
+
+uart@73fbc000 {
+	compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+	reg = <0x73fbc000 0x4000>;
+	interrupts = <31>;
+	fsl,uart-has-rtscts;
+};
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 09ebf0ba64fa..2c71a8f3535a 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1716,6 +1716,7 @@ config USE_OF
 	bool "Flattened Device Tree support"
 	select OF
 	select OF_EARLY_FLATTREE
+	select IRQ_DOMAIN
 	help
 	  Include support for flattened device tree machine descriptions.
 
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 3a4a04b33d0f..70c424eaf7b0 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -282,6 +282,12 @@ zImage Image xipImage bootpImage uImage: vmlinux
 zinstall uinstall install: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
 
+%.dtb:
+	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+
+dtbs:
+	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+
 # We use MRPROPER_FILES and CLEAN_FILES now
 archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
@@ -298,6 +304,7 @@ define archhelp
   echo  '  uImage        - U-Boot wrapped zImage'
   echo  '  bootpImage    - Combined zImage and initial RAM disk' 
   echo  '                  (supply initrd image via make variable INITRD=<path>)'
+  echo  '  dtbs          - Build device tree blobs for enabled boards'
   echo  '  install       - Install uncompressed kernel'
   echo  '  zinstall      - Install compressed kernel'
   echo  '  uinstall      - Install U-Boot wrapped compressed kernel'
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index 9128fddf1109..a1edfd5a129a 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -59,6 +59,12 @@ $(obj)/zImage:	$(obj)/compressed/vmlinux FORCE
 
 endif
 
+# Rule to build device tree blobs
+$(obj)/%.dtb: $(src)/dts/%.dts
+	$(call cmd,dtc)
+
+$(obj)/dtbs: $(addprefix $(obj)/, $(dtb-y))
+
 quiet_cmd_uimage = UIMAGE  $@
       cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \
 		   -C none -a $(LOADADDR) -e $(STARTADDR) \
diff --git a/arch/arm/boot/dts/skeleton.dtsi b/arch/arm/boot/dts/skeleton.dtsi
new file mode 100644
index 000000000000..b41d241de2cd
--- /dev/null
+++ b/arch/arm/boot/dts/skeleton.dtsi
@@ -0,0 +1,13 @@
+/*
+ * Skeleton device tree; the bare minimum needed to boot; just include and
+ * add a compatible value.  The bootloader will typically populate the memory
+ * node.
+ */
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	chosen { };
+	aliases { };
+	memory { device_type = "memory"; reg = <0 0>; };
+};
diff --git a/arch/arm/boot/dts/tegra-harmony.dts b/arch/arm/boot/dts/tegra-harmony.dts
new file mode 100644
index 000000000000..4c053340ce33
--- /dev/null
+++ b/arch/arm/boot/dts/tegra-harmony.dts
@@ -0,0 +1,70 @@
+/dts-v1/;
+
+/memreserve/ 0x1c000000 0x04000000;
+/include/ "tegra20.dtsi"
+
+/ {
+	model = "NVIDIA Tegra2 Harmony evaluation board";
+	compatible = "nvidia,harmony", "nvidia,tegra20";
+
+	chosen {
+		bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/mmcblk0p2 rw rootwait";
+	};
+
+	memory@0 {
+		reg = < 0x00000000 0x40000000 >;
+	};
+
+	i2c@7000c000 {
+		clock-frequency = <400000>;
+
+		codec: wm8903@1a {
+			compatible = "wlf,wm8903";
+			reg = <0x1a>;
+			interrupts = < 347 >;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			/* 0x8000 = Not configured */
+			gpio-cfg = < 0x8000 0x8000 0 0x8000 0x8000 >;
+		};
+	};
+
+	i2c@7000c400 {
+		clock-frequency = <400000>;
+	};
+
+	i2c@7000c500 {
+		clock-frequency = <400000>;
+	};
+
+	i2c@7000d000 {
+		clock-frequency = <400000>;
+	};
+
+	sound {
+		compatible = "nvidia,harmony-sound", "nvidia,tegra-wm8903";
+
+		spkr-en-gpios = <&codec 2 0>;
+		hp-det-gpios = <&gpio 178 0>;
+		int-mic-en-gpios = <&gpio 184 0>;
+		ext-mic-en-gpios = <&gpio 185 0>;
+	};
+
+	serial@70006300 {
+		clock-frequency = < 216000000 >;
+	};
+
+	sdhci@c8000200 {
+		gpios = <&gpio 69 0>, /* cd, gpio PI5 */
+			<&gpio 57 0>, /* wp, gpio PH1 */
+			<&gpio 155 0>; /* power, gpio PT3 */
+	};
+
+	sdhci@c8000600 {
+		gpios = <&gpio 58 0>, /* cd, gpio PH2 */
+			<&gpio 59 0>, /* wp, gpio PH3 */
+			<&gpio 70 0>; /* power, gpio PI6 */
+	};
+};
diff --git a/arch/arm/boot/dts/tegra-seaboard.dts b/arch/arm/boot/dts/tegra-seaboard.dts
new file mode 100644
index 000000000000..1940cae00748
--- /dev/null
+++ b/arch/arm/boot/dts/tegra-seaboard.dts
@@ -0,0 +1,28 @@
+/dts-v1/;
+
+/memreserve/ 0x1c000000 0x04000000;
+/include/ "tegra20.dtsi"
+
+/ {
+	model = "NVIDIA Seaboard";
+	compatible = "nvidia,seaboard", "nvidia,tegra20";
+
+	chosen {
+		bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/mmcblk1p3 rw rootwait";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = < 0x00000000 0x40000000 >;
+	};
+
+	serial@70006300 {
+		clock-frequency = < 216000000 >;
+	};
+
+	sdhci@c8000400 {
+		gpios = <&gpio 69 0>, /* cd, gpio PI5 */
+			<&gpio 57 0>, /* wp, gpio PH1 */
+			<&gpio 70 0>; /* power, gpio PI6 */
+	};
+};
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
new file mode 100644
index 000000000000..5727595cde61
--- /dev/null
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -0,0 +1,139 @@
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "nvidia,tegra20";
+	interrupt-parent = <&intc>;
+
+	intc: interrupt-controller@50041000 {
+		compatible = "nvidia,tegra20-gic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = < 0x50041000 0x1000 >,
+		      < 0x50040100 0x0100 >;
+	};
+
+	i2c@7000c000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "nvidia,tegra20-i2c";
+		reg = <0x7000C000 0x100>;
+		interrupts = < 70 >;
+	};
+
+	i2c@7000c400 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "nvidia,tegra20-i2c";
+		reg = <0x7000C400 0x100>;
+		interrupts = < 116 >;
+	};
+
+	i2c@7000c500 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "nvidia,tegra20-i2c";
+		reg = <0x7000C500 0x100>;
+		interrupts = < 124 >;
+	};
+
+	i2c@7000d000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "nvidia,tegra20-i2c";
+		reg = <0x7000D000 0x200>;
+		interrupts = < 85 >;
+	};
+
+	i2s@70002800 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "nvidia,tegra20-i2s";
+		reg = <0x70002800 0x200>;
+		interrupts = < 45 >;
+		dma-channel = < 2 >;
+	};
+
+	i2s@70002a00 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "nvidia,tegra20-i2s";
+		reg = <0x70002a00 0x200>;
+		interrupts = < 35 >;
+		dma-channel = < 1 >;
+	};
+
+	das@70000c00 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "nvidia,tegra20-das";
+		reg = <0x70000c00 0x80>;
+	};
+
+	gpio: gpio@6000d000 {
+		compatible = "nvidia,tegra20-gpio";
+		reg = < 0x6000d000 0x1000 >;
+		interrupts = < 64 65 66 67 87 119 121 >;
+		#gpio-cells = <2>;
+		gpio-controller;
+	};
+
+	serial@70006000 {
+		compatible = "nvidia,tegra20-uart";
+		reg = <0x70006000 0x40>;
+		reg-shift = <2>;
+		interrupts = < 68 >;
+	};
+
+	serial@70006040 {
+		compatible = "nvidia,tegra20-uart";
+		reg = <0x70006040 0x40>;
+		reg-shift = <2>;
+		interrupts = < 69 >;
+	};
+
+	serial@70006200 {
+		compatible = "nvidia,tegra20-uart";
+		reg = <0x70006200 0x100>;
+		reg-shift = <2>;
+		interrupts = < 78 >;
+	};
+
+	serial@70006300 {
+		compatible = "nvidia,tegra20-uart";
+		reg = <0x70006300 0x100>;
+		reg-shift = <2>;
+		interrupts = < 122 >;
+	};
+
+	serial@70006400 {
+		compatible = "nvidia,tegra20-uart";
+		reg = <0x70006400 0x100>;
+		reg-shift = <2>;
+		interrupts = < 123 >;
+	};
+
+	sdhci@c8000000 {
+		compatible = "nvidia,tegra20-sdhci";
+		reg = <0xc8000000 0x200>;
+		interrupts = < 46 >;
+	};
+
+	sdhci@c8000200 {
+		compatible = "nvidia,tegra20-sdhci";
+		reg = <0xc8000200 0x200>;
+		interrupts = < 47 >;
+	};
+
+	sdhci@c8000400 {
+		compatible = "nvidia,tegra20-sdhci";
+		reg = <0xc8000400 0x200>;
+		interrupts = < 51 >;
+	};
+
+	sdhci@c8000600 {
+		compatible = "nvidia,tegra20-sdhci";
+		reg = <0xc8000600 0x200>;
+		interrupts = < 63 >;
+	};
+};
+
diff --git a/arch/arm/boot/dts/versatile-ab.dts b/arch/arm/boot/dts/versatile-ab.dts
new file mode 100644
index 000000000000..0b32925f2147
--- /dev/null
+++ b/arch/arm/boot/dts/versatile-ab.dts
@@ -0,0 +1,192 @@
+/dts-v1/;
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "ARM Versatile AB";
+	compatible = "arm,versatile-ab";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&vic>;
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		i2c0 = &i2c0;
+	};
+
+	memory {
+		reg = <0x0 0x08000000>;
+	};
+
+	flash@34000000 {
+		compatible = "arm,versatile-flash";
+		reg = <0x34000000 0x4000000>;
+		bank-width = <4>;
+	};
+
+	i2c0: i2c@10002000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "arm,versatile-i2c";
+		reg = <0x10002000 0x1000>;
+
+		rtc@68 {
+			compatible = "dallas,ds1338";
+			reg = <0x68>;
+		};
+	};
+
+	net@10010000 {
+		compatible = "smsc,lan91c111";
+		reg = <0x10010000 0x10000>;
+		interrupts = <25>;
+	};
+
+	lcd@10008000 {
+		compatible = "arm,versatile-lcd";
+		reg = <0x10008000 0x1000>;
+	};
+
+	amba {
+		compatible = "arm,amba-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		vic: intc@10140000 {
+			compatible = "arm,versatile-vic";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			reg = <0x10140000 0x1000>;
+		};
+
+		sic: intc@10003000 {
+			compatible = "arm,versatile-sic";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			reg = <0x10003000 0x1000>;
+			interrupt-parent = <&vic>;
+			interrupts = <31>; /* Cascaded to vic */
+		};
+
+		dma@10130000 {
+			compatible = "arm,pl081", "arm,primecell";
+			reg = <0x10130000 0x1000>;
+			interrupts = <17>;
+		};
+
+		uart0: uart@101f1000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x101f1000 0x1000>;
+			interrupts = <12>;
+		};
+
+		uart1: uart@101f2000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x101f2000 0x1000>;
+			interrupts = <13>;
+		};
+
+		uart2: uart@101f3000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x101f3000 0x1000>;
+			interrupts = <14>;
+		};
+
+		smc@10100000 {
+			compatible = "arm,primecell";
+			reg = <0x10100000 0x1000>;
+		};
+
+		mpmc@10110000 {
+			compatible = "arm,primecell";
+			reg = <0x10110000 0x1000>;
+		};
+
+		display@10120000 {
+			compatible = "arm,pl110", "arm,primecell";
+			reg = <0x10120000 0x1000>;
+			interrupts = <16>;
+		};
+
+		sctl@101e0000 {
+			compatible = "arm,primecell";
+			reg = <0x101e0000 0x1000>;
+		};
+
+		watchdog@101e1000 {
+			compatible = "arm,primecell";
+			reg = <0x101e1000 0x1000>;
+			interrupts = <0>;
+		};
+
+		gpio0: gpio@101e4000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x101e4000 0x1000>;
+			gpio-controller;
+			interrupts = <6>;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio1: gpio@101e5000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x101e5000 0x1000>;
+			interrupts = <7>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		rtc@101e8000 {
+			compatible = "arm,pl030", "arm,primecell";
+			reg = <0x101e8000 0x1000>;
+			interrupts = <10>;
+		};
+
+		sci@101f0000 {
+			compatible = "arm,primecell";
+			reg = <0x101f0000 0x1000>;
+			interrupts = <15>;
+		};
+
+		ssp@101f4000 {
+			compatible = "arm,pl022", "arm,primecell";
+			reg = <0x101f4000 0x1000>;
+			interrupts = <11>;
+		};
+
+		fpga {
+			compatible = "arm,versatile-fpga", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x10000000 0x10000>;
+
+			aaci@4000 {
+				compatible = "arm,primecell";
+				reg = <0x4000 0x1000>;
+				interrupts = <24>;
+			};
+			mmc@5000 {
+				compatible = "arm,primecell";
+				reg = < 0x5000 0x1000>;
+				interrupts = <22>;
+			};
+			kmi@6000 {
+				compatible = "arm,pl050", "arm,primecell";
+				reg = <0x6000 0x1000>;
+				interrupt-parent = <&sic>;
+				interrupts = <3>;
+			};
+			kmi@7000 {
+				compatible = "arm,pl050", "arm,primecell";
+				reg = <0x7000 0x1000>;
+				interrupt-parent = <&sic>;
+				interrupts = <4>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/versatile-pb.dts b/arch/arm/boot/dts/versatile-pb.dts
new file mode 100644
index 000000000000..8a614e398004
--- /dev/null
+++ b/arch/arm/boot/dts/versatile-pb.dts
@@ -0,0 +1,48 @@
+/include/ "versatile-ab.dts"
+
+/ {
+	model = "ARM Versatile PB";
+	compatible = "arm,versatile-pb";
+
+	amba {
+		gpio2: gpio@101e6000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x101e6000 0x1000>;
+			interrupts = <8>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio3: gpio@101e7000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x101e7000 0x1000>;
+			interrupts = <9>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		fpga {
+			uart@9000 {
+				compatible = "arm,pl011", "arm,primecell";
+				reg = <0x9000 0x1000>;
+				interrupt-parent = <&sic>;
+				interrupts = <6>;
+			};
+			sci@a000 {
+				compatible = "arm,primecell";
+				reg = <0xa000 0x1000>;
+				interrupt-parent = <&sic>;
+				interrupts = <5>;
+			};
+			mmc@b000 {
+				compatible = "arm,primecell";
+				reg = <0xb000 0x1000>;
+				interrupts = <23>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index 3281fb4b12e3..217aa1911dd7 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -74,4 +74,11 @@ static const struct machine_desc __mach_desc_##_type	\
 #define MACHINE_END				\
 };
 
+#define DT_MACHINE_START(_name, _namestr)		\
+static const struct machine_desc __mach_desc_##_name	\
+ __used							\
+ __attribute__((__section__(".arch.info.init"))) = {	\
+	.nr		= ~0,				\
+	.name		= _namestr,
+
 #endif
diff --git a/arch/arm/include/asm/prom.h b/arch/arm/include/asm/prom.h
index 11b8708fc4db..6f65ca86a5ec 100644
--- a/arch/arm/include/asm/prom.h
+++ b/arch/arm/include/asm/prom.h
@@ -16,11 +16,6 @@
 #include <asm/setup.h>
 #include <asm/irq.h>
 
-static inline void irq_dispose_mapping(unsigned int virq)
-{
-	return;
-}
-
 extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
 extern void arm_dt_memblock_reserve(void);
 
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
index 0cdd7b456cb2..1a33e9d6bb1f 100644
--- a/arch/arm/kernel/devtree.c
+++ b/arch/arm/kernel/devtree.c
@@ -132,17 +132,3 @@ struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
 
 	return mdesc_best;
 }
-
-/**
- * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq#
- *
- * Currently the mapping mechanism is trivial; simple flat hwirq numbers are
- * mapped 1:1 onto Linux irq numbers.  Cascaded irq controllers are not
- * supported.
- */
-unsigned int irq_create_of_mapping(struct device_node *controller,
-				   const u32 *intspec, unsigned int intsize)
-{
-	return intspec[0];
-}
-EXPORT_SYMBOL_GPL(irq_create_of_mapping);
diff --git a/arch/arm/mach-imx/clock-imx1.c b/arch/arm/mach-imx/clock-imx1.c
index dcc41728fe72..4aabeb241563 100644
--- a/arch/arm/mach-imx/clock-imx1.c
+++ b/arch/arm/mach-imx/clock-imx1.c
@@ -587,9 +587,9 @@ static struct clk_lookup lookups[] __initdata = {
 	_REGISTER_CLOCK(NULL, "mma", mma_clk)
 	_REGISTER_CLOCK("imx_udc.0", NULL, usbd_clk)
 	_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
-	_REGISTER_CLOCK("imx-uart.0", NULL, uart_clk)
-	_REGISTER_CLOCK("imx-uart.1", NULL, uart_clk)
-	_REGISTER_CLOCK("imx-uart.2", NULL, uart_clk)
+	_REGISTER_CLOCK("imx1-uart.0", NULL, uart_clk)
+	_REGISTER_CLOCK("imx1-uart.1", NULL, uart_clk)
+	_REGISTER_CLOCK("imx1-uart.2", NULL, uart_clk)
 	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
 	_REGISTER_CLOCK("imx1-cspi.0", NULL, spi_clk)
 	_REGISTER_CLOCK("imx1-cspi.1", NULL, spi_clk)
diff --git a/arch/arm/mach-imx/clock-imx21.c b/arch/arm/mach-imx/clock-imx21.c
index bf30a8c7ce6f..ee15d8c9db08 100644
--- a/arch/arm/mach-imx/clock-imx21.c
+++ b/arch/arm/mach-imx/clock-imx21.c
@@ -1162,10 +1162,10 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK(NULL, "perclk3", per_clk[2])
 	_REGISTER_CLOCK(NULL, "perclk4", per_clk[3])
 	_REGISTER_CLOCK(NULL, "clko", clko_clk)
-	_REGISTER_CLOCK("imx-uart.0", NULL, uart_clk[0])
-	_REGISTER_CLOCK("imx-uart.1", NULL, uart_clk[1])
-	_REGISTER_CLOCK("imx-uart.2", NULL, uart_clk[2])
-	_REGISTER_CLOCK("imx-uart.3", NULL, uart_clk[3])
+	_REGISTER_CLOCK("imx21-uart.0", NULL, uart_clk[0])
+	_REGISTER_CLOCK("imx21-uart.1", NULL, uart_clk[1])
+	_REGISTER_CLOCK("imx21-uart.2", NULL, uart_clk[2])
+	_REGISTER_CLOCK("imx21-uart.3", NULL, uart_clk[3])
 	_REGISTER_CLOCK(NULL, "gpt1", gpt_clk[0])
 	_REGISTER_CLOCK(NULL, "gpt1", gpt_clk[1])
 	_REGISTER_CLOCK(NULL, "gpt1", gpt_clk[2])
diff --git a/arch/arm/mach-imx/clock-imx25.c b/arch/arm/mach-imx/clock-imx25.c
index af1c580b06bc..0fc7ba56d616 100644
--- a/arch/arm/mach-imx/clock-imx25.c
+++ b/arch/arm/mach-imx/clock-imx25.c
@@ -272,11 +272,12 @@ DEFINE_CLOCK(can2_clk,	 1, CCM_CGCR1,  3, get_rate_ipg, NULL, NULL);
 	},
 
 static struct clk_lookup lookups[] = {
-	_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
-	_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
-	_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
-	_REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
-	_REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
+	/* i.mx25 has the i.mx21 type uart */
+	_REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
+	_REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
+	_REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
+	_REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
+	_REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
 	_REGISTER_CLOCK("mxc-ehci.0", "usb", usbotg_clk)
 	_REGISTER_CLOCK("mxc-ehci.1", "usb", usbotg_clk)
 	_REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk)
@@ -295,19 +296,20 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
 	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c_clk)
 	_REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk)
-	_REGISTER_CLOCK("fec.0", NULL, fec_clk)
+	_REGISTER_CLOCK("imx25-fec.0", NULL, fec_clk)
 	_REGISTER_CLOCK("imxdi_rtc.0", NULL, dryice_clk)
 	_REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk)
 	_REGISTER_CLOCK("imx2-wdt.0", NULL, wdt_clk)
 	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
 	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx25.0", NULL, esdhc1_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx25.1", NULL, esdhc2_clk)
 	_REGISTER_CLOCK("mx2-camera.0", NULL, csi_clk)
 	_REGISTER_CLOCK(NULL, "audmux", audmux_clk)
 	_REGISTER_CLOCK("flexcan.0", NULL, can1_clk)
 	_REGISTER_CLOCK("flexcan.1", NULL, can2_clk)
-	_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
+	/* i.mx25 has the i.mx35 type sdma */
+	_REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
 };
 
 int __init mx25_clocks_init(void)
diff --git a/arch/arm/mach-imx/clock-imx27.c b/arch/arm/mach-imx/clock-imx27.c
index 583f2515c1d5..6912b821b37b 100644
--- a/arch/arm/mach-imx/clock-imx27.c
+++ b/arch/arm/mach-imx/clock-imx27.c
@@ -624,12 +624,13 @@ DEFINE_CLOCK1(csi_clk,     0, NULL,   0, parent, &csi_clk1, &per4_clk);
 	},
 
 static struct clk_lookup lookups[] = {
-	_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
-	_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
-	_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
-	_REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
-	_REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
-	_REGISTER_CLOCK("imx-uart.5", NULL, uart6_clk)
+	/* i.mx27 has the i.mx21 type uart */
+	_REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
+	_REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
+	_REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
+	_REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
+	_REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
+	_REGISTER_CLOCK("imx21-uart.5", NULL, uart6_clk)
 	_REGISTER_CLOCK(NULL, "gpt1", gpt1_clk)
 	_REGISTER_CLOCK(NULL, "gpt2", gpt2_clk)
 	_REGISTER_CLOCK(NULL, "gpt3", gpt3_clk)
@@ -662,7 +663,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK(NULL, "brom", brom_clk)
 	_REGISTER_CLOCK(NULL, "emma", emma_clk)
 	_REGISTER_CLOCK(NULL, "slcdc", slcdc_clk)
-	_REGISTER_CLOCK("fec.0", NULL, fec_clk)
+	_REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
 	_REGISTER_CLOCK(NULL, "emi", emi_clk)
 	_REGISTER_CLOCK(NULL, "sahara2", sahara2_clk)
 	_REGISTER_CLOCK(NULL, "ata", ata_clk)
diff --git a/arch/arm/mach-imx/clock-imx31.c b/arch/arm/mach-imx/clock-imx31.c
index 25f343fca2b9..d973770b1f96 100644
--- a/arch/arm/mach-imx/clock-imx31.c
+++ b/arch/arm/mach-imx/clock-imx31.c
@@ -547,11 +547,12 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk1)
 	_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usb_clk2)
 	_REGISTER_CLOCK("mx3-camera.0", NULL, csi_clk)
-	_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
-	_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
-	_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
-	_REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
-	_REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
+	/* i.mx31 has the i.mx21 type uart */
+	_REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
+	_REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
+	_REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
+	_REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
+	_REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
 	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
 	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
 	_REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_clk)
@@ -564,7 +565,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK(NULL, "ata", ata_clk)
 	_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
 	_REGISTER_CLOCK(NULL, "rng", rng_clk)
-	_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk1)
+	_REGISTER_CLOCK("imx31-sdma", NULL, sdma_clk1)
 	_REGISTER_CLOCK(NULL, "sdma_ipg", sdma_clk2)
 	_REGISTER_CLOCK(NULL, "mstick", mstick1_clk)
 	_REGISTER_CLOCK(NULL, "mstick", mstick2_clk)
diff --git a/arch/arm/mach-imx/clock-imx35.c b/arch/arm/mach-imx/clock-imx35.c
index 5a4cc1ea405b..88b62a071aea 100644
--- a/arch/arm/mach-imx/clock-imx35.c
+++ b/arch/arm/mach-imx/clock-imx35.c
@@ -458,10 +458,11 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("imx-epit.0", NULL, epit1_clk)
 	_REGISTER_CLOCK("imx-epit.1", NULL, epit2_clk)
 	_REGISTER_CLOCK(NULL, "esai", esai_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_clk)
-	_REGISTER_CLOCK("fec.0", NULL, fec_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx35.0", NULL, esdhc1_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx35.1", NULL, esdhc2_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx35.2", NULL, esdhc3_clk)
+	/* i.mx35 has the i.mx27 type fec */
+	_REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
 	_REGISTER_CLOCK(NULL, "gpio", gpio1_clk)
 	_REGISTER_CLOCK(NULL, "gpio", gpio2_clk)
 	_REGISTER_CLOCK(NULL, "gpio", gpio3_clk)
@@ -481,14 +482,15 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK(NULL, "rtc", rtc_clk)
 	_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
 	_REGISTER_CLOCK(NULL, "scc", scc_clk)
-	_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
+	_REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
 	_REGISTER_CLOCK(NULL, "spba", spba_clk)
 	_REGISTER_CLOCK(NULL, "spdif", spdif_clk)
 	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
 	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
-	_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
-	_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
-	_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
+	/* i.mx35 has the i.mx21 type uart */
+	_REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
+	_REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
+	_REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
 	_REGISTER_CLOCK("mxc-ehci.0", "usb", usbotg_clk)
 	_REGISTER_CLOCK("mxc-ehci.1", "usb", usbotg_clk)
 	_REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk)
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
index 01ebcb31e482..66e8726253fa 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
@@ -225,7 +225,8 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
 
 static struct esdhc_platform_data sd1_pdata = {
 	.cd_gpio = GPIO_SD1CD,
-	.wp_gpio = -EINVAL,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_NONE,
 };
 
 /*
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
index 558eb526ba56..0f0af02b3182 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
@@ -236,7 +236,8 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
 
 static struct esdhc_platform_data sd1_pdata = {
 	.cd_gpio = GPIO_SD1CD,
-	.wp_gpio = -EINVAL,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_NONE,
 };
 
 /*
diff --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c
index 01534bb61305..7f66a91df361 100644
--- a/arch/arm/mach-imx/mach-mx25_3ds.c
+++ b/arch/arm/mach-imx/mach-mx25_3ds.c
@@ -215,6 +215,8 @@ static const struct imxi2c_platform_data mx25_3ds_i2c0_data __initconst = {
 static const struct esdhc_platform_data mx25pdk_esdhc_pdata __initconst = {
 	.wp_gpio = SD1_GPIO_WP,
 	.cd_gpio = SD1_GPIO_CD,
+	.wp_type = ESDHC_WP_GPIO,
+	.cd_type = ESDHC_CD_GPIO,
 };
 
 static void __init mx25pdk_init(void)
diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c
index 163cc318cafb..660ec3e80cf8 100644
--- a/arch/arm/mach-imx/mach-pcm043.c
+++ b/arch/arm/mach-imx/mach-pcm043.c
@@ -349,6 +349,8 @@ __setup("otg_mode=", pcm043_otg_mode);
 static struct esdhc_platform_data sd1_pdata = {
 	.wp_gpio = SD1_GPIO_WP,
 	.cd_gpio = SD1_GPIO_CD,
+	.wp_type = ESDHC_WP_GPIO,
+	.cd_type = ESDHC_CD_GPIO,
 };
 
 /*
diff --git a/arch/arm/mach-imx/mm-imx25.c b/arch/arm/mach-imx/mm-imx25.c
index 8bf029164652..cc4d152bd9bd 100644
--- a/arch/arm/mach-imx/mm-imx25.c
+++ b/arch/arm/mach-imx/mm-imx25.c
@@ -79,7 +79,6 @@ static struct sdma_script_start_addrs imx25_sdma_script __initdata = {
 };
 
 static struct sdma_platform_data imx25_sdma_pdata __initdata = {
-	.sdma_version = 2,
 	.fw_name = "sdma-imx25.bin",
 	.script_addrs = &imx25_sdma_script,
 };
@@ -92,5 +91,6 @@ void __init imx25_soc_init(void)
 	mxc_register_gpio("imx31-gpio", 2, MX25_GPIO3_BASE_ADDR, SZ_16K, MX25_INT_GPIO3, 0);
 	mxc_register_gpio("imx31-gpio", 3, MX25_GPIO4_BASE_ADDR, SZ_16K, MX25_INT_GPIO4, 0);
 
-	imx_add_imx_sdma(MX25_SDMA_BASE_ADDR, MX25_INT_SDMA, &imx25_sdma_pdata);
+	/* i.mx25 has the i.mx35 type sdma */
+	imx_add_imx_sdma("imx35-sdma", MX25_SDMA_BASE_ADDR, MX25_INT_SDMA, &imx25_sdma_pdata);
 }
diff --git a/arch/arm/mach-imx/mm-imx31.c b/arch/arm/mach-imx/mm-imx31.c
index 61bff38cb955..b7c55e7db000 100644
--- a/arch/arm/mach-imx/mm-imx31.c
+++ b/arch/arm/mach-imx/mm-imx31.c
@@ -69,7 +69,6 @@ static struct sdma_script_start_addrs imx31_to2_sdma_script __initdata = {
 };
 
 static struct sdma_platform_data imx31_sdma_pdata __initdata = {
-	.sdma_version = 1,
 	.fw_name = "sdma-imx31-to2.bin",
 	.script_addrs = &imx31_to2_sdma_script,
 };
@@ -88,5 +87,5 @@ void __init imx31_soc_init(void)
 		imx31_sdma_pdata.script_addrs = &imx31_to1_sdma_script;
 	}
 
-	imx_add_imx_sdma(MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
+	imx_add_imx_sdma("imx31-sdma", MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
 }
diff --git a/arch/arm/mach-imx/mm-imx35.c b/arch/arm/mach-imx/mm-imx35.c
index 98769ae34377..f49bac7a1ede 100644
--- a/arch/arm/mach-imx/mm-imx35.c
+++ b/arch/arm/mach-imx/mm-imx35.c
@@ -86,7 +86,6 @@ static struct sdma_script_start_addrs imx35_to2_sdma_script __initdata = {
 };
 
 static struct sdma_platform_data imx35_sdma_pdata __initdata = {
-	.sdma_version = 2,
 	.fw_name = "sdma-imx35-to2.bin",
 	.script_addrs = &imx35_to2_sdma_script,
 };
@@ -106,5 +105,5 @@ void __init imx35_soc_init(void)
 		imx35_sdma_pdata.script_addrs = &imx35_to1_sdma_script;
 	}
 
-	imx_add_imx_sdma(MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
+	imx_add_imx_sdma("imx35-sdma", MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
 }
diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c
index 15c600026aee..e400b09109ce 100644
--- a/arch/arm/mach-mx5/board-mx51_babbage.c
+++ b/arch/arm/mach-mx5/board-mx51_babbage.c
@@ -41,8 +41,6 @@
 #define BABBAGE_POWER_KEY	IMX_GPIO_NR(2, 21)
 #define BABBAGE_ECSPI1_CS0	IMX_GPIO_NR(4, 24)
 #define BABBAGE_ECSPI1_CS1	IMX_GPIO_NR(4, 25)
-#define BABBAGE_SD1_CD		IMX_GPIO_NR(1, 0)
-#define BABBAGE_SD1_WP		IMX_GPIO_NR(1, 1)
 #define BABBAGE_SD2_CD		IMX_GPIO_NR(1, 6)
 #define BABBAGE_SD2_WP		IMX_GPIO_NR(1, 5)
 
@@ -146,8 +144,9 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
 	MX51_PAD_SD1_DATA1__SD1_DATA1,
 	MX51_PAD_SD1_DATA2__SD1_DATA2,
 	MX51_PAD_SD1_DATA3__SD1_DATA3,
-	MX51_PAD_GPIO1_0__GPIO1_0,
-	MX51_PAD_GPIO1_1__GPIO1_1,
+	/* CD/WP from controller */
+	MX51_PAD_GPIO1_0__SD1_CD,
+	MX51_PAD_GPIO1_1__SD1_WP,
 
 	/* SD 2 */
 	MX51_PAD_SD2_CMD__SD2_CMD,
@@ -156,6 +155,7 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
 	MX51_PAD_SD2_DATA1__SD2_DATA1,
 	MX51_PAD_SD2_DATA2__SD2_DATA2,
 	MX51_PAD_SD2_DATA3__SD2_DATA3,
+	/* CD/WP gpio */
 	MX51_PAD_GPIO1_6__GPIO1_6,
 	MX51_PAD_GPIO1_5__GPIO1_5,
 
@@ -340,13 +340,15 @@ static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = {
 };
 
 static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = {
-	.cd_gpio = BABBAGE_SD1_CD,
-	.wp_gpio = BABBAGE_SD1_WP,
+	.cd_type = ESDHC_CD_CONTROLLER,
+	.wp_type = ESDHC_WP_CONTROLLER,
 };
 
 static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = {
 	.cd_gpio = BABBAGE_SD2_CD,
 	.wp_gpio = BABBAGE_SD2_WP,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_GPIO,
 };
 
 /*
diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c
index 54be525e2bd7..4e1d51d252dc 100644
--- a/arch/arm/mach-mx5/board-mx53_loco.c
+++ b/arch/arm/mach-mx5/board-mx53_loco.c
@@ -210,11 +210,15 @@ static const struct gpio_keys_platform_data loco_button_data __initconst = {
 
 static const struct esdhc_platform_data mx53_loco_sd1_data __initconst = {
 	.cd_gpio = LOCO_SD1_CD,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_NONE,
 };
 
 static const struct esdhc_platform_data mx53_loco_sd3_data __initconst = {
 	.cd_gpio = LOCO_SD3_CD,
 	.wp_gpio = LOCO_SD3_WP,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_GPIO,
 };
 
 static inline void mx53_loco_fec_reset(void)
diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
index 23cd809fa8b8..7f20308c4dbd 100644
--- a/arch/arm/mach-mx5/clock-mx51-mx53.c
+++ b/arch/arm/mach-mx5/clock-mx51-mx53.c
@@ -1422,11 +1422,13 @@ DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET,
        },
 
 static struct clk_lookup mx51_lookups[] = {
-	_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
-	_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
-	_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
+	/* i.mx51 has the i.mx21 type uart */
+	_REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
+	_REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
+	_REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
 	_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
-	_REGISTER_CLOCK("fec.0", NULL, fec_clk)
+	/* i.mx51 has the i.mx27 type fec */
+	_REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
 	_REGISTER_CLOCK("mxc_pwm.0", "pwm", pwm1_clk)
 	_REGISTER_CLOCK("mxc_pwm.1", "pwm", pwm2_clk)
 	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
@@ -1446,7 +1448,8 @@ static struct clk_lookup mx51_lookups[] = {
 	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
 	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
 	_REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
-	_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
+	/* i.mx51 has the i.mx35 type sdma */
+	_REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
 	_REGISTER_CLOCK(NULL, "ckih", ckih_clk)
 	_REGISTER_CLOCK(NULL, "ckih2", ckih2_clk)
 	_REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)
@@ -1454,10 +1457,10 @@ static struct clk_lookup mx51_lookups[] = {
 	_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
 	/* i.mx51 has the i.mx35 type cspi */
 	_REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.3", NULL, esdhc4_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx51.0", NULL, esdhc1_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx51.1", NULL, esdhc2_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx51.2", NULL, esdhc3_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx51.3", NULL, esdhc4_clk)
 	_REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk)
 	_REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
 	_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
@@ -1470,29 +1473,32 @@ static struct clk_lookup mx51_lookups[] = {
 };
 
 static struct clk_lookup mx53_lookups[] = {
-	_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
-	_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
-	_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
-	_REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
-	_REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
+	/* i.mx53 has the i.mx21 type uart */
+	_REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
+	_REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
+	_REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
+	_REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
+	_REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
 	_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
-	_REGISTER_CLOCK("fec.0", NULL, fec_clk)
+	/* i.mx53 has the i.mx25 type fec */
+	_REGISTER_CLOCK("imx25-fec.0", NULL, fec_clk)
 	_REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
 	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
 	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
 	_REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_mx53_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_mx53_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_mx53_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.3", NULL, esdhc4_mx53_clk)
 	/* i.mx53 has the i.mx51 type ecspi */
 	_REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
 	_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
 	/* i.mx53 has the i.mx25 type cspi */
 	_REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx53.0", NULL, esdhc1_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx53.1", NULL, esdhc2_mx53_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx53.2", NULL, esdhc3_mx53_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx53.3", NULL, esdhc4_mx53_clk)
 	_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
 	_REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
-	_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
+	/* i.mx53 has the i.mx35 type sdma */
+	_REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
 	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
 	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
 	_REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
diff --git a/arch/arm/mach-mx5/mm.c b/arch/arm/mach-mx5/mm.c
index ef8aec9319b6..baea6e5cddd9 100644
--- a/arch/arm/mach-mx5/mm.c
+++ b/arch/arm/mach-mx5/mm.c
@@ -115,7 +115,6 @@ static struct sdma_script_start_addrs imx51_sdma_script __initdata = {
 };
 
 static struct sdma_platform_data imx51_sdma_pdata __initdata = {
-	.sdma_version = 2,
 	.fw_name = "sdma-imx51.bin",
 	.script_addrs = &imx51_sdma_script,
 };
@@ -135,7 +134,6 @@ static struct sdma_script_start_addrs imx53_sdma_script __initdata = {
 };
 
 static struct sdma_platform_data imx53_sdma_pdata __initdata = {
-	.sdma_version = 2,
 	.fw_name = "sdma-imx53.bin",
 	.script_addrs = &imx53_sdma_script,
 };
@@ -148,7 +146,8 @@ void __init imx51_soc_init(void)
 	mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO3_LOW, MX51_MXC_INT_GPIO3_HIGH);
 	mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO4_LOW, MX51_MXC_INT_GPIO4_HIGH);
 
-	imx_add_imx_sdma(MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
+	/* i.mx51 has the i.mx35 type sdma */
+	imx_add_imx_sdma("imx35-sdma", MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
 }
 
 void __init imx53_soc_init(void)
@@ -162,5 +161,6 @@ void __init imx53_soc_init(void)
 	mxc_register_gpio("imx31-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH);
 	mxc_register_gpio("imx31-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);
 
-	imx_add_imx_sdma(MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata);
+	/* i.mx53 has the i.mx35 type sdma */
+	imx_add_imx_sdma("imx35-sdma", MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata);
 }
diff --git a/arch/arm/mach-mx5/mx51_efika.c b/arch/arm/mach-mx5/mx51_efika.c
index 56739c23aca7..4435e03cea5d 100644
--- a/arch/arm/mach-mx5/mx51_efika.c
+++ b/arch/arm/mach-mx5/mx51_efika.c
@@ -260,8 +260,8 @@ static struct regulator_consumer_supply vvideo_consumers[] = {
 };
 
 static struct regulator_consumer_supply vsd_consumers[] = {
-	REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.0"),
-	REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.1"),
+	REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.0"),
+	REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.1"),
 };
 
 static struct regulator_consumer_supply pwgt1_consumer[] = {
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index fec64f3aa68e..d82ebab50e11 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -51,6 +51,12 @@ config MACH_SEABOARD
 	 also be included for some of the derivative boards that
 	 have large similarities with the seaboard design.
 
+config MACH_TEGRA_DT
+	bool "Generic Tegra board (FDT support)"
+	select USE_OF
+	help
+	  Support for generic nVidia Tegra boards using Flattened Device Tree
+
 config MACH_TRIMSLICE
        bool "TrimSlice board"
        select TEGRA_PCI
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index ed58ef9019b5..f11b9100114a 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -29,5 +29,8 @@ obj-${CONFIG_MACH_PAZ00}		+= board-paz00-pinmux.o
 obj-${CONFIG_MACH_SEABOARD}             += board-seaboard.o
 obj-${CONFIG_MACH_SEABOARD}             += board-seaboard-pinmux.o
 
+obj-${CONFIG_MACH_TEGRA_DT}             += board-dt.o
+obj-${CONFIG_MACH_TEGRA_DT}             += board-harmony-pinmux.o
+
 obj-${CONFIG_MACH_TRIMSLICE}            += board-trimslice.o
 obj-${CONFIG_MACH_TRIMSLICE}            += board-trimslice-pinmux.o
diff --git a/arch/arm/mach-tegra/Makefile.boot b/arch/arm/mach-tegra/Makefile.boot
index db52d61a7386..428ad122be03 100644
--- a/arch/arm/mach-tegra/Makefile.boot
+++ b/arch/arm/mach-tegra/Makefile.boot
@@ -1,3 +1,6 @@
 zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC)	:= 0x00008000
 params_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)	:= 0x00000100
 initrd_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)	:= 0x00800000
+
+dtb-$(CONFIG_MACH_HARMONY) += tegra-harmony.dtb
+dtb-$(CONFIG_MACH_SEABOARD) += tegra-seaboard.dtb
diff --git a/arch/arm/mach-tegra/board-dt.c b/arch/arm/mach-tegra/board-dt.c
new file mode 100644
index 000000000000..9f47e04446f3
--- /dev/null
+++ b/arch/arm/mach-tegra/board-dt.c
@@ -0,0 +1,119 @@
+/*
+ * nVidia Tegra device tree board support
+ *
+ * Copyright (C) 2010 Secret Lab Technologies, Ltd.
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/pda_power.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/i2c-tegra.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/setup.h>
+
+#include <mach/iomap.h>
+#include <mach/irqs.h>
+
+#include "board.h"
+#include "board-harmony.h"
+#include "clock.h"
+#include "devices.h"
+
+void harmony_pinmux_init(void);
+void seaboard_pinmux_init(void);
+
+
+struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
+	OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC1_BASE, "sdhci-tegra.0", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC2_BASE, "sdhci-tegra.1", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC3_BASE, "sdhci-tegra.2", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC4_BASE, "sdhci-tegra.3", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C_BASE, "tegra-i2c.0", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C2_BASE, "tegra-i2c.1", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C3_BASE, "tegra-i2c.2", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_DVC_BASE, "tegra-i2c.3", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra-i2s.0", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra-i2s.1", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-das", TEGRA_APB_MISC_DAS_BASE, "tegra-das", NULL),
+	{}
+};
+
+static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
+	/* name		parent		rate		enabled */
+	{ "uartd",	"pll_p",	216000000,	true },
+	{ NULL,		NULL,		0,		0},
+};
+
+static struct of_device_id tegra_dt_match_table[] __initdata = {
+	{ .compatible = "simple-bus", },
+	{}
+};
+
+static struct of_device_id tegra_dt_gic_match[] __initdata = {
+	{ .compatible = "nvidia,tegra20-gic", },
+	{}
+};
+
+static void __init tegra_dt_init(void)
+{
+	struct device_node *node;
+
+	node = of_find_matching_node_by_address(NULL, tegra_dt_gic_match,
+						TEGRA_ARM_INT_DIST_BASE);
+	if (node)
+		irq_domain_add_simple(node, INT_GIC_BASE);
+
+	tegra_clk_init_from_table(tegra_dt_clk_init_table);
+
+	if (of_machine_is_compatible("nvidia,harmony"))
+		harmony_pinmux_init();
+	else if (of_machine_is_compatible("nvidia,seaboard"))
+		seaboard_pinmux_init();
+
+	/*
+	 * Finished with the static registrations now; fill in the missing
+	 * devices
+	 */
+	of_platform_populate(NULL, tegra_dt_match_table, tegra20_auxdata_lookup, NULL);
+}
+
+static const char * tegra_dt_board_compat[] = {
+	"nvidia,harmony",
+	"nvidia,seaboard",
+	NULL
+};
+
+DT_MACHINE_START(TEGRA_DT, "nVidia Tegra (Flattened Device Tree)")
+	.map_io		= tegra_map_common_io,
+	.init_early	= tegra_init_early,
+	.init_irq	= tegra_init_irq,
+	.timer		= &tegra_timer,
+	.init_machine	= tegra_dt_init,
+	.dt_compat	= tegra_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-versatile/Kconfig b/arch/arm/mach-versatile/Kconfig
index 9cdec5aa04a0..c1f38f6625b2 100644
--- a/arch/arm/mach-versatile/Kconfig
+++ b/arch/arm/mach-versatile/Kconfig
@@ -17,4 +17,12 @@ config MACH_VERSATILE_AB
 	  Include support for the ARM(R) Versatile Application Baseboard
 	  for the ARM926EJ-S.
 
+config MACH_VERSATILE_DT
+	bool "Support Versatile platform from device tree"
+	select USE_OF
+	select CPU_ARM926T
+	help
+	  Include support for the ARM(R) Versatile/PB platform,
+	  using the device tree for discovery
+
 endmenu
diff --git a/arch/arm/mach-versatile/Makefile b/arch/arm/mach-versatile/Makefile
index 97cf4d831b0c..81fa3fe25e1a 100644
--- a/arch/arm/mach-versatile/Makefile
+++ b/arch/arm/mach-versatile/Makefile
@@ -5,4 +5,5 @@
 obj-y					:= core.o
 obj-$(CONFIG_ARCH_VERSATILE_PB)		+= versatile_pb.o
 obj-$(CONFIG_MACH_VERSATILE_AB)		+= versatile_ab.o
+obj-$(CONFIG_MACH_VERSATILE_DT)		+= versatile_dt.o
 obj-$(CONFIG_PCI)			+= pci.o
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 0c99cf076c63..e340a54251df 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -24,6 +24,9 @@
 #include <linux/platform_device.h>
 #include <linux/sysdev.h>
 #include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
 #include <linux/amba/pl061.h>
@@ -83,13 +86,26 @@ static struct fpga_irq_data sic_irq = {
 #define PIC_MASK	0
 #endif
 
+/* Lookup table for finding a DT node that represents the vic instance */
+static const struct of_device_id vic_of_match[] __initconst = {
+	{ .compatible = "arm,versatile-vic", },
+	{}
+};
+
+static const struct of_device_id sic_of_match[] __initconst = {
+	{ .compatible = "arm,versatile-sic", },
+	{}
+};
+
 void __init versatile_init_irq(void)
 {
 	vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0);
+	irq_domain_generate_simple(vic_of_match, VERSATILE_VIC_BASE, IRQ_VIC_START);
 
 	writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
 
 	fpga_irq_init(IRQ_VICSOURCE31, ~PIC_MASK, &sic_irq);
+	irq_domain_generate_simple(sic_of_match, VERSATILE_SIC_BASE, IRQ_SIC_START);
 
 	/*
 	 * Interrupts on secondary controller from 0 to 8 are routed to
@@ -646,6 +662,52 @@ static struct amba_device *amba_devs[] __initdata = {
 	&kmi1_device,
 };
 
+#ifdef CONFIG_OF
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate().  Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+struct of_dev_auxdata versatile_auxdata_lookup[] __initdata = {
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_MMCI0_BASE, "fpga:05", NULL),
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_KMI0_BASE, "fpga:06", NULL),
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_KMI1_BASE, "fpga:07", NULL),
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART3_BASE, "fpga:09", NULL),
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_MMCI1_BASE, "fpga:0b", NULL),
+
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_CLCD_BASE, "dev:20", &clcd_plat_data),
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART0_BASE, "dev:f1", NULL),
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART1_BASE, "dev:f2", NULL),
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_UART2_BASE, "dev:f3", NULL),
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_SSP_BASE, "dev:f4", NULL),
+
+#if 0
+	/*
+	 * These entries are unnecessary because no clocks referencing
+	 * them.  I've left them in for now as place holders in case
+	 * any of them need to be added back, but they should be
+	 * removed before actually committing this patch.  --gcl
+	 */
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_AACI_BASE, "fpga:04", NULL),
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_SCI1_BASE, "fpga:0a", NULL),
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_SMC_BASE, "dev:00", NULL),
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_MPMC_BASE, "dev:10", NULL),
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_DMAC_BASE, "dev:30", NULL),
+
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_SCTL_BASE, "dev:e0", NULL),
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_WATCHDOG_BASE, "dev:e1", NULL),
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_GPIO0_BASE, "dev:e4", NULL),
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_GPIO1_BASE, "dev:e5", NULL),
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_GPIO2_BASE, "dev:e6", NULL),
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_GPIO3_BASE, "dev:e7", NULL),
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_RTC_BASE, "dev:e8", NULL),
+	OF_DEV_AUXDATA("arm,primecell", VERSATILE_SCI_BASE, "dev:f0", NULL),
+#endif
+	{}
+};
+#endif
+
 #ifdef CONFIG_LEDS
 #define VA_LEDS_BASE (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_LED_OFFSET)
 
diff --git a/arch/arm/mach-versatile/core.h b/arch/arm/mach-versatile/core.h
index fd6404e5d788..e01422700ebb 100644
--- a/arch/arm/mach-versatile/core.h
+++ b/arch/arm/mach-versatile/core.h
@@ -23,6 +23,7 @@
 #define __ASM_ARCH_VERSATILE_H
 
 #include <linux/amba/bus.h>
+#include <linux/of_platform.h>
 
 extern void __init versatile_init(void);
 extern void __init versatile_init_early(void);
@@ -30,6 +31,9 @@ extern void __init versatile_init_irq(void);
 extern void __init versatile_map_io(void);
 extern struct sys_timer versatile_timer;
 extern unsigned int mmc_status(struct device *dev);
+#ifdef CONFIG_OF
+extern struct of_dev_auxdata versatile_auxdata_lookup[];
+#endif
 
 #define AMBA_DEVICE(name,busid,base,plat)			\
 static struct amba_device name##_device = {			\
diff --git a/arch/arm/mach-versatile/versatile_dt.c b/arch/arm/mach-versatile/versatile_dt.c
new file mode 100644
index 000000000000..54e037c090f5
--- /dev/null
+++ b/arch/arm/mach-versatile/versatile_dt.c
@@ -0,0 +1,51 @@
+/*
+ * Versatile board support using the device tree
+ *
+ *  Copyright (C) 2010 Secret Lab Technologies Ltd.
+ *  Copyright (C) 2009 Jeremy Kerr <jeremy.kerr@canonical.com>
+ *  Copyright (C) 2004 ARM Limited
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * 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
+ */
+
+#include <linux/init.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include "core.h"
+
+static void __init versatile_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     versatile_auxdata_lookup, NULL);
+}
+
+static const char *versatile_dt_match[] __initconst = {
+	"arm,versatile-ab",
+	"arm,versatile-pb",
+	NULL,
+};
+
+DT_MACHINE_START(VERSATILE_PB, "ARM-Versatile (Device Tree Support)")
+	.map_io		= versatile_map_io,
+	.init_early	= versatile_init_early,
+	.init_irq	= versatile_init_irq,
+	.timer		= &versatile_timer,
+	.init_machine	= versatile_dt_init,
+	.dt_compat	= versatile_dt_match,
+MACHINE_END
diff --git a/arch/arm/plat-mxc/devices/platform-fec.c b/arch/arm/plat-mxc/devices/platform-fec.c
index 4fc6ffc2a13e..0bae44e890db 100644
--- a/arch/arm/plat-mxc/devices/platform-fec.c
+++ b/arch/arm/plat-mxc/devices/platform-fec.c
@@ -11,40 +11,45 @@
 #include <mach/hardware.h>
 #include <mach/devices-common.h>
 
-#define imx_fec_data_entry_single(soc)					\
+#define imx_fec_data_entry_single(soc, _devid)				\
 	{								\
+		.devid = _devid,					\
 		.iobase = soc ## _FEC_BASE_ADDR,			\
 		.irq = soc ## _INT_FEC,					\
 	}
 
 #ifdef CONFIG_SOC_IMX25
 const struct imx_fec_data imx25_fec_data __initconst =
-	imx_fec_data_entry_single(MX25);
+	imx_fec_data_entry_single(MX25, "imx25-fec");
 #endif /* ifdef CONFIG_SOC_IMX25 */
 
 #ifdef CONFIG_SOC_IMX27
 const struct imx_fec_data imx27_fec_data __initconst =
-	imx_fec_data_entry_single(MX27);
+	imx_fec_data_entry_single(MX27, "imx27-fec");
 #endif /* ifdef CONFIG_SOC_IMX27 */
 
 #ifdef CONFIG_SOC_IMX35
+/* i.mx35 has the i.mx27 type fec */
 const struct imx_fec_data imx35_fec_data __initconst =
-	imx_fec_data_entry_single(MX35);
+	imx_fec_data_entry_single(MX35, "imx27-fec");
 #endif
 
 #ifdef CONFIG_SOC_IMX50
+/* i.mx50 has the i.mx25 type fec */
 const struct imx_fec_data imx50_fec_data __initconst =
-	imx_fec_data_entry_single(MX50);
+	imx_fec_data_entry_single(MX50, "imx25-fec");
 #endif
 
 #ifdef CONFIG_SOC_IMX51
+/* i.mx51 has the i.mx27 type fec */
 const struct imx_fec_data imx51_fec_data __initconst =
-	imx_fec_data_entry_single(MX51);
+	imx_fec_data_entry_single(MX51, "imx27-fec");
 #endif
 
 #ifdef CONFIG_SOC_IMX53
+/* i.mx53 has the i.mx25 type fec */
 const struct imx_fec_data imx53_fec_data __initconst =
-	imx_fec_data_entry_single(MX53);
+	imx_fec_data_entry_single(MX53, "imx25-fec");
 #endif
 
 struct platform_device *__init imx_add_fec(
@@ -63,7 +68,7 @@ struct platform_device *__init imx_add_fec(
 		},
 	};
 
-	return imx_add_platform_device_dmamask("fec", 0,
+	return imx_add_platform_device_dmamask(data->devid, 0,
 			res, ARRAY_SIZE(res),
 			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
 }
diff --git a/arch/arm/plat-mxc/devices/platform-imx-dma.c b/arch/arm/plat-mxc/devices/platform-imx-dma.c
index 2b0fdb23beb8..7fa7e9c92468 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-dma.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-dma.c
@@ -14,7 +14,7 @@ struct platform_device __init __maybe_unused *imx_add_imx_dma(void)
 			"imx-dma", -1, NULL, 0, NULL, 0);
 }
 
-struct platform_device __init __maybe_unused *imx_add_imx_sdma(
+struct platform_device __init __maybe_unused *imx_add_imx_sdma(char *name,
 	resource_size_t iobase, int irq, struct sdma_platform_data *pdata)
 {
 	struct resource res[] = {
@@ -29,6 +29,6 @@ struct platform_device __init __maybe_unused *imx_add_imx_sdma(
 		},
 	};
 
-	return platform_device_register_resndata(&mxc_ahb_bus, "imx-sdma",
+	return platform_device_register_resndata(&mxc_ahb_bus, name,
 			-1, res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
diff --git a/arch/arm/plat-mxc/devices/platform-imx-uart.c b/arch/arm/plat-mxc/devices/platform-imx-uart.c
index cfce8c918b73..2020d84956c3 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-uart.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-uart.c
@@ -152,7 +152,7 @@ struct platform_device *__init imx_add_imx_uart_3irq(
 		},
 	};
 
-	return imx_add_platform_device("imx-uart", data->id, res,
+	return imx_add_platform_device("imx1-uart", data->id, res,
 			ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
 
@@ -172,6 +172,7 @@ struct platform_device *__init imx_add_imx_uart_1irq(
 		},
 	};
 
-	return imx_add_platform_device("imx-uart", data->id, res, ARRAY_SIZE(res),
-			pdata, sizeof(*pdata));
+	/* i.mx21 type uart runs on all i.mx except i.mx1 */
+	return imx_add_platform_device("imx21-uart", data->id,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
diff --git a/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c b/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
index 6b2940b93d94..5955f5da82ee 100644
--- a/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
+++ b/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
@@ -10,21 +10,22 @@
 #include <mach/devices-common.h>
 #include <mach/esdhc.h>
 
-#define imx_sdhci_esdhc_imx_data_entry_single(soc, _id, hwid) \
+#define imx_sdhci_esdhc_imx_data_entry_single(soc, _devid, _id, hwid) \
 	{								\
+		.devid = _devid,					\
 		.id = _id,						\
 		.iobase = soc ## _ESDHC ## hwid ## _BASE_ADDR,	\
 		.irq = soc ## _INT_ESDHC ## hwid,			\
 	}
 
-#define imx_sdhci_esdhc_imx_data_entry(soc, id, hwid)	\
-	[id] = imx_sdhci_esdhc_imx_data_entry_single(soc, id, hwid)
+#define imx_sdhci_esdhc_imx_data_entry(soc, devid, id, hwid)	\
+	[id] = imx_sdhci_esdhc_imx_data_entry_single(soc, devid, id, hwid)
 
 #ifdef CONFIG_SOC_IMX25
 const struct imx_sdhci_esdhc_imx_data
 imx25_sdhci_esdhc_imx_data[] __initconst = {
 #define imx25_sdhci_esdhc_imx_data_entry(_id, _hwid)			\
-	imx_sdhci_esdhc_imx_data_entry(MX25, _id, _hwid)
+	imx_sdhci_esdhc_imx_data_entry(MX25, "sdhci-esdhc-imx25", _id, _hwid)
 	imx25_sdhci_esdhc_imx_data_entry(0, 1),
 	imx25_sdhci_esdhc_imx_data_entry(1, 2),
 };
@@ -34,7 +35,7 @@ imx25_sdhci_esdhc_imx_data[] __initconst = {
 const struct imx_sdhci_esdhc_imx_data
 imx35_sdhci_esdhc_imx_data[] __initconst = {
 #define imx35_sdhci_esdhc_imx_data_entry(_id, _hwid)			\
-	imx_sdhci_esdhc_imx_data_entry(MX35, _id, _hwid)
+	imx_sdhci_esdhc_imx_data_entry(MX35, "sdhci-esdhc-imx35", _id, _hwid)
 	imx35_sdhci_esdhc_imx_data_entry(0, 1),
 	imx35_sdhci_esdhc_imx_data_entry(1, 2),
 	imx35_sdhci_esdhc_imx_data_entry(2, 3),
@@ -45,7 +46,7 @@ imx35_sdhci_esdhc_imx_data[] __initconst = {
 const struct imx_sdhci_esdhc_imx_data
 imx51_sdhci_esdhc_imx_data[] __initconst = {
 #define imx51_sdhci_esdhc_imx_data_entry(_id, _hwid)			\
-	imx_sdhci_esdhc_imx_data_entry(MX51, _id, _hwid)
+	imx_sdhci_esdhc_imx_data_entry(MX51, "sdhci-esdhc-imx51", _id, _hwid)
 	imx51_sdhci_esdhc_imx_data_entry(0, 1),
 	imx51_sdhci_esdhc_imx_data_entry(1, 2),
 	imx51_sdhci_esdhc_imx_data_entry(2, 3),
@@ -57,7 +58,7 @@ imx51_sdhci_esdhc_imx_data[] __initconst = {
 const struct imx_sdhci_esdhc_imx_data
 imx53_sdhci_esdhc_imx_data[] __initconst = {
 #define imx53_sdhci_esdhc_imx_data_entry(_id, _hwid)			\
-	imx_sdhci_esdhc_imx_data_entry(MX53, _id, _hwid)
+	imx_sdhci_esdhc_imx_data_entry(MX53, "sdhci-esdhc-imx53", _id, _hwid)
 	imx53_sdhci_esdhc_imx_data_entry(0, 1),
 	imx53_sdhci_esdhc_imx_data_entry(1, 2),
 	imx53_sdhci_esdhc_imx_data_entry(2, 3),
@@ -65,6 +66,11 @@ imx53_sdhci_esdhc_imx_data[] __initconst = {
 };
 #endif /* ifdef CONFIG_SOC_IMX53 */
 
+static const struct esdhc_platform_data default_esdhc_pdata __initconst = {
+	.wp_type = ESDHC_WP_NONE,
+	.cd_type = ESDHC_CD_NONE,
+};
+
 struct platform_device *__init imx_add_sdhci_esdhc_imx(
 		const struct imx_sdhci_esdhc_imx_data *data,
 		const struct esdhc_platform_data *pdata)
@@ -81,6 +87,13 @@ struct platform_device *__init imx_add_sdhci_esdhc_imx(
 		},
 	};
 
-	return imx_add_platform_device("sdhci-esdhc-imx", data->id, res,
+	/*
+	 * If machine does not provide pdata, use the default one
+	 * which means no WP/CD support
+	 */
+	if (!pdata)
+		pdata = &default_esdhc_pdata;
+
+	return imx_add_platform_device(data->devid, data->id, res,
 			ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h
index bf93820ab61c..524538aabc4b 100644
--- a/arch/arm/plat-mxc/include/mach/devices-common.h
+++ b/arch/arm/plat-mxc/include/mach/devices-common.h
@@ -30,6 +30,7 @@ static inline struct platform_device *imx_add_platform_device(
 
 #include <linux/fec.h>
 struct imx_fec_data {
+	const char *devid;
 	resource_size_t iobase;
 	resource_size_t irq;
 };
@@ -276,6 +277,7 @@ struct platform_device *__init imx_add_mxc_w1(
 
 #include <mach/esdhc.h>
 struct imx_sdhci_esdhc_imx_data {
+	const char *devid;
 	int id;
 	resource_size_t iobase;
 	resource_size_t irq;
@@ -297,5 +299,5 @@ struct platform_device *__init imx_add_spi_imx(
 		const struct spi_imx_master *pdata);
 
 struct platform_device *imx_add_imx_dma(void);
-struct platform_device *imx_add_imx_sdma(
+struct platform_device *imx_add_imx_sdma(char *name,
 	resource_size_t iobase, int irq, struct sdma_platform_data *pdata);
diff --git a/arch/arm/plat-mxc/include/mach/dma.h b/arch/arm/plat-mxc/include/mach/dma.h
index ef7751546f5f..233d0a5e2d68 100644
--- a/arch/arm/plat-mxc/include/mach/dma.h
+++ b/arch/arm/plat-mxc/include/mach/dma.h
@@ -60,7 +60,8 @@ static inline int imx_dma_is_ipu(struct dma_chan *chan)
 
 static inline int imx_dma_is_general_purpose(struct dma_chan *chan)
 {
-	return !strcmp(dev_name(chan->device->dev), "imx-sdma") ||
+	return !strcmp(dev_name(chan->device->dev), "imx31-sdma") ||
+		!strcmp(dev_name(chan->device->dev), "imx35-sdma") ||
 		!strcmp(dev_name(chan->device->dev), "imx-dma");
 }
 
diff --git a/arch/arm/plat-mxc/include/mach/esdhc.h b/arch/arm/plat-mxc/include/mach/esdhc.h
index 86003f411755..aaf97481f413 100644
--- a/arch/arm/plat-mxc/include/mach/esdhc.h
+++ b/arch/arm/plat-mxc/include/mach/esdhc.h
@@ -10,17 +10,34 @@
 #ifndef __ASM_ARCH_IMX_ESDHC_H
 #define __ASM_ARCH_IMX_ESDHC_H
 
+enum wp_types {
+	ESDHC_WP_NONE,		/* no WP, neither controller nor gpio */
+	ESDHC_WP_CONTROLLER,	/* mmc controller internal WP */
+	ESDHC_WP_GPIO,		/* external gpio pin for WP */
+};
+
+enum cd_types {
+	ESDHC_CD_NONE,		/* no CD, neither controller nor gpio */
+	ESDHC_CD_CONTROLLER,	/* mmc controller internal CD */
+	ESDHC_CD_GPIO,		/* external gpio pin for CD */
+	ESDHC_CD_PERMANENT,	/* no CD, card permanently wired to host */
+};
+
 /**
- * struct esdhc_platform_data - optional platform data for esdhc on i.MX
+ * struct esdhc_platform_data - platform data for esdhc on i.MX
  *
- * strongly recommended for i.MX25/35, not needed for other variants
+ * ESDHC_WP(CD)_CONTROLLER type is not available on i.MX25/35.
  *
- * @wp_gpio:	gpio for write_protect (-EINVAL if unused)
- * @cd_gpio:	gpio for card_detect interrupt (-EINVAL if unused)
+ * @wp_gpio:	gpio for write_protect
+ * @cd_gpio:	gpio for card_detect interrupt
+ * @wp_type:	type of write_protect method (see wp_types enum above)
+ * @cd_type:	type of card_detect method (see cd_types enum above)
  */
 
 struct esdhc_platform_data {
 	unsigned int wp_gpio;
 	unsigned int cd_gpio;
+	enum wp_types wp_type;
+	enum cd_types cd_type;
 };
 #endif /* __ASM_ARCH_IMX_ESDHC_H */
diff --git a/arch/arm/plat-mxc/include/mach/sdma.h b/arch/arm/plat-mxc/include/mach/sdma.h
index f495c87c113f..3a3942823c20 100644
--- a/arch/arm/plat-mxc/include/mach/sdma.h
+++ b/arch/arm/plat-mxc/include/mach/sdma.h
@@ -48,12 +48,10 @@ struct sdma_script_start_addrs {
 /**
  * struct sdma_platform_data - platform specific data for SDMA engine
  *
- * @sdma_version	The version of this SDMA engine
  * @fw_name		The firmware name
  * @script_addrs	SDMA scripts addresses in SDMA ROM
  */
 struct sdma_platform_data {
-	int sdma_version;
 	char *fw_name;
 	struct sdma_script_start_addrs *script_addrs;
 };
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 1ea47db2ff06..1eb60ded2f0d 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -32,6 +32,8 @@
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/dmaengine.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <asm/irq.h>
 #include <mach/sdma.h>
@@ -65,8 +67,8 @@
 #define SDMA_ONCE_RTB		0x060
 #define SDMA_XTRIG_CONF1	0x070
 #define SDMA_XTRIG_CONF2	0x074
-#define SDMA_CHNENBL0_V2	0x200
-#define SDMA_CHNENBL0_V1	0x080
+#define SDMA_CHNENBL0_IMX35	0x200
+#define SDMA_CHNENBL0_IMX31	0x080
 #define SDMA_CHNPRI_0		0x100
 
 /*
@@ -299,13 +301,18 @@ struct sdma_firmware_header {
 	u32	ram_code_size;
 };
 
+enum sdma_devtype {
+	IMX31_SDMA,	/* runs on i.mx31 */
+	IMX35_SDMA,	/* runs on i.mx35 and later */
+};
+
 struct sdma_engine {
 	struct device			*dev;
 	struct device_dma_parameters	dma_parms;
 	struct sdma_channel		channel[MAX_DMA_CHANNELS];
 	struct sdma_channel_control	*channel_control;
 	void __iomem			*regs;
-	unsigned int			version;
+	enum sdma_devtype		devtype;
 	unsigned int			num_events;
 	struct sdma_context_data	*context;
 	dma_addr_t			context_phys;
@@ -314,6 +321,26 @@ struct sdma_engine {
 	struct sdma_script_start_addrs	*script_addrs;
 };
 
+static struct platform_device_id sdma_devtypes[] = {
+	{
+		.name = "imx31-sdma",
+		.driver_data = IMX31_SDMA,
+	}, {
+		.name = "imx35-sdma",
+		.driver_data = IMX35_SDMA,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(platform, sdma_devtypes);
+
+static const struct of_device_id sdma_dt_ids[] = {
+	{ .compatible = "fsl,imx31-sdma", .data = &sdma_devtypes[IMX31_SDMA], },
+	{ .compatible = "fsl,imx35-sdma", .data = &sdma_devtypes[IMX35_SDMA], },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sdma_dt_ids);
+
 #define SDMA_H_CONFIG_DSPDMA	(1 << 12) /* indicates if the DSPDMA is used */
 #define SDMA_H_CONFIG_RTD_PINS	(1 << 11) /* indicates if Real-Time Debug pins are enabled */
 #define SDMA_H_CONFIG_ACR	(1 << 4)  /* indicates if AHB freq /core freq = 2 or 1 */
@@ -321,8 +348,8 @@ struct sdma_engine {
 
 static inline u32 chnenbl_ofs(struct sdma_engine *sdma, unsigned int event)
 {
-	u32 chnenbl0 = (sdma->version == 2 ? SDMA_CHNENBL0_V2 : SDMA_CHNENBL0_V1);
-
+	u32 chnenbl0 = (sdma->devtype == IMX31_SDMA ? SDMA_CHNENBL0_IMX31 :
+						      SDMA_CHNENBL0_IMX35);
 	return chnenbl0 + event * 4;
 }
 
@@ -1108,22 +1135,14 @@ static int __init sdma_get_firmware(struct sdma_engine *sdma,
 		const char *fw_name)
 {
 	const struct firmware *fw;
-	char *fwname;
 	const struct sdma_firmware_header *header;
 	int ret;
 	const struct sdma_script_start_addrs *addr;
 	unsigned short *ram_code;
 
-	fwname = kasprintf(GFP_KERNEL, "%s", fw_name);
-	if (!fwname)
-		return -ENOMEM;
-
-	ret = request_firmware(&fw, fwname, sdma->dev);
-	if (ret) {
-		kfree(fwname);
+	ret = request_firmware(&fw, fw_name, sdma->dev);
+	if (ret)
 		return ret;
-	}
-	kfree(fwname);
 
 	if (fw->size < sizeof(*header))
 		goto err_firmware;
@@ -1162,15 +1181,16 @@ static int __init sdma_init(struct sdma_engine *sdma)
 	int i, ret;
 	dma_addr_t ccb_phys;
 
-	switch (sdma->version) {
-	case 1:
+	switch (sdma->devtype) {
+	case IMX31_SDMA:
 		sdma->num_events = 32;
 		break;
-	case 2:
+	case IMX35_SDMA:
 		sdma->num_events = 48;
 		break;
 	default:
-		dev_err(sdma->dev, "Unknown version %d. aborting\n", sdma->version);
+		dev_err(sdma->dev, "Unknown sdma type %d. aborting\n",
+			sdma->devtype);
 		return -ENODEV;
 	}
 
@@ -1239,6 +1259,10 @@ err_dma_alloc:
 
 static int __init sdma_probe(struct platform_device *pdev)
 {
+	const struct of_device_id *of_id =
+			of_match_device(sdma_dt_ids, &pdev->dev);
+	struct device_node *np = pdev->dev.of_node;
+	const char *fw_name;
 	int ret;
 	int irq;
 	struct resource *iores;
@@ -1254,7 +1278,7 @@ static int __init sdma_probe(struct platform_device *pdev)
 
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	irq = platform_get_irq(pdev, 0);
-	if (!iores || irq < 0 || !pdata) {
+	if (!iores || irq < 0) {
 		ret = -EINVAL;
 		goto err_irq;
 	}
@@ -1284,7 +1308,9 @@ static int __init sdma_probe(struct platform_device *pdev)
 	if (!sdma->script_addrs)
 		goto err_alloc;
 
-	sdma->version = pdata->sdma_version;
+	if (of_id)
+		pdev->id_entry = of_id->data;
+	sdma->devtype = pdev->id_entry->driver_data;
 
 	dma_cap_set(DMA_SLAVE, sdma->dma_device.cap_mask);
 	dma_cap_set(DMA_CYCLIC, sdma->dma_device.cap_mask);
@@ -1314,10 +1340,30 @@ static int __init sdma_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_init;
 
-	if (pdata->script_addrs)
+	if (pdata && pdata->script_addrs)
 		sdma_add_scripts(sdma, pdata->script_addrs);
 
-	sdma_get_firmware(sdma, pdata->fw_name);
+	if (pdata) {
+		sdma_get_firmware(sdma, pdata->fw_name);
+	} else {
+		/*
+		 * Because that device tree does not encode ROM script address,
+		 * the RAM script in firmware is mandatory for device tree
+		 * probe, otherwise it fails.
+		 */
+		ret = of_property_read_string(np, "fsl,sdma-ram-script-name",
+					      &fw_name);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to get firmware name\n");
+			goto err_init;
+		}
+
+		ret = sdma_get_firmware(sdma, fw_name);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to get firmware\n");
+			goto err_init;
+		}
+	}
 
 	sdma->dma_device.dev = &pdev->dev;
 
@@ -1365,7 +1411,9 @@ static int __exit sdma_remove(struct platform_device *pdev)
 static struct platform_driver sdma_driver = {
 	.driver		= {
 		.name	= "imx-sdma",
+		.of_match_table = sdma_dt_ids,
 	},
+	.id_table	= sdma_devtypes,
 	.remove		= __exit_p(sdma_remove),
 };
 
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 710b706f4fcf..9ebfb4b482f5 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -20,7 +20,9 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/sdio.h>
-#include <mach/hardware.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
 #include <mach/esdhc.h>
 #include "sdhci-pltfm.h"
 #include "sdhci-esdhc.h"
@@ -29,7 +31,6 @@
 #define SDHCI_VENDOR_SPEC		0xC0
 #define  SDHCI_VENDOR_SPEC_SDIO_QUIRK	0x00000002
 
-#define ESDHC_FLAG_GPIO_FOR_CD		(1 << 0)
 /*
  * The CMDTYPE of the CMD register (offset 0xE) should be set to
  * "11" when the STOP CMD12 is issued on imx53 to abort one
@@ -43,10 +44,67 @@
  */
 #define ESDHC_FLAG_MULTIBLK_NO_INT	(1 << 1)
 
+enum imx_esdhc_type {
+	IMX25_ESDHC,
+	IMX35_ESDHC,
+	IMX51_ESDHC,
+	IMX53_ESDHC,
+};
+
 struct pltfm_imx_data {
 	int flags;
 	u32 scratchpad;
+	enum imx_esdhc_type devtype;
+	struct esdhc_platform_data boarddata;
+};
+
+static struct platform_device_id imx_esdhc_devtype[] = {
+	{
+		.name = "sdhci-esdhc-imx25",
+		.driver_data = IMX25_ESDHC,
+	}, {
+		.name = "sdhci-esdhc-imx35",
+		.driver_data = IMX35_ESDHC,
+	}, {
+		.name = "sdhci-esdhc-imx51",
+		.driver_data = IMX51_ESDHC,
+	}, {
+		.name = "sdhci-esdhc-imx53",
+		.driver_data = IMX53_ESDHC,
+	}, {
+		/* sentinel */
+	}
 };
+MODULE_DEVICE_TABLE(platform, imx_esdhc_devtype);
+
+static const struct of_device_id imx_esdhc_dt_ids[] = {
+	{ .compatible = "fsl,imx25-esdhc", .data = &imx_esdhc_devtype[IMX25_ESDHC], },
+	{ .compatible = "fsl,imx35-esdhc", .data = &imx_esdhc_devtype[IMX35_ESDHC], },
+	{ .compatible = "fsl,imx51-esdhc", .data = &imx_esdhc_devtype[IMX51_ESDHC], },
+	{ .compatible = "fsl,imx53-esdhc", .data = &imx_esdhc_devtype[IMX53_ESDHC], },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids);
+
+static inline int is_imx25_esdhc(struct pltfm_imx_data *data)
+{
+	return data->devtype == IMX25_ESDHC;
+}
+
+static inline int is_imx35_esdhc(struct pltfm_imx_data *data)
+{
+	return data->devtype == IMX35_ESDHC;
+}
+
+static inline int is_imx51_esdhc(struct pltfm_imx_data *data)
+{
+	return data->devtype == IMX51_ESDHC;
+}
+
+static inline int is_imx53_esdhc(struct pltfm_imx_data *data)
+{
+	return data->devtype == IMX53_ESDHC;
+}
 
 static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg)
 {
@@ -60,17 +118,14 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct pltfm_imx_data *imx_data = pltfm_host->priv;
+	struct esdhc_platform_data *boarddata = &imx_data->boarddata;
 
-	/* fake CARD_PRESENT flag on mx25/35 */
+	/* fake CARD_PRESENT flag */
 	u32 val = readl(host->ioaddr + reg);
 
 	if (unlikely((reg == SDHCI_PRESENT_STATE)
-			&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD))) {
-		struct esdhc_platform_data *boarddata =
-				host->mmc->parent->platform_data;
-
-		if (boarddata && gpio_is_valid(boarddata->cd_gpio)
-				&& gpio_get_value(boarddata->cd_gpio))
+			&& gpio_is_valid(boarddata->cd_gpio))) {
+		if (gpio_get_value(boarddata->cd_gpio))
 			/* no card, if a valid gpio says so... */
 			val &= ~SDHCI_CARD_PRESENT;
 		else
@@ -85,12 +140,12 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct pltfm_imx_data *imx_data = pltfm_host->priv;
+	struct esdhc_platform_data *boarddata = &imx_data->boarddata;
 
 	if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)
-			&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD)))
+			&& (boarddata->cd_type == ESDHC_CD_GPIO)))
 		/*
 		 * these interrupts won't work with a custom card_detect gpio
-		 * (only applied to mx25/35)
 		 */
 		val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
 
@@ -173,6 +228,17 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
 		return;
 	}
 	esdhc_clrset_le(host, 0xff, val, reg);
+
+	/*
+	 * The esdhc has a design violation to SDHC spec which tells
+	 * that software reset should not affect card detection circuit.
+	 * But esdhc clears its SYSCTL register bits [0..2] during the
+	 * software reset.  This will stop those clocks that card detection
+	 * circuit relies on.  To work around it, we turn the clocks on back
+	 * to keep card detection circuit functional.
+	 */
+	if ((reg == SDHCI_SOFTWARE_RESET) && (val & 1))
+		esdhc_clrset_le(host, 0x7, 0x7, ESDHC_SYSTEM_CONTROL);
 }
 
 static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host)
@@ -189,6 +255,26 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
 	return clk_get_rate(pltfm_host->clk) / 256 / 16;
 }
 
+static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct pltfm_imx_data *imx_data = pltfm_host->priv;
+	struct esdhc_platform_data *boarddata = &imx_data->boarddata;
+
+	switch (boarddata->wp_type) {
+	case ESDHC_WP_GPIO:
+		if (gpio_is_valid(boarddata->wp_gpio))
+			return gpio_get_value(boarddata->wp_gpio);
+	case ESDHC_WP_CONTROLLER:
+		return !(readl(host->ioaddr + SDHCI_PRESENT_STATE) &
+			       SDHCI_WRITE_PROTECT);
+	case ESDHC_WP_NONE:
+		break;
+	}
+
+	return -ENOSYS;
+}
+
 static struct sdhci_ops sdhci_esdhc_ops = {
 	.read_l = esdhc_readl_le,
 	.read_w = esdhc_readw_le,
@@ -198,6 +284,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
 	.set_clock = esdhc_set_clock,
 	.get_max_clock = esdhc_pltfm_get_max_clock,
 	.get_min_clock = esdhc_pltfm_get_min_clock,
+	.get_ro = esdhc_pltfm_get_ro,
 };
 
 static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
@@ -207,17 +294,6 @@ static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
 	.ops = &sdhci_esdhc_ops,
 };
 
-static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
-{
-	struct esdhc_platform_data *boarddata =
-			host->mmc->parent->platform_data;
-
-	if (boarddata && gpio_is_valid(boarddata->wp_gpio))
-		return gpio_get_value(boarddata->wp_gpio);
-	else
-		return -ENOSYS;
-}
-
 static irqreturn_t cd_irq(int irq, void *data)
 {
 	struct sdhci_host *sdhost = (struct sdhci_host *)data;
@@ -226,8 +302,48 @@ static irqreturn_t cd_irq(int irq, void *data)
 	return IRQ_HANDLED;
 };
 
+#ifdef CONFIG_OF
+static int __devinit
+sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
+			 struct esdhc_platform_data *boarddata)
+{
+	struct device_node *np = pdev->dev.of_node;
+
+	if (!np)
+		return -ENODEV;
+
+	if (of_get_property(np, "fsl,card-wired", NULL))
+		boarddata->cd_type = ESDHC_CD_PERMANENT;
+
+	if (of_get_property(np, "fsl,cd-controller", NULL))
+		boarddata->cd_type = ESDHC_CD_CONTROLLER;
+
+	if (of_get_property(np, "fsl,wp-controller", NULL))
+		boarddata->wp_type = ESDHC_WP_CONTROLLER;
+
+	boarddata->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
+	if (gpio_is_valid(boarddata->cd_gpio))
+		boarddata->cd_type = ESDHC_CD_GPIO;
+
+	boarddata->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
+	if (gpio_is_valid(boarddata->wp_gpio))
+		boarddata->wp_type = ESDHC_WP_GPIO;
+
+	return 0;
+}
+#else
+static inline int
+sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
+			 struct esdhc_platform_data *boarddata)
+{
+	return -ENODEV;
+}
+#endif
+
 static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
 {
+	const struct of_device_id *of_id =
+			of_match_device(imx_esdhc_dt_ids, &pdev->dev);
 	struct sdhci_pltfm_host *pltfm_host;
 	struct sdhci_host *host;
 	struct esdhc_platform_data *boarddata;
@@ -242,8 +358,14 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
 	pltfm_host = sdhci_priv(host);
 
 	imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL);
-	if (!imx_data)
-		return -ENOMEM;
+	if (!imx_data) {
+		err = -ENOMEM;
+		goto err_imx_data;
+	}
+
+	if (of_id)
+		pdev->id_entry = of_id->data;
+	imx_data->devtype = pdev->id_entry->driver_data;
 	pltfm_host->priv = imx_data;
 
 	clk = clk_get(mmc_dev(host->mmc), NULL);
@@ -255,50 +377,72 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
 	clk_enable(clk);
 	pltfm_host->clk = clk;
 
-	if (!cpu_is_mx25())
+	if (!is_imx25_esdhc(imx_data))
 		host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 
-	if (cpu_is_mx25() || cpu_is_mx35()) {
+	if (is_imx25_esdhc(imx_data) || is_imx35_esdhc(imx_data))
 		/* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
 		host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
-		/* write_protect can't be routed to controller, use gpio */
-		sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
-	}
 
-	if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51()))
+	if (is_imx53_esdhc(imx_data))
 		imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
 
-	boarddata = host->mmc->parent->platform_data;
-	if (boarddata) {
+	boarddata = &imx_data->boarddata;
+	if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) {
+		if (!host->mmc->parent->platform_data) {
+			dev_err(mmc_dev(host->mmc), "no board data!\n");
+			err = -EINVAL;
+			goto no_board_data;
+		}
+		imx_data->boarddata = *((struct esdhc_platform_data *)
+					host->mmc->parent->platform_data);
+	}
+
+	/* write_protect */
+	if (boarddata->wp_type == ESDHC_WP_GPIO) {
 		err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
 		if (err) {
 			dev_warn(mmc_dev(host->mmc),
-				"no write-protect pin available!\n");
-			boarddata->wp_gpio = err;
+				 "no write-protect pin available!\n");
+			boarddata->wp_gpio = -EINVAL;
 		}
+	} else {
+		boarddata->wp_gpio = -EINVAL;
+	}
+
+	/* card_detect */
+	if (boarddata->cd_type != ESDHC_CD_GPIO)
+		boarddata->cd_gpio = -EINVAL;
 
+	switch (boarddata->cd_type) {
+	case ESDHC_CD_GPIO:
 		err = gpio_request_one(boarddata->cd_gpio, GPIOF_IN, "ESDHC_CD");
 		if (err) {
-			dev_warn(mmc_dev(host->mmc),
+			dev_err(mmc_dev(host->mmc),
 				"no card-detect pin available!\n");
 			goto no_card_detect_pin;
 		}
 
-		/* i.MX5x has issues to be researched */
-		if (!cpu_is_mx25() && !cpu_is_mx35())
-			goto not_supported;
-
 		err = request_irq(gpio_to_irq(boarddata->cd_gpio), cd_irq,
 				 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
 				 mmc_hostname(host->mmc), host);
 		if (err) {
-			dev_warn(mmc_dev(host->mmc), "request irq error\n");
+			dev_err(mmc_dev(host->mmc), "request irq error\n");
 			goto no_card_detect_irq;
 		}
+		/* fall through */
 
-		imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD;
-		/* Now we have a working card_detect again */
+	case ESDHC_CD_CONTROLLER:
+		/* we have a working card_detect back */
 		host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+		break;
+
+	case ESDHC_CD_PERMANENT:
+		host->mmc->caps = MMC_CAP_NONREMOVABLE;
+		break;
+
+	case ESDHC_CD_NONE:
+		break;
 	}
 
 	err = sdhci_add_host(host);
@@ -307,16 +451,21 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
 
 	return 0;
 
- no_card_detect_irq:
-	gpio_free(boarddata->cd_gpio);
- no_card_detect_pin:
-	boarddata->cd_gpio = err;
- not_supported:
-	kfree(imx_data);
- err_add_host:
+err_add_host:
+	if (gpio_is_valid(boarddata->cd_gpio))
+		free_irq(gpio_to_irq(boarddata->cd_gpio), host);
+no_card_detect_irq:
+	if (gpio_is_valid(boarddata->cd_gpio))
+		gpio_free(boarddata->cd_gpio);
+	if (gpio_is_valid(boarddata->wp_gpio))
+		gpio_free(boarddata->wp_gpio);
+no_card_detect_pin:
+no_board_data:
 	clk_disable(pltfm_host->clk);
 	clk_put(pltfm_host->clk);
- err_clk_get:
+err_clk_get:
+	kfree(imx_data);
+err_imx_data:
 	sdhci_pltfm_free(pdev);
 	return err;
 }
@@ -325,20 +474,18 @@ static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
 {
 	struct sdhci_host *host = platform_get_drvdata(pdev);
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-	struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
 	struct pltfm_imx_data *imx_data = pltfm_host->priv;
+	struct esdhc_platform_data *boarddata = &imx_data->boarddata;
 	int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
 
 	sdhci_remove_host(host, dead);
 
-	if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+	if (gpio_is_valid(boarddata->wp_gpio))
 		gpio_free(boarddata->wp_gpio);
 
-	if (boarddata && gpio_is_valid(boarddata->cd_gpio)) {
+	if (gpio_is_valid(boarddata->cd_gpio)) {
+		free_irq(gpio_to_irq(boarddata->cd_gpio), host);
 		gpio_free(boarddata->cd_gpio);
-
-		if (!(host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION))
-			free_irq(gpio_to_irq(boarddata->cd_gpio), host);
 	}
 
 	clk_disable(pltfm_host->clk);
@@ -354,7 +501,9 @@ static struct platform_driver sdhci_esdhc_imx_driver = {
 	.driver		= {
 		.name	= "sdhci-esdhc-imx",
 		.owner	= THIS_MODULE,
+		.of_match_table = imx_esdhc_dt_ids,
 	},
+	.id_table	= imx_esdhc_devtype,
 	.probe		= sdhci_esdhc_imx_probe,
 	.remove		= __devexit_p(sdhci_esdhc_imx_remove),
 #ifdef CONFIG_PM
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index 71c0ce1f6db0..6414efeddca0 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -85,6 +85,7 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
 {
 	struct sdhci_host *host;
 	struct sdhci_pltfm_host *pltfm_host;
+	struct device_node *np = pdev->dev.of_node;
 	struct resource *iomem;
 	int ret;
 
@@ -98,7 +99,7 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
 		dev_err(&pdev->dev, "Invalid iomem size!\n");
 
 	/* Some PCI-based MFD need the parent here */
-	if (pdev->dev.parent != &platform_bus)
+	if (pdev->dev.parent != &platform_bus && !np)
 		host = sdhci_alloc_host(pdev->dev.parent, sizeof(*pltfm_host));
 	else
 		host = sdhci_alloc_host(&pdev->dev, sizeof(*pltfm_host));
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 5b631fe74738..e8266ccf818a 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -44,6 +44,10 @@
 #include <linux/platform_device.h>
 #include <linux/phy.h>
 #include <linux/fec.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/of_net.h>
 
 #include <asm/cacheflush.h>
 
@@ -66,17 +70,42 @@
 #define FEC_QUIRK_ENET_MAC		(1 << 0)
 /* Controller needs driver to swap frame */
 #define FEC_QUIRK_SWAP_FRAME		(1 << 1)
+/* Controller uses gasket */
+#define FEC_QUIRK_USE_GASKET		(1 << 2)
 
 static struct platform_device_id fec_devtype[] = {
 	{
+		/* keep it for coldfire */
 		.name = DRIVER_NAME,
 		.driver_data = 0,
 	}, {
+		.name = "imx25-fec",
+		.driver_data = FEC_QUIRK_USE_GASKET,
+	}, {
+		.name = "imx27-fec",
+		.driver_data = 0,
+	}, {
 		.name = "imx28-fec",
 		.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME,
-	},
-	{ }
+	}, {
+		/* sentinel */
+	}
 };
+MODULE_DEVICE_TABLE(platform, fec_devtype);
+
+enum imx_fec_type {
+	IMX25_FEC = 1, 	/* runs on i.mx25/50/53 */
+	IMX27_FEC,	/* runs on i.mx27/35/51 */
+	IMX28_FEC,
+};
+
+static const struct of_device_id fec_dt_ids[] = {
+	{ .compatible = "fsl,imx25-fec", .data = &fec_devtype[IMX25_FEC], },
+	{ .compatible = "fsl,imx27-fec", .data = &fec_devtype[IMX27_FEC], },
+	{ .compatible = "fsl,imx28-fec", .data = &fec_devtype[IMX28_FEC], },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, fec_dt_ids);
 
 static unsigned char macaddr[ETH_ALEN];
 module_param_array(macaddr, byte, NULL, 0);
@@ -427,7 +456,7 @@ fec_restart(struct net_device *ndev, int duplex)
 
 	} else {
 #ifdef FEC_MIIGSK_ENR
-		if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) {
+		if (id_entry->driver_data & FEC_QUIRK_USE_GASKET) {
 			/* disable the gasket and wait */
 			writel(0, fep->hwp + FEC_MIIGSK_ENR);
 			while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4)
@@ -436,8 +465,11 @@ fec_restart(struct net_device *ndev, int duplex)
 			/*
 			 * configure the gasket:
 			 *   RMII, 50 MHz, no loopback, no echo
+			 *   MII, 25 MHz, no loopback, no echo
 			 */
-			writel(1, fep->hwp + FEC_MIIGSK_CFGR);
+			writel((fep->phy_interface == PHY_INTERFACE_MODE_RMII) ?
+					1 : 0, fep->hwp + FEC_MIIGSK_CFGR);
+
 
 			/* re-enable the gasket */
 			writel(2, fep->hwp + FEC_MIIGSK_ENR);
@@ -734,8 +766,22 @@ static void __inline__ fec_get_mac(struct net_device *ndev)
 	 */
 	iap = macaddr;
 
+#ifdef CONFIG_OF
 	/*
-	 * 2) from flash or fuse (via platform data)
+	 * 2) from device tree data
+	 */
+	if (!is_valid_ether_addr(iap)) {
+		struct device_node *np = fep->pdev->dev.of_node;
+		if (np) {
+			const char *mac = of_get_mac_address(np);
+			if (mac)
+				iap = (unsigned char *) mac;
+		}
+	}
+#endif
+
+	/*
+	 * 3) from flash or fuse (via platform data)
 	 */
 	if (!is_valid_ether_addr(iap)) {
 #ifdef CONFIG_M5272
@@ -748,7 +794,7 @@ static void __inline__ fec_get_mac(struct net_device *ndev)
 	}
 
 	/*
-	 * 3) FEC mac registers set by bootloader
+	 * 4) FEC mac registers set by bootloader
 	 */
 	if (!is_valid_ether_addr(iap)) {
 		*((unsigned long *) &tmpaddr[0]) =
@@ -1354,6 +1400,52 @@ static int fec_enet_init(struct net_device *ndev)
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static int __devinit fec_get_phy_mode_dt(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+
+	if (np)
+		return of_get_phy_mode(np);
+
+	return -ENODEV;
+}
+
+static int __devinit fec_reset_phy(struct platform_device *pdev)
+{
+	int err, phy_reset;
+	struct device_node *np = pdev->dev.of_node;
+
+	if (!np)
+		return -ENODEV;
+
+	phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
+	err = gpio_request_one(phy_reset, GPIOF_OUT_INIT_LOW, "phy-reset");
+	if (err) {
+		pr_warn("FEC: failed to get gpio phy-reset: %d\n", err);
+		return err;
+	}
+	msleep(1);
+	gpio_set_value(phy_reset, 1);
+
+	return 0;
+}
+#else /* CONFIG_OF */
+static inline int fec_get_phy_mode_dt(struct platform_device *pdev)
+{
+	return -ENODEV;
+}
+
+static inline int fec_reset_phy(struct platform_device *pdev)
+{
+	/*
+	 * In case of platform probe, the reset has been done
+	 * by machine code.
+	 */
+	return 0;
+}
+#endif /* CONFIG_OF */
+
 static int __devinit
 fec_probe(struct platform_device *pdev)
 {
@@ -1362,6 +1454,11 @@ fec_probe(struct platform_device *pdev)
 	struct net_device *ndev;
 	int i, irq, ret = 0;
 	struct resource *r;
+	const struct of_device_id *of_id;
+
+	of_id = of_match_device(fec_dt_ids, &pdev->dev);
+	if (of_id)
+		pdev->id_entry = of_id->data;
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!r)
@@ -1393,9 +1490,18 @@ fec_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, ndev);
 
-	pdata = pdev->dev.platform_data;
-	if (pdata)
-		fep->phy_interface = pdata->phy;
+	ret = fec_get_phy_mode_dt(pdev);
+	if (ret < 0) {
+		pdata = pdev->dev.platform_data;
+		if (pdata)
+			fep->phy_interface = pdata->phy;
+		else
+			fep->phy_interface = PHY_INTERFACE_MODE_MII;
+	} else {
+		fep->phy_interface = ret;
+	}
+
+	fec_reset_phy(pdev);
 
 	/* This device has up to three irqs on some platforms */
 	for (i = 0; i < 3; i++) {
@@ -1530,6 +1636,7 @@ static struct platform_driver fec_driver = {
 #ifdef CONFIG_PM
 		.pm	= &fec_pm_ops,
 #endif
+		.of_match_table = fec_dt_ids,
 	},
 	.id_table = fec_devtype,
 	.probe	= fec_probe,
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index 725399ea0690..70cb7d8a3b53 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -39,6 +39,7 @@
 #include <linux/bitops.h>
 #include <linux/workqueue.h>
 #include <linux/of.h>
+#include <linux/of_net.h>
 #include <linux/slab.h>
 
 #include <asm/processor.h>
@@ -2506,18 +2507,6 @@ static int __devinit emac_init_config(struct emac_instance *dev)
 {
 	struct device_node *np = dev->ofdev->dev.of_node;
 	const void *p;
-	unsigned int plen;
-	const char *pm, *phy_modes[] = {
-		[PHY_MODE_NA] = "",
-		[PHY_MODE_MII] = "mii",
-		[PHY_MODE_RMII] = "rmii",
-		[PHY_MODE_SMII] = "smii",
-		[PHY_MODE_RGMII] = "rgmii",
-		[PHY_MODE_TBI] = "tbi",
-		[PHY_MODE_GMII] = "gmii",
-		[PHY_MODE_RTBI] = "rtbi",
-		[PHY_MODE_SGMII] = "sgmii",
-	};
 
 	/* Read config from device-tree */
 	if (emac_read_uint_prop(np, "mal-device", &dev->mal_ph, 1))
@@ -2566,23 +2555,9 @@ static int __devinit emac_init_config(struct emac_instance *dev)
 		dev->mal_burst_size = 256;
 
 	/* PHY mode needs some decoding */
-	dev->phy_mode = PHY_MODE_NA;
-	pm = of_get_property(np, "phy-mode", &plen);
-	if (pm != NULL) {
-		int i;
-		for (i = 0; i < ARRAY_SIZE(phy_modes); i++)
-			if (!strcasecmp(pm, phy_modes[i])) {
-				dev->phy_mode = i;
-				break;
-			}
-	}
-
-	/* Backward compat with non-final DT */
-	if (dev->phy_mode == PHY_MODE_NA && pm != NULL && plen == 4) {
-		u32 nmode = *(const u32 *)pm;
-		if (nmode > PHY_MODE_NA && nmode <= PHY_MODE_SGMII)
-			dev->phy_mode = nmode;
-	}
+	dev->phy_mode = of_get_phy_mode(np);
+	if (dev->phy_mode < 0)
+		dev->phy_mode = PHY_MODE_NA;
 
 	/* Check EMAC version */
 	if (of_device_is_compatible(np, "ibm,emac4sync")) {
diff --git a/drivers/net/ibm_newemac/emac.h b/drivers/net/ibm_newemac/emac.h
index 8a61b597a169..1568278d759a 100644
--- a/drivers/net/ibm_newemac/emac.h
+++ b/drivers/net/ibm_newemac/emac.h
@@ -26,6 +26,7 @@
 #define __IBM_NEWEMAC_H
 
 #include <linux/types.h>
+#include <linux/phy.h>
 
 /* EMAC registers 			Write Access rules */
 struct emac_regs {
@@ -106,15 +107,15 @@ struct emac_regs {
 /*
  * PHY mode settings (EMAC <-> ZMII/RGMII bridge <-> PHY)
  */
-#define PHY_MODE_NA	0
-#define PHY_MODE_MII	1
-#define PHY_MODE_RMII	2
-#define PHY_MODE_SMII	3
-#define PHY_MODE_RGMII	4
-#define PHY_MODE_TBI	5
-#define PHY_MODE_GMII	6
-#define PHY_MODE_RTBI	7
-#define PHY_MODE_SGMII	8
+#define PHY_MODE_NA	PHY_INTERFACE_MODE_NA
+#define PHY_MODE_MII	PHY_INTERFACE_MODE_MII
+#define PHY_MODE_RMII	PHY_INTERFACE_MODE_RMII
+#define PHY_MODE_SMII	PHY_INTERFACE_MODE_SMII
+#define PHY_MODE_RGMII	PHY_INTERFACE_MODE_RGMII
+#define PHY_MODE_TBI	PHY_INTERFACE_MODE_TBI
+#define PHY_MODE_GMII	PHY_INTERFACE_MODE_GMII
+#define PHY_MODE_RTBI	PHY_INTERFACE_MODE_RTBI
+#define PHY_MODE_SGMII	PHY_INTERFACE_MODE_SGMII
 
 /* EMACx_MR0 */
 #define EMAC_MR0_RXI			0x80000000
diff --git a/drivers/net/ibm_newemac/phy.c b/drivers/net/ibm_newemac/phy.c
index ac9d964e59ec..ab4e5969fe65 100644
--- a/drivers/net/ibm_newemac/phy.c
+++ b/drivers/net/ibm_newemac/phy.c
@@ -28,12 +28,15 @@
 #include "emac.h"
 #include "phy.h"
 
-static inline int phy_read(struct mii_phy *phy, int reg)
+#define phy_read _phy_read
+#define phy_write _phy_write
+
+static inline int _phy_read(struct mii_phy *phy, int reg)
 {
 	return phy->mdio_read(phy->dev, phy->address, reg);
 }
 
-static inline void phy_write(struct mii_phy *phy, int reg, int val)
+static inline void _phy_write(struct mii_phy *phy, int reg, int val)
 {
 	phy->mdio_write(phy->dev, phy->address, reg, val);
 }
diff --git a/drivers/of/of_net.c b/drivers/of/of_net.c
index 86f334a2769c..bb184717588f 100644
--- a/drivers/of/of_net.c
+++ b/drivers/of/of_net.c
@@ -8,6 +8,51 @@
 #include <linux/etherdevice.h>
 #include <linux/kernel.h>
 #include <linux/of_net.h>
+#include <linux/phy.h>
+
+/**
+ * It maps 'enum phy_interface_t' found in include/linux/phy.h
+ * into the device tree binding of 'phy-mode', so that Ethernet
+ * device driver can get phy interface from device tree.
+ */
+static const char *phy_modes[] = {
+	[PHY_INTERFACE_MODE_NA]		= "",
+	[PHY_INTERFACE_MODE_MII]	= "mii",
+	[PHY_INTERFACE_MODE_GMII]	= "gmii",
+	[PHY_INTERFACE_MODE_SGMII]	= "sgmii",
+	[PHY_INTERFACE_MODE_TBI]	= "tbi",
+	[PHY_INTERFACE_MODE_RMII]	= "rmii",
+	[PHY_INTERFACE_MODE_RGMII]	= "rgmii",
+	[PHY_INTERFACE_MODE_RGMII_ID]	= "rgmii-id",
+	[PHY_INTERFACE_MODE_RGMII_RXID]	= "rgmii-rxid",
+	[PHY_INTERFACE_MODE_RGMII_TXID] = "rgmii-txid",
+	[PHY_INTERFACE_MODE_RTBI]	= "rtbi",
+	[PHY_INTERFACE_MODE_SMII]	= "smii",
+};
+
+/**
+ * of_get_phy_mode - Get phy mode for given device_node
+ * @np:	Pointer to the given device_node
+ *
+ * The function gets phy interface string from property 'phy-mode',
+ * and return its index in phy_modes table, or errno in error case.
+ */
+const int of_get_phy_mode(struct device_node *np)
+{
+	const char *pm;
+	int err, i;
+
+	err = of_property_read_string(np, "phy-mode", &pm);
+	if (err < 0)
+		return err;
+
+	for (i = 0; i < ARRAY_SIZE(phy_modes); i++)
+		if (!strcasecmp(pm, phy_modes[i]))
+			return i;
+
+	return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(of_get_phy_mode);
 
 /**
  * Search the device tree for the best MAC address to use.  'mac-address' is
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 22fe801cce31..827db7654594 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -45,10 +45,11 @@
 #include <linux/delay.h>
 #include <linux/rational.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <mach/hardware.h>
 #include <mach/imx-uart.h>
 
 /* Register definitions */
@@ -66,8 +67,9 @@
 #define UBIR  0xa4 /* BRM Incremental Register */
 #define UBMR  0xa8 /* BRM Modulator Register */
 #define UBRC  0xac /* Baud Rate Count Register */
-#define MX2_ONEMS 0xb0 /* One Millisecond register */
-#define UTS (cpu_is_mx1() ? 0xd0 : 0xb4) /* UART Test Register */
+#define IMX21_ONEMS 0xb0 /* One Millisecond register */
+#define IMX1_UTS 0xd0 /* UART Test Register on i.mx1 */
+#define IMX21_UTS 0xb4 /* UART Test Register on all other i.mx*/
 
 /* UART Control Register Bit Fields.*/
 #define  URXD_CHARRDY    (1<<15)
@@ -87,7 +89,7 @@
 #define  UCR1_RTSDEN     (1<<5)	 /* RTS delta interrupt enable */
 #define  UCR1_SNDBRK     (1<<4)	 /* Send break */
 #define  UCR1_TDMAEN     (1<<3)	 /* Transmitter ready DMA enable */
-#define  MX1_UCR1_UARTCLKEN  (1<<2)	 /* UART clock enabled, mx1 only */
+#define  IMX1_UCR1_UARTCLKEN  (1<<2)  /* UART clock enabled, i.mx1 only */
 #define  UCR1_DOZE       (1<<1)	 /* Doze */
 #define  UCR1_UARTEN     (1<<0)	 /* UART enabled */
 #define  UCR2_ESCI     	 (1<<15) /* Escape seq interrupt enable */
@@ -113,9 +115,7 @@
 #define  UCR3_RXDSEN	 (1<<6)  /* Receive status interrupt enable */
 #define  UCR3_AIRINTEN   (1<<5)  /* Async IR wake interrupt enable */
 #define  UCR3_AWAKEN	 (1<<4)  /* Async wake interrupt enable */
-#define  MX1_UCR3_REF25 	 (1<<3)  /* Ref freq 25 MHz, only on mx1 */
-#define  MX1_UCR3_REF30 	 (1<<2)  /* Ref Freq 30 MHz, only on mx1 */
-#define  MX2_UCR3_RXDMUXSEL	 (1<<2)  /* RXD Muxed Input Select, on mx2/mx3 */
+#define  IMX21_UCR3_RXDMUXSEL	 (1<<2)  /* RXD Muxed Input Select */
 #define  UCR3_INVT  	 (1<<1)  /* Inverted Infrared transmission */
 #define  UCR3_BPEN  	 (1<<0)  /* Preset registers enable */
 #define  UCR4_CTSTL_SHF  10      /* CTS trigger level shift */
@@ -181,6 +181,18 @@
 
 #define UART_NR 8
 
+/* i.mx21 type uart runs on all i.mx except i.mx1 */
+enum imx_uart_type {
+	IMX1_UART,
+	IMX21_UART,
+};
+
+/* device type dependent stuff */
+struct imx_uart_data {
+	unsigned uts_reg;
+	enum imx_uart_type devtype;
+};
+
 struct imx_port {
 	struct uart_port	port;
 	struct timer_list	timer;
@@ -192,6 +204,7 @@ struct imx_port {
 	unsigned int		irda_inv_tx:1;
 	unsigned short		trcv_delay; /* transceiver delay */
 	struct clk		*clk;
+	struct imx_uart_data	*devdata;
 };
 
 #ifdef CONFIG_IRDA
@@ -200,6 +213,52 @@ struct imx_port {
 #define USE_IRDA(sport)	(0)
 #endif
 
+static struct imx_uart_data imx_uart_devdata[] = {
+	[IMX1_UART] = {
+		.uts_reg = IMX1_UTS,
+		.devtype = IMX1_UART,
+	},
+	[IMX21_UART] = {
+		.uts_reg = IMX21_UTS,
+		.devtype = IMX21_UART,
+	},
+};
+
+static struct platform_device_id imx_uart_devtype[] = {
+	{
+		.name = "imx1-uart",
+		.driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX1_UART],
+	}, {
+		.name = "imx21-uart",
+		.driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX21_UART],
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(platform, imx_uart_devtype);
+
+static struct of_device_id imx_uart_dt_ids[] = {
+	{ .compatible = "fsl,imx1-uart", .data = &imx_uart_devdata[IMX1_UART], },
+	{ .compatible = "fsl,imx21-uart", .data = &imx_uart_devdata[IMX21_UART], },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_uart_dt_ids);
+
+static inline unsigned uts_reg(struct imx_port *sport)
+{
+	return sport->devdata->uts_reg;
+}
+
+static inline int is_imx1_uart(struct imx_port *sport)
+{
+	return sport->devdata->devtype == IMX1_UART;
+}
+
+static inline int is_imx21_uart(struct imx_port *sport)
+{
+	return sport->devdata->devtype == IMX21_UART;
+}
+
 /*
  * Handle any change of modem status signal since we were last called.
  */
@@ -326,7 +385,8 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
 	struct circ_buf *xmit = &sport->port.state->xmit;
 
 	while (!uart_circ_empty(xmit) &&
-			!(readl(sport->port.membase + UTS) & UTS_TXFULL)) {
+			!(readl(sport->port.membase + uts_reg(sport))
+				& UTS_TXFULL)) {
 		/* send xmit->buf[xmit->tail]
 		 * out the port here */
 		writel(xmit->buf[xmit->tail], sport->port.membase + URTX0);
@@ -373,7 +433,7 @@ static void imx_start_tx(struct uart_port *port)
 		writel(temp, sport->port.membase + UCR4);
 	}
 
-	if (readl(sport->port.membase + UTS) & UTS_TXEMPTY)
+	if (readl(sport->port.membase + uts_reg(sport)) & UTS_TXEMPTY)
 		imx_transmit_buffer(sport);
 }
 
@@ -689,9 +749,9 @@ static int imx_startup(struct uart_port *port)
 		}
 	}
 
-	if (!cpu_is_mx1()) {
+	if (is_imx21_uart(sport)) {
 		temp = readl(sport->port.membase + UCR3);
-		temp |= MX2_UCR3_RXDMUXSEL;
+		temp |= IMX21_UCR3_RXDMUXSEL;
 		writel(temp, sport->port.membase + UCR3);
 	}
 
@@ -923,9 +983,9 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 	writel(num, sport->port.membase + UBIR);
 	writel(denom, sport->port.membase + UBMR);
 
-	if (!cpu_is_mx1())
+	if (is_imx21_uart(sport))
 		writel(sport->port.uartclk / div / 1000,
-				sport->port.membase + MX2_ONEMS);
+				sport->port.membase + IMX21_ONEMS);
 
 	writel(old_ucr1, sport->port.membase + UCR1);
 
@@ -1041,7 +1101,7 @@ static void imx_console_putchar(struct uart_port *port, int ch)
 {
 	struct imx_port *sport = (struct imx_port *)port;
 
-	while (readl(sport->port.membase + UTS) & UTS_TXFULL)
+	while (readl(sport->port.membase + uts_reg(sport)) & UTS_TXFULL)
 		barrier();
 
 	writel(ch, sport->port.membase + URTX0);
@@ -1062,8 +1122,8 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
 	ucr1 = old_ucr1 = readl(sport->port.membase + UCR1);
 	old_ucr2 = readl(sport->port.membase + UCR2);
 
-	if (cpu_is_mx1())
-		ucr1 |= MX1_UCR1_UARTCLKEN;
+	if (is_imx1_uart(sport))
+		ucr1 |= IMX1_UCR1_UARTCLKEN;
 	ucr1 |= UCR1_UARTEN;
 	ucr1 &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN);
 
@@ -1222,6 +1282,63 @@ static int serial_imx_resume(struct platform_device *dev)
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static int serial_imx_probe_dt(struct imx_port *sport,
+		struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	const struct of_device_id *of_id =
+			of_match_device(imx_uart_dt_ids, &pdev->dev);
+	int ret;
+
+	if (!np)
+		return -ENODEV;
+
+	ret = of_alias_get_id(np, "serial");
+	if (ret < 0) {
+		pr_err("%s: failed to get alias id, errno %d\n",
+			__func__, ret);
+		return -ENODEV;
+	} else {
+		sport->port.line = ret;
+	}
+
+	if (of_get_property(np, "fsl,uart-has-rtscts", NULL))
+		sport->have_rtscts = 1;
+
+	if (of_get_property(np, "fsl,irda-mode", NULL))
+		sport->use_irda = 1;
+
+	sport->devdata = of_id->data;
+
+	return 0;
+}
+#else
+static inline int serial_imx_probe_dt(struct imx_port *sport,
+		struct platform_device *pdev)
+{
+	return -ENODEV;
+}
+#endif
+
+static void serial_imx_probe_pdata(struct imx_port *sport,
+		struct platform_device *pdev)
+{
+	struct imxuart_platform_data *pdata = pdev->dev.platform_data;
+
+	sport->port.line = pdev->id;
+	sport->devdata = (struct imx_uart_data	*) pdev->id_entry->driver_data;
+
+	if (!pdata)
+		return;
+
+	if (pdata->flags & IMXUART_HAVE_RTSCTS)
+		sport->have_rtscts = 1;
+
+	if (pdata->flags & IMXUART_IRDA)
+		sport->use_irda = 1;
+}
+
 static int serial_imx_probe(struct platform_device *pdev)
 {
 	struct imx_port *sport;
@@ -1234,6 +1351,10 @@ static int serial_imx_probe(struct platform_device *pdev)
 	if (!sport)
 		return -ENOMEM;
 
+	ret = serial_imx_probe_dt(sport, pdev);
+	if (ret == -ENODEV)
+		serial_imx_probe_pdata(sport, pdev);
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		ret = -ENODEV;
@@ -1258,7 +1379,6 @@ static int serial_imx_probe(struct platform_device *pdev)
 	sport->port.fifosize = 32;
 	sport->port.ops = &imx_pops;
 	sport->port.flags = UPF_BOOT_AUTOCONF;
-	sport->port.line = pdev->id;
 	init_timer(&sport->timer);
 	sport->timer.function = imx_timeout;
 	sport->timer.data     = (unsigned long)sport;
@@ -1272,17 +1392,9 @@ static int serial_imx_probe(struct platform_device *pdev)
 
 	sport->port.uartclk = clk_get_rate(sport->clk);
 
-	imx_ports[pdev->id] = sport;
+	imx_ports[sport->port.line] = sport;
 
 	pdata = pdev->dev.platform_data;
-	if (pdata && (pdata->flags & IMXUART_HAVE_RTSCTS))
-		sport->have_rtscts = 1;
-
-#ifdef CONFIG_IRDA
-	if (pdata && (pdata->flags & IMXUART_IRDA))
-		sport->use_irda = 1;
-#endif
-
 	if (pdata && pdata->init) {
 		ret = pdata->init(pdev);
 		if (ret)
@@ -1340,9 +1452,11 @@ static struct platform_driver serial_imx_driver = {
 
 	.suspend	= serial_imx_suspend,
 	.resume		= serial_imx_resume,
+	.id_table	= imx_uart_devtype,
 	.driver		= {
 		.name	= "imx-uart",
 		.owner	= THIS_MODULE,
+		.of_match_table = imx_uart_dt_ids,
 	},
 };
 
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 5f695041090c..87a06f345bd2 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -108,14 +108,18 @@ enum {
 };
 
 struct msi_desc;
+struct irq_domain;
 
 /**
  * struct irq_data - per irq and irq chip data passed down to chip functions
  * @irq:		interrupt number
+ * @hwirq:		hardware interrupt number, local to the interrupt domain
  * @node:		node index useful for balancing
  * @state_use_accessors: status information for irq chip functions.
  *			Use accessor functions to deal with it
  * @chip:		low level interrupt hardware access
+ * @domain:		Interrupt translation domain; responsible for mapping
+ *			between hwirq number and linux irq number.
  * @handler_data:	per-IRQ data for the irq_chip methods
  * @chip_data:		platform-specific per-chip private data for the chip
  *			methods, to allow shared chip implementations
@@ -128,9 +132,11 @@ struct msi_desc;
  */
 struct irq_data {
 	unsigned int		irq;
+	unsigned long		hwirq;
 	unsigned int		node;
 	unsigned int		state_use_accessors;
 	struct irq_chip		*chip;
+	struct irq_domain	*domain;
 	void			*handler_data;
 	void			*chip_data;
 	struct msi_desc		*msi_desc;
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
new file mode 100644
index 000000000000..e807ad687a07
--- /dev/null
+++ b/include/linux/irqdomain.h
@@ -0,0 +1,91 @@
+/*
+ * irq_domain - IRQ translation domains
+ *
+ * Translation infrastructure between hw and linux irq numbers.  This is
+ * helpful for interrupt controllers to implement mapping between hardware
+ * irq numbers and the Linux irq number space.
+ *
+ * irq_domains also have a hook for translating device tree interrupt
+ * representation into a hardware irq number that can be mapped back to a
+ * Linux irq number without any extra platform support code.
+ *
+ * irq_domain is expected to be embedded in an interrupt controller's private
+ * data structure.
+ */
+#ifndef _LINUX_IRQDOMAIN_H
+#define _LINUX_IRQDOMAIN_H
+
+#include <linux/irq.h>
+#include <linux/mod_devicetable.h>
+
+#ifdef CONFIG_IRQ_DOMAIN
+struct device_node;
+struct irq_domain;
+
+/**
+ * struct irq_domain_ops - Methods for irq_domain objects
+ * @to_irq: (optional) given a local hardware irq number, return the linux
+ *          irq number.  If to_irq is not implemented, then the irq_domain
+ *          will use this translation: irq = (domain->irq_base + hwirq)
+ * @dt_translate: Given a device tree node and interrupt specifier, decode
+ *                the hardware irq number and linux irq type value.
+ */
+struct irq_domain_ops {
+	unsigned int (*to_irq)(struct irq_domain *d, unsigned long hwirq);
+
+#ifdef CONFIG_OF
+	int (*dt_translate)(struct irq_domain *d, struct device_node *node,
+			    const u32 *intspec, unsigned int intsize,
+			    unsigned long *out_hwirq, unsigned int *out_type);
+#endif /* CONFIG_OF */
+};
+
+/**
+ * struct irq_domain - Hardware interrupt number translation object
+ * @list: Element in global irq_domain list.
+ * @irq_base: Start of irq_desc range assigned to the irq_domain.  The creator
+ *            of the irq_domain is responsible for allocating the array of
+ *            irq_desc structures.
+ * @nr_irq: Number of irqs managed by the irq domain
+ * @ops: pointer to irq_domain methods
+ * @priv: private data pointer for use by owner.  Not touched by irq_domain
+ *        core code.
+ * @of_node: (optional) Pointer to device tree nodes associated with the
+ *           irq_domain.  Used when decoding device tree interrupt specifiers.
+ */
+struct irq_domain {
+	struct list_head list;
+	unsigned int irq_base;
+	unsigned int nr_irq;
+	const struct irq_domain_ops *ops;
+	void *priv;
+	struct device_node *of_node;
+};
+
+/**
+ * irq_domain_to_irq() - Translate from a hardware irq to a linux irq number
+ *
+ * Returns the linux irq number associated with a hardware irq.  By default,
+ * the mapping is irq == domain->irq_base + hwirq, but this mapping can
+ * be overridden if the irq_domain implements a .to_irq() hook.
+ */
+static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
+					     unsigned long hwirq)
+{
+	return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
+}
+
+extern void irq_domain_add(struct irq_domain *domain);
+extern void irq_domain_del(struct irq_domain *domain);
+#endif /* CONFIG_IRQ_DOMAIN */
+
+#if defined(CONFIG_IRQ_DOMAIN) && defined(CONFIG_OF_IRQ)
+extern void irq_domain_add_simple(struct device_node *controller, int irq_base);
+extern void irq_domain_generate_simple(const struct of_device_id *match,
+					u64 phys_base, unsigned int irq_start);
+#else /* CONFIG_IRQ_DOMAIN && CONFIG_OF_IRQ */
+static inline void irq_domain_generate_simple(const struct of_device_id *match,
+					u64 phys_base, unsigned int irq_start) { }
+#endif /* CONFIG_IRQ_DOMAIN && CONFIG_OF_IRQ */
+
+#endif /* _LINUX_IRQDOMAIN_H */
diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
index e6955f5d1f08..cd2e61ce4e83 100644
--- a/include/linux/of_irq.h
+++ b/include/linux/of_irq.h
@@ -63,6 +63,9 @@ extern int of_irq_map_one(struct device_node *device, int index,
 extern unsigned int irq_create_of_mapping(struct device_node *controller,
 					  const u32 *intspec,
 					  unsigned int intsize);
+#ifdef CONFIG_IRQ_DOMAIN
+extern void irq_dispose_mapping(unsigned int irq);
+#endif
 extern int of_irq_to_resource(struct device_node *dev, int index,
 			      struct resource *r);
 extern int of_irq_count(struct device_node *dev);
@@ -70,6 +73,7 @@ extern int of_irq_to_resource_table(struct device_node *dev,
 		struct resource *res, int nr_irqs);
 extern struct device_node *of_irq_find_parent(struct device_node *child);
 
+
 #endif /* CONFIG_OF_IRQ */
 #endif /* CONFIG_OF */
 #endif /* __OF_IRQ_H */
diff --git a/include/linux/of_net.h b/include/linux/of_net.h
index e913081fb52a..f47464188710 100644
--- a/include/linux/of_net.h
+++ b/include/linux/of_net.h
@@ -9,6 +9,7 @@
 
 #ifdef CONFIG_OF_NET
 #include <linux/of.h>
+extern const int of_get_phy_mode(struct device_node *np);
 extern const void *of_get_mac_address(struct device_node *np);
 #endif
 
diff --git a/include/linux/phy.h b/include/linux/phy.h
index ad5186354d92..54fc4138955f 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -53,6 +53,7 @@
 
 /* Interface Mode definitions */
 typedef enum {
+	PHY_INTERFACE_MODE_NA,
 	PHY_INTERFACE_MODE_MII,
 	PHY_INTERFACE_MODE_GMII,
 	PHY_INTERFACE_MODE_SGMII,
@@ -62,7 +63,8 @@ typedef enum {
 	PHY_INTERFACE_MODE_RGMII_ID,
 	PHY_INTERFACE_MODE_RGMII_RXID,
 	PHY_INTERFACE_MODE_RGMII_TXID,
-	PHY_INTERFACE_MODE_RTBI
+	PHY_INTERFACE_MODE_RTBI,
+	PHY_INTERFACE_MODE_SMII,
 } phy_interface_t;
 
 
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
index d1d051b38e0b..5a38bf4de641 100644
--- a/kernel/irq/Kconfig
+++ b/kernel/irq/Kconfig
@@ -52,6 +52,10 @@ config IRQ_EDGE_EOI_HANDLER
 config GENERIC_IRQ_CHIP
        bool
 
+# Generic irq_domain hw <--> linux irq number translation
+config IRQ_DOMAIN
+	bool
+
 # Support forced irq threading
 config IRQ_FORCED_THREADING
        bool
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile
index 73290056cfb6..fff17381f0af 100644
--- a/kernel/irq/Makefile
+++ b/kernel/irq/Makefile
@@ -2,6 +2,7 @@
 obj-y := irqdesc.o handle.o manage.o spurious.o resend.o chip.o dummychip.o devres.o
 obj-$(CONFIG_GENERIC_IRQ_CHIP) += generic-chip.o
 obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
+obj-$(CONFIG_IRQ_DOMAIN) += irqdomain.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
 obj-$(CONFIG_PM_SLEEP) += pm.o
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
new file mode 100644
index 000000000000..d5828da3fd38
--- /dev/null
+++ b/kernel/irq/irqdomain.c
@@ -0,0 +1,180 @@
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+static LIST_HEAD(irq_domain_list);
+static DEFINE_MUTEX(irq_domain_mutex);
+
+/**
+ * irq_domain_add() - Register an irq_domain
+ * @domain: ptr to initialized irq_domain structure
+ *
+ * Registers an irq_domain structure.  The irq_domain must at a minimum be
+ * initialized with an ops structure pointer, and either a ->to_irq hook or
+ * a valid irq_base value.  Everything else is optional.
+ */
+void irq_domain_add(struct irq_domain *domain)
+{
+	struct irq_data *d;
+	int hwirq;
+
+	/*
+	 * This assumes that the irq_domain owner has already allocated
+	 * the irq_descs.  This block will be removed when support for dynamic
+	 * allocation of irq_descs is added to irq_domain.
+	 */
+	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
+		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
+		if (d || d->domain) {
+			/* things are broken; just report, don't clean up */
+			WARN(1, "error: irq_desc already assigned to a domain");
+			return;
+		}
+		d->domain = domain;
+		d->hwirq = hwirq;
+	}
+
+	mutex_lock(&irq_domain_mutex);
+	list_add(&domain->list, &irq_domain_list);
+	mutex_unlock(&irq_domain_mutex);
+}
+
+/**
+ * irq_domain_del() - Unregister an irq_domain
+ * @domain: ptr to registered irq_domain.
+ */
+void irq_domain_del(struct irq_domain *domain)
+{
+	struct irq_data *d;
+	int hwirq;
+
+	mutex_lock(&irq_domain_mutex);
+	list_del(&domain->list);
+	mutex_unlock(&irq_domain_mutex);
+
+	/* Clear the irq_domain assignments */
+	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
+		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
+		d->domain = NULL;
+	}
+}
+
+#if defined(CONFIG_OF_IRQ)
+/**
+ * irq_create_of_mapping() - Map a linux irq number from a DT interrupt spec
+ *
+ * Used by the device tree interrupt mapping code to translate a device tree
+ * interrupt specifier to a valid linux irq number.  Returns either a valid
+ * linux IRQ number or 0.
+ *
+ * When the caller no longer need the irq number returned by this function it
+ * should arrange to call irq_dispose_mapping().
+ */
+unsigned int irq_create_of_mapping(struct device_node *controller,
+				   const u32 *intspec, unsigned int intsize)
+{
+	struct irq_domain *domain;
+	unsigned long hwirq;
+	unsigned int irq, type;
+	int rc = -EINVAL;
+
+	/* Find a domain which can translate the irq spec */
+	mutex_lock(&irq_domain_mutex);
+	list_for_each_entry(domain, &irq_domain_list, list) {
+		if (!domain->ops->dt_translate)
+			continue;
+		rc = domain->ops->dt_translate(domain, controller,
+					intspec, intsize, &hwirq, &type);
+		if (rc == 0)
+			break;
+	}
+	mutex_unlock(&irq_domain_mutex);
+
+	if (rc != 0)
+		return 0;
+
+	irq = irq_domain_to_irq(domain, hwirq);
+	if (type != IRQ_TYPE_NONE)
+		irq_set_irq_type(irq, type);
+	pr_debug("%s: mapped hwirq=%i to irq=%i, flags=%x\n",
+		 controller->full_name, (int)hwirq, irq, type);
+	return irq;
+}
+EXPORT_SYMBOL_GPL(irq_create_of_mapping);
+
+/**
+ * irq_dispose_mapping() - Discard a mapping created by irq_create_of_mapping()
+ * @irq: linux irq number to be discarded
+ *
+ * Calling this function indicates the caller no longer needs a reference to
+ * the linux irq number returned by a prior call to irq_create_of_mapping().
+ */
+void irq_dispose_mapping(unsigned int irq)
+{
+	/*
+	 * nothing yet; will be filled when support for dynamic allocation of
+	 * irq_descs is added to irq_domain
+	 */
+}
+EXPORT_SYMBOL_GPL(irq_dispose_mapping);
+
+int irq_domain_simple_dt_translate(struct irq_domain *d,
+			    struct device_node *controller,
+			    const u32 *intspec, unsigned int intsize,
+			    unsigned long *out_hwirq, unsigned int *out_type)
+{
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize < 1)
+		return -EINVAL;
+
+	*out_hwirq = intspec[0];
+	*out_type = IRQ_TYPE_NONE;
+	if (intsize > 1)
+		*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+	return 0;
+}
+
+struct irq_domain_ops irq_domain_simple_ops = {
+	.dt_translate = irq_domain_simple_dt_translate,
+};
+EXPORT_SYMBOL_GPL(irq_domain_simple_ops);
+
+/**
+ * irq_domain_create_simple() - Set up a 'simple' translation range
+ */
+void irq_domain_add_simple(struct device_node *controller, int irq_base)
+{
+	struct irq_domain *domain;
+
+	domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+	if (!domain) {
+		WARN_ON(1);
+		return;
+	}
+
+	domain->irq_base = irq_base;
+	domain->of_node = of_node_get(controller);
+	domain->ops = &irq_domain_simple_ops;
+	irq_domain_add(domain);
+}
+EXPORT_SYMBOL_GPL(irq_domain_add_simple);
+
+void irq_domain_generate_simple(const struct of_device_id *match,
+				u64 phys_base, unsigned int irq_start)
+{
+	struct device_node *node;
+	pr_info("looking for phys_base=%llx, irq_start=%i\n",
+		(unsigned long long) phys_base, (int) irq_start);
+	node = of_find_matching_node_by_address(NULL, match, phys_base);
+	if (node)
+		irq_domain_add_simple(node, irq_start);
+	else
+		pr_info("no node found\n");
+}
+EXPORT_SYMBOL_GPL(irq_domain_generate_simple);
+#endif /* CONFIG_OF_IRQ */