fdtdec: Support reserved-memory flags

Reserved memory nodes can have additional flags. Support reading and
writing these flags to ensure that reserved memory nodes can be properly
parsed and emitted.

This converts support for the existing "no-map" flag to avoid extending
the argument list for fdtdec_add_reserved_memory() to excessive length.

Signed-off-by: Thierry Reding <treding@nvidia.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Tom Warren <twarren@nvidia.com>
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/soc.c b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
index 4f17c32..adf3b4e 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/soc.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
@@ -55,7 +55,7 @@
 	lpi_base.start = addr;
 	lpi_base.end = addr + size - 1;
 	ret = fdtdec_add_reserved_memory(blob, "lpi_rd_table", &lpi_base, NULL,
-					 NULL, 0, false);
+					 NULL, 0, 0);
 	if (ret) {
 		debug("%s: failed to add reserved memory\n", __func__);
 		return ret;
diff --git a/arch/riscv/lib/fdt_fixup.c b/arch/riscv/lib/fdt_fixup.c
index 7ac30a4..36c16e9 100644
--- a/arch/riscv/lib/fdt_fixup.c
+++ b/arch/riscv/lib/fdt_fixup.c
@@ -75,7 +75,7 @@
 		pmp_mem.start = addr;
 		pmp_mem.end = addr + size - 1;
 		err = fdtdec_add_reserved_memory(dst, basename, &pmp_mem,
-						 NULL, 0, &phandle, false);
+						 NULL, 0, &phandle, 0);
 		if (err < 0 && err != -FDT_ERR_EXISTS) {
 			log_err("failed to add reserved memory: %d\n", err);
 			return err;
diff --git a/board/nvidia/p2371-2180/p2371-2180.c b/board/nvidia/p2371-2180/p2371-2180.c
index bc0a133..137c7d3 100644
--- a/board/nvidia/p2371-2180/p2371-2180.c
+++ b/board/nvidia/p2371-2180/p2371-2180.c
@@ -129,7 +129,7 @@
 	int err;
 
 	err = fdtdec_get_carveout(src, node, "memory-region", 0, &fb, NULL,
-				  NULL, NULL);
+				  NULL, NULL, NULL);
 	if (err < 0) {
 		if (err != -FDT_ERR_NOTFOUND)
 			printf("failed to get carveout for %s: %d\n", node,
@@ -139,7 +139,7 @@
 	}
 
 	err = fdtdec_set_carveout(dst, node, "memory-region", 0, &fb,
-				  "framebuffer", NULL, 0);
+				  "framebuffer", NULL, 0, 0);
 	if (err < 0) {
 		printf("failed to set carveout for %s: %d\n", node, err);
 		return err;
diff --git a/board/nvidia/p2771-0000/p2771-0000.c b/board/nvidia/p2771-0000/p2771-0000.c
index cde5eff..3d2653d 100644
--- a/board/nvidia/p2771-0000/p2771-0000.c
+++ b/board/nvidia/p2771-0000/p2771-0000.c
@@ -105,7 +105,7 @@
 	int err;
 
 	err = fdtdec_get_carveout(src, node, "memory-region", 0, &fb, NULL,
-				  NULL, NULL);
+				  NULL, NULL, NULL);
 	if (err < 0) {
 		if (err != -FDT_ERR_NOTFOUND)
 			printf("failed to get carveout for %s: %d\n", node,
@@ -115,7 +115,7 @@
 	}
 
 	err = fdtdec_set_carveout(dst, node, "memory-region", 0, &fb,
-				  "framebuffer", NULL, 0);
+				  "framebuffer", NULL, 0, 0);
 	if (err < 0) {
 		printf("failed to set carveout for %s: %d\n", node, err);
 		return err;
diff --git a/board/nvidia/p3450-0000/p3450-0000.c b/board/nvidia/p3450-0000/p3450-0000.c
index e737fc1..2770862 100644
--- a/board/nvidia/p3450-0000/p3450-0000.c
+++ b/board/nvidia/p3450-0000/p3450-0000.c
@@ -128,7 +128,7 @@
 	int err;
 
 	err = fdtdec_get_carveout(src, node, "memory-region", 0, &fb, NULL,
-				  NULL, NULL);
+				  NULL, NULL, NULL);
 	if (err < 0) {
 		if (err != -FDT_ERR_NOTFOUND)
 			printf("failed to get carveout for %s: %d\n", node,
@@ -138,7 +138,7 @@
 	}
 
 	err = fdtdec_set_carveout(dst, node, "memory-region", 0, &fb,
-				  "framebuffer", NULL, 0);
+				  "framebuffer", NULL, 0, 0);
 	if (err < 0) {
 		printf("failed to set carveout for %s: %d\n", node, err);
 		return err;
diff --git a/include/fdtdec.h b/include/fdtdec.h
index d360d7b..f94d1f4 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -977,6 +977,9 @@
 	return fdt_setprop_u32(blob, node, "phandle", phandle);
 }
 
+/* add "no-map" property */
+#define FDTDEC_RESERVED_MEMORY_NO_MAP (1 << 0)
+
 /**
  * fdtdec_add_reserved_memory() - add or find a reserved-memory node
  *
@@ -996,7 +999,7 @@
  *     uint32_t phandle;
  *
  *     fdtdec_add_reserved_memory(fdt, "framebuffer", &fb, NULL, 0, &phandle,
- *                                false);
+ *                                0);
  *
  * This results in the following subnode being added to the top-level
  * /reserved-memory node:
@@ -1025,13 +1028,13 @@
  * @param count		number of compatible strings for the carveout region
  * @param phandlep	return location for the phandle of the carveout region
  *			can be NULL if no phandle should be added
- * @param no_map	add "no-map" property if true
+ * @param flags		bitmask of flags to set for the carveout region
  * @return 0 on success or a negative error code on failure
  */
 int fdtdec_add_reserved_memory(void *blob, const char *basename,
 			       const struct fdt_memory *carveout,
 			       const char **compatibles, unsigned int count,
-			       uint32_t *phandlep, bool no_map);
+			       uint32_t *phandlep, unsigned long flags);
 
 /**
  * fdtdec_get_carveout() - reads a carveout from an FDT
@@ -1048,13 +1051,15 @@
  * @param carveout	return location for the carveout information
  * @param name		return location for the carveout name
  * @param compatiblesp	return location for compatible strings
- * @param countp		return location for the number of compatible strings
+ * @param countp	return location for the number of compatible strings
+ * @param flags		return location for the flags of the carveout
  * @return 0 on success or a negative error code on failure
  */
 int fdtdec_get_carveout(const void *blob, const char *node,
 			const char *prop_name, unsigned int index,
 			struct fdt_memory *carveout, const char **name,
-			const char ***compatiblesp, unsigned int *countp);
+			const char ***compatiblesp, unsigned int *countp,
+			unsigned long *flags);
 
 /**
  * fdtdec_set_carveout() - sets a carveout region for a given node
@@ -1073,7 +1078,7 @@
  *     };
  *
  *     fdtdec_set_carveout(fdt, node, "memory-region", 0, "framebuffer", NULL,
- *                         0, &fb);
+ *                         0, &fb, 0);
  *
  * dc@54200000 is a display controller and was set up by the bootloader to
  * scan out the framebuffer specified by "fb". This would cause the following
@@ -1114,12 +1119,13 @@
  * @param name		base name of the reserved-memory node to create
  * @param compatibles	compatible strings to set for the carveout
  * @param count		number of compatible strings
+ * @param flags		bitmask of flags to set for the carveout
  * @return 0 on success or a negative error code on failure
  */
 int fdtdec_set_carveout(void *blob, const char *node, const char *prop_name,
 			unsigned int index, const struct fdt_memory *carveout,
 			const char *name, const char **compatibles,
-			unsigned int count);
+			unsigned int count, unsigned long flags);
 
 /**
  * Set up the device tree ready for use
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index a0ecc72..ad090ea 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -1294,7 +1294,7 @@
 int fdtdec_add_reserved_memory(void *blob, const char *basename,
 			       const struct fdt_memory *carveout,
 			       const char **compatibles, unsigned int count,
-			       uint32_t *phandlep, bool no_map)
+			       uint32_t *phandlep, unsigned long flags)
 {
 	fdt32_t cells[4] = {}, *ptr = cells;
 	uint32_t upper, lower, phandle;
@@ -1364,6 +1364,12 @@
 	if (node < 0)
 		return node;
 
+	if (flags & FDTDEC_RESERVED_MEMORY_NO_MAP) {
+		err = fdt_setprop(blob, node, "no-map", NULL, 0);
+		if (err < 0)
+			return err;
+	}
+
 	if (phandlep) {
 		err = fdt_generate_phandle(blob, &phandle);
 		if (err < 0)
@@ -1394,12 +1400,6 @@
 	if (err < 0)
 		return err;
 
-	if (no_map) {
-		err = fdt_setprop(blob, node, "no-map", NULL, 0);
-		if (err < 0)
-			return err;
-	}
-
 	if (compatibles && count > 0) {
 		size_t length = 0, len = 0;
 		unsigned int i;
@@ -1432,7 +1432,8 @@
 int fdtdec_get_carveout(const void *blob, const char *node,
 			const char *prop_name, unsigned int index,
 			struct fdt_memory *carveout, const char **name,
-			const char ***compatiblesp, unsigned int *countp)
+			const char ***compatiblesp, unsigned int *countp,
+			unsigned long *flags)
 {
 	const fdt32_t *prop;
 	uint32_t phandle;
@@ -1519,13 +1520,20 @@
 
 	carveout->end = carveout->start + size - 1;
 
+	if (flags) {
+		*flags = 0;
+
+		if (fdtdec_get_bool(blob, offset, "no-map"))
+			*flags |= FDTDEC_RESERVED_MEMORY_NO_MAP;
+	}
+
 	return 0;
 }
 
 int fdtdec_set_carveout(void *blob, const char *node, const char *prop_name,
 			unsigned int index, const struct fdt_memory *carveout,
 			const char *name, const char **compatibles,
-			unsigned int count)
+			unsigned int count, unsigned long flags)
 {
 	uint32_t phandle;
 	int err, offset, len;
@@ -1533,7 +1541,7 @@
 	void *prop;
 
 	err = fdtdec_add_reserved_memory(blob, name, carveout, compatibles,
-					 count, &phandle, false);
+					 count, &phandle, flags);
 	if (err < 0) {
 		debug("failed to add reserved memory: %d\n", err);
 		return err;
diff --git a/lib/fdtdec_test.c b/lib/fdtdec_test.c
index 3af9fb5..85351c7 100644
--- a/lib/fdtdec_test.c
+++ b/lib/fdtdec_test.c
@@ -190,7 +190,7 @@
 	CHECK(fdt_setprop(fdt, offset, "reg", cells, (na + ns) * sizeof(*cells)));
 
 	return fdtdec_set_carveout(fdt, name, "memory-region", 0, &carveout,
-				   "framebuffer", NULL, 0);
+				   "framebuffer", NULL, 0, 0);
 }
 
 static int check_fdt_carveout(void *fdt, uint32_t address_cells,
@@ -215,7 +215,7 @@
 	       &expected.end, address_cells, size_cells);
 
 	CHECK(fdtdec_get_carveout(fdt, name, "memory-region", 0, &carveout,
-				  NULL, NULL, NULL));
+				  NULL, NULL, NULL, NULL));
 
 	if ((carveout.start != expected.start) ||
 	    (carveout.end != expected.end)) {
diff --git a/lib/optee/optee.c b/lib/optee/optee.c
index 3fbde93..b036224 100644
--- a/lib/optee/optee.c
+++ b/lib/optee/optee.c
@@ -161,6 +161,7 @@
 					.start = res.start,
 					.end = res.end,
 				};
+				unsigned long flags = FDTDEC_RESERVED_MEMORY_NO_MAP;
 				char *oldname, *nodename, *tmp;
 
 				oldname = strdup(name);
@@ -178,7 +179,7 @@
 								 nodename,
 								 &carveout,
 								 NULL, 0,
-								 NULL, true);
+								 NULL, flags);
 				free(oldname);
 
 				if (ret < 0)
diff --git a/test/dm/fdtdec.c b/test/dm/fdtdec.c
index 385aa77..087d484 100644
--- a/test/dm/fdtdec.c
+++ b/test/dm/fdtdec.c
@@ -29,17 +29,17 @@
 	resv.start = 0x1000;
 	resv.end = 0x2000;
 	ut_assertok(fdtdec_set_carveout(blob, "/a-test", "memory-region", 2,
-					&resv, "test_resv1", NULL, 0));
+					&resv, "test_resv1", NULL, 0, 0));
 
 	resv.start = 0x10000;
 	resv.end = 0x20000;
 	ut_assertok(fdtdec_set_carveout(blob, "/a-test", "memory-region", 1,
-					&resv, "test_resv2", NULL, 0));
+					&resv, "test_resv2", NULL, 0, 0));
 
 	resv.start = 0x100000;
 	resv.end = 0x200000;
 	ut_assertok(fdtdec_set_carveout(blob, "/a-test", "memory-region", 0,
-					&resv, "test_resv3", NULL, 0));
+					&resv, "test_resv3", NULL, 0, 0));
 
 	offset = fdt_path_offset(blob, "/a-test");
 	ut_assert(offset > 0);
@@ -64,6 +64,7 @@
 	fdt_addr_t addr;
 	fdt_size_t size;
 	void *blob;
+	unsigned long flags = FDTDEC_RESERVED_MEMORY_NO_MAP;
 	int blob_sz, parent, subnode;
 	uint32_t phandle, phandle1;
 
@@ -78,7 +79,7 @@
 	resv.start = 0x1000;
 	resv.end = 0x1fff;
 	ut_assertok(fdtdec_add_reserved_memory(blob, "rsvd_region", &resv,
-					       NULL, 0, &phandle, false));
+					       NULL, 0, &phandle, 0));
 
 	/* Test /reserve-memory and its subnode should exist */
 	parent = fdt_path_offset(blob, "/reserved-memory");
@@ -99,7 +100,7 @@
 	resv.start = 0x2000;
 	resv.end = 0x2fff;
 	ut_assertok(fdtdec_add_reserved_memory(blob, "rsvd_region1", &resv,
-					       NULL, 0, &phandle1, true));
+					       NULL, 0, &phandle1, flags));
 	subnode = fdt_path_offset(blob, "/reserved-memory/rsvd_region1");
 	ut_assert(subnode > 0);
 
@@ -116,7 +117,7 @@
 	resv.start = 0x1000;
 	resv.end = 0x1fff;
 	ut_assertok(fdtdec_add_reserved_memory(blob, "rsvd_region2", &resv,
-					       NULL, 0, &phandle1, false));
+					       NULL, 0, &phandle1, 0));
 	subnode = fdt_path_offset(blob, "/reserved-memory/rsvd_region2");
 	ut_assert(subnode < 0);