瀏覽代碼

Merge branch 'master' of git://git.denx.de/u-boot-mpc85xx

Tom Rini 9 年之前
父節點
當前提交
cc749523ae
共有 53 個文件被更改,包括 478 次插入107 次删除
  1. 1 1
      arch/powerpc/cpu/mpc512x/fixed_sdram.c
  2. 1 1
      arch/powerpc/cpu/mpc8260/cpu_init.c
  3. 4 4
      arch/powerpc/cpu/mpc8260/ether_fcc.c
  4. 1 1
      arch/powerpc/cpu/mpc83xx/cpu_init.c
  5. 1 1
      arch/powerpc/cpu/mpc83xx/speed.c
  6. 1 1
      arch/powerpc/cpu/mpc85xx/ether_fcc.c
  7. 2 2
      arch/powerpc/cpu/mpc8xx/fec.c
  8. 1 1
      arch/powerpc/cpu/ppc4xx/reginfo.c
  9. 2 2
      arch/powerpc/cpu/ppc4xx/sdram.c
  10. 2 0
      arch/powerpc/include/asm/arch-mpc85xx/gpio.h
  11. 2 0
      arch/powerpc/include/asm/immap_85xx.h
  12. 20 0
      arch/sandbox/include/asm/gpio.h
  13. 3 3
      board/freescale/b4860qds/Makefile
  14. 3 5
      board/freescale/b4860qds/ddr.c
  15. 1 0
      board/freescale/b4860qds/spl.c
  16. 6 10
      board/freescale/bsc9131rdb/Makefile
  17. 3 6
      board/freescale/bsc9132qds/Makefile
  18. 3 3
      board/freescale/c29xpcie/Makefile
  19. 1 0
      board/freescale/c29xpcie/spl.c
  20. 4 8
      board/freescale/p1010rdb/Makefile
  21. 1 0
      board/freescale/p1010rdb/spl.c
  22. 5 7
      board/freescale/p1022ds/Makefile
  23. 1 0
      board/freescale/p1022ds/spl.c
  24. 7 10
      board/freescale/p1_p2_rdb_pc/Makefile
  25. 1 0
      board/freescale/p1_p2_rdb_pc/spl.c
  26. 1 1
      board/freescale/p2041rdb/Makefile
  27. 1 1
      board/freescale/t102xqds/Makefile
  28. 2 3
      board/freescale/t102xqds/ddr.c
  29. 1 0
      board/freescale/t102xqds/spl.c
  30. 1 1
      board/freescale/t102xrdb/Makefile
  31. 2 2
      board/freescale/t102xrdb/ddr.c
  32. 1 0
      board/freescale/t102xrdb/spl.c
  33. 2 5
      board/freescale/t104xrdb/ddr.c
  34. 1 0
      board/freescale/t104xrdb/spl.c
  35. 2 4
      board/freescale/t208xqds/Makefile
  36. 2 3
      board/freescale/t208xqds/ddr.c
  37. 1 0
      board/freescale/t208xqds/spl.c
  38. 2 4
      board/freescale/t208xrdb/Makefile
  39. 3 3
      board/freescale/t208xrdb/ddr.c
  40. 1 0
      board/freescale/t208xrdb/spl.c
  41. 3 3
      board/freescale/t4qds/Makefile
  42. 3 4
      board/freescale/t4qds/ddr.c
  43. 1 0
      board/freescale/t4qds/spl.c
  44. 5 4
      board/freescale/t4rdb/Makefile
  45. 2 3
      board/freescale/t4rdb/ddr.c
  46. 1 0
      board/freescale/t4rdb/spl.c
  47. 26 0
      drivers/gpio/Kconfig
  48. 1 0
      drivers/gpio/Makefile
  49. 32 0
      drivers/gpio/gpio-uclass.c
  50. 228 0
      drivers/gpio/mpc85xx_gpio.c
  51. 35 0
      drivers/gpio/sandbox.c
  52. 34 0
      include/asm-generic/gpio.h
  53. 7 0
      test/dm/gpio.c

+ 1 - 1
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 */

+ 1 - 1
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;

+ 4 - 4
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

+ 1 - 1
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;

+ 1 - 1
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;
 	}

+ 1 - 1
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);

+ 2 - 2
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);
 }
 

+ 1 - 1
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;

+ 2 - 2
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

+ 2 - 0
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

+ 2 - 0
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 {

+ 20 - 0
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)
  *

+ 3 - 3
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

+ 3 - 5
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;
 }
 

+ 1 - 0
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();

+ 6 - 10
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

+ 3 - 6
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

+ 3 - 3
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

+ 1 - 0
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,

+ 4 - 8
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

+ 1 - 0
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();

+ 5 - 7
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

+ 1 - 0
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

+ 7 - 10
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

+ 1 - 0
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();

+ 1 - 1
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

+ 1 - 1
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

+ 2 - 3
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();

+ 1 - 0
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,

+ 1 - 1
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

+ 2 - 2
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();

+ 1 - 0
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,

+ 2 - 5
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();

+ 1 - 0
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);

+ 2 - 4
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
 

+ 2 - 3
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;
 }

+ 1 - 0
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,

+ 2 - 4
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
 

+ 3 - 3
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;
 }

+ 1 - 0
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,

+ 3 - 3
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

+ 3 - 4
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;
 }

+ 1 - 0
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,

+ 5 - 4
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

+ 2 - 3
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;
 }

+ 1 - 0
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,

+ 26 - 0
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

+ 1 - 0
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

+ 32 - 0
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;

+ 228 - 0
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),
+};

+ 35 - 0
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,
 };

+ 34 - 0
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
  *

+ 7 - 0
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)));