Browse Source

Merge git://git.denx.de/u-boot-dm

Conflicts:
	drivers/serial/serial-uclass.c

Signed-off-by: Tom Rini <trini@ti.com>
Tom Rini 10 years ago
parent
commit
1739564e75

+ 119 - 0
README

@@ -623,6 +623,120 @@ The following options need to be configured:
 		exists, unlike the similar options in the Linux kernel. Do not
 		exists, unlike the similar options in the Linux kernel. Do not
 		set these options unless they apply!
 		set these options unless they apply!
 
 
+- Driver Model
+		Driver model is a new framework for devices in U-Boot
+		introduced in early 2014. U-Boot is being progressively
+		moved over to this. It offers a consistent device structure,
+		supports grouping devices into classes and has built-in
+		handling of platform data and device tree.
+
+		To enable transition to driver model in a relatively
+		painful fashion, each subsystem can be independently
+		switched between the legacy/ad-hoc approach and the new
+		driver model using the options below. Also, many uclass
+		interfaces include compatibility features which may be
+		removed once the conversion of that subsystem is complete.
+		As a result, the API provided by the subsystem may in fact
+		not change with driver model.
+
+		See doc/driver-model/README.txt for more information.
+
+		CONFIG_DM
+
+		Enable driver model. This brings in the core support,
+		including scanning of platform data on start-up. If
+		CONFIG_OF_CONTROL is enabled, the device tree will be
+		scanned also when available.
+
+		CONFIG_CMD_DM
+
+		Enable driver model test commands. These allow you to print
+		out the driver model tree and the uclasses.
+
+		CONFIG_DM_DEMO
+
+		Enable some demo devices and the 'demo' command. These are
+		really only useful for playing around while trying to
+		understand driver model in sandbox.
+
+		CONFIG_SPL_DM
+
+		Enable driver model in SPL. You will need to provide a
+		suitable malloc() implementation. If you are not using the
+		full malloc() enabled by CONFIG_SYS_SPL_MALLOC_START,
+		consider using CONFIG_SYS_MALLOC_SIMPLE. In that case you
+		must provide CONFIG_SYS_MALLOC_F_LEN to set the size.
+		In most cases driver model will only allocate a few uclasses
+		and devices in SPL, so 1KB should be enable. See
+		CONFIG_SYS_MALLOC_F_LEN for more details on how to enable
+		it.
+
+		CONFIG_DM_SERIAL
+
+		Enable driver model for serial. This replaces
+		drivers/serial/serial.c with the serial uclass, which
+		implements serial_putc() etc. The uclass interface is
+		defined in include/serial.h.
+
+		CONFIG_DM_GPIO
+
+		Enable driver model for GPIO access. The standard GPIO
+		interface (gpio_get_value(), etc.) is then implemented by
+		the GPIO uclass. Drivers provide methods to query the
+		particular GPIOs that they provide. The uclass interface
+		is defined in include/asm-generic/gpio.h.
+
+		CONFIG_DM_SPI
+
+		Enable driver model for SPI. The SPI slave interface
+		(spi_setup_slave(), spi_xfer(), etc.) is then implemented by
+		the SPI uclass. Drivers provide methods to access the SPI
+		buses that they control. The uclass interface is defined in
+		include/spi.h. The existing spi_slave structure is attached
+		as 'parent data' to every slave on each bus. Slaves
+		typically use driver-private data instead of extending the
+		spi_slave structure.
+
+		CONFIG_DM_SPI_FLASH
+
+		Enable driver model for SPI flash. This SPI flash interface
+		(spi_flash_probe(), spi_flash_write(), etc.) is then
+		implemented by the SPI flash uclass. There is one standard
+		SPI flash driver which knows how to probe most chips
+		supported by U-Boot. The uclass interface is defined in
+		include/spi_flash.h, but is currently fully compatible
+		with the old interface to avoid confusion and duplication
+		during the transition parent. SPI and SPI flash must be
+		enabled together (it is not possible to use driver model
+		for one and not the other).
+
+		CONFIG_DM_CROS_EC
+
+		Enable driver model for the Chrome OS EC interface. This
+		allows the cros_ec SPI driver to operate with CONFIG_DM_SPI
+		but otherwise makes few changes. Since cros_ec also supports
+		I2C and LPC (which don't support driver model yet), a full
+		conversion is not yet possible.
+
+
+		** Code size options: The following options are enabled by
+		default except in SPL. Enable them explicitly to get these
+		features in SPL.
+
+		CONFIG_DM_WARN
+
+		Enable the dm_warn() function. This can use up quite a bit
+		of space for its strings.
+
+		CONFIG_DM_STDIO
+
+		Enable registering a serial device with the stdio library.
+
+		CONFIG_DM_DEVICE_REMOVE
+
+		Enable removing of devices.
+
+
 - Linux Kernel Interface:
 - Linux Kernel Interface:
 		CONFIG_CLOCKS_IN_MHZ
 		CONFIG_CLOCKS_IN_MHZ
 
 
@@ -3870,6 +3984,11 @@ Configuration Settings:
 		Pre-relocation malloc() is only supported on ARM and sandbox
 		Pre-relocation malloc() is only supported on ARM and sandbox
 		at present but is fairly easy to enable for other archs.
 		at present but is fairly easy to enable for other archs.
 
 
+- CONFIG_SYS_MALLOC_SIMPLE
+		Provides a simple and small malloc() and calloc() for those
+		boards which do not use the full malloc in SPL (which is
+		enabled with CONFIG_SYS_SPL_MALLOC_START).
+
 - CONFIG_SYS_BOOTM_LEN:
 - CONFIG_SYS_BOOTM_LEN:
 		Normally compressed uImages are limited to an
 		Normally compressed uImages are limited to an
 		uncompressed size of 8 MBytes. If this is not enough,
 		uncompressed size of 8 MBytes. If this is not enough,

+ 14 - 0
arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c

@@ -7,6 +7,7 @@
  */
  */
 
 
 #include <common.h>
 #include <common.h>
+#include <dm.h>
 #include <asm/io.h>
 #include <asm/io.h>
 #include <asm/arch/at91sam9260_matrix.h>
 #include <asm/arch/at91sam9260_matrix.h>
 #include <asm/arch/at91_common.h>
 #include <asm/arch/at91_common.h>
@@ -229,3 +230,16 @@ void at91_sdram_hw_init(void)
 	at91_set_a_periph(AT91_PIO_PORTC, 30, 0);
 	at91_set_a_periph(AT91_PIO_PORTC, 30, 0);
 	at91_set_a_periph(AT91_PIO_PORTC, 31, 0);
 	at91_set_a_periph(AT91_PIO_PORTC, 31, 0);
 }
 }
+
+/* Platform data for the GPIOs */
+static const struct at91_port_platdata at91sam9260_plat[] = {
+	{ ATMEL_BASE_PIOA, "PA" },
+	{ ATMEL_BASE_PIOB, "PB" },
+	{ ATMEL_BASE_PIOC, "PC" },
+};
+
+U_BOOT_DEVICES(at91sam9260_gpios) = {
+	{ "gpio_at91", &at91sam9260_plat[0] },
+	{ "gpio_at91", &at91sam9260_plat[1] },
+	{ "gpio_at91", &at91sam9260_plat[2] },
+};

+ 7 - 0
arch/arm/cpu/u-boot-spl.lds

@@ -34,6 +34,13 @@ SECTIONS
 	. = ALIGN(4);
 	. = ALIGN(4);
 
 
 	. = .;
 	. = .;
+#ifdef CONFIG_SPL_DM
+	.u_boot_list : {
+		KEEP(*(SORT(.u_boot_list_*_driver_*)));
+		KEEP(*(SORT(.u_boot_list_*_uclass_*)));
+	}
+#endif
+	. = ALIGN(4);
 
 
 	__image_copy_end = .;
 	__image_copy_end = .;
 
 

+ 3 - 1
arch/arm/include/asm/arch-at91/at91sam9260.h

@@ -136,9 +136,11 @@
 /*
 /*
  * Other misc defines
  * Other misc defines
  */
  */
+#ifndef CONFIG_DM_GPIO
 #define ATMEL_PIO_PORTS		3		/* these SoCs have 3 PIO */
 #define ATMEL_PIO_PORTS		3		/* these SoCs have 3 PIO */
-#define ATMEL_PMC_UHP		AT91SAM926x_PMC_UHP
 #define ATMEL_BASE_PIO		ATMEL_BASE_PIOA
 #define ATMEL_BASE_PIO		ATMEL_BASE_PIOA
+#endif
+#define ATMEL_PMC_UHP		AT91SAM926x_PMC_UHP
 
 
 /*
 /*
  * SoC specific defines
  * SoC specific defines

+ 15 - 0
arch/arm/include/asm/arch-at91/atmel_serial.h

@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef _ATMEL_SERIAL_H
+#define _ATMEL_SERIAL_H
+
+/* Information about a serial port */
+struct atmel_serial_platdata {
+	uint32_t base_addr;
+};
+
+#endif

+ 6 - 0
arch/arm/include/asm/arch-at91/gpio.h

@@ -253,4 +253,10 @@ static inline unsigned at91_gpio_to_pin(unsigned gpio)
 	return gpio % 32;
 	return gpio % 32;
 }
 }
 
 
+/* Platform data for each GPIO port */
+struct at91_port_platdata {
+	uint32_t base_addr;
+	const char *bank_name;
+};
+
 #endif /* __ASM_ARCH_AT91_GPIO_H */
 #endif /* __ASM_ARCH_AT91_GPIO_H */

+ 1 - 1
arch/arm/lib/crt0.S

@@ -78,7 +78,7 @@ clr_gd:
 	strlo	r0, [r1]		/* clear 32-bit GD word */
 	strlo	r0, [r1]		/* clear 32-bit GD word */
 	addlo	r1, r1, #4		/* move to next */
 	addlo	r1, r1, #4		/* move to next */
 	blo	clr_gd
 	blo	clr_gd
-#if defined(CONFIG_SYS_MALLOC_F_LEN) && !defined(CONFIG_SPL_BUILD)
+#if defined(CONFIG_SYS_MALLOC_F_LEN)
 	sub	sp, sp, #CONFIG_SYS_MALLOC_F_LEN
 	sub	sp, sp, #CONFIG_SYS_MALLOC_F_LEN
 	str	sp, [r9, #GD_MALLOC_BASE]
 	str	sp, [r9, #GD_MALLOC_BASE]
 #endif
 #endif

+ 1 - 1
board/bluewater/snapper9260/MAINTAINERS

@@ -1,5 +1,5 @@
 SNAPPER9260 BOARD
 SNAPPER9260 BOARD
-M:	Ryan Mallon <ryan@bluewatersys.com>
+M:	Simon Glass <sjg@chromium.org>
 S:	Maintained
 S:	Maintained
 F:	board/bluewater/snapper9260/
 F:	board/bluewater/snapper9260/
 F:	include/configs/snapper9260.h
 F:	include/configs/snapper9260.h

+ 16 - 2
board/bluewater/snapper9260/snapper9260.c

@@ -9,12 +9,15 @@
  */
  */
 
 
 #include <common.h>
 #include <common.h>
+#include <dm.h>
 #include <asm/io.h>
 #include <asm/io.h>
+#include <asm/gpio.h>
 #include <asm/arch/at91sam9260_matrix.h>
 #include <asm/arch/at91sam9260_matrix.h>
 #include <asm/arch/at91sam9_smc.h>
 #include <asm/arch/at91sam9_smc.h>
 #include <asm/arch/at91_common.h>
 #include <asm/arch/at91_common.h>
 #include <asm/arch/at91_pmc.h>
 #include <asm/arch/at91_pmc.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/gpio.h>
+#include <asm/arch/atmel_serial.h>
 #include <net.h>
 #include <net.h>
 #include <netdev.h>
 #include <netdev.h>
 #include <i2c.h>
 #include <i2c.h>
@@ -95,10 +98,12 @@ static void nand_hw_init(void)
 	       &smc->cs[3].mode);
 	       &smc->cs[3].mode);
 
 
 	/* Configure RDY/BSY */
 	/* Configure RDY/BSY */
-	at91_set_gpio_input(CONFIG_SYS_NAND_READY_PIN, 1);
+	gpio_request(CONFIG_SYS_NAND_READY_PIN, "nand_rdy");
+	gpio_direction_input(CONFIG_SYS_NAND_READY_PIN);
 
 
 	/* Enable NandFlash */
 	/* Enable NandFlash */
-	at91_set_gpio_output(CONFIG_SYS_NAND_ENABLE_PIN, 1);
+	gpio_request(CONFIG_SYS_NAND_ENABLE_PIN, "nand_ce");
+	gpio_direction_output(CONFIG_SYS_NAND_ENABLE_PIN, 1);
 }
 }
 
 
 int board_init(void)
 int board_init(void)
@@ -140,3 +145,12 @@ int dram_init(void)
 void reset_phy(void)
 void reset_phy(void)
 {
 {
 }
 }
+
+static struct atmel_serial_platdata at91sam9260_serial_plat = {
+	.base_addr = ATMEL_BASE_DBGU,
+};
+
+U_BOOT_DEVICE(at91sam9260_serial) = {
+	.name	= "serial_atmel",
+	.platdata = &at91sam9260_serial_plat,
+};

+ 8 - 0
board/nvidia/common/board.c

@@ -6,6 +6,7 @@
  */
  */
 
 
 #include <common.h>
 #include <common.h>
+#include <dm.h>
 #include <ns16550.h>
 #include <ns16550.h>
 #include <linux/compiler.h>
 #include <linux/compiler.h>
 #include <asm/io.h>
 #include <asm/io.h>
@@ -43,6 +44,13 @@
 
 
 DECLARE_GLOBAL_DATA_PTR;
 DECLARE_GLOBAL_DATA_PTR;
 
 
+#ifdef CONFIG_SPL_BUILD
+/* TODO(sjg@chromium.org): Remove once SPL supports device tree */
+U_BOOT_DEVICE(tegra_gpios) = {
+	"gpio_tegra"
+};
+#endif
+
 const struct tegra_sysinfo sysinfo = {
 const struct tegra_sysinfo sysinfo = {
 	CONFIG_TEGRA_BOARD_STRING
 	CONFIG_TEGRA_BOARD_STRING
 };
 };

+ 3 - 0
common/Makefile

@@ -252,6 +252,9 @@ obj-$(CONFIG_BOUNCE_BUFFER) += bouncebuf.o
 obj-y += console.o
 obj-y += console.o
 obj-$(CONFIG_CROS_EC) += cros_ec.o
 obj-$(CONFIG_CROS_EC) += cros_ec.o
 obj-y += dlmalloc.o
 obj-y += dlmalloc.o
+ifdef CONFIG_SYS_MALLOC_F_LEN
+obj-y += malloc_simple.o
+endif
 obj-y += image.o
 obj-y += image.o
 obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o
 obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o
 obj-$(CONFIG_OF_LIBFDT) += image-fdt.o
 obj-$(CONFIG_OF_LIBFDT) += image-fdt.o

+ 2 - 1
common/board_r.c

@@ -99,7 +99,8 @@ static int initr_trace(void)
 
 
 static int initr_reloc(void)
 static int initr_reloc(void)
 {
 {
-	gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */
+	/* tell others: relocation done */
+	gd->flags |= GD_FLG_RELOC | GD_FLG_FULL_MALLOC_INIT;
 	bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R, "board_init_r");
 	bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R, "board_init_r");
 
 
 	return 0;
 	return 0;

+ 22 - 10
common/cmd_i2c.c

@@ -198,6 +198,19 @@ static uint get_alen(char *arg)
 	return alen;
 	return alen;
 }
 }
 
 
+enum i2c_err_op {
+	I2C_ERR_READ,
+	I2C_ERR_WRITE,
+};
+
+static int i2c_report_err(int ret, enum i2c_err_op op)
+{
+	printf("Error %s the chip: %d\n",
+	       op == I2C_ERR_READ ? "reading" : "writing", ret);
+
+	return CMD_RET_FAILURE;
+}
+
 /**
 /**
  * do_i2c_read() - Handle the "i2c read" command-line command
  * do_i2c_read() - Handle the "i2c read" command-line command
  * @cmdtp:	Command data struct pointer
  * @cmdtp:	Command data struct pointer
@@ -245,7 +258,7 @@ static int do_i2c_read ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
 	memaddr = (u_char *)simple_strtoul(argv[4], NULL, 16);
 	memaddr = (u_char *)simple_strtoul(argv[4], NULL, 16);
 
 
 	if (i2c_read(chip, devaddr, alen, memaddr, length) != 0) {
 	if (i2c_read(chip, devaddr, alen, memaddr, length) != 0) {
-		puts ("Error reading the chip.\n");
+		i2c_report_err(-1, I2C_ERR_READ);
 		return 1;
 		return 1;
 	}
 	}
 	return 0;
 	return 0;
@@ -286,8 +299,7 @@ static int do_i2c_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
 
 
 	while (length-- > 0) {
 	while (length-- > 0) {
 		if (i2c_write(chip, devaddr++, alen, memaddr++, 1) != 0) {
 		if (i2c_write(chip, devaddr++, alen, memaddr++, 1) != 0) {
-			puts("Error writing to the chip.\n");
-			return 1;
+			return i2c_report_err(-1, I2C_ERR_WRITE);
 		}
 		}
 /*
 /*
  * No write delay with FRAM devices.
  * No write delay with FRAM devices.
@@ -370,7 +382,7 @@ static int do_i2c_md ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
 		linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes;
 		linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes;
 
 
 		if (i2c_read(chip, addr, alen, linebuf, linebytes) != 0)
 		if (i2c_read(chip, addr, alen, linebuf, linebytes) != 0)
-			puts ("Error reading the chip.\n");
+			i2c_report_err(-1, I2C_ERR_READ);
 		else {
 		else {
 			printf("%04x:", addr);
 			printf("%04x:", addr);
 			cp = linebuf;
 			cp = linebuf;
@@ -452,7 +464,7 @@ static int do_i2c_mw ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
 
 
 	while (count-- > 0) {
 	while (count-- > 0) {
 		if (i2c_write(chip, addr++, alen, &byte, 1) != 0)
 		if (i2c_write(chip, addr++, alen, &byte, 1) != 0)
-			puts ("Error writing the chip.\n");
+			i2c_report_err(-1, I2C_ERR_WRITE);
 		/*
 		/*
 		 * Wait for the write to complete.  The write can take
 		 * Wait for the write to complete.  The write can take
 		 * up to 10mSec (we allow a little more time).
 		 * up to 10mSec (we allow a little more time).
@@ -528,7 +540,7 @@ static int do_i2c_crc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
 		addr++;
 		addr++;
 	}
 	}
 	if (err > 0)
 	if (err > 0)
-		puts ("Error reading the chip,\n");
+		i2c_report_err(-1, I2C_ERR_READ);
 	else
 	else
 		printf ("%08lx\n", crc);
 		printf ("%08lx\n", crc);
 
 
@@ -601,7 +613,7 @@ mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const arg
 	do {
 	do {
 		printf("%08lx:", addr);
 		printf("%08lx:", addr);
 		if (i2c_read(chip, addr, alen, (uchar *)&data, size) != 0)
 		if (i2c_read(chip, addr, alen, (uchar *)&data, size) != 0)
-			puts ("\nError reading the chip,\n");
+			i2c_report_err(-1, I2C_ERR_READ);
 		else {
 		else {
 			data = cpu_to_be32(data);
 			data = cpu_to_be32(data);
 			if (size == 1)
 			if (size == 1)
@@ -644,7 +656,7 @@ mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const arg
 				 */
 				 */
 				bootretry_reset_cmd_timeout();
 				bootretry_reset_cmd_timeout();
 				if (i2c_write(chip, addr, alen, (uchar *)&data, size) != 0)
 				if (i2c_write(chip, addr, alen, (uchar *)&data, size) != 0)
-					puts ("Error writing the chip.\n");
+					i2c_report_err(-1, I2C_ERR_WRITE);
 #ifdef CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS
 #ifdef CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS
 				udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
 				udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
 #endif
 #endif
@@ -783,7 +795,7 @@ static int do_i2c_loop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
 	 */
 	 */
 	while (1) {
 	while (1) {
 		if (i2c_read(chip, addr, alen, bytes, length) != 0)
 		if (i2c_read(chip, addr, alen, bytes, length) != 0)
-			puts ("Error reading the chip.\n");
+			i2c_report_err(-1, I2C_ERR_READ);
 		udelay(delay);
 		udelay(delay);
 	}
 	}
 
 
@@ -1341,7 +1353,7 @@ int do_edid(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
 
 
 	chip = simple_strtoul(argv[1], NULL, 16);
 	chip = simple_strtoul(argv[1], NULL, 16);
 	if (i2c_read(chip, 0, 1, (uchar *)&edid, sizeof(edid)) != 0) {
 	if (i2c_read(chip, 0, 1, (uchar *)&edid, sizeof(edid)) != 0) {
-		puts("Error reading EDID content.\n");
+		i2c_report_err(-1, I2C_ERR_READ);
 		return 1;
 		return 1;
 	}
 	}
 
 

+ 5 - 14
common/dlmalloc.c

@@ -2184,17 +2184,8 @@ Void_t* mALLOc(bytes) size_t bytes;
   INTERNAL_SIZE_T nb;
   INTERNAL_SIZE_T nb;
 
 
 #ifdef CONFIG_SYS_MALLOC_F_LEN
 #ifdef CONFIG_SYS_MALLOC_F_LEN
-	if (gd && !(gd->flags & GD_FLG_RELOC)) {
-		ulong new_ptr;
-		void *ptr;
-
-		new_ptr = gd->malloc_ptr + bytes;
-		if (new_ptr > gd->malloc_limit)
-			panic("Out of pre-reloc memory");
-		ptr = map_sysmem(gd->malloc_base + gd->malloc_ptr, bytes);
-		gd->malloc_ptr = ALIGN(new_ptr, sizeof(new_ptr));
-		return ptr;
-	}
+	if (gd && !(gd->flags & GD_FLG_FULL_MALLOC_INIT))
+		return malloc_simple(bytes);
 #endif
 #endif
 
 
   /* check if mem_malloc_init() was run */
   /* check if mem_malloc_init() was run */
@@ -2462,7 +2453,7 @@ void fREe(mem) Void_t* mem;
 
 
 #ifdef CONFIG_SYS_MALLOC_F_LEN
 #ifdef CONFIG_SYS_MALLOC_F_LEN
 	/* free() is a no-op - all the memory will be freed on relocation */
 	/* free() is a no-op - all the memory will be freed on relocation */
-	if (!(gd->flags & GD_FLG_RELOC))
+	if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT))
 		return;
 		return;
 #endif
 #endif
 
 
@@ -2618,7 +2609,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
   if (oldmem == NULL) return mALLOc(bytes);
   if (oldmem == NULL) return mALLOc(bytes);
 
 
 #ifdef CONFIG_SYS_MALLOC_F_LEN
 #ifdef CONFIG_SYS_MALLOC_F_LEN
-	if (!(gd->flags & GD_FLG_RELOC)) {
+	if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT)) {
 		/* This is harder to support and should not be needed */
 		/* This is harder to support and should not be needed */
 		panic("pre-reloc realloc() is not supported");
 		panic("pre-reloc realloc() is not supported");
 	}
 	}
@@ -2970,7 +2961,7 @@ Void_t* cALLOc(n, elem_size) size_t n; size_t elem_size;
   else
   else
   {
   {
 #ifdef CONFIG_SYS_MALLOC_F_LEN
 #ifdef CONFIG_SYS_MALLOC_F_LEN
-	if (!(gd->flags & GD_FLG_RELOC)) {
+	if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT)) {
 		MALLOC_ZERO(mem, sz);
 		MALLOC_ZERO(mem, sz);
 		return mem;
 		return mem;
 	}
 	}

+ 39 - 0
common/malloc_simple.c

@@ -0,0 +1,39 @@
+/*
+ * Simple malloc implementation
+ *
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void *malloc_simple(size_t bytes)
+{
+	ulong new_ptr;
+	void *ptr;
+
+	new_ptr = gd->malloc_ptr + bytes;
+	if (new_ptr > gd->malloc_limit)
+		panic("Out of pre-reloc memory");
+	ptr = map_sysmem(gd->malloc_base + gd->malloc_ptr, bytes);
+	gd->malloc_ptr = ALIGN(new_ptr, sizeof(new_ptr));
+	return ptr;
+}
+
+#ifdef CONFIG_SYS_MALLOC_SIMPLE
+void *calloc(size_t nmemb, size_t elem_size)
+{
+	size_t size = nmemb * elem_size;
+	void *ptr;
+
+	ptr = malloc(size);
+	memset(ptr, '\0', size);
+
+	return ptr;
+}
+#endif

+ 15 - 1
common/spl/spl.c

@@ -7,6 +7,7 @@
  * SPDX-License-Identifier:	GPL-2.0+
  * SPDX-License-Identifier:	GPL-2.0+
  */
  */
 #include <common.h>
 #include <common.h>
+#include <dm.h>
 #include <spl.h>
 #include <spl.h>
 #include <asm/u-boot.h>
 #include <asm/u-boot.h>
 #include <nand.h>
 #include <nand.h>
@@ -15,6 +16,7 @@
 #include <i2c.h>
 #include <i2c.h>
 #include <image.h>
 #include <image.h>
 #include <malloc.h>
 #include <malloc.h>
+#include <dm/root.h>
 #include <linux/compiler.h>
 #include <linux/compiler.h>
 
 
 DECLARE_GLOBAL_DATA_PTR;
 DECLARE_GLOBAL_DATA_PTR;
@@ -139,9 +141,16 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
 	u32 boot_device;
 	u32 boot_device;
 	debug(">>spl:board_init_r()\n");
 	debug(">>spl:board_init_r()\n");
 
 
-#ifdef CONFIG_SYS_SPL_MALLOC_START
+#if defined(CONFIG_SYS_SPL_MALLOC_START)
 	mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START,
 	mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START,
 			CONFIG_SYS_SPL_MALLOC_SIZE);
 			CONFIG_SYS_SPL_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
+#elif defined(CONFIG_SYS_MALLOC_F_LEN)
+	gd->malloc_limit = gd->malloc_base + CONFIG_SYS_MALLOC_F_LEN;
+	gd->malloc_ptr = 0;
+#endif
+#ifdef CONFIG_SPL_DM
+	dm_init_and_scan(true);
 #endif
 #endif
 
 
 #ifndef CONFIG_PPC
 #ifndef CONFIG_PPC
@@ -240,6 +249,11 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
 	default:
 	default:
 		debug("Unsupported OS image.. Jumping nevertheless..\n");
 		debug("Unsupported OS image.. Jumping nevertheless..\n");
 	}
 	}
+#if defined(CONFIG_SYS_MALLOC_F_LEN) && !defined(CONFIG_SYS_SPL_MALLOC_SIZE)
+	debug("SPL malloc() used %#lx bytes (%ld KB)\n", gd->malloc_ptr,
+	      gd->malloc_ptr / 1024);
+#endif
+
 	jump_to_image_no_args(&spl_image);
 	jump_to_image_no_args(&spl_image);
 }
 }
 
 

+ 34 - 10
doc/driver-model/README.txt

@@ -750,19 +750,43 @@ device pointers, but this is not currently implemented (the root device
 pointer is saved but not made available through the driver model API).
 pointer is saved but not made available through the driver model API).
 
 
 
 
-Things to punt for later
-------------------------
+SPL Support
+-----------
+
+Driver model can operate in SPL. Its efficient implementation and small code
+size provide for a small overhead which is acceptable for all but the most
+constrained systems.
+
+To enable driver model in SPL, define CONFIG_SPL_DM. You might want to
+consider the following option also. See the main README for more details.
+
+   - CONFIG_SYS_MALLOC_SIMPLE
+   - CONFIG_DM_WARN
+   - CONFIG_DM_DEVICE_REMOVE
+   - CONFIG_DM_STDIO
 
 
-- SPL support - this will have to be present before many drivers can be
-converted, but it seems like we can add it once we are happy with the
-core implementation.
 
 
-That is not to say that no thinking has gone into this - in fact there
-is quite a lot there. However, getting these right is non-trivial and
-there is a high cost associated with going down the wrong path.
+Enabling Driver Model
+---------------------
 
 
-For SPL, it may be possible to fit in a simplified driver model with only
-bind and probe methods, to reduce size.
+Driver model is being brought into U-Boot gradually. As each subsystems gets
+support, a uclass is created and a CONFIG to enable use of driver model for
+that subsystem.
+
+For example CONFIG_DM_SERIAL enables driver model for serial. With that
+defined, the old serial support is not enabled, and your serial driver must
+conform to driver model. With that undefined, the old serial support is
+enabled and driver model is not available for serial. This means that when
+you convert a driver, you must either convert all its boards, or provide for
+the driver to be compiled both with and without driver model (generally this
+is not very hard).
+
+See the main README for full details of the available driver model CONFIG
+options.
+
+
+Things to punt for later
+------------------------
 
 
 Uclasses are statically numbered at compile time. It would be possible to
 Uclasses are statically numbered at compile time. It would be possible to
 change this to dynamic numbering, but then we would require some sort of
 change this to dynamic numbering, but then we would require some sort of

+ 2 - 1
drivers/core/Makefile

@@ -4,5 +4,6 @@
 # SPDX-License-Identifier:	GPL-2.0+
 # SPDX-License-Identifier:	GPL-2.0+
 #
 #
 
 
-obj-y := device.o lists.o root.o uclass.o util.o
+obj-$(CONFIG_DM)	+= device.o lists.o root.o uclass.o util.o
 obj-$(CONFIG_OF_CONTROL) += simple-bus.o
 obj-$(CONFIG_OF_CONTROL) += simple-bus.o
+obj-$(CONFIG_DM_DEVICE_REMOVE)	+= device-remove.o

+ 187 - 0
drivers/core/device-remove.c

@@ -0,0 +1,187 @@
+/*
+ * Device manager
+ *
+ * Copyright (c) 2014 Google, Inc
+ *
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <malloc.h>
+#include <dm/device.h>
+#include <dm/device-internal.h>
+#include <dm/uclass.h>
+#include <dm/uclass-internal.h>
+#include <dm/util.h>
+
+/**
+ * device_chld_unbind() - Unbind all device's children from the device
+ *
+ * On error, the function continues to unbind all children, and reports the
+ * first error.
+ *
+ * @dev:	The device that is to be stripped of its children
+ * @return 0 on success, -ve on error
+ */
+static int device_chld_unbind(struct udevice *dev)
+{
+	struct udevice *pos, *n;
+	int ret, saved_ret = 0;
+
+	assert(dev);
+
+	list_for_each_entry_safe(pos, n, &dev->child_head, sibling_node) {
+		ret = device_unbind(pos);
+		if (ret && !saved_ret)
+			saved_ret = ret;
+	}
+
+	return saved_ret;
+}
+
+/**
+ * device_chld_remove() - Stop all device's children
+ * @dev:	The device whose children are to be removed
+ * @return 0 on success, -ve on error
+ */
+static int device_chld_remove(struct udevice *dev)
+{
+	struct udevice *pos, *n;
+	int ret;
+
+	assert(dev);
+
+	list_for_each_entry_safe(pos, n, &dev->child_head, sibling_node) {
+		ret = device_remove(pos);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+int device_unbind(struct udevice *dev)
+{
+	struct driver *drv;
+	int ret;
+
+	if (!dev)
+		return -EINVAL;
+
+	if (dev->flags & DM_FLAG_ACTIVATED)
+		return -EINVAL;
+
+	drv = dev->driver;
+	assert(drv);
+
+	if (drv->unbind) {
+		ret = drv->unbind(dev);
+		if (ret)
+			return ret;
+	}
+
+	ret = device_chld_unbind(dev);
+	if (ret)
+		return ret;
+
+	ret = uclass_unbind_device(dev);
+	if (ret)
+		return ret;
+
+	if (dev->parent)
+		list_del(&dev->sibling_node);
+	free(dev);
+
+	return 0;
+}
+
+/**
+ * device_free() - Free memory buffers allocated by a device
+ * @dev:	Device that is to be started
+ */
+void device_free(struct udevice *dev)
+{
+	int size;
+
+	if (dev->driver->priv_auto_alloc_size) {
+		free(dev->priv);
+		dev->priv = NULL;
+	}
+	if (dev->flags & DM_FLAG_ALLOC_PDATA) {
+		free(dev->platdata);
+		dev->platdata = NULL;
+	}
+	size = dev->uclass->uc_drv->per_device_auto_alloc_size;
+	if (size) {
+		free(dev->uclass_priv);
+		dev->uclass_priv = NULL;
+	}
+	if (dev->parent) {
+		size = dev->parent->driver->per_child_auto_alloc_size;
+		if (size) {
+			free(dev->parent_priv);
+			dev->parent_priv = NULL;
+		}
+	}
+}
+
+int device_remove(struct udevice *dev)
+{
+	struct driver *drv;
+	int ret;
+
+	if (!dev)
+		return -EINVAL;
+
+	if (!(dev->flags & DM_FLAG_ACTIVATED))
+		return 0;
+
+	drv = dev->driver;
+	assert(drv);
+
+	ret = uclass_pre_remove_device(dev);
+	if (ret)
+		return ret;
+
+	ret = device_chld_remove(dev);
+	if (ret)
+		goto err;
+
+	if (drv->remove) {
+		ret = drv->remove(dev);
+		if (ret)
+			goto err_remove;
+	}
+
+	if (dev->parent && dev->parent->driver->child_post_remove) {
+		ret = dev->parent->driver->child_post_remove(dev);
+		if (ret) {
+			dm_warn("%s: Device '%s' failed child_post_remove()",
+				__func__, dev->name);
+		}
+	}
+
+	device_free(dev);
+
+	dev->seq = -1;
+	dev->flags &= ~DM_FLAG_ACTIVATED;
+
+	return ret;
+
+err_remove:
+	/* We can't put the children back */
+	dm_warn("%s: Device '%s' failed to remove, but children are gone\n",
+		__func__, dev->name);
+err:
+	ret = uclass_post_probe_device(dev);
+	if (ret) {
+		dm_warn("%s: Device '%s' failed to post_probe on error path\n",
+			__func__, dev->name);
+	}
+
+	return ret;
+}

+ 10 - 168
drivers/core/device.c

@@ -24,52 +24,6 @@
 
 
 DECLARE_GLOBAL_DATA_PTR;
 DECLARE_GLOBAL_DATA_PTR;
 
 
-/**
- * device_chld_unbind() - Unbind all device's children from the device
- *
- * On error, the function continues to unbind all children, and reports the
- * first error.
- *
- * @dev:	The device that is to be stripped of its children
- * @return 0 on success, -ve on error
- */
-static int device_chld_unbind(struct udevice *dev)
-{
-	struct udevice *pos, *n;
-	int ret, saved_ret = 0;
-
-	assert(dev);
-
-	list_for_each_entry_safe(pos, n, &dev->child_head, sibling_node) {
-		ret = device_unbind(pos);
-		if (ret && !saved_ret)
-			saved_ret = ret;
-	}
-
-	return saved_ret;
-}
-
-/**
- * device_chld_remove() - Stop all device's children
- * @dev:	The device whose children are to be removed
- * @return 0 on success, -ve on error
- */
-static int device_chld_remove(struct udevice *dev)
-{
-	struct udevice *pos, *n;
-	int ret;
-
-	assert(dev);
-
-	list_for_each_entry_safe(pos, n, &dev->child_head, sibling_node) {
-		ret = device_remove(pos);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
 int device_bind(struct udevice *parent, struct driver *drv, const char *name,
 int device_bind(struct udevice *parent, struct driver *drv, const char *name,
 		void *platdata, int of_offset, struct udevice **devp)
 		void *platdata, int of_offset, struct udevice **devp)
 {
 {
@@ -167,71 +121,6 @@ int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
 			   -1, devp);
 			   -1, devp);
 }
 }
 
 
-int device_unbind(struct udevice *dev)
-{
-	struct driver *drv;
-	int ret;
-
-	if (!dev)
-		return -EINVAL;
-
-	if (dev->flags & DM_FLAG_ACTIVATED)
-		return -EINVAL;
-
-	drv = dev->driver;
-	assert(drv);
-
-	if (drv->unbind) {
-		ret = drv->unbind(dev);
-		if (ret)
-			return ret;
-	}
-
-	ret = device_chld_unbind(dev);
-	if (ret)
-		return ret;
-
-	ret = uclass_unbind_device(dev);
-	if (ret)
-		return ret;
-
-	if (dev->parent)
-		list_del(&dev->sibling_node);
-	free(dev);
-
-	return 0;
-}
-
-/**
- * device_free() - Free memory buffers allocated by a device
- * @dev:	Device that is to be started
- */
-static void device_free(struct udevice *dev)
-{
-	int size;
-
-	if (dev->driver->priv_auto_alloc_size) {
-		free(dev->priv);
-		dev->priv = NULL;
-	}
-	if (dev->flags & DM_FLAG_ALLOC_PDATA) {
-		free(dev->platdata);
-		dev->platdata = NULL;
-	}
-	size = dev->uclass->uc_drv->per_device_auto_alloc_size;
-	if (size) {
-		free(dev->uclass_priv);
-		dev->uclass_priv = NULL;
-	}
-	if (dev->parent) {
-		size = dev->parent->driver->per_child_auto_alloc_size;
-		if (size) {
-			free(dev->parent_priv);
-			dev->parent_priv = NULL;
-		}
-	}
-}
-
 int device_probe_child(struct udevice *dev, void *parent_priv)
 int device_probe_child(struct udevice *dev, void *parent_priv)
 {
 {
 	struct driver *drv;
 	struct driver *drv;
@@ -342,63 +231,6 @@ int device_probe(struct udevice *dev)
 	return device_probe_child(dev, NULL);
 	return device_probe_child(dev, NULL);
 }
 }
 
 
-int device_remove(struct udevice *dev)
-{
-	struct driver *drv;
-	int ret;
-
-	if (!dev)
-		return -EINVAL;
-
-	if (!(dev->flags & DM_FLAG_ACTIVATED))
-		return 0;
-
-	drv = dev->driver;
-	assert(drv);
-
-	ret = uclass_pre_remove_device(dev);
-	if (ret)
-		return ret;
-
-	ret = device_chld_remove(dev);
-	if (ret)
-		goto err;
-
-	if (drv->remove) {
-		ret = drv->remove(dev);
-		if (ret)
-			goto err_remove;
-	}
-
-	if (dev->parent && dev->parent->driver->child_post_remove) {
-		ret = dev->parent->driver->child_post_remove(dev);
-		if (ret) {
-			dm_warn("%s: Device '%s' failed child_post_remove()",
-				__func__, dev->name);
-		}
-	}
-
-	device_free(dev);
-
-	dev->seq = -1;
-	dev->flags &= ~DM_FLAG_ACTIVATED;
-
-	return ret;
-
-err_remove:
-	/* We can't put the children back */
-	dm_warn("%s: Device '%s' failed to remove, but children are gone\n",
-		__func__, dev->name);
-err:
-	ret = uclass_post_probe_device(dev);
-	if (ret) {
-		dm_warn("%s: Device '%s' failed to post_probe on error path\n",
-			__func__, dev->name);
-	}
-
-	return ret;
-}
-
 void *dev_get_platdata(struct udevice *dev)
 void *dev_get_platdata(struct udevice *dev)
 {
 {
 	if (!dev) {
 	if (!dev) {
@@ -548,3 +380,13 @@ int device_find_next_child(struct udevice **devp)
 
 
 	return 0;
 	return 0;
 }
 }
+
+struct udevice *dev_get_parent(struct udevice *child)
+{
+	return child->parent;
+}
+
+ulong dev_get_of_data(struct udevice *dev)
+{
+	return dev->of_id->data;
+}

+ 36 - 14
drivers/core/lists.c

@@ -25,9 +25,6 @@ struct driver *lists_driver_lookup_name(const char *name)
 	const int n_ents = ll_entry_count(struct driver, driver);
 	const int n_ents = ll_entry_count(struct driver, driver);
 	struct driver *entry;
 	struct driver *entry;
 
 
-	if (!drv || !n_ents)
-		return NULL;
-
 	for (entry = drv; entry != drv + n_ents; entry++) {
 	for (entry = drv; entry != drv + n_ents; entry++) {
 		if (!strcmp(name, entry->name))
 		if (!strcmp(name, entry->name))
 			return entry;
 			return entry;
@@ -44,9 +41,6 @@ struct uclass_driver *lists_uclass_lookup(enum uclass_id id)
 	const int n_ents = ll_entry_count(struct uclass_driver, uclass);
 	const int n_ents = ll_entry_count(struct uclass_driver, uclass);
 	struct uclass_driver *entry;
 	struct uclass_driver *entry;
 
 
-	if ((id == UCLASS_INVALID) || !uclass)
-		return NULL;
-
 	for (entry = uclass; entry != uclass + n_ents; entry++) {
 	for (entry = uclass; entry != uclass + n_ents; entry++) {
 		if (entry->id == id)
 		if (entry->id == id)
 			return entry;
 			return entry;
@@ -77,34 +71,60 @@ int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only)
 	return result;
 	return result;
 }
 }
 
 
+int device_bind_driver(struct udevice *parent, const char *drv_name,
+		       const char *dev_name, struct udevice **devp)
+{
+	struct driver *drv;
+	int ret;
+
+	drv = lists_driver_lookup_name(drv_name);
+	if (!drv) {
+		printf("Cannot find driver '%s'\n", drv_name);
+		return -ENOENT;
+	}
+	ret = device_bind(parent, drv, dev_name, NULL, -1, devp);
+	if (ret) {
+		printf("Cannot create device named '%s' (err=%d)\n",
+		       dev_name, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 #ifdef CONFIG_OF_CONTROL
 #ifdef CONFIG_OF_CONTROL
 /**
 /**
  * driver_check_compatible() - Check if a driver is compatible with this node
  * driver_check_compatible() - Check if a driver is compatible with this node
  *
  *
  * @param blob:		Device tree pointer
  * @param blob:		Device tree pointer
  * @param offset:	Offset of node in device tree
  * @param offset:	Offset of node in device tree
- * @param of_matchL	List of compatible strings to match
+ * @param of_match:	List of compatible strings to match
+ * @param of_idp:	Returns the match that was found
  * @return 0 if there is a match, -ENOENT if no match, -ENODEV if the node
  * @return 0 if there is a match, -ENOENT if no match, -ENODEV if the node
  * does not have a compatible string, other error <0 if there is a device
  * does not have a compatible string, other error <0 if there is a device
  * tree error
  * tree error
  */
  */
 static int driver_check_compatible(const void *blob, int offset,
 static int driver_check_compatible(const void *blob, int offset,
-				   const struct udevice_id *of_match)
+				   const struct udevice_id *of_match,
+				   const struct udevice_id **of_idp)
 {
 {
 	int ret;
 	int ret;
 
 
+	*of_idp = NULL;
 	if (!of_match)
 	if (!of_match)
 		return -ENOENT;
 		return -ENOENT;
 
 
 	while (of_match->compatible) {
 	while (of_match->compatible) {
 		ret = fdt_node_check_compatible(blob, offset,
 		ret = fdt_node_check_compatible(blob, offset,
 						of_match->compatible);
 						of_match->compatible);
-		if (!ret)
+		if (!ret) {
+			*of_idp = of_match;
 			return 0;
 			return 0;
-		else if (ret == -FDT_ERR_NOTFOUND)
+		} else if (ret == -FDT_ERR_NOTFOUND) {
 			return -ENODEV;
 			return -ENODEV;
-		else if (ret < 0)
+		} else if (ret < 0) {
 			return -EINVAL;
 			return -EINVAL;
+		}
 		of_match++;
 		of_match++;
 	}
 	}
 
 
@@ -116,6 +136,7 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
 {
 {
 	struct driver *driver = ll_entry_start(struct driver, driver);
 	struct driver *driver = ll_entry_start(struct driver, driver);
 	const int n_ents = ll_entry_count(struct driver, driver);
 	const int n_ents = ll_entry_count(struct driver, driver);
+	const struct udevice_id *id;
 	struct driver *entry;
 	struct driver *entry;
 	struct udevice *dev;
 	struct udevice *dev;
 	bool found = false;
 	bool found = false;
@@ -127,7 +148,8 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
 	if (devp)
 	if (devp)
 		*devp = NULL;
 		*devp = NULL;
 	for (entry = driver; entry != driver + n_ents; entry++) {
 	for (entry = driver; entry != driver + n_ents; entry++) {
-		ret = driver_check_compatible(blob, offset, entry->of_match);
+		ret = driver_check_compatible(blob, offset, entry->of_match,
+					      &id);
 		name = fdt_get_name(blob, offset, NULL);
 		name = fdt_get_name(blob, offset, NULL);
 		if (ret == -ENOENT) {
 		if (ret == -ENOENT) {
 			continue;
 			continue;
@@ -136,8 +158,7 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
 			break;
 			break;
 		} else if (ret) {
 		} else if (ret) {
 			dm_warn("Device tree error at offset %d\n", offset);
 			dm_warn("Device tree error at offset %d\n", offset);
-			if (!result || ret != -ENOENT)
-				result = ret;
+			result = ret;
 			break;
 			break;
 		}
 		}
 
 
@@ -147,6 +168,7 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
 			dm_warn("Error binding driver '%s'\n", entry->name);
 			dm_warn("Error binding driver '%s'\n", entry->name);
 			return ret;
 			return ret;
 		} else {
 		} else {
+			dev->of_id = id;
 			found = true;
 			found = true;
 			if (devp)
 			if (devp)
 				*devp = dev;
 				*devp = dev;

+ 1 - 3
drivers/core/root.c

@@ -73,10 +73,8 @@ int dm_scan_platdata(bool pre_reloc_only)
 		dm_warn("Some drivers were not found\n");
 		dm_warn("Some drivers were not found\n");
 		ret = 0;
 		ret = 0;
 	}
 	}
-	if (ret)
-		return ret;
 
 
-	return 0;
+	return ret;
 }
 }
 
 
 #ifdef CONFIG_OF_CONTROL
 #ifdef CONFIG_OF_CONTROL

+ 187 - 54
drivers/gpio/at91_gpio.c

@@ -10,11 +10,14 @@
 
 
 #include <config.h>
 #include <config.h>
 #include <common.h>
 #include <common.h>
+#include <dm.h>
 #include <asm/io.h>
 #include <asm/io.h>
 #include <linux/sizes.h>
 #include <linux/sizes.h>
+#include <asm/gpio.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/at91_pio.h>
 #include <asm/arch/at91_pio.h>
-#include <asm/arch/gpio.h>
+
+#define GPIO_PER_BANK	32
 
 
 static struct at91_port *at91_pio_get_port(unsigned port)
 static struct at91_port *at91_pio_get_port(unsigned port)
 {
 {
@@ -39,19 +42,25 @@ static struct at91_port *at91_pio_get_port(unsigned port)
 	}
 	}
 }
 }
 
 
+static void at91_set_port_pullup(struct at91_port *at91_port, unsigned offset,
+				 int use_pullup)
+{
+	u32 mask;
+
+	mask = 1 << offset;
+	if (use_pullup)
+		writel(mask, &at91_port->puer);
+	else
+		writel(mask, &at91_port->pudr);
+	writel(mask, &at91_port->per);
+}
+
 int at91_set_pio_pullup(unsigned port, unsigned pin, int use_pullup)
 int at91_set_pio_pullup(unsigned port, unsigned pin, int use_pullup)
 {
 {
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	struct at91_port *at91_port = at91_pio_get_port(port);
-	u32 mask;
 
 
-	if (at91_port && (pin < 32)) {
-		mask = 1 << pin;
-		if (use_pullup)
-			writel(1 << pin, &at91_port->puer);
-		else
-			writel(1 << pin, &at91_port->pudr);
-		writel(mask, &at91_port->per);
-	}
+	if (at91_port && (pin < GPIO_PER_BANK))
+		at91_set_port_pullup(at91_port, pin, use_pullup);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -64,7 +73,7 @@ int at91_set_pio_periph(unsigned port, unsigned pin, int use_pullup)
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	u32 mask;
 	u32 mask;
 
 
-	if (at91_port && (pin < 32)) {
+	if (at91_port && (pin < GPIO_PER_BANK)) {
 		mask = 1 << pin;
 		mask = 1 << pin;
 		writel(mask, &at91_port->idr);
 		writel(mask, &at91_port->idr);
 		at91_set_pio_pullup(port, pin, use_pullup);
 		at91_set_pio_pullup(port, pin, use_pullup);
@@ -82,7 +91,7 @@ int at91_set_a_periph(unsigned port, unsigned pin, int use_pullup)
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	u32 mask;
 	u32 mask;
 
 
-	if (at91_port && (pin < 32)) {
+	if (at91_port && (pin < GPIO_PER_BANK)) {
 		mask = 1 << pin;
 		mask = 1 << pin;
 		writel(mask, &at91_port->idr);
 		writel(mask, &at91_port->idr);
 		at91_set_pio_pullup(port, pin, use_pullup);
 		at91_set_pio_pullup(port, pin, use_pullup);
@@ -108,7 +117,7 @@ int at91_set_b_periph(unsigned port, unsigned pin, int use_pullup)
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	u32 mask;
 	u32 mask;
 
 
-	if (at91_port && (pin < 32)) {
+	if (at91_port && (pin < GPIO_PER_BANK)) {
 		mask = 1 << pin;
 		mask = 1 << pin;
 		writel(mask, &at91_port->idr);
 		writel(mask, &at91_port->idr);
 		at91_set_pio_pullup(port, pin, use_pullup);
 		at91_set_pio_pullup(port, pin, use_pullup);
@@ -135,7 +144,7 @@ int at91_set_c_periph(unsigned port, unsigned pin, int use_pullup)
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	u32 mask;
 	u32 mask;
 
 
-	if (at91_port && (pin < 32)) {
+	if (at91_port && (pin < GPIO_PER_BANK)) {
 		mask = 1 << pin;
 		mask = 1 << pin;
 		writel(mask, &at91_port->idr);
 		writel(mask, &at91_port->idr);
 		at91_set_pio_pullup(port, pin, use_pullup);
 		at91_set_pio_pullup(port, pin, use_pullup);
@@ -157,7 +166,7 @@ int at91_set_d_periph(unsigned port, unsigned pin, int use_pullup)
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	u32 mask;
 	u32 mask;
 
 
-	if (at91_port && (pin < 32)) {
+	if (at91_port && (pin < GPIO_PER_BANK)) {
 		mask = 1 << pin;
 		mask = 1 << pin;
 		writel(mask, &at91_port->idr);
 		writel(mask, &at91_port->idr);
 		at91_set_pio_pullup(port, pin, use_pullup);
 		at91_set_pio_pullup(port, pin, use_pullup);
@@ -172,6 +181,29 @@ int at91_set_d_periph(unsigned port, unsigned pin, int use_pullup)
 }
 }
 #endif
 #endif
 
 
+#ifdef CONFIG_DM_GPIO
+static bool at91_get_port_output(struct at91_port *at91_port, int offset)
+{
+	u32 mask, val;
+
+	mask = 1 << offset;
+	val = readl(&at91_port->osr);
+	return val & mask;
+}
+#endif
+
+static void at91_set_port_input(struct at91_port *at91_port, int offset,
+				int use_pullup)
+{
+	u32 mask;
+
+	mask = 1 << offset;
+	writel(mask, &at91_port->idr);
+	at91_set_port_pullup(at91_port, offset, use_pullup);
+	writel(mask, &at91_port->odr);
+	writel(mask, &at91_port->per);
+}
+
 /*
 /*
  * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and
  * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and
  * configure it for an input.
  * configure it for an input.
@@ -179,19 +211,29 @@ int at91_set_d_periph(unsigned port, unsigned pin, int use_pullup)
 int at91_set_pio_input(unsigned port, u32 pin, int use_pullup)
 int at91_set_pio_input(unsigned port, u32 pin, int use_pullup)
 {
 {
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	struct at91_port *at91_port = at91_pio_get_port(port);
-	u32 mask;
 
 
-	if (at91_port && (pin < 32)) {
-		mask = 1 << pin;
-		writel(mask, &at91_port->idr);
-		at91_set_pio_pullup(port, pin, use_pullup);
-		writel(mask, &at91_port->odr);
-		writel(mask, &at91_port->per);
-	}
+	if (at91_port && (pin < GPIO_PER_BANK))
+		at91_set_port_input(at91_port, pin, use_pullup);
 
 
 	return 0;
 	return 0;
 }
 }
 
 
+static void at91_set_port_output(struct at91_port *at91_port, int offset,
+				 int value)
+{
+	u32 mask;
+
+	mask = 1 << offset;
+	writel(mask, &at91_port->idr);
+	writel(mask, &at91_port->pudr);
+	if (value)
+		writel(mask, &at91_port->sodr);
+	else
+		writel(mask, &at91_port->codr);
+	writel(mask, &at91_port->oer);
+	writel(mask, &at91_port->per);
+}
+
 /*
 /*
  * mux the pin to the gpio controller (instead of "A" or "B" peripheral),
  * mux the pin to the gpio controller (instead of "A" or "B" peripheral),
  * and configure it for an output.
  * and configure it for an output.
@@ -199,19 +241,9 @@ int at91_set_pio_input(unsigned port, u32 pin, int use_pullup)
 int at91_set_pio_output(unsigned port, u32 pin, int value)
 int at91_set_pio_output(unsigned port, u32 pin, int value)
 {
 {
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	struct at91_port *at91_port = at91_pio_get_port(port);
-	u32 mask;
 
 
-	if (at91_port && (port < ATMEL_PIO_PORTS) && (pin < 32)) {
-		mask = 1 << pin;
-		writel(mask, &at91_port->idr);
-		writel(mask, &at91_port->pudr);
-		if (value)
-			writel(mask, &at91_port->sodr);
-		else
-			writel(mask, &at91_port->codr);
-		writel(mask, &at91_port->oer);
-		writel(mask, &at91_port->per);
-	}
+	if (at91_port && (pin < GPIO_PER_BANK))
+		at91_set_port_output(at91_port, pin, value);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -224,7 +256,7 @@ int at91_set_pio_deglitch(unsigned port, unsigned pin, int is_on)
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	u32 mask;
 	u32 mask;
 
 
-	if (at91_port && (pin < 32)) {
+	if (at91_port && (pin < GPIO_PER_BANK)) {
 		mask = 1 << pin;
 		mask = 1 << pin;
 		if (is_on) {
 		if (is_on) {
 #if defined(CPU_HAS_PIO3)
 #if defined(CPU_HAS_PIO3)
@@ -248,7 +280,7 @@ int at91_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div)
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	u32 mask;
 	u32 mask;
 
 
-	if (at91_port && (pin < 32)) {
+	if (at91_port && (pin < GPIO_PER_BANK)) {
 		mask = 1 << pin;
 		mask = 1 << pin;
 		if (is_on) {
 		if (is_on) {
 			writel(mask, &at91_port->ifscer);
 			writel(mask, &at91_port->ifscer);
@@ -271,7 +303,7 @@ int at91_set_pio_pulldown(unsigned port, unsigned pin, int is_on)
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	u32 mask;
 	u32 mask;
 
 
-	if (at91_port && (pin < 32)) {
+	if (at91_port && (pin < GPIO_PER_BANK)) {
 		mask = 1 << pin;
 		mask = 1 << pin;
 		writel(mask, &at91_port->pudr);
 		writel(mask, &at91_port->pudr);
 		if (is_on)
 		if (is_on)
@@ -291,7 +323,7 @@ int at91_set_pio_disable_schmitt_trig(unsigned port, unsigned pin)
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	u32 mask;
 	u32 mask;
 
 
-	if (at91_port && (pin < 32)) {
+	if (at91_port && (pin < GPIO_PER_BANK)) {
 		mask = 1 << pin;
 		mask = 1 << pin;
 		writel(readl(&at91_port->schmitt) | mask,
 		writel(readl(&at91_port->schmitt) | mask,
 		       &at91_port->schmitt);
 		       &at91_port->schmitt);
@@ -310,7 +342,7 @@ int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on)
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	u32 mask;
 	u32 mask;
 
 
-	if (at91_port && (pin < 32)) {
+	if (at91_port && (pin < GPIO_PER_BANK)) {
 		mask = 1 << pin;
 		mask = 1 << pin;
 		if (is_on)
 		if (is_on)
 			writel(mask, &at91_port->mder);
 			writel(mask, &at91_port->mder);
@@ -321,41 +353,54 @@ int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on)
 	return 0;
 	return 0;
 }
 }
 
 
+static void at91_set_port_value(struct at91_port *at91_port, int offset,
+				int value)
+{
+	u32 mask;
+
+	mask = 1 << offset;
+	if (value)
+		writel(mask, &at91_port->sodr);
+	else
+		writel(mask, &at91_port->codr);
+}
+
 /*
 /*
  * assuming the pin is muxed as a gpio output, set its value.
  * assuming the pin is muxed as a gpio output, set its value.
  */
  */
 int at91_set_pio_value(unsigned port, unsigned pin, int value)
 int at91_set_pio_value(unsigned port, unsigned pin, int value)
 {
 {
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	struct at91_port *at91_port = at91_pio_get_port(port);
-	u32 mask;
 
 
-	if (at91_port && (pin < 32)) {
-		mask = 1 << pin;
-		if (value)
-			writel(mask, &at91_port->sodr);
-		else
-			writel(mask, &at91_port->codr);
-	}
+	if (at91_port && (pin < GPIO_PER_BANK))
+		at91_set_port_value(at91_port, pin, value);
 
 
 	return 0;
 	return 0;
 }
 }
 
 
+static int at91_get_port_value(struct at91_port *at91_port, int offset)
+{
+	u32 pdsr = 0, mask;
+
+	mask = 1 << offset;
+	pdsr = readl(&at91_port->pdsr) & mask;
+
+	return pdsr != 0;
+}
 /*
 /*
  * read the pin's value (works even if it's not muxed as a gpio).
  * read the pin's value (works even if it's not muxed as a gpio).
  */
  */
 int at91_get_pio_value(unsigned port, unsigned pin)
 int at91_get_pio_value(unsigned port, unsigned pin)
 {
 {
 	struct at91_port *at91_port = at91_pio_get_port(port);
 	struct at91_port *at91_port = at91_pio_get_port(port);
-	u32 pdsr = 0, mask;
 
 
-	if (at91_port && (pin < 32)) {
-		mask = 1 << pin;
-		pdsr = readl(&at91_port->pdsr) & mask;
-	}
+	if (at91_port && (pin < GPIO_PER_BANK))
+		return at91_get_port_value(at91_port, pin);
 
 
-	return pdsr != 0;
+	return 0;
 }
 }
 
 
+#ifndef CONFIG_DM_GPIO
 /* Common GPIO API */
 /* Common GPIO API */
 
 
 int gpio_request(unsigned gpio, const char *label)
 int gpio_request(unsigned gpio, const char *label)
@@ -395,3 +440,91 @@ int gpio_set_value(unsigned gpio, int value)
 
 
 	return 0;
 	return 0;
 }
 }
+#endif
+
+#ifdef CONFIG_DM_GPIO
+
+struct at91_port_priv {
+	struct at91_port *regs;
+};
+
+/* set GPIO pin 'gpio' as an input */
+static int at91_gpio_direction_input(struct udevice *dev, unsigned offset)
+{
+	struct at91_port_priv *port = dev_get_platdata(dev);
+
+	at91_set_port_input(port->regs, offset, 0);
+
+	return 0;
+}
+
+/* set GPIO pin 'gpio' as an output, with polarity 'value' */
+static int at91_gpio_direction_output(struct udevice *dev, unsigned offset,
+				       int value)
+{
+	struct at91_port_priv *port = dev_get_platdata(dev);
+
+	at91_set_port_output(port->regs, offset, value);
+
+	return 0;
+}
+
+/* read GPIO IN value of pin 'gpio' */
+static int at91_gpio_get_value(struct udevice *dev, unsigned offset)
+{
+	struct at91_port_priv *port = dev_get_platdata(dev);
+
+	return at91_get_port_value(port->regs, offset);
+}
+
+/* write GPIO OUT value to pin 'gpio' */
+static int at91_gpio_set_value(struct udevice *dev, unsigned offset,
+			       int value)
+{
+	struct at91_port_priv *port = dev_get_platdata(dev);
+
+	at91_set_port_value(port->regs, offset, value);
+
+	return 0;
+}
+
+static int at91_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+	struct at91_port_priv *port = dev_get_platdata(dev);
+
+	/* GPIOF_FUNC is not implemented yet */
+	if (at91_get_port_output(port->regs, offset))
+		return GPIOF_OUTPUT;
+	else
+		return GPIOF_INPUT;
+}
+
+static const struct dm_gpio_ops gpio_at91_ops = {
+	.direction_input	= at91_gpio_direction_input,
+	.direction_output	= at91_gpio_direction_output,
+	.get_value		= at91_gpio_get_value,
+	.set_value		= at91_gpio_set_value,
+	.get_function		= at91_gpio_get_function,
+};
+
+static int at91_gpio_probe(struct udevice *dev)
+{
+	struct at91_port_priv *port = dev_get_priv(dev);
+	struct at91_port_platdata *plat = dev_get_platdata(dev);
+	struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+
+	uc_priv->bank_name = plat->bank_name;
+	uc_priv->gpio_count = GPIO_PER_BANK;
+	port->regs = (struct at91_port *)plat->base_addr;
+
+	return 0;
+}
+
+U_BOOT_DRIVER(gpio_at91) = {
+	.name	= "gpio_at91",
+	.id	= UCLASS_GPIO,
+	.ops	= &gpio_at91_ops,
+	.probe	= at91_gpio_probe,
+	.priv_auto_alloc_size = sizeof(struct at91_port_priv),
+};
+#endif

+ 1 - 0
drivers/misc/cros_ec.c

@@ -701,6 +701,7 @@ static int cros_ec_check_version(struct cros_ec_dev *dev)
 
 
 	/* Try sending a version 3 packet */
 	/* Try sending a version 3 packet */
 	dev->protocol_version = 3;
 	dev->protocol_version = 3;
+	req.in_data = 0;
 	if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req),
 	if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req),
 			     (uint8_t **)&resp, sizeof(*resp)) > 0) {
 			     (uint8_t **)&resp, sizeof(*resp)) > 0) {
 		return 0;
 		return 0;

+ 2 - 2
drivers/mtd/spi/sandbox.c

@@ -602,14 +602,14 @@ static int sandbox_sf_bind_bus_cs(struct sandbox_state *state, int busnum,
 		       spec, ret);
 		       spec, ret);
 		return ret;
 		return ret;
 	}
 	}
-	ret = device_find_child_by_seq(bus, cs, true, &slave);
+	ret = spi_find_chip_select(bus, cs, &slave);
 	if (!ret) {
 	if (!ret) {
 		printf("Chip select %d already exists for spec '%s'\n", cs,
 		printf("Chip select %d already exists for spec '%s'\n", cs,
 		       spec);
 		       spec);
 		return -EEXIST;
 		return -EEXIST;
 	}
 	}
 
 
-	ret = spi_bind_device(bus, cs, "spi_flash_std", spec, &slave);
+	ret = device_bind_driver(bus, "spi_flash_std", spec, &slave);
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 

+ 107 - 9
drivers/serial/atmel_usart.c

@@ -7,11 +7,16 @@
  * SPDX-License-Identifier:	GPL-2.0+
  * SPDX-License-Identifier:	GPL-2.0+
  */
  */
 #include <common.h>
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
 #include <watchdog.h>
 #include <watchdog.h>
 #include <serial.h>
 #include <serial.h>
 #include <linux/compiler.h>
 #include <linux/compiler.h>
 
 
 #include <asm/io.h>
 #include <asm/io.h>
+#ifdef CONFIG_DM_SERIAL
+#include <asm/arch/atmel_serial.h>
+#endif
 #include <asm/arch/clk.h>
 #include <asm/arch/clk.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/hardware.h>
 
 
@@ -19,9 +24,9 @@
 
 
 DECLARE_GLOBAL_DATA_PTR;
 DECLARE_GLOBAL_DATA_PTR;
 
 
-static void atmel_serial_setbrg(void)
+static void atmel_serial_setbrg_internal(atmel_usart3_t *usart, int id,
+					 int baudrate)
 {
 {
-	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
 	unsigned long divisor;
 	unsigned long divisor;
 	unsigned long usart_hz;
 	unsigned long usart_hz;
 
 
@@ -30,15 +35,13 @@ static void atmel_serial_setbrg(void)
 	 * Baud Rate = --------------
 	 * Baud Rate = --------------
 	 *                16 * CD
 	 *                16 * CD
 	 */
 	 */
-	usart_hz = get_usart_clk_rate(CONFIG_USART_ID);
-	divisor = (usart_hz / 16 + gd->baudrate / 2) / gd->baudrate;
+	usart_hz = get_usart_clk_rate(id);
+	divisor = (usart_hz / 16 + baudrate / 2) / baudrate;
 	writel(USART3_BF(CD, divisor), &usart->brgr);
 	writel(USART3_BF(CD, divisor), &usart->brgr);
 }
 }
 
 
-static int atmel_serial_init(void)
+static void atmel_serial_init_internal(atmel_usart3_t *usart)
 {
 {
-	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
-
 	/*
 	/*
 	 * Just in case: drain transmitter register
 	 * Just in case: drain transmitter register
 	 * 1000us is enough for baudrate >= 9600
 	 * 1000us is enough for baudrate >= 9600
@@ -47,9 +50,10 @@ static int atmel_serial_init(void)
 		__udelay(1000);
 		__udelay(1000);
 
 
 	writel(USART3_BIT(RSTRX) | USART3_BIT(RSTTX), &usart->cr);
 	writel(USART3_BIT(RSTRX) | USART3_BIT(RSTTX), &usart->cr);
+}
 
 
-	serial_setbrg();
-
+static void atmel_serial_activate(atmel_usart3_t *usart)
+{
 	writel((USART3_BF(USART_MODE, USART3_USART_MODE_NORMAL)
 	writel((USART3_BF(USART_MODE, USART3_USART_MODE_NORMAL)
 			   | USART3_BF(USCLKS, USART3_USCLKS_MCK)
 			   | USART3_BF(USCLKS, USART3_USCLKS_MCK)
 			   | USART3_BF(CHRL, USART3_CHRL_8)
 			   | USART3_BF(CHRL, USART3_CHRL_8)
@@ -59,6 +63,22 @@ static int atmel_serial_init(void)
 	writel(USART3_BIT(RXEN) | USART3_BIT(TXEN), &usart->cr);
 	writel(USART3_BIT(RXEN) | USART3_BIT(TXEN), &usart->cr);
 	/* 100us is enough for the new settings to be settled */
 	/* 100us is enough for the new settings to be settled */
 	__udelay(100);
 	__udelay(100);
+}
+
+#ifndef CONFIG_DM_SERIAL
+static void atmel_serial_setbrg(void)
+{
+	atmel_serial_setbrg_internal((atmel_usart3_t *)CONFIG_USART_BASE,
+				     CONFIG_USART_ID, gd->baudrate);
+}
+
+static int atmel_serial_init(void)
+{
+	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
+
+	atmel_serial_init_internal(usart);
+	serial_setbrg();
+	atmel_serial_activate(usart);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -109,3 +129,81 @@ __weak struct serial_device *default_serial_console(void)
 {
 {
 	return &atmel_serial_drv;
 	return &atmel_serial_drv;
 }
 }
+#endif
+
+#ifdef CONFIG_DM_SERIAL
+
+struct atmel_serial_priv {
+	atmel_usart3_t *usart;
+};
+
+int atmel_serial_setbrg(struct udevice *dev, int baudrate)
+{
+	struct atmel_serial_priv *priv = dev_get_priv(dev);
+
+	atmel_serial_setbrg_internal(priv->usart, 0 /* ignored */, baudrate);
+	atmel_serial_activate(priv->usart);
+
+	return 0;
+}
+
+static int atmel_serial_getc(struct udevice *dev)
+{
+	struct atmel_serial_priv *priv = dev_get_priv(dev);
+
+	if (!(readl(&priv->usart->csr) & USART3_BIT(RXRDY)))
+		return -EAGAIN;
+
+	return readl(&priv->usart->rhr);
+}
+
+static int atmel_serial_putc(struct udevice *dev, const char ch)
+{
+	struct atmel_serial_priv *priv = dev_get_priv(dev);
+
+	if (!(readl(&priv->usart->csr) & USART3_BIT(TXRDY)))
+		return -EAGAIN;
+
+	writel(ch, &priv->usart->thr);
+
+	return 0;
+}
+
+static int atmel_serial_pending(struct udevice *dev, bool input)
+{
+	struct atmel_serial_priv *priv = dev_get_priv(dev);
+	uint32_t csr = readl(&priv->usart->csr);
+
+	if (input)
+		return csr & USART3_BIT(RXRDY) ? 1 : 0;
+	else
+		return csr & USART3_BIT(TXEMPTY) ? 0 : 1;
+}
+
+static const struct dm_serial_ops atmel_serial_ops = {
+	.putc = atmel_serial_putc,
+	.pending = atmel_serial_pending,
+	.getc = atmel_serial_getc,
+	.setbrg = atmel_serial_setbrg,
+};
+
+static int atmel_serial_probe(struct udevice *dev)
+{
+	struct atmel_serial_platdata *plat = dev->platdata;
+	struct atmel_serial_priv *priv = dev_get_priv(dev);
+
+	priv->usart = (atmel_usart3_t *)plat->base_addr;
+	atmel_serial_init_internal(priv->usart);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(serial_atmel) = {
+	.name	= "serial_atmel",
+	.id	= UCLASS_SERIAL,
+	.probe = atmel_serial_probe,
+	.ops	= &atmel_serial_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+	.priv_auto_alloc_size	= sizeof(struct atmel_serial_priv),
+};
+#endif

+ 74 - 3
drivers/serial/serial-uclass.c

@@ -6,6 +6,7 @@
 
 
 #include <common.h>
 #include <common.h>
 #include <dm.h>
 #include <dm.h>
+#include <environment.h>
 #include <errno.h>
 #include <errno.h>
 #include <fdtdec.h>
 #include <fdtdec.h>
 #include <os.h>
 #include <os.h>
@@ -19,6 +20,11 @@
 
 
 DECLARE_GLOBAL_DATA_PTR;
 DECLARE_GLOBAL_DATA_PTR;
 
 
+/*
+ * Table with supported baudrates (defined in config_xyz.h)
+ */
+static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE;
+
 #ifndef CONFIG_SYS_MALLOC_F_LEN
 #ifndef CONFIG_SYS_MALLOC_F_LEN
 #error "Serial is required before relocation - define CONFIG_SYS_MALLOC_F_LEN to make this work"
 #error "Serial is required before relocation - define CONFIG_SYS_MALLOC_F_LEN to make this work"
 #endif
 #endif
@@ -160,10 +166,12 @@ void serial_stdio_init(void)
 {
 {
 }
 }
 
 
+#ifdef CONFIG_DM_STDIO
 static void serial_stub_putc(struct stdio_dev *sdev, const char ch)
 static void serial_stub_putc(struct stdio_dev *sdev, const char ch)
 {
 {
 	_serial_putc(sdev->priv, ch);
 	_serial_putc(sdev->priv, ch);
 }
 }
+#endif
 
 
 void serial_stub_puts(struct stdio_dev *sdev, const char *str)
 void serial_stub_puts(struct stdio_dev *sdev, const char *str)
 {
 {
@@ -180,11 +188,74 @@ int serial_stub_tstc(struct stdio_dev *sdev)
 	return _serial_tstc(sdev->priv);
 	return _serial_tstc(sdev->priv);
 }
 }
 
 
+/**
+ * on_baudrate() - Update the actual baudrate when the env var changes
+ *
+ * This will check for a valid baudrate and only apply it if valid.
+ */
+static int on_baudrate(const char *name, const char *value, enum env_op op,
+	int flags)
+{
+	int i;
+	int baudrate;
+
+	switch (op) {
+	case env_op_create:
+	case env_op_overwrite:
+		/*
+		 * Switch to new baudrate if new baudrate is supported
+		 */
+		baudrate = simple_strtoul(value, NULL, 10);
+
+		/* Not actually changing */
+		if (gd->baudrate == baudrate)
+			return 0;
+
+		for (i = 0; i < ARRAY_SIZE(baudrate_table); ++i) {
+			if (baudrate == baudrate_table[i])
+				break;
+		}
+		if (i == ARRAY_SIZE(baudrate_table)) {
+			if ((flags & H_FORCE) == 0)
+				printf("## Baudrate %d bps not supported\n",
+				       baudrate);
+			return 1;
+		}
+		if ((flags & H_INTERACTIVE) != 0) {
+			printf("## Switch baudrate to %d bps and press ENTER ...\n",
+			       baudrate);
+			udelay(50000);
+		}
+
+		gd->baudrate = baudrate;
+
+		serial_setbrg();
+
+		udelay(50000);
+
+		if ((flags & H_INTERACTIVE) != 0)
+			while (1) {
+				if (getc() == '\r')
+					break;
+			}
+
+		return 0;
+	case env_op_delete:
+		printf("## Baudrate may not be deleted\n");
+		return 1;
+	default:
+		return 0;
+	}
+}
+U_BOOT_ENV_CALLBACK(baudrate, on_baudrate);
+
 static int serial_post_probe(struct udevice *dev)
 static int serial_post_probe(struct udevice *dev)
 {
 {
-	struct stdio_dev sdev;
 	struct dm_serial_ops *ops = serial_get_ops(dev);
 	struct dm_serial_ops *ops = serial_get_ops(dev);
+#ifdef CONFIG_DM_STDIO
 	struct serial_dev_priv *upriv = dev->uclass_priv;
 	struct serial_dev_priv *upriv = dev->uclass_priv;
+	struct stdio_dev sdev;
+#endif
 	int ret;
 	int ret;
 
 
 	/* Set the baud rate */
 	/* Set the baud rate */
@@ -194,9 +265,9 @@ static int serial_post_probe(struct udevice *dev)
 			return ret;
 			return ret;
 	}
 	}
 
 
+#ifdef CONFIG_DM_STDIO
 	if (!(gd->flags & GD_FLG_RELOC))
 	if (!(gd->flags & GD_FLG_RELOC))
 		return 0;
 		return 0;
-
 	memset(&sdev, '\0', sizeof(sdev));
 	memset(&sdev, '\0', sizeof(sdev));
 
 
 	strncpy(sdev.name, dev->name, sizeof(sdev.name));
 	strncpy(sdev.name, dev->name, sizeof(sdev.name));
@@ -207,7 +278,7 @@ static int serial_post_probe(struct udevice *dev)
 	sdev.getc = serial_stub_getc;
 	sdev.getc = serial_stub_getc;
 	sdev.tstc = serial_stub_tstc;
 	sdev.tstc = serial_stub_tstc;
 	stdio_register_dev(&sdev, &upriv->sdev);
 	stdio_register_dev(&sdev, &upriv->sdev);
-
+#endif
 	return 0;
 	return 0;
 }
 }
 
 

+ 16 - 0
drivers/serial/serial_tegra.c

@@ -9,6 +9,7 @@
 #include <ns16550.h>
 #include <ns16550.h>
 #include <serial.h>
 #include <serial.h>
 
 
+#ifdef CONFIG_OF_CONTROL
 static const struct udevice_id tegra_serial_ids[] = {
 static const struct udevice_id tegra_serial_ids[] = {
 	{ .compatible = "nvidia,tegra20-uart" },
 	{ .compatible = "nvidia,tegra20-uart" },
 	{ }
 	{ }
@@ -26,13 +27,28 @@ static int tegra_serial_ofdata_to_platdata(struct udevice *dev)
 
 
 	return 0;
 	return 0;
 }
 }
+#else
+struct ns16550_platdata tegra_serial = {
+	.base = CONFIG_SYS_NS16550_COM1,
+	.reg_shift = 2,
+	.clock = V_NS16550_CLK,
+};
+
+U_BOOT_DEVICE(ns16550_serial) = {
+	"serial_tegra20", &tegra_serial
+};
+#endif
+
 U_BOOT_DRIVER(serial_ns16550) = {
 U_BOOT_DRIVER(serial_ns16550) = {
 	.name	= "serial_tegra20",
 	.name	= "serial_tegra20",
 	.id	= UCLASS_SERIAL,
 	.id	= UCLASS_SERIAL,
+#ifdef CONFIG_OF_CONTROL
 	.of_match = tegra_serial_ids,
 	.of_match = tegra_serial_ids,
 	.ofdata_to_platdata = tegra_serial_ofdata_to_platdata,
 	.ofdata_to_platdata = tegra_serial_ofdata_to_platdata,
 	.platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
 	.platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
+#endif
 	.priv_auto_alloc_size = sizeof(struct NS16550),
 	.priv_auto_alloc_size = sizeof(struct NS16550),
 	.probe = ns16550_serial_probe,
 	.probe = ns16550_serial_probe,
 	.ops	= &ns16550_serial_ops,
 	.ops	= &ns16550_serial_ops,
+	.flags	= DM_FLAG_PRE_RELOC,
 };
 };

+ 2 - 32
drivers/spi/spi-uclass.c

@@ -115,16 +115,7 @@ int spi_chip_select(struct udevice *dev)
 	return slave ? slave->cs : -ENOENT;
 	return slave ? slave->cs : -ENOENT;
 }
 }
 
 
-/**
- * spi_find_chip_select() - Find the slave attached to chip select
- *
- * @bus:	SPI bus to search
- * @cs:		Chip select to look for
- * @devp:	Returns the slave device if found
- * @return 0 if found, -ENODEV on error
- */
-static int spi_find_chip_select(struct udevice *bus, int cs,
-				struct udevice **devp)
+int spi_find_chip_select(struct udevice *bus, int cs, struct udevice **devp)
 {
 {
 	struct udevice *dev;
 	struct udevice *dev;
 
 
@@ -197,27 +188,6 @@ int spi_cs_info(struct udevice *bus, uint cs, struct spi_cs_info *info)
 	return -ENODEV;
 	return -ENODEV;
 }
 }
 
 
-int spi_bind_device(struct udevice *bus, int cs, const char *drv_name,
-		    const char *dev_name, struct udevice **devp)
-{
-	struct driver *drv;
-	int ret;
-
-	drv = lists_driver_lookup_name(drv_name);
-	if (!drv) {
-		printf("Cannot find driver '%s'\n", drv_name);
-		return -ENOENT;
-	}
-	ret = device_bind(bus, drv, dev_name, NULL, -1, devp);
-	if (ret) {
-		printf("Cannot create device named '%s' (err=%d)\n",
-		       dev_name, ret);
-		return ret;
-	}
-
-	return 0;
-}
-
 int spi_find_bus_and_cs(int busnum, int cs, struct udevice **busp,
 int spi_find_bus_and_cs(int busnum, int cs, struct udevice **busp,
 			struct udevice **devp)
 			struct udevice **devp)
 {
 {
@@ -264,7 +234,7 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
 	if (ret == -ENODEV && drv_name) {
 	if (ret == -ENODEV && drv_name) {
 		debug("%s: Binding new device '%s', busnum=%d, cs=%d, driver=%s\n",
 		debug("%s: Binding new device '%s', busnum=%d, cs=%d, driver=%s\n",
 		      __func__, dev_name, busnum, cs, drv_name);
 		      __func__, dev_name, busnum, cs, drv_name);
-		ret = spi_bind_device(bus, cs, drv_name, dev_name, &dev);
+		ret = device_bind_driver(bus, drv_name, dev_name, &dev);
 		if (ret)
 		if (ret)
 			return ret;
 			return ret;
 		created = true;
 		created = true;

+ 1 - 0
include/asm-generic/global_data.h

@@ -108,5 +108,6 @@ typedef struct global_data {
 #define GD_FLG_DISABLE_CONSOLE	0x00040	/* Disable console (in & out)	   */
 #define GD_FLG_DISABLE_CONSOLE	0x00040	/* Disable console (in & out)	   */
 #define GD_FLG_ENV_READY	0x00080	/* Env. imported into hash table   */
 #define GD_FLG_ENV_READY	0x00080	/* Env. imported into hash table   */
 #define GD_FLG_SERIAL_READY	0x00100	/* Pre-reloc serial console ready  */
 #define GD_FLG_SERIAL_READY	0x00100	/* Pre-reloc serial console ready  */
+#define GD_FLG_FULL_MALLOC_INIT	0x00200	/* Full malloc() is ready	   */
 
 
 #endif /* __ASM_GENERIC_GBL_DATA_H */
 #endif /* __ASM_GENERIC_GBL_DATA_H */

+ 6 - 0
include/config_defaults.h

@@ -20,4 +20,10 @@
 #define CONFIG_ZLIB 1
 #define CONFIG_ZLIB 1
 #define CONFIG_PARTITIONS 1
 #define CONFIG_PARTITIONS 1
 
 
+#ifndef CONFIG_SPL_BUILD
+#define CONFIG_DM_WARN
+#define CONFIG_DM_DEVICE_REMOVE
+#define CONFIG_DM_STDIO
+#endif
+
 #endif
 #endif

+ 10 - 2
include/configs/snapper9260.h

@@ -15,11 +15,17 @@
 #include <asm/hardware.h>
 #include <asm/hardware.h>
 #include <linux/sizes.h>
 #include <linux/sizes.h>
 
 
-#define CONFIG_SYS_TEXT_BASE		0x20000000
+#define CONFIG_SYS_TEXT_BASE		0x21f00000
 
 
 /* ARM asynchronous clock */
 /* ARM asynchronous clock */
 #define CONFIG_SYS_AT91_MAIN_CLOCK	18432000 /* External Crystal, in Hz */
 #define CONFIG_SYS_AT91_MAIN_CLOCK	18432000 /* External Crystal, in Hz */
 #define CONFIG_SYS_AT91_SLOW_CLOCK	32768
 #define CONFIG_SYS_AT91_SLOW_CLOCK	32768
+#define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_DM
+#define CONFIG_CMD_DM
+#define CONFIG_DM_GPIO
+#define CONFIG_DM_SERIAL
+#define CONFIG_SYS_MALLOC_F_LEN		(1 << 10)
 
 
 /* CPU */
 /* CPU */
 #define CONFIG_ARCH_CPU_INIT
 #define CONFIG_ARCH_CPU_INIT
@@ -84,8 +90,10 @@
 
 
 /* UARTs/Serial console */
 /* UARTs/Serial console */
 #define CONFIG_ATMEL_USART
 #define CONFIG_ATMEL_USART
+#ifndef CONFIG_DM_SERIAL
 #define CONFIG_USART_BASE		ATMEL_BASE_DBGU
 #define CONFIG_USART_BASE		ATMEL_BASE_DBGU
 #define CONFIG_USART_ID			ATMEL_ID_SYS
 #define CONFIG_USART_ID			ATMEL_ID_SYS
+#endif
 #define CONFIG_BAUDRATE			115200
 #define CONFIG_BAUDRATE			115200
 #define CONFIG_SYS_PROMPT		"Snapper> "
 #define CONFIG_SYS_PROMPT		"Snapper> "
 
 
@@ -159,7 +167,7 @@
 #define CONFIG_CMD_DHCP
 #define CONFIG_CMD_DHCP
 #define CONFIG_CMD_FAT
 #define CONFIG_CMD_FAT
 #define CONFIG_CMD_I2C
 #define CONFIG_CMD_I2C
-#undef CONFIG_CMD_GPIO
+#define CONFIG_CMD_GPIO
 #define CONFIG_CMD_USB
 #define CONFIG_CMD_USB
 #define CONFIG_CMD_MII
 #define CONFIG_CMD_MII
 #define CONFIG_CMD_NAND
 #define CONFIG_CMD_NAND

+ 2 - 0
include/configs/tegra-common.h

@@ -118,7 +118,9 @@
 #define CONFIG_SYS_MEMTEST_START	(NV_PA_SDRC_CS0 + 0x600000)
 #define CONFIG_SYS_MEMTEST_START	(NV_PA_SDRC_CS0 + 0x600000)
 #define CONFIG_SYS_MEMTEST_END		(CONFIG_SYS_MEMTEST_START + 0x100000)
 #define CONFIG_SYS_MEMTEST_END		(CONFIG_SYS_MEMTEST_START + 0x100000)
 
 
+#ifndef CONFIG_SPL_BUILD
 #define CONFIG_USE_ARCH_MEMCPY
 #define CONFIG_USE_ARCH_MEMCPY
+#endif
 
 
 /*-----------------------------------------------------------------------
 /*-----------------------------------------------------------------------
  * Physical Memory Map
  * Physical Memory Map

+ 10 - 0
include/dm/device-internal.h

@@ -87,7 +87,11 @@ int device_probe_child(struct udevice *dev, void *parent_priv);
  * @dev: Pointer to device to remove
  * @dev: Pointer to device to remove
  * @return 0 if OK, -ve on error (an error here is normally a very bad thing)
  * @return 0 if OK, -ve on error (an error here is normally a very bad thing)
  */
  */
+#ifdef CONFIG_DM_DEVICE_REMOVE
 int device_remove(struct udevice *dev);
 int device_remove(struct udevice *dev);
+#else
+static inline int device_remove(struct udevice *dev) { return 0; }
+#endif
 
 
 /**
 /**
  * device_unbind() - Unbind a device, destroying it
  * device_unbind() - Unbind a device, destroying it
@@ -99,6 +103,12 @@ int device_remove(struct udevice *dev);
  */
  */
 int device_unbind(struct udevice *dev);
 int device_unbind(struct udevice *dev);
 
 
+#ifdef CONFIG_DM_DEVICE_REMOVE
+void device_free(struct udevice *dev);
+#else
+static inline void device_free(struct udevice *dev) {}
+#endif
+
 /* Cast away any volatile pointer */
 /* Cast away any volatile pointer */
 #define DM_ROOT_NON_CONST		(((gd_t *)gd)->dm_root)
 #define DM_ROOT_NON_CONST		(((gd_t *)gd)->dm_root)
 #define DM_UCLASS_ROOT_NON_CONST	(((gd_t *)gd)->uclass_root)
 #define DM_UCLASS_ROOT_NON_CONST	(((gd_t *)gd)->uclass_root)

+ 19 - 0
include/dm/device.h

@@ -47,6 +47,7 @@ struct driver_info;
  * @name: Name of device, typically the FDT node name
  * @name: Name of device, typically the FDT node name
  * @platdata: Configuration data for this device
  * @platdata: Configuration data for this device
  * @of_offset: Device tree node offset for this device (- for none)
  * @of_offset: Device tree node offset for this device (- for none)
+ * @of_id: Pointer to the udevice_id structure which created the device
  * @parent: Parent of this device, or NULL for the top level device
  * @parent: Parent of this device, or NULL for the top level device
  * @priv: Private data for this device
  * @priv: Private data for this device
  * @uclass: Pointer to uclass for this device
  * @uclass: Pointer to uclass for this device
@@ -65,6 +66,7 @@ struct udevice {
 	const char *name;
 	const char *name;
 	void *platdata;
 	void *platdata;
 	int of_offset;
 	int of_offset;
+	const struct udevice_id *of_id;
 	struct udevice *parent;
 	struct udevice *parent;
 	void *priv;
 	void *priv;
 	struct uclass *uclass;
 	struct uclass *uclass;
@@ -205,6 +207,23 @@ void *dev_get_parentdata(struct udevice *dev);
  */
  */
 void *dev_get_priv(struct udevice *dev);
 void *dev_get_priv(struct udevice *dev);
 
 
+/**
+ * struct dev_get_parent() - Get the parent of a device
+ *
+ * @child:	Child to check
+ * @return parent of child, or NULL if this is the root device
+ */
+struct udevice *dev_get_parent(struct udevice *child);
+
+/**
+ * dev_get_of_data() - get the device tree data used to bind a device
+ *
+ * When a device is bound using a device tree node, it matches a
+ * particular compatible string as in struct udevice_id. This function
+ * returns the associated data value for that compatible string
+ */
+ulong dev_get_of_data(struct udevice *dev);
+
 /**
 /**
  * device_get_child() - Get the child of a device by index
  * device_get_child() - Get the child of a device by index
  *
  *

+ 13 - 0
include/dm/lists.h

@@ -60,4 +60,17 @@ int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only);
 int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
 int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
 		   struct udevice **devp);
 		   struct udevice **devp);
 
 
+/**
+ * device_bind_driver() - bind a device to a driver
+ *
+ * This binds a new device to a driver.
+ *
+ * @parent:	Parent device
+ * @drv_name:	Name of driver to attach to this parent
+ * @dev_name:	Name of the new device thus created
+ * @devp:	Returns the newly bound device
+ */
+int device_bind_driver(struct udevice *parent, const char *drv_name,
+		       const char *dev_name, struct udevice **devp);
+
 #endif
 #endif

+ 6 - 0
include/dm/util.h

@@ -7,7 +7,13 @@
 #ifndef __DM_UTIL_H
 #ifndef __DM_UTIL_H
 #define __DM_UTIL_H
 #define __DM_UTIL_H
 
 
+#ifdef CONFIG_DM_WARN
 void dm_warn(const char *fmt, ...);
 void dm_warn(const char *fmt, ...);
+#else
+static inline void dm_warn(const char *fmt, ...)
+{
+}
+#endif
 
 
 #ifdef DEBUG
 #ifdef DEBUG
 void dm_dbg(const char *fmt, ...);
 void dm_dbg(const char *fmt, ...);

+ 37 - 23
include/malloc.h

@@ -872,33 +872,46 @@ extern Void_t*     sbrk();
 
 
 #else
 #else
 
 
-#ifdef USE_DL_PREFIX
-#define cALLOc		dlcalloc
-#define fREe		dlfree
-#define mALLOc		dlmalloc
-#define mEMALIGn	dlmemalign
-#define rEALLOc		dlrealloc
-#define vALLOc		dlvalloc
-#define pvALLOc		dlpvalloc
-#define mALLINFo	dlmallinfo
-#define mALLOPt		dlmallopt
-#else /* USE_DL_PREFIX */
-#define cALLOc		calloc
-#define fREe		free
-#define mALLOc		malloc
-#define mEMALIGn	memalign
-#define rEALLOc		realloc
-#define vALLOc		valloc
-#define pvALLOc		pvalloc
-#define mALLINFo	mallinfo
-#define mALLOPt		mallopt
-#endif /* USE_DL_PREFIX */
+#ifdef CONFIG_SYS_MALLOC_SIMPLE
+#define malloc malloc_simple
+#define realloc realloc_simple
+#define memalign memalign_simple
+static inline void free(void *ptr) {}
+void *calloc(size_t nmemb, size_t size);
+void *memalign_simple(size_t alignment, size_t bytes);
+void *realloc_simple(void *ptr, size_t size);
+#else
+
+# ifdef USE_DL_PREFIX
+# define cALLOc		dlcalloc
+# define fREe		dlfree
+# define mALLOc		dlmalloc
+# define mEMALIGn	dlmemalign
+# define rEALLOc		dlrealloc
+# define vALLOc		dlvalloc
+# define pvALLOc		dlpvalloc
+# define mALLINFo	dlmallinfo
+# define mALLOPt		dlmallopt
+# else /* USE_DL_PREFIX */
+# define cALLOc		calloc
+# define fREe		free
+# define mALLOc		malloc
+# define mEMALIGn	memalign
+# define rEALLOc		realloc
+# define vALLOc		valloc
+# define pvALLOc		pvalloc
+# define mALLINFo	mallinfo
+# define mALLOPt		mallopt
+# endif /* USE_DL_PREFIX */
 
 
 #endif
 #endif
 
 
 /* Public routines */
 /* Public routines */
 
 
-#if __STD_C
+/* Simple versions which can be used when space is tight */
+void *malloc_simple(size_t size);
+
+# if __STD_C
 
 
 Void_t* mALLOc(size_t);
 Void_t* mALLOc(size_t);
 void    fREe(Void_t*);
 void    fREe(Void_t*);
@@ -913,7 +926,7 @@ size_t  malloc_usable_size(Void_t*);
 void    malloc_stats(void);
 void    malloc_stats(void);
 int     mALLOPt(int, int);
 int     mALLOPt(int, int);
 struct mallinfo mALLINFo(void);
 struct mallinfo mALLINFo(void);
-#else
+# else
 Void_t* mALLOc();
 Void_t* mALLOc();
 void    fREe();
 void    fREe();
 Void_t* rEALLOc();
 Void_t* rEALLOc();
@@ -927,6 +940,7 @@ size_t  malloc_usable_size();
 void    malloc_stats();
 void    malloc_stats();
 int     mALLOPt();
 int     mALLOPt();
 struct mallinfo mALLINFo();
 struct mallinfo mALLINFo();
+# endif
 #endif
 #endif
 
 
 /*
 /*

+ 5 - 9
include/spi.h

@@ -534,18 +534,14 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
 int spi_chip_select(struct udevice *slave);
 int spi_chip_select(struct udevice *slave);
 
 
 /**
 /**
- * spi_bind_device() - bind a device to a bus's chip select
- *
- * This binds a new device to an given chip select (which must be unused).
+ * spi_find_chip_select() - Find the slave attached to chip select
  *
  *
  * @bus:	SPI bus to search
  * @bus:	SPI bus to search
- * @cs:		Chip select to attach to
- * @drv_name:	Name of driver to attach to this chip select
- * @dev_name:	Name of the new device thus created
- * @devp:	Returns the newly bound device
+ * @cs:		Chip select to look for
+ * @devp:	Returns the slave device if found
+ * @return 0 if found, -ENODEV on error
  */
  */
-int spi_bind_device(struct udevice *bus, int cs, const char *drv_name,
-		    const char *dev_name, struct udevice **devp);
+int spi_find_chip_select(struct udevice *bus, int cs, struct udevice **devp);
 
 
 /**
 /**
  * spi_ofdata_to_platdata() - decode standard SPI platform data
  * spi_ofdata_to_platdata() - decode standard SPI platform data

+ 3 - 3
lib/fdtdec.c

@@ -357,9 +357,9 @@ int fdtdec_get_alias_seq(const void *blob, const char *base, int offset,
 		slash = strrchr(prop, '/');
 		slash = strrchr(prop, '/');
 		if (strcmp(slash + 1, find_name))
 		if (strcmp(slash + 1, find_name))
 			continue;
 			continue;
-		for (p = name; *p; p++) {
-			if (isdigit(*p)) {
-				*seqp = simple_strtoul(p, NULL, 10);
+		for (p = name + strlen(name) - 1; p > name; p--) {
+			if (!isdigit(*p)) {
+				*seqp = simple_strtoul(p + 1, NULL, 10);
 				debug("Found seq %d\n", *seqp);
 				debug("Found seq %d\n", *seqp);
 				return 0;
 				return 0;
 			}
 			}

+ 1 - 0
scripts/Makefile.spl

@@ -66,6 +66,7 @@ libs-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/
 libs-$(CONFIG_SPL_FRAMEWORK) += common/spl/
 libs-$(CONFIG_SPL_FRAMEWORK) += common/spl/
 libs-$(CONFIG_SPL_LIBCOMMON_SUPPORT) += common/
 libs-$(CONFIG_SPL_LIBCOMMON_SUPPORT) += common/
 libs-$(CONFIG_SPL_LIBDISK_SUPPORT) += disk/
 libs-$(CONFIG_SPL_LIBDISK_SUPPORT) += disk/
+libs-$(CONFIG_SPL_DM) += drivers/core/
 libs-$(CONFIG_SPL_I2C_SUPPORT) += drivers/i2c/
 libs-$(CONFIG_SPL_I2C_SUPPORT) += drivers/i2c/
 libs-$(CONFIG_SPL_GPIO_SUPPORT) += drivers/gpio/
 libs-$(CONFIG_SPL_GPIO_SUPPORT) += drivers/gpio/
 libs-$(CONFIG_SPL_MMC_SUPPORT) += drivers/mmc/
 libs-$(CONFIG_SPL_MMC_SUPPORT) += drivers/mmc/