summaryrefslogtreecommitdiffstats
path: root/common/resource.c
diff options
context:
space:
mode:
authorAhmad Fatoum <a.fatoum@pengutronix.de>2021-05-31 09:12:35 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2021-06-02 08:37:22 +0200
commit0a78ac84e9fe3e91d9b01b1e128ea493c6ebc3f4 (patch)
treedfee4cf3c4932c1fa7aa7399ecf8e10faee45158 /common/resource.c
parentb9958d497dfd9fc563b198f7233c57388d76cd06 (diff)
downloadbarebox-0a78ac84e9fe3e91d9b01b1e128ea493c6ebc3f4.tar.gz
barebox-0a78ac84e9fe3e91d9b01b1e128ea493c6ebc3f4.tar.xz
memory: fuse overlapping memory banks
Some ARM subarchitectures read back RAM size from the SDRAM controller and use the info to register memory banks. If an overlapping memory region is already registered, e.g. via device tree /memory, this second registration will fail. This is especially annoying as it can regress after a device tree sync: - Kind soul updates upstream device tree to describe minimal available RAM across hardware variants - barebox PBL has enough info about the board to set up larger RAM size and relocates barebox to the end of the RAM - barebox proper starts with new device tree and is upset to find itself outside of registered memory Account for this by growing the existing bank if a bank to be added happens to overlap it. As a special case, if the existing bank completely contains the new memory bank, the function is a no-op. Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> Link: https://lore.barebox.org/20210531071239.30653-3-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'common/resource.c')
-rw-r--r--common/resource.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/common/resource.c b/common/resource.c
index ff4318a0d7..f96cb94b50 100644
--- a/common/resource.c
+++ b/common/resource.c
@@ -102,6 +102,28 @@ int release_region(struct resource *res)
return 0;
}
+
+/*
+ * merge two adjacent sibling regions.
+ */
+int __merge_regions(const char *name,
+ struct resource *resa, struct resource *resb)
+{
+ if (!resource_adjacent(resa, resb))
+ return -EINVAL;
+
+ if (resa->start < resb->start)
+ resa->end = resb->end;
+ else
+ resa->start = resb->start;
+
+ free((char *)resa->name);
+ resa->name = xstrdup(name);
+ release_region(resb);
+
+ return 0;
+}
+
/* The root resource for the whole memory-mapped io space */
struct resource iomem_resource = {
.start = 0,