Merge tag 'u-boot-rockchip-20210606' of https://source.denx.de/u-boot/custodians/u-boot-rockchip
diff --git a/arch/arm/dts/armada-37xx.dtsi b/arch/arm/dts/armada-37xx.dtsi
index a1052ad..2615b8c 100644
--- a/arch/arm/dts/armada-37xx.dtsi
+++ b/arch/arm/dts/armada-37xx.dtsi
@@ -323,7 +323,7 @@
 		};
 
 		pcie0: pcie@d0070000 {
-			compatible = "marvell,armada-37xx-pcie";
+			compatible = "marvell,armada-3700-pcie";
 			reg = <0 0xd0070000 0 0x20000>;
 			#address-cells = <3>;
 			#size-cells = <2>;
@@ -332,10 +332,17 @@
 			status = "disabled";
 
 			bus-range = <0 0xff>;
+			/*
+			 * The 128 MiB address range [0xe8000000-0xf0000000] is
+			 * dedicated for PCIe and can be assigned to 8 windows
+			 * with size a power of two. Use one 64 KiB window for
+			 * IO at the end and the remaining seven windows
+			 * (totaling 127 MiB) for MEM.
+			 */
 			ranges = <0x82000000 0 0xe8000000
-				 0 0xe8000000 0 0x1000000 /* Port 0 MEM */
-				 0x81000000 0 0xe9000000
-				 0 0xe9000000 0 0x10000>; /* Port 0 IO*/
+				 0 0xe8000000 0 0x7f00000 /* Port 0 MEM */
+				 0x81000000 0 0xefff0000
+				 0 0xefff0000 0 0x10000>; /* Port 0 IO*/
 		};
 	};
 };
diff --git a/arch/arm/mach-mvebu/armada3700/cpu.c b/arch/arm/mach-mvebu/armada3700/cpu.c
index 0cf60d7..9aec0ce 100644
--- a/arch/arm/mach-mvebu/armada3700/cpu.c
+++ b/arch/arm/mach-mvebu/armada3700/cpu.c
@@ -8,6 +8,7 @@
 #include <cpu_func.h>
 #include <dm.h>
 #include <fdtdec.h>
+#include <fdt_support.h>
 #include <init.h>
 #include <asm/global_data.h>
 #include <linux/bitops.h>
@@ -53,8 +54,6 @@
 #define A3700_PTE_BLOCK_DEVICE \
 	(PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE)
 
-#define PCIE_PATH			"/soc/pcie@d0070000"
-
 DECLARE_GLOBAL_DATA_PTR;
 
 static struct mm_region mvebu_mem_map[MAX_MEM_MAP_REGIONS] = {
@@ -282,36 +281,81 @@
 	return -1;
 }
 
+static int fdt_setprop_inplace_u32_partial(void *blob, int node,
+					   const char *name,
+					   u32 idx, u32 val)
+{
+	val = cpu_to_fdt32(val);
+
+	return fdt_setprop_inplace_namelen_partial(blob, node, name,
+						   strlen(name),
+						   idx * sizeof(u32),
+						   &val, sizeof(u32));
+}
+
 int a3700_fdt_fix_pcie_regions(void *blob)
 {
-	u32 new_ranges[14], base;
+	int acells, pacells, scells;
+	u32 base, fix_offset;
 	const u32 *ranges;
-	int node, len;
+	int node, pnode;
+	int ret, i, len;
 
-	node = fdt_path_offset(blob, PCIE_PATH);
+	base = find_pcie_window_base();
+	if (base == -1)
+		return -ENOENT;
+
+	node = fdt_node_offset_by_compatible(blob, -1, "marvell,armada-3700-pcie");
 	if (node < 0)
 		return node;
 
 	ranges = fdt_getprop(blob, node, "ranges", &len);
-	if (!ranges)
+	if (!ranges || len % sizeof(u32))
 		return -ENOENT;
 
-	if (len != sizeof(new_ranges))
-		return -EINVAL;
-
-	memcpy(new_ranges, ranges, len);
+	/*
+	 * The "ranges" property is an array of
+	 * { <child address> <parent address> <size in child address space> }
+	 *
+	 * All 3 elements can span a diffent number of cells. Fetch their sizes.
+	 */
+	pnode = fdt_parent_offset(blob, node);
+	acells = fdt_address_cells(blob, node);
+	pacells = fdt_address_cells(blob, pnode);
+	scells = fdt_size_cells(blob, node);
 
-	base = find_pcie_window_base();
-	if (base == -1)
+	/* Child PCI addresses always use 3 cells */
+	if (acells != 3)
 		return -ENOENT;
 
+	/* Calculate fixup offset from first child address (in last cell) */
+	fix_offset = base - fdt32_to_cpu(ranges[2]);
+
-	new_ranges[2] = cpu_to_fdt32(base);
-	new_ranges[4] = new_ranges[2];
+	/*
+	 * Fix address (last cell) of each child address and each parent
+	 * address
+	 */
+	for (i = 0; i < len / sizeof(u32); i += acells + pacells + scells) {
+		int idx;
 
-	new_ranges[9] = cpu_to_fdt32(base + 0x1000000);
-	new_ranges[11] = new_ranges[9];
+		/* fix child address */
+		idx = i + acells - 1;
+		ret = fdt_setprop_inplace_u32_partial(blob, node, "ranges", idx,
+						      fdt32_to_cpu(ranges[idx]) +
+						      fix_offset);
+		if (ret)
+			return ret;
 
-	return fdt_setprop_inplace(blob, node, "ranges", new_ranges, len);
+		/* fix parent address */
+		idx = i + acells + pacells - 1;
+		ret = fdt_setprop_inplace_u32_partial(blob, node, "ranges", idx,
+						      fdt32_to_cpu(ranges[idx]) +
+						      fix_offset);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
 }
 
 void reset_cpu(void)
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c
index 63ca514..6bb9447 100644
--- a/arch/sandbox/cpu/start.c
+++ b/arch/sandbox/cpu/start.c
@@ -436,10 +436,13 @@
 int main(int argc, char *argv[])
 {
 	struct sandbox_state *state;
+	void * text_base;
 	gd_t data;
 	int size;
 	int ret;
 
+	text_base = os_find_text_base();
+
 	/*
 	 * Copy argv[] so that we can pass the arguments in the original
 	 * sequence when resetting the sandbox.
@@ -452,7 +455,7 @@
 
 	memset(&data, '\0', sizeof(data));
 	gd = &data;
-	gd->arch.text_base = os_find_text_base();
+	gd->arch.text_base = text_base;
 
 	ret = state_init();
 	if (ret)
diff --git a/board/BuR/brxre1/board.c b/board/BuR/brxre1/board.c
index ef692b0..544e09f 100644
--- a/board/BuR/brxre1/board.c
+++ b/board/BuR/brxre1/board.c
@@ -164,12 +164,21 @@
 	br_resetc_bmode();
 
 	/* setup othbootargs for bootvx-command (vxWorks bootline) */
+#ifdef CONFIG_LCD
 	snprintf(othbootargs, sizeof(othbootargs),
 		 "u=vxWorksFTP pw=vxWorks o=0x%08x;0x%08x;0x%08x;0x%08x",
 		 (u32)gd->fb_base - 0x20,
 		 (u32)env_get_ulong("vx_memtop", 16, gd->fb_base - 0x20),
 		 (u32)env_get_ulong("vx_romfsbase", 16, 0),
 		 (u32)env_get_ulong("vx_romfssize", 16, 0));
+#else
+	snprintf(othbootargs, sizeof(othbootargs),
+		 "u=vxWorksFTP pw=vxWorks o=0x%08x;0x%08x;0x%08x;0x%08x",
+		 (u32)gd->relocaddr,
+		 (u32)env_get_ulong("vx_memtop", 16, gd->relocaddr),
+		 (u32)env_get_ulong("vx_romfsbase", 16, 0),
+		 (u32)env_get_ulong("vx_romfssize", 16, 0));
+#endif
 	env_set("othbootargs", othbootargs);
 	/*
 	 * reset VBAR registers to its reset location, VxWorks 6.9.3.2 does
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c
index 1d3cefe..ade923f 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -337,24 +337,6 @@
 	return env_set("regdomain", rd);
 }
 
-/*
- * default factory reset bootcommand on Omnia first sets all the front LEDs
- * to green and then tries to load the rescue image from SPI flash memory and
- * boot it
- */
-#define OMNIA_FACTORY_RESET_BOOTCMD \
-	"i2c dev 2; " \
-	"i2c mw 0x2a.1 0x3 0x1c 1; " \
-	"i2c mw 0x2a.1 0x4 0x1c 1; " \
-	"mw.l 0x01000000 0x00ff000c; " \
-	"i2c write 0x01000000 0x2a.1 0x5 4 -s; " \
-	"setenv bootargs \"earlyprintk console=ttyS0,115200" \
-			" omniarescue=$omnia_reset\"; " \
-	"sf probe; " \
-	"sf read 0x1000000 0x100000 0x700000; " \
-	"bootm 0x1000000; " \
-	"bootz 0x1000000"
-
 static void handle_reset_button(void)
 {
 	int ret;
@@ -370,8 +352,36 @@
 	env_set_ulong("omnia_reset", reset_status);
 
 	if (reset_status) {
+		const char * const vars[3] = {
+			"bootcmd",
+			"bootcmd_rescue",
+			"distro_bootcmd",
+		};
+
+		/*
+		 * Set the above envs to their default values, in case the user
+		 * managed to break them.
+		 */
+		env_set_default_vars(3, (char * const *)vars, 0);
+
+		/* Ensure bootcmd_rescue is used by distroboot */
+		env_set("boot_targets", "rescue");
+
 		printf("RESET button was pressed, overwriting bootcmd!\n");
-		env_set("bootcmd", OMNIA_FACTORY_RESET_BOOTCMD);
+	} else {
+		/*
+		 * In case the user somehow managed to save environment with
+		 * boot_targets=rescue, reset boot_targets to default value.
+		 * This could happen in subsequent commands if bootcmd_rescue
+		 * failed.
+		 */
+		if (!strcmp(env_get("boot_targets"), "rescue")) {
+			const char * const vars[1] = {
+				"boot_targets",
+			};
+
+			env_set_default_vars(1, (char * const *)vars, 0);
+		}
 	}
 }
 #endif
diff --git a/configs/brxre1_defconfig b/configs/brxre1_defconfig
index 57f3f43..6d9f243 100644
--- a/configs/brxre1_defconfig
+++ b/configs/brxre1_defconfig
@@ -92,8 +92,8 @@
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_SYS_WHITE_ON_BLACK=y
-CONFIG_AM335X_LCD=y
-CONFIG_LCD=y
+# CONFIG_AM335X_LCD is not set
+# CONFIG_LCD is not set
 CONFIG_SPL_TINY_MEMSET=y
 # CONFIG_OF_LIBFDT_OVERLAY is not set
 # CONFIG_EFI_LOADER is not set
diff --git a/configs/mx28evk_auart_console_defconfig b/configs/mx28evk_auart_console_defconfig
index ec4fd65..60b9f39 100644
--- a/configs/mx28evk_auart_console_defconfig
+++ b/configs/mx28evk_auart_console_defconfig
@@ -56,8 +56,8 @@
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_USB_ETHER_SMSC95XX=y
-CONFIG_VIDEO=y
+# CONFIG_VIDEO is not set
 CONFIG_SPLASH_SCREEN=y
-CONFIG_VIDEO_BMP_GZIP=y
-CONFIG_VIDEO_BMP_RLE8=y
+# CONFIG_VIDEO_BMP_GZIP is not set
+# CONFIG_VIDEO_BMP_RLE8 is not set
 CONFIG_OF_LIBFDT=y
diff --git a/configs/mx28evk_defconfig b/configs/mx28evk_defconfig
index 4f0ed83..abc0c48 100644
--- a/configs/mx28evk_defconfig
+++ b/configs/mx28evk_defconfig
@@ -56,8 +56,8 @@
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_USB_ETHER_SMSC95XX=y
-CONFIG_VIDEO=y
+# CONFIG_VIDEO is not set
 CONFIG_SPLASH_SCREEN=y
-CONFIG_VIDEO_BMP_GZIP=y
-CONFIG_VIDEO_BMP_RLE8=y
+# CONFIG_VIDEO_BMP_GZIP is not set
+# CONFIG_VIDEO_BMP_RLE8 is not set
 CONFIG_OF_LIBFDT=y
diff --git a/configs/mx28evk_nand_defconfig b/configs/mx28evk_nand_defconfig
index 7d95b8f..0a376a2 100644
--- a/configs/mx28evk_nand_defconfig
+++ b/configs/mx28evk_nand_defconfig
@@ -57,8 +57,8 @@
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_USB_ETHER_SMSC95XX=y
-CONFIG_VIDEO=y
+# CONFIG_VIDEO is not set
 CONFIG_SPLASH_SCREEN=y
-CONFIG_VIDEO_BMP_GZIP=y
-CONFIG_VIDEO_BMP_RLE8=y
+# CONFIG_VIDEO_BMP_GZIP is not set
+# CONFIG_VIDEO_BMP_RLE8 is not set
 CONFIG_OF_LIBFDT=y
diff --git a/configs/mx28evk_spi_defconfig b/configs/mx28evk_spi_defconfig
index e969d50..a6b00c2 100644
--- a/configs/mx28evk_spi_defconfig
+++ b/configs/mx28evk_spi_defconfig
@@ -53,8 +53,8 @@
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_USB_ETHER_SMSC95XX=y
-CONFIG_VIDEO=y
+# CONFIG_VIDEO is not set
 CONFIG_SPLASH_SCREEN=y
-CONFIG_VIDEO_BMP_GZIP=y
-CONFIG_VIDEO_BMP_RLE8=y
+# CONFIG_VIDEO_BMP_GZIP is not set
+# CONFIG_VIDEO_BMP_RLE8 is not set
 CONFIG_OF_LIBFDT=y
diff --git a/configs/pico-dwarf-imx6ul_defconfig b/configs/pico-dwarf-imx6ul_defconfig
index 9695eb2..bf016f8 100644
--- a/configs/pico-dwarf-imx6ul_defconfig
+++ b/configs/pico-dwarf-imx6ul_defconfig
@@ -68,7 +68,7 @@
 CONFIG_USB_GADGET_VENDOR_NUM=0x0525
 CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
-CONFIG_VIDEO=y
+# CONFIG_VIDEO is not set
 CONFIG_SPLASH_SCREEN=y
 CONFIG_SPLASH_SCREEN_ALIGN=y
-CONFIG_VIDEO_BMP_RLE8=y
+# CONFIG_VIDEO_BMP_RLE8 is not set
diff --git a/configs/pico-hobbit-imx6ul_defconfig b/configs/pico-hobbit-imx6ul_defconfig
index 5c1ca0b..14d36c5 100644
--- a/configs/pico-hobbit-imx6ul_defconfig
+++ b/configs/pico-hobbit-imx6ul_defconfig
@@ -71,7 +71,7 @@
 CONFIG_USB_GADGET_VENDOR_NUM=0x0525
 CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
-CONFIG_VIDEO=y
+# CONFIG_VIDEO is not set
 CONFIG_SPLASH_SCREEN=y
 CONFIG_SPLASH_SCREEN_ALIGN=y
-CONFIG_VIDEO_BMP_RLE8=y
+# CONFIG_VIDEO_BMP_RLE8 is not set
diff --git a/configs/pico-pi-imx6ul_defconfig b/configs/pico-pi-imx6ul_defconfig
index 51b71a7..ba8b1a1 100644
--- a/configs/pico-pi-imx6ul_defconfig
+++ b/configs/pico-pi-imx6ul_defconfig
@@ -71,7 +71,7 @@
 CONFIG_USB_GADGET_VENDOR_NUM=0x0525
 CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
-CONFIG_VIDEO=y
+# CONFIG_VIDEO is not set
 CONFIG_SPLASH_SCREEN=y
 CONFIG_SPLASH_SCREEN_ALIGN=y
-CONFIG_VIDEO_BMP_RLE8=y
+# CONFIG_VIDEO_BMP_RLE8 is not set
diff --git a/configs/pxm2_defconfig b/configs/pxm2_defconfig
index 90ef4c8..da6b1bb 100644
--- a/configs/pxm2_defconfig
+++ b/configs/pxm2_defconfig
@@ -101,10 +101,10 @@
 CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_USB_ETHER=y
 CONFIG_USBNET_HOST_ADDR="de:ad:be:af:00:00"
-CONFIG_VIDEO=y
+# CONFIG_VIDEO is not set
 # CONFIG_VIDEO_SW_CURSOR is not set
 CONFIG_SYS_CONSOLE_BG_COL=0xff
 CONFIG_SYS_CONSOLE_FG_COL=0x00
 CONFIG_SPLASH_SCREEN=y
 CONFIG_SPLASH_SCREEN_ALIGN=y
-CONFIG_VIDEO_BMP_RLE8=y
+# CONFIG_VIDEO_BMP_RLE8 is not set
diff --git a/configs/rut_defconfig b/configs/rut_defconfig
index 6fc06f1..2ddf0e6 100644
--- a/configs/rut_defconfig
+++ b/configs/rut_defconfig
@@ -31,7 +31,6 @@
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 # CONFIG_DISPLAY_CPUINFO is not set
 # CONFIG_DISPLAY_BOARDINFO is not set
-CONFIG_ARCH_EARLY_INIT_R=y
 CONFIG_ARCH_MISC_INIT=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_NAND_DRIVERS=y
@@ -101,10 +100,10 @@
 CONFIG_USB_GADGET_PRODUCT_NUM=0x02d2
 CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_USB_ETHER=y
-CONFIG_VIDEO=y
+# CONFIG_VIDEO is not set
 # CONFIG_VIDEO_SW_CURSOR is not set
 CONFIG_SYS_CONSOLE_BG_COL=0xff
 CONFIG_SYS_CONSOLE_FG_COL=0x00
 CONFIG_SPLASH_SCREEN=y
 CONFIG_SPLASH_SCREEN_ALIGN=y
-CONFIG_VIDEO_BMP_RLE8=y
+# CONFIG_VIDEO_BMP_RLE8 is not set
diff --git a/drivers/core/of_addr.c b/drivers/core/of_addr.c
index 9b77308..3fbc0a7 100644
--- a/drivers/core/of_addr.c
+++ b/drivers/core/of_addr.c
@@ -118,11 +118,6 @@
 	return NULL;
 }
 
-static void dev_count_cells(const struct device_node *np, int *nap, int *nsp)
-{
-	of_bus_default_count_cells(np, nap, nsp);
-}
-
 const __be32 *of_get_address(const struct device_node *dev, int index,
 			     u64 *size, unsigned int *flags)
 {
@@ -136,7 +131,6 @@
 	parent = of_get_parent(dev);
 	if (parent == NULL)
 		return NULL;
-	dev_count_cells(dev, &na, &ns);
 	bus = of_match_bus(parent);
 	bus->count_cells(dev, &na, &ns);
 	of_node_put(parent);
@@ -192,9 +186,13 @@
 	 *
 	 * As far as we know, this damage only exists on Apple machines, so
 	 * This code is only enabled on powerpc. --gcl
+	 *
+	 * This quirk also applies for 'dma-ranges' which frequently exist in
+	 * child nodes without 'dma-ranges' in the parent nodes. --RobH
 	 */
 	ranges = of_get_property(parent, rprop, &rlen);
-	if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
+	if (ranges == NULL && !of_empty_ranges_quirk(parent) &&
+	    strcmp(rprop, "dma-ranges")) {
 		debug("no ranges; cannot translate\n");
 		return 1;
 	}
diff --git a/drivers/net/mscc_eswitch/luton_switch.c b/drivers/net/mscc_eswitch/luton_switch.c
index 54afa14..73c950d 100644
--- a/drivers/net/mscc_eswitch/luton_switch.c
+++ b/drivers/net/mscc_eswitch/luton_switch.c
@@ -588,7 +588,6 @@
 	struct luton_private *priv = dev_get_priv(dev);
 	int i, ret;
 	struct resource res;
-	fdt32_t faddr;
 	phys_addr_t addr_base;
 	unsigned long addr_size;
 	ofnode eth_node, node, mdio_node;
@@ -658,9 +657,7 @@
 
 		if (ofnode_read_resource(mdio_node, 0, &res))
 			return -ENOMEM;
-		faddr = cpu_to_fdt32(res.start);
-
-		addr_base = ofnode_translate_address(mdio_node, &faddr);
+		addr_base = res.start;
 		addr_size = res.end - res.start;
 
 		/* If the bus is new then create a new bus */
diff --git a/drivers/pci/pci-aardvark.c b/drivers/pci/pci-aardvark.c
index c43d4f3..96aa039 100644
--- a/drivers/pci/pci-aardvark.c
+++ b/drivers/pci/pci-aardvark.c
@@ -99,6 +99,46 @@
 #define     PCIE_CORE_CTRL2_STRICT_ORDER_ENABLE	BIT(5)
 #define     PCIE_CORE_CTRL2_ADDRWIN_MAP_ENABLE	BIT(6)
 
+/* PCIe window configuration */
+#define OB_WIN_BASE_ADDR			0x4c00
+#define OB_WIN_BLOCK_SIZE			0x20
+#define OB_WIN_COUNT				8
+#define OB_WIN_REG_ADDR(win, offset)		(OB_WIN_BASE_ADDR + \
+						 OB_WIN_BLOCK_SIZE * (win) + \
+						 (offset))
+#define OB_WIN_MATCH_LS(win)			OB_WIN_REG_ADDR(win, 0x00)
+#define     OB_WIN_ENABLE			BIT(0)
+#define OB_WIN_MATCH_MS(win)			OB_WIN_REG_ADDR(win, 0x04)
+#define OB_WIN_REMAP_LS(win)			OB_WIN_REG_ADDR(win, 0x08)
+#define OB_WIN_REMAP_MS(win)			OB_WIN_REG_ADDR(win, 0x0c)
+#define OB_WIN_MASK_LS(win)			OB_WIN_REG_ADDR(win, 0x10)
+#define OB_WIN_MASK_MS(win)			OB_WIN_REG_ADDR(win, 0x14)
+#define OB_WIN_ACTIONS(win)			OB_WIN_REG_ADDR(win, 0x18)
+#define OB_WIN_DEFAULT_ACTIONS			(OB_WIN_ACTIONS(OB_WIN_COUNT-1) + 0x4)
+#define     OB_WIN_FUNC_NUM_MASK		GENMASK(31, 24)
+#define     OB_WIN_FUNC_NUM_SHIFT		24
+#define     OB_WIN_FUNC_NUM_ENABLE		BIT(23)
+#define     OB_WIN_BUS_NUM_BITS_MASK		GENMASK(22, 20)
+#define     OB_WIN_BUS_NUM_BITS_SHIFT		20
+#define     OB_WIN_MSG_CODE_ENABLE		BIT(22)
+#define     OB_WIN_MSG_CODE_MASK		GENMASK(21, 14)
+#define     OB_WIN_MSG_CODE_SHIFT		14
+#define     OB_WIN_MSG_PAYLOAD_LEN		BIT(12)
+#define     OB_WIN_ATTR_ENABLE			BIT(11)
+#define     OB_WIN_ATTR_TC_MASK			GENMASK(10, 8)
+#define     OB_WIN_ATTR_TC_SHIFT		8
+#define     OB_WIN_ATTR_RELAXED			BIT(7)
+#define     OB_WIN_ATTR_NOSNOOP			BIT(6)
+#define     OB_WIN_ATTR_POISON			BIT(5)
+#define     OB_WIN_ATTR_IDO			BIT(4)
+#define     OB_WIN_TYPE_MASK			GENMASK(3, 0)
+#define     OB_WIN_TYPE_SHIFT			0
+#define     OB_WIN_TYPE_MEM			0x0
+#define     OB_WIN_TYPE_IO			0x4
+#define     OB_WIN_TYPE_CONFIG_TYPE0		0x8
+#define     OB_WIN_TYPE_CONFIG_TYPE1		0x9
+#define     OB_WIN_TYPE_MSG			0xc
+
 /* LMI registers base address and register offsets */
 #define LMI_BASE_ADDR				0x6000
 #define CFG_REG					(LMI_BASE_ADDR + 0x0)
@@ -522,6 +562,86 @@
 	return -ETIMEDOUT;
 }
 
+/*
+ * Set PCIe address window register which could be used for memory
+ * mapping.
+ */
+static void pcie_advk_set_ob_win(struct pcie_advk *pcie, u8 win_num,
+				 phys_addr_t match, phys_addr_t remap,
+				 phys_addr_t mask, u32 actions)
+{
+	advk_writel(pcie, OB_WIN_ENABLE |
+			  lower_32_bits(match), OB_WIN_MATCH_LS(win_num));
+	advk_writel(pcie, upper_32_bits(match), OB_WIN_MATCH_MS(win_num));
+	advk_writel(pcie, lower_32_bits(remap), OB_WIN_REMAP_LS(win_num));
+	advk_writel(pcie, upper_32_bits(remap), OB_WIN_REMAP_MS(win_num));
+	advk_writel(pcie, lower_32_bits(mask), OB_WIN_MASK_LS(win_num));
+	advk_writel(pcie, upper_32_bits(mask), OB_WIN_MASK_MS(win_num));
+	advk_writel(pcie, actions, OB_WIN_ACTIONS(win_num));
+}
+
+static void pcie_advk_disable_ob_win(struct pcie_advk *pcie, u8 win_num)
+{
+	advk_writel(pcie, 0, OB_WIN_MATCH_LS(win_num));
+	advk_writel(pcie, 0, OB_WIN_MATCH_MS(win_num));
+	advk_writel(pcie, 0, OB_WIN_REMAP_LS(win_num));
+	advk_writel(pcie, 0, OB_WIN_REMAP_MS(win_num));
+	advk_writel(pcie, 0, OB_WIN_MASK_LS(win_num));
+	advk_writel(pcie, 0, OB_WIN_MASK_MS(win_num));
+	advk_writel(pcie, 0, OB_WIN_ACTIONS(win_num));
+}
+
+static void pcie_advk_set_ob_region(struct pcie_advk *pcie, int *wins,
+				    struct pci_region *region, u32 actions)
+{
+	phys_addr_t phys_start = region->phys_start;
+	pci_addr_t bus_start = region->bus_start;
+	pci_size_t size = region->size;
+	phys_addr_t win_mask;
+	u64 win_size;
+
+	if (*wins == -1)
+		return;
+
+	/*
+	 * The n-th PCIe window is configured by tuple (match, remap, mask)
+	 * and an access to address A uses this window it if A matches the
+	 * match with given mask.
+	 * So every PCIe window size must be a power of two and every start
+	 * address must be aligned to window size. Minimal size is 64 KiB
+	 * because lower 16 bits of mask must be zero.
+	 */
+	while (*wins < OB_WIN_COUNT && size > 0) {
+		/* Calculate the largest aligned window size */
+		win_size = (1ULL << (fls64(size) - 1)) |
+			   (phys_start ? (1ULL << __ffs64(phys_start)) : 0);
+		win_size = 1ULL << __ffs64(win_size);
+		if (win_size < 0x10000)
+			break;
+
+		dev_dbg(pcie->dev,
+			"Configuring PCIe window %d: [0x%llx-0x%llx] as 0x%x\n",
+			*wins, (u64)phys_start, (u64)phys_start + win_size,
+			actions);
+		win_mask = ~(win_size - 1) & ~0xffff;
+		pcie_advk_set_ob_win(pcie, *wins, phys_start, bus_start,
+				     win_mask, actions);
+
+		phys_start += win_size;
+		bus_start += win_size;
+		size -= win_size;
+		(*wins)++;
+	}
+
+	if (size > 0) {
+		*wins = -1;
+		dev_err(pcie->dev,
+			"Invalid PCIe region [0x%llx-0x%llx]\n",
+			(u64)region->phys_start,
+			(u64)region->phys_start + region->size);
+	}
+}
+
 /**
  * pcie_advk_setup_hw() - PCIe initailzation
  *
@@ -531,6 +651,8 @@
  */
 static int pcie_advk_setup_hw(struct pcie_advk *pcie)
 {
+	struct pci_region *io, *mem, *pref;
+	int i, wins;
 	u32 reg;
 
 	/* Set to Direct mode */
@@ -597,7 +719,9 @@
 	 * configurations (Default User Field: 0xD0074CFC)
 	 * are used to transparent address translation for
 	 * the outbound transactions. Thus, PCIe address
-	 * windows are not required.
+	 * windows are not required for transparent memory
+	 * access when default outbound window configuration
+	 * is set for memory access.
 	 */
 	reg = advk_readl(pcie, PCIE_CORE_CTRL2_REG);
 	reg |= PCIE_CORE_CTRL2_ADDRWIN_MAP_ENABLE;
@@ -613,10 +737,33 @@
 	reg |= PIO_CTRL_ADDR_WIN_DISABLE;
 	advk_writel(pcie, reg, PIO_CTRL);
 
-	/* Start link training */
-	reg = advk_readl(pcie, PCIE_CORE_LINK_CTRL_STAT_REG);
-	reg |= PCIE_CORE_LINK_TRAINING;
-	advk_writel(pcie, reg, PCIE_CORE_LINK_CTRL_STAT_REG);
+	/*
+	 * Set memory access in Default User Field so it
+	 * is not required to configure PCIe address for
+	 * transparent memory access.
+	 */
+	advk_writel(pcie, OB_WIN_TYPE_MEM, OB_WIN_DEFAULT_ACTIONS);
+
+	/*
+	 * Configure PCIe address windows for non-memory or
+	 * non-transparent access as by default PCIe uses
+	 * transparent memory access.
+	 */
+	wins = 0;
+	pci_get_regions(pcie->dev, &io, &mem, &pref);
+	if (io)
+		pcie_advk_set_ob_region(pcie, &wins, io, OB_WIN_TYPE_IO);
+	if (mem && mem->phys_start != mem->bus_start)
+		pcie_advk_set_ob_region(pcie, &wins, mem, OB_WIN_TYPE_MEM);
+	if (pref && pref->phys_start != pref->bus_start)
+		pcie_advk_set_ob_region(pcie, &wins, pref, OB_WIN_TYPE_MEM);
+
+	/* Disable remaining PCIe outbound windows */
+	for (i = ((wins >= 0) ? wins : 0); i < OB_WIN_COUNT; i++)
+		pcie_advk_disable_ob_win(pcie, i);
+
+	if (wins == -1)
+		return -EINVAL;
 
 	/* Wait for PCIe link up */
 	if (pcie_advk_wait_for_link(pcie))
@@ -679,6 +826,16 @@
 {
 	struct pcie_advk *pcie = dev_get_priv(dev);
 	u32 reg;
+	int i;
+
+	for (i = 0; i < OB_WIN_COUNT; i++)
+		pcie_advk_disable_ob_win(pcie, i);
+
+	reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
+	reg &= ~(PCIE_CORE_CMD_MEM_ACCESS_EN |
+		 PCIE_CORE_CMD_IO_ACCESS_EN |
+		 PCIE_CORE_CMD_MEM_IO_REQ_EN);
+	advk_writel(pcie, reg, PCIE_CORE_CMD_STATUS_REG);
 
 	reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
 	reg &= ~LINK_TRAINING_EN;
@@ -716,7 +873,7 @@
 };
 
 static const struct udevice_id pcie_advk_ids[] = {
-	{ .compatible = "marvell,armada-37xx-pcie" },
+	{ .compatible = "marvell,armada-3700-pcie" },
 	{ }
 };
 
diff --git a/drivers/pwm/cros_ec_pwm.c b/drivers/pwm/cros_ec_pwm.c
index 44f4105..4a39c31 100644
--- a/drivers/pwm/cros_ec_pwm.c
+++ b/drivers/pwm/cros_ec_pwm.c
@@ -80,5 +80,5 @@
 	.id	= UCLASS_PWM,
 	.of_match = cros_ec_pwm_ids,
 	.ops	= &cros_ec_pwm_ops,
-	.priv_auto_alloc_size	= sizeof(struct cros_ec_pwm_priv),
+	.priv_auto = sizeof(struct cros_ec_pwm_priv),
 };
diff --git a/include/configs/turris_omnia.h b/include/configs/turris_omnia.h
index 0b55c14..7da18f9 100644
--- a/include/configs/turris_omnia.h
+++ b/include/configs/turris_omnia.h
@@ -108,12 +108,35 @@
 
 #include <config_distro_bootcmd.h>
 
+/*
+ * The factory reset bootcommand on Omnia first sets all the front LEDs to green
+ * and then tries to load the rescue image from SPI flash memory and boot it
+ */
+#define TURRIS_OMNIA_BOOTCMD_RESCUE \
+	"i2c dev 2; " \
+	"i2c mw 0x2a.1 0x3 0x1c 1; " \
+	"i2c mw 0x2a.1 0x4 0x1c 1; " \
+	"mw.l 0x01000000 0x00ff000c; " \
+	"i2c write 0x01000000 0x2a.1 0x5 4 -s; " \
+	"setenv bootargs \"earlyprintk console=ttyS0,115200" \
+		" omniarescue=$omnia_reset rescue_mode=$omnia_reset\"; " \
+	"sf probe; " \
+	"sf read 0x1000000 0x100000 0x700000; " \
+	"lzmadec 0x1000000 0x1700000; " \
+	"if gpio input gpio@71_4; then " \
+		"bootm 0x1700000#sfp; " \
+	"else " \
+		"bootm 0x1700000; " \
+	"fi; " \
+	"bootz 0x1000000"
+
 #define CONFIG_EXTRA_ENV_SETTINGS \
 	RELOCATION_LIMITS_ENV_SETTINGS \
 	LOAD_ADDRESS_ENV_SETTINGS \
 	"fdtfile=" CONFIG_DEFAULT_DEVICE_TREE ".dtb\0" \
 	"console=ttyS0,115200\0" \
 	"ethact=ethernet@34000\0" \
+	"bootcmd_rescue=" TURRIS_OMNIA_BOOTCMD_RESCUE "\0" \
 	BOOTENV
 
 #endif /* CONFIG_SPL_BUILD */
diff --git a/lib/image-sparse.c b/lib/image-sparse.c
index 187ac28..d80fdbb 100644
--- a/lib/image-sparse.c
+++ b/lib/image-sparse.c
@@ -55,10 +55,10 @@
 	lbaint_t blk;
 	lbaint_t blkcnt;
 	lbaint_t blks;
-	uint32_t bytes_written = 0;
+	uint64_t bytes_written = 0;
 	unsigned int chunk;
 	unsigned int offset;
-	unsigned int chunk_data_sz;
+	uint64_t chunk_data_sz;
 	uint32_t *fill_buf = NULL;
 	uint32_t fill_val;
 	sparse_header_t *sparse_header;
@@ -132,8 +132,8 @@
 				 sizeof(chunk_header_t));
 		}
 
-		chunk_data_sz = sparse_header->blk_sz * chunk_header->chunk_sz;
-		blkcnt = chunk_data_sz / info->blksz;
+		chunk_data_sz = ((u64)sparse_header->blk_sz) * chunk_header->chunk_sz;
+		blkcnt = DIV_ROUND_UP_ULL(chunk_data_sz, info->blksz);
 		switch (chunk_header->chunk_type) {
 		case CHUNK_TYPE_RAW:
 			if (chunk_header->total_sz !=
@@ -162,7 +162,7 @@
 				return -1;
 			}
 			blk += blks;
-			bytes_written += blkcnt * info->blksz;
+			bytes_written += ((u64)blkcnt) * info->blksz;
 			total_blocks += chunk_header->chunk_sz;
 			data += chunk_data_sz;
 			break;
@@ -222,8 +222,9 @@
 				blk += blks;
 				i += j;
 			}
-			bytes_written += blkcnt * info->blksz;
-			total_blocks += chunk_data_sz / sparse_header->blk_sz;
+			bytes_written += ((u64)blkcnt) * info->blksz;
+			total_blocks += DIV_ROUND_UP_ULL(chunk_data_sz,
+							 sparse_header->blk_sz);
 			free(fill_buf);
 			break;
 
@@ -253,7 +254,7 @@
 
 	debug("Wrote %d blocks, expected to write %d blocks\n",
 	      total_blocks, sparse_header->total_blks);
-	printf("........ wrote %u bytes to '%s'\n", bytes_written, part_name);
+	printf("........ wrote %llu bytes to '%s'\n", bytes_written, part_name);
 
 	if (total_blocks != sparse_header->total_blks) {
 		info->mssg("sparse image write failure", response);
diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c
index 9b771fd..d273e21 100644
--- a/test/dm/test-fdt.c
+++ b/test/dm/test-fdt.c
@@ -19,6 +19,7 @@
 #include <dm/util.h>
 #include <dm/lists.h>
 #include <dm/of_access.h>
+#include <linux/ioport.h>
 #include <test/test.h>
 #include <test/ut.h>
 
@@ -1165,3 +1166,35 @@
 	return 0;
 }
 DM_TEST(dm_test_decode_display_timing, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+/* Test read_resourcee() */
+static int dm_test_read_resource(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	struct resource res;
+
+	/* test resource without translation */
+	ut_assertok(uclass_find_device_by_name(UCLASS_SIMPLE_BUS, "syscon@2", &dev));
+	ut_assertok(dev_read_resource(dev, 0, &res));
+	ut_asserteq(0x40, res.start);
+	ut_asserteq(0x44, res.end);
+	ut_assertok(dev_read_resource(dev, 1, &res));
+	ut_asserteq(0x48, res.start);
+	ut_asserteq(0x4d, res.end);
+
+	/* test resource with translation */
+	ut_assertok(uclass_find_device_by_name(UCLASS_TEST_DUMMY, "dev@1,100", &dev));
+	ut_assertok(dev_read_resource(dev, 0, &res));
+	ut_asserteq(0x9000, res.start);
+	ut_asserteq(0x9fff, res.end);
+
+	/* test named resource */
+	ut_assertok(uclass_find_device_by_name(UCLASS_TEST_DUMMY, "dev@0,0", &dev));
+	ut_assertok(dev_read_resource_byname(dev, "sandbox-dummy-0", &res));
+	ut_asserteq(0x8000, res.start);
+	ut_asserteq(0x8fff, res.end);
+
+	return 0;
+}
+
+DM_TEST(dm_test_read_resource, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);