Merge git://git.denx.de/u-boot-rockchip
diff --git a/MAINTAINERS b/MAINTAINERS
index d459153..0c7efde 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -92,14 +92,17 @@
 F:	arch/arm/mach-at91/
 
 ARM BROADCOM BCM283X
-#M:	Stephen Warren <swarren@wwwdotorg.org>
-S:	Orphaned (Since 2017-07)
+M:	Alexander Graf <agraf@suse.de>
+S:	Maintained
 F:	arch/arm/mach-bcm283x/
 F:	drivers/gpio/bcm2835_gpio.c
 F:	drivers/mmc/bcm2835_sdhci.c
+F:	drivers/mmc/bcm2835_sdhost.c
 F:	drivers/serial/serial_bcm283x_mu.c
+F:	drivers/serial/serial_bcm283x_pl011.c
 F:	drivers/video/bcm2835.c
 F:	include/dm/platform_data/serial_bcm283x_mu.h
+F:	drivers/pinctrl/broadcom/
 
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 73fbd54..30a6f6d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -348,6 +348,7 @@
 config TARGET_EDB93XX
 	bool "Support edb93xx"
 	select CPU_ARM920T
+	select PL010_SERIAL
 
 config TARGET_ASPENITE
 	bool "Support aspenite"
@@ -399,49 +400,58 @@
 	bool "Support apx4devkit"
 	select CPU_ARM926EJS
 	select SUPPORT_SPL
+	select PL011_SERIAL
 
 config TARGET_XFI3
 	bool "Support xfi3"
 	select CPU_ARM926EJS
 	select SUPPORT_SPL
+	select PL011_SERIAL
 
 config TARGET_M28EVK
 	bool "Support m28evk"
 	select CPU_ARM926EJS
 	select SUPPORT_SPL
+	select PL011_SERIAL
 
 config TARGET_MX23EVK
 	bool "Support mx23evk"
 	select CPU_ARM926EJS
 	select SUPPORT_SPL
 	select BOARD_EARLY_INIT_F
+	select PL011_SERIAL
 
 config TARGET_MX28EVK
 	bool "Support mx28evk"
 	select CPU_ARM926EJS
 	select SUPPORT_SPL
 	select BOARD_EARLY_INIT_F
+	select PL011_SERIAL
 
 config TARGET_MX23_OLINUXINO
 	bool "Support mx23_olinuxino"
 	select CPU_ARM926EJS
 	select SUPPORT_SPL
 	select BOARD_EARLY_INIT_F
+	select PL011_SERIAL
 
 config TARGET_BG0900
 	bool "Support bg0900"
 	select CPU_ARM926EJS
 	select SUPPORT_SPL
+	select PL011_SERIAL
 
 config TARGET_SANSA_FUZE_PLUS
 	bool "Support sansa_fuze_plus"
 	select CPU_ARM926EJS
 	select SUPPORT_SPL
+	select PL011_SERIAL
 
 config TARGET_SC_SPS_1
 	bool "Support sc_sps_1"
 	select CPU_ARM926EJS
 	select SUPPORT_SPL
+	select PL011_SERIAL
 
 config ORION5X
 	bool "Marvell Orion"
@@ -452,24 +462,28 @@
 	select CPU_ARM926EJS
 	select BOARD_EARLY_INIT_F
 	imply CMD_SAVES
+	select PL011_SERIAL
 
 config TARGET_SPEAR310
 	bool "Support spear310"
 	select CPU_ARM926EJS
 	select BOARD_EARLY_INIT_F
 	imply CMD_SAVES
+	select PL011_SERIAL
 
 config TARGET_SPEAR320
 	bool "Support spear320"
 	select CPU_ARM926EJS
 	select BOARD_EARLY_INIT_F
 	imply CMD_SAVES
+	select PL011_SERIAL
 
 config TARGET_SPEAR600
 	bool "Support spear600"
 	select CPU_ARM926EJS
 	select BOARD_EARLY_INIT_F
 	imply CMD_SAVES
+	select PL011_SERIAL
 
 config TARGET_STV0991
 	bool "Support stv0991"
@@ -479,12 +493,14 @@
 	select DM_SPI
 	select DM_SPI_FLASH
 	select SPI_FLASH
+	select PL01X_SERIAL
 
 config TARGET_X600
 	bool "Support x600"
 	select BOARD_LATE_INIT
 	select CPU_ARM926EJS
 	select SUPPORT_SPL
+	select PL011_SERIAL
 
 config TARGET_IMX31_PHYCORE
 	bool "Support imx31_phycore_eet"
@@ -533,6 +549,7 @@
 	select DM_SERIAL
 	select DM_GPIO
 	select OF_CONTROL
+	select PL01X_SERIAL
 	imply FAT_WRITE
 
 config TARGET_VEXPRESS_CA15_TC2
@@ -540,14 +557,17 @@
 	select CPU_V7
 	select CPU_V7_HAS_NONSEC
 	select CPU_V7_HAS_VIRT
+	select PL011_SERIAL
 
 config TARGET_VEXPRESS_CA5X2
 	bool "Support vexpress_ca5x2"
 	select CPU_V7
+	select PL011_SERIAL
 
 config TARGET_VEXPRESS_CA9X4
 	bool "Support vexpress_ca9x4"
 	select CPU_V7
+	select PL011_SERIAL
 
 config TARGET_BCM23550_W1D
 	bool "Support bcm23550_w1d"
@@ -606,11 +626,13 @@
 config ARCH_HIGHBANK
 	bool "Calxeda Highbank"
 	select CPU_V7
+	select PL011_SERIAL
 
 config ARCH_INTEGRATOR
 	bool "ARM Ltd. Integrator family"
 	select DM
 	select DM_SERIAL
+	select PL01X_SERIAL
 
 config ARCH_KEYSTONE
 	bool "TI Keystone"
@@ -678,6 +700,7 @@
 	select DM
 	select DM_SERIAL
 	select OF_CONTROL
+	select PL01X_SERIAL
 
 config ARCH_RMOBILE
 	bool "Renesas ARM SoCs"
@@ -761,6 +784,7 @@
 	bool "Support TS4600"
 	select CPU_ARM926EJS
 	select SUPPORT_SPL
+	select PL011_SERIAL
 
 config ARCH_VF610
 	bool "Freescale Vybrid"
@@ -816,15 +840,18 @@
 config TARGET_VEXPRESS64_AEMV8A
 	bool "Support vexpress_aemv8a"
 	select ARM64
+	select PL01X_SERIAL
 
 config TARGET_VEXPRESS64_BASE_FVP
 	bool "Support Versatile Express ARMv8a FVP BASE model"
 	select ARM64
 	select SEMIHOSTING
+	select PL01X_SERIAL
 
 config TARGET_VEXPRESS64_BASE_FVP_DRAM
 	bool "Support Versatile Express ARMv8a FVP BASE model booting from DRAM"
 	select ARM64
+	select PL01X_SERIAL
 	help
 	  This target is derived from TARGET_VEXPRESS64_BASE_FVP and over-rides
 	  the default config to allow the user to load the images directly into
@@ -834,6 +861,7 @@
 config TARGET_VEXPRESS64_JUNO
 	bool "Support Versatile Express Juno Development Platform"
 	select ARM64
+	select PL01X_SERIAL
 
 config TARGET_LS2080A_EMU
 	bool "Support ls2080a_emu"
@@ -926,6 +954,7 @@
 	select DM_GPIO
 	select DM_SERIAL
 	select OF_CONTROL
+	select PL01X_SERIAL
 	  help
 	  Support for HiKey 96boards platform. It features a HI6220
 	  SoC, with 8xA53 CPU, mali450 gpu, and 1GB RAM.
@@ -937,6 +966,7 @@
 	select OF_CONTROL
 	select DM_SERIAL
 	select DM_USB
+	select PL01X_SERIAL
 	  help
 	  Support for Poplar 96boards EE platform. It features a HI3798cv200
 	  SoC, with 4xA53 CPU, 1GB RAM and the high performance Mali T720 GPU
@@ -1192,6 +1222,7 @@
 	select ARM64
 	select OF_CONTROL
 	select SYS_CACHE_SHIFT_7
+	select PL01X_SERIAL
 
 config ARCH_ASPEED
 	bool "Support Aspeed SoCs"
@@ -1291,6 +1322,7 @@
 source "board/cavium/thunderx/Kconfig"
 source "board/cirrus/edb93xx/Kconfig"
 source "board/creative/xfi3/Kconfig"
+source "board/eets/pdu001/Kconfig"
 source "board/freescale/ls2080a/Kconfig"
 source "board/freescale/ls2080aqds/Kconfig"
 source "board/freescale/ls2080ardb/Kconfig"
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 9540ba4..da0ae0d 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -161,7 +161,8 @@
 	am335x-bonegreen.dtb \
 	am335x-icev2.dtb \
 	am335x-pxm50.dtb \
-	am335x-rut.dtb
+	am335x-rut.dtb \
+	am335x-pdu001.dtb
 dtb-$(CONFIG_AM43XX) += am437x-gp-evm.dtb am437x-sk-evm.dtb	\
 	am43x-epos-evm.dtb \
 	am437x-idk-evm.dtb
@@ -217,6 +218,7 @@
 dtb-$(CONFIG_TARGET_DRAGONBOARD820C) += dragonboard820c.dtb
 
 dtb-$(CONFIG_STM32F4) += stm32f429-disco.dtb \
+	stm32429i-eval.dtb \
 	stm32f469-disco.dtb
 
 dtb-$(CONFIG_STM32F7) += stm32f746-disco.dtb \
diff --git a/arch/arm/dts/am335x-pdu001-u-boot.dtsi b/arch/arm/dts/am335x-pdu001-u-boot.dtsi
new file mode 100644
index 0000000..0dcffd5
--- /dev/null
+++ b/arch/arm/dts/am335x-pdu001-u-boot.dtsi
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 EETS GmbH - https://www.eets.ch/
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/ {
+	ocp {
+		u-boot,dm-pre-reloc;
+	};
+};
+
+&l4_wkup {
+	u-boot,dm-pre-reloc;
+};
+
+&scm {
+	u-boot,dm-pre-reloc;
+};
+
+&am33xx_pinmux {
+	u-boot,dm-pre-reloc;
+};
+
+&uart3_pins {
+	u-boot,dm-pre-reloc;
+};
+
+&uart3 {
+	u-boot,dm-pre-reloc;
+};
+
+&mmc1_pins {
+	u-boot,dm-pre-reloc;
+};
+
+&mmc2_pins {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/am335x-pdu001.dts b/arch/arm/dts/am335x-pdu001.dts
new file mode 100644
index 0000000..bdf3b27
--- /dev/null
+++ b/arch/arm/dts/am335x-pdu001.dts
@@ -0,0 +1,595 @@
+/*
+ * pdu001.dts
+ *
+ * EETS GmbH PDU001 board device tree file
+ *
+ * Copyright (C) 2018 EETS GmbH - http://www.eets.ch/
+ *
+ * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/
+ *
+ * SPDX-License-Identifier:  GPL-2.0+
+ */
+
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/leds/leds-pca9532.h>
+
+/ {
+	model = "EETS,PDU001";
+	compatible = "eets,pdu001", "ti,am33xx";
+
+	chosen {
+		stdout-path = &uart3;
+	};
+
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&vdd1_reg>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	vbat: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbat";
+		regulator-min-microvolt = <3600000>;
+		regulator-max-microvolt = <3600000>;
+		regulator-boot-on;
+	};
+
+	lis3_reg: fixedregulator@1 {
+		compatible = "regulator-fixed";
+		regulator-name = "lis3_reg";
+		regulator-boot-on;
+	};
+
+	panel {
+		compatible = "ti,tilcdc,panel";
+		status = "okay";
+		pinctrl-names = "default";
+		pinctrl-0 = <&lcd_pins_s0>;
+		panel-info {
+			ac-bias           = <255>;
+			ac-bias-intrpt    = <0>;
+			dma-burst-sz      = <16>;
+			bpp               = <16>;
+			fdd               = <0x80>;
+			sync-edge         = <0>;
+			sync-ctrl         = <1>;
+			raster-order      = <0>;
+			fifo-th           = <0>;
+		};
+
+		display-timings {
+			240x320p16 {
+				clock-frequency = <6500000>;
+				hactive = <240>;
+				vactive = <320>;
+				hfront-porch = <6>;
+				hback-porch = <6>;
+				hsync-len = <1>;
+				vback-porch = <6>;
+				vfront-porch = <6>;
+				vsync-len = <1>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				pixelclk-active = <1>;
+				de-active = <0>;
+			};
+		};
+	};
+};
+
+&am33xx_pinmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&clkout2_pin>;
+
+	i2c0_pins: pinmux_i2c0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
+			AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
+		>;
+	};
+
+	i2c1_pins: pinmux_i2c1_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE2)	/* spi0_d1.i2c1_sda */
+			AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE2)	/* spi0_cs0.i2c1_scl */
+		>;
+	};
+
+	i2c2_pins: pinmux_i2c2_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE2)	/* spi0_clk.i2c2_sda */
+			AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE2)	/* spi0_d0.i2c2_scl */
+		>;
+	};
+
+	spi1_pins: pinmux_spi1_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x990, PIN_OUTPUT | MUX_MODE3)		/* mcasp0_aclkx.spi1_sclk */
+			AM33XX_IOPAD(0x994, PIN_OUTPUT | MUX_MODE3)		/* mcasp0_fsx.spi1_d0 */
+			AM33XX_IOPAD(0x998, PIN_INPUT_PULLDOWN | MUX_MODE3)	/* mcasp0_axr0.spi1_d1 */
+			AM33XX_IOPAD(0x99C, PIN_OUTPUT | MUX_MODE3)		/* mcasp0_ahclkr.spi1_cs0 */
+		>;
+	};
+
+	uart0_pins: pinmux_uart0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x96C, PIN_OUTPUT | MUX_MODE7)		/* uart0_rtsn.gpio1_9 */
+			AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart0_txd.uart0_txd */
+		>;
+	};
+
+	uart1_pins: pinmux_uart1_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0)	/* uart1_rxd.uart1_rxd */
+			AM33XX_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart1_txd.uart1_txd */
+		>;
+	};
+
+	uart3_pins: pinmux_uart3_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE1)	/* spi0_cs1.uart3_rxd */
+			AM33XX_IOPAD(0x964, PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* ecap0_in_pwm0_out.uart3_txd */
+		>;
+	};
+
+	clkout2_pin: pinmux_clkout2_pin {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x9b4, PIN_OUTPUT_PULLDOWN | MUX_MODE3)	/* xdma_event_intr1.clkout2 */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Port 1 (emac0) */
+			AM33XX_IOPAD(0x908, PIN_INPUT | MUX_MODE0)		/* mii1_col.mii1_col */
+			AM33XX_IOPAD(0x90C, PIN_INPUT | MUX_MODE0)		/* mii1_crs.mii1_crs */
+			AM33XX_IOPAD(0x910, PIN_INPUT | MUX_MODE0)		/* mii1_rxer.mii1_rxer */
+			AM33XX_IOPAD(0x914, PIN_OUTPUT | MUX_MODE0)		/* mii1_txen.mii1_txen */
+			AM33XX_IOPAD(0x918, PIN_INPUT | MUX_MODE0)		/* mii1_rxdv.mii1_rxdv */
+			AM33XX_IOPAD(0x91c, PIN_OUTPUT | MUX_MODE0)		/* mii1_txd3.mii1_txd3 */
+			AM33XX_IOPAD(0x920, PIN_OUTPUT | MUX_MODE0)		/* mii1_txd2.mii1_txd2 */
+			AM33XX_IOPAD(0x924, PIN_OUTPUT | MUX_MODE0)		/* mii1_txd1.mii1_txd1 */
+			AM33XX_IOPAD(0x928, PIN_OUTPUT | MUX_MODE0)		/* mii1_txd0.mii1_txd0 */
+			AM33XX_IOPAD(0x92c, PIN_INPUT | MUX_MODE0)		/* mii1_txclk.mii1_txclk */
+			AM33XX_IOPAD(0x930, PIN_INPUT | MUX_MODE0)		/* mii1_rxclk.mii1_rxclk */
+			AM33XX_IOPAD(0x934, PIN_INPUT | MUX_MODE0)		/* mii1_rxd3.mii1_rxd3 */
+			AM33XX_IOPAD(0x938, PIN_INPUT | MUX_MODE0)		/* mii1_rxd2.mii1_rxd2 */
+			AM33XX_IOPAD(0x93c, PIN_INPUT | MUX_MODE0)		/* mii1_rxd1.mii1_rxd1 */
+			AM33XX_IOPAD(0x940, PIN_INPUT | MUX_MODE0)		/* mii1_rxd0.mii1_rxd0 */
+
+			/* Port 2 (emac1) */
+			AM33XX_IOPAD(0x840, PIN_OUTPUT | MUX_MODE1)		/* mii2_txen.gpmc_a0 */
+			AM33XX_IOPAD(0x844, PIN_INPUT | MUX_MODE1)		/* mii2_rxdv.gpmc_a1 */
+			AM33XX_IOPAD(0x848, PIN_OUTPUT | MUX_MODE1)		/* mii2_txd3.gpmc_a2 */
+			AM33XX_IOPAD(0x84c, PIN_OUTPUT | MUX_MODE1)		/* mii2_txd2.gpmc_a3 */
+			AM33XX_IOPAD(0x850, PIN_OUTPUT | MUX_MODE1)		/* mii2_txd1.gpmc_a4 */
+			AM33XX_IOPAD(0x854, PIN_OUTPUT | MUX_MODE1)		/* mii2_txd0.gpmc_a5 */
+			AM33XX_IOPAD(0x858, PIN_INPUT | MUX_MODE1)		/* mii2_txclk.gpmc_a6 */
+			AM33XX_IOPAD(0x85c, PIN_INPUT | MUX_MODE1)		/* mii2_rxclk.gpmc_a7 */
+			AM33XX_IOPAD(0x860, PIN_INPUT | MUX_MODE1)		/* mii2_rxd3.gpmc_a8 */
+			AM33XX_IOPAD(0x864, PIN_INPUT | MUX_MODE1)		/* mii2_rxd2.gpmc_a9 */
+			AM33XX_IOPAD(0x868, PIN_INPUT | MUX_MODE1)		/* mii2_rxd1.gpmc_a10 */
+			AM33XX_IOPAD(0x86C, PIN_INPUT | MUX_MODE1)		/* mii2_rxd0.gpmc_a11 */
+			AM33XX_IOPAD(0x870, PIN_INPUT | MUX_MODE1)		/* mii2_crs.gpmc_wait0 */
+			AM33XX_IOPAD(0x874, PIN_INPUT | MUX_MODE1)		/* mii2_rxer.gpmc_wpn */
+			AM33XX_IOPAD(0x878, PIN_INPUT | MUX_MODE1)		/* mii2_col.gpmc_ben1 */
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+			AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	mmc1_pins: pinmux_mmc1_pins {
+		/* eMMC */
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat3 */
+			AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat2 */
+			AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat1 */
+			AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat0 */
+			AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_clk */
+			AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_cmd */
+		>;
+	};
+
+	mmc2_pins: pinmux_mmc2_pins {
+		/* SD cardcage */
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad3.mmc1_dat3 */
+			AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad2.mmc1_dat2 */
+			AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad1.mmc1_dat1 */
+			AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1)	/* gpmc_ad0.mmc1_dat0 */
+			AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2)	/* gpmc_csn1.mmc1_clk */
+			AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2)	/* gpmc_csn2.mmc1_cmd */
+			/* card change signal for frontpanel SD cardcage */
+			AM33XX_IOPAD(0x890, PIN_INPUT | MUX_MODE7)		/* gpmc_advn_ale.gpio2_2 */
+		>;
+	};
+
+	lcd_pins_s0: lcd_pins_s0 {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0)		/* lcd_data0.lcd_data0 */
+			AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0)		/* lcd_data1.lcd_data1 */
+			AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0)		/* lcd_data2.lcd_data2 */
+			AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0)		/* lcd_data3.lcd_data3 */
+			AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0)		/* lcd_data4.lcd_data4 */
+			AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0)		/* lcd_data5.lcd_data5 */
+			AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0)		/* lcd_data6.lcd_data6 */
+			AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0)		/* lcd_data7.lcd_data7 */
+			AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0)		/* lcd_data8.lcd_data8 */
+			AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0)		/* lcd_data9.lcd_data9 */
+			AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0)		/* lcd_data10.lcd_data10 */
+			AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0)		/* lcd_data11.lcd_data11 */
+			AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0)		/* lcd_data12.lcd_data12 */
+			AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0)		/* lcd_data13.lcd_data13 */
+			AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0)		/* lcd_data14.lcd_data14 */
+			AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0)		/* lcd_data15.lcd_data15 */
+			AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE0)		/* lcd_vsync.lcd_vsync */
+			AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE0)		/* lcd_hsync.lcd_hsync */
+			AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE0)		/* lcd_pclk.lcd_pclk */
+			AM33XX_IOPAD(0x8ec, PIN_OUTPUT | MUX_MODE0)		/* lcd_ac_bias_en.lcd_ac_bias_en */
+		>;
+	};
+
+	dcan0_pins: pinmux_dcan0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x978, PIN_OUTPUT | MUX_MODE2)		/* uart1_ctsn.d_can0_tx */
+			AM33XX_IOPAD(0x97c, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* uart1_rtsn.d_can0_rx */
+		>;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+
+	rts-gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+	rs485-rts-active-high;
+	rs485-rts-delay = <0 0>;
+	linux,rs485-enabled-at-boot-time;
+
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins>;
+
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+
+	status = "okay";
+	clock-frequency = <400000>;
+
+	tps: tps@2d {
+		reg = <0x2d>;
+	};
+
+	m2_eeprom: m2_eeprom@50 {
+		compatible = "atmel,24c256";
+		reg = <0x50>;
+		status = "okay";
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+
+	status = "okay";
+	clock-frequency = <100000>;
+
+	board_24aa025e48: board_24aa025e48@50 {
+		compatible = "microchip,24aa025e48";
+		reg = <0x50>;
+	};
+
+	backplane_24aa025e48: backplane_24aa025e48@53 {
+		compatible = "microchip,24aa025e48";
+		reg = <0x53>;
+	};
+
+	pca9532: pca9532@60 {
+		compatible = "nxp,pca9532";
+		reg = <0x60>;
+		psc0 = <0x97>;
+		pwm0 = <0x80>;
+		psc1 = <0x97>;
+		pwm1 = <0x10>;
+
+		run.red@0 {
+			type = <PCA9532_TYPE_LED>;
+		};
+		run.green@1 {
+			type = <PCA9532_TYPE_LED>;
+			default-state = "on";
+		};
+		s2.red@2 {
+			type = <PCA9532_TYPE_LED>;
+		};
+		s2.green@3 {
+			type = <PCA9532_TYPE_LED>;
+		};
+		s1.yellow@4 {
+			type = <PCA9532_TYPE_LED>;
+		};
+		s1.green@5 {
+			type = <PCA9532_TYPE_LED>;
+		};
+	};
+
+	pca9530: pca9530@61 {
+		compatible = "nxp,pca9530";
+		reg = <0x61>;
+
+		tft-panel@0 {
+			type = <PCA9532_TYPE_LED>;
+			linux,default-trigger = "backlight";
+			default-state = "on";
+		};
+	};
+
+	mcp79400: mcp79400@6f {
+		compatible = "microchip,mcp7940x";
+		reg = <0x6f>;
+	};
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_pins>;
+
+	status = "okay";
+	clock-frequency = <100000>;
+};
+
+&spi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi1_pins>;
+	ti,pindir-d0-out-d1-in;
+	status = "okay";
+
+	cfaf240320a032t {
+		compatible = "orise,otm3225a";
+		reg = <0>;
+		spi-max-frequency = <1000000>;
+		// SPI mode 3
+		spi-cpol;
+		spi-cpha;
+		status = "okay";
+	};
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb_ctrl_mod {
+	status = "okay";
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+};
+
+&usb1 {
+	status = "okay";
+};
+
+&cppi41dma  {
+	status = "okay";
+};
+
+/*
+ * Disable soc's rtc as we have no VBAT for it. This makes the board
+ * rtc (Microchip MCP79400) the default rtc device 'rtc0'.
+ */
+&rtc {
+	status = "disabled";
+};
+
+&lcdc {
+	status = "okay";
+};
+
+&elm {
+	status = "okay";
+};
+
+#include "tps65910.dtsi"
+
+&tps {
+	vcc1-supply = <&vbat>;
+	vcc2-supply = <&vbat>;
+	vcc3-supply = <&vbat>;
+	vcc4-supply = <&vbat>;
+	vcc5-supply = <&vbat>;
+	vcc6-supply = <&vbat>;
+	vcc7-supply = <&vbat>;
+	vccio-supply = <&vbat>;
+
+	regulators {
+		vrtc_reg: regulator@0 {
+			regulator-name = "ldo_vrtc";
+			regulator-always-on;
+		};
+
+		vio_reg: regulator@1 {
+			regulator-name = "buck_vdd_ddr";
+			regulator-always-on;
+		};
+
+		vdd1_reg: regulator@2 {
+			/* VDD_MPU voltage limits */
+			regulator-name = "buck_vdd_mpu";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1312500>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd2_reg: regulator@3 {
+			/* VDD_CORE voltage limits */
+			regulator-name = "buck_vdd_core";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1150000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd3_reg: regulator@4 {
+			regulator-name = "boost_res";
+			regulator-always-on;
+		};
+
+		vdig1_reg: regulator@5 {
+			regulator-name = "ldo_vdig1";
+			regulator-always-on;
+		};
+
+		vdig2_reg: regulator@6 {
+			regulator-name = "ldo_vdig2";
+			regulator-always-on;
+		};
+
+		vpll_reg: regulator@7 {
+			regulator-name = "ldo_vpll";
+			regulator-always-on;
+		};
+
+		vdac_reg: regulator@8 {
+			regulator-name = "ldo_vdac";
+			regulator-always-on;
+		};
+
+		vaux1_reg: regulator@9 {
+			regulator-name = "ldo_vaux1";
+			regulator-always-on;
+		};
+
+		vaux2_reg: regulator@10 {
+			regulator-name = "ldo_vaux2";
+			regulator-always-on;
+		};
+
+		vaux33_reg: regulator@11 {
+			regulator-name = "ldo_vaux33";
+			regulator-always-on;
+		};
+
+		vmmc_reg: regulator@12 {
+			regulator-name = "ldo_vmmc";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		vbb_reg: regulator@13 {
+			regulator-name = "bat_vbb";
+		};
+	};
+};
+
+&mac {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpsw_default>;
+	dual_emac;			/* no switch, two distinct MACs */
+	status = "okay";
+};
+
+&davinci_mdio {
+	pinctrl-names = "default";
+	pinctrl-0 = <&davinci_mdio_default>;
+	status = "okay";
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+	phy-mode = "mii";
+	dual_emac_res_vlan = <1>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <1>;
+	phy-mode = "mii";
+	dual_emac_res_vlan = <2>;
+};
+
+&tscadc {
+	status = "okay";
+	tsc {
+		ti,wires = <4>;
+		ti,x-plate-resistance = <200>;
+		ti,coordinate-readouts = <5>;
+		ti,wire-config = <0x01 0x10 0x22 0x33>;
+		ti,charge-delay = <0x400>;
+	};
+
+	adc {
+		ti,adc-channels = <4 5 6 7>;
+	};
+};
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&vmmc_reg>;
+	bus-width = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	non-removable;
+};
+
+&mmc2 {
+	status = "okay";
+	vmmc-supply = <&vmmc_reg>;
+	bus-width = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_pins>;
+	cd-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>;
+};
+
+&sham {
+	status = "okay";
+};
+
+&aes {
+	status = "okay";
+};
+
+&dcan0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&dcan0_pins>;
+};
diff --git a/arch/arm/dts/bcm283x-uboot.dtsi b/arch/arm/dts/bcm283x-uboot.dtsi
index 8e4231a..21d038a 100644
--- a/arch/arm/dts/bcm283x-uboot.dtsi
+++ b/arch/arm/dts/bcm283x-uboot.dtsi
@@ -20,3 +20,7 @@
 	skip-init;
 	u-boot,dm-pre-reloc;
 };
+
+&gpio {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/stm32429i-eval-u-boot.dtsi b/arch/arm/dts/stm32429i-eval-u-boot.dtsi
new file mode 100644
index 0000000..826c942
--- /dev/null
+++ b/arch/arm/dts/stm32429i-eval-u-boot.dtsi
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Author(s): Patrice Chotard, <patrice.chotard@st.com> for STMicroelectronics.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <dt-bindings/memory/stm32-sdram.h>
+/{
+	clocks {
+		u-boot,dm-pre-reloc;
+	};
+
+	aliases {
+		/* Aliases for gpios so as to use sequence */
+		gpio0 = &gpioa;
+		gpio1 = &gpiob;
+		gpio2 = &gpioc;
+		gpio3 = &gpiod;
+		gpio4 = &gpioe;
+		gpio5 = &gpiof;
+		gpio6 = &gpiog;
+		gpio7 = &gpioh;
+		gpio8 = &gpioi;
+		gpio9 = &gpioj;
+		gpio10 = &gpiok;
+	};
+
+	soc {
+		u-boot,dm-pre-reloc;
+		pin-controller {
+			u-boot,dm-pre-reloc;
+		};
+
+		fmc: fmc@A0000000 {
+			compatible = "st,stm32-fmc";
+			reg = <0xA0000000 0x1000>;
+			clocks = <&rcc 0 STM32F4_AHB3_CLOCK(FMC)>;
+			st,syscfg = <&syscfg>;
+			pinctrl-0 = <&fmc_pins_d32>;
+			pinctrl-names = "default";
+			st,mem_remap = <4>;
+			u-boot,dm-pre-reloc;
+
+			/*
+			 * Memory configuration from sdram
+			 * MICRON MT48LC4M32B2B5-7
+			 */
+			bank0: bank@0 {
+			       st,sdram-control = /bits/ 8 <NO_COL_9
+							    NO_ROW_12
+							    MWIDTH_32
+							    BANKS_4
+							    CAS_3
+							    SDCLK_2
+							    RD_BURST_EN
+							    RD_PIPE_DL_0>;
+			       st,sdram-timing = /bits/ 8 <TMRD_2
+							   TXSR_6
+							   TRAS_4
+							   TRC_6
+							   TWR_2
+							   TRP_2
+							   TRCD_2>;
+			       st,sdram-refcount = < 2812 >;
+		       };
+		};
+	};
+};
+
+&clk_hse {
+	u-boot,dm-pre-reloc;
+};
+
+&clk_lse {
+	u-boot,dm-pre-reloc;
+};
+
+&clk_i2s_ckin {
+	u-boot,dm-pre-reloc;
+};
+
+&pwrcfg {
+	u-boot,dm-pre-reloc;
+};
+
+&syscfg {
+	u-boot,dm-pre-reloc;
+};
+
+&rcc {
+	u-boot,dm-pre-reloc;
+};
+
+&gpioa {
+	compatible = "st,stm32-gpio";
+	u-boot,dm-pre-reloc;
+};
+
+&gpiob {
+	compatible = "st,stm32-gpio";
+	u-boot,dm-pre-reloc;
+};
+
+&gpioc {
+	compatible = "st,stm32-gpio";
+	u-boot,dm-pre-reloc;
+};
+
+&gpiod {
+	compatible = "st,stm32-gpio";
+	u-boot,dm-pre-reloc;
+};
+
+&gpioe {
+	compatible = "st,stm32-gpio";
+	u-boot,dm-pre-reloc;
+};
+
+&gpiof {
+	compatible = "st,stm32-gpio";
+	u-boot,dm-pre-reloc;
+};
+
+&gpiog {
+	compatible = "st,stm32-gpio";
+	u-boot,dm-pre-reloc;
+};
+
+&gpioh {
+	compatible = "st,stm32-gpio";
+	u-boot,dm-pre-reloc;
+};
+
+&gpioi {
+	compatible = "st,stm32-gpio";
+	u-boot,dm-pre-reloc;
+};
+
+&gpioj {
+	compatible = "st,stm32-gpio";
+	u-boot,dm-pre-reloc;
+};
+
+&gpiok {
+	compatible = "st,stm32-gpio";
+	u-boot,dm-pre-reloc;
+};
+
+&pinctrl {
+	usart1_pins_a: usart1@0	{
+		u-boot,dm-pre-reloc;
+		pins1 {
+			u-boot,dm-pre-reloc;
+		};
+		pins2 {
+			u-boot,dm-pre-reloc;
+		};
+	};
+
+	fmc_pins_d32: fmc_d32@0 {
+		u-boot,dm-pre-reloc;
+		pins
+		{
+			pinmux = <STM32_PINMUX('I',10, AF12)>, /* D31 */
+				 <STM32_PINMUX('I', 9, AF12)>, /* D30 */
+				 <STM32_PINMUX('I', 7, AF12)>, /* D29 */
+				 <STM32_PINMUX('I', 6, AF12)>, /* D28 */
+				 <STM32_PINMUX('I', 3, AF12)>, /* D27 */
+				 <STM32_PINMUX('I', 2, AF12)>, /* D26 */
+				 <STM32_PINMUX('I', 1, AF12)>, /* D25 */
+				 <STM32_PINMUX('I', 0, AF12)>, /* D24 */
+				 <STM32_PINMUX('H',15, AF12)>, /* D23 */
+				 <STM32_PINMUX('H',14, AF12)>, /* D22 */
+				 <STM32_PINMUX('H',13, AF12)>, /* D21 */
+				 <STM32_PINMUX('H',12, AF12)>, /* D20 */
+				 <STM32_PINMUX('H',11, AF12)>, /* D19 */
+				 <STM32_PINMUX('H',10, AF12)>, /* D18 */
+				 <STM32_PINMUX('H', 9, AF12)>, /* D17 */
+				 <STM32_PINMUX('H', 8, AF12)>, /* D16 */
+
+				 <STM32_PINMUX('D',10, AF12)>, /* D15 */
+				 <STM32_PINMUX('D', 9, AF12)>, /* D14 */
+				 <STM32_PINMUX('D', 8, AF12)>, /* D13 */
+				 <STM32_PINMUX('E',15, AF12)>, /* D12 */
+				 <STM32_PINMUX('E',14, AF12)>, /* D11 */
+				 <STM32_PINMUX('E',13, AF12)>, /* D10 */
+				 <STM32_PINMUX('E',12, AF12)>, /* D09 */
+				 <STM32_PINMUX('E',11, AF12)>, /* D08 */
+				 <STM32_PINMUX('E',10, AF12)>, /* D07 */
+				 <STM32_PINMUX('E', 9, AF12)>, /* D06 */
+				 <STM32_PINMUX('E', 8, AF12)>, /* D05 */
+				 <STM32_PINMUX('E', 7, AF12)>, /* D04 */
+				 <STM32_PINMUX('D', 1, AF12)>, /* D03 */
+				 <STM32_PINMUX('D', 0, AF12)>, /* D02 */
+				 <STM32_PINMUX('D',15, AF12)>, /* D01 */
+				 <STM32_PINMUX('D',14, AF12)>, /* D00 */
+
+				 <STM32_PINMUX('E', 0, AF12)>, /* NBL0 */
+				 <STM32_PINMUX('E', 1, AF12)>, /* NBL1 */
+				 <STM32_PINMUX('I', 4, AF12)>, /* NBL2 */
+				 <STM32_PINMUX('I', 5, AF12)>, /* NBL3 */
+
+				 <STM32_PINMUX('G', 5, AF12)>, /* A15-BA1 */
+				 <STM32_PINMUX('G', 4, AF12)>, /* A14-BA0 */
+				 <STM32_PINMUX('G', 3, AF12)>, /* A13 */
+				 <STM32_PINMUX('G', 2, AF12)>, /* A12 */
+				 <STM32_PINMUX('G', 1, AF12)>, /* A11 */
+				 <STM32_PINMUX('G', 0, AF12)>, /* A10 */
+				 <STM32_PINMUX('F',15, AF12)>, /* A09 */
+				 <STM32_PINMUX('F',14, AF12)>, /* A08 */
+				 <STM32_PINMUX('F',13, AF12)>, /* A07 */
+				 <STM32_PINMUX('F',12, AF12)>, /* A06 */
+				 <STM32_PINMUX('F', 5, AF12)>, /* A05 */
+				 <STM32_PINMUX('F', 4, AF12)>, /* A04 */
+				 <STM32_PINMUX('F', 3, AF12)>, /* A03 */
+				 <STM32_PINMUX('F', 2, AF12)>, /* A02 */
+				 <STM32_PINMUX('F', 1, AF12)>, /* A01 */
+				 <STM32_PINMUX('F', 0, AF12)>, /* A00 */
+
+				 <STM32_PINMUX('H', 3, AF12)>, /* SDNE0 */
+				 <STM32_PINMUX('H', 5, AF12)>, /* SDNWE */
+				 <STM32_PINMUX('F',11, AF12)>, /* SDNRAS */
+				 <STM32_PINMUX('G',15, AF12)>, /* SDNCAS */
+				 <STM32_PINMUX('H', 2, AF12)>, /* SDCKE0 */
+				 <STM32_PINMUX('G', 8, AF12)>; /* SDCLK> */
+			slew-rate = <2>;
+			u-boot,dm-pre-reloc;
+		};
+	};
+};
diff --git a/arch/arm/dts/stm32429i-eval.dts b/arch/arm/dts/stm32429i-eval.dts
new file mode 100644
index 0000000..362ea42
--- /dev/null
+++ b/arch/arm/dts/stm32429i-eval.dts
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2015, STMicroelectronics - All Rights Reserved
+ * Author: Maxime Coquelin <mcoquelin.stm32@gmail.com> for STMicroelectronics.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+#include "stm32f429.dtsi"
+#include "stm32f429-pinctrl.dtsi"
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "STMicroelectronics STM32429i-EVAL board";
+	compatible = "st,stm32429i-eval", "st,stm32f429";
+
+	chosen {
+		bootargs = "root=/dev/ram";
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory {
+		reg = <0x00000000 0x2000000>;
+	};
+
+	aliases {
+		serial0 = &usart1;
+	};
+
+	clocks {
+		clk_ext_camera: clk-ext-camera {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	soc {
+		dma-ranges = <0xc0000000 0x0 0x10000000>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_vref: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vref";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		green {
+			gpios = <&gpiog 6 1>;
+			linux,default-trigger = "heartbeat";
+		};
+		orange {
+			gpios = <&gpiog 7 1>;
+		};
+		red {
+			gpios = <&gpiog 10 1>;
+		};
+		blue {
+			gpios = <&gpiog 12 1>;
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		autorepeat;
+		button@0 {
+			label = "Wake up";
+			linux,code = <KEY_WAKEUP>;
+			gpios = <&gpioa 0 0>;
+		};
+		button@1 {
+			label = "Tamper";
+			linux,code = <KEY_RESTART>;
+			gpios = <&gpioc 13 0>;
+		};
+	};
+
+	usbotg_hs_phy: usbphy {
+		#phy-cells = <0>;
+		compatible = "usb-nop-xceiv";
+		clocks = <&rcc 0 STM32F4_AHB1_CLOCK(OTGHSULPI)>;
+		clock-names = "main_clk";
+	};
+
+	panel_rgb: panel-rgb {
+		compatible = "ampire,am-480272h3tmqw-t01h";
+		status = "okay";
+		port {
+			panel_in_rgb: endpoint {
+				remote-endpoint = <&ltdc_out_rgb>;
+			};
+		};
+	};
+
+	mmc_vcard: mmc_vcard {
+		compatible = "regulator-fixed";
+		regulator-name = "mmc_vcard";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+};
+
+&adc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&adc3_in8_pin>;
+	vref-supply = <&reg_vref>;
+	status = "okay";
+	adc3: adc@200 {
+		st,adc-channels = <8>;
+		status = "okay";
+	};
+};
+
+&clk_hse {
+	clock-frequency = <25000000>;
+};
+
+&crc {
+	status = "okay";
+};
+
+&dcmi {
+	status = "okay";
+
+	port {
+		dcmi_0: endpoint {
+			remote-endpoint = <&ov2640_0>;
+			bus-width = <8>;
+			hsync-active = <0>;
+			vsync-active = <0>;
+			pclk-sample = <1>;
+		};
+	};
+};
+
+&i2c1 {
+	pinctrl-0 = <&i2c1_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	ov2640: camera@30 {
+		compatible = "ovti,ov2640";
+		reg = <0x30>;
+		resetb-gpios = <&stmpegpio 2 GPIO_ACTIVE_HIGH>;
+		pwdn-gpios = <&stmpegpio 0 GPIO_ACTIVE_LOW>;
+		clocks = <&clk_ext_camera>;
+		clock-names = "xvclk";
+		status = "okay";
+
+		port {
+			ov2640_0: endpoint {
+				remote-endpoint = <&dcmi_0>;
+			};
+		};
+	};
+
+	stmpe1600: stmpe1600@42 {
+		compatible = "st,stmpe1600";
+		reg = <0x42>;
+		interrupts = <8 3>;
+		interrupt-parent = <&gpioi>;
+		interrupt-controller;
+		wakeup-source;
+
+		stmpegpio: stmpe_gpio {
+			compatible = "st,stmpe-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+	};
+};
+
+&iwdg {
+	status = "okay";
+	timeout-sec = <32>;
+};
+
+&ltdc {
+	status = "okay";
+	pinctrl-0 = <&ltdc_pins>;
+	pinctrl-names = "default";
+	dma-ranges;
+
+	port {
+		ltdc_out_rgb: endpoint {
+			remote-endpoint = <&panel_in_rgb>;
+		};
+	};
+};
+
+&mac {
+	status = "okay";
+	pinctrl-0	= <&ethernet_mii>;
+	pinctrl-names	= "default";
+	phy-mode	= "mii";
+	phy-handle	= <&phy1>;
+	mdio0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "snps,dwmac-mdio";
+		phy1: ethernet-phy@1 {
+			reg = <1>;
+		};
+	};
+};
+
+&rtc {
+	status = "okay";
+};
+
+&sdio {
+	status = "okay";
+	vmmc-supply = <&mmc_vcard>;
+	cd-gpios = <&stmpegpio 15 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+	pinctrl-names = "default", "opendrain";
+	pinctrl-0 = <&sdio_pins>;
+	pinctrl-1 = <&sdio_pins_od>;
+	bus-width = <4>;
+};
+
+&timers1 {
+	status = "okay";
+
+	pwm {
+		pinctrl-0 = <&pwm1_pins>;
+		pinctrl-names = "default";
+		status = "okay";
+	};
+
+	timer@0 {
+		status = "okay";
+	};
+};
+
+&timers3 {
+	status = "okay";
+
+	pwm {
+		pinctrl-0 = <&pwm3_pins>;
+		pinctrl-names = "default";
+		status = "okay";
+	};
+
+	timer@2 {
+		status = "okay";
+	};
+};
+
+&usart1 {
+	pinctrl-0 = <&usart1_pins_a>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&usbotg_hs {
+	dr_mode = "host";
+	phys = <&usbotg_hs_phy>;
+	phy-names = "usb2-phy";
+	pinctrl-0 = <&usbotg_hs_pins_a>;
+	pinctrl-names = "default";
+	status = "okay";
+};
diff --git a/arch/arm/dts/stm32f7-u-boot.dtsi b/arch/arm/dts/stm32f7-u-boot.dtsi
index a56ae93..9a9e4e5 100644
--- a/arch/arm/dts/stm32f7-u-boot.dtsi
+++ b/arch/arm/dts/stm32f7-u-boot.dtsi
@@ -26,3 +26,7 @@
 &pwrcfg {
 	u-boot,dm-pre-reloc;
 };
+
+&clk_hse {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/stm32f746.dtsi b/arch/arm/dts/stm32f746.dtsi
index 929bf82..46d148e 100644
--- a/arch/arm/dts/stm32f746.dtsi
+++ b/arch/arm/dts/stm32f746.dtsi
@@ -65,6 +65,9 @@
 			compatible = "st,stm32-dwmac";
 			reg = <0x40028000 0x8000>;
 			reg-names = "stmmaceth";
+			clocks = <&rcc 0 STM32F7_AHB1_CLOCK(ETHMAC)>,
+				 <&rcc 0 STM32F7_AHB1_CLOCK(ETHMACTX)>,
+				 <&rcc 0 STM32F7_AHB1_CLOCK(ETHMACRX)>;
 			interrupts = <61>, <62>;
 			interrupt-names = "macirq", "eth_wake_irq";
 			snps,pbl = <8>;
diff --git a/arch/arm/include/asm/arch-stm32f7/stm32_periph.h b/arch/arm/include/asm/arch-stm32f7/stm32_periph.h
index ae0faef..7b8f66a 100644
--- a/arch/arm/include/asm/arch-stm32f7/stm32_periph.h
+++ b/arch/arm/include/asm/arch-stm32f7/stm32_periph.h
@@ -21,9 +21,7 @@
 };
 
 enum periph_clock {
-	SYSCFG_CLOCK_CFG,
 	TIMER2_CLOCK_CFG,
-	STMMAC_CLOCK_CFG,
 };
 
 #endif /* __ASM_ARM_ARCH_PERIPH_H */
diff --git a/arch/arm/lib/bootm-fdt.c b/arch/arm/lib/bootm-fdt.c
index fcc2a0e..83409a7 100644
--- a/arch/arm/lib/bootm-fdt.c
+++ b/arch/arm/lib/bootm-fdt.c
@@ -34,7 +34,7 @@
 
 int arch_fixup_fdt(void *blob)
 {
-	int ret = 0;
+	__maybe_unused int ret = 0;
 #if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_OF_LIBFDT)
 	bd_t *bd = gd->bd;
 	int bank;
diff --git a/arch/arm/mach-bcm283x/include/mach/gpio.h b/arch/arm/mach-bcm283x/include/mach/gpio.h
index daaee52..7b4ddc9 100644
--- a/arch/arm/mach-bcm283x/include/mach/gpio.h
+++ b/arch/arm/mach-bcm283x/include/mach/gpio.h
@@ -61,6 +61,4 @@
 	unsigned long base;
 };
 
-int bcm2835_gpio_get_func_id(struct udevice *dev, unsigned gpio);
-
 #endif /* _BCM2835_GPIO_H_ */
diff --git a/arch/arm/mach-omap2/am33xx/Kconfig b/arch/arm/mach-omap2/am33xx/Kconfig
index 7260d27..9a9ccd7 100644
--- a/arch/arm/mach-omap2/am33xx/Kconfig
+++ b/arch/arm/mach-omap2/am33xx/Kconfig
@@ -185,6 +185,15 @@
 	select DM_SERIAL
 	select DM_GPIO
 
+config TARGET_PDU001
+	bool "Support PDU001"
+	select DM
+	select DM_SERIAL
+	help
+	  Support for PDU001 platform developed by EETS GmbH.
+	  The PDU001 is a processor and display unit developed around
+	  the Computing-Module m2 from bytes at work AG.
+
 endchoice
 
 endif
diff --git a/arch/arm/mach-omap2/am33xx/board.c b/arch/arm/mach-omap2/am33xx/board.c
index ae86b69..ea0caba 100644
--- a/arch/arm/mach-omap2/am33xx/board.c
+++ b/arch/arm/mach-omap2/am33xx/board.c
@@ -353,6 +353,9 @@
 #ifdef CONFIG_TI_I2C_BOARD_DETECT
 	do_board_detect();
 #endif
+#ifdef CONFIG_SPL_BUILD
+	spl_early_init();
+#endif
 #if defined(CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC)
 	/* Enable RTC32K clock */
 	rtc32k_enable();
diff --git a/arch/arm/mach-omap2/sec-common.c b/arch/arm/mach-omap2/sec-common.c
index 896cb70..bd003cb 100644
--- a/arch/arm/mach-omap2/sec-common.c
+++ b/arch/arm/mach-omap2/sec-common.c
@@ -56,7 +56,7 @@
 	u32 tee_arg0;          /* argument to TEE jump function, in r0 */
 };
 
-static uint32_t secure_rom_call_args[5] __aligned(ARCH_DMA_MINALIGN);
+static uint32_t secure_rom_call_args[5] __aligned(ARCH_DMA_MINALIGN) __section(".data");
 
 u32 secure_rom_call(u32 service, u32 proc_id, u32 flag, ...)
 {
diff --git a/arch/arm/mach-stm32/stm32f4/Kconfig b/arch/arm/mach-stm32/stm32f4/Kconfig
index 7005c65..e8fae4d 100644
--- a/arch/arm/mach-stm32/stm32f4/Kconfig
+++ b/arch/arm/mach-stm32/stm32f4/Kconfig
@@ -3,10 +3,14 @@
 config TARGET_STM32F429_DISCOVERY
 	bool "STM32F429 Discovery board"
 
+config TARGET_STM32F429_EVALUATION
+	bool "STM32F429 Evaluation board"
+
 config TARGET_STM32F469_DISCOVERY
 	bool "STM32F469 Discovery board"
 
 source "board/st/stm32f429-discovery/Kconfig"
+source "board/st/stm32f429-evaluation/Kconfig"
 source "board/st/stm32f469-discovery/Kconfig"
 
 endif
diff --git a/arch/powerpc/include/asm/arch-mpc85xx/gpio.h b/arch/powerpc/include/asm/arch-mpc85xx/gpio.h
index 76faa22..b2ba31e 100644
--- a/arch/powerpc/include/asm/arch-mpc85xx/gpio.h
+++ b/arch/powerpc/include/asm/arch-mpc85xx/gpio.h
@@ -18,7 +18,7 @@
 #include <asm/mpc85xx_gpio.h>
 #endif
 
-struct mpc85xx_gpio_plat {
+struct mpc8xxx_gpio_plat {
 	ulong addr;
 	unsigned long size;
 	uint ngpios;
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index baf38f8..57b11b8 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -1206,11 +1206,6 @@
 #endif
 
 
-#ifndef CONFIG_MACH_SPECIFIC
-extern int _machine;
-extern int have_of;
-#endif /* CONFIG_MACH_SPECIFIC */
-
 /* what kind of prep workstation we are */
 extern int _prep_type;
 /*
@@ -1336,15 +1331,6 @@
 
 #endif /* ndef ASSEMBLY*/
 
-#ifdef CONFIG_MACH_SPECIFIC
-#if defined(CONFIG_WALNUT)
-#define _machine _MACH_walnut
-#define have_of 0
-#else
-#error "Machine not defined correctly"
-#endif
-#endif /* CONFIG_MACH_SPECIFIC */
-
 #if defined(CONFIG_MPC85xx)
  #define EPAPR_MAGIC	(0x45504150)
 #else
diff --git a/board/eets/pdu001/Kconfig b/board/eets/pdu001/Kconfig
new file mode 100644
index 0000000..6217a8f
--- /dev/null
+++ b/board/eets/pdu001/Kconfig
@@ -0,0 +1,66 @@
+# Copyright (C) 2018 EETS GmbH - http://www.eets.ch/
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+if TARGET_PDU001
+
+config SYS_BOARD
+	default "pdu001"
+
+config SYS_VENDOR
+	default "eets"
+
+config SYS_SOC
+	default "am33xx"
+
+config SYS_CONFIG_NAME
+	default "pdu001"
+
+config CONS_INDEX
+	int "UART used for console"
+	range 1 6
+	default 4
+	help
+	  The AM335x SoC has a total of 6 UARTs (UART0 to UART5 as referenced
+	  in documentation, etc) available to it.  The best choice for the
+	  PDU001 is UART3 as it is wired to the header K2; enter 4 here to
+	  use UART3. UART0 is connected to the EIA-485 transceiver. If you
+	  really need to use it, you are advised to remove the transceiver U14
+	  from the board. UART1 is wired to the backplane and therefore
+	  accessible from there or by the backplane connector K1 of the PDU.
+	  Any other UART then UART3 (enter 4 here), UART1 (enter 2 here) or
+	  UART0 (enter 1 here) are not sensible since they are not wired to
+	  any connector and therefore difficult to access.
+
+choice
+	prompt "State of Run LED"
+	default PDU001_RUN_LED_RED
+	help
+	  The PDU001 has a bi-color (red/green) LED labeled 'Run' which
+	  can be used to indicate the operating state of the board. By
+	  default it will be lit red by U-Boot. Later in the start-up
+	  process it can be changed to green (or heartbeat or anything else)
+	  by the kernel or some other software.
+
+config RUN_LED_RED
+	bool
+	prompt "Red"
+	help
+	  Lit Run LED red.
+
+config RUN_LED_GREEN
+	bool
+	prompt "Green"
+	help
+	  Lit Run LED green.
+
+config RUN_LED_OFF
+	bool
+	prompt "Off"
+	help
+	  Do not lit Run LED.
+
+endchoice
+
+endif
diff --git a/board/eets/pdu001/MAINTAINERS b/board/eets/pdu001/MAINTAINERS
new file mode 100644
index 0000000..95295dd
--- /dev/null
+++ b/board/eets/pdu001/MAINTAINERS
@@ -0,0 +1,6 @@
+PDU001 BOARD
+M:	Felix Brack <fb@ltec.ch>
+S:	Maintained
+F:	board/eets/pdu001/
+F:	include/configs/pdu001.h
+F:	configs/am335x_pdu001_defconfig
diff --git a/board/eets/pdu001/Makefile b/board/eets/pdu001/Makefile
new file mode 100644
index 0000000..08c6d53
--- /dev/null
+++ b/board/eets/pdu001/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile
+#
+# Copyright (C) 2018 EETS GmbH - http://www.eets.ch/
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+ifeq ($(CONFIG_SKIP_LOWLEVEL_INIT),)
+obj-y	:= mux.o
+endif
+
+obj-y	+= board.o
diff --git a/board/eets/pdu001/README b/board/eets/pdu001/README
new file mode 100644
index 0000000..50e7154
--- /dev/null
+++ b/board/eets/pdu001/README
@@ -0,0 +1,35 @@
+# Copyright (C) 2018 EETS GmbH - http://www.eets.ch/
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+Summary
+=======
+
+This document covers the PDU001 target.
+
+Hardware
+========
+
+The PDU-001 (Processor and Display Unit) is a plugin card for 19" racks. It is
+manufactured by EETS GmbH (https://www.eets.ch). The core of the board is a m2
+SOM from bytes at work (https://www.bytesatwork.ch) which in turn is based on
+AM3352 SOC from TI (http://www.ti.com).
+
+Customization
+=============
+
+As usual the console serial interface is set by CONFIG_CONS_INDEX. Best choice
+is 4 here since UART3 is wired to the connector K2.
+The Run LED on the PDU-001 can be turned on red by setting CONFIG_RUN_LED_RED
+or green by setting CONFIG_RUN_LED_GREEN. Setting CONFIG_RUN_LED_OFF will turn
+off the Run LED.
+
+Booting
+=======
+
+The system boots from either eMMC or SD card cage. It will first try to boot
+from the SD card cage. If this fails (missing or unbootable SD card) it will
+try to boot from the internal eMMC. The root file system is always expected to
+be located in the second partition of the device (eMMC or SD card) that pro-
+vided the boot loader.
diff --git a/board/eets/pdu001/board.c b/board/eets/pdu001/board.c
new file mode 100644
index 0000000..416bd93
--- /dev/null
+++ b/board/eets/pdu001/board.c
@@ -0,0 +1,276 @@
+/*
+ * board.c
+ *
+ * Board functions for EETS PDU001 board
+ *
+ * Copyright (C) 2018, EETS GmbH, http://www.eets.ch/
+ *
+ * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <spl.h>
+#include <i2c.h>
+#include <environment.h>
+#include <watchdog.h>
+#include <debug_uart.h>
+#include <dm/ofnode.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/omap.h>
+#include <asm/arch/ddr_defs.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/mmc_host_def.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/mem.h>
+#include <asm/io.h>
+#include <asm/emif.h>
+#include <asm/gpio.h>
+#include "board.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define I2C_ADDR_NODE_ID	0x50
+#define I2C_REG_NODE_ID_BASE	0xfa
+#define NODE_ID_BYTE_COUNT	6
+
+#define I2C_ADDR_LEDS		0x60
+#define I2C_REG_RUN_LED		0x06
+#define RUN_LED_OFF		0x0
+#define RUN_LED_RED		0x1
+#define RUN_LED_GREEN		(0x1 << 2)
+
+#define VDD_MPU_REGULATOR	"regulator@2"
+#define VDD_CORE_REGULATOR	"regulator@3"
+#define DEFAULT_CORE_VOLTAGE	1137500
+
+/*
+ *  boot device save register
+ * -------------------------
+ * The boot device can be quired by 'spl_boot_device()' in
+ * 'am33xx_spl_board_init'. However it can't be saved in the u-boot
+ * environment here. In turn 'spl_boot_device' can't be called in
+ * 'board_late_init' which allows writing to u-boot environment.
+ * To get the boot device from 'am33xx_spl_board_init' to
+ * 'board_late_init' we therefore use a scratch register from the RTC.
+ */
+#define CONFIG_SYS_RTC_SCRATCH0 0x60
+#define BOOT_DEVICE_SAVE_REGISTER (RTC_BASE + CONFIG_SYS_RTC_SCRATCH0)
+
+#ifdef CONFIG_SPL_BUILD
+static void save_boot_device(void)
+{
+	*((u32 *)(BOOT_DEVICE_SAVE_REGISTER)) = spl_boot_device();
+}
+#endif
+
+u32 boot_device(void)
+{
+	return *((u32 *)(BOOT_DEVICE_SAVE_REGISTER));
+}
+
+/* Store the boot device in the environment variable 'boot_device' */
+static void env_set_boot_device(void)
+{
+	switch (boot_device()) {
+		case BOOT_DEVICE_MMC1: {
+			env_set("boot_device", "emmc");
+			break;
+		}
+		case BOOT_DEVICE_MMC2: {
+			env_set("boot_device", "sdcard");
+			break;
+		}
+		default: {
+			env_set("boot_device", "unknown");
+			break;
+		}
+	}
+}
+
+static void set_run_led(struct udevice *dev)
+{
+	int val = RUN_LED_OFF;
+
+	if (IS_ENABLED(CONFIG_RUN_LED_RED))
+		val = RUN_LED_RED;
+	else if (IS_ENABLED(CONFIG_RUN_LED_GREEN))
+		val = RUN_LED_GREEN;
+
+	dm_i2c_reg_write(dev, I2C_REG_RUN_LED, val);
+}
+
+/* Set 'serial#' to the EUI-48 value of board node ID chip */
+static void env_set_serial(struct udevice *dev)
+{
+	int val;
+	char serial[2 * NODE_ID_BYTE_COUNT + 1];
+	int n;
+
+	for (n = 0; n < sizeof(serial); n += 2) {
+		val = dm_i2c_reg_read(dev, I2C_REG_NODE_ID_BASE + n / 2);
+		sprintf(serial + n, "%02X", val);
+	}
+	serial[2 * NODE_ID_BYTE_COUNT] = '\0';
+	env_set("serial#", serial);
+}
+
+static void set_mpu_and_core_voltage(void)
+{
+	int mpu_vdd;
+	int sil_rev;
+	struct udevice *dev;
+	struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE;
+
+	/*
+	 * The PDU001 (more precisely the computing module m2) uses a
+	 * TPS65910 PMIC.  For all MPU frequencies we support we use a CORE
+	 * voltage of 1.1375V.  For MPU voltage we need to switch based on
+	 * the frequency we are running at.
+	 */
+
+	/*
+	 * Depending on MPU clock and PG we will need a different VDD
+	 * to drive at that speed.
+	 */
+	sil_rev = readl(&cdev->deviceid) >> 28;
+	mpu_vdd = am335x_get_mpu_vdd(sil_rev, dpll_mpu_opp100.m);
+
+	/* first update the MPU voltage */
+	if (!regulator_get_by_devname(VDD_MPU_REGULATOR, &dev)) {
+		if (regulator_set_value(dev, mpu_vdd))
+			debug("failed to set MPU voltage\n");
+	} else {
+		debug("invalid MPU voltage ragulator %s\n", VDD_MPU_REGULATOR);
+	}
+
+	/* second update the CORE voltage */
+	if (!regulator_get_by_devname(VDD_CORE_REGULATOR, &dev)) {
+		if (regulator_set_value(dev, DEFAULT_CORE_VOLTAGE))
+			debug("failed to set CORE voltage\n");
+	} else {
+		debug("invalid CORE voltage ragulator %s\n",
+		      VDD_CORE_REGULATOR);
+	}
+}
+
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+static const struct ddr_data ddr2_data = {
+	.datardsratio0 = MT47H128M16RT25E_RD_DQS,
+	.datafwsratio0 = MT47H128M16RT25E_PHY_FIFO_WE,
+	.datawrsratio0 = MT47H128M16RT25E_PHY_WR_DATA,
+};
+
+static const struct cmd_control ddr2_cmd_ctrl_data = {
+	.cmd0csratio = MT47H128M16RT25E_RATIO,
+	.cmd1csratio = MT47H128M16RT25E_RATIO,
+	.cmd2csratio = MT47H128M16RT25E_RATIO,
+};
+
+static const struct emif_regs ddr2_emif_reg_data = {
+	.sdram_config = MT47H128M16RT25E_EMIF_SDCFG,
+	.ref_ctrl = MT47H128M16RT25E_EMIF_SDREF,
+	.sdram_tim1 = MT47H128M16RT25E_EMIF_TIM1,
+	.sdram_tim2 = MT47H128M16RT25E_EMIF_TIM2,
+	.sdram_tim3 = MT47H128M16RT25E_EMIF_TIM3,
+	.emif_ddr_phy_ctlr_1 = MT47H128M16RT25E_EMIF_READ_LATENCY,
+};
+
+#define OSC	(V_OSCK / 1000000)
+const struct dpll_params dpll_ddr = {
+		266, OSC - 1, 1, -1, -1, -1, -1};
+const struct dpll_params dpll_ddr_evm_sk = {
+		303, OSC - 1, 1, -1, -1, -1, -1};
+const struct dpll_params dpll_ddr_bone_black = {
+		400, OSC - 1, 1, -1, -1, -1, -1};
+
+void am33xx_spl_board_init(void)
+{
+	struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE;
+
+	/* Get the frequency */
+	dpll_mpu_opp100.m = am335x_get_efuse_mpu_max_freq(cdev);
+
+	/* Set CORE Frequencies to OPP100 */
+	do_setup_dpll(&dpll_core_regs, &dpll_core_opp100);
+
+	/* Set MPU Frequency to what we detected now that voltages are set */
+	do_setup_dpll(&dpll_mpu_regs, &dpll_mpu_opp100);
+
+	/* save boot device for later use by 'board_late_init' */
+	save_boot_device();
+}
+
+const struct dpll_params *get_dpll_ddr_params(void)
+{
+	enable_i2c0_pin_mux();
+	i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED, CONFIG_SYS_OMAP24_I2C_SLAVE);
+
+	return &dpll_ddr;
+}
+
+void set_mux_conf_regs(void)
+{
+	/* done first by the ROM and afterwards by the pin controller driver */
+	enable_i2c0_pin_mux();
+}
+
+const struct ctrl_ioregs ioregs = {
+	.cm0ioctl		= MT47H128M16RT25E_IOCTRL_VALUE,
+	.cm1ioctl		= MT47H128M16RT25E_IOCTRL_VALUE,
+	.cm2ioctl		= MT47H128M16RT25E_IOCTRL_VALUE,
+	.dt0ioctl		= MT47H128M16RT25E_IOCTRL_VALUE,
+	.dt1ioctl		= MT47H128M16RT25E_IOCTRL_VALUE,
+};
+
+void sdram_init(void)
+{
+	config_ddr(266, &ioregs, &ddr2_data,
+		   &ddr2_cmd_ctrl_data, &ddr2_emif_reg_data, 0);
+}
+#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
+
+#ifdef CONFIG_DEBUG_UART
+void board_debug_uart_init(void)
+{
+	/* done by pin controller driver if not debugging */
+	enable_uart_pin_mux(CONFIG_DEBUG_UART_BASE);
+}
+#endif
+
+/*
+ * Basic board specific setup.  Pinmux has been handled already.
+ */
+int board_init(void)
+{
+#ifdef CONFIG_HW_WATCHDOG
+	hw_watchdog_init();
+#endif
+
+	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
+	return 0;
+}
+
+#ifdef CONFIG_BOARD_LATE_INIT
+int board_late_init(void)
+{
+	struct udevice *dev;
+
+	set_mpu_and_core_voltage();
+	env_set_boot_device();
+
+	/* second I2C bus connects to node ID and front panel LED chip */
+	if (!i2c_get_chip_for_busnum(1, I2C_ADDR_LEDS, 1, &dev))
+		set_run_led(dev);
+	if (!i2c_get_chip_for_busnum(1, I2C_ADDR_NODE_ID, 1, &dev))
+		env_set_serial(dev);
+
+	return 0;
+}
+#endif
diff --git a/board/eets/pdu001/board.h b/board/eets/pdu001/board.h
new file mode 100644
index 0000000..3474e6a
--- /dev/null
+++ b/board/eets/pdu001/board.h
@@ -0,0 +1,38 @@
+/*
+ * board.h
+ *
+ * EETS GmbH PDU001 board information header
+ *
+ * Copyright (C) 2018 EETS GmbH - http://www.eets.ch/
+ *
+ * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _BOARD_H_
+#define _BOARD_H_
+
+/*
+ * We have two pin mux functions that must exist. First we need I2C0 to
+ * access the TPS65910 PMIC located on the M2 computing module.
+ * Second, if we want low-level debugging or a early UART (ie. before the
+ * pin controller driver is running), we need one of the UART ports UART0 to
+ * UART5 (usually UART3 since it is wired to K2).
+ * In case of I2C0 access we explicitly don't rely on the the ROM but we could
+ * do so as we use the primary mode (mode 0) for I2C0.
+ * All other multiplexing and pin configuration is done by the DT once it
+ * gets parsed by the pin controller driver.
+ * However we relay on the ROM to configure the pins of MMC0 (eMMC) as well
+ * as MMC1 (microSD card-cage) since these are our boot devices.
+ */
+void enable_uart0_pin_mux(void);
+void enable_uart1_pin_mux(void);
+void enable_uart2_pin_mux(void);
+void enable_uart3_pin_mux(void);
+void enable_uart4_pin_mux(void);
+void enable_uart5_pin_mux(void);
+void enable_uart_pin_mux(u32 addr);
+void enable_i2c0_pin_mux(void);
+
+#endif
diff --git a/board/eets/pdu001/mux.c b/board/eets/pdu001/mux.c
new file mode 100644
index 0000000..bf2c8df
--- /dev/null
+++ b/board/eets/pdu001/mux.c
@@ -0,0 +1,120 @@
+/*
+ * mux.c
+ *
+ * Copyright (C) 2018 EETS GmbH - http://www.eets.ch/
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/mux.h>
+#include <asm/io.h>
+#include <i2c.h>
+#include "board.h"
+
+static struct module_pin_mux uart0_pin_mux[] = {
+	{OFFSET(uart0_rxd), (MODE(0) | PULLUP_EN | RXACTIVE)},	/* UART0_RXD */
+	{OFFSET(uart0_txd), (MODE(0) | PULLUDEN)},		/* UART0_TXD */
+	{-1},
+};
+
+static struct module_pin_mux uart1_pin_mux[] = {
+	{OFFSET(uart1_rxd), (MODE(0) | PULLUP_EN | RXACTIVE)},	/* UART1_RXD */
+	{OFFSET(uart1_txd), (MODE(0) | PULLUDEN)},		/* UART1_TXD */
+	{-1},
+};
+
+static struct module_pin_mux uart2_pin_mux[] = {
+	{OFFSET(spi0_sclk), (MODE(1) | PULLUP_EN | RXACTIVE)},	/* UART2_RXD */
+	{OFFSET(spi0_d0), (MODE(1) | PULLUDEN)},		/* UART2_TXD */
+	{-1},
+};
+
+static struct module_pin_mux uart3_pin_mux[] = {
+	{OFFSET(spi0_cs1), (MODE(1) | PULLUP_EN | RXACTIVE)},	/* UART3_RXD */
+	{OFFSET(ecap0_in_pwm0_out), (MODE(1) | PULLUDEN)},	/* UART3_TXD */
+	{-1},
+};
+
+static struct module_pin_mux uart4_pin_mux[] = {
+	{OFFSET(gpmc_wait0), (MODE(6) | PULLUP_EN | RXACTIVE)},	/* UART4_RXD */
+	{OFFSET(gpmc_wpn), (MODE(6) | PULLUDEN)},		/* UART4_TXD */
+	{-1},
+};
+
+static struct module_pin_mux uart5_pin_mux[] = {
+	{OFFSET(lcd_data9), (MODE(4) | PULLUP_EN | RXACTIVE)},	/* UART5_RXD */
+	{OFFSET(lcd_data8), (MODE(4) | PULLUDEN)},		/* UART5_TXD */
+	{-1},
+};
+
+static struct module_pin_mux i2c0_pin_mux[] = {
+	{OFFSET(i2c0_sda), (MODE(0) | RXACTIVE |
+			PULLUDEN | SLEWCTRL)},			/* I2C_DATA  */
+	{OFFSET(i2c0_scl), (MODE(0) | RXACTIVE |
+			PULLUDEN | SLEWCTRL)},			/* I2C_SCLK  */
+	{-1},
+};
+
+void enable_uart0_pin_mux(void)
+{
+	configure_module_pin_mux(uart0_pin_mux);
+}
+
+void enable_uart1_pin_mux(void)
+{
+	configure_module_pin_mux(uart1_pin_mux);
+}
+
+void enable_uart2_pin_mux(void)
+{
+	configure_module_pin_mux(uart2_pin_mux);
+}
+
+void enable_uart3_pin_mux(void)
+{
+	configure_module_pin_mux(uart3_pin_mux);
+}
+
+void enable_uart4_pin_mux(void)
+{
+	configure_module_pin_mux(uart4_pin_mux);
+}
+
+void enable_uart5_pin_mux(void)
+{
+	configure_module_pin_mux(uart5_pin_mux);
+}
+
+void enable_uart_pin_mux(u32 addr)
+{
+	switch (addr) {
+	case CONFIG_SYS_NS16550_COM1:
+		enable_uart0_pin_mux();
+		break;
+	case CONFIG_SYS_NS16550_COM2:
+		enable_uart1_pin_mux();
+		break;
+	case CONFIG_SYS_NS16550_COM3:
+		enable_uart2_pin_mux();
+		break;
+	case CONFIG_SYS_NS16550_COM4:
+		enable_uart3_pin_mux();
+		break;
+	case CONFIG_SYS_NS16550_COM5:
+		enable_uart4_pin_mux();
+		break;
+	case CONFIG_SYS_NS16550_COM6:
+		enable_uart5_pin_mux();
+		break;
+	}
+}
+
+void enable_i2c0_pin_mux(void)
+{
+	configure_module_pin_mux(i2c0_pin_mux);
+}
diff --git a/board/logicpd/omap3som/omap3logic.h b/board/logicpd/omap3som/omap3logic.h
index 22d7760..7376119 100644
--- a/board/logicpd/omap3som/omap3logic.h
+++ b/board/logicpd/omap3som/omap3logic.h
@@ -229,17 +229,17 @@
 	MUX_VAL(CP(HSUSB0_DATA6), (IEN  | PTD | DIS | M0)); /*HSUSB0_DATA6*/
 	MUX_VAL(CP(HSUSB0_DATA7), (IEN  | PTD | DIS | M0)); /*HSUSB0_DATA7*/
 
-	MUX_VAL(CP(I2C1_SCL), (IEN  | PTU | EN  | M0)); /*I2C1_SCL*/
-	MUX_VAL(CP(I2C1_SDA), (IEN  | PTU | EN  | M0)); /*I2C1_SDA*/
+	MUX_VAL(CP(I2C1_SCL), (IEN  | EN  | M0)); /*I2C1_SCL*/
+	MUX_VAL(CP(I2C1_SDA), (IEN  | EN  | M0)); /*I2C1_SDA*/
 
-	MUX_VAL(CP(I2C2_SCL), (IEN  | PTU | EN  | M0)); /*I2C2_SCL*/
-	MUX_VAL(CP(I2C2_SDA), (IEN  | PTU | EN  | M0)); /*I2C2_SDA*/
+	MUX_VAL(CP(I2C2_SCL), (IEN  | EN  | M0)); /*I2C2_SCL*/
+	MUX_VAL(CP(I2C2_SDA), (IEN  | EN  | M0)); /*I2C2_SDA*/
 
-	MUX_VAL(CP(I2C3_SCL), (IEN  | PTU | EN  | M0)); /*I2C3_SCL*/
-	MUX_VAL(CP(I2C3_SDA), (IEN  | PTU | EN  | M0)); /*I2C3_SDA*/
+	MUX_VAL(CP(I2C3_SCL), (IEN  | EN  | M0)); /*I2C3_SCL*/
+	MUX_VAL(CP(I2C3_SDA), (IEN  | EN  | M0)); /*I2C3_SDA*/
 
-	MUX_VAL(CP(I2C4_SCL), (IEN  | PTU | EN  | M0)); /*I2C4_SCL*/
-	MUX_VAL(CP(I2C4_SDA), (IEN  | PTU | EN  | M0)); /*I2C4_SDA*/
+	MUX_VAL(CP(I2C4_SCL), (IEN  | EN  | M0)); /*I2C4_SCL*/
+	MUX_VAL(CP(I2C4_SDA), (IEN  | EN  | M0)); /*I2C4_SDA*/
 
 	MUX_VAL(CP(HDQ_SIO), (IEN  | PTU | EN  | M0)); /*HDQ_SIO*/
 
diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index 3b7a54f..177f4af 100644
--- a/board/raspberrypi/rpi/rpi.c
+++ b/board/raspberrypi/rpi/rpi.c
@@ -24,6 +24,7 @@
 #include <asm/armv8/mmu.h>
 #endif
 #include <watchdog.h>
+#include <dm/pinctrl.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -419,54 +420,11 @@
 	printf("RPI %s (0x%x)\n", model->name, revision);
 }
 
-#ifndef CONFIG_PL01X_SERIAL
-static bool rpi_is_serial_active(void)
-{
-	int serial_gpio = 15;
-	struct udevice *dev;
-
-	/*
-	 * The RPi3 disables the mini uart by default. The easiest way to find
-	 * out whether it is available is to check if the RX pin is muxed.
-	 */
-
-	if (uclass_first_device(UCLASS_GPIO, &dev) || !dev)
-		return true;
-
-	if (bcm2835_gpio_get_func_id(dev, serial_gpio) != BCM2835_GPIO_ALT5)
-		return false;
-
-	return true;
-}
-
-/* Disable mini-UART I/O if it's not pinmuxed to our pins.
- * The firmware only enables it if explicitly done in config.txt: enable_uart=1
- */
-static void rpi_disable_inactive_uart(void)
-{
-	struct udevice *dev;
-	struct bcm283x_mu_serial_platdata *plat;
-
-	if (uclass_get_device_by_driver(UCLASS_SERIAL,
-					DM_GET_DRIVER(serial_bcm283x_mu),
-					&dev) || !dev)
-		return;
-
-	if (!rpi_is_serial_active()) {
-		plat = dev_get_platdata(dev);
-		plat->disabled = true;
-	}
-}
-#endif
-
 int board_init(void)
 {
 #ifdef CONFIG_HW_WATCHDOG
 	hw_watchdog_init();
 #endif
-#ifndef CONFIG_PL01X_SERIAL
-	rpi_disable_inactive_uart();
-#endif
 
 	get_board_rev();
 
diff --git a/board/st/stm32f429-evaluation/Kconfig b/board/st/stm32f429-evaluation/Kconfig
new file mode 100644
index 0000000..ca4bb3d
--- /dev/null
+++ b/board/st/stm32f429-evaluation/Kconfig
@@ -0,0 +1,19 @@
+if TARGET_STM32F429_EVALUATION
+
+config SYS_BOARD
+	string
+	default "stm32f429-evaluation"
+
+config SYS_VENDOR
+	string
+	default "st"
+
+config SYS_SOC
+	string
+	default "stm32f4"
+
+config SYS_CONFIG_NAME
+	string
+	default "stm32f429-evaluation"
+
+endif
diff --git a/board/st/stm32f429-evaluation/MAINTAINERS b/board/st/stm32f429-evaluation/MAINTAINERS
new file mode 100644
index 0000000..8b7b312
--- /dev/null
+++ b/board/st/stm32f429-evaluation/MAINTAINERS
@@ -0,0 +1,6 @@
+STM32F429-EVALUATION BOARD
+M:	Patrice Chotard <patrice.chotard@st.com>
+S:	Maintained
+F:	board/st/stm32f429-evaluation/
+F:	include/configs/stm32f429-evaluation.h
+F:	configs/stm32f429-evaluation_defconfig
diff --git a/board/st/stm32f429-evaluation/Makefile b/board/st/stm32f429-evaluation/Makefile
new file mode 100644
index 0000000..3efba3a
--- /dev/null
+++ b/board/st/stm32f429-evaluation/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+# Author(s): Patrice CHOTARD, <patrice.chotard@st.com> for STMicroelectronics.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y	:= stm32f429-evaluation.o
diff --git a/board/st/stm32f429-evaluation/stm32f429-evaluation.c b/board/st/stm32f429-evaluation/stm32f429-evaluation.c
new file mode 100644
index 0000000..25e0207
--- /dev/null
+++ b/board/st/stm32f429-evaluation/stm32f429-evaluation.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Author(s): Patrice Chotard, <patrice.chotard@st.com> for STMicroelectronics.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+
+#include <asm/io.h>
+#include <asm/arch/stm32.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dram_init(void)
+{
+	int rv;
+	struct udevice *dev;
+
+	rv = uclass_get_device(UCLASS_RAM, 0, &dev);
+	if (rv) {
+		debug("DRAM init failed: %d\n", rv);
+		return rv;
+	}
+
+	if (fdtdec_setup_memory_size() != 0)
+		rv = -EINVAL;
+
+	return rv;
+}
+
+int dram_init_banksize(void)
+{
+	fdtdec_setup_memory_banksize();
+
+	return 0;
+}
+
+u32 get_board_rev(void)
+{
+	return 0;
+}
+
+int board_early_init_f(void)
+{
+	return 0;
+}
+
+int board_init(void)
+{
+	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
+
+	return 0;
+}
+
+#ifdef CONFIG_MISC_INIT_R
+int misc_init_r(void)
+{
+	char serialno[25];
+	u32 u_id_low, u_id_mid, u_id_high;
+
+	if (!env_get("serial#")) {
+		u_id_low  = readl(&STM32_U_ID->u_id_low);
+		u_id_mid  = readl(&STM32_U_ID->u_id_mid);
+		u_id_high = readl(&STM32_U_ID->u_id_high);
+		sprintf(serialno, "%08x%08x%08x",
+			u_id_high, u_id_mid, u_id_low);
+		env_set("serial#", serialno);
+	}
+
+	return 0;
+}
+#endif
diff --git a/board/st/stm32f746-disco/stm32f746-disco.c b/board/st/stm32f746-disco/stm32f746-disco.c
index 2e8aa86..8da7028 100644
--- a/board/st/stm32f746-disco/stm32f746-disco.c
+++ b/board/st/stm32f746-disco/stm32f746-disco.c
@@ -69,24 +69,10 @@
 	return 0;
 }
 
-#ifdef CONFIG_ETH_DESIGNWARE
-static int stmmac_setup(void)
-{
-	clock_setup(SYSCFG_CLOCK_CFG);
-	/* Set >RMII mode */
-	STM32_SYSCFG->pmc |= SYSCFG_PMC_MII_RMII_SEL;
-	clock_setup(STMMAC_CLOCK_CFG);
-
-	return 0;
-}
-
 int board_early_init_f(void)
 {
-	stmmac_setup();
-
 	return 0;
 }
-#endif
 
 #ifdef CONFIG_SPL_BUILD
 #ifdef CONFIG_SPL_OS_BOOT
@@ -163,5 +149,11 @@
 int board_init(void)
 {
 	gd->bd->bi_boot_params = gd->bd->bi_dram[0].start + 0x100;
+
+#ifdef CONFIG_ETH_DESIGNWARE
+	/* Set >RMII mode */
+	STM32_SYSCFG->pmc |= SYSCFG_PMC_MII_RMII_SEL;
+#endif
+
 	return 0;
 }
diff --git a/board/ti/am43xx/board.c b/board/ti/am43xx/board.c
index 2c417e7..16150ad 100644
--- a/board/ti/am43xx/board.c
+++ b/board/ti/am43xx/board.c
@@ -580,6 +580,11 @@
 	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
 	gpmc_init();
 
+	/*
+	 * Call this to initialize *ctrl again
+	 */
+	hw_data_init();
+
 	/* Clear all important bits for DSS errata that may need to be tweaked*/
 	mreqprio_0 = readl(&cdev->mreqprio_0) & MREQPRIO_0_SAB_INIT1_MASK &
 	                   MREQPRIO_0_SAB_INIT0_MASK;
diff --git a/cmd/elf.c b/cmd/elf.c
index 5745a38..5b59fc6 100644
--- a/cmd/elf.c
+++ b/cmd/elf.c
@@ -240,11 +240,7 @@
 	 * from the VxWorks BSP header files.
 	 * This will vary from board to board
 	 */
-#if defined(CONFIG_WALNUT)
-	tmp = (char *)CONFIG_SYS_NVRAM_BASE_ADDR + 0x500;
-	eth_env_get_enetaddr("ethaddr", (uchar *)build_buf);
-	memcpy(tmp, &build_buf[3], 3);
-#elif defined(CONFIG_SYS_VXWORKS_MAC_PTR)
+#if defined(CONFIG_SYS_VXWORKS_MAC_PTR)
 	tmp = (char *)CONFIG_SYS_VXWORKS_MAC_PTR;
 	eth_env_get_enetaddr("ethaddr", (uchar *)build_buf);
 	memcpy(tmp, build_buf, 6);
diff --git a/common/autoboot.c b/common/autoboot.c
index a011865..2eef7a0 100644
--- a/common/autoboot.c
+++ b/common/autoboot.c
@@ -57,7 +57,7 @@
 	const char *algo_name = "sha256";
 	u_int presskey_len = 0;
 	int abort = 0;
-	int size;
+	int size = sizeof(sha);
 	int ret;
 
 	if (sha_env_str == NULL)
diff --git a/common/board_f.c b/common/board_f.c
index 1965bda..c6bc53e 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -49,7 +49,7 @@
 #ifdef XTRN_DECLARE_GLOBAL_DATA_PTR
 #undef	XTRN_DECLARE_GLOBAL_DATA_PTR
 #define XTRN_DECLARE_GLOBAL_DATA_PTR	/* empty = allocate here */
-DECLARE_GLOBAL_DATA_PTR = (gd_t *) (CONFIG_SYS_INIT_GD_ADDR);
+DECLARE_GLOBAL_DATA_PTR = (gd_t *)(CONFIG_SYS_INIT_GD_ADDR);
 #else
 DECLARE_GLOBAL_DATA_PTR;
 #endif
@@ -136,7 +136,7 @@
 #endif
 
 	debug("U-Boot code: %08lX -> %08lX  BSS: -> %08lX\n",
-		text_base, bss_start, bss_end);
+	      text_base, bss_start, bss_end);
 #endif
 
 	return 0;
@@ -420,7 +420,7 @@
 {
 	gd->start_addr_sp = gd->start_addr_sp - TOTAL_MALLOC_LEN;
 	debug("Reserving %dk for malloc() at: %08lx\n",
-			TOTAL_MALLOC_LEN >> 10, gd->start_addr_sp);
+	      TOTAL_MALLOC_LEN >> 10, gd->start_addr_sp);
 	return 0;
 }
 
@@ -450,7 +450,7 @@
 	gd->start_addr_sp -= sizeof(gd_t);
 	gd->new_gd = (gd_t *)map_sysmem(gd->start_addr_sp, sizeof(gd_t));
 	debug("Reserving %zu Bytes for Global Data at: %08lx\n",
-			sizeof(gd_t), gd->start_addr_sp);
+	      sizeof(gd_t), gd->start_addr_sp);
 	return 0;
 }
 
diff --git a/common/board_r.c b/common/board_r.c
index 2baa47f..6349e86 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -157,9 +157,9 @@
 #endif
 #ifdef CONFIG_OF_EMBED
 	/*
-	* The fdt_blob needs to be moved to new relocation address
-	* incase of FDT blob is embedded with in image
-	*/
+	 * The fdt_blob needs to be moved to new relocation address
+	 * incase of FDT blob is embedded with in image
+	 */
 	gd->fdt_blob += gd->reloc_off;
 #endif
 #ifdef CONFIG_EFI_LOADER
@@ -351,14 +351,16 @@
 	print_size(flash_size, "");
 #ifdef CONFIG_SYS_FLASH_CHECKSUM
 	/*
-	* Compute and print flash CRC if flashchecksum is set to 'y'
-	*
-	* NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
-	*/
+	 * Compute and print flash CRC if flashchecksum is set to 'y'
+	 *
+	 * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
+	 */
 	if (env_get_yesno("flashchecksum") == 1) {
+		const uchar *flash_base = (const uchar *)CONFIG_SYS_FLASH_BASE;
+
 		printf("  CRC: %08X", crc32(0,
-			(const unsigned char *) CONFIG_SYS_FLASH_BASE,
-			flash_size));
+					    flash_base,
+					    flash_size));
 	}
 #endif /* CONFIG_SYS_FLASH_CHECKSUM */
 	putc('\n');
@@ -375,7 +377,6 @@
 	update_flash_size(flash_size);
 #endif
 
-
 #if defined(CONFIG_OXC) || defined(CONFIG_RMU)
 	/* flash mapped at end of memory map */
 	bd->bi_flashoffset = CONFIG_SYS_TEXT_BASE + flash_size;
@@ -625,7 +626,7 @@
 	char memsz[32];
 
 	pram = env_get_ulong("pram", 10, CONFIG_PRAM);
-	sprintf(memsz, "%ldk", (long int) ((gd->ram_size / 1024) - pram));
+	sprintf(memsz, "%ldk", (long int)((gd->ram_size / 1024) - pram));
 	env_set("mem", memsz);
 
 	return 0;
@@ -678,7 +679,7 @@
 	initr_caches,
 	/* Note: For Freescale LS2 SoCs, new MMU table is created in DDR.
 	 *	 A temporary mapping of IFC high region is since removed,
-	 *	 so environmental variables in NOR flash is not availble
+	 *	 so environmental variables in NOR flash is not available
 	 *	 until board_init() is called below to remap IFC to high
 	 *	 region.
 	 */
@@ -741,7 +742,7 @@
 #if defined(CONFIG_PCI) && defined(CONFIG_SYS_EARLY_PCI_INIT)
 	/*
 	 * Do early PCI configuration _before_ the flash gets initialised,
-	 * because PCU ressources are crucial for flash access on some boards.
+	 * because PCU resources are crucial for flash access on some boards.
 	 */
 	initr_pci,
 #endif
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index d686b1e..65b3aff 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -118,6 +118,13 @@
 	  location is used. Normally we put the device tree at the end of BSS
 	  but with this option enabled, it goes at _image_binary_end.
 
+config SPL_DISABLE_BANNER_PRINT
+	bool "Disable output of the SPL banner 'U-Boot SPL ...'"
+	help
+	  If this option is enabled, SPL will not print the banner with version
+	  info. Selecting this option could be useful to reduce SPL boot time
+	  (e.g. approx. 6 ms slower, when output on i.MX6 with 115200 baud).
+
 config SPL_DISPLAY_PRINT
 	bool "Display a board-specific message in SPL"
 	help
@@ -757,6 +764,13 @@
 
 if TPL
 
+config TPL_BOARD_INIT
+	bool "Call board-specific initialization in TPL"
+	help
+	  If this option is enabled, U-Boot will call the function
+	  spl_board_init() from board_init_r(). This function should be
+	  provided by the board.
+
 config TPL_LDSCRIPT
         string "Linker script for the TPL stage"
 	depends on TPL
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 76c1963..2ebab8f 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -407,7 +407,7 @@
 	timer_init();
 #endif
 
-#ifdef CONFIG_SPL_BOARD_INIT
+#if CONFIG_IS_ENABLED(BOARD_INIT)
 	spl_board_init();
 #endif
 
@@ -477,8 +477,10 @@
 
 	gd->have_console = 1;
 
+#ifndef CONFIG_SPL_DISABLE_BANNER_PRINT
 	puts("\nU-Boot SPL " PLAIN_VERSION " (" U_BOOT_DATE " - " \
 			U_BOOT_TIME ")\n");
+#endif
 #ifdef CONFIG_SPL_DISPLAY_PRINT
 	spl_display_print();
 #endif
diff --git a/configs/am335x_pdu001_defconfig b/configs/am335x_pdu001_defconfig
new file mode 100644
index 0000000..31312b2
--- /dev/null
+++ b/configs/am335x_pdu001_defconfig
@@ -0,0 +1,55 @@
+CONFIG_ARM=y
+CONFIG_ARCH_OMAP2PLUS=y
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_AM33XX=y
+CONFIG_TARGET_PDU001=y
+CONFIG_SPL_MMC_SUPPORT=y
+CONFIG_SPL_SERIAL_SUPPORT=y
+CONFIG_SPL_LIBDISK_SUPPORT=y
+# CONFIG_SPL_NAND_SUPPORT is not set
+CONFIG_SPL_WATCHDOG_SUPPORT=y
+CONFIG_SPL_FAT_SUPPORT=y
+CONFIG_DEFAULT_DEVICE_TREE="am335x-pdu001"
+CONFIG_LOCALVERSION="-EETS-1.0.0"
+CONFIG_BOOTDELAY=1
+CONFIG_SPL=y
+# CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR is not set
+CONFIG_SPL_I2C_SUPPORT=y
+CONFIG_SPL_YMODEM_SUPPORT=y
+CONFIG_HUSH_PARSER=y
+CONFIG_AUTOBOOT_KEYED=y
+CONFIG_AUTOBOOT_PROMPT="Press SPACE to abort autoboot in %d seconds\n"
+CONFIG_AUTOBOOT_STOP_STR=" "
+CONFIG_CMD_BOOTZ=y
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_XIMG is not set
+CONFIG_CMD_MEMINFO=y
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_FPGA is not set
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+# CONFIG_CMD_NET is not set
+# CONFIG_CMD_NFS is not set
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_CMD_FAT=y
+CONFIG_OF_CONTROL=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_EMBED=y
+CONFIG_SPL_DM=y
+CONFIG_DM_GPIO=y
+CONFIG_DM_I2C=y
+CONFIG_MMC_OMAP_HS=y
+CONFIG_MMC_SDHCI=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_SINGLE=y
+CONFIG_DM_PMIC=y
+CONFIG_DM_PMIC_TPS65910=y
+CONFIG_DM_REGULATOR=y
+CONFIG_SPL_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_REGULATOR_TPS65910=y
+CONFIG_SYS_NS16550=y
+# CONFIG_USE_TINY_PRINTF is not set
+# CONFIG_EFI_LOADER is not set
diff --git a/configs/am43xx_evm_qspiboot_defconfig b/configs/am43xx_evm_qspiboot_defconfig
index a56abc9..35a412a 100644
--- a/configs/am43xx_evm_qspiboot_defconfig
+++ b/configs/am43xx_evm_qspiboot_defconfig
@@ -2,7 +2,7 @@
 # CONFIG_SYS_THUMB_BUILD is not set
 CONFIG_ARCH_OMAP2PLUS=y
 CONFIG_AM43XX=y
-CONFIG_ISW_ENTRY_ADDR=0x30000000
+CONFIG_SYS_TEXT_BASE=0x30000000
 CONFIG_SYS_EXTRA_OPTIONS="SERIAL1,CONS_INDEX=1,QSPI,QSPI_BOOT"
 CONFIG_QSPI_BOOT=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
diff --git a/configs/rpi_0_w_defconfig b/configs/rpi_0_w_defconfig
index 1248294..8ed7a58 100644
--- a/configs/rpi_0_w_defconfig
+++ b/configs/rpi_0_w_defconfig
@@ -32,3 +32,7 @@
 CONFIG_CONSOLE_SCROLL_LINES=10
 CONFIG_PHYS_TO_BUS=y
 CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_FULL=y
+# CONFIG_PINCTRL_GENERIC is not set
+CONFIG_PINCTRL_BCM283X=y
diff --git a/configs/rpi_2_defconfig b/configs/rpi_2_defconfig
index c45ffb6..b30e6e1 100644
--- a/configs/rpi_2_defconfig
+++ b/configs/rpi_2_defconfig
@@ -32,3 +32,7 @@
 CONFIG_CONSOLE_SCROLL_LINES=10
 CONFIG_PHYS_TO_BUS=y
 CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_FULL=y
+# CONFIG_PINCTRL_GENERIC is not set
+CONFIG_PINCTRL_BCM283X=y
diff --git a/configs/rpi_3_32b_defconfig b/configs/rpi_3_32b_defconfig
index f7aed35..bb40644 100644
--- a/configs/rpi_3_32b_defconfig
+++ b/configs/rpi_3_32b_defconfig
@@ -34,3 +34,7 @@
 CONFIG_CONSOLE_SCROLL_LINES=10
 CONFIG_PHYS_TO_BUS=y
 CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_FULL=y
+# CONFIG_PINCTRL_GENERIC is not set
+CONFIG_PINCTRL_BCM283X=y
diff --git a/configs/rpi_3_defconfig b/configs/rpi_3_defconfig
index 9416e3b..8306bc2 100644
--- a/configs/rpi_3_defconfig
+++ b/configs/rpi_3_defconfig
@@ -34,3 +34,7 @@
 CONFIG_CONSOLE_SCROLL_LINES=10
 CONFIG_PHYS_TO_BUS=y
 CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_FULL=y
+# CONFIG_PINCTRL_GENERIC is not set
+CONFIG_PINCTRL_BCM283X=y
diff --git a/configs/rpi_defconfig b/configs/rpi_defconfig
index 3bfa745..a7a079d 100644
--- a/configs/rpi_defconfig
+++ b/configs/rpi_defconfig
@@ -32,3 +32,7 @@
 CONFIG_CONSOLE_SCROLL_LINES=10
 CONFIG_PHYS_TO_BUS=y
 CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_FULL=y
+# CONFIG_PINCTRL_GENERIC is not set
+CONFIG_PINCTRL_BCM283X=y
diff --git a/configs/stm32f429-evaluation_defconfig b/configs/stm32f429-evaluation_defconfig
new file mode 100644
index 0000000..0d12fdb
--- /dev/null
+++ b/configs/stm32f429-evaluation_defconfig
@@ -0,0 +1,31 @@
+CONFIG_ARM=y
+CONFIG_STM32=y
+CONFIG_SYS_MALLOC_F_LEN=0xF00
+CONFIG_STM32F4=y
+CONFIG_TARGET_STM32F429_EVALUATION=y
+CONFIG_DEFAULT_DEVICE_TREE="stm32429i-eval"
+CONFIG_BOOTDELAY=3
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="U-Boot > "
+CONFIG_CMD_BOOTZ=y
+# CONFIG_CMD_BOOTEFI_HELLO_COMPILE is not set
+CONFIG_CMD_IMLS=y
+CONFIG_CMD_GPT=y
+# CONFIG_RANDOM_UUID is not set
+CONFIG_CMD_MMC=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIMER=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+# CONFIG_DOS_PARTITION is not set
+CONFIG_OF_CONTROL=y
+CONFIG_OF_EMBED=y
+# CONFIG_BLK is not set
+CONFIG_DM_MMC=y
+CONFIG_ARM_PL180_MMCI=y
+CONFIG_MTD_NOR_FLASH=y
diff --git a/drivers/clk/clk_stm32f.c b/drivers/clk/clk_stm32f.c
index 63116e0..06827fe 100644
--- a/drivers/clk/clk_stm32f.c
+++ b/drivers/clk/clk_stm32f.c
@@ -59,7 +59,7 @@
 #define RCC_PLLCFGR_PLLSAIP_MASK	GENMASK(17, 16)
 #define RCC_PLLSAICFGR_PLLSAIN_SHIFT	6
 #define RCC_PLLSAICFGR_PLLSAIP_SHIFT	16
-#define RCC_PLLSAICFGR_PLLSAIP_4	BIT(17)
+#define RCC_PLLSAICFGR_PLLSAIP_4	BIT(16)
 #define RCC_PLLSAICFGR_PLLSAIQ_4	BIT(26)
 #define RCC_PLLSAICFGR_PLLSAIR_2	BIT(29)
 
@@ -67,8 +67,6 @@
 #define RCC_DCKCFGRX_SDMMC1SEL		BIT(28)
 #define RCC_DCKCFGR2_SDMMC2SEL		BIT(29)
 
-#define RCC_APB2ENR_SAI1EN		BIT(22)
-
 /*
  * RCC AHB1ENR specific definitions
  */
@@ -86,17 +84,15 @@
  * RCC APB2ENR specific definitions
  */
 #define RCC_APB2ENR_SYSCFGEN		BIT(14)
+#define RCC_APB2ENR_SAI1EN		BIT(22)
 
 enum periph_clock {
-	SYSCFG_CLOCK_CFG,
 	TIMER2_CLOCK_CFG,
-	STMMAC_CLOCK_CFG,
 };
 
-struct stm32_clk_info stm32f4_clk_info = {
+static const struct stm32_clk_info stm32f4_clk_info = {
 	/* 180 MHz */
 	.sys_pll_psc = {
-		.pll_m = 8,
 		.pll_n = 360,
 		.pll_p = 2,
 		.pll_q = 8,
@@ -108,10 +104,9 @@
 	.v2 = false,
 };
 
-struct stm32_clk_info stm32f7_clk_info = {
+static const struct stm32_clk_info stm32f7_clk_info = {
 	/* 200 MHz */
 	.sys_pll_psc = {
-		.pll_m = 25,
 		.pll_n = 400,
 		.pll_p = 2,
 		.pll_q = 8,
@@ -126,7 +121,8 @@
 struct stm32_clk {
 	struct stm32_rcc_regs *base;
 	struct stm32_pwr_regs *pwr_regs;
-	struct stm32_clk_info *info;
+	struct stm32_clk_info info;
+	unsigned long hse_rate;
 };
 
 static int configure_clocks(struct udevice *dev)
@@ -134,7 +130,7 @@
 	struct stm32_clk *priv = dev_get_priv(dev);
 	struct stm32_rcc_regs *regs = priv->base;
 	struct stm32_pwr_regs *pwr = priv->pwr_regs;
-	struct pll_psc sys_pll_psc = priv->info->sys_pll_psc;
+	struct pll_psc *sys_pll_psc = &priv->info.sys_pll_psc;
 	u32 pllsaicfgr = 0;
 
 	/* Reset RCC configuration */
@@ -152,20 +148,20 @@
 		;
 
 	setbits_le32(&regs->cfgr, ((
-		sys_pll_psc.ahb_psc << RCC_CFGR_HPRE_SHIFT)
-		| (sys_pll_psc.apb1_psc << RCC_CFGR_PPRE1_SHIFT)
-		| (sys_pll_psc.apb2_psc << RCC_CFGR_PPRE2_SHIFT)));
+		sys_pll_psc->ahb_psc << RCC_CFGR_HPRE_SHIFT)
+		| (sys_pll_psc->apb1_psc << RCC_CFGR_PPRE1_SHIFT)
+		| (sys_pll_psc->apb2_psc << RCC_CFGR_PPRE2_SHIFT)));
 
 	/* Configure the main PLL */
 	setbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLSRC); /* pll source HSE */
 	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLM_MASK,
-			sys_pll_psc.pll_m << RCC_PLLCFGR_PLLM_SHIFT);
+			sys_pll_psc->pll_m << RCC_PLLCFGR_PLLM_SHIFT);
 	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLN_MASK,
-			sys_pll_psc.pll_n << RCC_PLLCFGR_PLLN_SHIFT);
+			sys_pll_psc->pll_n << RCC_PLLCFGR_PLLN_SHIFT);
 	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLP_MASK,
-			((sys_pll_psc.pll_p >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT);
+			((sys_pll_psc->pll_p >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT);
 	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLQ_MASK,
-			sys_pll_psc.pll_q << RCC_PLLCFGR_PLLQ_SHIFT);
+			sys_pll_psc->pll_q << RCC_PLLCFGR_PLLQ_SHIFT);
 
 	/* Configure the SAI PLL to get a 48 MHz source */
 	pllsaicfgr = RCC_PLLSAICFGR_PLLSAIR_2 | RCC_PLLSAICFGR_PLLSAIQ_4 |
@@ -178,7 +174,7 @@
 	while (!(readl(&regs->cr) & RCC_CR_PLLRDY))
 		;
 
-	if (priv->info->v2) { /*stm32f7 case */
+	if (priv->info.v2) { /*stm32f7 case */
 		/* select PLLSAI as 48MHz clock source */
 		setbits_le32(&regs->dckcfgr2, RCC_DCKCFGRX_CK48MSEL);
 
@@ -202,7 +198,7 @@
 
 	setbits_le32(&regs->apb1enr, RCC_APB1ENR_PWREN);
 
-	if (priv->info->has_overdrive) {
+	if (priv->info.has_overdrive) {
 		/*
 		 * Enable high performance mode
 		 * System frequency up to 200 MHz
@@ -228,6 +224,11 @@
 	/* gate the SAI clock, needed for MMC 1&2 clocks */
 	setbits_le32(&regs->apb2enr, RCC_APB2ENR_SAI1EN);
 
+#ifdef CONFIG_ETH_DESIGNWARE
+	/* gate the SYSCFG clock, needed to set RMII ethernet interface */
+	setbits_le32(&regs->apb2enr, RCC_APB2ENR_SYSCFGEN);
+#endif
+
 	return 0;
 }
 
@@ -241,7 +242,7 @@
 	pllq = (readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLQ_MASK)
 	       >> RCC_PLLCFGR_PLLQ_SHIFT;
 
-	if (priv->info->v2) /*stm32f7 case */
+	if (priv->info.v2) /*stm32f7 case */
 		pllsai = readl(&regs->dckcfgr2) & RCC_DCKCFGRX_CK48MSEL;
 	else
 		pllsai = readl(&regs->dckcfgr) & RCC_DCKCFGRX_CK48MSEL;
@@ -253,7 +254,7 @@
 			>> RCC_PLLSAICFGR_PLLSAIN_SHIFT);
 		pllsaip = ((((readl(&regs->pllsaicfgr) & RCC_PLLCFGR_PLLSAIP_MASK)
 			>> RCC_PLLSAICFGR_PLLSAIP_SHIFT) + 1) << 1);
-		return ((CONFIG_STM32_HSE_HZ / pllm) * pllsain) / pllsaip;
+		return ((priv->hse_rate / pllm) * pllsain) / pllsaip;
 	}
 	/* PLL48CLK is selected from PLLQ */
 	return sysclk / pllq;
@@ -281,7 +282,7 @@
 			>> RCC_PLLCFGR_PLLN_SHIFT);
 		pllp = ((((readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLP_MASK)
 			>> RCC_PLLCFGR_PLLP_SHIFT) + 1) << 1);
-		sysclk = ((CONFIG_STM32_HSE_HZ / pllm) * plln) / pllp;
+		sysclk = ((priv->hse_rate / pllm) * plln) / pllp;
 	} else {
 		return -EINVAL;
 	}
@@ -353,17 +354,9 @@
 void clock_setup(int peripheral)
 {
 	switch (peripheral) {
-	case SYSCFG_CLOCK_CFG:
-		setbits_le32(&STM32_RCC->apb2enr, RCC_APB2ENR_SYSCFGEN);
-		break;
 	case TIMER2_CLOCK_CFG:
 		setbits_le32(&STM32_RCC->apb1enr, RCC_APB1ENR_TIM2EN);
 		break;
-	case STMMAC_CLOCK_CFG:
-		setbits_le32(&STM32_RCC->ahb1enr, RCC_AHB1ENR_ETHMAC_EN);
-		setbits_le32(&STM32_RCC->ahb1enr, RCC_AHB1ENR_ETHMAC_RX_EN);
-		setbits_le32(&STM32_RCC->ahb1enr, RCC_AHB1ENR_ETHMAC_TX_EN);
-		break;
 	default:
 		break;
 	}
@@ -372,6 +365,8 @@
 static int stm32_clk_probe(struct udevice *dev)
 {
 	struct ofnode_phandle_args args;
+	struct udevice *fixed_clock_dev = NULL;
+	struct clk clk;
 	int err;
 
 	debug("%s\n", __func__);
@@ -387,16 +382,51 @@
 
 	switch (dev_get_driver_data(dev)) {
 	case STM32F4:
-		priv->info = &stm32f4_clk_info;
+		memcpy(&priv->info, &stm32f4_clk_info,
+		       sizeof(struct stm32_clk_info));
 		break;
 	case STM32F7:
-		priv->info = &stm32f7_clk_info;
+		memcpy(&priv->info, &stm32f7_clk_info,
+		       sizeof(struct stm32_clk_info));
 		break;
 	default:
 		return -EINVAL;
 	}
 
+	/* retrieve HSE frequency (external oscillator) */
+	err = uclass_get_device_by_name(UCLASS_CLK, "clk-hse",
+					&fixed_clock_dev);
+
+	if (err) {
+		pr_err("Can't find fixed clock (%d)", err);
+		return err;
+	}
+
+	err = clk_request(fixed_clock_dev, &clk);
+	if (err) {
+		pr_err("Can't request %s clk (%d)", fixed_clock_dev->name,
+		       err);
+		return err;
+	}
+
+	/*
+	 * set pllm factor accordingly to the external oscillator
+	 * frequency (HSE). For STM32F4 and STM32F7, we want VCO
+	 * freq at 1MHz
+	 * if input PLL frequency is 25Mhz, divide it by 25
+	 */
+	clk.id = 0;
+	priv->hse_rate = clk_get_rate(&clk);
+
+	if (priv->hse_rate < 1000000) {
+		pr_err("%s: unexpected HSE clock rate = %ld \"n", __func__,
+		       priv->hse_rate);
+		return -EINVAL;
+	}
+
-	if (priv->info->has_overdrive) {
+	priv->info.sys_pll_psc.pll_m = priv->hse_rate / 1000000;
+
+	if (priv->info.has_overdrive) {
 		err = dev_read_phandle_with_args(dev, "st,syscfg", NULL, 0, 0,
 						 &args);
 		if (err) {
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index b4e859e..b121979 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -276,11 +276,11 @@
 	  Now, max 24 bits chips and PCA953X compatible chips are
 	  supported
 
-config MPC85XX_GPIO
-	bool "Freescale MPC85XX GPIO driver"
+config MPC8XXX_GPIO
+	bool "Freescale MPC8XXX GPIO driver"
 	depends on DM_GPIO
 	help
-	  This driver supports the built-in GPIO controller of MPC85XX CPUs.
+	  This driver supports the built-in GPIO controller of MPC8XXX CPUs.
 	  Each GPIO bank is identified by its own entry in the device tree,
 	  i.e.
 
@@ -298,7 +298,4 @@
 	  Aside from the standard functions of input/output mode, and output
 	  value setting, the open-drain feature, which can configure individual
 	  GPIOs to work as open-drain outputs, is supported.
-
-	  The driver has been tested on MPC85XX, but it is likely that other
-	  PowerQUICC III devices will work as well.
 endmenu
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 8525679..266c958 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -38,7 +38,7 @@
 obj-$(CONFIG_DM644X_GPIO)	+= da8xx_gpio.o
 obj-$(CONFIG_ALTERA_PIO)	+= altera_pio.o
 obj-$(CONFIG_MPC83XX_GPIO)	+= mpc83xx_gpio.o
-obj-$(CONFIG_MPC85XX_GPIO)	+= mpc85xx_gpio.o
+obj-$(CONFIG_MPC8XXX_GPIO)	+= mpc8xxx_gpio.o
 obj-$(CONFIG_SH_GPIO_PFC)	+= sh_pfc.o
 obj-$(CONFIG_OMAP_GPIO)	+= omap_gpio.o
 obj-$(CONFIG_DB8500_GPIO)	+= db8500_gpio.o
diff --git a/drivers/gpio/bcm2835_gpio.c b/drivers/gpio/bcm2835_gpio.c
index beaa218..d68f8df 100644
--- a/drivers/gpio/bcm2835_gpio.c
+++ b/drivers/gpio/bcm2835_gpio.c
@@ -7,6 +7,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <dm/pinctrl.h>
 #include <errno.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
@@ -14,6 +15,7 @@
 
 struct bcm2835_gpios {
 	struct bcm2835_gpio_regs *reg;
+	struct udevice *pinctrl;
 };
 
 static int bcm2835_gpio_direction_input(struct udevice *dev, unsigned gpio)
@@ -29,7 +31,7 @@
 	return 0;
 }
 
-static int bcm2835_gpio_direction_output(struct udevice *dev, unsigned gpio,
+static int bcm2835_gpio_direction_output(struct udevice *dev, unsigned int gpio,
 					 int value)
 {
 	struct bcm2835_gpios *gpios = dev_get_priv(dev);
@@ -73,19 +75,12 @@
 	return 0;
 }
 
-int bcm2835_gpio_get_func_id(struct udevice *dev, unsigned gpio)
-{
-	struct bcm2835_gpios *gpios = dev_get_priv(dev);
-	u32 val;
-
-	val = readl(&gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
-
-	return (val >> BCM2835_GPIO_FSEL_SHIFT(gpio) & BCM2835_GPIO_FSEL_MASK);
-}
-
 static int bcm2835_gpio_get_function(struct udevice *dev, unsigned offset)
 {
-	int funcid = bcm2835_gpio_get_func_id(dev, offset);
+	struct bcm2835_gpios *priv = dev_get_priv(dev);
+	int funcid;
+
+	funcid = pinctrl_get_gpio_mux(priv->pinctrl, 0, offset);
 
 	switch (funcid) {
 	case BCM2835_GPIO_OUTPUT:
@@ -97,7 +92,6 @@
 	}
 }
 
-
 static const struct dm_gpio_ops gpio_bcm2835_ops = {
 	.direction_input	= bcm2835_gpio_direction_input,
 	.direction_output	= bcm2835_gpio_direction_output,
@@ -116,15 +110,13 @@
 	uc_priv->gpio_count = BCM2835_GPIO_COUNT;
 	gpios->reg = (struct bcm2835_gpio_regs *)plat->base;
 
+	/* We know we're spawned by the pinctrl driver */
+	gpios->pinctrl = dev->parent;
+
 	return 0;
 }
 
 #if CONFIG_IS_ENABLED(OF_CONTROL)
-static const struct udevice_id bcm2835_gpio_id[] = {
-	{.compatible = "brcm,bcm2835-gpio"},
-	{}
-};
-
 static int bcm2835_gpio_ofdata_to_platdata(struct udevice *dev)
 {
 	struct bcm2835_gpio_platdata *plat = dev_get_platdata(dev);
@@ -142,7 +134,6 @@
 U_BOOT_DRIVER(gpio_bcm2835) = {
 	.name	= "gpio_bcm2835",
 	.id	= UCLASS_GPIO,
-	.of_match = of_match_ptr(bcm2835_gpio_id),
 	.ofdata_to_platdata = of_match_ptr(bcm2835_gpio_ofdata_to_platdata),
 	.platdata_auto_alloc_size = sizeof(struct bcm2835_gpio_platdata),
 	.ops	= &gpio_bcm2835_ops,
diff --git a/drivers/gpio/mpc85xx_gpio.c b/drivers/gpio/mpc85xx_gpio.c
deleted file mode 100644
index cfeb6e7..0000000
--- a/drivers/gpio/mpc85xx_gpio.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * (C) Copyright 2016
- * Mario Six, Guntermann & Drunck GmbH, six@gdsys.de
- *
- * based on arch/powerpc/include/asm/mpc85xx_gpio.h, which is
- *
- * Copyright 2010 eXMeritus, A Boeing Company
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <dm.h>
-#include <asm/gpio.h>
-#include <mapmem.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-struct ccsr_gpio {
-	u32	gpdir;
-	u32	gpodr;
-	u32	gpdat;
-	u32	gpier;
-	u32	gpimr;
-	u32	gpicr;
-};
-
-struct mpc85xx_gpio_data {
-	/* The bank's register base in memory */
-	struct ccsr_gpio __iomem *base;
-	/* The address of the registers; used to identify the bank */
-	ulong addr;
-	/* The GPIO count of the bank */
-	uint gpio_count;
-	/* The GPDAT register cannot be used to determine the value of output
-	 * pins on MPC8572/MPC8536, so we shadow it and use the shadowed value
-	 * for output pins */
-	u32 dat_shadow;
-};
-
-inline u32 gpio_mask(unsigned gpio) {
-	return (1U << (31 - (gpio)));
-}
-
-static inline u32 mpc85xx_gpio_get_val(struct ccsr_gpio *base, u32 mask)
-{
-	return in_be32(&base->gpdat) & mask;
-}
-
-static inline u32 mpc85xx_gpio_get_dir(struct ccsr_gpio *base, u32 mask)
-{
-	return in_be32(&base->gpdir) & mask;
-}
-
-static inline void mpc85xx_gpio_set_in(struct ccsr_gpio *base, u32 gpios)
-{
-	clrbits_be32(&base->gpdat, gpios);
-	/* GPDIR register 0 -> input */
-	clrbits_be32(&base->gpdir, gpios);
-}
-
-static inline void mpc85xx_gpio_set_low(struct ccsr_gpio *base, u32 gpios)
-{
-	clrbits_be32(&base->gpdat, gpios);
-	/* GPDIR register 1 -> output */
-	setbits_be32(&base->gpdir, gpios);
-}
-
-static inline void mpc85xx_gpio_set_high(struct ccsr_gpio *base, u32 gpios)
-{
-	setbits_be32(&base->gpdat, gpios);
-	/* GPDIR register 1 -> output */
-	setbits_be32(&base->gpdir, gpios);
-}
-
-static inline int mpc85xx_gpio_open_drain_val(struct ccsr_gpio *base, u32 mask)
-{
-	return in_be32(&base->gpodr) & mask;
-}
-
-static inline void mpc85xx_gpio_open_drain_on(struct ccsr_gpio *base, u32
-					      gpios)
-{
-	/* GPODR register 1 -> open drain on */
-	setbits_be32(&base->gpodr, gpios);
-}
-
-static inline void mpc85xx_gpio_open_drain_off(struct ccsr_gpio *base,
-					       u32 gpios)
-{
-	/* GPODR register 0 -> open drain off (actively driven) */
-	clrbits_be32(&base->gpodr, gpios);
-}
-
-static int mpc85xx_gpio_direction_input(struct udevice *dev, unsigned gpio)
-{
-	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
-
-	mpc85xx_gpio_set_in(data->base, gpio_mask(gpio));
-	return 0;
-}
-
-static int mpc85xx_gpio_set_value(struct udevice *dev, unsigned gpio,
-				  int value)
-{
-	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
-
-	if (value) {
-		data->dat_shadow |= gpio_mask(gpio);
-		mpc85xx_gpio_set_high(data->base, gpio_mask(gpio));
-	} else {
-		data->dat_shadow &= ~gpio_mask(gpio);
-		mpc85xx_gpio_set_low(data->base, gpio_mask(gpio));
-	}
-	return 0;
-}
-
-static int mpc85xx_gpio_direction_output(struct udevice *dev, unsigned gpio,
-					 int value)
-{
-	return mpc85xx_gpio_set_value(dev, gpio, value);
-}
-
-static int mpc85xx_gpio_get_value(struct udevice *dev, unsigned gpio)
-{
-	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
-
-	if (!!mpc85xx_gpio_get_dir(data->base, gpio_mask(gpio))) {
-		/* Output -> use shadowed value */
-		return !!(data->dat_shadow & gpio_mask(gpio));
-	} else {
-		/* Input -> read value from GPDAT register */
-		return !!mpc85xx_gpio_get_val(data->base, gpio_mask(gpio));
-	}
-}
-
-static int mpc85xx_gpio_get_open_drain(struct udevice *dev, unsigned gpio)
-{
-	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
-
-	return !!mpc85xx_gpio_open_drain_val(data->base, gpio_mask(gpio));
-}
-
-static int mpc85xx_gpio_set_open_drain(struct udevice *dev, unsigned gpio,
-				       int value)
-{
-	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
-
-	if (value) {
-		mpc85xx_gpio_open_drain_on(data->base, gpio_mask(gpio));
-	} else {
-		mpc85xx_gpio_open_drain_off(data->base, gpio_mask(gpio));
-	}
-	return 0;
-}
-
-static int mpc85xx_gpio_get_function(struct udevice *dev, unsigned gpio)
-{
-	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
-	int dir;
-
-	dir = !!mpc85xx_gpio_get_dir(data->base, gpio_mask(gpio));
-	return dir ? GPIOF_OUTPUT : GPIOF_INPUT;
-}
-
-#if CONFIG_IS_ENABLED(OF_CONTROL)
-static int mpc85xx_gpio_ofdata_to_platdata(struct udevice *dev) {
-	struct mpc85xx_gpio_plat *plat = dev_get_platdata(dev);
-	fdt_addr_t addr;
-	fdt_size_t size;
-
-	addr = fdtdec_get_addr_size_auto_noparent(gd->fdt_blob,
-			dev_of_offset(dev), "reg", 0, &size, false);
-
-	plat->addr = addr;
-	plat->size = size;
-	plat->ngpios = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
-				      "ngpios", 32);
-
-	return 0;
-}
-#endif
-
-static int mpc85xx_gpio_platdata_to_priv(struct udevice *dev)
-{
-	struct mpc85xx_gpio_data *priv = dev_get_priv(dev);
-	struct mpc85xx_gpio_plat *plat = dev_get_platdata(dev);
-	unsigned long size = plat->size;
-
-	if (size == 0)
-		size = 0x100;
-
-	priv->addr = plat->addr;
-	priv->base = map_sysmem(CONFIG_SYS_IMMR + plat->addr, size);
-
-	if (!priv->base)
-		return -ENOMEM;
-
-	priv->gpio_count = plat->ngpios;
-	priv->dat_shadow = 0;
-
-	return 0;
-}
-
-static int mpc85xx_gpio_probe(struct udevice *dev)
-{
-	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
-	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
-	char name[32], *str;
-
-	mpc85xx_gpio_platdata_to_priv(dev);
-
-	snprintf(name, sizeof(name), "MPC@%lx_", data->addr);
-	str = strdup(name);
-
-	if (!str)
-		return -ENOMEM;
-
-	uc_priv->bank_name = str;
-	uc_priv->gpio_count = data->gpio_count;
-
-	return 0;
-}
-
-static const struct dm_gpio_ops gpio_mpc85xx_ops = {
-	.direction_input	= mpc85xx_gpio_direction_input,
-	.direction_output	= mpc85xx_gpio_direction_output,
-	.get_value		= mpc85xx_gpio_get_value,
-	.set_value		= mpc85xx_gpio_set_value,
-	.get_open_drain		= mpc85xx_gpio_get_open_drain,
-	.set_open_drain		= mpc85xx_gpio_set_open_drain,
-	.get_function 		= mpc85xx_gpio_get_function,
-};
-
-static const struct udevice_id mpc85xx_gpio_ids[] = {
-	{ .compatible = "fsl,pq3-gpio" },
-	{ /* sentinel */ }
-};
-
-U_BOOT_DRIVER(gpio_mpc85xx) = {
-	.name	= "gpio_mpc85xx",
-	.id	= UCLASS_GPIO,
-	.ops	= &gpio_mpc85xx_ops,
-#if CONFIG_IS_ENABLED(OF_CONTROL)
-	.ofdata_to_platdata = mpc85xx_gpio_ofdata_to_platdata,
-	.platdata_auto_alloc_size = sizeof(struct mpc85xx_gpio_plat),
-	.of_match = mpc85xx_gpio_ids,
-#endif
-	.probe	= mpc85xx_gpio_probe,
-	.priv_auto_alloc_size = sizeof(struct mpc85xx_gpio_data),
-};
diff --git a/drivers/gpio/mpc8xxx_gpio.c b/drivers/gpio/mpc8xxx_gpio.c
new file mode 100644
index 0000000..326fd16
--- /dev/null
+++ b/drivers/gpio/mpc8xxx_gpio.c
@@ -0,0 +1,271 @@
+/*
+ * (C) Copyright 2016
+ * Mario Six, Guntermann & Drunck GmbH, six@gdsys.de
+ *
+ * based on arch/powerpc/include/asm/mpc85xx_gpio.h, which is
+ *
+ * Copyright 2010 eXMeritus, A Boeing Company
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <asm/gpio.h>
+
+struct ccsr_gpio {
+	u32	gpdir;
+	u32	gpodr;
+	u32	gpdat;
+	u32	gpier;
+	u32	gpimr;
+	u32	gpicr;
+};
+
+struct mpc8xxx_gpio_data {
+	/* The bank's register base in memory */
+	struct ccsr_gpio __iomem *base;
+	/* The address of the registers; used to identify the bank */
+	ulong addr;
+	/* The GPIO count of the bank */
+	uint gpio_count;
+	/* The GPDAT register cannot be used to determine the value of output
+	 * pins on MPC8572/MPC8536, so we shadow it and use the shadowed value
+	 * for output pins
+	 */
+	u32 dat_shadow;
+	ulong type;
+};
+
+enum {
+	MPC8XXX_GPIO_TYPE,
+	MPC5121_GPIO_TYPE,
+};
+
+inline u32 gpio_mask(uint gpio)
+{
+	return (1U << (31 - (gpio)));
+}
+
+static inline u32 mpc8xxx_gpio_get_val(struct ccsr_gpio *base, u32 mask)
+{
+	return in_be32(&base->gpdat) & mask;
+}
+
+static inline u32 mpc8xxx_gpio_get_dir(struct ccsr_gpio *base, u32 mask)
+{
+	return in_be32(&base->gpdir) & mask;
+}
+
+static inline void mpc8xxx_gpio_set_in(struct ccsr_gpio *base, u32 gpios)
+{
+	clrbits_be32(&base->gpdat, gpios);
+	/* GPDIR register 0 -> input */
+	clrbits_be32(&base->gpdir, gpios);
+}
+
+static inline void mpc8xxx_gpio_set_low(struct ccsr_gpio *base, u32 gpios)
+{
+	clrbits_be32(&base->gpdat, gpios);
+	/* GPDIR register 1 -> output */
+	setbits_be32(&base->gpdir, gpios);
+}
+
+static inline void mpc8xxx_gpio_set_high(struct ccsr_gpio *base, u32 gpios)
+{
+	setbits_be32(&base->gpdat, gpios);
+	/* GPDIR register 1 -> output */
+	setbits_be32(&base->gpdir, gpios);
+}
+
+static inline int mpc8xxx_gpio_open_drain_val(struct ccsr_gpio *base, u32 mask)
+{
+	return in_be32(&base->gpodr) & mask;
+}
+
+static inline void mpc8xxx_gpio_open_drain_on(struct ccsr_gpio *base, u32
+					      gpios)
+{
+	/* GPODR register 1 -> open drain on */
+	setbits_be32(&base->gpodr, gpios);
+}
+
+static inline void mpc8xxx_gpio_open_drain_off(struct ccsr_gpio *base,
+					       u32 gpios)
+{
+	/* GPODR register 0 -> open drain off (actively driven) */
+	clrbits_be32(&base->gpodr, gpios);
+}
+
+static int mpc8xxx_gpio_direction_input(struct udevice *dev, uint gpio)
+{
+	struct mpc8xxx_gpio_data *data = dev_get_priv(dev);
+
+	mpc8xxx_gpio_set_in(data->base, gpio_mask(gpio));
+	return 0;
+}
+
+static int mpc8xxx_gpio_set_value(struct udevice *dev, uint gpio, int value)
+{
+	struct mpc8xxx_gpio_data *data = dev_get_priv(dev);
+
+	if (value) {
+		data->dat_shadow |= gpio_mask(gpio);
+		mpc8xxx_gpio_set_high(data->base, gpio_mask(gpio));
+	} else {
+		data->dat_shadow &= ~gpio_mask(gpio);
+		mpc8xxx_gpio_set_low(data->base, gpio_mask(gpio));
+	}
+	return 0;
+}
+
+static int mpc8xxx_gpio_direction_output(struct udevice *dev, uint gpio,
+					 int value)
+{
+	struct mpc8xxx_gpio_data *data = dev_get_priv(dev);
+
+	/* GPIO 28..31 are input only on MPC5121 */
+	if (data->type == MPC5121_GPIO_TYPE && gpio >= 28)
+		return -EINVAL;
+
+	return mpc8xxx_gpio_set_value(dev, gpio, value);
+}
+
+static int mpc8xxx_gpio_get_value(struct udevice *dev, uint gpio)
+{
+	struct mpc8xxx_gpio_data *data = dev_get_priv(dev);
+
+	if (!!mpc8xxx_gpio_get_dir(data->base, gpio_mask(gpio))) {
+		/* Output -> use shadowed value */
+		return !!(data->dat_shadow & gpio_mask(gpio));
+	}
+
+	/* Input -> read value from GPDAT register */
+	return !!mpc8xxx_gpio_get_val(data->base, gpio_mask(gpio));
+}
+
+static int mpc8xxx_gpio_get_open_drain(struct udevice *dev, uint gpio)
+{
+	struct mpc8xxx_gpio_data *data = dev_get_priv(dev);
+
+	return !!mpc8xxx_gpio_open_drain_val(data->base, gpio_mask(gpio));
+}
+
+static int mpc8xxx_gpio_set_open_drain(struct udevice *dev, uint gpio,
+				       int value)
+{
+	struct mpc8xxx_gpio_data *data = dev_get_priv(dev);
+
+	if (value)
+		mpc8xxx_gpio_open_drain_on(data->base, gpio_mask(gpio));
+	else
+		mpc8xxx_gpio_open_drain_off(data->base, gpio_mask(gpio));
+
+	return 0;
+}
+
+static int mpc8xxx_gpio_get_function(struct udevice *dev, uint gpio)
+{
+	struct mpc8xxx_gpio_data *data = dev_get_priv(dev);
+	int dir;
+
+	dir = !!mpc8xxx_gpio_get_dir(data->base, gpio_mask(gpio));
+	return dir ? GPIOF_OUTPUT : GPIOF_INPUT;
+}
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static int mpc8xxx_gpio_ofdata_to_platdata(struct udevice *dev)
+{
+	struct mpc8xxx_gpio_plat *plat = dev_get_platdata(dev);
+	fdt_addr_t addr;
+	u32 reg[2];
+
+	dev_read_u32_array(dev, "reg", reg, 2);
+	addr = dev_translate_address(dev, reg);
+
+	plat->addr = addr;
+	plat->size = reg[1];
+	plat->ngpios = dev_read_u32_default(dev, "ngpios", 32);
+
+	return 0;
+}
+#endif
+
+static int mpc8xxx_gpio_platdata_to_priv(struct udevice *dev)
+{
+	struct mpc8xxx_gpio_data *priv = dev_get_priv(dev);
+	struct mpc8xxx_gpio_plat *plat = dev_get_platdata(dev);
+	unsigned long size = plat->size;
+	ulong driver_data = dev_get_driver_data(dev);
+
+	if (size == 0)
+		size = 0x100;
+
+	priv->addr = plat->addr;
+	priv->base = map_sysmem(plat->addr, size);
+
+	if (!priv->base)
+		return -ENOMEM;
+
+	priv->gpio_count = plat->ngpios;
+	priv->dat_shadow = 0;
+
+	priv->type = driver_data;
+
+	return 0;
+}
+
+static int mpc8xxx_gpio_probe(struct udevice *dev)
+{
+	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct mpc8xxx_gpio_data *data = dev_get_priv(dev);
+	char name[32], *str;
+
+	mpc8xxx_gpio_platdata_to_priv(dev);
+
+	snprintf(name, sizeof(name), "MPC@%lx_", data->addr);
+	str = strdup(name);
+
+	if (!str)
+		return -ENOMEM;
+
+	uc_priv->bank_name = str;
+	uc_priv->gpio_count = data->gpio_count;
+
+	return 0;
+}
+
+static const struct dm_gpio_ops gpio_mpc8xxx_ops = {
+	.direction_input	= mpc8xxx_gpio_direction_input,
+	.direction_output	= mpc8xxx_gpio_direction_output,
+	.get_value		= mpc8xxx_gpio_get_value,
+	.set_value		= mpc8xxx_gpio_set_value,
+	.get_open_drain		= mpc8xxx_gpio_get_open_drain,
+	.set_open_drain		= mpc8xxx_gpio_set_open_drain,
+	.get_function		= mpc8xxx_gpio_get_function,
+};
+
+static const struct udevice_id mpc8xxx_gpio_ids[] = {
+	{ .compatible = "fsl,pq3-gpio", .data = MPC8XXX_GPIO_TYPE },
+	{ .compatible = "fsl,mpc8308-gpio", .data = MPC8XXX_GPIO_TYPE },
+	{ .compatible = "fsl,mpc8349-gpio", .data = MPC8XXX_GPIO_TYPE },
+	{ .compatible = "fsl,mpc8572-gpio", .data = MPC8XXX_GPIO_TYPE},
+	{ .compatible = "fsl,mpc8610-gpio", .data = MPC8XXX_GPIO_TYPE},
+	{ .compatible = "fsl,mpc5121-gpio", .data = MPC5121_GPIO_TYPE, },
+	{ .compatible = "fsl,qoriq-gpio", .data = MPC8XXX_GPIO_TYPE },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(gpio_mpc8xxx) = {
+	.name	= "gpio_mpc8xxx",
+	.id	= UCLASS_GPIO,
+	.ops	= &gpio_mpc8xxx_ops,
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+	.ofdata_to_platdata = mpc8xxx_gpio_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct mpc8xxx_gpio_plat),
+	.of_match = mpc8xxx_gpio_ids,
+#endif
+	.probe	= mpc8xxx_gpio_probe,
+	.priv_auto_alloc_size = sizeof(struct mpc8xxx_gpio_data),
+};
diff --git a/drivers/gpio/pca953x_gpio.c b/drivers/gpio/pca953x_gpio.c
index 791d1d1..a8a5a89 100644
--- a/drivers/gpio/pca953x_gpio.c
+++ b/drivers/gpio/pca953x_gpio.c
@@ -50,8 +50,6 @@
 #define MAX_BANK 5
 #define BANK_SZ 8
 
-DECLARE_GLOBAL_DATA_PTR;
-
 /*
  * struct pca953x_info - Data for pca953x
  *
@@ -123,7 +121,8 @@
 		ret = dm_i2c_read(dev, reg << 1, val, info->bank_count);
 	} else if (info->gpio_count == 40) {
 		/* Auto increment */
-		ret = dm_i2c_read(dev, (reg << 3) | 0x80, val, info->bank_count);
+		ret = dm_i2c_read(dev, (reg << 3) | 0x80, val,
+				  info->bank_count);
 	} else {
 		dev_err(dev, "Unsupported now\n");
 		return -EINVAL;
@@ -143,7 +142,7 @@
 	return !(info->reg_direction[bank] & (1 << off));
 }
 
-static int pca953x_get_value(struct udevice *dev, unsigned offset)
+static int pca953x_get_value(struct udevice *dev, uint offset)
 {
 	int ret;
 	u8 val = 0;
@@ -157,8 +156,7 @@
 	return (val >> off) & 0x1;
 }
 
-static int pca953x_set_value(struct udevice *dev, unsigned offset,
-			     int value)
+static int pca953x_set_value(struct udevice *dev, uint offset, int value)
 {
 	struct pca953x_info *info = dev_get_platdata(dev);
 	int bank = offset / BANK_SZ;
@@ -180,7 +178,7 @@
 	return 0;
 }
 
-static int pca953x_set_direction(struct udevice *dev, unsigned offset, int dir)
+static int pca953x_set_direction(struct udevice *dev, uint offset, int dir)
 {
 	struct pca953x_info *info = dev_get_platdata(dev);
 	int bank = offset / BANK_SZ;
@@ -202,13 +200,12 @@
 	return 0;
 }
 
-static int pca953x_direction_input(struct udevice *dev, unsigned offset)
+static int pca953x_direction_input(struct udevice *dev, uint offset)
 {
 	return pca953x_set_direction(dev, offset, PCA953X_DIRECTION_IN);
 }
 
-static int pca953x_direction_output(struct udevice *dev, unsigned offset,
-				    int value)
+static int pca953x_direction_output(struct udevice *dev, uint offset, int value)
 {
 	/* Configure output value. */
 	pca953x_set_value(dev, offset, value);
@@ -219,7 +216,7 @@
 	return 0;
 }
 
-static int pca953x_get_function(struct udevice *dev, unsigned offset)
+static int pca953x_get_function(struct udevice *dev, uint offset)
 {
 	if (pca953x_is_output(dev, offset))
 		return GPIOF_OUTPUT;
@@ -231,7 +228,7 @@
 			 struct ofnode_phandle_args *args)
 {
 	desc->offset = args->args[0];
-	desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
+	desc->flags = args->args[1] & (GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0);
 
 	return 0;
 }
@@ -254,7 +251,7 @@
 	ulong driver_data;
 	int ret;
 
-	addr = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "reg", 0);
+	addr = dev_read_addr(dev);
 	if (addr == 0)
 		return -ENODEV;
 
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index bc29611..a1b21fd 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -261,6 +261,20 @@
 	  This selects support for the Matsushita SD/MMC Host Controller on
 	  SocioNext UniPhier and Renesas RCar SoCs.
 
+config MMC_BCM2835
+	bool "BCM2835 family custom SD/MMC Host Controller support"
+	depends on ARCH_BCM283X
+	depends on BLK && DM_MMC
+	depends on OF_CONTROL
+	default y
+	help
+	  This selects support for the custom SD host controller in the BCM2835
+	  family of devices.
+
+	  If you have a BCM2835 platform with SD or MMC devices, say Y here.
+
+	  If unsure, say N.
+
 config MMC_SANDBOX
 	bool "Sandbox MMC support"
 	depends on SANDBOX
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 64b6f21..42113e2 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -64,3 +64,4 @@
 
 obj-$(CONFIG_MMC_SUNXI)			+= sunxi_mmc.o
 obj-$(CONFIG_MMC_UNIPHIER)		+= uniphier-sd.o
+obj-$(CONFIG_MMC_BCM2835)		+= bcm2835_sdhost.o
diff --git a/drivers/mmc/bcm2835_sdhost.c b/drivers/mmc/bcm2835_sdhost.c
new file mode 100644
index 0000000..1bf52a3
--- /dev/null
+++ b/drivers/mmc/bcm2835_sdhost.c
@@ -0,0 +1,979 @@
+/*
+ * bcm2835 sdhost driver.
+ *
+ * The 2835 has two SD controllers: The Arasan sdhci controller
+ * (supported by the iproc driver) and a custom sdhost controller
+ * (supported by this driver).
+ *
+ * The sdhci controller supports both sdcard and sdio.  The sdhost
+ * controller supports the sdcard only, but has better performance.
+ * Also note that the rpi3 has sdio wifi, so driving the sdcard with
+ * the sdhost controller allows to use the sdhci controller for wifi
+ * support.
+ *
+ * The configuration is done by devicetree via pin muxing.  Both
+ * SD controller are available on the same pins (2 pin groups = pin 22
+ * to 27 + pin 48 to 53).  So it's possible to use both SD controllers
+ * at the same time with different pin groups.
+ *
+ * This code was ported to U-Boot by
+ *  Alexander Graf <agraf@suse.de>
+ * and is based on drivers/mmc/host/bcm2835.c in Linux which is written by
+ *  Phil Elwell <phil@raspberrypi.org>
+ *  Copyright (C) 2015-2016 Raspberry Pi (Trading) Ltd.
+ * which is based on
+ *  mmc-bcm2835.c by Gellert Weisz
+ * which is, in turn, based on
+ *  sdhci-bcm2708.c by Broadcom
+ *  sdhci-bcm2835.c by Stephen Warren and Oleksandr Tymoshenko
+ *  sdhci.c and sdhci-pci.c by Pierre Ossman
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+#include <clk.h>
+#include <common.h>
+#include <dm.h>
+#include <mmc.h>
+#include <asm/arch/msg.h>
+#include <asm/unaligned.h>
+#include <linux/compat.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/sizes.h>
+#include <mach/gpio.h>
+#include <power/regulator.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define msleep(a) udelay(a * 1000)
+
+#define SDCMD  0x00 /* Command to SD card              - 16 R/W */
+#define SDARG  0x04 /* Argument to SD card             - 32 R/W */
+#define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */
+#define SDCDIV 0x0c /* Start value for clock divider   - 11 R/W */
+#define SDRSP0 0x10 /* SD card response (31:0)         - 32 R   */
+#define SDRSP1 0x14 /* SD card response (63:32)        - 32 R   */
+#define SDRSP2 0x18 /* SD card response (95:64)        - 32 R   */
+#define SDRSP3 0x1c /* SD card response (127:96)       - 32 R   */
+#define SDHSTS 0x20 /* SD host status                  - 11 R/W */
+#define SDVDD  0x30 /* SD card power control           -  1 R/W */
+#define SDEDM  0x34 /* Emergency Debug Mode            - 13 R/W */
+#define SDHCFG 0x38 /* Host configuration              -  2 R/W */
+#define SDHBCT 0x3c /* Host byte count (debug)         - 32 R/W */
+#define SDDATA 0x40 /* Data to/from SD card            - 32 R/W */
+#define SDHBLC 0x50 /* Host block count (SDIO/SDHC)    -  9 R/W */
+
+#define SDCMD_NEW_FLAG			0x8000
+#define SDCMD_FAIL_FLAG			0x4000
+#define SDCMD_BUSYWAIT			0x800
+#define SDCMD_NO_RESPONSE		0x400
+#define SDCMD_LONG_RESPONSE		0x200
+#define SDCMD_WRITE_CMD			0x80
+#define SDCMD_READ_CMD			0x40
+#define SDCMD_CMD_MASK			0x3f
+
+#define SDCDIV_MAX_CDIV			0x7ff
+
+#define SDHSTS_BUSY_IRPT		0x400
+#define SDHSTS_BLOCK_IRPT		0x200
+#define SDHSTS_SDIO_IRPT		0x100
+#define SDHSTS_REW_TIME_OUT		0x80
+#define SDHSTS_CMD_TIME_OUT		0x40
+#define SDHSTS_CRC16_ERROR		0x20
+#define SDHSTS_CRC7_ERROR		0x10
+#define SDHSTS_FIFO_ERROR		0x08
+#define SDHSTS_DATA_FLAG		0x01
+
+#define SDHSTS_CLEAR_MASK		(SDHSTS_BUSY_IRPT | \
+					 SDHSTS_BLOCK_IRPT | \
+					 SDHSTS_SDIO_IRPT | \
+					 SDHSTS_REW_TIME_OUT | \
+					 SDHSTS_CMD_TIME_OUT | \
+					 SDHSTS_CRC16_ERROR | \
+					 SDHSTS_CRC7_ERROR | \
+					 SDHSTS_FIFO_ERROR)
+
+#define SDHSTS_TRANSFER_ERROR_MASK	(SDHSTS_CRC7_ERROR | \
+					 SDHSTS_CRC16_ERROR | \
+					 SDHSTS_REW_TIME_OUT | \
+					 SDHSTS_FIFO_ERROR)
+
+#define SDHSTS_ERROR_MASK		(SDHSTS_CMD_TIME_OUT | \
+					 SDHSTS_TRANSFER_ERROR_MASK)
+
+#define SDHCFG_BUSY_IRPT_EN	BIT(10)
+#define SDHCFG_BLOCK_IRPT_EN	BIT(8)
+#define SDHCFG_SDIO_IRPT_EN	BIT(5)
+#define SDHCFG_DATA_IRPT_EN	BIT(4)
+#define SDHCFG_SLOW_CARD	BIT(3)
+#define SDHCFG_WIDE_EXT_BUS	BIT(2)
+#define SDHCFG_WIDE_INT_BUS	BIT(1)
+#define SDHCFG_REL_CMD_LINE	BIT(0)
+
+#define SDVDD_POWER_OFF		0
+#define SDVDD_POWER_ON		1
+
+#define SDEDM_FORCE_DATA_MODE	BIT(19)
+#define SDEDM_CLOCK_PULSE	BIT(20)
+#define SDEDM_BYPASS		BIT(21)
+
+#define SDEDM_FIFO_FILL_SHIFT	4
+#define SDEDM_FIFO_FILL_MASK	0x1f
+static u32 edm_fifo_fill(u32 edm)
+{
+	return (edm >> SDEDM_FIFO_FILL_SHIFT) & SDEDM_FIFO_FILL_MASK;
+}
+
+#define SDEDM_WRITE_THRESHOLD_SHIFT	9
+#define SDEDM_READ_THRESHOLD_SHIFT	14
+#define SDEDM_THRESHOLD_MASK		0x1f
+
+#define SDEDM_FSM_MASK		0xf
+#define SDEDM_FSM_IDENTMODE	0x0
+#define SDEDM_FSM_DATAMODE	0x1
+#define SDEDM_FSM_READDATA	0x2
+#define SDEDM_FSM_WRITEDATA	0x3
+#define SDEDM_FSM_READWAIT	0x4
+#define SDEDM_FSM_READCRC	0x5
+#define SDEDM_FSM_WRITECRC	0x6
+#define SDEDM_FSM_WRITEWAIT1	0x7
+#define SDEDM_FSM_POWERDOWN	0x8
+#define SDEDM_FSM_POWERUP	0x9
+#define SDEDM_FSM_WRITESTART1	0xa
+#define SDEDM_FSM_WRITESTART2	0xb
+#define SDEDM_FSM_GENPULSES	0xc
+#define SDEDM_FSM_WRITEWAIT2	0xd
+#define SDEDM_FSM_STARTPOWDOWN	0xf
+
+#define SDDATA_FIFO_WORDS	16
+
+#define FIFO_READ_THRESHOLD	4
+#define FIFO_WRITE_THRESHOLD	4
+#define SDDATA_FIFO_PIO_BURST	8
+
+#define SDHST_TIMEOUT_MAX_USEC	100000
+
+struct bcm2835_plat {
+	struct mmc_config cfg;
+	struct mmc mmc;
+};
+
+struct bcm2835_host {
+	void __iomem		*ioaddr;
+	u32			phys_addr;
+
+	int			clock;		/* Current clock speed */
+	unsigned int		max_clk;	/* Max possible freq */
+	unsigned int		blocks;		/* remaining PIO blocks */
+	int			irq;		/* Device IRQ */
+
+	u32			ns_per_fifo_word;
+
+	/* cached registers */
+	u32			hcfg;
+	u32			cdiv;
+
+	struct mmc_cmd	*cmd;		/* Current command */
+	struct mmc_data		*data;		/* Current data request */
+	bool			data_complete:1;/* Data finished before cmd */
+	bool			use_busy:1;	/* Wait for busy interrupt */
+	bool			wait_data_complete:1;	/* Wait for data */
+
+	/* for threaded irq handler */
+	bool			irq_block;
+	bool			irq_busy;
+	bool			irq_data;
+
+	struct udevice		*dev;
+	struct mmc		*mmc;
+	struct bcm2835_plat	*plat;
+};
+
+static void bcm2835_dumpregs(struct bcm2835_host *host)
+{
+	dev_dbg(dev, "=========== REGISTER DUMP ===========\n");
+	dev_dbg(dev, "SDCMD  0x%08x\n", readl(host->ioaddr + SDCMD));
+	dev_dbg(dev, "SDARG  0x%08x\n", readl(host->ioaddr + SDARG));
+	dev_dbg(dev, "SDTOUT 0x%08x\n", readl(host->ioaddr + SDTOUT));
+	dev_dbg(dev, "SDCDIV 0x%08x\n", readl(host->ioaddr + SDCDIV));
+	dev_dbg(dev, "SDRSP0 0x%08x\n", readl(host->ioaddr + SDRSP0));
+	dev_dbg(dev, "SDRSP1 0x%08x\n", readl(host->ioaddr + SDRSP1));
+	dev_dbg(dev, "SDRSP2 0x%08x\n", readl(host->ioaddr + SDRSP2));
+	dev_dbg(dev, "SDRSP3 0x%08x\n", readl(host->ioaddr + SDRSP3));
+	dev_dbg(dev, "SDHSTS 0x%08x\n", readl(host->ioaddr + SDHSTS));
+	dev_dbg(dev, "SDVDD  0x%08x\n", readl(host->ioaddr + SDVDD));
+	dev_dbg(dev, "SDEDM  0x%08x\n", readl(host->ioaddr + SDEDM));
+	dev_dbg(dev, "SDHCFG 0x%08x\n", readl(host->ioaddr + SDHCFG));
+	dev_dbg(dev, "SDHBCT 0x%08x\n", readl(host->ioaddr + SDHBCT));
+	dev_dbg(dev, "SDHBLC 0x%08x\n", readl(host->ioaddr + SDHBLC));
+	dev_dbg(dev, "===========================================\n");
+}
+
+static void bcm2835_reset_internal(struct bcm2835_host *host)
+{
+	u32 temp;
+
+	writel(SDVDD_POWER_OFF, host->ioaddr + SDVDD);
+	writel(0, host->ioaddr + SDCMD);
+	writel(0, host->ioaddr + SDARG);
+	/* Set timeout to a big enough value so we don't hit it */
+	writel(0xf00000, host->ioaddr + SDTOUT);
+	writel(0, host->ioaddr + SDCDIV);
+	/* Clear status register */
+	writel(SDHSTS_CLEAR_MASK, host->ioaddr + SDHSTS);
+	writel(0, host->ioaddr + SDHCFG);
+	writel(0, host->ioaddr + SDHBCT);
+	writel(0, host->ioaddr + SDHBLC);
+
+	/* Limit fifo usage due to silicon bug */
+	temp = readl(host->ioaddr + SDEDM);
+	temp &= ~((SDEDM_THRESHOLD_MASK << SDEDM_READ_THRESHOLD_SHIFT) |
+		  (SDEDM_THRESHOLD_MASK << SDEDM_WRITE_THRESHOLD_SHIFT));
+	temp |= (FIFO_READ_THRESHOLD << SDEDM_READ_THRESHOLD_SHIFT) |
+		(FIFO_WRITE_THRESHOLD << SDEDM_WRITE_THRESHOLD_SHIFT);
+	writel(temp, host->ioaddr + SDEDM);
+	/* Wait for FIFO threshold to populate */
+	msleep(20);
+	writel(SDVDD_POWER_ON, host->ioaddr + SDVDD);
+	/* Wait for all components to go through power on cycle */
+	msleep(20);
+	host->clock = 0;
+	writel(host->hcfg, host->ioaddr + SDHCFG);
+	writel(host->cdiv, host->ioaddr + SDCDIV);
+}
+
+static int bcm2835_finish_command(struct bcm2835_host *host);
+
+static void bcm2835_wait_transfer_complete(struct bcm2835_host *host)
+{
+	int timediff;
+	u32 alternate_idle;
+
+	alternate_idle = (host->data->flags & MMC_DATA_READ) ?
+		SDEDM_FSM_READWAIT : SDEDM_FSM_WRITESTART1;
+
+	timediff = 0;
+
+	while (1) {
+		u32 edm, fsm;
+
+		edm = readl(host->ioaddr + SDEDM);
+		fsm = edm & SDEDM_FSM_MASK;
+
+		if ((fsm == SDEDM_FSM_IDENTMODE) ||
+		    (fsm == SDEDM_FSM_DATAMODE))
+			break;
+		if (fsm == alternate_idle) {
+			writel(edm | SDEDM_FORCE_DATA_MODE,
+			       host->ioaddr + SDEDM);
+			break;
+		}
+
+		/* Error out after 100000 register reads (~1s) */
+		if (timediff++ == 100000) {
+			dev_err(host->dev,
+				"wait_transfer_complete - still waiting after %d retries\n",
+				timediff);
+			bcm2835_dumpregs(host);
+			return;
+		}
+	}
+}
+
+static int bcm2835_transfer_block_pio(struct bcm2835_host *host, bool is_read)
+{
+	struct mmc_data *data = host->data;
+	size_t blksize = data->blocksize;
+	int copy_words;
+	u32 hsts = 0;
+	u32 *buf;
+
+	if (blksize % sizeof(u32))
+		return -EINVAL;
+
+	buf = is_read ? (u32 *)data->dest : (u32 *)data->src;
+
+	if (is_read)
+		data->dest += blksize;
+	else
+		data->src += blksize;
+
+	copy_words = blksize / sizeof(u32);
+
+	/*
+	 * Copy all contents from/to the FIFO as far as it reaches,
+	 * then wait for it to fill/empty again and rewind.
+	 */
+	while (copy_words) {
+		int burst_words, words;
+		u32 edm;
+
+		burst_words = min(SDDATA_FIFO_PIO_BURST, copy_words);
+		edm = readl(host->ioaddr + SDEDM);
+		if (is_read)
+			words = edm_fifo_fill(edm);
+		else
+			words = SDDATA_FIFO_WORDS - edm_fifo_fill(edm);
+
+		if (words < burst_words) {
+			int fsm_state = (edm & SDEDM_FSM_MASK);
+
+			if ((is_read &&
+			     (fsm_state != SDEDM_FSM_READDATA &&
+			      fsm_state != SDEDM_FSM_READWAIT &&
+			      fsm_state != SDEDM_FSM_READCRC)) ||
+			    (!is_read &&
+			     (fsm_state != SDEDM_FSM_WRITEDATA &&
+			      fsm_state != SDEDM_FSM_WRITESTART1 &&
+			      fsm_state != SDEDM_FSM_WRITESTART2))) {
+				hsts = readl(host->ioaddr + SDHSTS);
+				printf("fsm %x, hsts %08x\n", fsm_state, hsts);
+				if (hsts & SDHSTS_ERROR_MASK)
+					break;
+			}
+
+			continue;
+		} else if (words > copy_words) {
+			words = copy_words;
+		}
+
+		copy_words -= words;
+
+		/* Copy current chunk to/from the FIFO */
+		while (words) {
+			if (is_read)
+				*(buf++) = readl(host->ioaddr + SDDATA);
+			else
+				writel(*(buf++), host->ioaddr + SDDATA);
+			words--;
+		}
+	}
+
+	return 0;
+}
+
+static int bcm2835_transfer_pio(struct bcm2835_host *host)
+{
+	u32 sdhsts;
+	bool is_read;
+	int ret = 0;
+
+	is_read = (host->data->flags & MMC_DATA_READ) != 0;
+	ret = bcm2835_transfer_block_pio(host, is_read);
+
+	if (host->wait_data_complete)
+		bcm2835_wait_transfer_complete(host);
+
+	sdhsts = readl(host->ioaddr + SDHSTS);
+	if (sdhsts & (SDHSTS_CRC16_ERROR |
+		      SDHSTS_CRC7_ERROR |
+		      SDHSTS_FIFO_ERROR)) {
+		printf("%s transfer error - HSTS %08x\n",
+		       is_read ? "read" : "write", sdhsts);
+		ret =  -EILSEQ;
+	} else if ((sdhsts & (SDHSTS_CMD_TIME_OUT |
+			      SDHSTS_REW_TIME_OUT))) {
+		printf("%s timeout error - HSTS %08x\n",
+		       is_read ? "read" : "write", sdhsts);
+		ret = -ETIMEDOUT;
+	}
+
+	return ret;
+}
+
+static void bcm2835_set_transfer_irqs(struct bcm2835_host *host)
+{
+	u32 all_irqs = SDHCFG_DATA_IRPT_EN | SDHCFG_BLOCK_IRPT_EN |
+		SDHCFG_BUSY_IRPT_EN;
+
+	host->hcfg = (host->hcfg & ~all_irqs) |
+		SDHCFG_DATA_IRPT_EN |
+		SDHCFG_BUSY_IRPT_EN;
+
+	writel(host->hcfg, host->ioaddr + SDHCFG);
+}
+
+static
+void bcm2835_prepare_data(struct bcm2835_host *host, struct mmc_cmd *cmd,
+			  struct mmc_data *data)
+{
+	WARN_ON(host->data);
+
+	host->data = data;
+	if (!data)
+		return;
+
+	host->wait_data_complete = cmd->cmdidx != MMC_CMD_READ_MULTIPLE_BLOCK;
+	host->data_complete = false;
+
+	/* Use PIO */
+	host->blocks = data->blocks;
+
+	bcm2835_set_transfer_irqs(host);
+
+	writel(data->blocksize, host->ioaddr + SDHBCT);
+	writel(data->blocks, host->ioaddr + SDHBLC);
+}
+
+static u32 bcm2835_read_wait_sdcmd(struct bcm2835_host *host)
+{
+	u32 value;
+	int ret;
+	int timeout_us = SDHST_TIMEOUT_MAX_USEC;
+
+	ret = readl_poll_timeout(host->ioaddr + SDCMD, value,
+				 !(value & SDCMD_NEW_FLAG), timeout_us);
+	if (ret == -ETIMEDOUT)
+		printf("%s: timeout (%d us)\n", __func__, timeout_us);
+
+	return value;
+}
+
+static int bcm2835_send_command(struct bcm2835_host *host, struct mmc_cmd *cmd,
+				struct mmc_data *data)
+{
+	u32 sdcmd, sdhsts;
+
+	WARN_ON(host->cmd);
+
+	if ((cmd->resp_type & MMC_RSP_136) && (cmd->resp_type & MMC_RSP_BUSY)) {
+		printf("unsupported response type!\n");
+		return -EINVAL;
+	}
+
+	sdcmd = bcm2835_read_wait_sdcmd(host);
+	if (sdcmd & SDCMD_NEW_FLAG) {
+		printf("previous command never completed.\n");
+		bcm2835_dumpregs(host);
+		return -EBUSY;
+	}
+
+	host->cmd = cmd;
+
+	/* Clear any error flags */
+	sdhsts = readl(host->ioaddr + SDHSTS);
+	if (sdhsts & SDHSTS_ERROR_MASK)
+		writel(sdhsts, host->ioaddr + SDHSTS);
+
+	bcm2835_prepare_data(host, cmd, data);
+
+	writel(cmd->cmdarg, host->ioaddr + SDARG);
+
+	sdcmd = cmd->cmdidx & SDCMD_CMD_MASK;
+
+	host->use_busy = false;
+	if (!(cmd->resp_type & MMC_RSP_PRESENT)) {
+		sdcmd |= SDCMD_NO_RESPONSE;
+	} else {
+		if (cmd->resp_type & MMC_RSP_136)
+			sdcmd |= SDCMD_LONG_RESPONSE;
+		if (cmd->resp_type & MMC_RSP_BUSY) {
+			sdcmd |= SDCMD_BUSYWAIT;
+			host->use_busy = true;
+		}
+	}
+
+	if (data) {
+		if (data->flags & MMC_DATA_WRITE)
+			sdcmd |= SDCMD_WRITE_CMD;
+		if (data->flags & MMC_DATA_READ)
+			sdcmd |= SDCMD_READ_CMD;
+	}
+
+	writel(sdcmd | SDCMD_NEW_FLAG, host->ioaddr + SDCMD);
+
+	return 0;
+}
+
+static int bcm2835_transfer_complete(struct bcm2835_host *host)
+{
+	int ret = 0;
+
+	WARN_ON(!host->data_complete);
+
+	host->data = NULL;
+
+	return ret;
+}
+
+static void bcm2835_finish_data(struct bcm2835_host *host)
+{
+	host->hcfg &= ~(SDHCFG_DATA_IRPT_EN | SDHCFG_BLOCK_IRPT_EN);
+	writel(host->hcfg, host->ioaddr + SDHCFG);
+
+	host->data_complete = true;
+
+	if (host->cmd) {
+		/* Data managed to finish before the
+		 * command completed. Make sure we do
+		 * things in the proper order.
+		 */
+		dev_dbg(dev, "Finished early - HSTS %08x\n",
+			readl(host->ioaddr + SDHSTS));
+	} else {
+		bcm2835_transfer_complete(host);
+	}
+}
+
+static int bcm2835_finish_command(struct bcm2835_host *host)
+{
+	struct mmc_cmd *cmd = host->cmd;
+	u32 sdcmd;
+	int ret = 0;
+
+	sdcmd = bcm2835_read_wait_sdcmd(host);
+
+	/* Check for errors */
+	if (sdcmd & SDCMD_NEW_FLAG) {
+		printf("command never completed.\n");
+		bcm2835_dumpregs(host);
+		return -EIO;
+	} else if (sdcmd & SDCMD_FAIL_FLAG) {
+		u32 sdhsts = readl(host->ioaddr + SDHSTS);
+
+		/* Clear the errors */
+		writel(SDHSTS_ERROR_MASK, host->ioaddr + SDHSTS);
+
+		if (!(sdhsts & SDHSTS_CRC7_ERROR) ||
+		    (host->cmd->cmdidx != MMC_CMD_SEND_OP_COND)) {
+			if (sdhsts & SDHSTS_CMD_TIME_OUT) {
+				ret = -ETIMEDOUT;
+			} else {
+				printf("unexpected command %d error\n",
+				       host->cmd->cmdidx);
+				bcm2835_dumpregs(host);
+				ret = -EILSEQ;
+			}
+
+			return ret;
+		}
+	}
+
+	if (cmd->resp_type & MMC_RSP_PRESENT) {
+		if (cmd->resp_type & MMC_RSP_136) {
+			int i;
+
+			for (i = 0; i < 4; i++) {
+				cmd->response[3 - i] =
+					readl(host->ioaddr + SDRSP0 + i * 4);
+			}
+		} else {
+			cmd->response[0] = readl(host->ioaddr + SDRSP0);
+		}
+	}
+
+	/* Processed actual command. */
+	host->cmd = NULL;
+	if (host->data && host->data_complete)
+		ret = bcm2835_transfer_complete(host);
+
+	return ret;
+}
+
+static int bcm2835_check_cmd_error(struct bcm2835_host *host, u32 intmask)
+{
+	int ret = -EINVAL;
+
+	if (!(intmask & SDHSTS_ERROR_MASK))
+		return 0;
+
+	if (!host->cmd)
+		return -EINVAL;
+
+	printf("sdhost_busy_irq: intmask %08x\n", intmask);
+	if (intmask & SDHSTS_CRC7_ERROR) {
+		ret = -EILSEQ;
+	} else if (intmask & (SDHSTS_CRC16_ERROR |
+			      SDHSTS_FIFO_ERROR)) {
+		ret = -EILSEQ;
+	} else if (intmask & (SDHSTS_REW_TIME_OUT | SDHSTS_CMD_TIME_OUT)) {
+		ret = -ETIMEDOUT;
+	}
+	bcm2835_dumpregs(host);
+	return ret;
+}
+
+static int bcm2835_check_data_error(struct bcm2835_host *host, u32 intmask)
+{
+	int ret = 0;
+
+	if (!host->data)
+		return 0;
+	if (intmask & (SDHSTS_CRC16_ERROR | SDHSTS_FIFO_ERROR))
+		ret = -EILSEQ;
+	if (intmask & SDHSTS_REW_TIME_OUT)
+		ret = -ETIMEDOUT;
+
+	if (ret)
+		printf("%s:%d %d\n", __func__, __LINE__, ret);
+
+	return ret;
+}
+
+static void bcm2835_busy_irq(struct bcm2835_host *host)
+{
+	if (WARN_ON(!host->cmd)) {
+		bcm2835_dumpregs(host);
+		return;
+	}
+
+	if (WARN_ON(!host->use_busy)) {
+		bcm2835_dumpregs(host);
+		return;
+	}
+	host->use_busy = false;
+
+	bcm2835_finish_command(host);
+}
+
+static void bcm2835_data_irq(struct bcm2835_host *host, u32 intmask)
+{
+	int ret;
+
+	/*
+	 * There are no dedicated data/space available interrupt
+	 * status bits, so it is necessary to use the single shared
+	 * data/space available FIFO status bits. It is therefore not
+	 * an error to get here when there is no data transfer in
+	 * progress.
+	 */
+	if (!host->data)
+		return;
+
+	ret = bcm2835_check_data_error(host, intmask);
+	if (ret)
+		goto finished;
+
+	if (host->data->flags & MMC_DATA_WRITE) {
+		/* Use the block interrupt for writes after the first block */
+		host->hcfg &= ~(SDHCFG_DATA_IRPT_EN);
+		host->hcfg |= SDHCFG_BLOCK_IRPT_EN;
+		writel(host->hcfg, host->ioaddr + SDHCFG);
+		bcm2835_transfer_pio(host);
+	} else {
+		bcm2835_transfer_pio(host);
+		host->blocks--;
+		if ((host->blocks == 0))
+			goto finished;
+	}
+	return;
+
+finished:
+	host->hcfg &= ~(SDHCFG_DATA_IRPT_EN | SDHCFG_BLOCK_IRPT_EN);
+	writel(host->hcfg, host->ioaddr + SDHCFG);
+}
+
+static void bcm2835_data_threaded_irq(struct bcm2835_host *host)
+{
+	if (!host->data)
+		return;
+	if ((host->blocks == 0))
+		bcm2835_finish_data(host);
+}
+
+static void bcm2835_block_irq(struct bcm2835_host *host)
+{
+	if (WARN_ON(!host->data)) {
+		bcm2835_dumpregs(host);
+		return;
+	}
+
+	WARN_ON(!host->blocks);
+	if ((--host->blocks == 0))
+		bcm2835_finish_data(host);
+	else
+		bcm2835_transfer_pio(host);
+}
+
+static irqreturn_t bcm2835_irq(int irq, void *dev_id)
+{
+	irqreturn_t result = IRQ_NONE;
+	struct bcm2835_host *host = dev_id;
+	u32 intmask;
+
+	intmask = readl(host->ioaddr + SDHSTS);
+
+	writel(SDHSTS_BUSY_IRPT |
+	       SDHSTS_BLOCK_IRPT |
+	       SDHSTS_SDIO_IRPT |
+	       SDHSTS_DATA_FLAG,
+	       host->ioaddr + SDHSTS);
+
+	if (intmask & SDHSTS_BLOCK_IRPT) {
+		bcm2835_check_data_error(host, intmask);
+		host->irq_block = true;
+		result = IRQ_WAKE_THREAD;
+	}
+
+	if (intmask & SDHSTS_BUSY_IRPT) {
+		if (!bcm2835_check_cmd_error(host, intmask)) {
+			host->irq_busy = true;
+			result = IRQ_WAKE_THREAD;
+		} else {
+			result = IRQ_HANDLED;
+		}
+	}
+
+	/* There is no true data interrupt status bit, so it is
+	 * necessary to qualify the data flag with the interrupt
+	 * enable bit.
+	 */
+	if ((intmask & SDHSTS_DATA_FLAG) &&
+	    (host->hcfg & SDHCFG_DATA_IRPT_EN)) {
+		bcm2835_data_irq(host, intmask);
+		host->irq_data = true;
+		result = IRQ_WAKE_THREAD;
+	}
+
+	return result;
+}
+
+static irqreturn_t bcm2835_threaded_irq(int irq, void *dev_id)
+{
+	struct bcm2835_host *host = dev_id;
+
+	if (host->irq_block) {
+		host->irq_block = false;
+		bcm2835_block_irq(host);
+	}
+
+	if (host->irq_busy) {
+		host->irq_busy = false;
+		bcm2835_busy_irq(host);
+	}
+
+	if (host->irq_data) {
+		host->irq_data = false;
+		bcm2835_data_threaded_irq(host);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void bcm2835_irq_poll(struct bcm2835_host *host)
+{
+	u32 intmask;
+
+	while (1) {
+		intmask = readl(host->ioaddr + SDHSTS);
+		if (intmask & (SDHSTS_BUSY_IRPT | SDHSTS_BLOCK_IRPT |
+			       SDHSTS_SDIO_IRPT | SDHSTS_DATA_FLAG)) {
+			bcm2835_irq(0, host);
+			bcm2835_threaded_irq(0, host);
+			return;
+		}
+	}
+}
+
+static void bcm2835_set_clock(struct bcm2835_host *host, unsigned int clock)
+{
+	int div;
+
+	/* The SDCDIV register has 11 bits, and holds (div - 2).  But
+	 * in data mode the max is 50MHz wihout a minimum, and only
+	 * the bottom 3 bits are used. Since the switch over is
+	 * automatic (unless we have marked the card as slow...),
+	 * chosen values have to make sense in both modes.  Ident mode
+	 * must be 100-400KHz, so can range check the requested
+	 * clock. CMD15 must be used to return to data mode, so this
+	 * can be monitored.
+	 *
+	 * clock 250MHz -> 0->125MHz, 1->83.3MHz, 2->62.5MHz, 3->50.0MHz
+	 *                 4->41.7MHz, 5->35.7MHz, 6->31.3MHz, 7->27.8MHz
+	 *
+	 *		 623->400KHz/27.8MHz
+	 *		 reset value (507)->491159/50MHz
+	 *
+	 * BUT, the 3-bit clock divisor in data mode is too small if
+	 * the core clock is higher than 250MHz, so instead use the
+	 * SLOW_CARD configuration bit to force the use of the ident
+	 * clock divisor at all times.
+	 */
+
+	if (clock < 100000) {
+		/* Can't stop the clock, but make it as slow as possible
+		 * to show willing
+		 */
+		host->cdiv = SDCDIV_MAX_CDIV;
+		writel(host->cdiv, host->ioaddr + SDCDIV);
+		return;
+	}
+
+	div = host->max_clk / clock;
+	if (div < 2)
+		div = 2;
+	if ((host->max_clk / div) > clock)
+		div++;
+	div -= 2;
+
+	if (div > SDCDIV_MAX_CDIV)
+		div = SDCDIV_MAX_CDIV;
+
+	clock = host->max_clk / (div + 2);
+	host->mmc->clock = clock;
+
+	/* Calibrate some delays */
+
+	host->ns_per_fifo_word = (1000000000 / clock) *
+		((host->mmc->card_caps & MMC_MODE_4BIT) ? 8 : 32);
+
+	host->cdiv = div;
+	writel(host->cdiv, host->ioaddr + SDCDIV);
+
+	/* Set the timeout to 500ms */
+	writel(host->mmc->clock / 2, host->ioaddr + SDTOUT);
+}
+
+static inline int is_power_of_2(u64 x)
+{
+	return !(x & (x - 1));
+}
+
+static int bcm2835_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+			    struct mmc_data *data)
+{
+	struct bcm2835_host *host = dev_get_priv(dev);
+	u32 edm, fsm;
+	int ret = 0;
+
+	if (data && !is_power_of_2(data->blocksize)) {
+		printf("unsupported block size (%d bytes)\n", data->blocksize);
+
+		if (cmd)
+			return -EINVAL;
+	}
+
+	edm = readl(host->ioaddr + SDEDM);
+	fsm = edm & SDEDM_FSM_MASK;
+
+	if ((fsm != SDEDM_FSM_IDENTMODE) &&
+	    (fsm != SDEDM_FSM_DATAMODE) &&
+	    (cmd && cmd->cmdidx != MMC_CMD_STOP_TRANSMISSION)) {
+		printf("previous command (%d) not complete (EDM %08x)\n",
+		       readl(host->ioaddr + SDCMD) & SDCMD_CMD_MASK, edm);
+		bcm2835_dumpregs(host);
+
+		if (cmd)
+			return -EILSEQ;
+
+		return 0;
+	}
+
+	if (cmd) {
+		ret = bcm2835_send_command(host, cmd, data);
+		if (!ret && !host->use_busy)
+			ret = bcm2835_finish_command(host);
+	}
+
+	/* Wait for completion of busy signal or data transfer */
+	while (host->use_busy || host->data)
+		bcm2835_irq_poll(host);
+
+	return ret;
+}
+
+static int bcm2835_set_ios(struct udevice *dev)
+{
+	struct bcm2835_host *host = dev_get_priv(dev);
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+
+	if (!mmc->clock || mmc->clock != host->clock) {
+		bcm2835_set_clock(host, mmc->clock);
+		host->clock = mmc->clock;
+	}
+
+	/* set bus width */
+	host->hcfg &= ~SDHCFG_WIDE_EXT_BUS;
+	if (mmc->bus_width == 4)
+		host->hcfg |= SDHCFG_WIDE_EXT_BUS;
+
+	host->hcfg |= SDHCFG_WIDE_INT_BUS;
+
+	/* Disable clever clock switching, to cope with fast core clocks */
+	host->hcfg |= SDHCFG_SLOW_CARD;
+
+	writel(host->hcfg, host->ioaddr + SDHCFG);
+
+	return 0;
+}
+
+static void bcm2835_add_host(struct bcm2835_host *host)
+{
+	struct mmc_config *cfg = &host->plat->cfg;
+
+	cfg->f_max = host->max_clk;
+	cfg->f_min = host->max_clk / SDCDIV_MAX_CDIV;
+	cfg->b_max = 65535;
+
+	dev_dbg(dev, "f_max %d, f_min %d\n",
+		cfg->f_max, cfg->f_min);
+
+	/* host controller capabilities */
+	cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_HS | MMC_MODE_HS_52MHz;
+
+	/* report supported voltage ranges */
+	cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+	/* Set interrupt enables */
+	host->hcfg = SDHCFG_BUSY_IRPT_EN;
+
+	bcm2835_reset_internal(host);
+}
+
+static int bcm2835_probe(struct udevice *dev)
+{
+	struct bcm2835_plat *plat = dev_get_platdata(dev);
+	struct bcm2835_host *host = dev_get_priv(dev);
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+
+	host->dev = dev;
+	host->mmc = mmc;
+	host->plat = plat;
+	upriv->mmc = &plat->mmc;
+	plat->cfg.name = dev->name;
+
+	host->phys_addr = devfdt_get_addr(dev);
+	if (host->phys_addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	host->ioaddr = devm_ioremap(dev, host->phys_addr, SZ_256);
+	if (!host->ioaddr)
+		return -ENOMEM;
+
+	host->max_clk = bcm2835_get_mmc_clock();
+
+	bcm2835_add_host(host);
+
+	dev_dbg(dev, "%s -> OK\n", __func__);
+
+	return 0;
+}
+
+static const struct udevice_id bcm2835_match[] = {
+	{ .compatible = "brcm,bcm2835-sdhost" },
+	{ }
+};
+
+static const struct dm_mmc_ops bcm2835_ops = {
+	.send_cmd = bcm2835_send_cmd,
+	.set_ios = bcm2835_set_ios,
+};
+
+static int bcm2835_bind(struct udevice *dev)
+{
+	struct bcm2835_plat *plat = dev_get_platdata(dev);
+
+	return mmc_bind(dev, &plat->mmc, &plat->cfg);
+}
+
+U_BOOT_DRIVER(bcm2835_sdhost) = {
+	.name = "bcm2835-sdhost",
+	.id = UCLASS_MMC,
+	.of_match = bcm2835_match,
+	.bind = bcm2835_bind,
+	.probe = bcm2835_probe,
+	.priv_auto_alloc_size = sizeof(struct bcm2835_host),
+	.platdata_auto_alloc_size = sizeof(struct bcm2835_plat),
+	.ops = &bcm2835_ops,
+};
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 7e8e4b0..0a4dd3c 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -306,5 +306,6 @@
 source "drivers/pinctrl/uniphier/Kconfig"
 source "drivers/pinctrl/exynos/Kconfig"
 source "drivers/pinctrl/mvebu/Kconfig"
+source "drivers/pinctrl/broadcom/Kconfig"
 
 endmenu
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 8c04028..c7135d2 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -22,3 +22,4 @@
 obj-$(CONFIG_PINCTRL_SINGLE)	+= pinctrl-single.o
 obj-$(CONFIG_PINCTRL_STI)	+= pinctrl-sti.o
 obj-$(CONFIG_PINCTRL_STM32)	+= pinctrl_stm32.o
+obj-y				+= broadcom/
diff --git a/drivers/pinctrl/broadcom/Kconfig b/drivers/pinctrl/broadcom/Kconfig
new file mode 100644
index 0000000..4056782
--- /dev/null
+++ b/drivers/pinctrl/broadcom/Kconfig
@@ -0,0 +1,7 @@
+config PINCTRL_BCM283X
+	depends on ARCH_BCM283X && PINCTRL_FULL && OF_CONTROL
+	default y
+	bool "Broadcom 283x family pin control driver"
+	help
+	   Support pin multiplexing and pin configuration control on
+	   Broadcom's 283x family of SoCs.
diff --git a/drivers/pinctrl/broadcom/Makefile b/drivers/pinctrl/broadcom/Makefile
new file mode 100644
index 0000000..2a1e550
--- /dev/null
+++ b/drivers/pinctrl/broadcom/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2018 Alexander Graf <agraf@suse.de>
+#
+# SPDX-License-Identifier:	GPL-2.0
+# https://spdx.org/licenses
+
+obj-$(CONFIG_PINCTRL_BCM283X) += pinctrl-bcm283x.o
diff --git a/drivers/pinctrl/broadcom/pinctrl-bcm283x.c b/drivers/pinctrl/broadcom/pinctrl-bcm283x.c
new file mode 100644
index 0000000..6fbd6ef
--- /dev/null
+++ b/drivers/pinctrl/broadcom/pinctrl-bcm283x.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2018 Alexander Graf <agraf@suse.de>
+ *
+ * Based on drivers/pinctrl/mvebu/pinctrl-mvebu.c and
+ *          drivers/gpio/bcm2835_gpio.c
+ *
+ * This driver gets instantiated by the GPIO driver, because both devices
+ * share the same device node.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ * https://spdx.org/licenses
+ */
+
+#include <common.h>
+#include <config.h>
+#include <errno.h>
+#include <dm.h>
+#include <dm/pinctrl.h>
+#include <dm/root.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+
+struct bcm283x_pinctrl_priv {
+	u32 *base_reg;
+};
+
+#define MAX_PINS_PER_BANK 16
+
+static void bcm2835_gpio_set_func_id(struct udevice *dev, unsigned int gpio,
+				     int func)
+{
+	struct bcm283x_pinctrl_priv *priv = dev_get_priv(dev);
+	int reg_offset;
+	int field_offset;
+
+	reg_offset = BCM2835_GPIO_FSEL_BANK(gpio);
+	field_offset = BCM2835_GPIO_FSEL_SHIFT(gpio);
+
+	clrsetbits_le32(&priv->base_reg[reg_offset],
+			BCM2835_GPIO_FSEL_MASK << field_offset,
+			(func & BCM2835_GPIO_FSEL_MASK) << field_offset);
+}
+
+static int bcm2835_gpio_get_func_id(struct udevice *dev, unsigned int gpio)
+{
+	struct bcm283x_pinctrl_priv *priv = dev_get_priv(dev);
+	u32 val;
+
+	val = readl(&priv->base_reg[BCM2835_GPIO_FSEL_BANK(gpio)]);
+
+	return (val >> BCM2835_GPIO_FSEL_SHIFT(gpio) & BCM2835_GPIO_FSEL_MASK);
+}
+
+/*
+ * bcm283x_pinctrl_set_state: configure pin functions.
+ * @dev: the pinctrl device to be configured.
+ * @config: the state to be configured.
+ * @return: 0 in success
+ */
+int bcm283x_pinctrl_set_state(struct udevice *dev, struct udevice *config)
+{
+	u32 pin_arr[MAX_PINS_PER_BANK];
+	u32 function;
+	int i, len, pin_count = 0;
+
+	if (!dev_read_prop(config, "brcm,pins", &len) || !len ||
+	    len & 0x3 || dev_read_u32_array(config, "brcm,pins", pin_arr,
+						  len / sizeof(u32))) {
+		debug("Failed reading pins array for pinconfig %s (%d)\n",
+		      config->name, len);
+		return -EINVAL;
+	}
+
+	pin_count = len / sizeof(u32);
+
+	function = dev_read_u32_default(config, "brcm,function", -1);
+	if (function < 0) {
+		debug("Failed reading function for pinconfig %s (%d)\n",
+		      config->name, function);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < pin_count; i++)
+		bcm2835_gpio_set_func_id(dev, pin_arr[i], function);
+
+	return 0;
+}
+
+static int bcm283x_pinctrl_get_gpio_mux(struct udevice *dev, int banknum,
+					int index)
+{
+	if (banknum != 0)
+		return -EINVAL;
+
+	return bcm2835_gpio_get_func_id(dev, index);
+}
+
+static const struct udevice_id bcm2835_pinctrl_id[] = {
+	{.compatible = "brcm,bcm2835-gpio"},
+	{}
+};
+
+int bcm283x_pinctl_probe(struct udevice *dev)
+{
+	struct bcm283x_pinctrl_priv *priv;
+	int ret;
+	struct udevice *pdev;
+
+	priv = dev_get_priv(dev);
+	if (!priv) {
+		debug("%s: Failed to get private\n", __func__);
+		return -EINVAL;
+	}
+
+	priv->base_reg = dev_read_addr_ptr(dev);
+	if (priv->base_reg == (void *)FDT_ADDR_T_NONE) {
+		debug("%s: Failed to get base address\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Create GPIO device as well */
+	ret = device_bind(dev, lists_driver_lookup_name("gpio_bcm2835"),
+			  "gpio_bcm2835", NULL, dev_of_offset(dev), &pdev);
+	if (ret) {
+		/*
+		 * While we really want the pinctrl driver to work to make
+		 * devices go where they should go, the GPIO controller is
+		 * not quite as crucial as it's only rarely used, so don't
+		 * fail here.
+		 */
+		printf("Failed to bind GPIO driver\n");
+	}
+
+	return 0;
+}
+
+static struct pinctrl_ops bcm283x_pinctrl_ops = {
+	.set_state	= bcm283x_pinctrl_set_state,
+	.get_gpio_mux	= bcm283x_pinctrl_get_gpio_mux,
+};
+
+U_BOOT_DRIVER(pinctrl_bcm283x) = {
+	.name		= "bcm283x_pinctrl",
+	.id		= UCLASS_PINCTRL,
+	.of_match	= of_match_ptr(bcm2835_pinctrl_id),
+	.priv_auto_alloc_size = sizeof(struct bcm283x_pinctrl_priv),
+	.ops		= &bcm283x_pinctrl_ops,
+	.probe		= bcm283x_pinctl_probe,
+	.flags		= DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 7b20b47..3ffedba 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -388,6 +388,22 @@
 	  configured in the device tree, and input clock frequency can
 	  be got from the clk node.
 
+config BCM283X_MU_SERIAL
+	bool "Support for BCM283x Mini-UART"
+	depends on DM_SERIAL && ARCH_BCM283X
+	default y
+	help
+	  Select this to enable Mini-UART support on BCM283X family of SoCs.
+
+config BCM283X_PL011_SERIAL
+	bool "Support for BCM283x PL011 UART"
+	depends on PL01X_SERIAL && ARCH_BCM283X
+	default y
+	help
+	  Select this to enable an overriding PL011 driver for BCM283X SoCs
+	  that supports automatic disable, so that it only gets used when
+	  the UART is actually muxed.
+
 config BCM6345_SERIAL
 	bool "Support for BCM6345 UART"
 	depends on DM_SERIAL && ARCH_BMIPS
@@ -447,6 +463,24 @@
 	  Select this to enable a UART for Intel MID platforms.
 	  This uses the ns16550 driver as a library.
 
+config PL010_SERIAL
+	bool "ARM PL010 driver"
+	depends on !DM_SERIAL
+	help
+	  Select this to enable a UART for platforms using PL010.
+
+config PL011_SERIAL
+	bool "ARM PL011 driver"
+	depends on !DM_SERIAL
+	help
+	  Select this to enable a UART for platforms using PL011.
+
+config PL01X_SERIAL
+	bool "ARM PL010 and PL011 driver"
+	depends on DM_SERIAL
+	help
+	  Select this to enable a UART for platforms using PL010 or PL011.
+
 config ROCKCHIP_SERIAL
 	bool "Rockchip on-chip UART support"
 	depends on DM_SERIAL && SPL_OF_PLATDATA
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 5ef603a..cac9a8b 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -46,6 +46,7 @@
 obj-$(CONFIG_PIC32_SERIAL) += serial_pic32.o
 obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o
 obj-$(CONFIG_BCM283X_MU_SERIAL) += serial_bcm283x_mu.o
+obj-$(CONFIG_BCM283X_PL011_SERIAL) += serial_bcm283x_pl011.o
 obj-$(CONFIG_MSM_SERIAL) += serial_msm.o
 obj-$(CONFIG_MVEBU_A3700_UART) += serial_mvebu_a3700.o
 obj-$(CONFIG_MPC8XX_CONS) += serial_mpc8xx.o
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index c702304..6f9ce68 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -339,9 +339,9 @@
 	struct NS16550 *const com_port = dev_get_priv(dev);
 
 	if (input)
-		return serial_in(&com_port->lsr) & UART_LSR_DR ? 1 : 0;
+		return (serial_in(&com_port->lsr) & UART_LSR_DR) ? 1 : 0;
 	else
-		return serial_in(&com_port->lsr) & UART_LSR_THRE ? 0 : 1;
+		return (serial_in(&com_port->lsr) & UART_LSR_THRE) ? 0 : 1;
 }
 
 static int ns16550_serial_getc(struct udevice *dev)
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index 2e5116f..68ca2d0 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -74,6 +74,7 @@
 {
 	const void *blob = gd->fdt_blob;
 	struct udevice *dev;
+	int ret;
 
 	if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
 		uclass_first_device(UCLASS_SERIAL, &dev);
@@ -104,8 +105,8 @@
 		 * from 1!).
 		 *
 		 * Failing that, get the device with sequence number 0, or in
-		 * extremis just the first serial device we can find. But we
-		 * insist on having a console (even if it is silent).
+		 * extremis just the first working serial device we can find.
+		 * But we insist on having a console (even if it is silent).
 		 */
 #ifdef CONFIG_CONS_INDEX
 #define INDEX (CONFIG_CONS_INDEX - 1)
@@ -113,10 +114,22 @@
 #define INDEX 0
 #endif
 		if (!uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &dev) ||
-		    !uclass_get_device(UCLASS_SERIAL, INDEX, &dev) ||
-		    (!uclass_first_device(UCLASS_SERIAL, &dev) && dev)) {
-			gd->cur_serial_dev = dev;
-			return;
+		    !uclass_get_device(UCLASS_SERIAL, INDEX, &dev)) {
+			if (dev->flags & DM_FLAG_ACTIVATED) {
+				gd->cur_serial_dev = dev;
+				return;
+			}
+		}
+
+		/* Search for any working device */
+		for (ret = uclass_first_device_check(UCLASS_SERIAL, &dev);
+		     dev;
+		     ret = uclass_next_device_check(&dev)) {
+			if (!ret) {
+				/* Device did succeed probing */
+				gd->cur_serial_dev = dev;
+				return;
+			}
 		}
 #undef INDEX
 	}
diff --git a/drivers/serial/serial_bcm283x_mu.c b/drivers/serial/serial_bcm283x_mu.c
index 41c26b3..40029fa 100644
--- a/drivers/serial/serial_bcm283x_mu.c
+++ b/drivers/serial/serial_bcm283x_mu.c
@@ -19,13 +19,12 @@
 #include <dm.h>
 #include <errno.h>
 #include <watchdog.h>
+#include <asm/gpio.h>
 #include <asm/io.h>
 #include <serial.h>
 #include <dm/platform_data/serial_bcm283x_mu.h>
+#include <dm/pinctrl.h>
 #include <linux/compiler.h>
-#include <fdtdec.h>
-
-DECLARE_GLOBAL_DATA_PTR;
 
 struct bcm283x_mu_regs {
 	u32 io;
@@ -59,7 +58,7 @@
 	struct bcm283x_mu_regs *regs = priv->regs;
 	u32 divider;
 
-	if (plat->disabled || plat->skip_init)
+	if (plat->skip_init)
 		return 0;
 
 	divider = plat->clock / (baudrate * 8);
@@ -75,9 +74,6 @@
 	struct bcm283x_mu_serial_platdata *plat = dev_get_platdata(dev);
 	struct bcm283x_mu_priv *priv = dev_get_priv(dev);
 
-	if (plat->disabled)
-		return -ENODEV;
-
 	priv->regs = (struct bcm283x_mu_regs *)plat->base;
 
 	return 0;
@@ -85,14 +81,10 @@
 
 static int bcm283x_mu_serial_getc(struct udevice *dev)
 {
-	struct bcm283x_mu_serial_platdata *plat = dev_get_platdata(dev);
 	struct bcm283x_mu_priv *priv = dev_get_priv(dev);
 	struct bcm283x_mu_regs *regs = priv->regs;
 	u32 data;
 
-	if (plat->disabled)
-		return -EAGAIN;
-
 	/* Wait until there is data in the FIFO */
 	if (!(readl(&regs->lsr) & BCM283X_MU_LSR_RX_READY))
 		return -EAGAIN;
@@ -104,13 +96,9 @@
 
 static int bcm283x_mu_serial_putc(struct udevice *dev, const char data)
 {
-	struct bcm283x_mu_serial_platdata *plat = dev_get_platdata(dev);
 	struct bcm283x_mu_priv *priv = dev_get_priv(dev);
 	struct bcm283x_mu_regs *regs = priv->regs;
 
-	if (plat->disabled)
-		return 0;
-
 	/* Wait until there is space in the FIFO */
 	if (!(readl(&regs->lsr) & BCM283X_MU_LSR_TX_EMPTY))
 		return -EAGAIN;
@@ -123,14 +111,10 @@
 
 static int bcm283x_mu_serial_pending(struct udevice *dev, bool input)
 {
-	struct bcm283x_mu_serial_platdata *plat = dev_get_platdata(dev);
 	struct bcm283x_mu_priv *priv = dev_get_priv(dev);
 	struct bcm283x_mu_regs *regs = priv->regs;
 	unsigned int lsr;
 
-	if (plat->disabled)
-		return 0;
-
 	lsr = readl(&regs->lsr);
 
 	if (input) {
@@ -154,21 +138,50 @@
 	{}
 };
 
+/*
+ * Check if this serial device is muxed
+ *
+ * The serial device will only work properly if it has been muxed to the serial
+ * pins by firmware. Check whether that happened here.
+ *
+ * @return true if serial device is muxed, false if not
+ */
+static bool bcm283x_is_serial_muxed(void)
+{
+	int serial_gpio = 15;
+	struct udevice *dev;
+
+	if (uclass_first_device(UCLASS_PINCTRL, &dev) || !dev)
+		return false;
+
+	if (pinctrl_get_gpio_mux(dev, 0, serial_gpio) != BCM2835_GPIO_ALT5)
+		return false;
+
+	return true;
+}
+
 static int bcm283x_mu_serial_ofdata_to_platdata(struct udevice *dev)
 {
 	struct bcm283x_mu_serial_platdata *plat = dev_get_platdata(dev);
 	fdt_addr_t addr;
 
+	/* Don't spawn the device if it's not muxed */
+	if (!bcm283x_is_serial_muxed())
+		return -ENODEV;
+
 	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
 	plat->base = addr;
-	plat->clock = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "clock",
-				     1);
-	plat->skip_init = fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
-	                                  "skip-init");
-	plat->disabled = false;
+	plat->clock = dev_read_u32_default(dev, "clock", 1);
+
+	/*
+	 * TODO: Reinitialization doesn't always work for now, just skip
+	 *       init always - we know we're already initialized
+	 */
+	plat->skip_init = true;
+
 	return 0;
 }
 #endif
diff --git a/drivers/serial/serial_bcm283x_pl011.c b/drivers/serial/serial_bcm283x_pl011.c
new file mode 100644
index 0000000..bfd39f8
--- /dev/null
+++ b/drivers/serial/serial_bcm283x_pl011.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2018 Alexander Graf <agraf@suse.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/gpio.h>
+#include <dm/pinctrl.h>
+#include <dm/platform_data/serial_pl01x.h>
+#include "serial_pl01x_internal.h"
+
+/*
+ * Check if this serial device is muxed
+ *
+ * The serial device will only work properly if it has been muxed to the serial
+ * pins by firmware. Check whether that happened here.
+ *
+ * @return true if serial device is muxed, false if not
+ */
+static bool bcm283x_is_serial_muxed(void)
+{
+	int serial_gpio = 15;
+	struct udevice *dev;
+
+	if (uclass_first_device(UCLASS_PINCTRL, &dev) || !dev)
+		return false;
+
+	if (pinctrl_get_gpio_mux(dev, 0, serial_gpio) != BCM2835_GPIO_ALT0)
+		return false;
+
+	return true;
+}
+
+static int bcm283x_pl011_serial_ofdata_to_platdata(struct udevice *dev)
+{
+	struct pl01x_serial_platdata *plat = dev_get_platdata(dev);
+	int ret;
+
+	/* Don't spawn the device if it's not muxed */
+	if (!bcm283x_is_serial_muxed())
+		return -ENODEV;
+
+	ret = pl01x_serial_ofdata_to_platdata(dev);
+	if (ret)
+		return ret;
+
+	/*
+	 * TODO: Reinitialization doesn't always work for now, just skip
+	 *       init always - we know we're already initialized
+	 */
+	plat->skip_init = true;
+
+	return 0;
+}
+
+static const struct udevice_id bcm283x_pl011_serial_id[] = {
+	{.compatible = "brcm,bcm2835-pl011", .data = TYPE_PL011},
+	{}
+};
+
+U_BOOT_DRIVER(bcm283x_pl011_uart) = {
+	.name	= "bcm283x_pl011",
+	.id	= UCLASS_SERIAL,
+	.of_match = of_match_ptr(bcm283x_pl011_serial_id),
+	.ofdata_to_platdata = of_match_ptr(bcm283x_pl011_serial_ofdata_to_platdata),
+	.platdata_auto_alloc_size = sizeof(struct pl01x_serial_platdata),
+	.probe	= pl01x_serial_probe,
+	.ops	= &pl01x_serial_ops,
+	.flags	= DM_FLAG_PRE_RELOC,
+	.priv_auto_alloc_size = sizeof(struct pl01x_priv),
+};
diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c
index 4ec0f29..23d9d83 100644
--- a/drivers/serial/serial_pl01x.c
+++ b/drivers/serial/serial_pl01x.c
@@ -20,7 +20,6 @@
 #include <dm/platform_data/serial_pl01x.h>
 #include <linux/compiler.h>
 #include "serial_pl01x_internal.h"
-#include <fdtdec.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -274,11 +273,6 @@
 
 #ifdef CONFIG_DM_SERIAL
 
-struct pl01x_priv {
-	struct pl01x_regs *regs;
-	enum pl01x_type type;
-};
-
 static int pl01x_serial_setbrg(struct udevice *dev, int baudrate)
 {
 	struct pl01x_serial_platdata *plat = dev_get_platdata(dev);
@@ -292,7 +286,7 @@
 	return 0;
 }
 
-static int pl01x_serial_probe(struct udevice *dev)
+int pl01x_serial_probe(struct udevice *dev)
 {
 	struct pl01x_serial_platdata *plat = dev_get_platdata(dev);
 	struct pl01x_priv *priv = dev_get_priv(dev);
@@ -330,7 +324,7 @@
 		return fr & UART_PL01x_FR_TXFF ? 0 : 1;
 }
 
-static const struct dm_serial_ops pl01x_serial_ops = {
+const struct dm_serial_ops pl01x_serial_ops = {
 	.putc = pl01x_serial_putc,
 	.pending = pl01x_serial_pending,
 	.getc = pl01x_serial_getc,
@@ -344,7 +338,7 @@
 	{}
 };
 
-static int pl01x_serial_ofdata_to_platdata(struct udevice *dev)
+int pl01x_serial_ofdata_to_platdata(struct udevice *dev)
 {
 	struct pl01x_serial_platdata *plat = dev_get_platdata(dev);
 	fdt_addr_t addr;
@@ -354,11 +348,10 @@
 		return -EINVAL;
 
 	plat->base = addr;
-	plat->clock = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "clock",
-				     1);
+	plat->clock = dev_read_u32_default(dev, "clock", 1);
 	plat->type = dev_get_driver_data(dev);
-	plat->skip_init = fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
-	                                  "skip-init");
+	plat->skip_init = dev_read_bool(dev, "skip-init");
+
 	return 0;
 }
 #endif
diff --git a/drivers/serial/serial_pl01x_internal.h b/drivers/serial/serial_pl01x_internal.h
index 288a4f1..c56dd54 100644
--- a/drivers/serial/serial_pl01x_internal.h
+++ b/drivers/serial/serial_pl01x_internal.h
@@ -38,7 +38,20 @@
 	u32	pl011_lcrh;	/* 0x2C Line control register */
 	u32	pl011_cr;	/* 0x30 Control register */
 };
-#endif
+
+#ifdef CONFIG_DM_SERIAL
+
+int pl01x_serial_ofdata_to_platdata(struct udevice *dev);
+int pl01x_serial_probe(struct udevice *dev);
+extern const struct dm_serial_ops pl01x_serial_ops;
+
+struct pl01x_priv {
+	struct pl01x_regs *regs;
+	enum pl01x_type type;
+};
+
+#endif /* CONFIG_DM_SERIAL */
+#endif /* !__ASSEMBLY__ */
 
 #define UART_PL01x_RSR_OE               0x08
 #define UART_PL01x_RSR_BE               0x04
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 79df888..7f9ba24 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -14,7 +14,6 @@
 obj-$(CONFIG_USB_OHCI_NEW) += ohci-hcd.o
 obj-$(CONFIG_USB_ATMEL) += ohci-at91.o
 obj-$(CONFIG_USB_OHCI_DA8XX) += ohci-da8xx.o
-obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
 obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o
 obj-$(CONFIG_USB_SL811HS) += sl811-hcd.o
 obj-$(CONFIG_USB_OHCI_EP93XX) += ohci-ep93xx.o
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
deleted file mode 100644
index 32874d7..0000000
--- a/drivers/usb/host/isp116x-hcd.c
+++ /dev/null
@@ -1,1323 +0,0 @@
-/*
- * ISP116x HCD (Host Controller Driver) for u-boot.
- *
- * Copyright (C) 2006-2007 Rodolfo Giometti <giometti@linux.it>
- * Copyright (C) 2006-2007 Eurotech S.p.A. <info@eurotech.it>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- *
- * Derived in part from the SL811 HCD driver "u-boot/drivers/usb/sl811_usb.c"
- * (original copyright message follows):
- *
- *    (C) Copyright 2004
- *    Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- *    This code is based on linux driver for sl811hs chip, source at
- *    drivers/usb/host/sl811.c:
- *
- *    SL811 Host Controller Interface driver for USB.
- *
- *    Copyright (c) 2003/06, Courage Co., Ltd.
- *
- *    Based on:
- *         1.uhci.c by Linus Torvalds, Johannes Erdfelt, Randy Dunlap,
- *           Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber,
- *           Adam Richter, Gregory P. Smith;
- *         2.Original SL811 driver (hc_sl811.o) by Pei Liu <pbl@cypress.com>
- *         3.Rewrited as sl811.o by Yin Aihua <yinah:couragetech.com.cn>
- *
- *    [[GNU/GPL disclaimer]]
- *
- * and in part from AU1x00 OHCI HCD driver "u-boot/arch/mips/cpu/au1x00_usb_ohci.c"
- * (original copyright message follows):
- *
- *    URB OHCI HCD (Host Controller Driver) for USB on the AU1x00.
- *
- *    (C) Copyright 2003
- *    Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
- *
- *    [[GNU/GPL disclaimer]]
- *
- *    Note: Part of this code has been derived from linux
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <usb.h>
-#include <malloc.h>
-#include <linux/list.h>
-
-/*
- * ISP116x chips require certain delays between accesses to its
- * registers. The following timing options exist.
- *
- * 1. Configure your memory controller (the best)
- * 2. Use ndelay (easiest, poorest). For that, enable the following macro.
- *
- * Value is in microseconds.
- */
-#ifdef ISP116X_HCD_USE_UDELAY
-#define UDELAY		1
-#endif
-
-/*
- * On some (slowly?) machines an extra delay after data packing into
- * controller's FIFOs is required, * otherwise you may get the following
- * error:
- *
- *   uboot> usb start
- *   (Re)start USB...
- *   USB:   scanning bus for devices... isp116x: isp116x_submit_job: CTL:TIMEOUT
- *   isp116x: isp116x_submit_job: ****** FIFO not ready! ******
- *
- *         USB device not responding, giving up (status=4)
- *         isp116x: isp116x_submit_job: ****** FIFO not empty! ******
- *         isp116x: isp116x_submit_job: ****** FIFO not empty! ******
- *         isp116x: isp116x_submit_job: ****** FIFO not empty! ******
- *         3 USB Device(s) found
- *                scanning bus for storage devices... 0 Storage Device(s) found
- *
- * Value is in milliseconds.
- */
-#ifdef ISP116X_HCD_USE_EXTRA_DELAY
-#define EXTRA_DELAY	2
-#endif
-
-/*
- * Enable the following defines if you wish enable debugging messages.
- */
-#undef DEBUG			/* enable debugging messages */
-#undef TRACE			/* enable tracing code */
-#undef VERBOSE			/* verbose debugging messages */
-
-#include "isp116x.h"
-
-#define DRIVER_VERSION	"08 Jan 2007"
-static const char hcd_name[] = "isp116x-hcd";
-
-struct isp116x isp116x_dev;
-struct isp116x_platform_data isp116x_board;
-static int got_rhsc;		/* root hub status change */
-struct usb_device *devgone;	/* device which was disconnected */
-static int rh_devnum;		/* address of Root Hub endpoint */
-
-/* ------------------------------------------------------------------------- */
-
-static int isp116x_reset(struct isp116x *isp116x);
-
-/* --- Debugging functions ------------------------------------------------- */
-
-#define isp116x_show_reg(d, r) {				\
-	if ((r) < 0x20) {					\
-		DBG("%-12s[%02x]: %08x", #r,			\
-			r, isp116x_read_reg32(d, r));		\
-	} else {						\
-		DBG("%-12s[%02x]:     %04x", #r,		\
-			r, isp116x_read_reg16(d, r));		\
-	}							\
-}
-
-#define isp116x_show_regs(d) {					\
-	isp116x_show_reg(d, HCREVISION);			\
-	isp116x_show_reg(d, HCCONTROL);				\
-	isp116x_show_reg(d, HCCMDSTAT);				\
-	isp116x_show_reg(d, HCINTSTAT);				\
-	isp116x_show_reg(d, HCINTENB);				\
-	isp116x_show_reg(d, HCFMINTVL);				\
-	isp116x_show_reg(d, HCFMREM);				\
-	isp116x_show_reg(d, HCFMNUM);				\
-	isp116x_show_reg(d, HCLSTHRESH);			\
-	isp116x_show_reg(d, HCRHDESCA);				\
-	isp116x_show_reg(d, HCRHDESCB);				\
-	isp116x_show_reg(d, HCRHSTATUS);			\
-	isp116x_show_reg(d, HCRHPORT1);				\
-	isp116x_show_reg(d, HCRHPORT2);				\
-	isp116x_show_reg(d, HCHWCFG);				\
-	isp116x_show_reg(d, HCDMACFG);				\
-	isp116x_show_reg(d, HCXFERCTR);				\
-	isp116x_show_reg(d, HCuPINT);				\
-	isp116x_show_reg(d, HCuPINTENB);			\
-	isp116x_show_reg(d, HCCHIPID);				\
-	isp116x_show_reg(d, HCSCRATCH);				\
-	isp116x_show_reg(d, HCITLBUFLEN);			\
-	isp116x_show_reg(d, HCATLBUFLEN);			\
-	isp116x_show_reg(d, HCBUFSTAT);				\
-	isp116x_show_reg(d, HCRDITL0LEN);			\
-	isp116x_show_reg(d, HCRDITL1LEN);			\
-}
-
-#if defined(TRACE)
-
-static int isp116x_get_current_frame_number(struct usb_device *usb_dev)
-{
-	struct isp116x *isp116x = &isp116x_dev;
-
-	return isp116x_read_reg32(isp116x, HCFMNUM);
-}
-
-static void dump_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-		     int len, char *str)
-{
-#if defined(VERBOSE)
-	int i;
-#endif
-
-	DBG("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d stat:%#lx",
-	    str,
-	    isp116x_get_current_frame_number(dev),
-	    usb_pipedevice(pipe),
-	    usb_pipeendpoint(pipe),
-	    usb_pipeout(pipe) ? 'O' : 'I',
-	    usb_pipetype(pipe) < 2 ?
-	    (usb_pipeint(pipe) ?
-	     "INTR" : "ISOC") :
-	    (usb_pipecontrol(pipe) ? "CTRL" : "BULK"), len, dev->status);
-#if defined(VERBOSE)
-	if (len > 0 && buffer) {
-		printf(__FILE__ ": data(%d):", len);
-		for (i = 0; i < 16 && i < len; i++)
-			printf(" %02x", ((__u8 *) buffer)[i]);
-		printf("%s\n", i < len ? "..." : "");
-	}
-#endif
-}
-
-#define PTD_DIR_STR(ptd)  ({char __c;		\
-	switch(PTD_GET_DIR(ptd)){		\
-	case 0:  __c = 's'; break;		\
-	case 1:  __c = 'o'; break;		\
-	default: __c = 'i'; break;		\
-	}; __c;})
-
-/*
-  Dump PTD info. The code documents the format
-  perfectly, right :)
-*/
-static inline void dump_ptd(struct ptd *ptd)
-{
-#if defined(VERBOSE)
-	int k;
-#endif
-
-	DBG("PTD(ext) : cc:%x %d%c%d %d,%d,%d t:%x %x%x%x",
-	    PTD_GET_CC(ptd),
-	    PTD_GET_FA(ptd), PTD_DIR_STR(ptd), PTD_GET_EP(ptd),
-	    PTD_GET_COUNT(ptd), PTD_GET_LEN(ptd), PTD_GET_MPS(ptd),
-	    PTD_GET_TOGGLE(ptd),
-	    PTD_GET_ACTIVE(ptd), PTD_GET_SPD(ptd), PTD_GET_LAST(ptd));
-#if defined(VERBOSE)
-	printf("isp116x: %s: PTD(byte): ", __FUNCTION__);
-	for (k = 0; k < sizeof(struct ptd); ++k)
-		printf("%02x ", ((u8 *) ptd)[k]);
-	printf("\n");
-#endif
-}
-
-static inline void dump_ptd_data(struct ptd *ptd, u8 * buf, int type)
-{
-#if defined(VERBOSE)
-	int k;
-
-	if (type == 0 /* 0ut data */ ) {
-		printf("isp116x: %s: out data: ", __FUNCTION__);
-		for (k = 0; k < PTD_GET_LEN(ptd); ++k)
-			printf("%02x ", ((u8 *) buf)[k]);
-		printf("\n");
-	}
-	if (type == 1 /* 1n data */ ) {
-		printf("isp116x: %s: in data: ", __FUNCTION__);
-		for (k = 0; k < PTD_GET_COUNT(ptd); ++k)
-			printf("%02x ", ((u8 *) buf)[k]);
-		printf("\n");
-	}
-
-	if (PTD_GET_LAST(ptd))
-		DBG("--- last PTD ---");
-#endif
-}
-
-#else
-
-#define dump_msg(dev, pipe, buffer, len, str)			do { } while (0)
-#define dump_pkt(dev, pipe, buffer, len, setup, str, small)	do {} while (0)
-
-#define dump_ptd(ptd)			do {} while (0)
-#define dump_ptd_data(ptd, buf, type)	do {} while (0)
-
-#endif
-
-/* --- Virtual Root Hub ---------------------------------------------------- */
-
-#include <usbroothubdes.h>
-
-/*
- * Hub class-specific descriptor is constructed dynamically
- */
-
-/* --- Virtual root hub management functions ------------------------------- */
-
-static int rh_check_port_status(struct isp116x *isp116x)
-{
-	u32 temp, ndp, i;
-	int res;
-
-	res = -1;
-	temp = isp116x_read_reg32(isp116x, HCRHSTATUS);
-	ndp = (temp & RH_A_NDP);
-	for (i = 0; i < ndp; i++) {
-		temp = isp116x_read_reg32(isp116x, HCRHPORT1 + i);
-		/* check for a device disconnect */
-		if (((temp & (RH_PS_PESC | RH_PS_CSC)) ==
-		     (RH_PS_PESC | RH_PS_CSC)) && ((temp & RH_PS_CCS) == 0)) {
-			res = i;
-			break;
-		}
-	}
-	return res;
-}
-
-/* --- HC management functions --------------------------------------------- */
-
-/* Write len bytes to fifo, pad till 32-bit boundary
- */
-static void write_ptddata_to_fifo(struct isp116x *isp116x, void *buf, int len)
-{
-	u8 *dp = (u8 *) buf;
-	u16 *dp2 = (u16 *) buf;
-	u16 w;
-	int quot = len % 4;
-
-	if ((unsigned long)dp2 & 1) {
-		/* not aligned */
-		for (; len > 1; len -= 2) {
-			w = *dp++;
-			w |= *dp++ << 8;
-			isp116x_raw_write_data16(isp116x, w);
-		}
-		if (len)
-			isp116x_write_data16(isp116x, (u16) * dp);
-	} else {
-		/* aligned */
-		for (; len > 1; len -= 2)
-			isp116x_raw_write_data16(isp116x, *dp2++);
-		if (len)
-			isp116x_write_data16(isp116x, 0xff & *((u8 *) dp2));
-	}
-	if (quot == 1 || quot == 2)
-		isp116x_raw_write_data16(isp116x, 0);
-}
-
-/* Read len bytes from fifo and then read till 32-bit boundary
- */
-static void read_ptddata_from_fifo(struct isp116x *isp116x, void *buf, int len)
-{
-	u8 *dp = (u8 *) buf;
-	u16 *dp2 = (u16 *) buf;
-	u16 w;
-	int quot = len % 4;
-
-	if ((unsigned long)dp2 & 1) {
-		/* not aligned */
-		for (; len > 1; len -= 2) {
-			w = isp116x_raw_read_data16(isp116x);
-			*dp++ = w & 0xff;
-			*dp++ = (w >> 8) & 0xff;
-		}
-		if (len)
-			*dp = 0xff & isp116x_read_data16(isp116x);
-	} else {
-		/* aligned */
-		for (; len > 1; len -= 2)
-			*dp2++ = isp116x_raw_read_data16(isp116x);
-		if (len)
-			*(u8 *) dp2 = 0xff & isp116x_read_data16(isp116x);
-	}
-	if (quot == 1 || quot == 2)
-		isp116x_raw_read_data16(isp116x);
-}
-
-/* Write PTD's and data for scheduled transfers into the fifo ram.
- * Fifo must be empty and ready */
-static void pack_fifo(struct isp116x *isp116x, struct usb_device *dev,
-		      unsigned long pipe, struct ptd *ptd, int n, void *data,
-		      int len)
-{
-	int buflen = n * sizeof(struct ptd) + len;
-	int i, done;
-
-	DBG("--- pack buffer %p - %d bytes (fifo %d) ---", data, len, buflen);
-
-	isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT);
-	isp116x_write_reg16(isp116x, HCXFERCTR, buflen);
-	isp116x_write_addr(isp116x, HCATLPORT | ISP116x_WRITE_OFFSET);
-
-	done = 0;
-	for (i = 0; i < n; i++) {
-		DBG("i=%d - done=%d - len=%d", i, done, PTD_GET_LEN(&ptd[i]));
-
-		dump_ptd(&ptd[i]);
-		isp116x_write_data16(isp116x, ptd[i].count);
-		isp116x_write_data16(isp116x, ptd[i].mps);
-		isp116x_write_data16(isp116x, ptd[i].len);
-		isp116x_write_data16(isp116x, ptd[i].faddr);
-
-		dump_ptd_data(&ptd[i], (__u8 *) data + done, 0);
-		write_ptddata_to_fifo(isp116x,
-				      (__u8 *) data + done,
-				      PTD_GET_LEN(&ptd[i]));
-
-		done += PTD_GET_LEN(&ptd[i]);
-	}
-}
-
-/* Read the processed PTD's and data from fifo ram back to URBs' buffers.
- * Fifo must be full and done */
-static int unpack_fifo(struct isp116x *isp116x, struct usb_device *dev,
-		       unsigned long pipe, struct ptd *ptd, int n, void *data,
-		       int len)
-{
-	int buflen = n * sizeof(struct ptd) + len;
-	int i, done, cc, ret;
-
-	isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT);
-	isp116x_write_reg16(isp116x, HCXFERCTR, buflen);
-	isp116x_write_addr(isp116x, HCATLPORT);
-
-	ret = TD_CC_NOERROR;
-	done = 0;
-	for (i = 0; i < n; i++) {
-		DBG("i=%d - done=%d - len=%d", i, done, PTD_GET_LEN(&ptd[i]));
-
-		ptd[i].count = isp116x_read_data16(isp116x);
-		ptd[i].mps = isp116x_read_data16(isp116x);
-		ptd[i].len = isp116x_read_data16(isp116x);
-		ptd[i].faddr = isp116x_read_data16(isp116x);
-		dump_ptd(&ptd[i]);
-
-		read_ptddata_from_fifo(isp116x,
-				       (__u8 *) data + done,
-				       PTD_GET_LEN(&ptd[i]));
-		dump_ptd_data(&ptd[i], (__u8 *) data + done, 1);
-
-		done += PTD_GET_LEN(&ptd[i]);
-
-		cc = PTD_GET_CC(&ptd[i]);
-
-		/* Data underrun means basically that we had more buffer space than
-		 * the function had data. It is perfectly normal but upper levels have
-		 * to know how much we actually transferred.
-		 */
-		if (cc == TD_NOTACCESSED ||
-				(cc != TD_CC_NOERROR && (ret == TD_CC_NOERROR || ret == TD_DATAUNDERRUN)))
-			ret = cc;
-	}
-
-	DBG("--- unpack buffer %p - %d bytes (fifo %d) ---", data, len, buflen);
-
-	return ret;
-}
-
-/* Interrupt handling
- */
-static int isp116x_interrupt(struct isp116x *isp116x)
-{
-	u16 irqstat;
-	u32 intstat;
-	int ret = 0;
-
-	isp116x_write_reg16(isp116x, HCuPINTENB, 0);
-	irqstat = isp116x_read_reg16(isp116x, HCuPINT);
-	isp116x_write_reg16(isp116x, HCuPINT, irqstat);
-	DBG("------ irqstat %x ------", irqstat);
-
-	if (irqstat & HCuPINT_ATL) {
-		DBG("------ HCuPINT_ATL ------");
-		udelay(500);
-		ret = 1;
-	}
-
-	if (irqstat & HCuPINT_OPR) {
-		intstat = isp116x_read_reg32(isp116x, HCINTSTAT);
-		isp116x_write_reg32(isp116x, HCINTSTAT, intstat);
-		DBG("------ HCuPINT_OPR %x ------", intstat);
-
-		if (intstat & HCINT_UE) {
-			ERR("unrecoverable error, controller disabled");
-
-			/* FIXME: be optimistic, hope that bug won't repeat
-			 * often. Make some non-interrupt context restart the
-			 * controller. Count and limit the retries though;
-			 * either hardware or software errors can go forever...
-			 */
-			isp116x_reset(isp116x);
-			ret = -1;
-			return -1;
-		}
-
-		if (intstat & HCINT_RHSC) {
-			got_rhsc = 1;
-			ret = 1;
-			/* When root hub or any of its ports is going
-			   to come out of suspend, it may take more
-			   than 10ms for status bits to stabilize. */
-			mdelay(20);
-		}
-
-		if (intstat & HCINT_SO) {
-			ERR("schedule overrun");
-			ret = -1;
-		}
-
-		irqstat &= ~HCuPINT_OPR;
-	}
-
-	return ret;
-}
-
-/* With one PTD we can transfer almost 1K in one go;
- * HC does the splitting into endpoint digestible transactions
- */
-struct ptd ptd[1];
-
-static inline int max_transfer_len(struct usb_device *dev, unsigned long pipe)
-{
-	unsigned mpck = usb_maxpacket(dev, pipe);
-
-	/* One PTD can transfer 1023 bytes but try to always
-	 * transfer multiples of endpoint buffer size
-	 */
-	return 1023 / mpck * mpck;
-}
-
-/* Do an USB transfer
- */
-static int isp116x_submit_job(struct usb_device *dev, unsigned long pipe,
-			      int dir, void *buffer, int len)
-{
-	struct isp116x *isp116x = &isp116x_dev;
-	int type = usb_pipetype(pipe);
-	int epnum = usb_pipeendpoint(pipe);
-	int max = usb_maxpacket(dev, pipe);
-	int dir_out = usb_pipeout(pipe);
-	int speed_low = (dev->speed == USB_SPEED_LOW);
-	int i, done = 0, stat, timeout, cc;
-
-	/* 500 frames or 0.5s timeout when function is busy and NAKs transactions for a while */
-	int retries = 500;
-
-	DBG("------------------------------------------------");
-	dump_msg(dev, pipe, buffer, len, "SUBMIT");
-	DBG("------------------------------------------------");
-
-	if (len >= 1024) {
-		ERR("Too big job");
-		dev->status = USB_ST_CRC_ERR;
-		return -1;
-	}
-
-	if (isp116x->disabled) {
-		ERR("EPIPE");
-		dev->status = USB_ST_CRC_ERR;
-		return -1;
-	}
-
-	/* device pulled? Shortcut the action. */
-	if (devgone == dev) {
-		ERR("ENODEV");
-		dev->status = USB_ST_CRC_ERR;
-		return USB_ST_CRC_ERR;
-	}
-
-	if (!max) {
-		ERR("pipesize for pipe %lx is zero", pipe);
-		dev->status = USB_ST_CRC_ERR;
-		return -1;
-	}
-
-	if (type == PIPE_ISOCHRONOUS) {
-		ERR("isochronous transfers not supported");
-		dev->status = USB_ST_CRC_ERR;
-		return -1;
-	}
-
-	/* FIFO not empty? */
-	if (isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_FULL) {
-		ERR("****** FIFO not empty! ******");
-		dev->status = USB_ST_BUF_ERR;
-		return -1;
-	}
-
-      retry:
-	isp116x_write_reg32(isp116x, HCINTSTAT, 0xff);
-
-	/* Prepare the PTD data */
-	ptd->count = PTD_CC_MSK | PTD_ACTIVE_MSK |
-		PTD_TOGGLE(usb_gettoggle(dev, epnum, dir_out));
-	ptd->mps = PTD_MPS(max) | PTD_SPD(speed_low) | PTD_EP(epnum) | PTD_LAST_MSK;
-	ptd->len = PTD_LEN(len) | PTD_DIR(dir);
-	ptd->faddr = PTD_FA(usb_pipedevice(pipe));
-
-retry_same:
-	/* Pack data into FIFO ram */
-	pack_fifo(isp116x, dev, pipe, ptd, 1, buffer, len);
-#ifdef EXTRA_DELAY
-	mdelay(EXTRA_DELAY);
-#endif
-
-	/* Start the data transfer */
-
-	/* Allow more time for a BULK device to react - some are slow */
-	if (usb_pipebulk(pipe))
-		timeout = 5000;
-	else
-		timeout = 100;
-
-	/* Wait for it to complete */
-	for (;;) {
-		/* Check whether the controller is done */
-		stat = isp116x_interrupt(isp116x);
-
-		if (stat < 0) {
-			dev->status = USB_ST_CRC_ERR;
-			break;
-		}
-		if (stat > 0)
-			break;
-
-		/* Check the timeout */
-		if (--timeout)
-			udelay(1);
-		else {
-			ERR("CTL:TIMEOUT ");
-			stat = USB_ST_CRC_ERR;
-			break;
-		}
-	}
-
-	/* We got an Root Hub Status Change interrupt */
-	if (got_rhsc) {
-		isp116x_show_regs(isp116x);
-
-		got_rhsc = 0;
-
-		/* Abuse timeout */
-		timeout = rh_check_port_status(isp116x);
-		if (timeout >= 0) {
-			/*
-			 * FIXME! NOTE! AAAARGH!
-			 * This is potentially dangerous because it assumes
-			 * that only one device is ever plugged in!
-			 */
-			devgone = dev;
-		}
-	}
-
-	/* Ok, now we can read transfer status */
-
-	/* FIFO not ready? */
-	if (!(isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_DONE)) {
-		ERR("****** FIFO not ready! ******");
-		dev->status = USB_ST_BUF_ERR;
-		return -1;
-	}
-
-	/* Unpack data from FIFO ram */
-	cc = unpack_fifo(isp116x, dev, pipe, ptd, 1, buffer, len);
-
-	i = PTD_GET_COUNT(ptd);
-	done += i;
-	buffer += i;
-	len -= i;
-
-	/* There was some kind of real problem; Prepare the PTD again
-	 * and retry from the failed transaction on
-	 */
-	if (cc && cc != TD_NOTACCESSED && cc != TD_DATAUNDERRUN) {
-		if (retries >= 100) {
-			retries -= 100;
-			/* The chip will have toggled the toggle bit for the failed
-			 * transaction too. We have to toggle it back.
-			 */
-			usb_settoggle(dev, epnum, dir_out, !PTD_GET_TOGGLE(ptd));
-			goto retry;
-		}
-	}
-	/* "Normal" errors; TD_NOTACCESSED would mean in effect that the function have NAKed
-	 * the transactions from the first on for the whole frame. It may be busy and we retry
-	 * with the same PTD. PTD_ACTIVE (and not TD_NOTACCESSED) would mean that some of the
-	 * PTD didn't make it because the function was busy or the frame ended before the PTD
-	 * finished. We prepare the rest of the data and try again.
-	 */
-	else if (cc == TD_NOTACCESSED || PTD_GET_ACTIVE(ptd) || (cc != TD_DATAUNDERRUN && PTD_GET_COUNT(ptd) < PTD_GET_LEN(ptd))) {
-		if (retries) {
-			--retries;
-			if (cc == TD_NOTACCESSED && PTD_GET_ACTIVE(ptd) && !PTD_GET_COUNT(ptd)) goto retry_same;
-			usb_settoggle(dev, epnum, dir_out, PTD_GET_TOGGLE(ptd));
-			goto retry;
-		}
-	}
-
-	if (cc != TD_CC_NOERROR && cc != TD_DATAUNDERRUN) {
-		DBG("****** completition code error %x ******", cc);
-		switch (cc) {
-		case TD_CC_BITSTUFFING:
-			dev->status = USB_ST_BIT_ERR;
-			break;
-		case TD_CC_STALL:
-			dev->status = USB_ST_STALLED;
-			break;
-		case TD_BUFFEROVERRUN:
-		case TD_BUFFERUNDERRUN:
-			dev->status = USB_ST_BUF_ERR;
-			break;
-		default:
-			dev->status = USB_ST_CRC_ERR;
-		}
-		return -cc;
-	}
-	else usb_settoggle(dev, epnum, dir_out, PTD_GET_TOGGLE(ptd));
-
-	dump_msg(dev, pipe, buffer, len, "SUBMIT(ret)");
-
-	dev->status = 0;
-	return done;
-}
-
-/* Adapted from au1x00_usb_ohci.c
- */
-static int isp116x_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
-				 void *buffer, int transfer_len,
-				 struct devrequest *cmd)
-{
-	struct isp116x *isp116x = &isp116x_dev;
-	u32 tmp = 0;
-
-	int leni = transfer_len;
-	int len = 0;
-	int stat = 0;
-	u32 datab[4];
-	u8 *data_buf = (u8 *) datab;
-	u16 bmRType_bReq;
-	u16 wValue;
-	u16 wIndex;
-	u16 wLength;
-
-	if (usb_pipeint(pipe)) {
-		INFO("Root-Hub submit IRQ: NOT implemented");
-		return 0;
-	}
-
-	bmRType_bReq = cmd->requesttype | (cmd->request << 8);
-	wValue = swap_16(cmd->value);
-	wIndex = swap_16(cmd->index);
-	wLength = swap_16(cmd->length);
-
-	DBG("--- HUB ----------------------------------------");
-	DBG("submit rh urb, req=%x val=%#x index=%#x len=%d",
-	    bmRType_bReq, wValue, wIndex, wLength);
-	dump_msg(dev, pipe, buffer, transfer_len, "RH");
-	DBG("------------------------------------------------");
-
-	switch (bmRType_bReq) {
-	case RH_GET_STATUS:
-		DBG("RH_GET_STATUS");
-
-		*(__u16 *) data_buf = swap_16(1);
-		len = 2;
-		break;
-
-	case RH_GET_STATUS | RH_INTERFACE:
-		DBG("RH_GET_STATUS | RH_INTERFACE");
-
-		*(__u16 *) data_buf = swap_16(0);
-		len = 2;
-		break;
-
-	case RH_GET_STATUS | RH_ENDPOINT:
-		DBG("RH_GET_STATUS | RH_ENDPOINT");
-
-		*(__u16 *) data_buf = swap_16(0);
-		len = 2;
-		break;
-
-	case RH_GET_STATUS | RH_CLASS:
-		DBG("RH_GET_STATUS | RH_CLASS");
-
-		tmp = isp116x_read_reg32(isp116x, HCRHSTATUS);
-
-		*(__u32 *) data_buf = swap_32(tmp & ~(RH_HS_CRWE | RH_HS_DRWE));
-		len = 4;
-		break;
-
-	case RH_GET_STATUS | RH_OTHER | RH_CLASS:
-		DBG("RH_GET_STATUS | RH_OTHER | RH_CLASS");
-
-		tmp = isp116x_read_reg32(isp116x, HCRHPORT1 + wIndex - 1);
-		*(__u32 *) data_buf = swap_32(tmp);
-		isp116x_show_regs(isp116x);
-		len = 4;
-		break;
-
-	case RH_CLEAR_FEATURE | RH_ENDPOINT:
-		DBG("RH_CLEAR_FEATURE | RH_ENDPOINT");
-
-		switch (wValue) {
-		case RH_ENDPOINT_STALL:
-			DBG("C_HUB_ENDPOINT_STALL");
-			len = 0;
-			break;
-		}
-		break;
-
-	case RH_CLEAR_FEATURE | RH_CLASS:
-		DBG("RH_CLEAR_FEATURE | RH_CLASS");
-
-		switch (wValue) {
-		case RH_C_HUB_LOCAL_POWER:
-			DBG("C_HUB_LOCAL_POWER");
-			len = 0;
-			break;
-
-		case RH_C_HUB_OVER_CURRENT:
-			DBG("C_HUB_OVER_CURRENT");
-			isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_OCIC);
-			len = 0;
-			break;
-		}
-		break;
-
-	case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
-		DBG("RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS");
-
-		switch (wValue) {
-		case RH_PORT_ENABLE:
-			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-					    RH_PS_CCS);
-			len = 0;
-			break;
-
-		case RH_PORT_SUSPEND:
-			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-					    RH_PS_POCI);
-			len = 0;
-			break;
-
-		case RH_PORT_POWER:
-			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-					    RH_PS_LSDA);
-			len = 0;
-			break;
-
-		case RH_C_PORT_CONNECTION:
-			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-					    RH_PS_CSC);
-			len = 0;
-			break;
-
-		case RH_C_PORT_ENABLE:
-			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-					    RH_PS_PESC);
-			len = 0;
-			break;
-
-		case RH_C_PORT_SUSPEND:
-			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-					    RH_PS_PSSC);
-			len = 0;
-			break;
-
-		case RH_C_PORT_OVER_CURRENT:
-			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-					    RH_PS_POCI);
-			len = 0;
-			break;
-
-		case RH_C_PORT_RESET:
-			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-					    RH_PS_PRSC);
-			len = 0;
-			break;
-
-		default:
-			ERR("invalid wValue");
-			stat = USB_ST_STALLED;
-		}
-
-		isp116x_show_regs(isp116x);
-
-		break;
-
-	case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
-		DBG("RH_SET_FEATURE | RH_OTHER | RH_CLASS");
-
-		switch (wValue) {
-		case RH_PORT_SUSPEND:
-			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-					    RH_PS_PSS);
-			len = 0;
-			break;
-
-		case RH_PORT_RESET:
-			/* Spin until any current reset finishes */
-			while (1) {
-				tmp =
-				    isp116x_read_reg32(isp116x,
-						       HCRHPORT1 + wIndex - 1);
-				if (!(tmp & RH_PS_PRS))
-					break;
-				mdelay(1);
-			}
-			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-					    RH_PS_PRS);
-			mdelay(10);
-
-			len = 0;
-			break;
-
-		case RH_PORT_POWER:
-			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-					    RH_PS_PPS);
-			len = 0;
-			break;
-
-		case RH_PORT_ENABLE:
-			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
-					    RH_PS_PES);
-			len = 0;
-			break;
-
-		default:
-			ERR("invalid wValue");
-			stat = USB_ST_STALLED;
-		}
-
-		isp116x_show_regs(isp116x);
-
-		break;
-
-	case RH_SET_ADDRESS:
-		DBG("RH_SET_ADDRESS");
-
-		rh_devnum = wValue;
-		len = 0;
-		break;
-
-	case RH_GET_DESCRIPTOR:
-		DBG("RH_GET_DESCRIPTOR: %x, %d", wValue, wLength);
-
-		switch (wValue) {
-		case (USB_DT_DEVICE << 8):	/* device descriptor */
-			len = min_t(unsigned int,
-				    leni, min_t(unsigned int,
-						sizeof(root_hub_dev_des),
-						wLength));
-			data_buf = root_hub_dev_des;
-			break;
-
-		case (USB_DT_CONFIG << 8):	/* configuration descriptor */
-			len = min_t(unsigned int,
-				    leni, min_t(unsigned int,
-						sizeof(root_hub_config_des),
-						wLength));
-			data_buf = root_hub_config_des;
-			break;
-
-		case ((USB_DT_STRING << 8) | 0x00):	/* string 0 descriptors */
-			len = min_t(unsigned int,
-				    leni, min_t(unsigned int,
-						sizeof(root_hub_str_index0),
-						wLength));
-			data_buf = root_hub_str_index0;
-			break;
-
-		case ((USB_DT_STRING << 8) | 0x01):	/* string 1 descriptors */
-			len = min_t(unsigned int,
-				    leni, min_t(unsigned int,
-						sizeof(root_hub_str_index1),
-						wLength));
-			data_buf = root_hub_str_index1;
-			break;
-
-		default:
-			ERR("invalid wValue");
-			stat = USB_ST_STALLED;
-		}
-
-		break;
-
-	case RH_GET_DESCRIPTOR | RH_CLASS:
-		DBG("RH_GET_DESCRIPTOR | RH_CLASS");
-
-		tmp = isp116x_read_reg32(isp116x, HCRHDESCA);
-
-		data_buf[0] = 0x09;	/* min length; */
-		data_buf[1] = 0x29;
-		data_buf[2] = tmp & RH_A_NDP;
-		data_buf[3] = 0;
-		if (tmp & RH_A_PSM)	/* per-port power switching? */
-			data_buf[3] |= 0x01;
-		if (tmp & RH_A_NOCP)	/* no overcurrent reporting? */
-			data_buf[3] |= 0x10;
-		else if (tmp & RH_A_OCPM)	/* per-port overcurrent rep? */
-			data_buf[3] |= 0x08;
-
-		/* Corresponds to data_buf[4-7] */
-		datab[1] = 0;
-		data_buf[5] = (tmp & RH_A_POTPGT) >> 24;
-
-		tmp = isp116x_read_reg32(isp116x, HCRHDESCB);
-
-		data_buf[7] = tmp & RH_B_DR;
-		if (data_buf[2] < 7)
-			data_buf[8] = 0xff;
-		else {
-			data_buf[0] += 2;
-			data_buf[8] = (tmp & RH_B_DR) >> 8;
-			data_buf[10] = data_buf[9] = 0xff;
-		}
-
-		len = min_t(unsigned int, leni,
-			    min_t(unsigned int, data_buf[0], wLength));
-		break;
-
-	case RH_GET_CONFIGURATION:
-		DBG("RH_GET_CONFIGURATION");
-
-		*(__u8 *) data_buf = 0x01;
-		len = 1;
-		break;
-
-	case RH_SET_CONFIGURATION:
-		DBG("RH_SET_CONFIGURATION");
-
-		isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPSC);
-		len = 0;
-		break;
-
-	default:
-		ERR("*** *** *** unsupported root hub command *** *** ***");
-		stat = USB_ST_STALLED;
-	}
-
-	len = min_t(int, len, leni);
-	if (buffer != data_buf)
-		memcpy(buffer, data_buf, len);
-
-	dev->act_len = len;
-	dev->status = stat;
-	DBG("dev act_len %d, status %d", dev->act_len, dev->status);
-
-	dump_msg(dev, pipe, buffer, transfer_len, "RH(ret)");
-
-	return stat;
-}
-
-/* --- Transfer functions -------------------------------------------------- */
-
-int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-		   int len, int interval)
-{
-	DBG("dev=%p pipe=%#lx buf=%p size=%d int=%d",
-	    dev, pipe, buffer, len, interval);
-
-	return -1;
-}
-
-int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-		       int len, struct devrequest *setup)
-{
-	int devnum = usb_pipedevice(pipe);
-	int epnum = usb_pipeendpoint(pipe);
-	int max = max_transfer_len(dev, pipe);
-	int dir_in = usb_pipein(pipe);
-	int done, ret;
-
-	/* Control message is for the HUB? */
-	if (devnum == rh_devnum)
-		return isp116x_submit_rh_msg(dev, pipe, buffer, len, setup);
-
-	/* Ok, no HUB message so send the message to the device */
-
-	/* Setup phase */
-	DBG("--- SETUP PHASE --------------------------------");
-	usb_settoggle(dev, epnum, 1, 0);
-	ret = isp116x_submit_job(dev, pipe,
-				 PTD_DIR_SETUP,
-				 setup, sizeof(struct devrequest));
-	if (ret < 0) {
-		DBG("control setup phase error (ret = %d", ret);
-		return -1;
-	}
-
-	/* Data phase */
-	DBG("--- DATA PHASE ---------------------------------");
-	done = 0;
-	usb_settoggle(dev, epnum, !dir_in, 1);
-	while (done < len) {
-		ret = isp116x_submit_job(dev, pipe,
-					 dir_in ? PTD_DIR_IN : PTD_DIR_OUT,
-					 (__u8 *) buffer + done,
-					 max > len - done ? len - done : max);
-		if (ret < 0) {
-			DBG("control data phase error (ret = %d)", ret);
-			return -1;
-		}
-		done += ret;
-
-		if (dir_in && ret < max)	/* short packet */
-			break;
-	}
-
-	/* Status phase */
-	DBG("--- STATUS PHASE -------------------------------");
-	usb_settoggle(dev, epnum, !dir_in, 1);
-	ret = isp116x_submit_job(dev, pipe,
-				 !dir_in ? PTD_DIR_IN : PTD_DIR_OUT, NULL, 0);
-	if (ret < 0) {
-		DBG("control status phase error (ret = %d", ret);
-		return -1;
-	}
-
-	dev->act_len = done;
-
-	dump_msg(dev, pipe, buffer, len, "DEV(ret)");
-
-	return done;
-}
-
-int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
-		    int len)
-{
-	int dir_out = usb_pipeout(pipe);
-	int max = max_transfer_len(dev, pipe);
-	int done, ret;
-
-	DBG("--- BULK ---------------------------------------");
-	DBG("dev=%ld pipe=%ld buf=%p size=%d dir_out=%d",
-	    usb_pipedevice(pipe), usb_pipeendpoint(pipe), buffer, len, dir_out);
-
-	done = 0;
-	while (done < len) {
-		ret = isp116x_submit_job(dev, pipe,
-					 !dir_out ? PTD_DIR_IN : PTD_DIR_OUT,
-					 (__u8 *) buffer + done,
-					 max > len - done ? len - done : max);
-		if (ret < 0) {
-			DBG("error on bulk message (ret = %d)", ret);
-			return -1;
-		}
-
-		done += ret;
-
-		if (!dir_out && ret < max)	/* short packet */
-			break;
-	}
-
-	dev->act_len = done;
-
-	return 0;
-}
-
-/* --- Basic functions ----------------------------------------------------- */
-
-static int isp116x_sw_reset(struct isp116x *isp116x)
-{
-	int retries = 15;
-	int ret = 0;
-
-	DBG("");
-
-	isp116x->disabled = 1;
-
-	isp116x_write_reg16(isp116x, HCSWRES, HCSWRES_MAGIC);
-	isp116x_write_reg32(isp116x, HCCMDSTAT, HCCMDSTAT_HCR);
-	while (--retries) {
-		/* It usually resets within 1 ms */
-		mdelay(1);
-		if (!(isp116x_read_reg32(isp116x, HCCMDSTAT) & HCCMDSTAT_HCR))
-			break;
-	}
-	if (!retries) {
-		ERR("software reset timeout");
-		ret = -1;
-	}
-	return ret;
-}
-
-static int isp116x_reset(struct isp116x *isp116x)
-{
-	unsigned long t;
-	u16 clkrdy = 0;
-	int ret, timeout = 15 /* ms */ ;
-
-	DBG("");
-
-	ret = isp116x_sw_reset(isp116x);
-	if (ret)
-		return ret;
-
-	for (t = 0; t < timeout; t++) {
-		clkrdy = isp116x_read_reg16(isp116x, HCuPINT) & HCuPINT_CLKRDY;
-		if (clkrdy)
-			break;
-		mdelay(1);
-	}
-	if (!clkrdy) {
-		ERR("clock not ready after %dms", timeout);
-		/* After sw_reset the clock won't report to be ready, if
-		   H_WAKEUP pin is high. */
-		ERR("please make sure that the H_WAKEUP pin is pulled low!");
-		ret = -1;
-	}
-	return ret;
-}
-
-static void isp116x_stop(struct isp116x *isp116x)
-{
-	u32 val;
-
-	DBG("");
-
-	isp116x_write_reg16(isp116x, HCuPINTENB, 0);
-
-	/* Switch off ports' power, some devices don't come up
-	   after next 'start' without this */
-	val = isp116x_read_reg32(isp116x, HCRHDESCA);
-	val &= ~(RH_A_NPS | RH_A_PSM);
-	isp116x_write_reg32(isp116x, HCRHDESCA, val);
-	isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPS);
-
-	isp116x_sw_reset(isp116x);
-}
-
-/*
- *  Configure the chip. The chip must be successfully reset by now.
- */
-static int isp116x_start(struct isp116x *isp116x)
-{
-	struct isp116x_platform_data *board = isp116x->board;
-	u32 val;
-
-	DBG("");
-
-	/* Clear interrupt status and disable all interrupt sources */
-	isp116x_write_reg16(isp116x, HCuPINT, 0xff);
-	isp116x_write_reg16(isp116x, HCuPINTENB, 0);
-
-	isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE);
-	isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE);
-
-	/* Hardware configuration */
-	val = HCHWCFG_DBWIDTH(1);
-	if (board->sel15Kres)
-		val |= HCHWCFG_15KRSEL;
-	/* Remote wakeup won't work without working clock */
-	if (board->remote_wakeup_enable)
-		val |= HCHWCFG_CLKNOTSTOP;
-	if (board->oc_enable)
-		val |= HCHWCFG_ANALOG_OC;
-	isp116x_write_reg16(isp116x, HCHWCFG, val);
-
-	/* --- Root hub configuration */
-	val = (25 << 24) & RH_A_POTPGT;
-	/* AN10003_1.pdf recommends RH_A_NPS (no power switching) to
-	   be always set. Yet, instead, we request individual port
-	   power switching. */
-	val |= RH_A_PSM;
-	/* Report overcurrent per port */
-	val |= RH_A_OCPM;
-	isp116x_write_reg32(isp116x, HCRHDESCA, val);
-	isp116x->rhdesca = isp116x_read_reg32(isp116x, HCRHDESCA);
-
-	val = RH_B_PPCM;
-	isp116x_write_reg32(isp116x, HCRHDESCB, val);
-	isp116x->rhdescb = isp116x_read_reg32(isp116x, HCRHDESCB);
-
-	val = 0;
-	if (board->remote_wakeup_enable)
-		val |= RH_HS_DRWE;
-	isp116x_write_reg32(isp116x, HCRHSTATUS, val);
-	isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS);
-
-	isp116x_write_reg32(isp116x, HCFMINTVL, 0x27782edf);
-
-	/* Go operational */
-	val = HCCONTROL_USB_OPER;
-	if (board->remote_wakeup_enable)
-		val |= HCCONTROL_RWE;
-	isp116x_write_reg32(isp116x, HCCONTROL, val);
-
-	/* Disable ports to avoid race in device enumeration */
-	isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS);
-	isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS);
-
-	isp116x_show_regs(isp116x);
-
-	isp116x->disabled = 0;
-
-	return 0;
-}
-
-/* --- Init functions ------------------------------------------------------ */
-
-int isp116x_check_id(struct isp116x *isp116x)
-{
-	int val;
-
-	val = isp116x_read_reg16(isp116x, HCCHIPID);
-	if ((val & HCCHIPID_MASK) != HCCHIPID_MAGIC) {
-		ERR("invalid chip ID %04x", val);
-		return -1;
-	}
-
-	return 0;
-}
-
-int usb_lowlevel_init(int index, enum usb_init_type init, void **controller))
-{
-	struct isp116x *isp116x = &isp116x_dev;
-
-	DBG("");
-
-	got_rhsc = rh_devnum = 0;
-
-	/* Init device registers addr */
-	isp116x->addr_reg = (u16 *) ISP116X_HCD_ADDR;
-	isp116x->data_reg = (u16 *) ISP116X_HCD_DATA;
-
-	/* Setup specific board settings */
-#ifdef ISP116X_HCD_SEL15kRES
-	isp116x_board.sel15Kres = 1;
-#endif
-#ifdef ISP116X_HCD_OC_ENABLE
-	isp116x_board.oc_enable = 1;
-#endif
-#ifdef ISP116X_HCD_REMOTE_WAKEUP_ENABLE
-	isp116x_board.remote_wakeup_enable = 1;
-#endif
-	isp116x->board = &isp116x_board;
-
-	/* Try to get ISP116x silicon chip ID */
-	if (isp116x_check_id(isp116x) < 0)
-		return -1;
-
-	isp116x->disabled = 1;
-	isp116x->sleeping = 0;
-
-	isp116x_reset(isp116x);
-	isp116x_start(isp116x);
-
-	return 0;
-}
-
-int usb_lowlevel_stop(int index)
-{
-	struct isp116x *isp116x = &isp116x_dev;
-
-	DBG("");
-
-	if (!isp116x->disabled)
-		isp116x_stop(isp116x);
-
-	return 0;
-}
diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h
deleted file mode 100644
index 5b7afaf..0000000
--- a/drivers/usb/host/isp116x.h
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- * ISP116x register declarations and HCD data structures
- *
- * Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
- * Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it>
- * Copyright (C) 2005 Olav Kongas <ok@artecdesign.ee>
- * Portions:
- * Copyright (C) 2004 Lothar Wassmann
- * Copyright (C) 2004 Psion Teklogix
- * Copyright (C) 2004 David Brownell
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifdef DEBUG
-#define DBG(fmt, args...)	\
-		printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args)
-#else
-#define DBG(fmt, args...)	do {} while (0)
-#endif
-
-#ifdef VERBOSE
-#    define VDBG		DBG
-#else
-#    define VDBG(fmt, args...)	do {} while (0)
-#endif
-
-#define ERR(fmt, args...)	\
-		printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args)
-#define WARN(fmt, args...)	\
-		printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args)
-#define INFO(fmt, args...)	\
-		printf("isp116x: " fmt "\n" , ## args)
-
-/* ------------------------------------------------------------------------- */
-
-/* us of 1ms frame */
-#define  MAX_LOAD_LIMIT		850
-
-/* Full speed: max # of bytes to transfer for a single urb
-   at a time must be < 1024 && must be multiple of 64.
-   832 allows transfering 4kiB within 5 frames. */
-#define MAX_TRANSFER_SIZE_FULLSPEED	832
-
-/* Low speed: there is no reason to schedule in very big
-   chunks; often the requested long transfers are for
-   string descriptors containing short strings. */
-#define MAX_TRANSFER_SIZE_LOWSPEED	64
-
-/* Bytetime (us), a rough indication of how much time it
-   would take to transfer a byte of useful data over USB */
-#define BYTE_TIME_FULLSPEED	1
-#define BYTE_TIME_LOWSPEED	20
-
-/* Buffer sizes */
-#define ISP116x_BUF_SIZE	4096
-#define ISP116x_ITL_BUFSIZE	0
-#define ISP116x_ATL_BUFSIZE	((ISP116x_BUF_SIZE) - 2*(ISP116x_ITL_BUFSIZE))
-
-#define ISP116x_WRITE_OFFSET	0x80
-
-/* --- ISP116x registers/bits ---------------------------------------------- */
-
-#define	HCREVISION	0x00
-#define	HCCONTROL	0x01
-#define		HCCONTROL_HCFS	(3 << 6)	/* host controller
-						   functional state */
-#define		HCCONTROL_USB_RESET	(0 << 6)
-#define		HCCONTROL_USB_RESUME	(1 << 6)
-#define		HCCONTROL_USB_OPER	(2 << 6)
-#define		HCCONTROL_USB_SUSPEND	(3 << 6)
-#define		HCCONTROL_RWC	(1 << 9)	/* remote wakeup connected */
-#define		HCCONTROL_RWE	(1 << 10)	/* remote wakeup enable */
-#define	HCCMDSTAT	0x02
-#define		HCCMDSTAT_HCR	(1 << 0)	/* host controller reset */
-#define		HCCMDSTAT_SOC	(3 << 16)	/* scheduling overrun count */
-#define	HCINTSTAT	0x03
-#define		HCINT_SO	(1 << 0)	/* scheduling overrun */
-#define		HCINT_WDH	(1 << 1)	/* writeback of done_head */
-#define		HCINT_SF	(1 << 2)	/* start frame */
-#define		HCINT_RD	(1 << 3)	/* resume detect */
-#define		HCINT_UE	(1 << 4)	/* unrecoverable error */
-#define		HCINT_FNO	(1 << 5)	/* frame number overflow */
-#define		HCINT_RHSC	(1 << 6)	/* root hub status change */
-#define		HCINT_OC	(1 << 30)	/* ownership change */
-#define		HCINT_MIE	(1 << 31)	/* master interrupt enable */
-#define	HCINTENB	0x04
-#define	HCINTDIS	0x05
-#define	HCFMINTVL	0x0d
-#define	HCFMREM		0x0e
-#define	HCFMNUM		0x0f
-#define	HCLSTHRESH	0x11
-#define	HCRHDESCA	0x12
-#define		RH_A_NDP	(0x3 << 0)	/* # downstream ports */
-#define		RH_A_PSM	(1 << 8)	/* power switching mode */
-#define		RH_A_NPS	(1 << 9)	/* no power switching */
-#define		RH_A_DT		(1 << 10)	/* device type (mbz) */
-#define		RH_A_OCPM	(1 << 11)	/* overcurrent protection
-						   mode */
-#define		RH_A_NOCP	(1 << 12)	/* no overcurrent protection */
-#define		RH_A_POTPGT	(0xff << 24)	/* power on -> power good
-						   time */
-#define	HCRHDESCB	0x13
-#define		RH_B_DR		(0xffff << 0)	/* device removable flags */
-#define		RH_B_PPCM	(0xffff << 16)	/* port power control mask */
-#define	HCRHSTATUS	0x14
-#define		RH_HS_LPS	(1 << 0)	/* local power status */
-#define		RH_HS_OCI	(1 << 1)	/* over current indicator */
-#define		RH_HS_DRWE	(1 << 15)	/* device remote wakeup
-						   enable */
-#define		RH_HS_LPSC	(1 << 16)	/* local power status change */
-#define		RH_HS_OCIC	(1 << 17)	/* over current indicator
-						   change */
-#define		RH_HS_CRWE	(1 << 31)	/* clear remote wakeup
-						   enable */
-#define	HCRHPORT1	0x15
-#define		RH_PS_CCS	(1 << 0)	/* current connect status */
-#define		RH_PS_PES	(1 << 1)	/* port enable status */
-#define		RH_PS_PSS	(1 << 2)	/* port suspend status */
-#define		RH_PS_POCI	(1 << 3)	/* port over current
-						   indicator */
-#define		RH_PS_PRS	(1 << 4)	/* port reset status */
-#define		RH_PS_PPS	(1 << 8)	/* port power status */
-#define		RH_PS_LSDA	(1 << 9)	/* low speed device attached */
-#define		RH_PS_CSC	(1 << 16)	/* connect status change */
-#define		RH_PS_PESC	(1 << 17)	/* port enable status change */
-#define		RH_PS_PSSC	(1 << 18)	/* port suspend status
-						   change */
-#define		RH_PS_OCIC	(1 << 19)	/* over current indicator
-						   change */
-#define		RH_PS_PRSC	(1 << 20)	/* port reset status change */
-#define		HCRHPORT_CLRMASK	(0x1f << 16)
-#define	HCRHPORT2	0x16
-#define	HCHWCFG		0x20
-#define		HCHWCFG_15KRSEL		(1 << 12)
-#define		HCHWCFG_CLKNOTSTOP	(1 << 11)
-#define		HCHWCFG_ANALOG_OC	(1 << 10)
-#define		HCHWCFG_DACK_MODE	(1 << 8)
-#define		HCHWCFG_EOT_POL		(1 << 7)
-#define		HCHWCFG_DACK_POL	(1 << 6)
-#define		HCHWCFG_DREQ_POL	(1 << 5)
-#define		HCHWCFG_DBWIDTH_MASK	(0x03 << 3)
-#define		HCHWCFG_DBWIDTH(n)	(((n) << 3) & HCHWCFG_DBWIDTH_MASK)
-#define		HCHWCFG_INT_POL		(1 << 2)
-#define		HCHWCFG_INT_TRIGGER	(1 << 1)
-#define		HCHWCFG_INT_ENABLE	(1 << 0)
-#define	HCDMACFG	0x21
-#define		HCDMACFG_BURST_LEN_MASK	(0x03 << 5)
-#define		HCDMACFG_BURST_LEN(n)	(((n) << 5) & HCDMACFG_BURST_LEN_MASK)
-#define		HCDMACFG_BURST_LEN_1	HCDMACFG_BURST_LEN(0)
-#define		HCDMACFG_BURST_LEN_4	HCDMACFG_BURST_LEN(1)
-#define		HCDMACFG_BURST_LEN_8	HCDMACFG_BURST_LEN(2)
-#define		HCDMACFG_DMA_ENABLE	(1 << 4)
-#define		HCDMACFG_BUF_TYPE_MASK	(0x07 << 1)
-#define		HCDMACFG_CTR_SEL	(1 << 2)
-#define		HCDMACFG_ITLATL_SEL	(1 << 1)
-#define		HCDMACFG_DMA_RW_SELECT	(1 << 0)
-#define	HCXFERCTR	0x22
-#define	HCuPINT		0x24
-#define		HCuPINT_SOF		(1 << 0)
-#define		HCuPINT_ATL		(1 << 1)
-#define		HCuPINT_AIIEOT		(1 << 2)
-#define		HCuPINT_OPR		(1 << 4)
-#define		HCuPINT_SUSP		(1 << 5)
-#define		HCuPINT_CLKRDY		(1 << 6)
-#define	HCuPINTENB	0x25
-#define	HCCHIPID	0x27
-#define		HCCHIPID_MASK		0xff00
-#define		HCCHIPID_MAGIC		0x6100
-#define	HCSCRATCH	0x28
-#define	HCSWRES		0x29
-#define		HCSWRES_MAGIC		0x00f6
-#define	HCITLBUFLEN	0x2a
-#define	HCATLBUFLEN	0x2b
-#define	HCBUFSTAT	0x2c
-#define		HCBUFSTAT_ITL0_FULL	(1 << 0)
-#define		HCBUFSTAT_ITL1_FULL	(1 << 1)
-#define		HCBUFSTAT_ATL_FULL	(1 << 2)
-#define		HCBUFSTAT_ITL0_DONE	(1 << 3)
-#define		HCBUFSTAT_ITL1_DONE	(1 << 4)
-#define		HCBUFSTAT_ATL_DONE	(1 << 5)
-#define	HCRDITL0LEN	0x2d
-#define	HCRDITL1LEN	0x2e
-#define	HCITLPORT	0x40
-#define	HCATLPORT	0x41
-
-/* PTD accessor macros. */
-#define PTD_GET_COUNT(p)	(((p)->count & PTD_COUNT_MSK) >> 0)
-#define PTD_COUNT(v)		(((v) << 0) & PTD_COUNT_MSK)
-#define PTD_GET_TOGGLE(p)	(((p)->count & PTD_TOGGLE_MSK) >> 10)
-#define PTD_TOGGLE(v)		(((v) << 10) & PTD_TOGGLE_MSK)
-#define PTD_GET_ACTIVE(p)	(((p)->count & PTD_ACTIVE_MSK) >> 11)
-#define PTD_ACTIVE(v)		(((v) << 11) & PTD_ACTIVE_MSK)
-#define PTD_GET_CC(p)		(((p)->count & PTD_CC_MSK) >> 12)
-#define PTD_CC(v)		(((v) << 12) & PTD_CC_MSK)
-#define PTD_GET_MPS(p)		(((p)->mps & PTD_MPS_MSK) >> 0)
-#define PTD_MPS(v)		(((v) << 0) & PTD_MPS_MSK)
-#define PTD_GET_SPD(p)		(((p)->mps & PTD_SPD_MSK) >> 10)
-#define PTD_SPD(v)		(((v) << 10) & PTD_SPD_MSK)
-#define PTD_GET_LAST(p)		(((p)->mps & PTD_LAST_MSK) >> 11)
-#define PTD_LAST(v)		(((v) << 11) & PTD_LAST_MSK)
-#define PTD_GET_EP(p)		(((p)->mps & PTD_EP_MSK) >> 12)
-#define PTD_EP(v)		(((v) << 12) & PTD_EP_MSK)
-#define PTD_GET_LEN(p)		(((p)->len & PTD_LEN_MSK) >> 0)
-#define PTD_LEN(v)		(((v) << 0) & PTD_LEN_MSK)
-#define PTD_GET_DIR(p)		(((p)->len & PTD_DIR_MSK) >> 10)
-#define PTD_DIR(v)		(((v) << 10) & PTD_DIR_MSK)
-#define PTD_GET_B5_5(p)		(((p)->len & PTD_B5_5_MSK) >> 13)
-#define PTD_B5_5(v)		(((v) << 13) & PTD_B5_5_MSK)
-#define PTD_GET_FA(p)		(((p)->faddr & PTD_FA_MSK) >> 0)
-#define PTD_FA(v)		(((v) << 0) & PTD_FA_MSK)
-#define PTD_GET_FMT(p)		(((p)->faddr & PTD_FMT_MSK) >> 7)
-#define PTD_FMT(v)		(((v) << 7) & PTD_FMT_MSK)
-
-/*  Hardware transfer status codes -- CC from ptd->count */
-#define TD_CC_NOERROR      0x00
-#define TD_CC_CRC          0x01
-#define TD_CC_BITSTUFFING  0x02
-#define TD_CC_DATATOGGLEM  0x03
-#define TD_CC_STALL        0x04
-#define TD_DEVNOTRESP      0x05
-#define TD_PIDCHECKFAIL    0x06
-#define TD_UNEXPECTEDPID   0x07
-#define TD_DATAOVERRUN     0x08
-#define TD_DATAUNDERRUN    0x09
-    /* 0x0A, 0x0B reserved for hardware */
-#define TD_BUFFEROVERRUN   0x0C
-#define TD_BUFFERUNDERRUN  0x0D
-    /* 0x0E, 0x0F reserved for HCD */
-#define TD_NOTACCESSED     0x0F
-
-/* ------------------------------------------------------------------------- */
-
-#define	LOG2_PERIODIC_SIZE	5	/* arbitrary; this matches OHCI */
-#define	PERIODIC_SIZE		(1 << LOG2_PERIODIC_SIZE)
-
-/* Philips transfer descriptor */
-struct ptd {
-	u16 count;
-#define	PTD_COUNT_MSK	(0x3ff << 0)
-#define	PTD_TOGGLE_MSK	(1 << 10)
-#define	PTD_ACTIVE_MSK	(1 << 11)
-#define	PTD_CC_MSK	(0xf << 12)
-	u16 mps;
-#define	PTD_MPS_MSK	(0x3ff << 0)
-#define	PTD_SPD_MSK	(1 << 10)
-#define	PTD_LAST_MSK	(1 << 11)
-#define	PTD_EP_MSK	(0xf << 12)
-	u16 len;
-#define	PTD_LEN_MSK	(0x3ff << 0)
-#define	PTD_DIR_MSK	(3 << 10)
-#define	PTD_DIR_SETUP	(0)
-#define	PTD_DIR_OUT	(1)
-#define	PTD_DIR_IN	(2)
-#define	PTD_B5_5_MSK	(1 << 13)
-	u16 faddr;
-#define	PTD_FA_MSK	(0x7f << 0)
-#define	PTD_FMT_MSK	(1 << 7)
-} __attribute__ ((packed, aligned(2)));
-
-struct isp116x_ep {
-	struct usb_device *udev;
-	struct ptd ptd;
-
-	u8 maxpacket;
-	u8 epnum;
-	u8 nextpid;
-
-	u16 length;		/* of current packet */
-	unsigned char *data;	/* to databuf */
-
-	u16 error_count;
-};
-
-/* URB struct */
-#define N_URB_TD		48
-#define URB_DEL			1
-typedef struct {
-	struct isp116x_ep *ed;
-	void *transfer_buffer;	/* (in) associated data buffer */
-	int actual_length;	/* (return) actual transfer length */
-	unsigned long pipe;	/* (in) pipe information */
-#if 0
-	int state;
-#endif
-} urb_priv_t;
-
-struct isp116x_platform_data {
-	/* Enable internal resistors on downstream ports */
-	unsigned sel15Kres:1;
-	/* On-chip overcurrent detection */
-	unsigned oc_enable:1;
-	/* Enable wakeup by devices on usb bus (e.g. wakeup
-	   by attachment/detachment or by device activity
-	   such as moving a mouse). When chosen, this option
-	   prevents stopping internal clock, increasing
-	   thereby power consumption in suspended state. */
-	unsigned remote_wakeup_enable:1;
-};
-
-struct isp116x {
-	u16 *addr_reg;
-	u16 *data_reg;
-
-	struct isp116x_platform_data *board;
-
-	struct dentry *dentry;
-	unsigned long stat1, stat2, stat4, stat8, stat16;
-
-	/* Status flags */
-	unsigned disabled:1;
-	unsigned sleeping:1;
-
-	/* Root hub registers */
-	u32 rhdesca;
-	u32 rhdescb;
-	u32 rhstatus;
-	u32 rhport[2];
-
-	/* Schedule for the current frame */
-	struct isp116x_ep *atl_active;
-	int atl_buflen;
-	int atl_bufshrt;
-	int atl_last_dir;
-	int atl_finishing;
-};
-
-/* ------------------------------------------------- */
-
-/* Inter-io delay (ns). The chip is picky about access timings; it
- * expects at least:
- * 150ns delay between consecutive accesses to DATA_REG,
- * 300ns delay between access to ADDR_REG and DATA_REG
- * OE, WE MUST NOT be changed during these intervals
- */
-#if defined(UDELAY)
-#define	isp116x_delay(h,d)	udelay(d)
-#else
-#define	isp116x_delay(h,d)	do {} while (0)
-#endif
-
-static inline void isp116x_write_addr(struct isp116x *isp116x, unsigned reg)
-{
-	writew(reg & 0xff, isp116x->addr_reg);
-	isp116x_delay(isp116x, UDELAY);
-}
-
-static inline void isp116x_write_data16(struct isp116x *isp116x, u16 val)
-{
-	writew(val, isp116x->data_reg);
-	isp116x_delay(isp116x, UDELAY);
-}
-
-static inline void isp116x_raw_write_data16(struct isp116x *isp116x, u16 val)
-{
-	__raw_writew(val, isp116x->data_reg);
-	isp116x_delay(isp116x, UDELAY);
-}
-
-static inline u16 isp116x_read_data16(struct isp116x *isp116x)
-{
-	u16 val;
-
-	val = readw(isp116x->data_reg);
-	isp116x_delay(isp116x, UDELAY);
-	return val;
-}
-
-static inline u16 isp116x_raw_read_data16(struct isp116x *isp116x)
-{
-	u16 val;
-
-	val = __raw_readw(isp116x->data_reg);
-	isp116x_delay(isp116x, UDELAY);
-	return val;
-}
-
-static inline void isp116x_write_data32(struct isp116x *isp116x, u32 val)
-{
-	writew(val & 0xffff, isp116x->data_reg);
-	isp116x_delay(isp116x, UDELAY);
-	writew(val >> 16, isp116x->data_reg);
-	isp116x_delay(isp116x, UDELAY);
-}
-
-static inline u32 isp116x_read_data32(struct isp116x *isp116x)
-{
-	u32 val;
-
-	val = (u32) readw(isp116x->data_reg);
-	isp116x_delay(isp116x, UDELAY);
-	val |= ((u32) readw(isp116x->data_reg)) << 16;
-	isp116x_delay(isp116x, UDELAY);
-	return val;
-}
-
-/* Let's keep register access functions out of line. Hint:
-   we wait at least 150 ns at every access.
-*/
-static u16 isp116x_read_reg16(struct isp116x *isp116x, unsigned reg)
-{
-	isp116x_write_addr(isp116x, reg);
-	return isp116x_read_data16(isp116x);
-}
-
-static u32 isp116x_read_reg32(struct isp116x *isp116x, unsigned reg)
-{
-	isp116x_write_addr(isp116x, reg);
-	return isp116x_read_data32(isp116x);
-}
-
-static void isp116x_write_reg16(struct isp116x *isp116x, unsigned reg,
-				unsigned val)
-{
-	isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET);
-	isp116x_write_data16(isp116x, (u16) (val & 0xffff));
-}
-
-static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg,
-				unsigned val)
-{
-	isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET);
-	isp116x_write_data32(isp116x, (u32) val);
-}
-
-/* --- USB HUB constants (not OHCI-specific; see hub.h) -------------------- */
-
-/* destination of request */
-#define RH_INTERFACE               0x01
-#define RH_ENDPOINT                0x02
-#define RH_OTHER                   0x03
-
-#define RH_CLASS                   0x20
-#define RH_VENDOR                  0x40
-
-/* Requests: bRequest << 8 | bmRequestType */
-#define RH_GET_STATUS           0x0080
-#define RH_CLEAR_FEATURE        0x0100
-#define RH_SET_FEATURE          0x0300
-#define RH_SET_ADDRESS          0x0500
-#define RH_GET_DESCRIPTOR       0x0680
-#define RH_SET_DESCRIPTOR       0x0700
-#define RH_GET_CONFIGURATION    0x0880
-#define RH_SET_CONFIGURATION    0x0900
-#define RH_GET_STATE            0x0280
-#define RH_GET_INTERFACE        0x0A80
-#define RH_SET_INTERFACE        0x0B00
-#define RH_SYNC_FRAME           0x0C80
-/* Our Vendor Specific Request */
-#define RH_SET_EP               0x2000
-
-/* Hub port features */
-#define RH_PORT_CONNECTION         0x00
-#define RH_PORT_ENABLE             0x01
-#define RH_PORT_SUSPEND            0x02
-#define RH_PORT_OVER_CURRENT       0x03
-#define RH_PORT_RESET              0x04
-#define RH_PORT_POWER              0x08
-#define RH_PORT_LOW_SPEED          0x09
-
-#define RH_C_PORT_CONNECTION       0x10
-#define RH_C_PORT_ENABLE           0x11
-#define RH_C_PORT_SUSPEND          0x12
-#define RH_C_PORT_OVER_CURRENT     0x13
-#define RH_C_PORT_RESET            0x14
-
-/* Hub features */
-#define RH_C_HUB_LOCAL_POWER       0x00
-#define RH_C_HUB_OVER_CURRENT      0x01
-
-#define RH_DEVICE_REMOTE_WAKEUP    0x00
-#define RH_ENDPOINT_STALL          0x01
-
-#define RH_ACK                     0x01
-#define RH_REQ_ERR                 -1
-#define RH_NACK                    0x00
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index e0ca2cb..9dbb183 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -20,7 +20,6 @@
 #define R8A66597_DPRINT(...)
 #endif
 
-static const char hcd_name[] = "r8a66597_hcd";
 static struct r8a66597 gr8a66597;
 
 static void get_hub_data(struct usb_device *dev, u16 *hub_devnum, u16 *hubport)
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index a59ff5a..b1b4498 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -9,6 +9,7 @@
 #include "btrfs.h"
 #include <linux/lzo.h>
 #include <u-boot/zlib.h>
+#include <asm/unaligned.h>
 
 static u32 decompress_lzo(const u8 *cbuf, u32 clen, u8 *dbuf, u32 dlen)
 {
@@ -19,7 +20,7 @@
 	if (clen < 4)
 		return -1;
 
-	tot_len = le32_to_cpu(*(u32 *) cbuf);
+	tot_len = le32_to_cpu(get_unaligned((u32 *)cbuf));
 	cbuf += 4;
 	clen -= 4;
 	tot_len -= 4;
@@ -32,7 +33,7 @@
 	res = 0;
 
 	while (tot_len > 4) {
-		in_len = le32_to_cpu(*(u32 *) cbuf);
+		in_len = le32_to_cpu(get_unaligned((u32 *)cbuf));
 		cbuf += 4;
 		clen -= 4;
 
diff --git a/fs/btrfs/hash.c b/fs/btrfs/hash.c
index f8a50e5..cde3abd 100644
--- a/fs/btrfs/hash.c
+++ b/fs/btrfs/hash.c
@@ -8,6 +8,7 @@
 
 #include "btrfs.h"
 #include <u-boot/crc.h>
+#include <asm/unaligned.h>
 
 static u32 btrfs_crc32c_table[256];
 
@@ -34,5 +35,5 @@
 
 void btrfs_csum_final(u32 crc, void *result)
 {
-	*((u32 *) result) = cpu_to_le32(~crc);
+	put_unaligned(cpu_to_le32(~crc), (u32 *)result);
 }
diff --git a/include/asm-generic/atomic-long.h b/include/asm-generic/atomic-long.h
index d0469ef..32f288b 100644
--- a/include/asm-generic/atomic-long.h
+++ b/include/asm-generic/atomic-long.h
@@ -66,6 +66,7 @@
 	atomic64_sub(i, v);
 }
 
+#ifndef __UBOOT__
 static inline int atomic_long_sub_and_test(long i, atomic_long_t *l)
 {
 	atomic64_t *v = (atomic64_t *)l;
@@ -135,6 +136,7 @@
 	(atomic64_cmpxchg((atomic64_t *)(l), (old), (new)))
 #define atomic_long_xchg(v, new) \
 	(atomic64_xchg((atomic64_t *)(v), (new)))
+#endif  /*  __UBOOT__ */
 
 #else  /*  BITS_PER_LONG == 64  */
 
diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h
index 5c469a2..f567ceb 100644
--- a/include/config_distro_bootcmd.h
+++ b/include/config_distro_bootcmd.h
@@ -71,10 +71,15 @@
 #ifdef CONFIG_CMD_UBIFS
 #define BOOTENV_SHARED_UBIFS \
 	"ubifs_boot=" \
-		"if ubi part UBI && ubifsmount ubi${devnum}:boot; then "  \
-			"setenv devtype ubi; "                            \
-			"setenv bootpart 0; "                             \
-			"run scan_dev_for_boot; "                         \
+		"env exists bootubipart || " \
+			"env set bootubipart UBI; " \
+		"env exists bootubivol || " \
+			"env set bootubivol boot; " \
+		"if ubi part ${bootubipart} && " \
+			"ubifsmount ubi${devnum}:${bootubivol}; " \
+		"then " \
+			"setenv devtype ubi; " \
+			"run scan_dev_for_boot; " \
 		"fi\0"
 #define BOOTENV_DEV_UBIFS	BOOTENV_DEV_BLKDEV
 #define BOOTENV_DEV_NAME_UBIFS	BOOTENV_DEV_NAME_BLKDEV
@@ -125,7 +130,7 @@
 			"${kernel_addr_r} efi/boot/"BOOTEFI_NAME"; "      \
 		"if fdt addr ${fdt_addr_r}; then "                        \
 			"bootefi ${kernel_addr_r} ${fdt_addr_r};"         \
-		"else "                                                    \
+		"else "                                                   \
 			"bootefi ${kernel_addr_r} ${fdtcontroladdr};"     \
 		"fi\0"                                                    \
 	\
diff --git a/include/configs/am43xx_evm.h b/include/configs/am43xx_evm.h
index 77f8e76..726dbba 100644
--- a/include/configs/am43xx_evm.h
+++ b/include/configs/am43xx_evm.h
@@ -115,9 +115,6 @@
 #endif
 
 #ifdef CONFIG_QSPI_BOOT
-#ifndef CONFIG_SYS_TEXT_BASE
-#define CONFIG_SYS_TEXT_BASE		CONFIG_ISW_ENTRY_ADDR
-#endif
 #define CONFIG_SYS_REDUNDAND_ENVIRONMENT
 #define CONFIG_ENV_SPI_MAX_HZ           CONFIG_SF_DEFAULT_SPEED
 #define CONFIG_ENV_SECT_SIZE           (64 << 10) /* 64 KB sectors */
diff --git a/include/configs/edb93xx.h b/include/configs/edb93xx.h
index 8fcc791..fcad7c4 100644
--- a/include/configs/edb93xx.h
+++ b/include/configs/edb93xx.h
@@ -80,7 +80,6 @@
 #define CONFIG_SYS_CBSIZE		1024	/* Console I/O buffer size */
 
 /* Serial port hardware configuration */
-#define CONFIG_PL010_SERIAL
 #define CONFIG_CONS_INDEX		0
 #define CONFIG_SYS_BAUDRATE_TABLE	{9600, 19200, 38400, 57600, \
                         115200, 230400}
diff --git a/include/configs/highbank.h b/include/configs/highbank.h
index a5a5240..726ae8a 100644
--- a/include/configs/highbank.h
+++ b/include/configs/highbank.h
@@ -22,7 +22,6 @@
  */
 #define CONFIG_SYS_MALLOC_LEN		(512 * 1024)
 
-#define CONFIG_PL011_SERIAL
 #define CONFIG_PL011_CLOCK		150000000
 #define CONFIG_PL01x_PORTS		{ (void *)(0xFFF36000) }
 #define CONFIG_CONS_INDEX		0
diff --git a/include/configs/hikey.h b/include/configs/hikey.h
index 130c769..8679b6b 100644
--- a/include/configs/hikey.h
+++ b/include/configs/hikey.h
@@ -50,9 +50,6 @@
 /* Size of malloc() pool */
 #define CONFIG_SYS_MALLOC_LEN		(CONFIG_ENV_SIZE + SZ_8M)
 
-/* Serial port PL010/PL011 through the device model */
-#define CONFIG_PL01X_SERIAL
-
 #ifdef CONFIG_CMD_USB
 #define CONFIG_USB_DWC2_REG_ADDR 0xF72C0000
 /*#define CONFIG_DWC2_DFLT_SPEED_FULL*/
diff --git a/include/configs/integrator-common.h b/include/configs/integrator-common.h
index edc798b..f66d954 100644
--- a/include/configs/integrator-common.h
+++ b/include/configs/integrator-common.h
@@ -15,8 +15,6 @@
 #define CONFIG_SYS_LONGHELP
 #define CONFIG_SYS_MALLOC_LEN		(CONFIG_ENV_SIZE + 128*1024) /* Size of malloc() pool */
 
-/* Serial port PL010/PL011 through the device model */
-#define CONFIG_PL01X_SERIAL
 #define CONFIG_CONS_INDEX		0
 
 #define CONFIG_CMDLINE_TAG		/* enable passing of ATAGs  */
diff --git a/include/configs/mxs.h b/include/configs/mxs.h
index 804b9e1..3a27c15 100644
--- a/include/configs/mxs.h
+++ b/include/configs/mxs.h
@@ -108,7 +108,6 @@
  * DUART Serial Driver.
  * Conflicts with AUART driver which can be set by board.
  */
-#define CONFIG_PL011_SERIAL
 #define CONFIG_PL011_CLOCK		24000000
 #define CONFIG_PL01x_PORTS		{ (void *)MXS_UARTDBG_BASE }
 #define CONFIG_CONS_INDEX		0
diff --git a/include/configs/omap3_evm.h b/include/configs/omap3_evm.h
index ba67e33..71d49e3 100644
--- a/include/configs/omap3_evm.h
+++ b/include/configs/omap3_evm.h
@@ -86,43 +86,24 @@
 #define MEM_LAYOUT_ENV_SETTINGS \
 	DEFAULT_LINUX_BOOT_ENV
 
-#if defined(CONFIG_NAND) && defined(CONFIG_CMD_UBI)
-/* NAND boot with uImage from NAND 'kernel' partition */
 #define BOOTENV_DEV_NAND(devtypeu, devtypel, instance) \
 	"bootcmd_" #devtypel #instance "=" \
 	"run nandboot\0"
 #define BOOTENV_DEV_NAME_NAND(devtypeu, devtypel, instance) \
 	#devtypel #instance " "
 
-/* NAND boot with zImage from UBIFS '/boot/zImage' */
-#define BOOTENV_DEV_UBIFS_NAND(devtypeu, devtypel, instance) \
+#define BOOTENV_DEV_LEGACY_MMC(devtypeu, devtypel, instance) \
 	"bootcmd_" #devtypel #instance "=" \
-	"run nandbootubifs\0"
-#define BOOTENV_DEV_NAME_UBIFS_NAND(devtypeu, devtypel, instance) \
+	"setenv mmcdev " #instance "; " \
+	"setenv bootpart " #instance ":${mmcpart} ; " \
+	"run mmcboot\0"
+#define BOOTENV_DEV_NAME_LEGACY_MMC(devtypeu, devtypel, instance) \
 	#devtypel #instance " "
-#endif /* CONFIG_NAND && CONFIG_CMD_UBI */
-
-/* MMC boot with uImage from MMC 0:2 '/boot/uImage' */
-#define BOOTENV_DEV_UIMAGE_MMC(devtypeu, devtypel, instance) \
-	"bootcmd_" #devtypel #instance "=" \
-		"setenv mmcdev " #instance"; " \
-		"run mmcboot\0"
-#define BOOTENV_DEV_NAME_UIMAGE_MMC(devtypeu, devtypel, instance) \
-	#devtypel #instance " "
-
-/* MMC boot with zImage from MMC 0:2 '/boot/zImage' */
-#define BOOTENV_DEV_ZIMAGE_MMC(devtypeu, devtypel, instance) \
-	"bootcmd_" #devtypel #instance "=" \
-		"setenv mmcdev " #instance"; " \
-		"run mmcbootz\0"
-#define BOOTENV_DEV_NAME_ZIMAGE_MMC(devtypeu, devtypel, instance) \
-	#devtypel #instance " "
 
 #define BOOT_TARGET_DEVICES(func) \
 	func(MMC, mmc, 0) \
-	func(ZIMAGE_MMC, zimage_mmc, 0) \
-	func(UIMAGE_MMC, uimage_mmc, 0) \
-	func(UBIFS_NAND, ubifs_nand, 0) \
+	func(LEGACY_MMC, legacy_mmc, 0) \
+	func(UBIFS, ubifs, 0) \
 	func(NAND, nand, 0)
 
 #include <config_distro_bootcmd.h>
@@ -135,9 +116,13 @@
 	"fdt_high=0xffffffff\0" \
 	"bootdir=/boot\0" \
 	"bootenv=uEnv.txt\0" \
+	"bootfile=zImage\0" \
+	"bootubivol=rootfs\0" \
+	"bootubipart=rootfs\0" \
 	"optargs=\0" \
 	"mmcdev=0\0" \
 	"mmcpart=2\0" \
+	"bootpart=${mmcdev}:${mmcpart}\0" \
 	"console=ttyO0,115200n8\0" \
 	"mmcargs=setenv bootargs console=${console} " \
 		"${mtdparts} " \
@@ -150,7 +135,7 @@
 		"root=ubi0:rootfs rw ubi.mtd=rootfs noinitrd " \
 		"rootfstype=ubifs rootwait\0" \
 	"loadbootenv=fatload mmc ${mmcdev} ${loadaddr} ${bootenv}\0" \
-	"ext4bootenv=ext4load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${bootdir}/${bootenv}\0" \
+	"ext4bootenv=ext4load mmc ${bootpart} ${loadaddr} ${bootdir}/${bootenv}\0" \
 	"importbootenv=echo Importing environment from mmc ...; " \
 		"env import -t ${loadaddr} ${filesize}\0" \
 	"mmcbootenv=mmc dev ${mmcdev}; " \
@@ -162,39 +147,24 @@
 				"run uenvcmd; " \
 			"fi; " \
 		"fi\0" \
-	"loaduimage=setenv bootfile uImage; " \
-		"ext4load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${bootdir}/${bootfile}\0" \
-	"loadzimage=setenv bootfile zImage; " \
-		"ext4load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${bootdir}/${bootfile}\0" \
-	"loaddtb=ext4load mmc ${mmcdev}:${mmcpart} ${fdtaddr} ${bootdir}/${fdtfile}\0" \
-	"loadubizimage=setenv bootfile zImage; " \
-		"ubifsload ${loadaddr} ${bootdir}/${bootfile}\0" \
-	"loadubidtb=ubifsload ${fdtaddr} ${bootdir}/${fdtfile}\0" \
+	"loadimage=ext4load mmc ${bootpart} ${loadaddr} ${bootdir}/${bootfile}\0" \
+	"loaddtb=ext4load mmc ${bootpart} ${fdtaddr} ${bootdir}/${fdtfile}\0" \
 	"mmcboot=run mmcbootenv; " \
-		"if run loaduimage && run loaddtb; then " \
-			"echo Booting ${bootdir}/${bootfile} from mmc ${mmcdev}:${mmcpart} ...; " \
+		"if run loadimage && run loaddtb; then " \
+			"echo Booting ${bootdir}/${bootfile} from mmc ${bootpart} ...; " \
 			"run mmcargs; " \
-			"bootm ${loadaddr} - ${fdtaddr}; " \
-		"fi\0" \
-	"mmcbootz=run mmcbootenv; " \
-		"if run loadzimage && run loaddtb; then " \
-			"echo Booting ${bootdir}/${bootfile} from mmc ${mmcdev}:${mmcpart} ...; " \
-			"run mmcargs; " \
-			"bootz ${loadaddr} - ${fdtaddr}; " \
+			"if test ${bootfile} = uImage; then " \
+				"bootm ${loadaddr} - ${fdtaddr}; " \
+			"fi; " \
+			"if test ${bootfile} = zImage; then " \
+				"bootz ${loadaddr} - ${fdtaddr}; " \
+			"fi; " \
 		"fi\0" \
 	"nandboot=" \
-		"nand read ${loadaddr} kernel; " \
-		"nand read ${fdtaddr} dtb; " \
-		"echo Booting uImage from NAND MTD 'kernel' partition ...; " \
-		"run nandargs; " \
-		"bootm ${loadaddr} - ${fdtaddr}\0" \
-	"nandbootubifs=" \
-		"ubi part rootfs; " \
-		"ubifsmount ubi0:rootfs; " \
-		"if run loadubizimage && run loadubidtb; then " \
-			"echo Booting ${bootdir}/${bootfile} from NAND ubi0:rootfs ...; " \
+		"if nand read ${loadaddr} kernel && nand read ${fdtaddr} dtb; then " \
+			"echo Booting uImage from NAND MTD 'kernel' partition ...; " \
 			"run nandargs; " \
-			"bootz ${loadaddr} - ${fdtaddr}; " \
+			"bootm ${loadaddr} - ${fdtaddr}; " \
 		"fi\0" \
 	BOOTENV
 
diff --git a/include/configs/pdu001.h b/include/configs/pdu001.h
new file mode 100644
index 0000000..6fccae5
--- /dev/null
+++ b/include/configs/pdu001.h
@@ -0,0 +1,87 @@
+/*
+ * pdu001.h
+ *
+ * Copyright (C) 2018 EETS GmbH - http://www.eets.ch/
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __CONFIG_PDU001_H
+#define __CONFIG_PDU001_H
+
+#include <configs/ti_am335x_common.h>
+
+/* No more need for I2C legacy compatibility for this board.
+ * CONFIG_DM_I2C_COMPAT is defined in ti_armv7_common.h. See the comment there
+ * for the right moment to delete the following line.
+ */
+#undef CONFIG_DM_I2C_COMPAT
+
+/* Using 32K of volatile storage for environment */
+#define CONFIG_ENV_SIZE		0x4000
+
+#define MACH_TYPE_PDU001	5075
+#define CONFIG_MACH_TYPE	MACH_TYPE_PDU001
+#define CONFIG_BOARD_LATE_INIT
+
+/* Clock Defines */
+#define V_OSCK			24000000  /* Clock output from T2 */
+#define V_SCLK			(V_OSCK)
+
+#if CONFIG_CONS_INDEX == 1
+	#define CONSOLE_DEV "ttyO0"
+#elif CONFIG_CONS_INDEX == 2
+	#define CONSOLE_DEV "ttyO1"
+#elif CONFIG_CONS_INDEX == 3
+	#define CONSOLE_DEV "ttyO2"
+#elif CONFIG_CONS_INDEX == 4
+	#define CONSOLE_DEV "ttyO3"
+#elif CONFIG_CONS_INDEX == 5
+	#define CONSOLE_DEV "ttyO4"
+#elif CONFIG_CONS_INDEX == 6
+	#define CONSOLE_DEV "ttyO5"
+#endif
+
+#define CONFIG_BOOTCOMMAND \
+	"run eval_boot_device;" \
+	"setenv bootargs console=${console} " \
+	"vt.global_cursor_default=0 " \
+	"root=/dev/mmcblk${mmc_boot}p${root_fs_partition} " \
+	"rootfstype=ext4 " \
+	"rootwait " \
+	"rootdelay=1;" \
+	"fatload mmc ${mmc_boot} ${fdtaddr} ${fdtfile};" \
+	"fatload mmc ${mmc_boot} ${loadaddr} ${bootfile};" \
+	"bootz ${loadaddr} - ${fdtaddr}"
+
+#ifndef CONFIG_SPL_BUILD
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	DEFAULT_LINUX_BOOT_ENV \
+	"fdtfile=am335x-pdu001.dtb\0" \
+	"bootfile=zImage\0" \
+	"console=" CONSOLE_DEV ",115200n8\0" \
+	"root_fs_partition=2\0" \
+	"eval_boot_device=" \
+		"if test $boot_device = emmc; then " \
+			"setenv mmc_boot 0;" \
+		"elif test $boot_device = sdcard; then " \
+			"setenv mmc_boot 1;" \
+		"else " \
+			"echo Bootdevice is neither MMC0 nor MMC1;" \
+			"reset;" \
+		"fi;" \
+	"\0"
+#endif
+
+/* NS16550 Configuration */
+#define CONFIG_SYS_NS16550_COM1	UART0_BASE
+#define CONFIG_SYS_NS16550_COM2	UART1_BASE
+#define CONFIG_SYS_NS16550_COM3	UART2_BASE
+#define CONFIG_SYS_NS16550_COM4	UART3_BASE
+#define CONFIG_SYS_NS16550_COM5	UART4_BASE
+#define CONFIG_SYS_NS16550_COM6	UART5_BASE
+#define CONFIG_BAUDRATE		115200
+
+#endif	/* ! __CONFIG_PDU001_H */
diff --git a/include/configs/poplar.h b/include/configs/poplar.h
index acdce29..859da38 100644
--- a/include/configs/poplar.h
+++ b/include/configs/poplar.h
@@ -26,9 +26,6 @@
 /* ATF bl33.bin load address (must match) */
 #define CONFIG_SYS_TEXT_BASE			0x37000000
 
-/* PL010/PL011 */
-#define CONFIG_PL01X_SERIAL
-
 /* USB configuration */
 #define CONFIG_USB_MAX_CONTROLLER_COUNT		2
 
diff --git a/include/configs/qemu-arm.h b/include/configs/qemu-arm.h
index c8852ce..c8ba78d 100644
--- a/include/configs/qemu-arm.h
+++ b/include/configs/qemu-arm.h
@@ -20,9 +20,6 @@
 #define CONFIG_SYS_LOAD_ADDR		(CONFIG_SYS_SDRAM_BASE + SZ_2M)
 #define CONFIG_SYS_MALLOC_LEN		SZ_16M
 
-/* QEMU's PL011 serial port is detected via FDT using the device model */
-#define CONFIG_PL01X_SERIAL
-
 /* QEMU implements a 62.5MHz architected timer */
 /* FIXME: can we rely on CNTFREQ instead of hardcoding this fact here? */
 #define CONFIG_SYS_ARCH_TIMER
diff --git a/include/configs/rpi.h b/include/configs/rpi.h
index cab8661..f2d3646 100644
--- a/include/configs/rpi.h
+++ b/include/configs/rpi.h
@@ -75,13 +75,6 @@
 #define CONFIG_MISC_INIT_R
 #endif
 
-/* Console UART */
-#if defined (CONFIG_BCM2837) || defined(CONFIG_TARGET_RPI_0_W)
-#define CONFIG_BCM283X_MU_SERIAL
-#else
-#define CONFIG_PL01X_SERIAL
-#endif
-
 /* Console configuration */
 #define CONFIG_SYS_CBSIZE		1024
 
diff --git a/include/configs/spear-common.h b/include/configs/spear-common.h
index 349232e..c123e44 100644
--- a/include/configs/spear-common.h
+++ b/include/configs/spear-common.h
@@ -76,7 +76,6 @@
  * Serial Configuration (PL011)
  * CONFIG_PL01x_PORTS is defined in specific files
  */
-#define CONFIG_PL011_SERIAL
 #define CONFIG_PL011_CLOCK			(48 * 1000 * 1000)
 #define CONFIG_CONS_INDEX			0
 #define CONFIG_SYS_BAUDRATE_TABLE		{ 9600, 19200, 38400, \
diff --git a/include/configs/stm32f429-discovery.h b/include/configs/stm32f429-discovery.h
index 1ad3698..af9daad 100644
--- a/include/configs/stm32f429-discovery.h
+++ b/include/configs/stm32f429-discovery.h
@@ -43,8 +43,6 @@
 
 #define CONFIG_STM32_FLASH
 
-#define CONFIG_STM32_HSE_HZ		8000000
-
 #define CONFIG_SYS_CLK_FREQ		180000000 /* 180 MHz */
 
 #define CONFIG_SYS_HZ_CLOCK		1000000	/* Timer is clocked at 1MHz */
diff --git a/include/configs/stm32f429-evaluation.h b/include/configs/stm32f429-evaluation.h
new file mode 100644
index 0000000..ab33d0f
--- /dev/null
+++ b/include/configs/stm32f429-evaluation.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2017
+ * Author(s): Patrice CHOTARD, <patrice.chotard@st.com> for STMicroelectronics.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define CONFIG_MISC_INIT_R
+
+#define CONFIG_SYS_FLASH_BASE		0x08000000
+
+#define CONFIG_SYS_INIT_SP_ADDR		0x10010000
+#define CONFIG_SYS_TEXT_BASE		0x08000000
+
+#define CONFIG_SYS_ICACHE_OFF
+#define CONFIG_SYS_DCACHE_OFF
+
+/*
+ * Configuration of the external SDRAM memory
+ */
+#define CONFIG_NR_DRAM_BANKS		1
+#define CONFIG_SYS_RAM_FREQ_DIV		2
+#define CONFIG_SYS_RAM_BASE		0x00000000
+#define CONFIG_SYS_SDRAM_BASE		CONFIG_SYS_RAM_BASE
+#define CONFIG_SYS_LOAD_ADDR		0x00400000
+#define CONFIG_LOADADDR			0x00400000
+
+#define CONFIG_SYS_MAX_FLASH_SECT	12
+#define CONFIG_SYS_MAX_FLASH_BANKS	2
+
+#define CONFIG_ENV_OFFSET		(256 << 10)
+#define CONFIG_ENV_SECT_SIZE		(128 << 10)
+#define CONFIG_ENV_SIZE			(8 << 10)
+
+#define CONFIG_STM32_FLASH
+
+#define CONFIG_SYS_CLK_FREQ		180000000 /* 180 MHz */
+#define CONFIG_SYS_HZ_CLOCK		1000000	/* Timer is clocked at 1MHz */
+
+#define CONFIG_CMDLINE_TAG
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_INITRD_TAG
+#define CONFIG_REVISION_TAG
+
+#define CONFIG_SYS_CBSIZE		1024
+
+#define CONFIG_SYS_MALLOC_LEN		(1 * 1024 * 1024)
+
+#define CONFIG_BOOTCOMMAND						\
+	"run boot_sd"
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	"boot_sd=mmc dev 0;fatload mmc 0 0x00700000 stm32429i-eval.dtb; fatload mmc 0 0x00008000 zImage; icache off; bootz 0x00008000 - 0x00700000"
+
+/*
+ * Command line configuration.
+ */
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_CMDLINE_EDITING
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/stm32f469-discovery.h b/include/configs/stm32f469-discovery.h
index 1409999..c290a66 100644
--- a/include/configs/stm32f469-discovery.h
+++ b/include/configs/stm32f469-discovery.h
@@ -39,7 +39,6 @@
 
 #define CONFIG_STM32_FLASH
 
-#define CONFIG_STM32_HSE_HZ		8000000
 #define CONFIG_SYS_CLK_FREQ		180000000 /* 180 MHz */
 #define CONFIG_SYS_HZ_CLOCK		1000000	/* Timer is clocked at 1MHz */
 
diff --git a/include/configs/stm32f746-disco.h b/include/configs/stm32f746-disco.h
index d12b1d8..301ab0f 100644
--- a/include/configs/stm32f746-disco.h
+++ b/include/configs/stm32f746-disco.h
@@ -37,7 +37,6 @@
 #define CONFIG_MII
 #define CONFIG_PHY_SMSC
 
-#define CONFIG_STM32_HSE_HZ		25000000
 #define CONFIG_SYS_CLK_FREQ		200000000 /* 200 MHz */
 #define CONFIG_SYS_HZ_CLOCK		1000000	/* Timer is clocked at 1MHz */
 
diff --git a/include/configs/stv0991.h b/include/configs/stv0991.h
index beb8f1a..c21fea3 100644
--- a/include/configs/stv0991.h
+++ b/include/configs/stv0991.h
@@ -25,9 +25,6 @@
 	(PHYS_SDRAM_1_SIZE - CONFIG_ENV_SIZE)
 #define CONFIG_SYS_MALLOC_LEN			(CONFIG_ENV_SIZE + 16 * 1024)
 
-/* serial port (PL011) configuration */
-#define CONFIG_PL01X_SERIAL
-
 /* user interface */
 #define CONFIG_SYS_CBSIZE			1024
 
diff --git a/include/configs/thunderx_88xx.h b/include/configs/thunderx_88xx.h
index 209a7c3..34940ef 100644
--- a/include/configs/thunderx_88xx.h
+++ b/include/configs/thunderx_88xx.h
@@ -35,7 +35,6 @@
 
 /* PL011 Serial Configuration */
 
-#define CONFIG_PL01X_SERIAL
 #define CONFIG_PL011_CLOCK		24000000
 #define CONFIG_CONS_INDEX		1
 
diff --git a/include/configs/vexpress_aemv8a.h b/include/configs/vexpress_aemv8a.h
index 6203e14..07cc92c 100644
--- a/include/configs/vexpress_aemv8a.h
+++ b/include/configs/vexpress_aemv8a.h
@@ -110,8 +110,6 @@
 
 /* PL011 Serial Configuration */
 #define CONFIG_CONS_INDEX		0
-#define CONFIG_PL01X_SERIAL
-#define CONFIG_PL011_SERIAL
 #ifdef CONFIG_TARGET_VEXPRESS64_JUNO
 #define CONFIG_PL011_CLOCK		7273800
 #else
diff --git a/include/configs/vexpress_common.h b/include/configs/vexpress_common.h
index 294ca18..94a352f 100644
--- a/include/configs/vexpress_common.h
+++ b/include/configs/vexpress_common.h
@@ -133,7 +133,6 @@
 #define CONFIG_SYS_TIMER_COUNTS_DOWN
 
 /* PL011 Serial Configuration */
-#define CONFIG_PL011_SERIAL
 #define CONFIG_PL011_CLOCK		24000000
 #define CONFIG_PL01x_PORTS		{(void *)CONFIG_SYS_SERIAL0, \
 					 (void *)CONFIG_SYS_SERIAL1}
diff --git a/include/configs/x600.h b/include/configs/x600.h
index 4aa5a2a..66a8e88 100644
--- a/include/configs/x600.h
+++ b/include/configs/x600.h
@@ -38,7 +38,6 @@
 #define CONFIG_SYS_SERIAL1			0xD0080000
 #define CONFIG_PL01x_PORTS			{ (void *)CONFIG_SYS_SERIAL0, \
 						(void *)CONFIG_SYS_SERIAL1 }
-#define CONFIG_PL011_SERIAL
 #define CONFIG_PL011_CLOCK			(48 * 1000 * 1000)
 #define CONFIG_CONS_INDEX			0
 #define CONFIG_SYS_BAUDRATE_TABLE		{ 9600, 19200, 38400, \
diff --git a/include/dm/platform_data/serial_bcm283x_mu.h b/include/dm/platform_data/serial_bcm283x_mu.h
index c47d3c0..57ae6ad 100644
--- a/include/dm/platform_data/serial_bcm283x_mu.h
+++ b/include/dm/platform_data/serial_bcm283x_mu.h
@@ -19,7 +19,6 @@
 	unsigned long base;
 	unsigned int clock;
 	bool skip_init;
-	bool disabled;
 };
 
 #endif
diff --git a/include/dm/read.h b/include/dm/read.h
index f1f0dfd..f14c7a7 100644
--- a/include/dm/read.h
+++ b/include/dm/read.h
@@ -265,7 +265,7 @@
  * This walks back up the tree to find the closest #address-cells property
  * which controls the given node.
  *
- * @dev: devioe to check
+ * @dev: device to check
  * @return number of address cells this node uses
  */
 int dev_read_addr_cells(struct udevice *dev);
@@ -276,7 +276,7 @@
  * This walks back up the tree to find the closest #size-cells property
  * which controls the given node.
  *
- * @dev: devioe to check
+ * @dev: device to check
  * @return number of size cells this node uses
  */
 int dev_read_size_cells(struct udevice *dev);
@@ -286,7 +286,7 @@
  *
  * This function matches fdt_address_cells().
  *
- * @dev: devioe to check
+ * @dev: device to check
  * @return number of address cells this node uses
  */
 int dev_read_simple_addr_cells(struct udevice *dev);
@@ -296,7 +296,7 @@
  *
  * This function matches fdt_size_cells().
  *
- * @dev: devioe to check
+ * @dev: device to check
  * @return number of size cells this node uses
  */
 int dev_read_simple_size_cells(struct udevice *dev);
diff --git a/include/libfdt.h b/include/libfdt.h
index 7ba13e6..b00e993 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -1 +1,318 @@
-#include "../lib/libfdt/libfdt.h"
+#ifndef UBOOT_LIBFDT_H
+#define UBOOT_LIBFDT_H
+/*
+ * SPDX-License-Identifier:     GPL-2.0+ BSD-2-Clause
+ */
+
+#ifdef USE_HOSTCC
+#include "../scripts/dtc/libfdt/libfdt.h"
+#else
+#include <linux/libfdt.h>
+#endif
+
+/* U-Boot local hacks */
+
+#ifndef SWIG /* Not available in Python */
+struct fdt_region {
+	int offset;
+	int size;
+};
+
+/*
+ * Flags for fdt_find_regions()
+ *
+ * Add a region for the string table (always the last region)
+ */
+#define FDT_REG_ADD_STRING_TAB		(1 << 0)
+
+/*
+ * Add all supernodes of a matching node/property, useful for creating a
+ * valid subset tree
+ */
+#define FDT_REG_SUPERNODES		(1 << 1)
+
+/* Add the FDT_BEGIN_NODE tags of subnodes, including their names */
+#define FDT_REG_DIRECT_SUBNODES	(1 << 2)
+
+/* Add all subnodes of a matching node */
+#define FDT_REG_ALL_SUBNODES		(1 << 3)
+
+/* Add a region for the mem_rsvmap table (always the first region) */
+#define FDT_REG_ADD_MEM_RSVMAP		(1 << 4)
+
+/* Indicates what an fdt part is (node, property, value) */
+#define FDT_IS_NODE			(1 << 0)
+#define FDT_IS_PROP			(1 << 1)
+#define FDT_IS_VALUE			(1 << 2)	/* not supported */
+#define FDT_IS_COMPAT			(1 << 3)	/* used internally */
+#define FDT_NODE_HAS_PROP		(1 << 4)	/* node contains prop */
+
+#define FDT_ANY_GLOBAL		(FDT_IS_NODE | FDT_IS_PROP | FDT_IS_VALUE | \
+					FDT_IS_COMPAT)
+#define FDT_IS_ANY			0x1f		/* all the above */
+
+/* We set a reasonable limit on the number of nested nodes */
+#define FDT_MAX_DEPTH			32
+
+/* Decribes what we want to include from the current tag */
+enum want_t {
+	WANT_NOTHING,
+	WANT_NODES_ONLY,		/* No properties */
+	WANT_NODES_AND_PROPS,		/* Everything for one level */
+	WANT_ALL_NODES_AND_PROPS	/* Everything for all levels */
+};
+
+/* Keeps track of the state at parent nodes */
+struct fdt_subnode_stack {
+	int offset;		/* Offset of node */
+	enum want_t want;	/* The 'want' value here */
+	int included;		/* 1 if we included this node, 0 if not */
+};
+
+struct fdt_region_ptrs {
+	int depth;			/* Current tree depth */
+	int done;			/* What we have completed scanning */
+	enum want_t want;		/* What we are currently including */
+	char *end;			/* Pointer to end of full node path */
+	int nextoffset;			/* Next node offset to check */
+};
+
+/* The state of our finding algortihm */
+struct fdt_region_state {
+	struct fdt_subnode_stack stack[FDT_MAX_DEPTH];	/* node stack */
+	struct fdt_region *region;	/* Contains list of regions found */
+	int count;			/* Numnber of regions found */
+	const void *fdt;		/* FDT blob */
+	int max_regions;		/* Maximum regions to find */
+	int can_merge;		/* 1 if we can merge with previous region */
+	int start;			/* Start position of current region */
+	struct fdt_region_ptrs ptrs;	/* Pointers for what we are up to */
+};
+
+/**
+ * fdt_find_regions() - find regions in device tree
+ *
+ * Given a list of nodes to include and properties to exclude, find
+ * the regions of the device tree which describe those included parts.
+ *
+ * The intent is to get a list of regions which will be invariant provided
+ * those parts are invariant. For example, if you request a list of regions
+ * for all nodes but exclude the property "data", then you will get the
+ * same region contents regardless of any change to "data" properties.
+ *
+ * This function can be used to produce a byte-stream to send to a hashing
+ * function to verify that critical parts of the FDT have not changed.
+ *
+ * Nodes which are given in 'inc' are included in the region list, as
+ * are the names of the immediate subnodes nodes (but not the properties
+ * or subnodes of those subnodes).
+ *
+ * For eaxample "/" means to include the root node, all root properties
+ * and the FDT_BEGIN_NODE and FDT_END_NODE of all subnodes of /. The latter
+ * ensures that we capture the names of the subnodes. In a hashing situation
+ * it prevents the root node from changing at all Any change to non-excluded
+ * properties, names of subnodes or number of subnodes would be detected.
+ *
+ * When used with FITs this provides the ability to hash and sign parts of
+ * the FIT based on different configurations in the FIT. Then it is
+ * impossible to change anything about that configuration (include images
+ * attached to the configuration), but it may be possible to add new
+ * configurations, new images or new signatures within the existing
+ * framework.
+ *
+ * Adding new properties to a device tree may result in the string table
+ * being extended (if the new property names are different from those
+ * already added). This function can optionally include a region for
+ * the string table so that this can be part of the hash too.
+ *
+ * The device tree header is not included in the list.
+ *
+ * @fdt:	Device tree to check
+ * @inc:	List of node paths to included
+ * @inc_count:	Number of node paths in list
+ * @exc_prop:	List of properties names to exclude
+ * @exc_prop_count:	Number of properties in exclude list
+ * @region:	Returns list of regions
+ * @max_region:	Maximum length of region list
+ * @path:	Pointer to a temporary string for the function to use for
+ *		building path names
+ * @path_len:	Length of path, must be large enough to hold the longest
+ *		path in the tree
+ * @add_string_tab:	1 to add a region for the string table
+ * @return number of regions in list. If this is >max_regions then the
+ * region array was exhausted. You should increase max_regions and try
+ * the call again.
+ */
+int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
+		     char * const exc_prop[], int exc_prop_count,
+		     struct fdt_region region[], int max_regions,
+		     char *path, int path_len, int add_string_tab);
+
+/**
+ * fdt_first_region() - find regions in device tree
+ *
+ * Given a nodes and properties to include and properties to exclude, find
+ * the regions of the device tree which describe those included parts.
+ *
+ * The use for this function is twofold. Firstly it provides a convenient
+ * way of performing a structure-aware grep of the tree. For example it is
+ * possible to grep for a node and get all the properties associated with
+ * that node. Trees can be subsetted easily, by specifying the nodes that
+ * are required, and then writing out the regions returned by this function.
+ * This is useful for small resource-constrained systems, such as boot
+ * loaders, which want to use an FDT but do not need to know about all of
+ * it.
+ *
+ * Secondly it makes it easy to hash parts of the tree and detect changes.
+ * The intent is to get a list of regions which will be invariant provided
+ * those parts are invariant. For example, if you request a list of regions
+ * for all nodes but exclude the property "data", then you will get the
+ * same region contents regardless of any change to "data" properties.
+ *
+ * This function can be used to produce a byte-stream to send to a hashing
+ * function to verify that critical parts of the FDT have not changed.
+ * Note that semantically null changes in order could still cause false
+ * hash misses. Such reordering might happen if the tree is regenerated
+ * from source, and nodes are reordered (the bytes-stream will be emitted
+ * in a different order and many hash functions will detect this). However
+ * if an existing tree is modified using libfdt functions, such as
+ * fdt_add_subnode() and fdt_setprop(), then this problem is avoided.
+ *
+ * The nodes/properties to include/exclude are defined by a function
+ * provided by the caller. This function is called for each node and
+ * property, and must return:
+ *
+ *    0 - to exclude this part
+ *    1 - to include this part
+ *   -1 - for FDT_IS_PROP only: no information is available, so include
+ *		if its containing node is included
+ *
+ * The last case is only used to deal with properties. Often a property is
+ * included if its containing node is included - this is the case where
+ * -1 is returned.. However if the property is specifically required to be
+ * included/excluded, then 0 or 1 can be returned. Note that including a
+ * property when the FDT_REG_SUPERNODES flag is given will force its
+ * containing node to be included since it is not valid to have a property
+ * that is not in a node.
+ *
+ * Using the information provided, the inclusion of a node can be controlled
+ * either by a node name or its compatible string, or any other property
+ * that the function can determine.
+ *
+ * As an example, including node "/" means to include the root node and all
+ * root properties. A flag provides a way of also including supernodes (of
+ * which there is none for the root node), and another flag includes
+ * immediate subnodes, so in this case we would get the FDT_BEGIN_NODE and
+ * FDT_END_NODE of all subnodes of /.
+ *
+ * The subnode feature helps in a hashing situation since it prevents the
+ * root node from changing at all. Any change to non-excluded properties,
+ * names of subnodes or number of subnodes would be detected.
+ *
+ * When used with FITs this provides the ability to hash and sign parts of
+ * the FIT based on different configurations in the FIT. Then it is
+ * impossible to change anything about that configuration (include images
+ * attached to the configuration), but it may be possible to add new
+ * configurations, new images or new signatures within the existing
+ * framework.
+ *
+ * Adding new properties to a device tree may result in the string table
+ * being extended (if the new property names are different from those
+ * already added). This function can optionally include a region for
+ * the string table so that this can be part of the hash too. This is always
+ * the last region.
+ *
+ * The FDT also has a mem_rsvmap table which can also be included, and is
+ * always the first region if so.
+ *
+ * The device tree header is not included in the region list. Since the
+ * contents of the FDT are changing (shrinking, often), the caller will need
+ * to regenerate the header anyway.
+ *
+ * @fdt:	Device tree to check
+ * @h_include:	Function to call to determine whether to include a part or
+ *		not:
+ *
+ *		@priv: Private pointer as passed to fdt_find_regions()
+ *		@fdt: Pointer to FDT blob
+ *		@offset: Offset of this node / property
+ *		@type: Type of this part, FDT_IS_...
+ *		@data: Pointer to data (node name, property name, compatible
+ *			string, value (not yet supported)
+ *		@size: Size of data, or 0 if none
+ *		@return 0 to exclude, 1 to include, -1 if no information is
+ *		available
+ * @priv:	Private pointer passed to h_include
+ * @region:	Returns list of regions, sorted by offset
+ * @max_regions: Maximum length of region list
+ * @path:	Pointer to a temporary string for the function to use for
+ *		building path names
+ * @path_len:	Length of path, must be large enough to hold the longest
+ *		path in the tree
+ * @flags:	Various flags that control the region algortihm, see
+ *		FDT_REG_...
+ * @return number of regions in list. If this is >max_regions then the
+ * region array was exhausted. You should increase max_regions and try
+ * the call again. Only the first max_regions elements are available in the
+ * array.
+ *
+ * On error a -ve value is return, which can be:
+ *
+ *	-FDT_ERR_BADSTRUCTURE (too deep or more END tags than BEGIN tags
+ *	-FDT_ERR_BADLAYOUT
+ *	-FDT_ERR_NOSPACE (path area is too small)
+ */
+int fdt_first_region(const void *fdt,
+		     int (*h_include)(void *priv, const void *fdt, int offset,
+				      int type, const char *data, int size),
+		     void *priv, struct fdt_region *region,
+		     char *path, int path_len, int flags,
+		     struct fdt_region_state *info);
+
+/** fdt_next_region() - find next region
+ *
+ * See fdt_first_region() for full description. This function finds the
+ * next region according to the provided parameters, which must be the same
+ * as passed to fdt_first_region().
+ *
+ * This function can additionally return -FDT_ERR_NOTFOUND when there are no
+ * more regions
+ */
+int fdt_next_region(const void *fdt,
+		    int (*h_include)(void *priv, const void *fdt, int offset,
+				     int type, const char *data, int size),
+		    void *priv, struct fdt_region *region,
+		    char *path, int path_len, int flags,
+		    struct fdt_region_state *info);
+
+/**
+ * fdt_add_alias_regions() - find aliases that point to existing regions
+ *
+ * Once a device tree grep is complete some of the nodes will be present
+ * and some will have been dropped. This function checks all the alias nodes
+ * to figure out which points point to nodes which are still present. These
+ * aliases need to be kept, along with the nodes they reference.
+ *
+ * Given a list of regions function finds the aliases that still apply and
+ * adds more regions to the list for these. This function is called after
+ * fdt_next_region() has finished returning regions and requires the same
+ * state.
+ *
+ * @fdt:	Device tree file to reference
+ * @region:	List of regions that will be kept
+ * @count:	Number of regions
+ * @max_regions: Number of entries that can fit in @region
+ * @info:	Region state as returned from fdt_next_region()
+ * @return new number of regions in @region (i.e. count + the number added)
+ * or -FDT_ERR_NOSPACE if there was not enough space.
+ */
+int fdt_add_alias_regions(const void *fdt, struct fdt_region *region, int count,
+			  int max_regions, struct fdt_region_state *info);
+#endif /* SWIG */
+
+extern struct fdt_header *working_fdt;  /* Pointer to the working fdt */
+
+/* adding a ramdisk needs 0x44 bytes in version 2008.10 */
+#define FDT_RAMDISK_OVERHEAD	0x80
+
+#endif /* UBOOT_LIBFDT_H */
diff --git a/include/libfdt_env.h b/include/libfdt_env.h
index 273b5d3..d7e9d32 100644
--- a/include/libfdt_env.h
+++ b/include/libfdt_env.h
@@ -1,29 +1,5 @@
-/*
- * libfdt - Flat Device Tree manipulation (build/run environment adaptation)
- * Copyright (C) 2007 Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
- * Original version written by David Gibson, IBM Corporation.
- *
- * SPDX-License-Identifier:	LGPL-2.1+
- */
-
-#ifndef _LIBFDT_ENV_H
-#define _LIBFDT_ENV_H
-
-#include "compiler.h"
-#include "linux/types.h"
-
-extern struct fdt_header *working_fdt;  /* Pointer to the working fdt */
-
-typedef __be16 fdt16_t;
-typedef __be32 fdt32_t;
-typedef __be64 fdt64_t;
-
-#define fdt32_to_cpu(x)		be32_to_cpu(x)
-#define cpu_to_fdt32(x)		cpu_to_be32(x)
-#define fdt64_to_cpu(x)		be64_to_cpu(x)
-#define cpu_to_fdt64(x)		cpu_to_be64(x)
-
-/* adding a ramdisk needs 0x44 bytes in version 2008.10 */
-#define FDT_RAMDISK_OVERHEAD	0x80
-
-#endif /* _LIBFDT_ENV_H */
+#ifdef USE_HOSTCC
+#include "../scripts/dtc/libfdt/libfdt_env.h"
+#else
+#include <linux/libfdt_env.h>
+#endif
diff --git a/include/linux/libfdt.h b/include/linux/libfdt.h
index 2a663c6..90ed4eb 100644
--- a/include/linux/libfdt.h
+++ b/include/linux/libfdt.h
@@ -1,17 +1,8 @@
-#ifndef _LIBFDT_ENV_H
-#define _LIBFDT_ENV_H
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _INCLUDE_LIBFDT_H_
+#define _INCLUDE_LIBFDT_H_
 
-#include <linux/string.h>
-
-#include <asm/byteorder.h>
-
-typedef __be16 fdt16_t;
-typedef __be32 fdt32_t;
-typedef __be64 fdt64_t;
-
-#define fdt32_to_cpu(x) be32_to_cpu(x)
-#define cpu_to_fdt32(x) cpu_to_be32(x)
-#define fdt64_to_cpu(x) be64_to_cpu(x)
-#define cpu_to_fdt64(x) cpu_to_be64(x)
+#include <linux/libfdt_env.h>
+#include "../../scripts/dtc/libfdt/libfdt.h"
 
-#endif /* _LIBFDT_ENV_H */
+#endif /* _INCLUDE_LIBFDT_H_ */
diff --git a/lib/libfdt/Makefile b/lib/libfdt/Makefile
index be42e94..4e3e12f 100644
--- a/lib/libfdt/Makefile
+++ b/lib/libfdt/Makefile
@@ -11,6 +11,7 @@
 	fdt_wip.o \
 	fdt_strerror.o \
 	fdt_sw.o \
+	fdt_rw.o \
 	fdt_empty_tree.o \
 	fdt_addresses.o
 
@@ -18,9 +19,7 @@
 
 # Locally modified for U-Boot.
 # TODO: split out the local modifiction.
-obj-y += \
-	fdt_ro.o \
-	fdt_rw.o
+obj-y += fdt_ro.o
 
 # U-Boot own file
 obj-y += fdt_region.o
diff --git a/lib/libfdt/fdt_rw.c b/lib/libfdt/fdt_rw.c
index 3dc7752..aafded0 100644
--- a/lib/libfdt/fdt_rw.c
+++ b/lib/libfdt/fdt_rw.c
@@ -1,496 +1,2 @@
-/*
- * libfdt - Flat Device Tree manipulation
- * Copyright (C) 2006 David Gibson, IBM Corporation.
- * SPDX-License-Identifier:	GPL-2.0+ BSD-2-Clause
- */
-#include <libfdt_env.h>
-
-#ifndef USE_HOSTCC
-#include <fdt.h>
-#include <libfdt.h>
-#else
-#include "fdt_host.h"
-#endif
-
-#include "libfdt_internal.h"
-
-static int _fdt_blocks_misordered(const void *fdt,
-			      int mem_rsv_size, int struct_size)
-{
-	return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
-		|| (fdt_off_dt_struct(fdt) <
-		    (fdt_off_mem_rsvmap(fdt) + mem_rsv_size))
-		|| (fdt_off_dt_strings(fdt) <
-		    (fdt_off_dt_struct(fdt) + struct_size))
-		|| (fdt_totalsize(fdt) <
-		    (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
-}
-
-static int _fdt_rw_check_header(void *fdt)
-{
-	FDT_CHECK_HEADER(fdt);
-
-	if (fdt_version(fdt) < 17)
-		return -FDT_ERR_BADVERSION;
-	if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
-				   fdt_size_dt_struct(fdt)))
-		return -FDT_ERR_BADLAYOUT;
-	if (fdt_version(fdt) > 17)
-		fdt_set_version(fdt, 17);
-
-	return 0;
-}
-
-#define FDT_RW_CHECK_HEADER(fdt) \
-	{ \
-		int __err; \
-		if ((__err = _fdt_rw_check_header(fdt)) != 0) \
-			return __err; \
-	}
-
-static inline int _fdt_data_size(void *fdt)
-{
-	return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
-}
-
-static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
-{
-	char *p = splicepoint;
-	char *end = (char *)fdt + _fdt_data_size(fdt);
-
-	if (((p + oldlen) < p) || ((p + oldlen) > end))
-		return -FDT_ERR_BADOFFSET;
-	if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt))
-		return -FDT_ERR_BADOFFSET;
-	if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
-		return -FDT_ERR_NOSPACE;
-	memmove(p + newlen, p + oldlen, end - p - oldlen);
-	return 0;
-}
-
-static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
-			       int oldn, int newn)
-{
-	int delta = (newn - oldn) * sizeof(*p);
-	int err;
-	err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
-	if (err)
-		return err;
-	fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
-	fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
-	return 0;
-}
-
-static int _fdt_splice_struct(void *fdt, void *p,
-			      int oldlen, int newlen)
-{
-	int delta = newlen - oldlen;
-	int err;
-
-	if ((err = _fdt_splice(fdt, p, oldlen, newlen)))
-		return err;
-
-	fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
-	fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
-	return 0;
-}
-
-static int _fdt_splice_string(void *fdt, int newlen)
-{
-	void *p = (char *)fdt
-		+ fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
-	int err;
-
-	if ((err = _fdt_splice(fdt, p, 0, newlen)))
-		return err;
-
-	fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
-	return 0;
-}
-
-static int _fdt_find_add_string(void *fdt, const char *s)
-{
-	char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
-	const char *p;
-	char *new;
-	int len = strlen(s) + 1;
-	int err;
-
-	p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s);
-	if (p)
-		/* found it */
-		return (p - strtab);
-
-	new = strtab + fdt_size_dt_strings(fdt);
-	err = _fdt_splice_string(fdt, len);
-	if (err)
-		return err;
-
-	memcpy(new, s, len);
-	return (new - strtab);
-}
-
-int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
-{
-	struct fdt_reserve_entry *re;
-	int err;
-
-	FDT_RW_CHECK_HEADER(fdt);
-
-	re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
-	err = _fdt_splice_mem_rsv(fdt, re, 0, 1);
-	if (err)
-		return err;
-
-	re->address = cpu_to_fdt64(address);
-	re->size = cpu_to_fdt64(size);
-	return 0;
-}
-
-int fdt_del_mem_rsv(void *fdt, int n)
-{
-	struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
-
-	FDT_RW_CHECK_HEADER(fdt);
-
-	if (n >= fdt_num_mem_rsv(fdt))
-		return -FDT_ERR_NOTFOUND;
-
-	return _fdt_splice_mem_rsv(fdt, re, 1, 0);
-}
-
-static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
-				int len, struct fdt_property **prop)
-{
-	int oldlen;
-	int err;
-
-	*prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
-	if (!*prop)
-		return oldlen;
-
-	if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
-				      FDT_TAGALIGN(len))))
-		return err;
-
-	(*prop)->len = cpu_to_fdt32(len);
-	return 0;
-}
-
-static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,
-			     int len, struct fdt_property **prop)
-{
-	int proplen;
-	int nextoffset;
-	int namestroff;
-	int err;
-
-	if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
-		return nextoffset;
-
-	namestroff = _fdt_find_add_string(fdt, name);
-	if (namestroff < 0)
-		return namestroff;
-
-	*prop = _fdt_offset_ptr_w(fdt, nextoffset);
-	proplen = sizeof(**prop) + FDT_TAGALIGN(len);
-
-	err = _fdt_splice_struct(fdt, *prop, 0, proplen);
-	if (err)
-		return err;
-
-	(*prop)->tag = cpu_to_fdt32(FDT_PROP);
-	(*prop)->nameoff = cpu_to_fdt32(namestroff);
-	(*prop)->len = cpu_to_fdt32(len);
-	return 0;
-}
-
-int fdt_set_name(void *fdt, int nodeoffset, const char *name)
-{
-	char *namep;
-	int oldlen, newlen;
-	int err;
-
-	FDT_RW_CHECK_HEADER(fdt);
-
-	namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
-	if (!namep)
-		return oldlen;
-
-	newlen = strlen(name);
-
-	err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1),
-				 FDT_TAGALIGN(newlen+1));
-	if (err)
-		return err;
-
-	memcpy(namep, name, newlen+1);
-	return 0;
-}
-
-int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
-			    int len, void **prop_data)
-{
-	struct fdt_property *prop;
-	int err;
-
-	FDT_RW_CHECK_HEADER(fdt);
-
-	err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop);
-	if (err == -FDT_ERR_NOTFOUND)
-		err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
-	if (err)
-		return err;
-
-	*prop_data = prop->data;
-	return 0;
-}
-
-int fdt_setprop(void *fdt, int nodeoffset, const char *name,
-		const void *val, int len)
-{
-	void *prop_data;
-	int err;
-
-	err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data);
-	if (err)
-		return err;
-
-	if (len)
-		memcpy(prop_data, val, len);
-	return 0;
-}
-
-int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
-		   const void *val, int len)
-{
-	struct fdt_property *prop;
-	int err, oldlen, newlen;
-
-	FDT_RW_CHECK_HEADER(fdt);
-
-	prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
-	if (prop) {
-		newlen = len + oldlen;
-		err = _fdt_splice_struct(fdt, prop->data,
-					 FDT_TAGALIGN(oldlen),
-					 FDT_TAGALIGN(newlen));
-		if (err)
-			return err;
-		prop->len = cpu_to_fdt32(newlen);
-		memcpy(prop->data + oldlen, val, len);
-	} else {
-		err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
-		if (err)
-			return err;
-		memcpy(prop->data, val, len);
-	}
-	return 0;
-}
-
-int fdt_delprop(void *fdt, int nodeoffset, const char *name)
-{
-	struct fdt_property *prop;
-	int len, proplen;
-
-	FDT_RW_CHECK_HEADER(fdt);
-
-	prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
-	if (!prop)
-		return len;
-
-	proplen = sizeof(*prop) + FDT_TAGALIGN(len);
-	return _fdt_splice_struct(fdt, prop, proplen, 0);
-}
-
-int fdt_add_subnode_namelen(void *fdt, int parentoffset,
-			    const char *name, int namelen)
-{
-	struct fdt_node_header *nh;
-	int offset, nextoffset;
-	int nodelen;
-	int err;
-	uint32_t tag;
-	fdt32_t *endtag;
-
-	FDT_RW_CHECK_HEADER(fdt);
-
-	offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
-	if (offset >= 0)
-		return -FDT_ERR_EXISTS;
-	else if (offset != -FDT_ERR_NOTFOUND)
-		return offset;
-
-	/* Try to place the new node after the parent's properties */
-	fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
-	do {
-		offset = nextoffset;
-		tag = fdt_next_tag(fdt, offset, &nextoffset);
-	} while ((tag == FDT_PROP) || (tag == FDT_NOP));
-
-	nh = _fdt_offset_ptr_w(fdt, offset);
-	nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
-
-	err = _fdt_splice_struct(fdt, nh, 0, nodelen);
-	if (err)
-		return err;
-
-	nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
-	memset(nh->name, 0, FDT_TAGALIGN(namelen+1));
-	memcpy(nh->name, name, namelen);
-	endtag = (fdt32_t *)((char *)nh + nodelen - FDT_TAGSIZE);
-	*endtag = cpu_to_fdt32(FDT_END_NODE);
-
-	return offset;
-}
-
-int fdt_add_subnode(void *fdt, int parentoffset, const char *name)
-{
-	return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name));
-}
-
-int fdt_del_node(void *fdt, int nodeoffset)
-{
-	int endoffset;
-
-	FDT_RW_CHECK_HEADER(fdt);
-
-	endoffset = _fdt_node_end_offset(fdt, nodeoffset);
-	if (endoffset < 0)
-		return endoffset;
-
-	return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
-				  endoffset - nodeoffset, 0);
-}
-
-static void _fdt_packblocks(const char *old, char *new,
-			    int mem_rsv_size, int struct_size)
-{
-	int mem_rsv_off, struct_off, strings_off;
-
-	mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8);
-	struct_off = mem_rsv_off + mem_rsv_size;
-	strings_off = struct_off + struct_size;
-
-	memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size);
-	fdt_set_off_mem_rsvmap(new, mem_rsv_off);
-
-	memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size);
-	fdt_set_off_dt_struct(new, struct_off);
-	fdt_set_size_dt_struct(new, struct_size);
-
-	memmove(new + strings_off, old + fdt_off_dt_strings(old),
-		fdt_size_dt_strings(old));
-	fdt_set_off_dt_strings(new, strings_off);
-	fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
-}
-
-int fdt_open_into(const void *fdt, void *buf, int bufsize)
-{
-	int err;
-	int mem_rsv_size, struct_size;
-	int newsize;
-	const char *fdtstart = fdt;
-	const char *fdtend = fdtstart + fdt_totalsize(fdt);
-	char *tmp;
-
-	FDT_CHECK_HEADER(fdt);
-
-	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
-		* sizeof(struct fdt_reserve_entry);
-
-	if (fdt_version(fdt) >= 17) {
-		struct_size = fdt_size_dt_struct(fdt);
-	} else {
-		struct_size = 0;
-		while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
-			;
-		if (struct_size < 0)
-			return struct_size;
-	}
-
-	if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
-		/* no further work necessary */
-		err = fdt_move(fdt, buf, bufsize);
-		if (err)
-			return err;
-		fdt_set_version(buf, 17);
-		fdt_set_size_dt_struct(buf, struct_size);
-		fdt_set_totalsize(buf, bufsize);
-		return 0;
-	}
-
-	/* Need to reorder */
-	newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size
-		+ struct_size + fdt_size_dt_strings(fdt);
-
-	if (bufsize < newsize)
-		return -FDT_ERR_NOSPACE;
-
-	/* First attempt to build converted tree at beginning of buffer */
-	tmp = buf;
-	/* But if that overlaps with the old tree... */
-	if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) {
-		/* Try right after the old tree instead */
-		tmp = (char *)(uintptr_t)fdtend;
-		if ((tmp + newsize) > ((char *)buf + bufsize))
-			return -FDT_ERR_NOSPACE;
-	}
-
-	_fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size);
-	memmove(buf, tmp, newsize);
-
-	fdt_set_magic(buf, FDT_MAGIC);
-	fdt_set_totalsize(buf, bufsize);
-	fdt_set_version(buf, 17);
-	fdt_set_last_comp_version(buf, 16);
-	fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt));
-
-	return 0;
-}
-
-int fdt_pack(void *fdt)
-{
-	int mem_rsv_size;
-
-	FDT_RW_CHECK_HEADER(fdt);
-
-	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
-		* sizeof(struct fdt_reserve_entry);
-	_fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
-	fdt_set_totalsize(fdt, _fdt_data_size(fdt));
-
-	return 0;
-}
-
-int fdt_remove_unused_strings(const void *old, void *new)
-{
-	const struct fdt_property *old_prop;
-	struct fdt_property *new_prop;
-	int size = fdt_totalsize(old);
-	int next_offset, offset;
-	const char *str;
-	int ret;
-	int tag = FDT_PROP;
-
-	/* Make a copy and remove the strings */
-	memcpy(new, old, size);
-	fdt_set_size_dt_strings(new, 0);
-
-	/* Add every property name back into the new string table */
-	for (offset = 0; tag != FDT_END; offset = next_offset) {
-		tag = fdt_next_tag(old, offset, &next_offset);
-		if (tag != FDT_PROP)
-			continue;
-		old_prop = fdt_get_property_by_offset(old, offset, NULL);
-		new_prop = (struct fdt_property *)(unsigned long)
-			fdt_get_property_by_offset(new, offset, NULL);
-		str = fdt_string(old, fdt32_to_cpu(old_prop->nameoff));
-		ret = _fdt_find_add_string(new, str);
-		if (ret < 0)
-			return ret;
-		new_prop->nameoff = cpu_to_fdt32(ret);
-	}
-
-	return 0;
-}
+#include <linux/libfdt_env.h>
+#include "../../scripts/dtc/libfdt/fdt_rw.c"
diff --git a/lib/libfdt/libfdt.h b/lib/libfdt/libfdt.h
deleted file mode 100644
index 6af94cb..0000000
--- a/lib/libfdt/libfdt.h
+++ /dev/null
@@ -1,2170 +0,0 @@
-#ifndef _LIBFDT_H
-#define _LIBFDT_H
-/*
- * libfdt - Flat Device Tree manipulation
- * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * SPDX-License-Identifier:     GPL-2.0+ BSD-2-Clause
- */
-
-#include <libfdt_env.h>
-#include <fdt.h>
-
-#define FDT_FIRST_SUPPORTED_VERSION	0x10
-#define FDT_LAST_SUPPORTED_VERSION	0x11
-
-/* Error codes: informative error codes */
-#define FDT_ERR_NOTFOUND	1
-	/* FDT_ERR_NOTFOUND: The requested node or property does not exist */
-#define FDT_ERR_EXISTS		2
-	/* FDT_ERR_EXISTS: Attempted to create a node or property which
-	 * already exists */
-#define FDT_ERR_NOSPACE		3
-	/* FDT_ERR_NOSPACE: Operation needed to expand the device
-	 * tree, but its buffer did not have sufficient space to
-	 * contain the expanded tree. Use fdt_open_into() to move the
-	 * device tree to a buffer with more space. */
-
-/* Error codes: codes for bad parameters */
-#define FDT_ERR_BADOFFSET	4
-	/* FDT_ERR_BADOFFSET: Function was passed a structure block
-	 * offset which is out-of-bounds, or which points to an
-	 * unsuitable part of the structure for the operation. */
-#define FDT_ERR_BADPATH		5
-	/* FDT_ERR_BADPATH: Function was passed a badly formatted path
-	 * (e.g. missing a leading / for a function which requires an
-	 * absolute path) */
-#define FDT_ERR_BADPHANDLE	6
-	/* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle.
-	 * This can be caused either by an invalid phandle property
-	 * length, or the phandle value was either 0 or -1, which are
-	 * not permitted. */
-#define FDT_ERR_BADSTATE	7
-	/* FDT_ERR_BADSTATE: Function was passed an incomplete device
-	 * tree created by the sequential-write functions, which is
-	 * not sufficiently complete for the requested operation. */
-
-/* Error codes: codes for bad device tree blobs */
-#define FDT_ERR_TRUNCATED	8
-	/* FDT_ERR_TRUNCATED: Structure block of the given device tree
-	 * ends without an FDT_END tag. */
-#define FDT_ERR_BADMAGIC	9
-	/* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
-	 * device tree at all - it is missing the flattened device
-	 * tree magic number. */
-#define FDT_ERR_BADVERSION	10
-	/* FDT_ERR_BADVERSION: Given device tree has a version which
-	 * can't be handled by the requested operation.  For
-	 * read-write functions, this may mean that fdt_open_into() is
-	 * required to convert the tree to the expected version. */
-#define FDT_ERR_BADSTRUCTURE	11
-	/* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt
-	 * structure block or other serious error (e.g. misnested
-	 * nodes, or subnodes preceding properties). */
-#define FDT_ERR_BADLAYOUT	12
-	/* FDT_ERR_BADLAYOUT: For read-write functions, the given
-	 * device tree has it's sub-blocks in an order that the
-	 * function can't handle (memory reserve map, then structure,
-	 * then strings).  Use fdt_open_into() to reorganize the tree
-	 * into a form suitable for the read-write operations. */
-
-/* "Can't happen" error indicating a bug in libfdt */
-#define FDT_ERR_INTERNAL	13
-	/* FDT_ERR_INTERNAL: libfdt has failed an internal assertion.
-	 * Should never be returned, if it is, it indicates a bug in
-	 * libfdt itself. */
-
-/* Errors in device tree content */
-#define FDT_ERR_BADNCELLS	14
-	/* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells
-	 * or similar property with a bad format or value */
-
-#define FDT_ERR_BADVALUE	15
-	/* FDT_ERR_BADVALUE: Device tree has a property with an unexpected
-	 * value. For example: a property expected to contain a string list
-	 * is not NUL-terminated within the length of its value. */
-
-#define FDT_ERR_BADOVERLAY	16
-	/* FDT_ERR_BADOVERLAY: The device tree overlay, while
-	 * correctly structured, cannot be applied due to some
-	 * unexpected or missing value, property or node. */
-
-#define FDT_ERR_NOPHANDLES	17
-	/* FDT_ERR_NOPHANDLES: The device tree doesn't have any
-	 * phandle available anymore without causing an overflow */
-
-#define FDT_ERR_MAX		17
-
-/**********************************************************************/
-/* Low-level functions (you probably don't need these)                */
-/**********************************************************************/
-
-#ifndef SWIG /* This function is not useful in Python */
-const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
-#endif
-static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
-{
-	return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
-}
-
-uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
-
-/**********************************************************************/
-/* Traversal functions                                                */
-/**********************************************************************/
-
-int fdt_next_node(const void *fdt, int offset, int *depth);
-
-/**
- * fdt_first_subnode() - get offset of first direct subnode
- *
- * @fdt:	FDT blob
- * @offset:	Offset of node to check
- * @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none
- */
-int fdt_first_subnode(const void *fdt, int offset);
-
-/**
- * fdt_next_subnode() - get offset of next direct subnode
- *
- * After first calling fdt_first_subnode(), call this function repeatedly to
- * get direct subnodes of a parent node.
- *
- * @fdt:	FDT blob
- * @offset:	Offset of previous subnode
- * @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more
- * subnodes
- */
-int fdt_next_subnode(const void *fdt, int offset);
-
-/**
- * fdt_for_each_subnode - iterate over all subnodes of a parent
- *
- * @node:	child node (int, lvalue)
- * @fdt:	FDT blob (const void *)
- * @parent:	parent node (int)
- *
- * This is actually a wrapper around a for loop and would be used like so:
- *
- *	fdt_for_each_subnode(node, fdt, parent) {
- *		Use node
- *		...
- *	}
- *
- *	if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) {
- *		Error handling
- *	}
- *
- * Note that this is implemented as a macro and @node is used as
- * iterator in the loop. The parent variable be constant or even a
- * literal.
- *
- */
-#define fdt_for_each_subnode(node, fdt, parent)		\
-	for (node = fdt_first_subnode(fdt, parent);	\
-	     node >= 0;					\
-	     node = fdt_next_subnode(fdt, node))
-
-/**********************************************************************/
-/* General functions                                                  */
-/**********************************************************************/
-#define fdt_get_header(fdt, field) \
-	(fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
-#define fdt_magic(fdt)			(fdt_get_header(fdt, magic))
-#define fdt_totalsize(fdt)		(fdt_get_header(fdt, totalsize))
-#define fdt_off_dt_struct(fdt)		(fdt_get_header(fdt, off_dt_struct))
-#define fdt_off_dt_strings(fdt)		(fdt_get_header(fdt, off_dt_strings))
-#define fdt_off_mem_rsvmap(fdt)		(fdt_get_header(fdt, off_mem_rsvmap))
-#define fdt_version(fdt)		(fdt_get_header(fdt, version))
-#define fdt_last_comp_version(fdt)	(fdt_get_header(fdt, last_comp_version))
-#define fdt_boot_cpuid_phys(fdt)	(fdt_get_header(fdt, boot_cpuid_phys))
-#define fdt_size_dt_strings(fdt)	(fdt_get_header(fdt, size_dt_strings))
-#define fdt_size_dt_struct(fdt)		(fdt_get_header(fdt, size_dt_struct))
-
-#define __fdt_set_hdr(name) \
-	static inline void fdt_set_##name(void *fdt, uint32_t val) \
-	{ \
-		struct fdt_header *fdth = (struct fdt_header *)fdt; \
-		fdth->name = cpu_to_fdt32(val); \
-	}
-__fdt_set_hdr(magic);
-__fdt_set_hdr(totalsize);
-__fdt_set_hdr(off_dt_struct);
-__fdt_set_hdr(off_dt_strings);
-__fdt_set_hdr(off_mem_rsvmap);
-__fdt_set_hdr(version);
-__fdt_set_hdr(last_comp_version);
-__fdt_set_hdr(boot_cpuid_phys);
-__fdt_set_hdr(size_dt_strings);
-__fdt_set_hdr(size_dt_struct);
-#undef __fdt_set_hdr
-
-/**
- * fdt_check_header - sanity check a device tree or possible device tree
- * @fdt: pointer to data which might be a flattened device tree
- *
- * fdt_check_header() checks that the given buffer contains what
- * appears to be a flattened device tree with sane information in its
- * header.
- *
- * returns:
- *     0, if the buffer appears to contain a valid device tree
- *     -FDT_ERR_BADMAGIC,
- *     -FDT_ERR_BADVERSION,
- *     -FDT_ERR_BADSTATE, standard meanings, as above
- */
-int fdt_check_header(const void *fdt);
-
-/**
- * fdt_move - move a device tree around in memory
- * @fdt: pointer to the device tree to move
- * @buf: pointer to memory where the device is to be moved
- * @bufsize: size of the memory space at buf
- *
- * fdt_move() relocates, if possible, the device tree blob located at
- * fdt to the buffer at buf of size bufsize.  The buffer may overlap
- * with the existing device tree blob at fdt.  Therefore,
- *     fdt_move(fdt, fdt, fdt_totalsize(fdt))
- * should always succeed.
- *
- * returns:
- *     0, on success
- *     -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree
- *     -FDT_ERR_BADMAGIC,
- *     -FDT_ERR_BADVERSION,
- *     -FDT_ERR_BADSTATE, standard meanings
- */
-int fdt_move(const void *fdt, void *buf, int bufsize);
-
-/**********************************************************************/
-/* Read-only functions                                                */
-/**********************************************************************/
-
-/**
- * fdt_string - retrieve a string from the strings block of a device tree
- * @fdt: pointer to the device tree blob
- * @stroffset: offset of the string within the strings block (native endian)
- *
- * fdt_string() retrieves a pointer to a single string from the
- * strings block of the device tree blob at fdt.
- *
- * returns:
- *     a pointer to the string, on success
- *     NULL, if stroffset is out of bounds
- */
-const char *fdt_string(const void *fdt, int stroffset);
-
-/**
- * fdt_get_max_phandle - retrieves the highest phandle in a tree
- * @fdt: pointer to the device tree blob
- *
- * fdt_get_max_phandle retrieves the highest phandle in the given
- * device tree. This will ignore badly formatted phandles, or phandles
- * with a value of 0 or -1.
- *
- * returns:
- *      the highest phandle on success
- *      0, if no phandle was found in the device tree
- *      -1, if an error occurred
- */
-uint32_t fdt_get_max_phandle(const void *fdt);
-
-/**
- * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
- * @fdt: pointer to the device tree blob
- *
- * Returns the number of entries in the device tree blob's memory
- * reservation map.  This does not include the terminating 0,0 entry
- * or any other (0,0) entries reserved for expansion.
- *
- * returns:
- *     the number of entries
- */
-int fdt_num_mem_rsv(const void *fdt);
-
-/**
- * fdt_get_mem_rsv - retrieve one memory reserve map entry
- * @fdt: pointer to the device tree blob
- * @address, @size: pointers to 64-bit variables
- *
- * On success, *address and *size will contain the address and size of
- * the n-th reserve map entry from the device tree blob, in
- * native-endian format.
- *
- * returns:
- *     0, on success
- *     -FDT_ERR_BADMAGIC,
- *     -FDT_ERR_BADVERSION,
- *     -FDT_ERR_BADSTATE, standard meanings
- */
-int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
-
-/**
- * fdt_subnode_offset_namelen - find a subnode based on substring
- * @fdt: pointer to the device tree blob
- * @parentoffset: structure block offset of a node
- * @name: name of the subnode to locate
- * @namelen: number of characters of name to consider
- *
- * Identical to fdt_subnode_offset(), but only examine the first
- * namelen characters of name for matching the subnode name.  This is
- * useful for finding subnodes based on a portion of a larger string,
- * such as a full path.
- */
-#ifndef SWIG /* Not available in Python */
-int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
-			       const char *name, int namelen);
-#endif
-/**
- * fdt_subnode_offset - find a subnode of a given node
- * @fdt: pointer to the device tree blob
- * @parentoffset: structure block offset of a node
- * @name: name of the subnode to locate
- *
- * fdt_subnode_offset() finds a subnode of the node at structure block
- * offset parentoffset with the given name.  name may include a unit
- * address, in which case fdt_subnode_offset() will find the subnode
- * with that unit address, or the unit address may be omitted, in
- * which case fdt_subnode_offset() will find an arbitrary subnode
- * whose name excluding unit address matches the given name.
- *
- * returns:
- *	structure block offset of the requested subnode (>=0), on success
- *	-FDT_ERR_NOTFOUND, if the requested subnode does not exist
- *	-FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE
- *		tag
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_TRUNCATED, standard meanings.
- */
-int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
-
-/**
- * fdt_path_offset_namelen - find a tree node by its full path
- * @fdt: pointer to the device tree blob
- * @path: full path of the node to locate
- * @namelen: number of characters of path to consider
- *
- * Identical to fdt_path_offset(), but only consider the first namelen
- * characters of path as the path name.
- */
-#ifndef SWIG /* Not available in Python */
-int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
-#endif
-
-/**
- * fdt_path_offset - find a tree node by its full path
- * @fdt: pointer to the device tree blob
- * @path: full path of the node to locate
- *
- * fdt_path_offset() finds a node of a given path in the device tree.
- * Each path component may omit the unit address portion, but the
- * results of this are undefined if any such path component is
- * ambiguous (that is if there are multiple nodes at the relevant
- * level matching the given component, differentiated only by unit
- * address).
- *
- * returns:
- *	structure block offset of the node with the requested path (>=0), on
- *		success
- *	-FDT_ERR_BADPATH, given path does not begin with '/' or is invalid
- *	-FDT_ERR_NOTFOUND, if the requested node does not exist
- *      -FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_TRUNCATED, standard meanings.
- */
-int fdt_path_offset(const void *fdt, const char *path);
-
-/**
- * fdt_get_name - retrieve the name of a given node
- * @fdt: pointer to the device tree blob
- * @nodeoffset: structure block offset of the starting node
- * @lenp: pointer to an integer variable (will be overwritten) or NULL
- *
- * fdt_get_name() retrieves the name (including unit address) of the
- * device tree node at structure block offset nodeoffset.  If lenp is
- * non-NULL, the length of this name is also returned, in the integer
- * pointed to by lenp.
- *
- * returns:
- *	pointer to the node's name, on success
- *		If lenp is non-NULL, *lenp contains the length of that name
- *			(>=0)
- *	NULL, on error
- *		if lenp is non-NULL *lenp contains an error code (<0):
- *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE
- *			tag
- *		-FDT_ERR_BADMAGIC,
- *		-FDT_ERR_BADVERSION,
- *		-FDT_ERR_BADSTATE, standard meanings
- */
-const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
-
-/**
- * fdt_first_property_offset - find the offset of a node's first property
- * @fdt: pointer to the device tree blob
- * @nodeoffset: structure block offset of a node
- *
- * fdt_first_property_offset() finds the first property of the node at
- * the given structure block offset.
- *
- * returns:
- *	structure block offset of the property (>=0), on success
- *	-FDT_ERR_NOTFOUND, if the requested node has no properties
- *	-FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag
- *      -FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_TRUNCATED, standard meanings.
- */
-int fdt_first_property_offset(const void *fdt, int nodeoffset);
-
-/**
- * fdt_next_property_offset - step through a node's properties
- * @fdt: pointer to the device tree blob
- * @offset: structure block offset of a property
- *
- * fdt_next_property_offset() finds the property immediately after the
- * one at the given structure block offset.  This will be a property
- * of the same node as the given property.
- *
- * returns:
- *	structure block offset of the next property (>=0), on success
- *	-FDT_ERR_NOTFOUND, if the given property is the last in its node
- *	-FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag
- *      -FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_TRUNCATED, standard meanings.
- */
-int fdt_next_property_offset(const void *fdt, int offset);
-
-/**
- * fdt_for_each_property_offset - iterate over all properties of a node
- *
- * @property_offset:	property offset (int, lvalue)
- * @fdt:		FDT blob (const void *)
- * @node:		node offset (int)
- *
- * This is actually a wrapper around a for loop and would be used like so:
- *
- *	fdt_for_each_property_offset(property, fdt, node) {
- *		Use property
- *		...
- *	}
- *
- *	if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) {
- *		Error handling
- *	}
- *
- * Note that this is implemented as a macro and property is used as
- * iterator in the loop. The node variable can be constant or even a
- * literal.
- */
-#define fdt_for_each_property_offset(property, fdt, node)	\
-	for (property = fdt_first_property_offset(fdt, node);	\
-	     property >= 0;					\
-	     property = fdt_next_property_offset(fdt, property))
-
-/**
- * fdt_get_property_by_offset - retrieve the property at a given offset
- * @fdt: pointer to the device tree blob
- * @offset: offset of the property to retrieve
- * @lenp: pointer to an integer variable (will be overwritten) or NULL
- *
- * fdt_get_property_by_offset() retrieves a pointer to the
- * fdt_property structure within the device tree blob at the given
- * offset.  If lenp is non-NULL, the length of the property value is
- * also returned, in the integer pointed to by lenp.
- *
- * returns:
- *	pointer to the structure representing the property
- *		if lenp is non-NULL, *lenp contains the length of the property
- *		value (>=0)
- *	NULL, on error
- *		if lenp is non-NULL, *lenp contains an error code (<0):
- *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
- *		-FDT_ERR_BADMAGIC,
- *		-FDT_ERR_BADVERSION,
- *		-FDT_ERR_BADSTATE,
- *		-FDT_ERR_BADSTRUCTURE,
- *		-FDT_ERR_TRUNCATED, standard meanings
- */
-const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
-						      int offset,
-						      int *lenp);
-
-/**
- * fdt_get_property_namelen - find a property based on substring
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to find
- * @name: name of the property to find
- * @namelen: number of characters of name to consider
- * @lenp: pointer to an integer variable (will be overwritten) or NULL
- *
- * Identical to fdt_get_property(), but only examine the first namelen
- * characters of name for matching the property name.
- */
-#ifndef SWIG /* Not available in Python */
-const struct fdt_property *fdt_get_property_namelen(const void *fdt,
-						    int nodeoffset,
-						    const char *name,
-						    int namelen, int *lenp);
-#endif
-
-/**
- * fdt_get_property - find a given property in a given node
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to find
- * @name: name of the property to find
- * @lenp: pointer to an integer variable (will be overwritten) or NULL
- *
- * fdt_get_property() retrieves a pointer to the fdt_property
- * structure within the device tree blob corresponding to the property
- * named 'name' of the node at offset nodeoffset.  If lenp is
- * non-NULL, the length of the property value is also returned, in the
- * integer pointed to by lenp.
- *
- * returns:
- *	pointer to the structure representing the property
- *		if lenp is non-NULL, *lenp contains the length of the property
- *		value (>=0)
- *	NULL, on error
- *		if lenp is non-NULL, *lenp contains an error code (<0):
- *		-FDT_ERR_NOTFOUND, node does not have named property
- *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE
- *			tag
- *		-FDT_ERR_BADMAGIC,
- *		-FDT_ERR_BADVERSION,
- *		-FDT_ERR_BADSTATE,
- *		-FDT_ERR_BADSTRUCTURE,
- *		-FDT_ERR_TRUNCATED, standard meanings
- */
-const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset,
-					    const char *name, int *lenp);
-static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
-						      const char *name,
-						      int *lenp)
-{
-	return (struct fdt_property *)(uintptr_t)
-		fdt_get_property(fdt, nodeoffset, name, lenp);
-}
-
-/**
- * fdt_getprop_by_offset - retrieve the value of a property at a given offset
- * @fdt: pointer to the device tree blob
- * @ffset: offset of the property to read
- * @namep: pointer to a string variable (will be overwritten) or NULL
- * @lenp: pointer to an integer variable (will be overwritten) or NULL
- *
- * fdt_getprop_by_offset() retrieves a pointer to the value of the
- * property at structure block offset 'offset' (this will be a pointer
- * to within the device blob itself, not a copy of the value).  If
- * lenp is non-NULL, the length of the property value is also
- * returned, in the integer pointed to by lenp.  If namep is non-NULL,
- * the property's namne will also be returned in the char * pointed to
- * by namep (this will be a pointer to within the device tree's string
- * block, not a new copy of the name).
- *
- * returns:
- *	pointer to the property's value
- *		if lenp is non-NULL, *lenp contains the length of the property
- *		value (>=0)
- *		if namep is non-NULL *namep contiains a pointer to the property
- *		name.
- *	NULL, on error
- *		if lenp is non-NULL, *lenp contains an error code (<0):
- *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
- *		-FDT_ERR_BADMAGIC,
- *		-FDT_ERR_BADVERSION,
- *		-FDT_ERR_BADSTATE,
- *		-FDT_ERR_BADSTRUCTURE,
- *		-FDT_ERR_TRUNCATED, standard meanings
- */
-#ifndef SWIG /* This function is not useful in Python */
-const void *fdt_getprop_by_offset(const void *fdt, int offset,
-				  const char **namep, int *lenp);
-#endif
-
-/**
- * fdt_getprop_namelen - get property value based on substring
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to find
- * @name: name of the property to find
- * @namelen: number of characters of name to consider
- * @lenp: pointer to an integer variable (will be overwritten) or NULL
- *
- * Identical to fdt_getprop(), but only examine the first namelen
- * characters of name for matching the property name.
- */
-#ifndef SWIG /* Not available in Python */
-const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
-				const char *name, int namelen, int *lenp);
-static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
-					  const char *name, int namelen,
-					  int *lenp)
-{
-	return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
-						      namelen, lenp);
-}
-#endif
-
-/**
- * fdt_getprop - retrieve the value of a given property
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to find
- * @name: name of the property to find
- * @lenp: pointer to an integer variable (will be overwritten) or NULL
- *
- * fdt_getprop() retrieves a pointer to the value of the property
- * named 'name' of the node at offset nodeoffset (this will be a
- * pointer to within the device blob itself, not a copy of the value).
- * If lenp is non-NULL, the length of the property value is also
- * returned, in the integer pointed to by lenp.
- *
- * returns:
- *	pointer to the property's value
- *		if lenp is non-NULL, *lenp contains the length of the property
- *		value (>=0)
- *	NULL, on error
- *		if lenp is non-NULL, *lenp contains an error code (<0):
- *		-FDT_ERR_NOTFOUND, node does not have named property
- *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE
- *			tag
- *		-FDT_ERR_BADMAGIC,
- *		-FDT_ERR_BADVERSION,
- *		-FDT_ERR_BADSTATE,
- *		-FDT_ERR_BADSTRUCTURE,
- *		-FDT_ERR_TRUNCATED, standard meanings
- */
-const void *fdt_getprop(const void *fdt, int nodeoffset,
-			const char *name, int *lenp);
-static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
-				  const char *name, int *lenp)
-{
-	return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp);
-}
-
-/**
- * fdt_get_phandle - retrieve the phandle of a given node
- * @fdt: pointer to the device tree blob
- * @nodeoffset: structure block offset of the node
- *
- * fdt_get_phandle() retrieves the phandle of the device tree node at
- * structure block offset nodeoffset.
- *
- * returns:
- *	the phandle of the node at nodeoffset, on success (!= 0, != -1)
- *	0, if the node has no phandle, or another error occurs
- */
-uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
-
-/**
- * fdt_get_alias_namelen - get alias based on substring
- * @fdt: pointer to the device tree blob
- * @name: name of the alias th look up
- * @namelen: number of characters of name to consider
- *
- * Identical to fdt_get_alias(), but only examine the first namelen
- * characters of name for matching the alias name.
- */
-#ifndef SWIG /* Not available in Python */
-const char *fdt_get_alias_namelen(const void *fdt,
-				  const char *name, int namelen);
-#endif
-
-/**
- * fdt_get_alias - retrieve the path referenced by a given alias
- * @fdt: pointer to the device tree blob
- * @name: name of the alias th look up
- *
- * fdt_get_alias() retrieves the value of a given alias.  That is, the
- * value of the property named 'name' in the node /aliases.
- *
- * returns:
- *	a pointer to the expansion of the alias named 'name', if it exists
- *	NULL, if the given alias or the /aliases node does not exist
- */
-const char *fdt_get_alias(const void *fdt, const char *name);
-
-/**
- * fdt_get_path - determine the full path of a node
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose path to find
- * @buf: character buffer to contain the returned path (will be overwritten)
- * @buflen: size of the character buffer at buf
- *
- * fdt_get_path() computes the full path of the node at offset
- * nodeoffset, and records that path in the buffer at buf.
- *
- * NOTE: This function is expensive, as it must scan the device tree
- * structure from the start to nodeoffset.
- *
- * returns:
- *	0, on success
- *		buf contains the absolute path of the node at
- *		nodeoffset, as a NUL-terminated string.
- *	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
- *	-FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1)
- *		characters and will not fit in the given buffer.
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE, standard meanings
- */
-int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
-
-/**
- * fdt_supernode_atdepth_offset - find a specific ancestor of a node
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose parent to find
- * @supernodedepth: depth of the ancestor to find
- * @nodedepth: pointer to an integer variable (will be overwritten) or NULL
- *
- * fdt_supernode_atdepth_offset() finds an ancestor of the given node
- * at a specific depth from the root (where the root itself has depth
- * 0, its immediate subnodes depth 1 and so forth).  So
- *	fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL);
- * will always return 0, the offset of the root node.  If the node at
- * nodeoffset has depth D, then:
- *	fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL);
- * will return nodeoffset itself.
- *
- * NOTE: This function is expensive, as it must scan the device tree
- * structure from the start to nodeoffset.
- *
- * returns:
- *	structure block offset of the node at node offset's ancestor
- *		of depth supernodedepth (>=0), on success
- *	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
- *	-FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of
- *		nodeoffset
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE, standard meanings
- */
-int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
-				 int supernodedepth, int *nodedepth);
-
-/**
- * fdt_node_depth - find the depth of a given node
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose parent to find
- *
- * fdt_node_depth() finds the depth of a given node.  The root node
- * has depth 0, its immediate subnodes depth 1 and so forth.
- *
- * NOTE: This function is expensive, as it must scan the device tree
- * structure from the start to nodeoffset.
- *
- * returns:
- *	depth of the node at nodeoffset (>=0), on success
- *	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE, standard meanings
- */
-int fdt_node_depth(const void *fdt, int nodeoffset);
-
-/**
- * fdt_parent_offset - find the parent of a given node
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose parent to find
- *
- * fdt_parent_offset() locates the parent node of a given node (that
- * is, it finds the offset of the node which contains the node at
- * nodeoffset as a subnode).
- *
- * NOTE: This function is expensive, as it must scan the device tree
- * structure from the start to nodeoffset, *twice*.
- *
- * returns:
- *	structure block offset of the parent of the node at nodeoffset
- *		(>=0), on success
- *	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE, standard meanings
- */
-int fdt_parent_offset(const void *fdt, int nodeoffset);
-
-/**
- * fdt_node_offset_by_prop_value - find nodes with a given property value
- * @fdt: pointer to the device tree blob
- * @startoffset: only find nodes after this offset
- * @propname: property name to check
- * @propval: property value to search for
- * @proplen: length of the value in propval
- *
- * fdt_node_offset_by_prop_value() returns the offset of the first
- * node after startoffset, which has a property named propname whose
- * value is of length proplen and has value equal to propval; or if
- * startoffset is -1, the very first such node in the tree.
- *
- * To iterate through all nodes matching the criterion, the following
- * idiom can be used:
- *	offset = fdt_node_offset_by_prop_value(fdt, -1, propname,
- *					       propval, proplen);
- *	while (offset != -FDT_ERR_NOTFOUND) {
- *		// other code here
- *		offset = fdt_node_offset_by_prop_value(fdt, offset, propname,
- *						       propval, proplen);
- *	}
- *
- * Note the -1 in the first call to the function, if 0 is used here
- * instead, the function will never locate the root node, even if it
- * matches the criterion.
- *
- * returns:
- *	structure block offset of the located node (>= 0, >startoffset),
- *		 on success
- *	-FDT_ERR_NOTFOUND, no node matching the criterion exists in the
- *		tree after startoffset
- *	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE, standard meanings
- */
-int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
-				  const char *propname,
-				  const void *propval, int proplen);
-
-/**
- * fdt_node_offset_by_phandle - find the node with a given phandle
- * @fdt: pointer to the device tree blob
- * @phandle: phandle value
- *
- * fdt_node_offset_by_phandle() returns the offset of the node
- * which has the given phandle value.  If there is more than one node
- * in the tree with the given phandle (an invalid tree), results are
- * undefined.
- *
- * returns:
- *	structure block offset of the located node (>= 0), on success
- *	-FDT_ERR_NOTFOUND, no node with that phandle exists
- *	-FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1)
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE, standard meanings
- */
-int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
-
-/**
- * fdt_node_check_compatible: check a node's compatible property
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of a tree node
- * @compatible: string to match against
- *
- *
- * fdt_node_check_compatible() returns 0 if the given node contains a
- * 'compatible' property with the given string as one of its elements,
- * it returns non-zero otherwise, or on error.
- *
- * returns:
- *	0, if the node has a 'compatible' property listing the given string
- *	1, if the node has a 'compatible' property, but it does not list
- *		the given string
- *	-FDT_ERR_NOTFOUND, if the given node has no 'compatible' property
- *	-FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE, standard meanings
- */
-int fdt_node_check_compatible(const void *fdt, int nodeoffset,
-			      const char *compatible);
-
-/**
- * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value
- * @fdt: pointer to the device tree blob
- * @startoffset: only find nodes after this offset
- * @compatible: 'compatible' string to match against
- *
- * fdt_node_offset_by_compatible() returns the offset of the first
- * node after startoffset, which has a 'compatible' property which
- * lists the given compatible string; or if startoffset is -1, the
- * very first such node in the tree.
- *
- * To iterate through all nodes matching the criterion, the following
- * idiom can be used:
- *	offset = fdt_node_offset_by_compatible(fdt, -1, compatible);
- *	while (offset != -FDT_ERR_NOTFOUND) {
- *		// other code here
- *		offset = fdt_node_offset_by_compatible(fdt, offset, compatible);
- *	}
- *
- * Note the -1 in the first call to the function, if 0 is used here
- * instead, the function will never locate the root node, even if it
- * matches the criterion.
- *
- * returns:
- *	structure block offset of the located node (>= 0, >startoffset),
- *		 on success
- *	-FDT_ERR_NOTFOUND, no node matching the criterion exists in the
- *		tree after startoffset
- *	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE, standard meanings
- */
-int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
-				  const char *compatible);
-
-/**
- * fdt_stringlist_contains - check a string list property for a string
- * @strlist: Property containing a list of strings to check
- * @listlen: Length of property
- * @str: String to search for
- *
- * This is a utility function provided for convenience. The list contains
- * one or more strings, each terminated by \0, as is found in a device tree
- * "compatible" property.
- *
- * @return: 1 if the string is found in the list, 0 not found, or invalid list
- */
-int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
-
-/**
- * fdt_stringlist_count - count the number of strings in a string list
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of a tree node
- * @property: name of the property containing the string list
- * @return:
- *   the number of strings in the given property
- *   -FDT_ERR_BADVALUE if the property value is not NUL-terminated
- *   -FDT_ERR_NOTFOUND if the property does not exist
- */
-int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property);
-
-/**
- * fdt_stringlist_search - find a string in a string list and return its index
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of a tree node
- * @property: name of the property containing the string list
- * @string: string to look up in the string list
- *
- * Note that it is possible for this function to succeed on property values
- * that are not NUL-terminated. That's because the function will stop after
- * finding the first occurrence of @string. This can for example happen with
- * small-valued cell properties, such as #address-cells, when searching for
- * the empty string.
- *
- * @return:
- *   the index of the string in the list of strings
- *   -FDT_ERR_BADVALUE if the property value is not NUL-terminated
- *   -FDT_ERR_NOTFOUND if the property does not exist or does not contain
- *                     the given string
- */
-int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
-			  const char *string);
-
-/**
- * fdt_stringlist_get() - obtain the string at a given index in a string list
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of a tree node
- * @property: name of the property containing the string list
- * @index: index of the string to return
- * @lenp: return location for the string length or an error code on failure
- *
- * Note that this will successfully extract strings from properties with
- * non-NUL-terminated values. For example on small-valued cell properties
- * this function will return the empty string.
- *
- * If non-NULL, the length of the string (on success) or a negative error-code
- * (on failure) will be stored in the integer pointer to by lenp.
- *
- * @return:
- *   A pointer to the string at the given index in the string list or NULL on
- *   failure. On success the length of the string will be stored in the memory
- *   location pointed to by the lenp parameter, if non-NULL. On failure one of
- *   the following negative error codes will be returned in the lenp parameter
- *   (if non-NULL):
- *     -FDT_ERR_BADVALUE if the property value is not NUL-terminated
- *     -FDT_ERR_NOTFOUND if the property does not exist
- */
-const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
-			       const char *property, int index,
-			       int *lenp);
-
-/**********************************************************************/
-/* Read-only functions (addressing related)                           */
-/**********************************************************************/
-
-/**
- * FDT_MAX_NCELLS - maximum value for #address-cells and #size-cells
- *
- * This is the maximum value for #address-cells, #size-cells and
- * similar properties that will be processed by libfdt.  IEE1275
- * requires that OF implementations handle values up to 4.
- * Implementations may support larger values, but in practice higher
- * values aren't used.
- */
-#define FDT_MAX_NCELLS		4
-
-/**
- * fdt_address_cells - retrieve address size for a bus represented in the tree
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node to find the address size for
- *
- * When the node has a valid #address-cells property, returns its value.
- *
- * returns:
- *	0 <= n < FDT_MAX_NCELLS, on success
- *      2, if the node has no #address-cells property
- *      -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
- *		#address-cells property
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-int fdt_address_cells(const void *fdt, int nodeoffset);
-
-/**
- * fdt_size_cells - retrieve address range size for a bus represented in the
- *                  tree
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node to find the address range size for
- *
- * When the node has a valid #size-cells property, returns its value.
- *
- * returns:
- *	0 <= n < FDT_MAX_NCELLS, on success
- *      2, if the node has no #address-cells property
- *      -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
- *		#size-cells property
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-int fdt_size_cells(const void *fdt, int nodeoffset);
-
-
-/**********************************************************************/
-/* Write-in-place functions                                           */
-/**********************************************************************/
-
-/**
- * fdt_setprop_inplace_namelen_partial - change a property's value,
- *                                       but not its size
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to change
- * @name: name of the property to change
- * @namelen: number of characters of name to consider
- * @idx: index of the property to change in the array
- * @val: pointer to data to replace the property value with
- * @len: length of the property value
- *
- * Identical to fdt_setprop_inplace(), but modifies the given property
- * starting from the given index, and using only the first characters
- * of the name. It is useful when you want to manipulate only one value of
- * an array and you have a string that doesn't end with \0.
- */
-#ifndef SWIG /* Not available in Python */
-int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
-					const char *name, int namelen,
-					uint32_t idx, const void *val,
-					int len);
-#endif
-
-/**
- * fdt_setprop_inplace - change a property's value, but not its size
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to change
- * @name: name of the property to change
- * @val: pointer to data to replace the property value with
- * @len: length of the property value
- *
- * fdt_setprop_inplace() replaces the value of a given property with
- * the data in val, of length len.  This function cannot change the
- * size of a property, and so will only work if len is equal to the
- * current length of the property.
- *
- * This function will alter only the bytes in the blob which contain
- * the given property value, and will not alter or move any other part
- * of the tree.
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_NOSPACE, if len is not equal to the property's current length
- *	-FDT_ERR_NOTFOUND, node does not have the named property
- *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-#ifndef SWIG /* Not available in Python */
-int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
-			const void *val, int len);
-#endif
-
-/**
- * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to change
- * @name: name of the property to change
- * @val: 32-bit integer value to replace the property with
- *
- * fdt_setprop_inplace_u32() replaces the value of a given property
- * with the 32-bit integer value in val, converting val to big-endian
- * if necessary.  This function cannot change the size of a property,
- * and so will only work if the property already exists and has length
- * 4.
- *
- * This function will alter only the bytes in the blob which contain
- * the given property value, and will not alter or move any other part
- * of the tree.
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_NOSPACE, if the property's length is not equal to 4
- *	-FDT_ERR_NOTFOUND, node does not have the named property
- *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset,
-					  const char *name, uint32_t val)
-{
-	fdt32_t tmp = cpu_to_fdt32(val);
-	return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp));
-}
-
-/**
- * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to change
- * @name: name of the property to change
- * @val: 64-bit integer value to replace the property with
- *
- * fdt_setprop_inplace_u64() replaces the value of a given property
- * with the 64-bit integer value in val, converting val to big-endian
- * if necessary.  This function cannot change the size of a property,
- * and so will only work if the property already exists and has length
- * 8.
- *
- * This function will alter only the bytes in the blob which contain
- * the given property value, and will not alter or move any other part
- * of the tree.
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_NOSPACE, if the property's length is not equal to 8
- *	-FDT_ERR_NOTFOUND, node does not have the named property
- *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset,
-					  const char *name, uint64_t val)
-{
-	fdt64_t tmp = cpu_to_fdt64(val);
-	return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp));
-}
-
-/**
- * fdt_setprop_inplace_cell - change the value of a single-cell property
- *
- * This is an alternative name for fdt_setprop_inplace_u32()
- */
-static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
-					   const char *name, uint32_t val)
-{
-	return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val);
-}
-
-/**
- * fdt_nop_property - replace a property with nop tags
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to nop
- * @name: name of the property to nop
- *
- * fdt_nop_property() will replace a given property's representation
- * in the blob with FDT_NOP tags, effectively removing it from the
- * tree.
- *
- * This function will alter only the bytes in the blob which contain
- * the property, and will not alter or move any other part of the
- * tree.
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_NOTFOUND, node does not have the named property
- *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-int fdt_nop_property(void *fdt, int nodeoffset, const char *name);
-
-/**
- * fdt_nop_node - replace a node (subtree) with nop tags
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node to nop
- *
- * fdt_nop_node() will replace a given node's representation in the
- * blob, including all its subnodes, if any, with FDT_NOP tags,
- * effectively removing it from the tree.
- *
- * This function will alter only the bytes in the blob which contain
- * the node and its properties and subnodes, and will not alter or
- * move any other part of the tree.
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-int fdt_nop_node(void *fdt, int nodeoffset);
-
-/**********************************************************************/
-/* Sequential write functions                                         */
-/**********************************************************************/
-
-int fdt_create(void *buf, int bufsize);
-int fdt_resize(void *fdt, void *buf, int bufsize);
-int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
-int fdt_finish_reservemap(void *fdt);
-int fdt_begin_node(void *fdt, const char *name);
-int fdt_property(void *fdt, const char *name, const void *val, int len);
-static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val)
-{
-	fdt32_t tmp = cpu_to_fdt32(val);
-	return fdt_property(fdt, name, &tmp, sizeof(tmp));
-}
-static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val)
-{
-	fdt64_t tmp = cpu_to_fdt64(val);
-	return fdt_property(fdt, name, &tmp, sizeof(tmp));
-}
-static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
-{
-	return fdt_property_u32(fdt, name, val);
-}
-
-/**
- * fdt_property_placeholder - add a new property and return a ptr to its value
- *
- * @fdt: pointer to the device tree blob
- * @name: name of property to add
- * @len: length of property value in bytes
- * @valp: returns a pointer to where where the value should be placed
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_NOSPACE, standard meanings
- */
-int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp);
-
-#define fdt_property_string(fdt, name, str) \
-	fdt_property(fdt, name, str, strlen(str)+1)
-int fdt_end_node(void *fdt);
-int fdt_finish(void *fdt);
-
-/**********************************************************************/
-/* Read-write functions                                               */
-/**********************************************************************/
-
-int fdt_create_empty_tree(void *buf, int bufsize);
-int fdt_open_into(const void *fdt, void *buf, int bufsize);
-int fdt_pack(void *fdt);
-
-/**
- * fdt_add_mem_rsv - add one memory reserve map entry
- * @fdt: pointer to the device tree blob
- * @address, @size: 64-bit values (native endian)
- *
- * Adds a reserve map entry to the given blob reserving a region at
- * address address of length size.
- *
- * This function will insert data into the reserve map and will
- * therefore change the indexes of some entries in the table.
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
- *		contain the new reservation entry
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size);
-
-/**
- * fdt_del_mem_rsv - remove a memory reserve map entry
- * @fdt: pointer to the device tree blob
- * @n: entry to remove
- *
- * fdt_del_mem_rsv() removes the n-th memory reserve map entry from
- * the blob.
- *
- * This function will delete data from the reservation table and will
- * therefore change the indexes of some entries in the table.
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there
- *		are less than n+1 reserve map entries)
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-int fdt_del_mem_rsv(void *fdt, int n);
-
-/**
- * fdt_set_name - change the name of a given node
- * @fdt: pointer to the device tree blob
- * @nodeoffset: structure block offset of a node
- * @name: name to give the node
- *
- * fdt_set_name() replaces the name (including unit address, if any)
- * of the given node with the given string.  NOTE: this function can't
- * efficiently check if the new name is unique amongst the given
- * node's siblings; results are undefined if this function is invoked
- * with a name equal to one of the given node's siblings.
- *
- * This function may insert or delete data from the blob, and will
- * therefore change the offsets of some existing nodes.
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob
- *		to contain the new name
- *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE, standard meanings
- */
-int fdt_set_name(void *fdt, int nodeoffset, const char *name);
-
-/**
- * fdt_setprop - create or change a property
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to change
- * @name: name of the property to change
- * @val: pointer to data to set the property value to
- * @len: length of the property value
- *
- * fdt_setprop() sets the value of the named property in the given
- * node to the given value and length, creating the property if it
- * does not already exist.
- *
- * This function may insert or delete data from the blob, and will
- * therefore change the offsets of some existing nodes.
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
- *		contain the new property value
- *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-int fdt_setprop(void *fdt, int nodeoffset, const char *name,
-		const void *val, int len);
-
-/**
- * fdt_setprop _placeholder - allocate space for a property
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to change
- * @name: name of the property to change
- * @len: length of the property value
- * @prop_data: return pointer to property data
- *
- * fdt_setprop_placeholer() allocates the named property in the given node.
- * If the property exists it is resized. In either case a pointer to the
- * property data is returned.
- *
- * This function may insert or delete data from the blob, and will
- * therefore change the offsets of some existing nodes.
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
- *		contain the new property value
- *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
-			    int len, void **prop_data);
-
-/**
- * fdt_setprop_u32 - set a property to a 32-bit integer
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to change
- * @name: name of the property to change
- * @val: 32-bit integer value for the property (native endian)
- *
- * fdt_setprop_u32() sets the value of the named property in the given
- * node to the given 32-bit integer value (converting to big-endian if
- * necessary), or creates a new property with that value if it does
- * not already exist.
- *
- * This function may insert or delete data from the blob, and will
- * therefore change the offsets of some existing nodes.
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
- *		contain the new property value
- *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name,
-				  uint32_t val)
-{
-	fdt32_t tmp = cpu_to_fdt32(val);
-	return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
-}
-
-/**
- * fdt_setprop_u64 - set a property to a 64-bit integer
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to change
- * @name: name of the property to change
- * @val: 64-bit integer value for the property (native endian)
- *
- * fdt_setprop_u64() sets the value of the named property in the given
- * node to the given 64-bit integer value (converting to big-endian if
- * necessary), or creates a new property with that value if it does
- * not already exist.
- *
- * This function may insert or delete data from the blob, and will
- * therefore change the offsets of some existing nodes.
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
- *		contain the new property value
- *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name,
-				  uint64_t val)
-{
-	fdt64_t tmp = cpu_to_fdt64(val);
-	return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
-}
-
-/**
- * fdt_setprop_cell - set a property to a single cell value
- *
- * This is an alternative name for fdt_setprop_u32()
- */
-static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
-				   uint32_t val)
-{
-	return fdt_setprop_u32(fdt, nodeoffset, name, val);
-}
-
-/**
- * fdt_setprop_string - set a property to a string value
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to change
- * @name: name of the property to change
- * @str: string value for the property
- *
- * fdt_setprop_string() sets the value of the named property in the
- * given node to the given string value (using the length of the
- * string to determine the new length of the property), or creates a
- * new property with that value if it does not already exist.
- *
- * This function may insert or delete data from the blob, and will
- * therefore change the offsets of some existing nodes.
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
- *		contain the new property value
- *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-#define fdt_setprop_string(fdt, nodeoffset, name, str) \
-	fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
-
-
-/**
- * fdt_setprop_empty - set a property to an empty value
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to change
- * @name: name of the property to change
- *
- * fdt_setprop_empty() sets the value of the named property in the
- * given node to an empty (zero length) value, or creates a new empty
- * property if it does not already exist.
- *
- * This function may insert or delete data from the blob, and will
- * therefore change the offsets of some existing nodes.
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
- *		contain the new property value
- *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-#define fdt_setprop_empty(fdt, nodeoffset, name) \
-	fdt_setprop((fdt), (nodeoffset), (name), NULL, 0)
-
-/**
- * fdt_appendprop - append to or create a property
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to change
- * @name: name of the property to append to
- * @val: pointer to data to append to the property value
- * @len: length of the data to append to the property value
- *
- * fdt_appendprop() appends the value to the named property in the
- * given node, creating the property if it does not already exist.
- *
- * This function may insert data into the blob, and will therefore
- * change the offsets of some existing nodes.
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
- *		contain the new property value
- *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
-		   const void *val, int len);
-
-/**
- * fdt_appendprop_u32 - append a 32-bit integer value to a property
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to change
- * @name: name of the property to change
- * @val: 32-bit integer value to append to the property (native endian)
- *
- * fdt_appendprop_u32() appends the given 32-bit integer value
- * (converting to big-endian if necessary) to the value of the named
- * property in the given node, or creates a new property with that
- * value if it does not already exist.
- *
- * This function may insert data into the blob, and will therefore
- * change the offsets of some existing nodes.
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
- *		contain the new property value
- *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-static inline int fdt_appendprop_u32(void *fdt, int nodeoffset,
-				     const char *name, uint32_t val)
-{
-	fdt32_t tmp = cpu_to_fdt32(val);
-	return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
-}
-
-/**
- * fdt_appendprop_u64 - append a 64-bit integer value to a property
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to change
- * @name: name of the property to change
- * @val: 64-bit integer value to append to the property (native endian)
- *
- * fdt_appendprop_u64() appends the given 64-bit integer value
- * (converting to big-endian if necessary) to the value of the named
- * property in the given node, or creates a new property with that
- * value if it does not already exist.
- *
- * This function may insert data into the blob, and will therefore
- * change the offsets of some existing nodes.
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
- *		contain the new property value
- *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-static inline int fdt_appendprop_u64(void *fdt, int nodeoffset,
-				     const char *name, uint64_t val)
-{
-	fdt64_t tmp = cpu_to_fdt64(val);
-	return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
-}
-
-/**
- * fdt_appendprop_cell - append a single cell value to a property
- *
- * This is an alternative name for fdt_appendprop_u32()
- */
-static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
-				      const char *name, uint32_t val)
-{
-	return fdt_appendprop_u32(fdt, nodeoffset, name, val);
-}
-
-/**
- * fdt_appendprop_string - append a string to a property
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to change
- * @name: name of the property to change
- * @str: string value to append to the property
- *
- * fdt_appendprop_string() appends the given string to the value of
- * the named property in the given node, or creates a new property
- * with that value if it does not already exist.
- *
- * This function may insert data into the blob, and will therefore
- * change the offsets of some existing nodes.
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
- *		contain the new property value
- *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-#define fdt_appendprop_string(fdt, nodeoffset, name, str) \
-	fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
-
-/**
- * fdt_delprop - delete a property
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to nop
- * @name: name of the property to nop
- *
- * fdt_del_property() will delete the given property.
- *
- * This function will delete data from the blob, and will therefore
- * change the offsets of some existing nodes.
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_NOTFOUND, node does not have the named property
- *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-int fdt_delprop(void *fdt, int nodeoffset, const char *name);
-
-/**
- * fdt_add_subnode_namelen - creates a new node based on substring
- * @fdt: pointer to the device tree blob
- * @parentoffset: structure block offset of a node
- * @name: name of the subnode to locate
- * @namelen: number of characters of name to consider
- *
- * Identical to fdt_add_subnode(), but use only the first namelen
- * characters of name as the name of the new node.  This is useful for
- * creating subnodes based on a portion of a larger string, such as a
- * full path.
- */
-#ifndef SWIG /* Not available in Python */
-int fdt_add_subnode_namelen(void *fdt, int parentoffset,
-			    const char *name, int namelen);
-#endif
-
-/**
- * fdt_add_subnode - creates a new node
- * @fdt: pointer to the device tree blob
- * @parentoffset: structure block offset of a node
- * @name: name of the subnode to locate
- *
- * fdt_add_subnode() creates a new node as a subnode of the node at
- * structure block offset parentoffset, with the given name (which
- * should include the unit address, if any).
- *
- * This function will insert data into the blob, and will therefore
- * change the offsets of some existing nodes.
-
- * returns:
- *	structure block offset of the created nodeequested subnode (>=0), on
- *		success
- *	-FDT_ERR_NOTFOUND, if the requested subnode does not exist
- *	-FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE
- *		tag
- *	-FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of
- *		the given name
- *	-FDT_ERR_NOSPACE, if there is insufficient free space in the
- *		blob to contain the new node
- *	-FDT_ERR_NOSPACE
- *	-FDT_ERR_BADLAYOUT
- *      -FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_TRUNCATED, standard meanings.
- */
-int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
-
-/**
- * fdt_del_node - delete a node (subtree)
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node to nop
- *
- * fdt_del_node() will remove the given node, including all its
- * subnodes if any, from the blob.
- *
- * This function will delete data from the blob, and will therefore
- * change the offsets of some existing nodes.
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-int fdt_del_node(void *fdt, int nodeoffset);
-
-/**
- * fdt_overlay_apply - Applies a DT overlay on a base DT
- * @fdt: pointer to the base device tree blob
- * @fdto: pointer to the device tree overlay blob
- *
- * fdt_overlay_apply() will apply the given device tree overlay on the
- * given base device tree.
- *
- * Expect the base device tree to be modified, even if the function
- * returns an error.
- *
- * returns:
- *	0, on success
- *	-FDT_ERR_NOSPACE, there's not enough space in the base device tree
- *	-FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or
- *		properties in the base DT
- *	-FDT_ERR_BADPHANDLE,
- *	-FDT_ERR_BADOVERLAY,
- *	-FDT_ERR_NOPHANDLES,
- *	-FDT_ERR_INTERNAL,
- *	-FDT_ERR_BADLAYOUT,
- *	-FDT_ERR_BADMAGIC,
- *	-FDT_ERR_BADOFFSET,
- *	-FDT_ERR_BADPATH,
- *	-FDT_ERR_BADVERSION,
- *	-FDT_ERR_BADSTRUCTURE,
- *	-FDT_ERR_BADSTATE,
- *	-FDT_ERR_TRUNCATED, standard meanings
- */
-int fdt_overlay_apply(void *fdt, void *fdto);
-
-/**********************************************************************/
-/* Debugging / informational functions                                */
-/**********************************************************************/
-
-#ifndef SWIG /* Not available in Python */
-const char *fdt_strerror(int errval);
-
-/**
- * fdt_remove_unused_strings() - Remove any unused strings from an FDT
- *
- * This creates a new device tree in @new with unused strings removed. The
- * called can then use fdt_pack() to minimise the space consumed.
- *
- * @old:	Old device tree blog
- * @new:	Place to put new device tree blob, which must be as large as
- *		@old
- * @return
- *	0, on success
- *	-FDT_ERR_BADOFFSET, corrupt device tree
- *	-FDT_ERR_NOSPACE, out of space, which should not happen unless there
- *		is something very wrong with the device tree input
- */
-int fdt_remove_unused_strings(const void *old, void *new);
-
-struct fdt_region {
-	int offset;
-	int size;
-};
-
-/*
- * Flags for fdt_find_regions()
- *
- * Add a region for the string table (always the last region)
- */
-#define FDT_REG_ADD_STRING_TAB		(1 << 0)
-
-/*
- * Add all supernodes of a matching node/property, useful for creating a
- * valid subset tree
- */
-#define FDT_REG_SUPERNODES		(1 << 1)
-
-/* Add the FDT_BEGIN_NODE tags of subnodes, including their names */
-#define FDT_REG_DIRECT_SUBNODES	(1 << 2)
-
-/* Add all subnodes of a matching node */
-#define FDT_REG_ALL_SUBNODES		(1 << 3)
-
-/* Add a region for the mem_rsvmap table (always the first region) */
-#define FDT_REG_ADD_MEM_RSVMAP		(1 << 4)
-
-/* Indicates what an fdt part is (node, property, value) */
-#define FDT_IS_NODE			(1 << 0)
-#define FDT_IS_PROP			(1 << 1)
-#define FDT_IS_VALUE			(1 << 2)	/* not supported */
-#define FDT_IS_COMPAT			(1 << 3)	/* used internally */
-#define FDT_NODE_HAS_PROP		(1 << 4)	/* node contains prop */
-
-#define FDT_ANY_GLOBAL		(FDT_IS_NODE | FDT_IS_PROP | FDT_IS_VALUE | \
-					FDT_IS_COMPAT)
-#define FDT_IS_ANY			0x1f		/* all the above */
-
-/* We set a reasonable limit on the number of nested nodes */
-#define FDT_MAX_DEPTH			32
-
-/* Decribes what we want to include from the current tag */
-enum want_t {
-	WANT_NOTHING,
-	WANT_NODES_ONLY,		/* No properties */
-	WANT_NODES_AND_PROPS,		/* Everything for one level */
-	WANT_ALL_NODES_AND_PROPS	/* Everything for all levels */
-};
-
-/* Keeps track of the state at parent nodes */
-struct fdt_subnode_stack {
-	int offset;		/* Offset of node */
-	enum want_t want;	/* The 'want' value here */
-	int included;		/* 1 if we included this node, 0 if not */
-};
-
-struct fdt_region_ptrs {
-	int depth;			/* Current tree depth */
-	int done;			/* What we have completed scanning */
-	enum want_t want;		/* What we are currently including */
-	char *end;			/* Pointer to end of full node path */
-	int nextoffset;			/* Next node offset to check */
-};
-
-/* The state of our finding algortihm */
-struct fdt_region_state {
-	struct fdt_subnode_stack stack[FDT_MAX_DEPTH];	/* node stack */
-	struct fdt_region *region;	/* Contains list of regions found */
-	int count;			/* Numnber of regions found */
-	const void *fdt;		/* FDT blob */
-	int max_regions;		/* Maximum regions to find */
-	int can_merge;		/* 1 if we can merge with previous region */
-	int start;			/* Start position of current region */
-	struct fdt_region_ptrs ptrs;	/* Pointers for what we are up to */
-};
-
-/**
- * fdt_find_regions() - find regions in device tree
- *
- * Given a list of nodes to include and properties to exclude, find
- * the regions of the device tree which describe those included parts.
- *
- * The intent is to get a list of regions which will be invariant provided
- * those parts are invariant. For example, if you request a list of regions
- * for all nodes but exclude the property "data", then you will get the
- * same region contents regardless of any change to "data" properties.
- *
- * This function can be used to produce a byte-stream to send to a hashing
- * function to verify that critical parts of the FDT have not changed.
- *
- * Nodes which are given in 'inc' are included in the region list, as
- * are the names of the immediate subnodes nodes (but not the properties
- * or subnodes of those subnodes).
- *
- * For eaxample "/" means to include the root node, all root properties
- * and the FDT_BEGIN_NODE and FDT_END_NODE of all subnodes of /. The latter
- * ensures that we capture the names of the subnodes. In a hashing situation
- * it prevents the root node from changing at all Any change to non-excluded
- * properties, names of subnodes or number of subnodes would be detected.
- *
- * When used with FITs this provides the ability to hash and sign parts of
- * the FIT based on different configurations in the FIT. Then it is
- * impossible to change anything about that configuration (include images
- * attached to the configuration), but it may be possible to add new
- * configurations, new images or new signatures within the existing
- * framework.
- *
- * Adding new properties to a device tree may result in the string table
- * being extended (if the new property names are different from those
- * already added). This function can optionally include a region for
- * the string table so that this can be part of the hash too.
- *
- * The device tree header is not included in the list.
- *
- * @fdt:	Device tree to check
- * @inc:	List of node paths to included
- * @inc_count:	Number of node paths in list
- * @exc_prop:	List of properties names to exclude
- * @exc_prop_count:	Number of properties in exclude list
- * @region:	Returns list of regions
- * @max_region:	Maximum length of region list
- * @path:	Pointer to a temporary string for the function to use for
- *		building path names
- * @path_len:	Length of path, must be large enough to hold the longest
- *		path in the tree
- * @add_string_tab:	1 to add a region for the string table
- * @return number of regions in list. If this is >max_regions then the
- * region array was exhausted. You should increase max_regions and try
- * the call again.
- */
-int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
-		     char * const exc_prop[], int exc_prop_count,
-		     struct fdt_region region[], int max_regions,
-		     char *path, int path_len, int add_string_tab);
-
-/**
- * fdt_first_region() - find regions in device tree
- *
- * Given a nodes and properties to include and properties to exclude, find
- * the regions of the device tree which describe those included parts.
- *
- * The use for this function is twofold. Firstly it provides a convenient
- * way of performing a structure-aware grep of the tree. For example it is
- * possible to grep for a node and get all the properties associated with
- * that node. Trees can be subsetted easily, by specifying the nodes that
- * are required, and then writing out the regions returned by this function.
- * This is useful for small resource-constrained systems, such as boot
- * loaders, which want to use an FDT but do not need to know about all of
- * it.
- *
- * Secondly it makes it easy to hash parts of the tree and detect changes.
- * The intent is to get a list of regions which will be invariant provided
- * those parts are invariant. For example, if you request a list of regions
- * for all nodes but exclude the property "data", then you will get the
- * same region contents regardless of any change to "data" properties.
- *
- * This function can be used to produce a byte-stream to send to a hashing
- * function to verify that critical parts of the FDT have not changed.
- * Note that semantically null changes in order could still cause false
- * hash misses. Such reordering might happen if the tree is regenerated
- * from source, and nodes are reordered (the bytes-stream will be emitted
- * in a different order and mnay hash functions will detect this). However
- * if an existing tree is modified using libfdt functions, such as
- * fdt_add_subnode() and fdt_setprop(), then this problem is avoided.
- *
- * The nodes/properties to include/exclude are defined by a function
- * provided by the caller. This function is called for each node and
- * property, and must return:
- *
- *    0 - to exclude this part
- *    1 - to include this part
- *   -1 - for FDT_IS_PROP only: no information is available, so include
- *		if its containing node is included
- *
- * The last case is only used to deal with properties. Often a property is
- * included if its containing node is included - this is the case where
- * -1 is returned.. However if the property is specifically required to be
- * included/excluded, then 0 or 1 can be returned. Note that including a
- * property when the FDT_REG_SUPERNODES flag is given will force its
- * containing node to be included since it is not valid to have a property
- * that is not in a node.
- *
- * Using the information provided, the inclusion of a node can be controlled
- * either by a node name or its compatible string, or any other property
- * that the function can determine.
- *
- * As an example, including node "/" means to include the root node and all
- * root properties. A flag provides a way of also including supernodes (of
- * which there is none for the root node), and another flag includes
- * immediate subnodes, so in this case we would get the FDT_BEGIN_NODE and
- * FDT_END_NODE of all subnodes of /.
- *
- * The subnode feature helps in a hashing situation since it prevents the
- * root node from changing at all. Any change to non-excluded properties,
- * names of subnodes or number of subnodes would be detected.
- *
- * When used with FITs this provides the ability to hash and sign parts of
- * the FIT based on different configurations in the FIT. Then it is
- * impossible to change anything about that configuration (include images
- * attached to the configuration), but it may be possible to add new
- * configurations, new images or new signatures within the existing
- * framework.
- *
- * Adding new properties to a device tree may result in the string table
- * being extended (if the new property names are different from those
- * already added). This function can optionally include a region for
- * the string table so that this can be part of the hash too. This is always
- * the last region.
- *
- * The FDT also has a mem_rsvmap table which can also be included, and is
- * always the first region if so.
- *
- * The device tree header is not included in the region list. Since the
- * contents of the FDT are changing (shrinking, often), the caller will need
- * to regenerate the header anyway.
- *
- * @fdt:	Device tree to check
- * @h_include:	Function to call to determine whether to include a part or
- *		not:
- *
- *		@priv: Private pointer as passed to fdt_find_regions()
- *		@fdt: Pointer to FDT blob
- *		@offset: Offset of this node / property
- *		@type: Type of this part, FDT_IS_...
- *		@data: Pointer to data (node name, property name, compatible
- *			string, value (not yet supported)
- *		@size: Size of data, or 0 if none
- *		@return 0 to exclude, 1 to include, -1 if no information is
- *		available
- * @priv:	Private pointer passed to h_include
- * @region:	Returns list of regions, sorted by offset
- * @max_regions: Maximum length of region list
- * @path:	Pointer to a temporary string for the function to use for
- *		building path names
- * @path_len:	Length of path, must be large enough to hold the longest
- *		path in the tree
- * @flags:	Various flags that control the region algortihm, see
- *		FDT_REG_...
- * @return number of regions in list. If this is >max_regions then the
- * region array was exhausted. You should increase max_regions and try
- * the call again. Only the first max_regions elements are available in the
- * array.
- *
- * On error a -ve value is return, which can be:
- *
- *	-FDT_ERR_BADSTRUCTURE (too deep or more END tags than BEGIN tags
- *	-FDT_ERR_BADLAYOUT
- *	-FDT_ERR_NOSPACE (path area is too small)
- */
-int fdt_first_region(const void *fdt,
-		int (*h_include)(void *priv, const void *fdt, int offset,
-				 int type, const char *data, int size),
-		void *priv, struct fdt_region *region,
-		char *path, int path_len, int flags,
-		struct fdt_region_state *info);
-
-/** fdt_next_region() - find next region
- *
- * See fdt_first_region() for full description. This function finds the
- * next region according to the provided parameters, which must be the same
- * as passed to fdt_first_region().
- *
- * This function can additionally return -FDT_ERR_NOTFOUND when there are no
- * more regions
- */
-int fdt_next_region(const void *fdt,
-		int (*h_include)(void *priv, const void *fdt, int offset,
-				 int type, const char *data, int size),
-		void *priv, struct fdt_region *region,
-		char *path, int path_len, int flags,
-		struct fdt_region_state *info);
-
-/**
- * fdt_add_alias_regions() - find aliases that point to existing regions
- *
- * Once a device tree grep is complete some of the nodes will be present
- * and some will have been dropped. This function checks all the alias nodes
- * to figure out which points point to nodes which are still present. These
- * aliases need to be kept, along with the nodes they reference.
- *
- * Given a list of regions function finds the aliases that still apply and
- * adds more regions to the list for these. This function is called after
- * fdt_next_region() has finished returning regions and requires the same
- * state.
- *
- * @fdt:	Device tree file to reference
- * @region:	List of regions that will be kept
- * @count:	Number of regions
- * @max_regions: Number of entries that can fit in @region
- * @info:	Region state as returned from fdt_next_region()
- * @return new number of regions in @region (i.e. count + the number added)
- * or -FDT_ERR_NOSPACE if there was not enough space.
- */
-int fdt_add_alias_regions(const void *fdt, struct fdt_region *region, int count,
-			  int max_regions, struct fdt_region_state *info);
-#endif /* SWIG */
-
-#endif /* _LIBFDT_H */
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index bc7a148..efcb251 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -121,7 +121,6 @@
 CONFIG_BCH_CONST_PARAMS
 CONFIG_BCH_CONST_T
 CONFIG_BCM2835_GPIO
-CONFIG_BCM283X_MU_SERIAL
 CONFIG_BIOSEMU
 CONFIG_BITBANGMII_MULTI
 CONFIG_BL1_OFFSET
@@ -1276,7 +1275,6 @@
 CONFIG_MACB3_PHY
 CONFIG_MACB_SEARCH_PHY
 CONFIG_MACH_OMAPL138_LCDK
-CONFIG_MACH_SPECIFIC
 CONFIG_MACH_TYPE
 CONFIG_MACH_TYPE_COMPAT_REV
 CONFIG_MACRESET_TIMEOUT
@@ -1618,11 +1616,8 @@
 CONFIG_PIXIS_BRDCFG1_SSI_TDM_SSI
 CONFIG_PIXIS_BRDCFG1_TDM
 CONFIG_PIXIS_SGMII_CMD
-CONFIG_PL010_SERIAL
 CONFIG_PL011_CLOCK
-CONFIG_PL011_SERIAL
 CONFIG_PL011_SERIAL_RLCR
-CONFIG_PL01X_SERIAL
 CONFIG_PL01x_PORTS
 CONFIG_PLATFORM_ENV_SETTINGS
 CONFIG_PLATINUM_BOARD
diff --git a/scripts/dtc/pylibfdt/setup.py b/scripts/dtc/pylibfdt/setup.py
index daf1089..4f7cf04 100755
--- a/scripts/dtc/pylibfdt/setup.py
+++ b/scripts/dtc/pylibfdt/setup.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
 
 """
 setup.py file for SWIG libfdt
diff --git a/scripts/mailmapper b/scripts/mailmapper
index 922ada6..78b23d1 100755
--- a/scripts/mailmapper
+++ b/scripts/mailmapper
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
 #
 # Copyright (C) 2014, Masahiro Yamada <yamada.m@jp.panasonic.com>
 #
diff --git a/test/py/test.py b/test/py/test.py
index 74e560a..4695079 100755
--- a/test/py/test.py
+++ b/test/py/test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
 
 # Copyright (c) 2015 Stephen Warren
 # Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
diff --git a/tools/Makefile b/tools/Makefile
index b7d7d41..d3387fa 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -63,11 +63,11 @@
 
 # The following files are synced with upstream DTC.
 # Use synced versions from scripts/dtc/libfdt/.
-LIBFDT_SRCS_SYNCED := fdt.c fdt_wip.c fdt_sw.c fdt_strerror.c fdt_empty_tree.c \
-		      fdt_addresses.c fdt_overlay.c
+LIBFDT_SRCS_SYNCED := fdt.c fdt_wip.c fdt_sw.c fdt_rw.c \
+		fdt_strerror.c fdt_empty_tree.c fdt_addresses.c fdt_overlay.c
 # The following files are locally modified for U-Boot (unfotunately).
 # Use U-Boot own versions from lib/libfdt/.
-LIBFDT_SRCS_UNSYNCED := fdt_ro.c fdt_rw.c fdt_region.c
+LIBFDT_SRCS_UNSYNCED := fdt_ro.c fdt_region.c
 
 LIBFDT_OBJS := $(addprefix libfdt/, $(patsubst %.c, %.o, $(LIBFDT_SRCS_SYNCED))) \
 	       $(addprefix lib/libfdt/, $(patsubst %.c, %.o, $(LIBFDT_SRCS_UNSYNCED)))
@@ -242,7 +242,7 @@
 # Define __KERNEL_STRICT_NAMES to prevent typedef overlaps
 # Define _GNU_SOURCE to obtain the getline prototype from stdio.h
 #
-HOST_EXTRACFLAGS += -include $(srctree)/include/libfdt_env.h \
+HOST_EXTRACFLAGS += -include $(srctree)/include/compiler.h \
 		$(patsubst -I%,-idirafter%, $(filter -I%, $(UBOOTINCLUDE))) \
 		-I$(srctree)/lib/libfdt \
 		-I$(srctree)/tools \
diff --git a/tools/buildman/buildman.py b/tools/buildman/buildman.py
index 11a4f16..473117c 100755
--- a/tools/buildman/buildman.py
+++ b/tools/buildman/buildman.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
 #
 # Copyright (c) 2012 The Chromium OS Authors.
 #
diff --git a/tools/dtoc/dtoc.py b/tools/dtoc/dtoc.py
index ce7bc05..6eacfc9 100755
--- a/tools/dtoc/dtoc.py
+++ b/tools/dtoc/dtoc.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python2
 #
 # Copyright (C) 2016 Google, Inc
 # Written by Simon Glass <sjg@chromium.org>
diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c
index 18c2324..ca5507d 100644
--- a/tools/env/fw_env.c
+++ b/tools/env/fw_env.c
@@ -505,8 +505,6 @@
 
 int fw_env_flush(struct env_opts *opts)
 {
-	int ret;
-
 	if (!opts)
 		opts = &default_opts;
 
diff --git a/tools/fdt_host.h b/tools/fdt_host.h
index 134d965..8d4aa06 100644
--- a/tools/fdt_host.h
+++ b/tools/fdt_host.h
@@ -11,6 +11,23 @@
 #include "../include/libfdt.h"
 #include "../include/fdt_support.h"
 
+/**
+ * fdt_remove_unused_strings() - Remove any unused strings from an FDT
+ *
+ * This creates a new device tree in @new with unused strings removed. The
+ * called can then use fdt_pack() to minimise the space consumed.
+ *
+ * @old:	Old device tree blog
+ * @new:	Place to put new device tree blob, which must be as large as
+ *		@old
+ * @return
+ *	0, on success
+ *	-FDT_ERR_BADOFFSET, corrupt device tree
+ *	-FDT_ERR_NOSPACE, out of space, which should not happen unless there
+ *		is something very wrong with the device tree input
+ */
+int fdt_remove_unused_strings(const void *old, void *new);
+
 int fit_check_sign(const void *working_fdt, const void *key);
 
 #endif /* __FDT_HOST_H__ */
diff --git a/tools/fdtgrep.c b/tools/fdtgrep.c
index 5897b6d..8d33205 100644
--- a/tools/fdtgrep.c
+++ b/tools/fdtgrep.c
@@ -10,13 +10,16 @@
 
 #include <assert.h>
 #include <ctype.h>
+#include <errno.h>
 #include <getopt.h>
+#include <fcntl.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
-#include "../include/libfdt.h"
+#include "fdt_host.h"
 #include "libfdt_internal.h"
 
 /* Define DEBUG to get some debugging output on stderr */
diff --git a/tools/gen_ethaddr_crc.c b/tools/gen_ethaddr_crc.c
index fe9896d..8cf86f4 100644
--- a/tools/gen_ethaddr_crc.c
+++ b/tools/gen_ethaddr_crc.c
@@ -6,6 +6,7 @@
  */
 
 #include <ctype.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/tools/ifdtool.c b/tools/ifdtool.c
index 195b153..729991e 100644
--- a/tools/ifdtool.c
+++ b/tools/ifdtool.c
@@ -12,6 +12,7 @@
 #include <assert.h>
 #include <fcntl.h>
 #include <getopt.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
diff --git a/tools/imagetool.h b/tools/imagetool.h
index a8d5054..e67de9b 100644
--- a/tools/imagetool.h
+++ b/tools/imagetool.h
@@ -12,6 +12,7 @@
 #include "os_support.h"
 #include <errno.h>
 #include <fcntl.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
diff --git a/tools/libfdt/fdt_rw.c b/tools/libfdt/fdt_rw.c
new file mode 100644
index 0000000..e475084
--- /dev/null
+++ b/tools/libfdt/fdt_rw.c
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier:	GPL-2.0+ BSD-2-Clause */
+#include "fdt_host.h"
+#include "../../scripts/dtc/libfdt/fdt_rw.c"
+
+int fdt_remove_unused_strings(const void *old, void *new)
+{
+	const struct fdt_property *old_prop;
+	struct fdt_property *new_prop;
+	int size = fdt_totalsize(old);
+	int next_offset, offset;
+	const char *str;
+	int ret;
+	int tag = FDT_PROP;
+
+	/* Make a copy and remove the strings */
+	memcpy(new, old, size);
+	fdt_set_size_dt_strings(new, 0);
+
+	/* Add every property name back into the new string table */
+	for (offset = 0; tag != FDT_END; offset = next_offset) {
+		tag = fdt_next_tag(old, offset, &next_offset);
+		if (tag != FDT_PROP)
+			continue;
+		old_prop = fdt_get_property_by_offset(old, offset, NULL);
+		new_prop = (struct fdt_property *)(unsigned long)
+			fdt_get_property_by_offset(new, offset, NULL);
+		str = fdt_string(old, fdt32_to_cpu(old_prop->nameoff));
+		ret = _fdt_find_add_string(new, str);
+		if (ret < 0)
+			return ret;
+		new_prop->nameoff = cpu_to_fdt32(ret);
+	}
+
+	return 0;
+}
diff --git a/tools/microcode-tool.py b/tools/microcode-tool.py
index 790c27e..069d961 100755
--- a/tools/microcode-tool.py
+++ b/tools/microcode-tool.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
 #
 # Copyright (c) 2014 Google, Inc
 #
diff --git a/tools/mips-relocs.c b/tools/mips-relocs.c
index 8be69d3..27d4730 100644
--- a/tools/mips-relocs.c
+++ b/tools/mips-relocs.c
@@ -11,6 +11,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <limits.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/mman.h>
diff --git a/tools/patman/patman.py b/tools/patman/patman.py
index 4b3bc78..7647440 100755
--- a/tools/patman/patman.py
+++ b/tools/patman/patman.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
 #
 # Copyright (c) 2011 The Chromium OS Authors.
 #
diff --git a/tools/rkmux.py b/tools/rkmux.py
index 3917335..11c192a 100755
--- a/tools/rkmux.py
+++ b/tools/rkmux.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python2
 
 # Script to create enums from datasheet register tables
 #