diff --git a/arch/powerpc/cpu/mpc512x/fixed_sdram.c b/arch/powerpc/cpu/mpc512x/fixed_sdram.c
index 6451ea9a4aa5abef6712cc1359ca2db9a052e33f..68c5f8a27b31097cef00a8c52dee40cd6063a2fb 100644
--- a/arch/powerpc/cpu/mpc512x/fixed_sdram.c
+++ b/arch/powerpc/cpu/mpc512x/fixed_sdram.c
@@ -70,7 +70,7 @@ long int fixed_sdram(ddr512x_config_t *mddrc_config,
 		mddrc_config = &default_mddrc_config;
 	if (dram_init_seq == NULL) {
 		dram_init_seq = default_init_seq;
-		seq_sz = sizeof(default_init_seq)/sizeof(u32);
+		seq_sz = ARRAY_SIZE(default_init_seq);
 	}
 
 	/* Initialize IO Control */
diff --git a/arch/powerpc/cpu/mpc8260/cpu_init.c b/arch/powerpc/cpu/mpc8260/cpu_init.c
index a9bb5adeb2095493613da12c449218167279df65..55130f7831ef7ff7a4b5a2aa35c40fbce6918b90 100644
--- a/arch/powerpc/cpu/mpc8260/cpu_init.c
+++ b/arch/powerpc/cpu/mpc8260/cpu_init.c
@@ -253,7 +253,7 @@ int prt_8260_rsr (void)
 		RSR_ESRS, "External Soft"}, {
 		RSR_EHRS, "External Hard"}
 	};
-	static int n = sizeof bits / sizeof bits[0];
+	static int n = ARRAY_SIZE(bits);
 	ulong rsr = gd->arch.reset_status;
 	int i;
 	char *sep;
diff --git a/arch/powerpc/cpu/mpc8260/ether_fcc.c b/arch/powerpc/cpu/mpc8260/ether_fcc.c
index 9bb395e6a2621d317439fe5be68ebb4247874af2..a11ad1e9d06be650266fc48ee1d1402c853f15e8 100644
--- a/arch/powerpc/cpu/mpc8260/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc8260/ether_fcc.c
@@ -362,7 +362,7 @@ int fec_initialize(bd_t *bis)
 	struct eth_device* dev;
 	int i;
 
-	for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++)
+	for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++)
 	{
 		dev = (struct eth_device*) malloc(sizeof *dev);
 		memset(dev, 0, sizeof *dev);
@@ -432,7 +432,7 @@ static elbt_prdesc rxeacc_descs[] = {
 	{ offsetof(elbt_rxeacc, badlen),	"Bad Frame Length"	},
 	{ offsetof(elbt_rxeacc, badbit),	"Data Compare Errors"	},
 };
-static int rxeacc_ndesc = sizeof (rxeacc_descs) / sizeof (rxeacc_descs[0]);
+static int rxeacc_ndesc = ARRAY_SIZE(rxeacc_descs);
 
 typedef
 	struct {
@@ -449,7 +449,7 @@ static elbt_prdesc txeacc_descs[] = {
 	{ offsetof(elbt_txeacc, un),		"Underrun"		},
 	{ offsetof(elbt_txeacc, csl),		"Carrier Sense Lost"	},
 };
-static int txeacc_ndesc = sizeof (txeacc_descs) / sizeof (txeacc_descs[0]);
+static int txeacc_ndesc = ARRAY_SIZE(txeacc_descs);
 
 typedef
 	struct {
@@ -500,7 +500,7 @@ static elbt_prdesc epram_descs[] = {
 	{ offsetof(fcc_enet_t, fen_p512c),	"512-1023 Octet Frames"	},
 	{ offsetof(fcc_enet_t, fen_p1024c),	"1024-1518 Octet Frames"},
 };
-static int epram_ndesc = sizeof (epram_descs) / sizeof (epram_descs[0]);
+static int epram_ndesc = ARRAY_SIZE(epram_descs);
 
 /*
  * given an elbt_prdesc array and an array of base addresses, print
diff --git a/arch/powerpc/cpu/mpc83xx/cpu_init.c b/arch/powerpc/cpu/mpc83xx/cpu_init.c
index 0791043ee174e5ec4a38dda05ef2edb4bf3d171a..f911275b25f92e7c698dfc4c9238d816065a480a 100644
--- a/arch/powerpc/cpu/mpc83xx/cpu_init.c
+++ b/arch/powerpc/cpu/mpc83xx/cpu_init.c
@@ -484,7 +484,7 @@ int prt_83xx_rsr(void)
 		RSR_SRS,  "External/Internal Soft"}, {
 		RSR_HRS,  "External/Internal Hard"}
 	};
-	static int n = sizeof bits / sizeof bits[0];
+	static int n = ARRAY_SIZE(bits);
 	ulong rsr = gd->arch.reset_status;
 	int i;
 	char *sep;
diff --git a/arch/powerpc/cpu/mpc83xx/speed.c b/arch/powerpc/cpu/mpc83xx/speed.c
index 2e91f51fcee9e7ce9e77dffbdaedf7cb7513543d..5498c19e253d84e3a53b67a6f6fc7d2ec0af6206 100644
--- a/arch/powerpc/cpu/mpc83xx/speed.c
+++ b/arch/powerpc/cpu/mpc83xx/speed.c
@@ -412,7 +412,7 @@ int get_clocks(void)
 #endif
 
 	corecnf_tab_index = ((corepll & 0x1F) << 2) | ((corepll & 0x60) >> 5);
-	if (corecnf_tab_index > (sizeof(corecnf_tab) / sizeof(corecnf_t))) {
+	if (corecnf_tab_index > (ARRAY_SIZE(corecnf_tab))) {
 		/* corecnf_tab_index is too high, possibly wrong value */
 		return -11;
 	}
diff --git a/arch/powerpc/cpu/mpc85xx/ether_fcc.c b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
index 14358aeb03d8f3f6f7751aa6f4d57bc0e7650dd0..51f1beef5196a21f70067b1c3ae8a06c844ed9f6 100644
--- a/arch/powerpc/cpu/mpc85xx/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
@@ -424,7 +424,7 @@ int fec_initialize(bd_t *bis)
 	struct eth_device* dev;
 	int i;
 
-	for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++)
+	for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++)
 	{
 		dev = (struct eth_device*) malloc(sizeof *dev);
 		memset(dev, 0, sizeof *dev);
diff --git a/arch/powerpc/cpu/mpc8xx/fec.c b/arch/powerpc/cpu/mpc8xx/fec.c
index ea4ab3a04237837b4cb76480be9f79782e8d0e9c..f1ae3584660b33c39fa9802d53537b577ecbafef 100644
--- a/arch/powerpc/cpu/mpc8xx/fec.c
+++ b/arch/powerpc/cpu/mpc8xx/fec.c
@@ -137,7 +137,7 @@ int fec_initialize(bd_t *bis)
 	struct ether_fcc_info_s *efis;
 	int             i;
 
-	for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++) {
 
 		dev = malloc(sizeof(*dev));
 		if (dev == NULL)
@@ -879,7 +879,7 @@ void mii_init (void)
 
 	/* Setup the pin configuration of the FEC(s)
 	*/
-	for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++)
+	for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++)
 		fec_pin_init(ether_fcc_info[i].ether_index);
 }
 
diff --git a/arch/powerpc/cpu/ppc4xx/reginfo.c b/arch/powerpc/cpu/ppc4xx/reginfo.c
index 339d38aa998f522a1c059479e456809364de0931..a42327eb3dab7045e1ecc89105a33f2d21bc2aff 100644
--- a/arch/powerpc/cpu/ppc4xx/reginfo.c
+++ b/arch/powerpc/cpu/ppc4xx/reginfo.c
@@ -321,7 +321,7 @@ void ppc4xx_reginfo(void)
 	PRINT_DCR(OPB2PLB40_BCTRL);
 	PRINT_DCR(P4P3BO0_CFG);
 #endif
-	n = sizeof(ppc4xx_reg) / sizeof(ppc4xx_reg[0]);
+	n = ARRAY_SIZE(ppc4xx_reg);
 	for (i = 0; i < n; i++) {
 		value = 0;
 		type = ppc4xx_reg[i].type;
diff --git a/arch/powerpc/cpu/ppc4xx/sdram.c b/arch/powerpc/cpu/ppc4xx/sdram.c
index d4ef36d39ffc6f335e34ff7a2ec5c9089326579d..cd63456e700a32e5b532115f719638fba6954089 100644
--- a/arch/powerpc/cpu/ppc4xx/sdram.c
+++ b/arch/powerpc/cpu/ppc4xx/sdram.c
@@ -33,7 +33,7 @@ sdram_conf_t mb0cf[] = {
 sdram_conf_t mb0cf[] = CONFIG_SYS_SDRAM_TABLE;
 #endif
 
-#define N_MB0CF (sizeof(mb0cf) / sizeof(mb0cf[0]))
+#define N_MB0CF (ARRAY_SIZE(mb0cf))
 
 #ifdef CONFIG_SYS_SDRAM_CASL
 static ulong ns2clks(ulong ns)
@@ -266,7 +266,7 @@ sdram_conf_t mb0cf[] = CONFIG_SYS_SDRAM_TABLE;
 #define CONFIG_SYS_SDRAM0_CFG0		0x82000000 /* DCEN=1, PMUD=0, 64-bit */
 #endif
 
-#define N_MB0CF (sizeof(mb0cf) / sizeof(mb0cf[0]))
+#define N_MB0CF (ARRAY_SIZE(mb0cf))
 
 #define NUM_TRIES 64
 #define NUM_READS 10
diff --git a/arch/powerpc/include/asm/arch-mpc85xx/gpio.h b/arch/powerpc/include/asm/arch-mpc85xx/gpio.h
index da7352abb27a67a2d4677e01d7afaa247e78e7d2..41b6677bba38836bc4a29381f0f193380f66266a 100644
--- a/arch/powerpc/include/asm/arch-mpc85xx/gpio.h
+++ b/arch/powerpc/include/asm/arch-mpc85xx/gpio.h
@@ -14,6 +14,8 @@
 #ifndef __ASM_ARCH_MX85XX_GPIO_H
 #define __ASM_ARCH_MX85XX_GPIO_H
 
+#ifndef CONFIG_MPC85XX_GPIO
 #include <asm/mpc85xx_gpio.h>
+#endif
 
 #endif
diff --git a/arch/powerpc/include/asm/immap_85xx.h b/arch/powerpc/include/asm/immap_85xx.h
index 07d2adf71f1d8777107ee57bdaca84e39246a46e..c045a24d1aba15471434c22abfc6cae2fb56f66a 100644
--- a/arch/powerpc/include/asm/immap_85xx.h
+++ b/arch/powerpc/include/asm/immap_85xx.h
@@ -265,6 +265,7 @@ typedef struct ccsr_pcix {
 #define PIWAR_WRITE_SNOOP	0x00005000
 #define PIWAR_MEM_2G		0x0000001e
 
+#ifndef CONFIG_MPC85XX_GPIO
 typedef struct ccsr_gpio {
 	u32	gpdir;
 	u32	gpodr;
@@ -273,6 +274,7 @@ typedef struct ccsr_gpio {
 	u32	gpimr;
 	u32	gpicr;
 } ccsr_gpio_t;
+#endif
 
 /* L2 Cache Registers */
 typedef struct ccsr_l2cache {
diff --git a/arch/sandbox/include/asm/gpio.h b/arch/sandbox/include/asm/gpio.h
index 8317db1ad3d896a5f7ddefea6b9dd8dfe2a4dae3..427af2c97018d6627a84a869d7a2f4f5f8b9eca6 100644
--- a/arch/sandbox/include/asm/gpio.h
+++ b/arch/sandbox/include/asm/gpio.h
@@ -40,6 +40,26 @@ int sandbox_gpio_get_value(struct udevice *dev, unsigned int offset);
  */
 int sandbox_gpio_set_value(struct udevice *dev, unsigned int offset, int value);
 
+/**
+ * Set or reset the simulated open drain mode of a GPIO (used only in sandbox
+ * test code)
+ *
+ * @param gp	GPIO number
+ * @param value	value to set (0 for enabled open drain mode, non-zero for
+ * 		disabled)
+ * @return -1 on error, 0 if ok
+ */
+int sandbox_gpio_set_open_drain(struct udevice *dev, unsigned offset, int value);
+
+/**
+ * Return the state of the simulated open drain mode of a GPIO (used only in
+ * sandbox test code)
+ *
+ * @param gp	GPIO number
+ * @return -1 on error, 0 if GPIO is input, >0 if output
+ */
+int sandbox_gpio_get_open_drain(struct udevice *dev, unsigned offset);
+
 /**
  * Return the simulated direction of a GPIO (used only in sandbox test code)
  *
diff --git a/board/freescale/b4860qds/Makefile b/board/freescale/b4860qds/Makefile
index 0acd2a9aa4a02e3ad2b495ecb80e61610f644aff..673d2ea56ae5a1e62bb296982f4c4ff1f1cf2f5a 100644
--- a/board/freescale/b4860qds/Makefile
+++ b/board/freescale/b4860qds/Makefile
@@ -5,11 +5,11 @@
 #
 
 ifdef CONFIG_SPL_BUILD
-obj-y += spl.o
+obj-y	+= spl.o
 else
 obj-y	+= b4860qds.o
-obj-$(CONFIG_B4860QDS)+= eth_b4860qds.o
-obj-$(CONFIG_PCI)      += pci.o
+obj-$(CONFIG_B4860QDS)	+= eth_b4860qds.o
+obj-$(CONFIG_PCI)	+= pci.o
 endif
 
 obj-y	+= ddr.o
diff --git a/board/freescale/b4860qds/ddr.c b/board/freescale/b4860qds/ddr.c
index eb10a6f364af2e9842084ded5993f82976b5245a..31b186ea8ce9c51aaf35ed26dfc32d0a763ee764 100644
--- a/board/freescale/b4860qds/ddr.c
+++ b/board/freescale/b4860qds/ddr.c
@@ -179,15 +179,13 @@ phys_size_t initdram(int board_type)
 
 #if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_RAMBOOT_PBL)
 	puts("Initializing....using SPD\n");
-
 	dram_size = fsl_ddr_sdram();
-
-	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
-	dram_size *= 0x100000;
-
 #else
 	dram_size =  fsl_ddr_sdram_size();
 #endif
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	dram_size *= 0x100000;
+
 	return dram_size;
 }
 
diff --git a/board/freescale/b4860qds/spl.c b/board/freescale/b4860qds/spl.c
index 3f7cc03581afe07258b8fbf0bf8202e83869b7a0..fabc78301a05b522525c1fcbdfa705d6b04bac0d 100644
--- a/board/freescale/b4860qds/spl.c
+++ b/board/freescale/b4860qds/spl.c
@@ -91,6 +91,7 @@ void board_init_r(gd_t *gd, ulong dest_addr)
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 #ifndef CONFIG_SPL_NAND_BOOT
 	env_init();
diff --git a/board/freescale/bsc9131rdb/Makefile b/board/freescale/bsc9131rdb/Makefile
index b26d3a1e63d62a24d10d3a855fab685ecdfb50fe..8027750efbda1470e6ad3141a4bfbe0db80c9e65 100644
--- a/board/freescale/bsc9131rdb/Makefile
+++ b/board/freescale/bsc9131rdb/Makefile
@@ -13,15 +13,11 @@ endif
 endif
 
 ifdef MINIMAL
-
-obj-y	+= spl_minimal.o tlb.o law.o
-
+obj-y	+= spl_minimal.o
 else
-
-obj-y        += bsc9131rdb.o
-obj-y        += ddr.o
-obj-y        += law.o
-obj-y        += tlb.o
-#obj-y		+= bsc9131rdb_mux.o
-
+obj-y	+= bsc9131rdb.o
+obj-y	+= ddr.o
 endif
+
+obj-y	+= law.o
+obj-y	+= tlb.o
diff --git a/board/freescale/bsc9132qds/Makefile b/board/freescale/bsc9132qds/Makefile
index 2e4170f512f667b464259db351163f0206af5e54..54193350afd36b74fe1ea14075d0249e3c78c28a 100644
--- a/board/freescale/bsc9132qds/Makefile
+++ b/board/freescale/bsc9132qds/Makefile
@@ -13,14 +13,11 @@ endif
 endif
 
 ifdef MINIMAL
-
-obj-y	+= spl_minimal.o tlb.o law.o
-
+obj-y	+= spl_minimal.o
 else
-
 obj-y	+= bsc9132qds.o
 obj-y	+= ddr.o
+endif
+
 obj-y	+= law.o
 obj-y	+= tlb.o
-
-endif
diff --git a/board/freescale/c29xpcie/Makefile b/board/freescale/c29xpcie/Makefile
index 818484a57dc8ca49b1887340b8e7504054ef0a70..93b3cba03181dd4a098b0d723523a5abce247a43 100644
--- a/board/freescale/c29xpcie/Makefile
+++ b/board/freescale/c29xpcie/Makefile
@@ -11,15 +11,15 @@ endif
 endif
 
 ifdef MINIMAL
-obj-y	+= spl_minimal.o tlb.o law.o
+obj-y	+= spl_minimal.o
 else
 ifdef CONFIG_SPL_BUILD
 obj-y	+= spl.o
 endif
-
 obj-y	+= c29xpcie.o
 obj-y	+= cpld.o
 obj-y	+= ddr.o
+endif
+
 obj-y	+= law.o
 obj-y	+= tlb.o
-endif
diff --git a/board/freescale/c29xpcie/spl.c b/board/freescale/c29xpcie/spl.c
index 3d31d41a4f6de59b70628ac8e2ca78e4f897e216..d8d73c70b8e8e31a7b99b94947e87800780d761a 100644
--- a/board/freescale/c29xpcie/spl.c
+++ b/board/freescale/c29xpcie/spl.c
@@ -57,6 +57,7 @@ void board_init_r(gd_t *gd, ulong dest_addr)
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 	/* relocate environment function pointers etc. */
 	nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
diff --git a/board/freescale/p1010rdb/Makefile b/board/freescale/p1010rdb/Makefile
index 660d1bbc2aaf7671b72bbca2dc50070c937aae55..86eb6946dd12744fcb74deef9b0208fe11327d6e 100644
--- a/board/freescale/p1010rdb/Makefile
+++ b/board/freescale/p1010rdb/Makefile
@@ -13,18 +13,14 @@ endif
 endif
 
 ifdef MINIMAL
-
-obj-y	+= spl_minimal.o tlb.o law.o
-
+obj-y	+= spl_minimal.o
 else
-
 ifdef CONFIG_SPL_BUILD
-obj-y += spl.o
+obj-y	+= spl.o
 endif
-
 obj-y	+= p1010rdb.o
 obj-y	+= ddr.o
+endif
+
 obj-y	+= law.o
 obj-y	+= tlb.o
-
-endif
diff --git a/board/freescale/p1010rdb/spl.c b/board/freescale/p1010rdb/spl.c
index eb8e567554c8840bdfb14d2dce541621692dcbd9..f8584084ce5cc9b7421736cc249093c060e8e42e 100644
--- a/board/freescale/p1010rdb/spl.c
+++ b/board/freescale/p1010rdb/spl.c
@@ -72,6 +72,7 @@ void board_init_r(gd_t *gd, ulong dest_addr)
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 #ifndef CONFIG_SPL_NAND_BOOT
 	env_init();
diff --git a/board/freescale/p1022ds/Makefile b/board/freescale/p1022ds/Makefile
index a5821277ef7be0536cf6b16ba81c5063ed373235..9793853463c67f5b6d210f2bdd69dbfef52027a9 100644
--- a/board/freescale/p1022ds/Makefile
+++ b/board/freescale/p1022ds/Makefile
@@ -13,17 +13,15 @@ endif
 endif
 
 ifdef MINIMAL
-
-obj-y        += spl_minimal.o tlb.o law.o
-
+obj-y	+= spl_minimal.o
 else
 ifdef CONFIG_SPL_BUILD
-obj-y += spl.o
+obj-y	+= spl.o
 endif
 obj-y	+= p1022ds.o
 obj-y	+= ddr.o
-obj-y	+= law.o
-obj-y	+= tlb.o
-
 obj-$(CONFIG_FSL_DIU_FB) += diu.o
 endif
+
+obj-y	+= law.o
+obj-y	+= tlb.o
diff --git a/board/freescale/p1022ds/spl.c b/board/freescale/p1022ds/spl.c
index 89ef95aab891735ac1c0e80cf42ef3b731c32ff8..04db767f9810468e67c2a95fc1a95038e7c7e1e0 100644
--- a/board/freescale/p1022ds/spl.c
+++ b/board/freescale/p1022ds/spl.c
@@ -86,6 +86,7 @@ void board_init_r(gd_t *gd, ulong dest_addr)
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 #ifndef CONFIG_SPL_NAND_BOOT
 	env_init();
 #endif
diff --git a/board/freescale/p1_p2_rdb_pc/Makefile b/board/freescale/p1_p2_rdb_pc/Makefile
index a2a1f92ce86adf2165677c0bd58538a6ac405f11..045d4093aecd0e307da0c2eada300946fa4a2d80 100644
--- a/board/freescale/p1_p2_rdb_pc/Makefile
+++ b/board/freescale/p1_p2_rdb_pc/Makefile
@@ -13,17 +13,14 @@ endif
 endif
 
 ifdef MINIMAL
-
-obj-y	+= spl_minimal.o tlb.o law.o
-
+obj-y	+= spl_minimal.o
 else
 ifdef CONFIG_SPL_BUILD
-obj-y += spl.o
+obj-y	+= spl.o
 endif
-
-obj-y        += p1_p2_rdb_pc.o
-obj-y        += ddr.o
-obj-y        += law.o
-obj-y        += tlb.o
-
+obj-y	+= p1_p2_rdb_pc.o
+obj-y	+= ddr.o
 endif
+
+obj-y	+= law.o
+obj-y	+= tlb.o
diff --git a/board/freescale/p1_p2_rdb_pc/spl.c b/board/freescale/p1_p2_rdb_pc/spl.c
index 0142746c84211a0dea7da0133091b4d3b97ea467..76a3cf47cc68ba5be19129f26f94e7f312f1a492 100644
--- a/board/freescale/p1_p2_rdb_pc/spl.c
+++ b/board/freescale/p1_p2_rdb_pc/spl.c
@@ -83,6 +83,7 @@ void board_init_r(gd_t *gd, ulong dest_addr)
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 #ifndef CONFIG_SPL_NAND_BOOT
 	env_init();
diff --git a/board/freescale/p2041rdb/Makefile b/board/freescale/p2041rdb/Makefile
index c74f4c62f86142db60c880bfd4b0099dd7339fc1..a335ec65fafed89a9c68d5fc720a8463d53bb4bb 100644
--- a/board/freescale/p2041rdb/Makefile
+++ b/board/freescale/p2041rdb/Makefile
@@ -7,6 +7,6 @@
 #
 
 obj-y	+= p2041rdb.o
-obj-y += cpld.o
+obj-y	+= cpld.o
 obj-y	+= ddr.o
 obj-y	+= eth.o
diff --git a/board/freescale/t102xqds/Makefile b/board/freescale/t102xqds/Makefile
index d94f2307d9b50802b080155317c6748b34c206ce..afbc9146ed805d153826ef83b1b1867589870116 100644
--- a/board/freescale/t102xqds/Makefile
+++ b/board/freescale/t102xqds/Makefile
@@ -5,7 +5,7 @@
 #
 
 ifdef CONFIG_SPL_BUILD
-obj-y += spl.o
+obj-y	+= spl.o
 else
 obj-y	+= t102xqds.o
 obj-y	+= eth_t102xqds.o
diff --git a/board/freescale/t102xqds/ddr.c b/board/freescale/t102xqds/ddr.c
index 912d6a950f8c4653e222797c599f2e8b91a54020..c26f3503b99192bf009010fe0df981c9a5f9c005 100644
--- a/board/freescale/t102xqds/ddr.c
+++ b/board/freescale/t102xqds/ddr.c
@@ -172,14 +172,13 @@ phys_size_t initdram(int board_type)
 
 #if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_RAMBOOT_PBL)
 	puts("Initializing....using SPD\n");
-
 	dram_size = fsl_ddr_sdram();
-	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
-	dram_size *= 0x100000;
 #else
 	/* DDR has been initialised by first stage boot loader */
 	dram_size =  fsl_ddr_sdram_size();
 #endif
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	dram_size *= 0x100000;
 
 #if defined(CONFIG_DEEP_SLEEP) && !defined(CONFIG_SPL_BUILD)
 	fsl_dp_resume();
diff --git a/board/freescale/t102xqds/spl.c b/board/freescale/t102xqds/spl.c
index 073ff2dcde1cf893ad33f0a56c54021624cbe702..d59d3431ec1fd02cb4b771834c2ca92ef030da42 100644
--- a/board/freescale/t102xqds/spl.c
+++ b/board/freescale/t102xqds/spl.c
@@ -120,6 +120,7 @@ void board_init_r(gd_t *gd, ulong dest_addr)
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 #ifdef CONFIG_SPL_NAND_BOOT
 	nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
diff --git a/board/freescale/t102xrdb/Makefile b/board/freescale/t102xrdb/Makefile
index 052006610e6d3b211d317a517930bef02bd9e9a7..64528656aca8bd821093ebec25c93370682532f7 100644
--- a/board/freescale/t102xrdb/Makefile
+++ b/board/freescale/t102xrdb/Makefile
@@ -5,7 +5,7 @@
 #
 
 ifdef CONFIG_SPL_BUILD
-obj-y += spl.o
+obj-y	+= spl.o
 else
 obj-y   += t102xrdb.o
 obj-$(CONFIG_T1024RDB)   += cpld.o
diff --git a/board/freescale/t102xrdb/ddr.c b/board/freescale/t102xrdb/ddr.c
index 60ab9ff8ade08a6d775656842098d9d0903ce0a4..edfbdbf3a814e65b1fe3fd246b51f2fa38c9f5fd 100644
--- a/board/freescale/t102xrdb/ddr.c
+++ b/board/freescale/t102xrdb/ddr.c
@@ -234,12 +234,12 @@ phys_size_t initdram(int board_type)
 	puts("Initializing....using SPD\n");
 #endif
 	dram_size = fsl_ddr_sdram();
-	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
-	dram_size *= 0x100000;
 #else
 	/* DDR has been initialised by first stage boot loader */
 	dram_size =  fsl_ddr_sdram_size();
 #endif
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	dram_size *= 0x100000;
 
 #if defined(CONFIG_DEEP_SLEEP) && !defined(CONFIG_SPL_BUILD)
 	fsl_dp_resume();
diff --git a/board/freescale/t102xrdb/spl.c b/board/freescale/t102xrdb/spl.c
index da97c440c48bf845d6a274d976fb7611b6c6339b..bd3cbbf11c97a6c214bb06ad6335479a1f8d9394 100644
--- a/board/freescale/t102xrdb/spl.c
+++ b/board/freescale/t102xrdb/spl.c
@@ -107,6 +107,7 @@ void board_init_r(gd_t *gd, ulong dest_addr)
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 #ifdef CONFIG_SPL_NAND_BOOT
 	nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
diff --git a/board/freescale/t104xrdb/ddr.c b/board/freescale/t104xrdb/ddr.c
index cf79d2ddb2d462b7051ee473cbfc5909952f22e7..22d6a5f617693c71bca2050627aa46788a4b66a3 100644
--- a/board/freescale/t104xrdb/ddr.c
+++ b/board/freescale/t104xrdb/ddr.c
@@ -124,15 +124,12 @@ phys_size_t initdram(int board_type)
 
 #if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_RAMBOOT_PBL)
 	puts("Initializing....using SPD\n");
-
 	dram_size = fsl_ddr_sdram();
-
-	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
-	dram_size *= 0x100000;
-
 #else
 	dram_size =  fsl_ddr_sdram_size();
 #endif
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	dram_size *= 0x100000;
 
 #if defined(CONFIG_DEEP_SLEEP) && !defined(CONFIG_SPL_BUILD)
 	fsl_dp_resume();
diff --git a/board/freescale/t104xrdb/spl.c b/board/freescale/t104xrdb/spl.c
index 81f48c4c3010a7f71c740f3d736dc087c86e7a56..4b35af63f65d6f421d88ff910167854889ce8802 100644
--- a/board/freescale/t104xrdb/spl.c
+++ b/board/freescale/t104xrdb/spl.c
@@ -98,6 +98,7 @@ void board_init_r(gd_t *gd, ulong dest_addr)
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 #ifdef CONFIG_SPL_MMC_BOOT
 	mmc_initialize(bd);
diff --git a/board/freescale/t208xqds/Makefile b/board/freescale/t208xqds/Makefile
index 6cb72c9fd5dce24158f1930079ba692002a7192e..ef04a26463f9f6ff07d7beedc66559659ca0f031 100644
--- a/board/freescale/t208xqds/Makefile
+++ b/board/freescale/t208xqds/Makefile
@@ -7,10 +7,8 @@
 ifdef CONFIG_SPL_BUILD
 obj-y += spl.o
 else
-obj-$(CONFIG_T2080QDS) += t208xqds.o
-obj-$(CONFIG_T2080QDS) += eth_t208xqds.o
-obj-$(CONFIG_T2081QDS) += t208xqds.o
-obj-$(CONFIG_T2081QDS) += eth_t208xqds.o
+obj-$(CONFIG_T2080QDS) += t208xqds.o eth_t208xqds.o
+obj-$(CONFIG_T2081QDS) += t208xqds.o eth_t208xqds.o
 obj-$(CONFIG_PCI)      += pci.o
 endif
 
diff --git a/board/freescale/t208xqds/ddr.c b/board/freescale/t208xqds/ddr.c
index f1aff5481e49aeeb8a4c7d549ac7709cfaadc5aa..f96470f0206b551d2351369e784cca665040fc2b 100644
--- a/board/freescale/t208xqds/ddr.c
+++ b/board/freescale/t208xqds/ddr.c
@@ -108,13 +108,12 @@ phys_size_t initdram(int board_type)
 #if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_RAMBOOT_PBL)
 	puts("Initializing....using SPD\n");
 	dram_size = fsl_ddr_sdram();
-
-	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
-	dram_size *= 0x100000;
 #else
 	/* DDR has been initialised by first stage boot loader */
 	dram_size =  fsl_ddr_sdram_size();
 #endif
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	dram_size *= 0x100000;
 
 	return dram_size;
 }
diff --git a/board/freescale/t208xqds/spl.c b/board/freescale/t208xqds/spl.c
index 55a0f8fdce5bea1cdfd51f4c058eb2270a733d2e..bb02dab2f1539fdd103aee35c42d5abab37aa2d7 100644
--- a/board/freescale/t208xqds/spl.c
+++ b/board/freescale/t208xqds/spl.c
@@ -106,6 +106,7 @@ void board_init_r(gd_t *gd, ulong dest_addr)
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 #ifdef CONFIG_SPL_NAND_BOOT
 	nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
diff --git a/board/freescale/t208xrdb/Makefile b/board/freescale/t208xrdb/Makefile
index 9605f8b606c5e27927befe14b2b25c4ce2922ba6..cd8fe096d82426d48f1aa7eb9b9bebbf9cc62a1e 100644
--- a/board/freescale/t208xrdb/Makefile
+++ b/board/freescale/t208xrdb/Makefile
@@ -5,11 +5,9 @@
 #
 
 ifdef CONFIG_SPL_BUILD
-obj-y += spl.o
+obj-y	+= spl.o
 else
-obj-$(CONFIG_T2080RDB) += t208xrdb.o
-obj-$(CONFIG_T2080RDB) += eth_t208xrdb.o
-obj-$(CONFIG_T2080RDB) += cpld.o
+obj-$(CONFIG_T2080RDB) += t208xrdb.o eth_t208xrdb.o cpld.o
 obj-$(CONFIG_PCI)      += pci.o
 endif
 
diff --git a/board/freescale/t208xrdb/ddr.c b/board/freescale/t208xrdb/ddr.c
index 053f128e5b2286d84f727d022151839f36c2d8c5..f6c8ca30ac44388f35d2579e37cb2fb8c3c91098 100644
--- a/board/freescale/t208xrdb/ddr.c
+++ b/board/freescale/t208xrdb/ddr.c
@@ -101,12 +101,12 @@ phys_size_t initdram(int board_type)
 #if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_RAMBOOT_PBL)
 	puts("Initializing....using SPD\n");
 	dram_size = fsl_ddr_sdram();
-
-	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
-	dram_size *= 0x100000;
 #else
 	/* DDR has been initialised by first stage boot loader */
 	dram_size = fsl_ddr_sdram_size();
 #endif
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	dram_size *= 0x100000;
+
 	return dram_size;
 }
diff --git a/board/freescale/t208xrdb/spl.c b/board/freescale/t208xrdb/spl.c
index f63366bb0e6336614c73fd0d4b9d7ba5b30ec6ac..2ff05a29f507dae081ed7233d209a3bbc6994d1d 100644
--- a/board/freescale/t208xrdb/spl.c
+++ b/board/freescale/t208xrdb/spl.c
@@ -76,6 +76,7 @@ void board_init_r(gd_t *gd, ulong dest_addr)
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 #ifdef CONFIG_SPL_NAND_BOOT
 	nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
diff --git a/board/freescale/t4qds/Makefile b/board/freescale/t4qds/Makefile
index bd2c1f16222a1bd0a226cbed457b690936bfa4e8..731ccb0b295c1fcc255b38408f6b982f04391bd8 100644
--- a/board/freescale/t4qds/Makefile
+++ b/board/freescale/t4qds/Makefile
@@ -5,12 +5,12 @@
 #
 
 ifdef CONFIG_SPL_BUILD
-obj-y += spl.o
+obj-y	+= spl.o
 else
-obj-$(CONFIG_T4240QDS) += t4240qds.o
-obj-$(CONFIG_T4240QDS)+= eth.o
+obj-$(CONFIG_T4240QDS)	+= t4240qds.o eth.o
 obj-$(CONFIG_PCI)	+= pci.o
 endif
+
 obj-y	+= ddr.o
 obj-y	+= law.o
 obj-y	+= tlb.o
diff --git a/board/freescale/t4qds/ddr.c b/board/freescale/t4qds/ddr.c
index 62d58c5b1f10c183c628ecdfa59f812a04977966..d533924a0dd38ac76860870ba388e99d5b6383a2 100644
--- a/board/freescale/t4qds/ddr.c
+++ b/board/freescale/t4qds/ddr.c
@@ -117,13 +117,12 @@ phys_size_t initdram(int board_type)
 
 #if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_RAMBOOT_PBL)
 	dram_size = fsl_ddr_sdram();
-
-	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
-	dram_size *= 0x100000;
-
 #else
 	/* DDR has been initialised by first stage boot loader */
 	dram_size = fsl_ddr_sdram_size();
 #endif
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	dram_size *= 0x100000;
+
 	return dram_size;
 }
diff --git a/board/freescale/t4qds/spl.c b/board/freescale/t4qds/spl.c
index d52059a145330eff991256e1a32bbd91a684760c..6ca0f03ffe837b6ec886107b1248b5cb31d0c131 100644
--- a/board/freescale/t4qds/spl.c
+++ b/board/freescale/t4qds/spl.c
@@ -116,6 +116,7 @@ void board_init_r(gd_t *gd, ulong dest_addr)
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 #ifdef CONFIG_SPL_NAND_BOOT
 	nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
diff --git a/board/freescale/t4rdb/Makefile b/board/freescale/t4rdb/Makefile
index 83b55ee193460f4ad2bce1a6640ad05a312e7ece..4f29eea0f45985da2f263ae5bdb74183347dd980 100644
--- a/board/freescale/t4rdb/Makefile
+++ b/board/freescale/t4rdb/Makefile
@@ -5,13 +5,14 @@
 #
 
 ifdef CONFIG_SPL_BUILD
-obj-y += spl.o
+obj-y	+= spl.o
 else
-obj-$(CONFIG_T4240RDB) += t4240rdb.o
-obj-y	+= cpld.o
-obj-y	+= eth.o
+obj-$(CONFIG_T4240RDB)	+= t4240rdb.o
+obj-y			+= cpld.o
+obj-y			+= eth.o
 obj-$(CONFIG_PCI)	+= pci.o
 endif
+
 obj-y	+= ddr.o
 obj-y	+= law.o
 obj-y	+= tlb.o
diff --git a/board/freescale/t4rdb/ddr.c b/board/freescale/t4rdb/ddr.c
index 27b37b5cc42284c2bedc732da48bed95bcc601e8..230f031a3bf8d9319869f6d22f8bc8709a2f3504 100644
--- a/board/freescale/t4rdb/ddr.c
+++ b/board/freescale/t4rdb/ddr.c
@@ -110,13 +110,12 @@ phys_size_t initdram(int board_type)
 
 #if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_RAMBOOT_PBL)
 	dram_size = fsl_ddr_sdram();
-
-	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
-	dram_size *= 0x100000;
 #else
 	/* DDR has been initialised by first stage boot loader */
 	dram_size = fsl_ddr_sdram_size();
 #endif
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	dram_size *= 0x100000;
 
 	return dram_size;
 }
diff --git a/board/freescale/t4rdb/spl.c b/board/freescale/t4rdb/spl.c
index 4c1e0cc8d0e83ad2b127a0e406d2f3203896d5f1..b148a7fd1fad974269307032d8788e30cc13831b 100644
--- a/board/freescale/t4rdb/spl.c
+++ b/board/freescale/t4rdb/spl.c
@@ -80,6 +80,7 @@ void board_init_r(gd_t *gd, ulong dest_addr)
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 	mmc_initialize(bd);
 	mmc_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 32219ed478899dfb997f01c7b66de261e36d9051..73b862dc0b219b1a5e5445fb113f10d83e554c0a 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -188,4 +188,30 @@ config DM_PCA953X
 
 	  Now, max 24 bits chips and PCA953X compatible chips are
 	  supported
+
+config MPC85XX_GPIO
+	bool "Freescale MPC85XX GPIO driver"
+	depends on DM_GPIO
+	help
+	  This driver supports the built-in GPIO controller of MPC85XX CPUs.
+	  Each GPIO bank is identified by its own entry in the device tree,
+	  i.e.
+
+	  gpio-controller@fc00 {
+		#gpio-cells = <2>;
+		compatible = "fsl,pq3-gpio";
+		reg = <0xfc00 0x100>
+	  }
+
+	  By default, each bank is assumed to have 32 GPIOs, but the ngpios
+	  setting is honored, so the number of GPIOs for each bank is
+	  configurable to match the actual GPIO count of the SoC (e.g. the
+	  32/32/23 banks of the P1022 SoC).
+
+	  Aside from the standard functions of input/output mode, and output
+	  value setting, the open-drain feature, which can configure individual
+	  GPIOs to work as open-drain outputs, is supported.
+
+	  The driver has been tested on MPC85XX, but it is likely that other
+	  PowerQUICC III devices will work as well.
 endmenu
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 3c4310176d1d86bf8807e604ba0aa515a5f6724c..792d19186aadf19a4a0a6a63efcccb759d24188a 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_DA8XX_GPIO)	+= da8xx_gpio.o
 obj-$(CONFIG_DM644X_GPIO)	+= da8xx_gpio.o
 obj-$(CONFIG_ALTERA_PIO)	+= altera_pio.o
 obj-$(CONFIG_MPC83XX_GPIO)	+= mpc83xx_gpio.o
+obj-$(CONFIG_MPC85XX_GPIO)	+= mpc85xx_gpio.o
 obj-$(CONFIG_SH_GPIO_PFC)	+= sh_pfc.o
 obj-$(CONFIG_OMAP_GPIO)	+= omap_gpio.o
 obj-$(CONFIG_DB8500_GPIO)	+= db8500_gpio.o
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 732b6c2afa12ac8b99b66ee97465971defeb1f73..4559739d619c637d79495e349290b7ae93646de9 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -367,6 +367,38 @@ int dm_gpio_set_value(const struct gpio_desc *desc, int value)
 	return 0;
 }
 
+int dm_gpio_get_open_drain(struct gpio_desc *desc)
+{
+	struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
+	int ret;
+
+	ret = check_reserved(desc, "get_open_drain");
+	if (ret)
+		return ret;
+
+	if (ops->set_open_drain)
+		return ops->get_open_drain(desc->dev, desc->offset);
+	else
+		return -ENOSYS;
+}
+
+int dm_gpio_set_open_drain(struct gpio_desc *desc, int value)
+{
+	struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
+	int ret;
+
+	ret = check_reserved(desc, "set_open_drain");
+	if (ret)
+		return ret;
+
+	if (ops->set_open_drain)
+		ret = ops->set_open_drain(desc->dev, desc->offset, value);
+	else
+		return 0; /* feature not supported -> ignore setting */
+
+	return ret;
+}
+
 int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
 {
 	struct udevice *dev = desc->dev;
diff --git a/drivers/gpio/mpc85xx_gpio.c b/drivers/gpio/mpc85xx_gpio.c
new file mode 100644
index 0000000000000000000000000000000000000000..04773e2b31c3074e322dff41debfb5bc63522f4f
--- /dev/null
+++ b/drivers/gpio/mpc85xx_gpio.c
@@ -0,0 +1,228 @@
+/*
+ * (C) Copyright 2016
+ * Mario Six, Guntermann & Drunck GmbH, six@gdsys.de
+ *
+ * based on arch/powerpc/include/asm/mpc85xx_gpio.h, which is
+ *
+ * Copyright 2010 eXMeritus, A Boeing Company
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/gpio.h>
+#include <mapmem.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct ccsr_gpio {
+	u32	gpdir;
+	u32	gpodr;
+	u32	gpdat;
+	u32	gpier;
+	u32	gpimr;
+	u32	gpicr;
+};
+
+struct mpc85xx_gpio_data {
+	/* The bank's register base in memory */
+	struct ccsr_gpio __iomem *base;
+	/* The address of the registers; used to identify the bank */
+	ulong addr;
+	/* The GPIO count of the bank */
+	uint gpio_count;
+	/* The GPDAT register cannot be used to determine the value of output
+	 * pins on MPC8572/MPC8536, so we shadow it and use the shadowed value
+	 * for output pins */
+	u32 dat_shadow;
+};
+
+inline u32 gpio_mask(unsigned gpio) {
+	return (1U << (31 - (gpio)));
+}
+
+static inline u32 mpc85xx_gpio_get_val(struct ccsr_gpio *base, u32 mask)
+{
+	return in_be32(&base->gpdat) & mask;
+}
+
+static inline u32 mpc85xx_gpio_get_dir(struct ccsr_gpio *base, u32 mask)
+{
+	return in_be32(&base->gpdir) & mask;
+}
+
+static inline void mpc85xx_gpio_set_in(struct ccsr_gpio *base, u32 gpios)
+{
+	clrbits_be32(&base->gpdat, gpios);
+	/* GPDIR register 0 -> input */
+	clrbits_be32(&base->gpdir, gpios);
+}
+
+static inline void mpc85xx_gpio_set_low(struct ccsr_gpio *base, u32 gpios)
+{
+	clrbits_be32(&base->gpdat, gpios);
+	/* GPDIR register 1 -> output */
+	setbits_be32(&base->gpdir, gpios);
+}
+
+static inline void mpc85xx_gpio_set_high(struct ccsr_gpio *base, u32 gpios)
+{
+	setbits_be32(&base->gpdat, gpios);
+	/* GPDIR register 1 -> output */
+	setbits_be32(&base->gpdir, gpios);
+}
+
+static inline int mpc85xx_gpio_open_drain_val(struct ccsr_gpio *base, u32 mask)
+{
+	return in_be32(&base->gpodr) & mask;
+}
+
+static inline void mpc85xx_gpio_open_drain_on(struct ccsr_gpio *base, u32
+					      gpios)
+{
+	/* GPODR register 1 -> open drain on */
+	setbits_be32(&base->gpodr, gpios);
+}
+
+static inline void mpc85xx_gpio_open_drain_off(struct ccsr_gpio *base,
+					       u32 gpios)
+{
+	/* GPODR register 0 -> open drain off (actively driven) */
+	clrbits_be32(&base->gpodr, gpios);
+}
+
+static int mpc85xx_gpio_direction_input(struct udevice *dev, unsigned gpio)
+{
+	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
+
+	mpc85xx_gpio_set_in(data->base, gpio_mask(gpio));
+	return 0;
+}
+
+static int mpc85xx_gpio_set_value(struct udevice *dev, unsigned gpio,
+				  int value)
+{
+	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
+
+	if (value) {
+		data->dat_shadow |= gpio_mask(gpio);
+		mpc85xx_gpio_set_high(data->base, gpio_mask(gpio));
+	} else {
+		data->dat_shadow &= ~gpio_mask(gpio);
+		mpc85xx_gpio_set_low(data->base, gpio_mask(gpio));
+	}
+	return 0;
+}
+
+static int mpc85xx_gpio_direction_output(struct udevice *dev, unsigned gpio,
+					 int value)
+{
+	return mpc85xx_gpio_set_value(dev, gpio, value);
+}
+
+static int mpc85xx_gpio_get_value(struct udevice *dev, unsigned gpio)
+{
+	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
+
+	if (!!mpc85xx_gpio_get_dir(data->base, gpio_mask(gpio))) {
+		/* Output -> use shadowed value */
+		return !!(data->dat_shadow & gpio_mask(gpio));
+	} else {
+		/* Input -> read value from GPDAT register */
+		return !!mpc85xx_gpio_get_val(data->base, gpio_mask(gpio));
+	}
+}
+
+static int mpc85xx_gpio_get_open_drain(struct udevice *dev, unsigned gpio)
+{
+	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
+
+	return !!mpc85xx_gpio_open_drain_val(data->base, gpio_mask(gpio));
+}
+
+static int mpc85xx_gpio_set_open_drain(struct udevice *dev, unsigned gpio,
+				       int value)
+{
+	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
+
+	if (value) {
+		mpc85xx_gpio_open_drain_on(data->base, gpio_mask(gpio));
+	} else {
+		mpc85xx_gpio_open_drain_off(data->base, gpio_mask(gpio));
+	}
+	return 0;
+}
+
+static int mpc85xx_gpio_get_function(struct udevice *dev, unsigned gpio)
+{
+	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
+	int dir;
+
+	dir = !!mpc85xx_gpio_get_dir(data->base, gpio_mask(gpio));
+	return dir ? GPIOF_OUTPUT : GPIOF_INPUT;
+}
+
+static int mpc85xx_gpio_ofdata_to_platdata(struct udevice *dev) {
+	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
+	fdt_addr_t addr;
+	fdt_size_t size;
+
+	addr = fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, dev->of_offset,
+						  "reg", 0, &size);
+
+	data->addr = addr;
+	data->base = map_sysmem(CONFIG_SYS_IMMR + addr, size);
+
+	if (!data->base)
+		return -ENOMEM;
+
+	data->gpio_count = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+					  "ngpios", 32);
+	data->dat_shadow = 0;
+
+	return 0;
+}
+
+static int mpc85xx_gpio_probe(struct udevice *dev)
+{
+	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
+	char name[32], *str;
+
+	snprintf(name, sizeof(name), "MPC@%lx_", data->addr);
+	str = strdup(name);
+
+	if (!str)
+		return -ENOMEM;
+
+	uc_priv->bank_name = str;
+	uc_priv->gpio_count = data->gpio_count;
+
+	return 0;
+}
+
+static const struct dm_gpio_ops gpio_mpc85xx_ops = {
+	.direction_input	= mpc85xx_gpio_direction_input,
+	.direction_output	= mpc85xx_gpio_direction_output,
+	.get_value		= mpc85xx_gpio_get_value,
+	.set_value		= mpc85xx_gpio_set_value,
+	.get_open_drain		= mpc85xx_gpio_get_open_drain,
+	.set_open_drain		= mpc85xx_gpio_set_open_drain,
+	.get_function 		= mpc85xx_gpio_get_function,
+};
+
+static const struct udevice_id mpc85xx_gpio_ids[] = {
+	{ .compatible = "fsl,pq3-gpio" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(gpio_mpc85xx) = {
+	.name	= "gpio_mpc85xx",
+	.id	= UCLASS_GPIO,
+	.ops	= &gpio_mpc85xx_ops,
+	.ofdata_to_platdata = mpc85xx_gpio_ofdata_to_platdata,
+	.of_match = mpc85xx_gpio_ids,
+	.probe	= mpc85xx_gpio_probe,
+	.priv_auto_alloc_size = sizeof(struct mpc85xx_gpio_data),
+};
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index a9b1efcd061222220be45b881ec3a119164ab7f8..f6435a0543ba787981a70830d65f6c923f97aa4e 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -15,6 +15,7 @@ DECLARE_GLOBAL_DATA_PTR;
 /* Flags for each GPIO */
 #define GPIOF_OUTPUT	(1 << 0)	/* Currently set as an output */
 #define GPIOF_HIGH	(1 << 1)	/* Currently set high */
+#define GPIOF_ODR	(1 << 2)	/* Currently set to open drain mode */
 
 struct gpio_state {
 	const char *label;	/* label given by requester */
@@ -70,6 +71,16 @@ int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value)
 	return set_gpio_flag(dev, offset, GPIOF_HIGH, value);
 }
 
+int sandbox_gpio_get_open_drain(struct udevice *dev, unsigned offset)
+{
+	return get_gpio_flag(dev, offset, GPIOF_ODR);
+}
+
+int sandbox_gpio_set_open_drain(struct udevice *dev, unsigned offset, int value)
+{
+	return set_gpio_flag(dev, offset, GPIOF_ODR, value);
+}
+
 int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset)
 {
 	return get_gpio_flag(dev, offset, GPIOF_OUTPUT);
@@ -124,6 +135,28 @@ static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
 	return sandbox_gpio_set_value(dev, offset, value);
 }
 
+/* read GPIO ODR value of port 'offset' */
+static int sb_gpio_get_open_drain(struct udevice *dev, unsigned offset)
+{
+	debug("%s: offset:%u\n", __func__, offset);
+
+	return sandbox_gpio_get_open_drain(dev, offset);
+}
+
+/* write GPIO ODR value to port 'offset' */
+static int sb_gpio_set_open_drain(struct udevice *dev, unsigned offset, int value)
+{
+	debug("%s: offset:%u, value = %d\n", __func__, offset, value);
+
+	if (!sandbox_gpio_get_direction(dev, offset)) {
+		printf("sandbox_gpio: error: set_open_drain on input gpio %u\n",
+		       offset);
+		return -1;
+	}
+
+	return sandbox_gpio_set_open_drain(dev, offset, value);
+}
+
 static int sb_gpio_get_function(struct udevice *dev, unsigned offset)
 {
 	if (get_gpio_flag(dev, offset, GPIOF_OUTPUT))
@@ -154,6 +187,8 @@ static const struct dm_gpio_ops gpio_sandbox_ops = {
 	.direction_output	= sb_gpio_direction_output,
 	.get_value		= sb_gpio_get_value,
 	.set_value		= sb_gpio_set_value,
+	.get_open_drain		= sb_gpio_get_open_drain,
+	.set_open_drain		= sb_gpio_set_open_drain,
 	.get_function		= sb_gpio_get_function,
 	.xlate			= sb_gpio_xlate,
 };
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 2500c10450062542b0b9ba2262adb6af6a7a5c6a..4aa0004fab4b2cc67e414b395ca38f9403e950c4 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -251,6 +251,8 @@ struct dm_gpio_ops {
 				int value);
 	int (*get_value)(struct udevice *dev, unsigned offset);
 	int (*set_value)(struct udevice *dev, unsigned offset, int value);
+	int (*get_open_drain)(struct udevice *dev, unsigned offset);
+	int (*set_open_drain)(struct udevice *dev, unsigned offset, int value);
 	/**
 	 * get_function() Get the GPIO function
 	 *
@@ -549,6 +551,38 @@ int dm_gpio_get_value(const struct gpio_desc *desc);
 
 int dm_gpio_set_value(const struct gpio_desc *desc, int value);
 
+/**
+ * dm_gpio_get_open_drain() - Check if open-drain-mode of a GPIO is active
+ *
+ * This checks if open-drain-mode for a GPIO is enabled or not. This method is
+ * optional.
+ *
+ * @desc:	GPIO description containing device, offset and flags,
+ *		previously returned by gpio_request_by_name()
+ * @return Value of open drain mode for GPIO (0 for inactive, 1 for active) or
+ *	   -ve on error
+ */
+int dm_gpio_get_open_drain(struct gpio_desc *desc);
+
+/**
+ * dm_gpio_set_open_drain() - Switch open-drain-mode of a GPIO on or off
+ *
+ * This enables or disables open-drain mode for a GPIO. This method is
+ * optional; if the driver does not support it, nothing happens when the method
+ * is called.
+ *
+ * In open-drain mode, instead of actively driving the output (Push-pull
+ * output), the GPIO's pin is connected to the collector (for a NPN transistor)
+ * or the drain (for a MOSFET) of a transistor, respectively. The pin then
+ * either forms an open circuit or a connection to ground, depending on the
+ * state of the transistor.
+ *
+ * @desc:	GPIO description containing device, offset and flags,
+ *		previously returned by gpio_request_by_name()
+ * @return 0 if OK, -ve on error
+ */
+int dm_gpio_set_open_drain(struct gpio_desc *desc, int value);
+
 /**
  * dm_gpio_set_dir() - Set the direction for a GPIO
  *
diff --git a/test/dm/gpio.c b/test/dm/gpio.c
index 727db186903b5d4d324c8b7f979aee48d57ab1bf..b99452340dfcb5135fc9b9ec6106a9ecdded55a3 100644
--- a/test/dm/gpio.c
+++ b/test/dm/gpio.c
@@ -75,6 +75,13 @@ static int dm_test_gpio(struct unit_test_state *uts)
 	ut_assertok(ops->set_value(dev, offset, 1));
 	ut_asserteq(1, ops->get_value(dev, offset));
 
+	/* Make it an open drain output, and reset it */
+	ut_asserteq(0, sandbox_gpio_get_open_drain(dev, offset));
+	ut_assertok(ops->set_open_drain(dev, offset, 1));
+	ut_asserteq(1, sandbox_gpio_get_open_drain(dev, offset));
+	ut_assertok(ops->set_open_drain(dev, offset, 0));
+	ut_asserteq(0, sandbox_gpio_get_open_drain(dev, offset));
+
 	/* Make it an input */
 	ut_assertok(ops->direction_input(dev, offset));
 	ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));