Merge git://git.denx.de/u-boot-dm
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index e814eb0..aa3986d 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -29,9 +29,11 @@
 endif
 
 ifneq ($(CONFIG_OMAP54XX),)
+ifeq ($(CONFIG_DM_SCSI),)
 obj-y	+= pipe3-phy.o
 obj-$(CONFIG_SCSI_AHCI_PLAT) += sata.o
 endif
+endif
 
 ifeq ($(CONFIG_SYS_DCACHE_OFF),)
 obj-y	+= omap-cache.o
diff --git a/arch/arm/mach-omap2/omap5/hw_data.c b/arch/arm/mach-omap2/omap5/hw_data.c
index 5d956b5..a8a6b8a 100644
--- a/arch/arm/mach-omap2/omap5/hw_data.c
+++ b/arch/arm/mach-omap2/omap5/hw_data.c
@@ -361,6 +361,9 @@
 		(*prcm)->cm_l4per_gpio6_clkctrl,
 		(*prcm)->cm_l4per_gpio7_clkctrl,
 		(*prcm)->cm_l4per_gpio8_clkctrl,
+#ifdef CONFIG_SCSI_AHCI_PLAT
+		(*prcm)->cm_l3init_ocp2scp3_clkctrl,
+#endif
 		0
 	};
 
@@ -379,6 +382,9 @@
 #ifdef CONFIG_TI_QSPI
 		(*prcm)->cm_l4per_qspi_clkctrl,
 #endif
+#ifdef CONFIG_SCSI_AHCI_PLAT
+		(*prcm)->cm_l3init_sata_clkctrl,
+#endif
 		0
 	};
 
@@ -411,6 +417,12 @@
 	setbits_le32((*prcm)->cm_l4per_qspi_clkctrl, (1<<24));
 #endif
 
+#ifdef CONFIG_SCSI_AHCI_PLAT
+	/* Enable optional functional clock for SATA */
+	setbits_le32((*prcm)->cm_l3init_sata_clkctrl,
+		     SATA_CLKCTRL_OPTFCLKEN_MASK);
+#endif
+
 	/* Enable SCRM OPT clocks for PER and CORE dpll */
 	setbits_le32((*prcm)->cm_wkupaon_scrm_clkctrl,
 			OPTFCLKEN_SCRM_PER_MASK);
diff --git a/arch/arm/mach-omap2/sata.c b/arch/arm/mach-omap2/sata.c
index 2c2d1bc..0c82689 100644
--- a/arch/arm/mach-omap2/sata.c
+++ b/arch/arm/mach-omap2/sata.c
@@ -37,29 +37,6 @@
 	int ret;
 	u32 val;
 
-	u32 const clk_domains_sata[] = {
-		0
-	};
-
-	u32 const clk_modules_hw_auto_sata[] = {
-		(*prcm)->cm_l3init_ocp2scp3_clkctrl,
-		0
-	};
-
-	u32 const clk_modules_explicit_en_sata[] = {
-		(*prcm)->cm_l3init_sata_clkctrl,
-		0
-	};
-
-	do_enable_clocks(clk_domains_sata,
-			 clk_modules_hw_auto_sata,
-			 clk_modules_explicit_en_sata,
-			 0);
-
-	/* Enable optional functional clock for SATA */
-	setbits_le32((*prcm)->cm_l3init_sata_clkctrl,
-		     SATA_CLKCTRL_OPTFCLKEN_MASK);
-
 	sata_phy.power_reg = (void __iomem *)(*ctrl)->control_phy_power_sata;
 
 	/* Power up the PHY */
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 2061464..40f423d 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -123,6 +123,20 @@
 		yres = <768>;
 	};
 
+	leds {
+		compatible = "gpio-leds";
+
+		iracibble {
+			gpios = <&gpio_a 1 0>;
+			label = "sandbox:red";
+		};
+
+		martinet {
+			gpios = <&gpio_a 2 0>;
+			label = "sandbox:green";
+		};
+	};
+
 	pci: pci-controller {
 		compatible = "sandbox,pci";
 		device_type = "pci";
diff --git a/board/atmel/sama5d3_xplained/sama5d3_xplained.c b/board/atmel/sama5d3_xplained/sama5d3_xplained.c
index 2b9da91..ba7f9f2 100644
--- a/board/atmel/sama5d3_xplained/sama5d3_xplained.c
+++ b/board/atmel/sama5d3_xplained/sama5d3_xplained.c
@@ -6,16 +6,13 @@
  */
 
 #include <common.h>
-#include <mmc.h>
 #include <asm/io.h>
 #include <asm/arch/sama5d3_smc.h>
 #include <asm/arch/at91_common.h>
 #include <asm/arch/at91_rstc.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/clk.h>
-#include <atmel_mci.h>
-#include <net.h>
-#include <netdev.h>
+#include <debug_uart.h>
 #include <spl.h>
 #include <asm/arch/atmel_mpddrc.h>
 #include <asm/arch/at91_wdt.h>
@@ -65,24 +62,26 @@
 #ifdef CONFIG_GENERIC_ATMEL_MCI
 static void sama5d3_xplained_mci0_hw_init(void)
 {
-	at91_mci_hw_init();
-
 	at91_set_pio_output(AT91_PIO_PORTE, 2, 0);	/* MCI0 Power */
 }
 #endif
 
-int board_early_init_f(void)
+#ifdef CONFIG_DEBUG_UART_BOARD_INIT
+void board_debug_uart_init(void)
 {
-	at91_periph_clk_enable(ATMEL_ID_PIOA);
-	at91_periph_clk_enable(ATMEL_ID_PIOB);
-	at91_periph_clk_enable(ATMEL_ID_PIOC);
-	at91_periph_clk_enable(ATMEL_ID_PIOD);
-	at91_periph_clk_enable(ATMEL_ID_PIOE);
-
 	at91_seriald_hw_init();
+}
+#endif
 
+#ifdef CONFIG_BOARD_EARLY_INIT_F
+int board_early_init_f(void)
+{
+#ifdef CONFIG_DEBUG_UART
+	debug_uart_init();
+#endif
 	return 0;
 }
+#endif
 
 int board_init(void)
 {
@@ -98,10 +97,6 @@
 #ifdef CONFIG_GENERIC_ATMEL_MCI
 	sama5d3_xplained_mci0_hw_init();
 #endif
-#ifdef CONFIG_MACB
-	at91_gmac_hw_init();
-	at91_macb_hw_init();
-#endif
 	return 0;
 }
 
@@ -112,31 +107,15 @@
 
 	return 0;
 }
-
-int board_eth_init(bd_t *bis)
-{
-#ifdef CONFIG_MACB
-	macb_eth_initialize(0, (void *)ATMEL_BASE_GMAC, 0x00);
-	macb_eth_initialize(0, (void *)ATMEL_BASE_EMAC, 0x00);
-#endif
-	return 0;
-}
-
-#ifdef CONFIG_GENERIC_ATMEL_MCI
-int board_mmc_init(bd_t *bis)
-{
-	atmel_mci_init((void *)ATMEL_BASE_MCI0);
-
-	return 0;
-}
-#endif
 
 /* SPL */
 #ifdef CONFIG_SPL_BUILD
 void spl_board_init(void)
 {
 #ifdef CONFIG_SYS_USE_MMC
+#ifdef CONFIG_GENERIC_ATMEL_MCI
 	sama5d3_xplained_mci0_hw_init();
+#endif
 #elif CONFIG_SYS_USE_NANDFLASH
 	sama5d3_xplained_nand_hw_init();
 #endif
diff --git a/board/atmel/sama5d3xek/sama5d3xek.c b/board/atmel/sama5d3xek/sama5d3xek.c
index 134c2fe..cae6e24 100644
--- a/board/atmel/sama5d3xek/sama5d3xek.c
+++ b/board/atmel/sama5d3xek/sama5d3xek.c
@@ -6,29 +6,22 @@
  */
 
 #include <common.h>
-#include <mmc.h>
 #include <asm/io.h>
 #include <asm/arch/sama5d3_smc.h>
 #include <asm/arch/at91_common.h>
 #include <asm/arch/at91_rstc.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/clk.h>
+#include <debug_uart.h>
 #include <lcd.h>
 #include <linux/ctype.h>
 #include <atmel_hlcdc.h>
-#include <atmel_mci.h>
 #include <phy.h>
 #include <micrel.h>
-#include <net.h>
-#include <netdev.h>
 #include <spl.h>
 #include <asm/arch/atmel_mpddrc.h>
 #include <asm/arch/at91_wdt.h>
 
-#ifdef CONFIG_USB_GADGET_ATMEL_USBA
-#include <asm/arch/atmel_usba_udc.h>
-#endif
-
 DECLARE_GLOBAL_DATA_PTR;
 
 /* ------------------------------------------------------------------------- */
@@ -135,8 +128,6 @@
 #ifdef CONFIG_GENERIC_ATMEL_MCI
 static void sama5d3xek_mci_hw_init(void)
 {
-	at91_mci_hw_init();
-
 	at91_set_pio_output(AT91_PIO_PORTB, 10, 0);	/* MCI0 Power */
 }
 #endif
@@ -215,18 +206,22 @@
 #endif /* CONFIG_LCD_INFO */
 #endif /* CONFIG_LCD */
 
-int board_early_init_f(void)
+#ifdef CONFIG_DEBUG_UART_BOARD_INIT
+void board_debug_uart_init(void)
 {
-	at91_periph_clk_enable(ATMEL_ID_PIOA);
-	at91_periph_clk_enable(ATMEL_ID_PIOB);
-	at91_periph_clk_enable(ATMEL_ID_PIOC);
-	at91_periph_clk_enable(ATMEL_ID_PIOD);
-	at91_periph_clk_enable(ATMEL_ID_PIOE);
-
 	at91_seriald_hw_init();
+}
+#endif
 
+#ifdef CONFIG_BOARD_EARLY_INIT_F
+int board_early_init_f(void)
+{
+#ifdef CONFIG_DEBUG_UART
+	debug_uart_init();
+#endif
 	return 0;
 }
+#endif
 
 int board_init(void)
 {
@@ -242,21 +237,9 @@
 #ifdef CONFIG_CMD_USB
 	sama5d3xek_usb_hw_init();
 #endif
-#ifdef CONFIG_USB_GADGET_ATMEL_USBA
-	at91_udp_hw_init();
-#endif
 #ifdef CONFIG_GENERIC_ATMEL_MCI
 	sama5d3xek_mci_hw_init();
 #endif
-#ifdef CONFIG_ATMEL_SPI
-	at91_spi0_hw_init(1 << 0);
-#endif
-#ifdef CONFIG_MACB
-	if (has_emac())
-		at91_macb_hw_init();
-	if (has_gmac())
-		at91_gmac_hw_init();
-#endif
 #ifdef CONFIG_LCD
 	if (has_lcdc())
 		sama5d3xek_lcd_hw_init();
@@ -270,104 +253,6 @@
 				    CONFIG_SYS_SDRAM_SIZE);
 	return 0;
 }
-
-int board_phy_config(struct phy_device *phydev)
-{
-	/* board specific timings for GMAC */
-	if (has_gmac()) {
-		/* rx data delay */
-		ksz9021_phy_extended_write(phydev,
-					   MII_KSZ9021_EXT_RGMII_RX_DATA_SKEW,
-					   0x2222);
-		/* tx data delay */
-		ksz9021_phy_extended_write(phydev,
-					   MII_KSZ9021_EXT_RGMII_TX_DATA_SKEW,
-					   0x2222);
-		/* rx/tx clock delay */
-		ksz9021_phy_extended_write(phydev,
-					   MII_KSZ9021_EXT_RGMII_CLOCK_SKEW,
-					   0xf2f4);
-	}
-
-	/* always run the PHY's config routine */
-	if (phydev->drv->config)
-		return phydev->drv->config(phydev);
-
-	return 0;
-}
-
-int board_eth_init(bd_t *bis)
-{
-	int rc = 0;
-
-#ifdef CONFIG_MACB
-	if (has_emac())
-		rc = macb_eth_initialize(0, (void *)ATMEL_BASE_EMAC, 0x00);
-	if (has_gmac())
-		rc = macb_eth_initialize(0, (void *)ATMEL_BASE_GMAC, 0x00);
-#endif
-#ifdef CONFIG_USB_GADGET_ATMEL_USBA
-	usba_udc_probe(&pdata);
-#ifdef CONFIG_USB_ETH_RNDIS
-	usb_eth_initialize(bis);
-#endif
-#endif
-
-	return rc;
-}
-
-#ifdef CONFIG_GENERIC_ATMEL_MCI
-int board_mmc_init(bd_t *bis)
-{
-	int rc = 0;
-
-	rc = atmel_mci_init((void *)ATMEL_BASE_MCI0);
-
-	return rc;
-}
-#endif
-
-/* SPI chip select control */
-#ifdef CONFIG_ATMEL_SPI
-#include <spi.h>
-
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
-{
-	return bus == 0 && cs < 4;
-}
-
-void spi_cs_activate(struct spi_slave *slave)
-{
-	switch (slave->cs) {
-	case 0:
-		at91_set_pio_output(AT91_PIO_PORTD, 13, 0);
-	case 1:
-		at91_set_pio_output(AT91_PIO_PORTD, 14, 0);
-	case 2:
-		at91_set_pio_output(AT91_PIO_PORTD, 15, 0);
-	case 3:
-		at91_set_pio_output(AT91_PIO_PORTD, 16, 0);
-	default:
-		break;
-	}
-}
-
-void spi_cs_deactivate(struct spi_slave *slave)
-{
-	switch (slave->cs) {
-	case 0:
-		at91_set_pio_output(AT91_PIO_PORTD, 13, 1);
-	case 1:
-		at91_set_pio_output(AT91_PIO_PORTD, 14, 1);
-	case 2:
-		at91_set_pio_output(AT91_PIO_PORTD, 15, 1);
-	case 3:
-		at91_set_pio_output(AT91_PIO_PORTD, 16, 1);
-	default:
-		break;
-	}
-}
-#endif /* CONFIG_ATMEL_SPI */
 
 #ifdef CONFIG_BOARD_LATE_INIT
 int board_late_init(void)
@@ -392,12 +277,8 @@
 #ifdef CONFIG_SPL_BUILD
 void spl_board_init(void)
 {
-#ifdef CONFIG_SYS_USE_MMC
-	sama5d3xek_mci_hw_init();
-#elif CONFIG_SYS_USE_NANDFLASH
+#if CONFIG_SYS_USE_NANDFLASH
 	sama5d3xek_nand_hw_init();
-#elif CONFIG_SYS_USE_SERIALFLASH
-	at91_spi0_hw_init(1 << 0);
 #endif
 }
 
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 661ae7a..13dc46a 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -667,6 +667,15 @@
 	help
 	  Enable the "icache" and "dcache" commands
 
+config CMD_LED
+	bool "led"
+	default y if LED
+	help
+	  Enable the 'led' command which allows for control of LEDs supported
+	  by the board. The LEDs can be listed with 'led list' and controlled
+	  with led on/off/togle/blink. Any LED drivers can be controlled with
+	  this command, e.g. led_gpio.
+
 config CMD_TIME
 	bool "time"
 	help
diff --git a/cmd/Makefile b/cmd/Makefile
index ef1406b..3cb0cfd 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -78,7 +78,8 @@
 obj-$(CONFIG_CMD_JFFS2) += jffs2.o
 obj-$(CONFIG_CMD_CRAMFS) += cramfs.o
 obj-$(CONFIG_CMD_LDRINFO) += ldrinfo.o
-obj-$(CONFIG_LED_STATUS_CMD) += led.o
+obj-$(CONFIG_LED_STATUS_CMD) += legacy_led.o
+obj-$(CONFIG_CMD_LED) += led.o
 obj-$(CONFIG_CMD_LICENSE) += license.o
 obj-y += load.o
 obj-$(CONFIG_LOGBUFFER) += log.o
diff --git a/cmd/led.c b/cmd/led.c
index 951a5e2..84173f8 100644
--- a/cmd/led.c
+++ b/cmd/led.c
@@ -1,187 +1,145 @@
 /*
- * (C) Copyright 2010
- * Jason Kridner <jkridner@beagleboard.org>
+ * Copyright (c) 2017 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
  *
- * Based on cmd_led.c patch from:
- * http://www.mail-archive.com/u-boot@lists.denx.de/msg06873.html
- * (C) Copyright 2008
- * Ulf Samuelsson <ulf.samuelsson@atmel.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
+ * SPDX-License-Identifier:     GPL-2.0+
  */
 
 #include <common.h>
-#include <config.h>
 #include <command.h>
-#include <status_led.h>
-
-struct led_tbl_s {
-	char		*string;	/* String for use in the command */
-	led_id_t	mask;		/* Mask used for calling __led_set() */
-	void		(*off)(void);	/* Optional function for turning LED off */
-	void		(*on)(void);	/* Optional function for turning LED on */
-	void		(*toggle)(void);/* Optional function for toggling LED */
-};
+#include <dm.h>
+#include <led.h>
+#include <dm/uclass-internal.h>
 
-typedef struct led_tbl_s led_tbl_t;
+#define LED_TOGGLE LEDST_COUNT
 
-static const led_tbl_t led_commands[] = {
-#ifdef CONFIG_LED_STATUS_BOARD_SPECIFIC
-#ifdef CONFIG_LED_STATUS0
-	{ "0", CONFIG_LED_STATUS_BIT, NULL, NULL, NULL },
-#endif
-#ifdef CONFIG_LED_STATUS1
-	{ "1", CONFIG_LED_STATUS_BIT1, NULL, NULL, NULL },
-#endif
-#ifdef CONFIG_LED_STATUS2
-	{ "2", CONFIG_LED_STATUS_BIT2, NULL, NULL, NULL },
-#endif
-#ifdef CONFIG_LED_STATUS3
-	{ "3", CONFIG_LED_STATUS_BIT3, NULL, NULL, NULL },
-#endif
-#ifdef CONFIG_LED_STATUS4
-	{ "4", CONFIG_LED_STATUS_BIT4, NULL, NULL, NULL },
+static const char *const state_label[] = {
+	[LEDST_OFF]	= "off",
+	[LEDST_ON]	= "on",
+	[LEDST_TOGGLE]	= "toggle",
+#ifdef CONFIG_LED_BLINK
+	[LEDST_BLINK]	= "blink",
 #endif
-#ifdef CONFIG_LED_STATUS5
-	{ "5", CONFIG_LED_STATUS_BIT5, NULL, NULL, NULL },
-#endif
-#endif
-#ifdef CONFIG_LED_STATUS_GREEN
-	{ "green", CONFIG_LED_STATUS_GREEN, green_led_off, green_led_on, NULL },
-#endif
-#ifdef CONFIG_LED_STATUS_YELLOW
-	{ "yellow", CONFIG_LED_STATUS_YELLOW, yellow_led_off, yellow_led_on,
-	  NULL },
-#endif
-#ifdef CONFIG_LED_STATUS_RED
-	{ "red", CONFIG_LED_STATUS_RED, red_led_off, red_led_on, NULL },
-#endif
-#ifdef CONFIG_LED_STATUS_BLUE
-	{ "blue", CONFIG_LED_STATUS_BLUE, blue_led_off, blue_led_on, NULL },
-#endif
-	{ NULL, 0, NULL, NULL, NULL }
 };
 
-enum led_cmd { LED_ON, LED_OFF, LED_TOGGLE, LED_BLINK };
-
-enum led_cmd get_led_cmd(char *var)
+enum led_state_t get_led_cmd(char *var)
 {
-	if (strcmp(var, "off") == 0)
-		return LED_OFF;
-	if (strcmp(var, "on") == 0)
-		return LED_ON;
-	if (strcmp(var, "toggle") == 0)
-		return LED_TOGGLE;
-	if (strcmp(var, "blink") == 0)
-		return LED_BLINK;
+	int i;
+
+	for (i = 0; i < LEDST_COUNT; i++) {
+		if (!strncmp(var, state_label[i], strlen(var)))
+			return i;
+	}
 
 	return -1;
 }
 
-/*
- * LED drivers providing a blinking LED functionality, like the
- * PCA9551, can override this empty weak function
- */
-void __weak __led_blink(led_id_t mask, int freq)
+static int show_led_state(struct udevice *dev)
 {
+	int ret;
+
+	ret = led_get_state(dev);
+	if (ret >= LEDST_COUNT)
+		ret = -EINVAL;
+	if (ret >= 0)
+		printf("%s\n", state_label[ret]);
+
+	return ret;
 }
 
-int do_led (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+static int list_leds(void)
 {
-	int i, match = 0;
-	enum led_cmd cmd;
-	int freq;
+	struct udevice *dev;
+	int ret;
 
-	/* Validate arguments */
-	if ((argc < 3) || (argc > 4))
-		return CMD_RET_USAGE;
+	for (uclass_find_first_device(UCLASS_LED, &dev);
+	     dev;
+	     uclass_find_next_device(&dev)) {
+		struct led_uc_plat *plat = dev_get_uclass_platdata(dev);
 
-	cmd = get_led_cmd(argv[2]);
-	if (cmd < 0) {
-		return CMD_RET_USAGE;
+		if (!plat->label)
+			continue;
+		printf("%-15s ", plat->label);
+		if (device_active(dev)) {
+			ret = show_led_state(dev);
+			if (ret < 0)
+				printf("Error %d\n", ret);
+		} else {
+			printf("<inactive>\n");
+		}
 	}
 
+	return 0;
+}
+
-	for (i = 0; led_commands[i].string; i++) {
-		if ((strcmp("all", argv[1]) == 0) ||
-		    (strcmp(led_commands[i].string, argv[1]) == 0)) {
-			match = 1;
-			switch (cmd) {
-			case LED_ON:
-				if (led_commands[i].on)
-					led_commands[i].on();
-				else
-					__led_set(led_commands[i].mask,
-							  CONFIG_LED_STATUS_ON);
-				break;
-			case LED_OFF:
-				if (led_commands[i].off)
-					led_commands[i].off();
-				else
-					__led_set(led_commands[i].mask,
-						  CONFIG_LED_STATUS_OFF);
-				break;
-			case LED_TOGGLE:
-				if (led_commands[i].toggle)
-					led_commands[i].toggle();
-				else
-					__led_toggle(led_commands[i].mask);
-				break;
-			case LED_BLINK:
-				if (argc != 4)
-					return CMD_RET_USAGE;
+int do_led(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	enum led_state_t cmd;
+	const char *led_label;
+	struct udevice *dev;
+#ifdef CONFIG_LED_BLINK
+	int freq_ms = 0;
+#endif
+	int ret;
 
-				freq = simple_strtoul(argv[3], NULL, 10);
-				__led_blink(led_commands[i].mask, freq);
-			}
-			/* Need to set only 1 led if led_name wasn't 'all' */
-			if (strcmp("all", argv[1]) != 0)
-				break;
-		}
-	}
+	/* Validate arguments */
+	if (argc < 2)
+		return CMD_RET_USAGE;
+	led_label = argv[1];
+	if (*led_label == 'l')
+		return list_leds();
 
-	/* If we ran out of matches, print Usage */
-	if (!match) {
+	cmd = argc > 2 ? get_led_cmd(argv[2]) : LEDST_COUNT;
+	if (cmd < 0)
 		return CMD_RET_USAGE;
+#ifdef CONFIG_LED_BLINK
+	if (cmd == LEDST_BLINK) {
+		if (argc < 4)
+			return CMD_RET_USAGE;
+		freq_ms = simple_strtoul(argv[3], NULL, 10);
+	}
+#endif
+	ret = led_get_by_label(led_label, &dev);
+	if (ret) {
+		printf("LED '%s' not found (err=%d)\n", led_label, ret);
+		return CMD_RET_FAILURE;
+	}
+	switch (cmd) {
+	case LEDST_OFF:
+	case LEDST_ON:
+	case LEDST_TOGGLE:
+		ret = led_set_state(dev, cmd);
+		break;
+#ifdef CONFIG_LED_BLINK
+	case LEDST_BLINK:
+		ret = led_set_period(dev, freq_ms);
+		if (!ret)
+			ret = led_set_state(dev, LEDST_BLINK);
+		break;
+#endif
+	case LEDST_COUNT:
+		printf("LED '%s': ", led_label);
+		ret = show_led_state(dev);
+		break;
+	}
+	if (ret < 0) {
+		printf("LED '%s' operation failed (err=%d)\n", led_label, ret);
+		return CMD_RET_FAILURE;
 	}
 
 	return 0;
 }
 
+#ifdef CONFIG_LED_BLINK
+#define BLINK "|blink [blink-freq in ms]"
+#else
+#define BLINK ""
+#endif
+
 U_BOOT_CMD(
 	led, 4, 1, do_led,
-	"["
-#ifdef CONFIG_LED_STATUS_BOARD_SPECIFIC
-#ifdef CONFIG_LED_STATUS0
-	"0|"
-#endif
-#ifdef CONFIG_LED_STATUS1
-	"1|"
-#endif
-#ifdef CONFIG_LED_STATUS2
-	"2|"
-#endif
-#ifdef CONFIG_LED_STATUS3
-	"3|"
-#endif
-#ifdef CONFIG_LED_STATUS4
-	"4|"
-#endif
-#ifdef CONFIG_LED_STATUS5
-	"5|"
-#endif
-#endif
-#ifdef CONFIG_LED_STATUS_GREEN
-	"green|"
-#endif
-#ifdef CONFIG_LED_STATUS_YELLOW
-	"yellow|"
-#endif
-#ifdef CONFIG_LED_STATUS_RED
-	"red|"
-#endif
-#ifdef CONFIG_LED_STATUS_BLUE
-	"blue|"
-#endif
-	"all] [on|off|toggle|blink] [blink-freq in ms]",
-	"[led_name] [on|off|toggle|blink] sets or clears led(s)"
+	"manage LEDs",
+	"<led_label> on|off|toggle" BLINK "\tChange LED state\n"
+	"led [<led_label>\tGet LED state\n"
+	"led list\t\tshow a list of LEDs"
 );
diff --git a/cmd/legacy_led.c b/cmd/legacy_led.c
new file mode 100644
index 0000000..1ec2e43
--- /dev/null
+++ b/cmd/legacy_led.c
@@ -0,0 +1,187 @@
+/*
+ * (C) Copyright 2010
+ * Jason Kridner <jkridner@beagleboard.org>
+ *
+ * Based on cmd_led.c patch from:
+ * http://www.mail-archive.com/u-boot@lists.denx.de/msg06873.html
+ * (C) Copyright 2008
+ * Ulf Samuelsson <ulf.samuelsson@atmel.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <config.h>
+#include <command.h>
+#include <status_led.h>
+
+struct led_tbl_s {
+	char		*string;	/* String for use in the command */
+	led_id_t	mask;		/* Mask used for calling __led_set() */
+	void		(*off)(void);	/* Optional function for turning LED off */
+	void		(*on)(void);	/* Optional function for turning LED on */
+	void		(*toggle)(void);/* Optional function for toggling LED */
+};
+
+typedef struct led_tbl_s led_tbl_t;
+
+static const led_tbl_t led_commands[] = {
+#ifdef CONFIG_LED_STATUS_BOARD_SPECIFIC
+#ifdef CONFIG_LED_STATUS0
+	{ "0", CONFIG_LED_STATUS_BIT, NULL, NULL, NULL },
+#endif
+#ifdef CONFIG_LED_STATUS1
+	{ "1", CONFIG_LED_STATUS_BIT1, NULL, NULL, NULL },
+#endif
+#ifdef CONFIG_LED_STATUS2
+	{ "2", CONFIG_LED_STATUS_BIT2, NULL, NULL, NULL },
+#endif
+#ifdef CONFIG_LED_STATUS3
+	{ "3", CONFIG_LED_STATUS_BIT3, NULL, NULL, NULL },
+#endif
+#ifdef CONFIG_LED_STATUS4
+	{ "4", CONFIG_LED_STATUS_BIT4, NULL, NULL, NULL },
+#endif
+#ifdef CONFIG_LED_STATUS5
+	{ "5", CONFIG_LED_STATUS_BIT5, NULL, NULL, NULL },
+#endif
+#endif
+#ifdef CONFIG_LED_STATUS_GREEN
+	{ "green", CONFIG_LED_STATUS_GREEN, green_led_off, green_led_on, NULL },
+#endif
+#ifdef CONFIG_LED_STATUS_YELLOW
+	{ "yellow", CONFIG_LED_STATUS_YELLOW, yellow_led_off, yellow_led_on,
+	  NULL },
+#endif
+#ifdef CONFIG_LED_STATUS_RED
+	{ "red", CONFIG_LED_STATUS_RED, red_led_off, red_led_on, NULL },
+#endif
+#ifdef CONFIG_LED_STATUS_BLUE
+	{ "blue", CONFIG_LED_STATUS_BLUE, blue_led_off, blue_led_on, NULL },
+#endif
+	{ NULL, 0, NULL, NULL, NULL }
+};
+
+enum led_cmd { LED_ON, LED_OFF, LED_TOGGLE, LED_BLINK };
+
+enum led_cmd get_led_cmd(char *var)
+{
+	if (strcmp(var, "off") == 0)
+		return LED_OFF;
+	if (strcmp(var, "on") == 0)
+		return LED_ON;
+	if (strcmp(var, "toggle") == 0)
+		return LED_TOGGLE;
+	if (strcmp(var, "blink") == 0)
+		return LED_BLINK;
+
+	return -1;
+}
+
+/*
+ * LED drivers providing a blinking LED functionality, like the
+ * PCA9551, can override this empty weak function
+ */
+void __weak __led_blink(led_id_t mask, int freq)
+{
+}
+
+int do_legacy_led(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int i, match = 0;
+	enum led_cmd cmd;
+	int freq;
+
+	/* Validate arguments */
+	if ((argc < 3) || (argc > 4))
+		return CMD_RET_USAGE;
+
+	cmd = get_led_cmd(argv[2]);
+	if (cmd < 0) {
+		return CMD_RET_USAGE;
+	}
+
+	for (i = 0; led_commands[i].string; i++) {
+		if ((strcmp("all", argv[1]) == 0) ||
+		    (strcmp(led_commands[i].string, argv[1]) == 0)) {
+			match = 1;
+			switch (cmd) {
+			case LED_ON:
+				if (led_commands[i].on)
+					led_commands[i].on();
+				else
+					__led_set(led_commands[i].mask,
+							  CONFIG_LED_STATUS_ON);
+				break;
+			case LED_OFF:
+				if (led_commands[i].off)
+					led_commands[i].off();
+				else
+					__led_set(led_commands[i].mask,
+						  CONFIG_LED_STATUS_OFF);
+				break;
+			case LED_TOGGLE:
+				if (led_commands[i].toggle)
+					led_commands[i].toggle();
+				else
+					__led_toggle(led_commands[i].mask);
+				break;
+			case LED_BLINK:
+				if (argc != 4)
+					return CMD_RET_USAGE;
+
+				freq = simple_strtoul(argv[3], NULL, 10);
+				__led_blink(led_commands[i].mask, freq);
+			}
+			/* Need to set only 1 led if led_name wasn't 'all' */
+			if (strcmp("all", argv[1]) != 0)
+				break;
+		}
+	}
+
+	/* If we ran out of matches, print Usage */
+	if (!match) {
+		return CMD_RET_USAGE;
+	}
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	led, 4, 1, do_legacy_led,
+	"["
+#ifdef CONFIG_LED_STATUS_BOARD_SPECIFIC
+#ifdef CONFIG_LED_STATUS0
+	"0|"
+#endif
+#ifdef CONFIG_LED_STATUS1
+	"1|"
+#endif
+#ifdef CONFIG_LED_STATUS2
+	"2|"
+#endif
+#ifdef CONFIG_LED_STATUS3
+	"3|"
+#endif
+#ifdef CONFIG_LED_STATUS4
+	"4|"
+#endif
+#ifdef CONFIG_LED_STATUS5
+	"5|"
+#endif
+#endif
+#ifdef CONFIG_LED_STATUS_GREEN
+	"green|"
+#endif
+#ifdef CONFIG_LED_STATUS_YELLOW
+	"yellow|"
+#endif
+#ifdef CONFIG_LED_STATUS_RED
+	"red|"
+#endif
+#ifdef CONFIG_LED_STATUS_BLUE
+	"blue|"
+#endif
+	"all] [on|off|toggle|blink] [blink-freq in ms]",
+	"[led_name] [on|off|toggle|blink] sets or clears led(s)"
+);
diff --git a/common/scsi.c b/common/scsi.c
index fb5b407..d37222c 100644
--- a/common/scsi.c
+++ b/common/scsi.c
@@ -473,14 +473,15 @@
  * scsi_detect_dev - Detect scsi device
  *
  * @target: target id
+ * @lun: target lun
  * @dev_desc: block device description
  *
  * The scsi_detect_dev detects and fills a dev_desc structure when the device is
- * detected. The LUN number is taken from the struct blk_desc *dev_desc.
+ * detected.
  *
  * Return: 0 on success, error value otherwise
  */
-static int scsi_detect_dev(int target, struct blk_desc *dev_desc)
+static int scsi_detect_dev(int target, int lun, struct blk_desc *dev_desc)
 {
 	unsigned char perq, modi;
 	lbaint_t capacity;
@@ -488,7 +489,7 @@
 	ccb *pccb = (ccb *)&tempccb;
 
 	pccb->target = target;
-	pccb->lun = dev_desc->lun;
+	pccb->lun = lun;
 	pccb->pdata = (unsigned char *)&tempbuff;
 	pccb->datalen = 512;
 	scsi_setup_inquiry(pccb);
@@ -539,7 +540,6 @@
 	dev_desc->blksz = blksz;
 	dev_desc->log2blksz = LOG2(dev_desc->blksz);
 	dev_desc->type = perq;
-	part_init(&dev_desc[0]);
 removable:
 	return 0;
 }
@@ -580,9 +580,19 @@
 			for (lun = 0; lun < plat->max_lun; lun++) {
 				struct udevice *bdev; /* block device */
 				/* block device description */
+				struct blk_desc _bd;
 				struct blk_desc *bdesc;
 				char str[10];
 
+				scsi_init_dev_desc_priv(&_bd);
+				ret = scsi_detect_dev(i, lun, &_bd);
+				if (ret)
+					/*
+					 * no device detected?
+					 * check the next lun.
+					 */
+					continue;
+
 				/*
 				 * Create only one block device and do detection
 				 * to make sure that there won't be a lot of
@@ -590,21 +600,28 @@
 				 */
 				snprintf(str, sizeof(str), "id%dlun%d", i, lun);
 				ret = blk_create_devicef(dev, "scsi_blk",
-							  str, IF_TYPE_SCSI,
-							  -1, 0, 0, &bdev);
+						str, IF_TYPE_SCSI,
+						-1,
+						_bd.blksz,
+						_bd.blksz * _bd.lba,
+						&bdev);
 				if (ret) {
 					debug("Can't create device\n");
 					return ret;
 				}
-				bdesc = dev_get_uclass_platdata(bdev);
 
-				scsi_init_dev_desc_priv(bdesc);
+				bdesc = dev_get_uclass_platdata(bdev);
+				bdesc->target = i;
 				bdesc->lun = lun;
-				ret = scsi_detect_dev(i, bdesc);
-				if (ret) {
-					device_unbind(bdev);
-					continue;
-				}
+				bdesc->removable = _bd.removable;
+				bdesc->type = _bd.type;
+				memcpy(&bdesc->vendor, &_bd.vendor,
+				       sizeof(_bd.vendor));
+				memcpy(&bdesc->product, &_bd.product,
+				       sizeof(_bd.product));
+				memcpy(&bdesc->revision, &_bd.revision,
+				       sizeof(_bd.revision));
+				part_init(bdesc);
 
 				if (mode == 1) {
 					printf("  Device %d: ", 0);
@@ -630,10 +647,11 @@
 	scsi_max_devs = 0;
 	for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) {
 		for (lun = 0; lun < CONFIG_SYS_SCSI_MAX_LUN; lun++) {
-			scsi_dev_desc[scsi_max_devs].lun = lun;
-			ret = scsi_detect_dev(i, &scsi_dev_desc[scsi_max_devs]);
+			ret = scsi_detect_dev(i, lun,
+					      &scsi_dev_desc[scsi_max_devs]);
 			if (ret)
 				continue;
+			part_init(&scsi_dev_desc[scsi_max_devs]);
 
 			if (mode == 1) {
 				printf("  Device %d: ", 0);
diff --git a/configs/sama5d3_xplained_mmc_defconfig b/configs/sama5d3_xplained_mmc_defconfig
index 2654aa1..d28d1d9 100644
--- a/configs/sama5d3_xplained_mmc_defconfig
+++ b/configs/sama5d3_xplained_mmc_defconfig
@@ -4,15 +4,19 @@
 CONFIG_SPL_GPIO_SUPPORT=y
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_SPL_MMC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
+CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_FAT_SUPPORT=y
+CONFIG_DEFAULT_DEVICE_TREE="at91-sama5d3_xplained"
 CONFIG_FIT=y
 CONFIG_SYS_EXTRA_OPTIONS="SAMA5D3,SYS_USE_MMC"
 CONFIG_BOOTDELAY=3
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_SPL=y
+CONFIG_SPL_SEPARATE_BSS=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMI is not set
@@ -29,6 +33,35 @@
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_UBI=y
+CONFIG_OF_CONTROL=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_SPL_REMOVE_PROPS="interrupts interrupt-parent dmas dma-names"
+CONFIG_DM=y
+CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_CLK_AT91=y
+CONFIG_AT91_UTMI=y
+CONFIG_AT91_H32MX=y
+CONFIG_DM_GPIO=y
+CONFIG_AT91_GPIO=y
+CONFIG_DM_MMC=y
+CONFIG_GENERIC_ATMEL_MCI=y
+CONFIG_DM_ETH=y
+CONFIG_MACB=y
+CONFIG_PINCTRL=y
+CONFIG_SPL_PINCTRL=y
+CONFIG_PINCTRL_AT91=y
+CONFIG_DM_SERIAL=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_ATMEL=y
+CONFIG_DEBUG_UART_BASE=0xffffee00
+CONFIG_DEBUG_UART_CLOCK=132000000
+CONFIG_DEBUG_UART_BOARD_INIT=y
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_ATMEL_USART=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
-CONFIG_OF_LIBFDT=y
diff --git a/configs/sama5d3_xplained_nandflash_defconfig b/configs/sama5d3_xplained_nandflash_defconfig
index dc487d9..8cc8169 100644
--- a/configs/sama5d3_xplained_nandflash_defconfig
+++ b/configs/sama5d3_xplained_nandflash_defconfig
@@ -6,6 +6,9 @@
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
+CONFIG_DEFAULT_DEVICE_TREE="at91-sama5d3_xplained"
 CONFIG_FIT=y
 CONFIG_SYS_EXTRA_OPTIONS="SAMA5D3,SYS_USE_NANDFLASH"
 CONFIG_BOOTDELAY=3
@@ -27,6 +30,35 @@
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_UBI=y
+CONFIG_OF_CONTROL=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_SPL_REMOVE_PROPS="interrupts interrupt-parent dmas dma-names"
+CONFIG_DM=y
+CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_CLK_AT91=y
+CONFIG_AT91_UTMI=y
+CONFIG_AT91_H32MX=y
+CONFIG_DM_GPIO=y
+CONFIG_AT91_GPIO=y
+CONFIG_DM_MMC=y
+CONFIG_GENERIC_ATMEL_MCI=y
+CONFIG_DM_ETH=y
+CONFIG_MACB=y
+CONFIG_PINCTRL=y
+CONFIG_SPL_PINCTRL=y
+CONFIG_PINCTRL_AT91=y
+CONFIG_DM_SERIAL=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_ATMEL=y
+CONFIG_DEBUG_UART_BASE=0xffffee00
+CONFIG_DEBUG_UART_CLOCK=132000000
+CONFIG_DEBUG_UART_BOARD_INIT=y
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_ATMEL_USART=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
-CONFIG_OF_LIBFDT=y
diff --git a/configs/sama5d3xek_mmc_defconfig b/configs/sama5d3xek_mmc_defconfig
index b73d647..994bc04 100644
--- a/configs/sama5d3xek_mmc_defconfig
+++ b/configs/sama5d3xek_mmc_defconfig
@@ -4,10 +4,13 @@
 CONFIG_SPL_GPIO_SUPPORT=y
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_SPL_MMC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
+CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_FAT_SUPPORT=y
+CONFIG_DEFAULT_DEVICE_TREE="sama5d36ek"
 CONFIG_FIT=y
 CONFIG_SYS_EXTRA_OPTIONS="SAMA5D3,SYS_USE_MMC"
 CONFIG_BOOTDELAY=3
@@ -15,6 +18,7 @@
 CONFIG_SYS_CONSOLE_IS_IN_ENV=y
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_SPL=y
+CONFIG_SPL_SEPARATE_BSS=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMI is not set
@@ -26,13 +30,47 @@
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
+CONFIG_OF_CONTROL=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_SPL_REMOVE_PROPS="interrupts interrupt-parent dmas dma-names"
+CONFIG_DM=y
+CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_CLK_AT91=y
+CONFIG_AT91_UTMI=y
+CONFIG_AT91_H32MX=y
+CONFIG_DM_GPIO=y
+CONFIG_AT91_GPIO=y
+CONFIG_DM_MMC=y
+CONFIG_GENERIC_ATMEL_MCI=y
 CONFIG_MTD_NOR_FLASH=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_ATMEL=y
+CONFIG_DM_ETH=y
+CONFIG_MACB=y
+CONFIG_PINCTRL=y
+CONFIG_SPL_PINCTRL=y
+CONFIG_PINCTRL_AT91=y
+CONFIG_DM_SERIAL=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_ATMEL=y
+CONFIG_DEBUG_UART_BASE=0xffffee00
+CONFIG_DEBUG_UART_CLOCK=132000000
+CONFIG_DEBUG_UART_BOARD_INIT=y
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_ATMEL_USART=y
+CONFIG_DM_SPI=y
+CONFIG_ATMEL_SPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_ATMEL_USBA=y
 CONFIG_LCD=y
-CONFIG_OF_LIBFDT=y
diff --git a/configs/sama5d3xek_nandflash_defconfig b/configs/sama5d3xek_nandflash_defconfig
index 7f68d7d..dd0263c 100644
--- a/configs/sama5d3xek_nandflash_defconfig
+++ b/configs/sama5d3xek_nandflash_defconfig
@@ -4,8 +4,11 @@
 CONFIG_SPL_GPIO_SUPPORT=y
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_SPL_SERIAL_SUPPORT=y
+CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
+CONFIG_DEFAULT_DEVICE_TREE="sama5d36ek"
 CONFIG_FIT=y
 CONFIG_SYS_EXTRA_OPTIONS="SAMA5D3,SYS_USE_NANDFLASH"
 CONFIG_BOOTDELAY=3
@@ -25,12 +28,44 @@
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
 CONFIG_CMD_FAT=y
+CONFIG_OF_CONTROL=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_SPL_REMOVE_PROPS="interrupts interrupt-parent dmas dma-names"
+CONFIG_DM=y
+CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_CLK_AT91=y
+CONFIG_AT91_UTMI=y
+CONFIG_AT91_H32MX=y
+CONFIG_DM_GPIO=y
+CONFIG_AT91_GPIO=y
+CONFIG_DM_MMC=y
+CONFIG_GENERIC_ATMEL_MCI=y
 CONFIG_MTD_NOR_FLASH=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_ATMEL=y
+CONFIG_DM_ETH=y
+CONFIG_MACB=y
+CONFIG_PINCTRL=y
+CONFIG_SPL_PINCTRL=y
+CONFIG_PINCTRL_AT91=y
+CONFIG_DM_SERIAL=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_ATMEL=y
+CONFIG_DEBUG_UART_BASE=0xffffee00
+CONFIG_DEBUG_UART_CLOCK=132000000
+CONFIG_DEBUG_UART_BOARD_INIT=y
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_ATMEL_USART=y
+CONFIG_DM_SPI=y
+CONFIG_ATMEL_SPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_ATMEL_USBA=y
 CONFIG_LCD=y
-CONFIG_OF_LIBFDT=y
diff --git a/configs/sama5d3xek_spiflash_defconfig b/configs/sama5d3xek_spiflash_defconfig
index c7a183f..069fbcc 100644
--- a/configs/sama5d3xek_spiflash_defconfig
+++ b/configs/sama5d3xek_spiflash_defconfig
@@ -4,20 +4,23 @@
 CONFIG_SPL_GPIO_SUPPORT=y
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_SPL_SERIAL_SUPPORT=y
+CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
+CONFIG_DEFAULT_DEVICE_TREE="sama5d36ek"
 CONFIG_FIT=y
 CONFIG_SYS_EXTRA_OPTIONS="SAMA5D3,SYS_USE_SERIALFLASH"
 CONFIG_BOOTDELAY=3
-# CONFIG_CONSOLE_MUX is not set
-CONFIG_SYS_CONSOLE_IS_IN_ENV=y
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_SPL=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMI is not set
+# CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_LOADS is not set
+# CONFIG_CMD_FLASH is not set
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_USB=y
@@ -26,12 +29,44 @@
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
 CONFIG_CMD_FAT=y
+CONFIG_OF_CONTROL=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_SPL_REMOVE_PROPS="interrupts interrupt-parent dmas dma-names"
+CONFIG_DM=y
+CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_CLK_AT91=y
+CONFIG_AT91_UTMI=y
+CONFIG_AT91_H32MX=y
+CONFIG_DM_GPIO=y
+CONFIG_AT91_GPIO=y
+CONFIG_DM_MMC=y
+CONFIG_GENERIC_ATMEL_MCI=y
 CONFIG_MTD_NOR_FLASH=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_ATMEL=y
+CONFIG_DM_ETH=y
+CONFIG_MACB=y
+CONFIG_PINCTRL=y
+CONFIG_SPL_PINCTRL=y
+CONFIG_PINCTRL_AT91=y
+CONFIG_DM_SERIAL=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_ATMEL=y
+CONFIG_DEBUG_UART_BASE=0xffffee00
+CONFIG_DEBUG_UART_CLOCK=132000000
+CONFIG_DEBUG_UART_BOARD_INIT=y
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_ATMEL_USART=y
+CONFIG_DM_SPI=y
+CONFIG_ATMEL_SPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_ATMEL_USBA=y
 CONFIG_LCD=y
-CONFIG_OF_LIBFDT=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 7f3f5ac..9814ea3 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -83,6 +83,7 @@
 CONFIG_CROS_EC_KEYB=y
 CONFIG_I8042_KEYB=y
 CONFIG_LED=y
+CONFIG_LED_BLINK=y
 CONFIG_LED_GPIO=y
 CONFIG_DM_MAILBOX=y
 CONFIG_SANDBOX_MBOX=y
diff --git a/configs/sandbox_noblk_defconfig b/configs/sandbox_noblk_defconfig
index 3f8e70d..bba7443 100644
--- a/configs/sandbox_noblk_defconfig
+++ b/configs/sandbox_noblk_defconfig
@@ -92,6 +92,7 @@
 CONFIG_CROS_EC_KEYB=y
 CONFIG_I8042_KEYB=y
 CONFIG_LED=y
+CONFIG_LED_BLINK=y
 CONFIG_LED_GPIO=y
 CONFIG_CROS_EC=y
 CONFIG_CROS_EC_I2C=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index ade6714..6fe2125 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -94,6 +94,7 @@
 CONFIG_CROS_EC_KEYB=y
 CONFIG_I8042_KEYB=y
 CONFIG_LED=y
+CONFIG_LED_BLINK=y
 CONFIG_LED_GPIO=y
 CONFIG_DM_MAILBOX=y
 CONFIG_SANDBOX_MBOX=y
diff --git a/drivers/led/Kconfig b/drivers/led/Kconfig
index 609b1fa..309372a 100644
--- a/drivers/led/Kconfig
+++ b/drivers/led/Kconfig
@@ -9,6 +9,15 @@
 	  can provide access to board-specific LEDs. Use of the device tree
 	  for configuration is encouraged.
 
+config LED_BLINK
+	bool "Support LED blinking"
+	depends on LED
+	help
+	  Some drivers can support automatic blinking of LEDs with a given
+	  period, without needing timers or extra code to handle the timing.
+	  This option enables support for this which adds slightly to the
+	  code size.
+
 config SPL_LED
 	bool "Enable LED support in SPL"
 	depends on SPL && SPL_DM
@@ -17,6 +26,7 @@
 	  If this is acceptable and you have a need to use LEDs in SPL,
 	  enable this option. You will need to enable device tree in SPL
 	  for this to work.
+
 config LED_GPIO
 	bool "LED support for GPIO-connected LEDs"
 	depends on LED && DM_GPIO
diff --git a/drivers/led/led-uclass.c b/drivers/led/led-uclass.c
index 784ac87..78ab760 100644
--- a/drivers/led/led-uclass.c
+++ b/drivers/led/led-uclass.c
@@ -22,7 +22,7 @@
 	if (ret)
 		return ret;
 	uclass_foreach_dev(dev, uc) {
-		struct led_uclass_plat *uc_plat = dev_get_uclass_platdata(dev);
+		struct led_uc_plat *uc_plat = dev_get_uclass_platdata(dev);
 
 		/* Ignore the top-level LED node */
 		if (uc_plat->label && !strcmp(label, uc_plat->label))
@@ -32,18 +32,40 @@
 	return -ENODEV;
 }
 
-int led_set_on(struct udevice *dev, int on)
+int led_set_state(struct udevice *dev, enum led_state_t state)
 {
 	struct led_ops *ops = led_get_ops(dev);
 
-	if (!ops->set_on)
+	if (!ops->set_state)
 		return -ENOSYS;
 
-	return ops->set_on(dev, on);
+	return ops->set_state(dev, state);
 }
 
+enum led_state_t led_get_state(struct udevice *dev)
+{
+	struct led_ops *ops = led_get_ops(dev);
+
+	if (!ops->get_state)
+		return -ENOSYS;
+
+	return ops->get_state(dev);
+}
+
+#ifdef CONFIG_LED_BLINK
+int led_set_period(struct udevice *dev, int period_ms)
+{
+	struct led_ops *ops = led_get_ops(dev);
+
+	if (!ops->set_period)
+		return -ENOSYS;
+
+	return ops->set_period(dev, period_ms);
+}
+#endif
+
 UCLASS_DRIVER(led) = {
 	.id		= UCLASS_LED,
 	.name		= "led",
-	.per_device_platdata_auto_alloc_size = sizeof(struct led_uclass_plat),
+	.per_device_platdata_auto_alloc_size = sizeof(struct led_uc_plat),
 };
diff --git a/drivers/led/led_gpio.c b/drivers/led/led_gpio.c
index 5b11990..4106ecb 100644
--- a/drivers/led/led_gpio.c
+++ b/drivers/led/led_gpio.c
@@ -18,19 +18,47 @@
 	struct gpio_desc gpio;
 };
 
-static int gpio_led_set_on(struct udevice *dev, int on)
+static int gpio_led_set_state(struct udevice *dev, enum led_state_t state)
 {
 	struct led_gpio_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	if (!dm_gpio_is_valid(&priv->gpio))
+		return -EREMOTEIO;
+	switch (state) {
+	case LEDST_OFF:
+	case LEDST_ON:
+		break;
+	case LEDST_TOGGLE:
+		ret = dm_gpio_get_value(&priv->gpio);
+		if (ret < 0)
+			return ret;
+		state = !ret;
+		break;
+	default:
+		return -ENOSYS;
+	}
+
+	return dm_gpio_set_value(&priv->gpio, state);
+}
+
+static enum led_state_t gpio_led_get_state(struct udevice *dev)
+{
+	struct led_gpio_priv *priv = dev_get_priv(dev);
+	int ret;
 
 	if (!dm_gpio_is_valid(&priv->gpio))
 		return -EREMOTEIO;
+	ret = dm_gpio_get_value(&priv->gpio);
+	if (ret < 0)
+		return ret;
 
-	return dm_gpio_set_value(&priv->gpio, on);
+	return ret ? LEDST_ON : LEDST_OFF;
 }
 
 static int led_gpio_probe(struct udevice *dev)
 {
-	struct led_uclass_plat *uc_plat = dev_get_uclass_platdata(dev);
+	struct led_uc_plat *uc_plat = dev_get_uclass_platdata(dev);
 	struct led_gpio_priv *priv = dev_get_priv(dev);
 
 	/* Ignore the top-level LED node */
@@ -65,7 +93,7 @@
 	for (node = fdt_first_subnode(blob, dev_of_offset(parent));
 	     node > 0;
 	     node = fdt_next_subnode(blob, node)) {
-		struct led_uclass_plat *uc_plat;
+		struct led_uc_plat *uc_plat;
 		const char *label;
 
 		label = fdt_getprop(blob, node, "label", NULL);
@@ -87,7 +115,8 @@
 }
 
 static const struct led_ops gpio_led_ops = {
-	.set_on		= gpio_led_set_on,
+	.set_state	= gpio_led_set_state,
+	.get_state	= gpio_led_get_state,
 };
 
 static const struct udevice_id led_gpio_ids[] = {
diff --git a/include/configs/sama5d3_xplained.h b/include/configs/sama5d3_xplained.h
index 3c9f49e..b4a62bd 100644
--- a/include/configs/sama5d3_xplained.h
+++ b/include/configs/sama5d3_xplained.h
@@ -12,11 +12,6 @@
 
 #include "at91-sama5_common.h"
 
-/* serial console */
-#define CONFIG_ATMEL_USART
-#define CONFIG_USART_BASE		ATMEL_BASE_DBGU
-#define CONFIG_USART_ID			ATMEL_ID_DBGU
-
 /*
  * This needs to be defined for the OHCI code to work but it is defined as
  * ATMEL_ID_UHPHS in the CPU specific header files.
@@ -34,10 +29,10 @@
 #define CONFIG_SYS_SDRAM_SIZE		0x10000000
 
 #ifdef CONFIG_SPL_BUILD
-#define CONFIG_SYS_INIT_SP_ADDR		0x310000
+#define CONFIG_SYS_INIT_SP_ADDR		0x318000
 #else
 #define CONFIG_SYS_INIT_SP_ADDR \
-	(CONFIG_SYS_SDRAM_BASE + 4 * 1024 - GENERATED_GBL_DATA_SIZE)
+	(CONFIG_SYS_SDRAM_BASE + 16 * 1024 - GENERATED_GBL_DATA_SIZE)
 #endif
 
 /* NAND flash */
@@ -67,21 +62,6 @@
 #define CONFIG_CMD_UBIFS
 #endif
 
-/* Ethernet Hardware */
-#define CONFIG_MACB
-#define CONFIG_RMII
-#define CONFIG_NET_RETRY_COUNT		20
-#define CONFIG_MACB_SEARCH_PHY
-#define CONFIG_RGMII
-#define CONFIG_PHYLIB
-
-/* MMC */
-
-#ifdef CONFIG_CMD_MMC
-#define CONFIG_GENERIC_ATMEL_MCI
-#define CONFIG_ATMEL_MCI_8BIT
-#endif
-
 /* USB */
 
 #ifdef CONFIG_CMD_USB
@@ -111,7 +91,7 @@
 /* SPL */
 #define CONFIG_SPL_FRAMEWORK
 #define CONFIG_SPL_TEXT_BASE		0x300000
-#define CONFIG_SPL_MAX_SIZE		0x10000
+#define CONFIG_SPL_MAX_SIZE		0x18000
 #define CONFIG_SPL_BSS_START_ADDR	0x20000000
 #define CONFIG_SPL_BSS_MAX_SIZE		0x80000
 #define CONFIG_SYS_SPL_MALLOC_START	0x20080000
diff --git a/include/configs/sama5d3xek.h b/include/configs/sama5d3xek.h
index 13790e7..6c28c4c 100644
--- a/include/configs/sama5d3xek.h
+++ b/include/configs/sama5d3xek.h
@@ -17,11 +17,6 @@
 
 #define CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
 
-/* serial console */
-#define CONFIG_ATMEL_USART
-#define CONFIG_USART_BASE		ATMEL_BASE_DBGU
-#define	CONFIG_USART_ID			ATMEL_ID_DBGU
-
 /*
  * This needs to be defined for the OHCI code to work but it is defined as
  * ATMEL_ID_UHPHS in the CPU specific header files.
@@ -62,16 +57,15 @@
 #define CONFIG_SYS_SDRAM_SIZE		0x20000000
 
 #ifdef CONFIG_SPL_BUILD
-#define CONFIG_SYS_INIT_SP_ADDR		0x310000
+#define CONFIG_SYS_INIT_SP_ADDR		0x318000
 #else
 #define CONFIG_SYS_INIT_SP_ADDR \
-	(CONFIG_SYS_SDRAM_BASE + 4 * 1024 - GENERATED_GBL_DATA_SIZE)
+	(CONFIG_SYS_SDRAM_BASE + 16 * 1024 - GENERATED_GBL_DATA_SIZE)
 #endif
 
 /* SerialFlash */
 
 #ifdef CONFIG_CMD_SF
-#define CONFIG_ATMEL_SPI
 #define CONFIG_SF_DEFAULT_SPEED		30000000
 #endif
 
@@ -95,27 +89,11 @@
 #define CONFIG_CMD_NAND_TRIMFFS
 #endif
 
-/* Ethernet Hardware */
-#define CONFIG_MACB
-#define CONFIG_RMII
-#define CONFIG_NET_RETRY_COUNT		20
-#define CONFIG_MACB_SEARCH_PHY
-#define CONFIG_RGMII
-#define CONFIG_PHYLIB
-#define CONFIG_PHY_MICREL
 #define CONFIG_PHY_MICREL_KSZ9021
 
-/* MMC */
-
-#ifdef CONFIG_CMD_MMC
-#define CONFIG_GENERIC_ATMEL_MCI
-#define ATMEL_BASE_MMCI			ATMEL_BASE_MCI0
-#endif
-
 /* USB */
 
 #ifdef CONFIG_CMD_USB
-#define CONFIG_USB_ATMEL
 #define CONFIG_USB_ATMEL_CLK_SEL_UPLL
 #define CONFIG_USB_OHCI_NEW
 #define CONFIG_SYS_USB_OHCI_CPU_INIT
@@ -124,11 +102,6 @@
 #define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS	3
 #endif
 
-/* USB device */
-#define CONFIG_USB_ETHER
-#define CONFIG_USB_ETH_RNDIS
-#define CONFIG_USBNET_MANUFACTURER      "Atmel SAMA5D3xEK"
-
 #if defined(CONFIG_CMD_USB) || defined(CONFIG_CMD_MMC)
 #define CONFIG_FAT_WRITE
 #endif
@@ -148,7 +121,7 @@
 /* SPL */
 #define CONFIG_SPL_FRAMEWORK
 #define CONFIG_SPL_TEXT_BASE		0x300000
-#define CONFIG_SPL_MAX_SIZE		0x10000
+#define CONFIG_SPL_MAX_SIZE		0x18000
 #define CONFIG_SPL_BSS_START_ADDR	0x20000000
 #define CONFIG_SPL_BSS_MAX_SIZE		0x80000
 #define CONFIG_SYS_SPL_MALLOC_START	0x20080000
@@ -176,7 +149,7 @@
 
 #elif CONFIG_SYS_USE_SERIALFLASH
 #define CONFIG_SPL_SPI_LOAD
-#define CONFIG_SYS_SPI_U_BOOT_OFFS	0x8000
+#define CONFIG_SYS_SPI_U_BOOT_OFFS	0x10000
 
 #endif
 
diff --git a/include/led.h b/include/led.h
index b929d0c..c67af22 100644
--- a/include/led.h
+++ b/include/led.h
@@ -9,23 +9,65 @@
 #define __LED_H
 
 /**
- * struct led_uclass_plat - Platform data the uclass stores about each device
+ * struct led_uc_plat - Platform data the uclass stores about each device
  *
  * @label:	LED label
  */
-struct led_uclass_plat {
+struct led_uc_plat {
 	const char *label;
 };
 
+/**
+ * struct led_uc_priv - Private data the uclass stores about each device
+ *
+ * @period_ms:	Flash period in milliseconds
+ */
+struct led_uc_priv {
+	int period_ms;
+};
+
+enum led_state_t {
+	LEDST_OFF = 0,
+	LEDST_ON = 1,
+	LEDST_TOGGLE,
+#ifdef CONFIG_LED_BLINK
+	LEDST_BLINK,
+#endif
+
+	LEDST_COUNT,
+};
+
 struct led_ops {
 	/**
-	 * set_on() - set the state of an LED
+	 * set_state() - set the state of an LED
 	 *
 	 * @dev:	LED device to change
-	 * @on:		1 to turn the LED on, 0 to turn it off
+	 * @state:	LED state to set
 	 * @return 0 if OK, -ve on error
 	 */
-	int (*set_on)(struct udevice *dev, int on);
+	int (*set_state)(struct udevice *dev, enum led_state_t state);
+
+	/**
+	 * led_get_state() - get the state of an LED
+	 *
+	 * @dev:	LED device to change
+	 * @return LED state led_state_t, or -ve on error
+	 */
+	enum led_state_t (*get_state)(struct udevice *dev);
+
+#ifdef CONFIG_LED_BLINK
+	/**
+	 * led_set_period() - set the blink period of an LED
+	 *
+	 * Thie records the period if supported, or returns -ENOSYS if not.
+	 * To start the LED blinking, use set_state().
+	 *
+	 * @dev:	LED device to change
+	 * @period_ms:	LED blink period in milliseconds
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*set_period)(struct udevice *dev, int period_ms);
+#endif
 };
 
 #define led_get_ops(dev)	((struct led_ops *)(dev)->driver->ops)
@@ -40,12 +82,29 @@
 int led_get_by_label(const char *label, struct udevice **devp);
 
 /**
+ * led_set_state() - set the state of an LED
+ *
+ * @dev:	LED device to change
+ * @state:	LED state to set
+ * @return 0 if OK, -ve on error
+ */
+int led_set_state(struct udevice *dev, enum led_state_t state);
+
+/**
+ * led_get_state() - get the state of an LED
+ *
+ * @dev:	LED device to change
+ * @return LED state led_state_t, or -ve on error
+ */
+enum led_state_t led_get_state(struct udevice *dev);
+
+/**
- * led_set_on() - set the state of an LED
+ * led_set_period() - set the blink period of an LED
  *
  * @dev:	LED device to change
- * @on:		1 to turn the LED on, 0 to turn it off
+ * @period_ms:	LED blink period in milliseconds
  * @return 0 if OK, -ve on error
  */
-int led_set_on(struct udevice *dev, int on);
+int led_set_period(struct udevice *dev, int period_ms);
 
 #endif
diff --git a/test/dm/led.c b/test/dm/led.c
index 8ee075c..fde700b 100644
--- a/test/dm/led.c
+++ b/test/dm/led.c
@@ -41,15 +41,43 @@
 	ut_assertok(uclass_get_device(UCLASS_LED, 1, &dev));
 	ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio));
 	ut_asserteq(0, sandbox_gpio_get_value(gpio, offset));
-	led_set_on(dev, 1);
+	ut_assertok(led_set_state(dev, LEDST_ON));
 	ut_asserteq(1, sandbox_gpio_get_value(gpio, offset));
-	led_set_on(dev, 0);
+	ut_asserteq(LEDST_ON, led_get_state(dev));
+
+	ut_assertok(led_set_state(dev, LEDST_OFF));
 	ut_asserteq(0, sandbox_gpio_get_value(gpio, offset));
+	ut_asserteq(LEDST_OFF, led_get_state(dev));
 
 	return 0;
 }
 DM_TEST(dm_test_led_gpio, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
 
+/* Test that we can toggle LEDs */
+static int dm_test_led_toggle(struct unit_test_state *uts)
+{
+	const int offset = 1;
+	struct udevice *dev, *gpio;
+
+	/*
+	 * Check that we can manipulate an LED. LED 1 is connected to GPIO
+	 * bank gpio_a, offset 1.
+	 */
+	ut_assertok(uclass_get_device(UCLASS_LED, 1, &dev));
+	ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio));
+	ut_asserteq(0, sandbox_gpio_get_value(gpio, offset));
+	ut_assertok(led_set_state(dev, LEDST_TOGGLE));
+	ut_asserteq(1, sandbox_gpio_get_value(gpio, offset));
+	ut_asserteq(LEDST_ON, led_get_state(dev));
+
+	ut_assertok(led_set_state(dev, LEDST_TOGGLE));
+	ut_asserteq(0, sandbox_gpio_get_value(gpio, offset));
+	ut_asserteq(LEDST_OFF, led_get_state(dev));
+
+	return 0;
+}
+DM_TEST(dm_test_led_toggle, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
 /* Test obtaining an LED by label */
 static int dm_test_led_label(struct unit_test_state *uts)
 {
@@ -70,3 +98,27 @@
 	return 0;
 }
 DM_TEST(dm_test_led_label, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test LED blinking */
+#ifdef CONFIG_LED_BLINK
+static int dm_test_led_blink(struct unit_test_state *uts)
+{
+	const int offset = 1;
+	struct udevice *dev, *gpio;
+
+	/*
+	 * Check that we get an error when trying to blink an LED, since it is
+	 * not supported by the GPIO LED driver.
+	 */
+	ut_assertok(uclass_get_device(UCLASS_LED, 1, &dev));
+	ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio));
+	ut_asserteq(0, sandbox_gpio_get_value(gpio, offset));
+	ut_asserteq(-ENOSYS, led_set_state(dev, LEDST_BLINK));
+	ut_asserteq(0, sandbox_gpio_get_value(gpio, offset));
+	ut_asserteq(LEDST_OFF, led_get_state(dev));
+	ut_asserteq(-ENOSYS, led_set_period(dev, 100));
+
+	return 0;
+}
+DM_TEST(dm_test_led_blink, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+#endif