return;
 }
 
+/*
+ * __reserved_mem_alloc_in_range() - allocate reserved memory described with
+ *     'alloc-ranges'. Choose bottom-up/top-down depending on nearby existing
+ *     reserved regions to keep the reserved memory contiguous if possible.
+ */
+static int __init __reserved_mem_alloc_in_range(phys_addr_t size,
+       phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap,
+       phys_addr_t *res_base)
+{
+       bool prev_bottom_up = memblock_bottom_up();
+       bool bottom_up = false, top_down = false;
+       int ret, i;
+
+       for (i = 0; i < reserved_mem_count; i++) {
+               struct reserved_mem *rmem = &reserved_mem[i];
+
+               /* Skip regions that were not reserved yet */
+               if (rmem->size == 0)
+                       continue;
+
+               /*
+                * If range starts next to an existing reservation, use bottom-up:
+                *      |....RRRR................RRRRRRRR..............|
+                *             --RRRR------
+                */
+               if (start >= rmem->base && start <= (rmem->base + rmem->size))
+                       bottom_up = true;
+
+               /*
+                * If range ends next to an existing reservation, use top-down:
+                *      |....RRRR................RRRRRRRR..............|
+                *                    -------RRRR-----
+                */
+               if (end >= rmem->base && end <= (rmem->base + rmem->size))
+                       top_down = true;
+       }
+
+       /* Change setting only if either bottom-up or top-down was selected */
+       if (bottom_up != top_down)
+               memblock_set_bottom_up(bottom_up);
+
+       ret = early_init_dt_alloc_reserved_memory_arch(size, align,
+                       start, end, nomap, res_base);
+
+       /* Restore old setting if needed */
+       if (bottom_up != top_down)
+               memblock_set_bottom_up(prev_bottom_up);
+
+       return ret;
+}
+
 /*
  * __reserved_mem_alloc_size() - allocate reserved memory described by
  *     'size', 'alignment'  and 'alloc-ranges' properties.
                        end = start + dt_mem_next_cell(dt_root_size_cells,
                                                       &prop);
 
-                       ret = early_init_dt_alloc_reserved_memory_arch(size,
-                                       align, start, end, nomap, &base);
+                       ret = __reserved_mem_alloc_in_range(size, align,
+                                       start, end, nomap, &base);
                        if (ret == 0) {
                                pr_debug("allocated memory for '%s' node: base %pa, size %lu MiB\n",
                                        uname, &base,