Merge git://git.denx.de/u-boot-dm
authorTom Rini <trini@ti.com>
Mon, 24 Nov 2014 17:01:48 +0000 (12:01 -0500)
committerTom Rini <trini@ti.com>
Mon, 24 Nov 2014 17:01:48 +0000 (12:01 -0500)
Conflicts:
drivers/serial/serial-uclass.c

Signed-off-by: Tom Rini <trini@ti.com>
41 files changed:
README
arch/arm/cpu/arm926ejs/at91/at91sam9260_devices.c
arch/arm/cpu/u-boot-spl.lds
arch/arm/include/asm/arch-at91/at91sam9260.h
arch/arm/include/asm/arch-at91/atmel_serial.h [new file with mode: 0644]
arch/arm/include/asm/arch-at91/gpio.h
arch/arm/lib/crt0.S
board/bluewater/snapper9260/MAINTAINERS
board/bluewater/snapper9260/snapper9260.c
board/nvidia/common/board.c
common/Makefile
common/board_r.c
common/cmd_i2c.c
common/dlmalloc.c
common/malloc_simple.c [new file with mode: 0644]
common/spl/spl.c
doc/driver-model/README.txt
drivers/core/Makefile
drivers/core/device-remove.c [new file with mode: 0644]
drivers/core/device.c
drivers/core/lists.c
drivers/core/root.c
drivers/gpio/at91_gpio.c
drivers/misc/cros_ec.c
drivers/mtd/spi/sandbox.c
drivers/serial/atmel_usart.c
drivers/serial/serial-uclass.c
drivers/serial/serial_tegra.c
drivers/spi/spi-uclass.c
include/asm-generic/global_data.h
include/config_defaults.h
include/configs/snapper9260.h
include/configs/tegra-common.h
include/dm/device-internal.h
include/dm/device.h
include/dm/lists.h
include/dm/util.h
include/malloc.h
include/spi.h
lib/fdtdec.c
scripts/Makefile.spl

diff --git a/README b/README
index f52a5f7f64d78bb87aed645598860843154701de..e7cd1bcb436dff45feb2be387eaee30323cc15ae 100644 (file)
--- a/README
+++ b/README
@@ -623,6 +623,120 @@ The following options need to be configured:
                exists, unlike the similar options in the Linux kernel. Do not
                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:
                CONFIG_CLOCKS_IN_MHZ
 
@@ -3870,6 +3984,11 @@ Configuration Settings:
                Pre-relocation malloc() is only supported on ARM and sandbox
                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:
                Normally compressed uImages are limited to an
                uncompressed size of 8 MBytes. If this is not enough,
index 7a7fd7dfb223f598795a23728c745183bb4037ef..efb53d673f4ee137f68b3edfa94b707de4e1b257 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <asm/io.h>
 #include <asm/arch/at91sam9260_matrix.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, 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] },
+};
index 4beddf08e76722251b9d77182c7fc9bef508c314..a69b0061d21942df2dc04923a0009da55ae970dd 100644 (file)
@@ -34,6 +34,13 @@ SECTIONS
        . = 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 = .;
 
index a30d569f6b1b32f5ecab6aa3b53457814e8dba9f..8950d674093a09a1663d8643fec4385dc2b16197 100644 (file)
 /*
  * Other misc defines
  */
+#ifndef CONFIG_DM_GPIO
 #define ATMEL_PIO_PORTS                3               /* these SoCs have 3 PIO */
-#define ATMEL_PMC_UHP          AT91SAM926x_PMC_UHP
 #define ATMEL_BASE_PIO         ATMEL_BASE_PIOA
+#endif
+#define ATMEL_PMC_UHP          AT91SAM926x_PMC_UHP
 
 /*
  * SoC specific defines
diff --git a/arch/arm/include/asm/arch-at91/atmel_serial.h b/arch/arm/include/asm/arch-at91/atmel_serial.h
new file mode 100644 (file)
index 0000000..5bc094b
--- /dev/null
@@ -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
index 71213883d7b7098c52bc22564a41552967932e94..6d2a7b72ff3c98ca0d090569f9707e39f042ecbe 100644 (file)
@@ -253,4 +253,10 @@ static inline unsigned at91_gpio_to_pin(unsigned gpio)
        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 */
index 29cdad0f70716a85e260a124b73f63746b484b80..823b233bc861ef4749417d6b344a2658d6d2ebe2 100644 (file)
@@ -78,7 +78,7 @@ clr_gd:
        strlo   r0, [r1]                /* clear 32-bit GD word */
        addlo   r1, r1, #4              /* move to next */
        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
        str     sp, [r9, #GD_MALLOC_BASE]
 #endif
index ff1e9972cbdbfd89ccea533b5818b4d0db5d7b8e..1f8f4d6988f540c62ae3db875e81c3ee460a5cc4 100644 (file)
@@ -1,5 +1,5 @@
 SNAPPER9260 BOARD
-M:     Ryan Mallon <ryan@bluewatersys.com>
+M:     Simon Glass <sjg@chromium.org>
 S:     Maintained
 F:     board/bluewater/snapper9260/
 F:     include/configs/snapper9260.h
index bfde1291a59c8138740a76ae2c6b21e949b6a23e..95633b0d2e87074fd07d6f3ddb09852ac93622c5 100644 (file)
@@ -9,12 +9,15 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <asm/io.h>
+#include <asm/gpio.h>
 #include <asm/arch/at91sam9260_matrix.h>
 #include <asm/arch/at91sam9_smc.h>
 #include <asm/arch/at91_common.h>
 #include <asm/arch/at91_pmc.h>
 #include <asm/arch/gpio.h>
+#include <asm/arch/atmel_serial.h>
 #include <net.h>
 #include <netdev.h>
 #include <i2c.h>
@@ -95,10 +98,12 @@ static void nand_hw_init(void)
               &smc->cs[3].mode);
 
        /* 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 */
-       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)
@@ -140,3 +145,12 @@ int dram_init(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,
+};
index 51125df34f018b79a511b44dc49e73a817944a43..0e4a65ad059424ac6bea8aff10821e259ba18432 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <ns16550.h>
 #include <linux/compiler.h>
 #include <asm/io.h>
 
 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 = {
        CONFIG_TEGRA_BOARD_STRING
 };
index 508a0b28f5ad325ad4059d539a1fad3257884040..9c47e20c6d19f477170d96b29eadf6a365159d8e 100644 (file)
@@ -252,6 +252,9 @@ obj-$(CONFIG_BOUNCE_BUFFER) += bouncebuf.o
 obj-y += console.o
 obj-$(CONFIG_CROS_EC) += cros_ec.o
 obj-y += dlmalloc.o
+ifdef CONFIG_SYS_MALLOC_F_LEN
+obj-y += malloc_simple.o
+endif
 obj-y += image.o
 obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o
 obj-$(CONFIG_OF_LIBFDT) += image-fdt.o
index 7c339008ed2a46b91677d4c4c9e5e97fd58f4a1f..19c64271ab9d151be1d7e289af50973c62427875 100644 (file)
@@ -99,7 +99,8 @@ static int initr_trace(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");
 
        return 0;
index 3a75f94ea1ff50c14846998b38282b37c42da09a..c266b88e5b272a1d4e728a362194b17c1993ea8b 100644 (file)
@@ -198,6 +198,19 @@ static uint get_alen(char *arg)
        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
  * @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);
 
        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 0;
@@ -286,8 +299,7 @@ static int do_i2c_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
 
        while (length-- > 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.
@@ -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;
 
                if (i2c_read(chip, addr, alen, linebuf, linebytes) != 0)
-                       puts ("Error reading the chip.\n");
+                       i2c_report_err(-1, I2C_ERR_READ);
                else {
                        printf("%04x:", addr);
                        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) {
                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
                 * 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++;
        }
        if (err > 0)
-               puts ("Error reading the chip,\n");
+               i2c_report_err(-1, I2C_ERR_READ);
        else
                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 {
                printf("%08lx:", addr);
                if (i2c_read(chip, addr, alen, (uchar *)&data, size) != 0)
-                       puts ("\nError reading the chip,\n");
+                       i2c_report_err(-1, I2C_ERR_READ);
                else {
                        data = cpu_to_be32(data);
                        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();
                                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
                                udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
 #endif
@@ -783,7 +795,7 @@ static int do_i2c_loop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
         */
        while (1) {
                if (i2c_read(chip, addr, alen, bytes, length) != 0)
-                       puts ("Error reading the chip.\n");
+                       i2c_report_err(-1, I2C_ERR_READ);
                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);
        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;
        }
 
index 991229d5f788f6d85b77833122b8fa2b65102ae1..6453ee9c259fcde7bfbe63099255b9823d5580c2 100644 (file)
@@ -2184,17 +2184,8 @@ Void_t* mALLOc(bytes) size_t bytes;
   INTERNAL_SIZE_T nb;
 
 #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
 
   /* check if mem_malloc_init() was run */
@@ -2462,7 +2453,7 @@ void fREe(mem) Void_t* mem;
 
 #ifdef CONFIG_SYS_MALLOC_F_LEN
        /* 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;
 #endif
 
@@ -2618,7 +2609,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
   if (oldmem == NULL) return mALLOc(bytes);
 
 #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 */
                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
   {
 #ifdef CONFIG_SYS_MALLOC_F_LEN
-       if (!(gd->flags & GD_FLG_RELOC)) {
+       if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT)) {
                MALLOC_ZERO(mem, sz);
                return mem;
        }
diff --git a/common/malloc_simple.c b/common/malloc_simple.c
new file mode 100644 (file)
index 0000000..afdacff
--- /dev/null
@@ -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
index 97eb8eb987d97ed6b0c128742642ecca1a169477..1826c47a99c464bd0023f3c173cab788de49acb0 100644 (file)
@@ -7,6 +7,7 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 #include <common.h>
+#include <dm.h>
 #include <spl.h>
 #include <asm/u-boot.h>
 #include <nand.h>
@@ -15,6 +16,7 @@
 #include <i2c.h>
 #include <image.h>
 #include <malloc.h>
+#include <dm/root.h>
 #include <linux/compiler.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -139,9 +141,16 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
        u32 boot_device;
        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,
                        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
 
 #ifndef CONFIG_PPC
@@ -240,6 +249,11 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
        default:
                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);
 }
 
index 0278dda4d77045a7dbcc8400b1d5593252b4f514..3e2f62265793d09dc4d2277636ffffec0f62b494 100644 (file)
@@ -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).
 
 
-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
 change this to dynamic numbering, but then we would require some sort of
index 151c2398a4d47fce304d43a6ae775befd379baa2..f14695b2d6eae985d366827d69bcedda1ce1e2ce 100644 (file)
@@ -4,5 +4,6 @@
 # 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_DM_DEVICE_REMOVE) += device-remove.o
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
new file mode 100644 (file)
index 0000000..8fc6b71
--- /dev/null
@@ -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;
+}
index 49faa29dc1a0eecaa84e76371b8301c2eef14d7b..6793e1c4f944b9db600687669a222728f19feafd 100644 (file)
 
 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,
                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);
 }
 
-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)
 {
        struct driver *drv;
@@ -342,63 +231,6 @@ int device_probe(struct udevice *dev)
        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)
 {
        if (!dev) {
@@ -548,3 +380,13 @@ int device_find_next_child(struct udevice **devp)
 
        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;
+}
index 3a1ea8565449699a39ba5684dbecfbf71e30780b..ff115c4723e7135986daced0f08dede34379838f 100644 (file)
@@ -25,9 +25,6 @@ struct driver *lists_driver_lookup_name(const char *name)
        const int n_ents = ll_entry_count(struct driver, driver);
        struct driver *entry;
 
-       if (!drv || !n_ents)
-               return NULL;
-
        for (entry = drv; entry != drv + n_ents; entry++) {
                if (!strcmp(name, entry->name))
                        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);
        struct uclass_driver *entry;
 
-       if ((id == UCLASS_INVALID) || !uclass)
-               return NULL;
-
        for (entry = uclass; entry != uclass + n_ents; entry++) {
                if (entry->id == id)
                        return entry;
@@ -77,34 +71,60 @@ int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only)
        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
 /**
  * driver_check_compatible() - Check if a driver is compatible with this node
  *
  * @param blob:                Device tree pointer
  * @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
  * does not have a compatible string, other error <0 if there is a device
  * tree error
  */
 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;
 
+       *of_idp = NULL;
        if (!of_match)
                return -ENOENT;
 
        while (of_match->compatible) {
                ret = fdt_node_check_compatible(blob, offset,
                                                of_match->compatible);
-               if (!ret)
+               if (!ret) {
+                       *of_idp = of_match;
                        return 0;
-               else if (ret == -FDT_ERR_NOTFOUND)
+               } else if (ret == -FDT_ERR_NOTFOUND) {
                        return -ENODEV;
-               else if (ret < 0)
+               } else if (ret < 0) {
                        return -EINVAL;
+               }
                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);
        const int n_ents = ll_entry_count(struct driver, driver);
+       const struct udevice_id *id;
        struct driver *entry;
        struct udevice *dev;
        bool found = false;
@@ -127,7 +148,8 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
        if (devp)
                *devp = NULL;
        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);
                if (ret == -ENOENT) {
                        continue;
@@ -136,8 +158,7 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
                        break;
                } else if (ret) {
                        dm_warn("Device tree error at offset %d\n", offset);
-                       if (!result || ret != -ENOENT)
-                               result = ret;
+                       result = ret;
                        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);
                        return ret;
                } else {
+                       dev->of_id = id;
                        found = true;
                        if (devp)
                                *devp = dev;
index a328a4876f13ad68df6d5fddd8817df622d0195d..47b3acfbe981da9fcfe5ca6d7c20e60dd63b0285 100644 (file)
@@ -73,10 +73,8 @@ int dm_scan_platdata(bool pre_reloc_only)
                dm_warn("Some drivers were not found\n");
                ret = 0;
        }
-       if (ret)
-               return ret;
 
-       return 0;
+       return ret;
 }
 
 #ifdef CONFIG_OF_CONTROL
index 6517af162815ea8e5715dabb390ed46de12f4617..6129c020ea163fb2baa43b211285cad349f29038 100644 (file)
 
 #include <config.h>
 #include <common.h>
+#include <dm.h>
 #include <asm/io.h>
 #include <linux/sizes.h>
+#include <asm/gpio.h>
 #include <asm/arch/hardware.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)
 {
@@ -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)
 {
        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;
 }
@@ -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);
        u32 mask;
 
-       if (at91_port && (pin < 32)) {
+       if (at91_port && (pin < GPIO_PER_BANK)) {
                mask = 1 << pin;
                writel(mask, &at91_port->idr);
                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);
        u32 mask;
 
-       if (at91_port && (pin < 32)) {
+       if (at91_port && (pin < GPIO_PER_BANK)) {
                mask = 1 << pin;
                writel(mask, &at91_port->idr);
                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);
        u32 mask;
 
-       if (at91_port && (pin < 32)) {
+       if (at91_port && (pin < GPIO_PER_BANK)) {
                mask = 1 << pin;
                writel(mask, &at91_port->idr);
                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);
        u32 mask;
 
-       if (at91_port && (pin < 32)) {
+       if (at91_port && (pin < GPIO_PER_BANK)) {
                mask = 1 << pin;
                writel(mask, &at91_port->idr);
                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);
        u32 mask;
 
-       if (at91_port && (pin < 32)) {
+       if (at91_port && (pin < GPIO_PER_BANK)) {
                mask = 1 << pin;
                writel(mask, &at91_port->idr);
                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
 
+#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
  * 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)
 {
        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;
 }
 
+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),
  * 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)
 {
        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;
 }
@@ -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);
        u32 mask;
 
-       if (at91_port && (pin < 32)) {
+       if (at91_port && (pin < GPIO_PER_BANK)) {
                mask = 1 << pin;
                if (is_on) {
 #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);
        u32 mask;
 
-       if (at91_port && (pin < 32)) {
+       if (at91_port && (pin < GPIO_PER_BANK)) {
                mask = 1 << pin;
                if (is_on) {
                        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);
        u32 mask;
 
-       if (at91_port && (pin < 32)) {
+       if (at91_port && (pin < GPIO_PER_BANK)) {
                mask = 1 << pin;
                writel(mask, &at91_port->pudr);
                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);
        u32 mask;
 
-       if (at91_port && (pin < 32)) {
+       if (at91_port && (pin < GPIO_PER_BANK)) {
                mask = 1 << pin;
                writel(readl(&at91_port->schmitt) | mask,
                       &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);
        u32 mask;
 
-       if (at91_port && (pin < 32)) {
+       if (at91_port && (pin < GPIO_PER_BANK)) {
                mask = 1 << pin;
                if (is_on)
                        writel(mask, &at91_port->mder);
@@ -321,41 +353,54 @@ int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on)
        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.
  */
 int at91_set_pio_value(unsigned port, unsigned pin, int value)
 {
        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;
 }
 
+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).
  */
 int at91_get_pio_value(unsigned port, unsigned pin)
 {
        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 */
 
 int gpio_request(unsigned gpio, const char *label)
@@ -395,3 +440,91 @@ int gpio_set_value(unsigned gpio, int value)
 
        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
index 521edfd5de5cf5698ff98c1627e30703c3649282..9b4effb2fb56cda2fcba39d1a5ee80fe084384b8 100644 (file)
@@ -701,6 +701,7 @@ static int cros_ec_check_version(struct cros_ec_dev *dev)
 
        /* Try sending a version 3 packet */
        dev->protocol_version = 3;
+       req.in_data = 0;
        if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req),
                             (uint8_t **)&resp, sizeof(*resp)) > 0) {
                return 0;
index be6c43ed88ac34ceeab141585a7916b4ce06c17d..3024b988fef904884f4d6e4920d98859714f115c 100644 (file)
@@ -602,14 +602,14 @@ static int sandbox_sf_bind_bus_cs(struct sandbox_state *state, int busnum,
                       spec, ret);
                return ret;
        }
-       ret = device_find_child_by_seq(bus, cs, true, &slave);
+       ret = spi_find_chip_select(bus, cs, &slave);
        if (!ret) {
                printf("Chip select %d already exists for spec '%s'\n", cs,
                       spec);
                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)
                return ret;
 
index 8f0e3489a0e59287c60a2e3b34cc1fdc69eb91d7..4fe992bf2bf38dc9d53359dac9212efdf1246e0d 100644 (file)
@@ -7,11 +7,16 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
 #include <watchdog.h>
 #include <serial.h>
 #include <linux/compiler.h>
 
 #include <asm/io.h>
+#ifdef CONFIG_DM_SERIAL
+#include <asm/arch/atmel_serial.h>
+#endif
 #include <asm/arch/clk.h>
 #include <asm/arch/hardware.h>
 
@@ -19,9 +24,9 @@
 
 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 usart_hz;
 
@@ -30,15 +35,13 @@ static void atmel_serial_setbrg(void)
         * Baud Rate = --------------
         *                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);
 }
 
-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
         * 1000us is enough for baudrate >= 9600
@@ -47,9 +50,10 @@ static int atmel_serial_init(void)
                __udelay(1000);
 
        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)
                           | USART3_BF(USCLKS, USART3_USCLKS_MCK)
                           | 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);
        /* 100us is enough for the new settings to be settled */
        __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;
 }
@@ -109,3 +129,81 @@ __weak struct serial_device *default_serial_console(void)
 {
        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
index 0f019c8f505bf717fefe0b240d7524d09829f537..b09053f1402bdf55aa3c89abea593ab0bd82d2dd 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <environment.h>
 #include <errno.h>
 #include <fdtdec.h>
 #include <os.h>
 
 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
 #error "Serial is required before relocation - define CONFIG_SYS_MALLOC_F_LEN to make this work"
 #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)
 {
        _serial_putc(sdev->priv, ch);
 }
+#endif
 
 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);
 }
 
+/**
+ * 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)
 {
-       struct stdio_dev sdev;
        struct dm_serial_ops *ops = serial_get_ops(dev);
+#ifdef CONFIG_DM_STDIO
        struct serial_dev_priv *upriv = dev->uclass_priv;
+       struct stdio_dev sdev;
+#endif
        int ret;
 
        /* Set the baud rate */
@@ -194,9 +265,9 @@ static int serial_post_probe(struct udevice *dev)
                        return ret;
        }
 
+#ifdef CONFIG_DM_STDIO
        if (!(gd->flags & GD_FLG_RELOC))
                return 0;
-
        memset(&sdev, '\0', sizeof(sdev));
 
        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.tstc = serial_stub_tstc;
        stdio_register_dev(&sdev, &upriv->sdev);
-
+#endif
        return 0;
 }
 
index 7eb70e1de135eb18c9342fbabeb29ecb469406a0..b9227f05633c358a5c3918bec488a277d803601f 100644 (file)
@@ -9,6 +9,7 @@
 #include <ns16550.h>
 #include <serial.h>
 
+#ifdef CONFIG_OF_CONTROL
 static const struct udevice_id tegra_serial_ids[] = {
        { .compatible = "nvidia,tegra20-uart" },
        { }
@@ -26,13 +27,28 @@ static int tegra_serial_ofdata_to_platdata(struct udevice *dev)
 
        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) = {
        .name   = "serial_tegra20",
        .id     = UCLASS_SERIAL,
+#ifdef CONFIG_OF_CONTROL
        .of_match = tegra_serial_ids,
        .ofdata_to_platdata = tegra_serial_ofdata_to_platdata,
        .platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
+#endif
        .priv_auto_alloc_size = sizeof(struct NS16550),
        .probe = ns16550_serial_probe,
        .ops    = &ns16550_serial_ops,
+       .flags  = DM_FLAG_PRE_RELOC,
 };
index 637d420a3b2120be60cee9e751ff63403f6fd904..7a57bceb260f1c3e79fc9ed4d735f1b27c45160b 100644 (file)
@@ -115,16 +115,7 @@ int spi_chip_select(struct udevice *dev)
        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;
 
@@ -197,27 +188,6 @@ int spi_cs_info(struct udevice *bus, uint cs, struct spi_cs_info *info)
        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,
                        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) {
                debug("%s: Binding new device '%s', busnum=%d, cs=%d, driver=%s\n",
                      __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)
                        return ret;
                created = true;
index f61acbc4fc12f5cd815965eedba5cc6f25140826..9c5a1e166f9acf428e709c74f07c6102664b8898 100644 (file)
@@ -108,5 +108,6 @@ typedef struct global_data {
 #define GD_FLG_DISABLE_CONSOLE 0x00040 /* Disable console (in & out)      */
 #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_FULL_MALLOC_INIT        0x00200 /* Full malloc() is ready          */
 
 #endif /* __ASM_GENERIC_GBL_DATA_H */
index ad08c1d335d3ba29fd75dcab99f948a5c6a7e278..4d493150444f3f8827df51f9593d3ac4ed76aec0 100644 (file)
 #define CONFIG_ZLIB 1
 #define CONFIG_PARTITIONS 1
 
+#ifndef CONFIG_SPL_BUILD
+#define CONFIG_DM_WARN
+#define CONFIG_DM_DEVICE_REMOVE
+#define CONFIG_DM_STDIO
+#endif
+
 #endif
index 1ebee714ba3e5c568c86c99b937b7d5a2c645644..942af2e7f6244a59c2f3463b8d24dd539ea5baa7 100644 (file)
 #include <asm/hardware.h>
 #include <linux/sizes.h>
 
-#define CONFIG_SYS_TEXT_BASE           0x20000000
+#define CONFIG_SYS_TEXT_BASE           0x21f00000
 
 /* ARM asynchronous clock */
 #define CONFIG_SYS_AT91_MAIN_CLOCK     18432000 /* External Crystal, in Hz */
 #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 */
 #define CONFIG_ARCH_CPU_INIT
 
 /* UARTs/Serial console */
 #define CONFIG_ATMEL_USART
+#ifndef CONFIG_DM_SERIAL
 #define CONFIG_USART_BASE              ATMEL_BASE_DBGU
 #define CONFIG_USART_ID                        ATMEL_ID_SYS
+#endif
 #define CONFIG_BAUDRATE                        115200
 #define CONFIG_SYS_PROMPT              "Snapper> "
 
 #define CONFIG_CMD_DHCP
 #define CONFIG_CMD_FAT
 #define CONFIG_CMD_I2C
-#undef CONFIG_CMD_GPIO
+#define CONFIG_CMD_GPIO
 #define CONFIG_CMD_USB
 #define CONFIG_CMD_MII
 #define CONFIG_CMD_NAND
index 5d2b12a11d1ef1e1494fa76ae14f5eeae8401797..d690045eb046bb7d20cf9e10da1a1bab3cefe435 100644 (file)
 #define CONFIG_SYS_MEMTEST_START       (NV_PA_SDRC_CS0 + 0x600000)
 #define CONFIG_SYS_MEMTEST_END         (CONFIG_SYS_MEMTEST_START + 0x100000)
 
+#ifndef CONFIG_SPL_BUILD
 #define CONFIG_USE_ARCH_MEMCPY
+#endif
 
 /*-----------------------------------------------------------------------
  * Physical Memory Map
index 44cb7ef93bfdeea682ea0602d33bf9615260ad9d..f0cc7947505176907677840bd47554b8a22973c6 100644 (file)
@@ -87,7 +87,11 @@ int device_probe_child(struct udevice *dev, void *parent_priv);
  * @dev: Pointer to device to remove
  * @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);
+#else
+static inline int device_remove(struct udevice *dev) { return 0; }
+#endif
 
 /**
  * device_unbind() - Unbind a device, destroying it
@@ -99,6 +103,12 @@ int device_remove(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 */
 #define DM_ROOT_NON_CONST              (((gd_t *)gd)->dm_root)
 #define DM_UCLASS_ROOT_NON_CONST       (((gd_t *)gd)->uclass_root)
index 9ce95a834e75ee54d6d7edefb21ee0f848f97e0f..13598a15b68684ee81b023c30d8ec42e21941c2b 100644 (file)
@@ -47,6 +47,7 @@ struct driver_info;
  * @name: Name of device, typically the FDT node name
  * @platdata: Configuration data for this device
  * @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
  * @priv: Private data for this device
  * @uclass: Pointer to uclass for this device
@@ -65,6 +66,7 @@ struct udevice {
        const char *name;
        void *platdata;
        int of_offset;
+       const struct udevice_id *of_id;
        struct udevice *parent;
        void *priv;
        struct uclass *uclass;
@@ -205,6 +207,23 @@ void *dev_get_parentdata(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
  *
index 704e33e37fb9dadc739f71312e15f79c4f9bb651..1b50af9f23c19af91d8cc61bca853f05ec709982 100644 (file)
@@ -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,
                   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
index 6ac3a38ef008b686221a5e213e67f5e503233846..0cec17b52a413e8631bd0cc54c08d226e049515b 100644 (file)
@@ -7,7 +7,13 @@
 #ifndef __DM_UTIL_H
 #define __DM_UTIL_H
 
+#ifdef CONFIG_DM_WARN
 void dm_warn(const char *fmt, ...);
+#else
+static inline void dm_warn(const char *fmt, ...)
+{
+}
+#endif
 
 #ifdef DEBUG
 void dm_dbg(const char *fmt, ...);
index c33f3b494eb95b4390c5c2192295fa8f85937edb..5df634873f147f93fb444b9621abf07e1e6e21e1 100644 (file)
@@ -872,33 +872,46 @@ extern Void_t*     sbrk();
 
 #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
 
 /* 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    fREe(Void_t*);
@@ -913,7 +926,7 @@ size_t  malloc_usable_size(Void_t*);
 void    malloc_stats(void);
 int     mALLOPt(int, int);
 struct mallinfo mALLINFo(void);
-#else
+# else
 Void_t* mALLOc();
 void    fREe();
 Void_t* rEALLOc();
@@ -927,6 +940,7 @@ size_t  malloc_usable_size();
 void    malloc_stats();
 int     mALLOPt();
 struct mallinfo mALLINFo();
+# endif
 #endif
 
 /*
index aa0a48ea62710dd019c77c75cc5350a9f61fb14d..5b7827113d9a693ccaa26fee8fe7d0f87105d5d1 100644 (file)
@@ -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);
 
 /**
- * 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
- * @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
index aafc4f931505227b71a01bbbcc8ef8850f8beac4..e8775df5d00b135972799040d03cc76932af759d 100644 (file)
@@ -357,9 +357,9 @@ int fdtdec_get_alias_seq(const void *blob, const char *base, int offset,
                slash = strrchr(prop, '/');
                if (strcmp(slash + 1, find_name))
                        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);
                                return 0;
                        }
index 342d82e71182b1038d899e0fc45da2142c57e82c..190544688016c7f856826896098986526f3b53b4 100644 (file)
@@ -66,6 +66,7 @@ libs-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/
 libs-$(CONFIG_SPL_FRAMEWORK) += common/spl/
 libs-$(CONFIG_SPL_LIBCOMMON_SUPPORT) += common/
 libs-$(CONFIG_SPL_LIBDISK_SUPPORT) += disk/
+libs-$(CONFIG_SPL_DM) += drivers/core/
 libs-$(CONFIG_SPL_I2C_SUPPORT) += drivers/i2c/
 libs-$(CONFIG_SPL_GPIO_SUPPORT) += drivers/gpio/
 libs-$(CONFIG_SPL_MMC_SUPPORT) += drivers/mmc/