dm: core: Add a way to obtain a string list
authorSimon Glass <sjg@chromium.org>
Sat, 23 Oct 2021 23:26:07 +0000 (17:26 -0600)
committerSimon Glass <sjg@chromium.org>
Sun, 28 Nov 2021 23:51:51 +0000 (16:51 -0700)
At present we support reading a string list a string at a time. Apart
from being inefficient, this makes it impossible to separate reading of
the devicetree into the of_to_plat() method where it belongs, since any
code which needs access to the string must read it from the devicetree.

Add a function which returns the string property as an array of pointers
to the strings, which is easily used by clients.

Signed-off-by: Simon Glass <sjg@chromium.org>
drivers/core/ofnode.c
drivers/core/read.c
include/dm/ofnode.h
include/dm/read.h
test/dm/ofnode.c

index 08705ef..709bea2 100644 (file)
@@ -456,6 +456,32 @@ int ofnode_read_string_count(ofnode node, const char *property)
        }
 }
 
+int ofnode_read_string_list(ofnode node, const char *property,
+                           const char ***listp)
+{
+       const char **prop;
+       int count;
+       int i;
+
+       *listp = NULL;
+       count = ofnode_read_string_count(node, property);
+       if (count < 0)
+               return count;
+       if (!count)
+               return 0;
+
+       prop = calloc(count + 1, sizeof(char *));
+       if (!prop)
+               return -ENOMEM;
+
+       for (i = 0; i < count; i++)
+               ofnode_read_string_index(node, property, i, &prop[i]);
+       prop[count] = NULL;
+       *listp = prop;
+
+       return count;
+}
+
 static void ofnode_from_fdtdec_phandle_args(struct fdtdec_phandle_args *in,
                                            struct ofnode_phandle_args *out)
 {
index 4307ca4..31f9e78 100644 (file)
@@ -205,6 +205,12 @@ int dev_read_string_count(const struct udevice *dev, const char *propname)
        return ofnode_read_string_count(dev_ofnode(dev), propname);
 }
 
+int dev_read_string_list(const struct udevice *dev, const char *propname,
+                        const char ***listp)
+{
+       return ofnode_read_string_list(dev_ofnode(dev), propname, listp);
+}
+
 int dev_read_phandle_with_args(const struct udevice *dev, const char *list_name,
                               const char *cells_name, int cell_count,
                               int index, struct ofnode_phandle_args *out_args)
index 0eae8f9..6601bd8 100644 (file)
@@ -610,6 +610,26 @@ int ofnode_read_string_index(ofnode node, const char *propname, int index,
 int ofnode_read_string_count(ofnode node, const char *property);
 
 /**
+ * ofnode_read_string_list() - read a list of strings
+ *
+ * This produces a list of string pointers with each one pointing to a string
+ * in the string list. If the property does not exist, it returns {NULL}.
+ *
+ * The data is allocated and the caller is reponsible for freeing the return
+ * value (the list of string pointers). The strings themselves may not be
+ * changed as they point directly into the devicetree property.
+ *
+ * @node: node to check
+ * @listp: returns an allocated, NULL-terminated list of strings if the return
+ *     value is > 0, else is set to NULL
+ * @return number of strings in list, 0 if none, -ENOMEM if out of memory,
+ *     -EINVAL if no such property, -EENODATA if property is empty
+ * @return: NULL-terminated list of strings (NULL if no property or empty)
+ */
+int ofnode_read_string_list(ofnode node, const char *property,
+                           const char ***listp);
+
+/**
  * ofnode_parse_phandle_with_args() - Find a node pointed by phandle in a list
  *
  * This function is useful to parse lists of phandles and their arguments.
index 890bf3d..75c6ad6 100644 (file)
@@ -371,6 +371,27 @@ int dev_read_string_index(const struct udevice *dev, const char *propname,
  *   number of strings in the list, or -ve error value if not found
  */
 int dev_read_string_count(const struct udevice *dev, const char *propname);
+
+/**
+ * dev_read_string_list() - read a list of strings
+ *
+ * This produces a list of string pointers with each one pointing to a string
+ * in the string list. If the property does not exist, it returns {NULL}.
+ *
+ * The data is allocated and the caller is reponsible for freeing the return
+ * value (the list of string pointers). The strings themselves may not be
+ * changed as they point directly into the devicetree property.
+ *
+ * @dev: device to examine
+ * @propname: name of the property containing the string list
+ * @listp: returns an allocated, NULL-terminated list of strings if the return
+ *     value is > 0, else is set to NULL
+ * @return number of strings in list, 0 if none, -ENOMEM if out of memory,
+ *     -ENOENT if no such property
+ */
+int dev_read_string_list(const struct udevice *dev, const char *propname,
+                        const char ***listp);
+
 /**
  * dev_read_phandle_with_args() - Find a node pointed by phandle in a list
  *
@@ -906,6 +927,13 @@ static inline int dev_read_string_count(const struct udevice *dev,
        return ofnode_read_string_count(dev_ofnode(dev), propname);
 }
 
+static inline int dev_read_string_list(const struct udevice *dev,
+                                      const char *propname,
+                                      const char ***listp)
+{
+       return ofnode_read_string_list(dev_ofnode(dev), propname, listp);
+}
+
 static inline int dev_read_phandle_with_args(const struct udevice *dev,
                const char *list_name, const char *cells_name, int cell_count,
                int index, struct ofnode_phandle_args *out_args)
index c72e082..5e7c968 100644 (file)
@@ -354,6 +354,7 @@ DM_TEST(dm_test_ofnode_for_each_compatible_node, UT_TESTF_SCAN_FDT);
 
 static int dm_test_ofnode_string(struct unit_test_state *uts)
 {
+       const char **val;
        const char *out;
        ofnode node;
 
@@ -366,6 +367,10 @@ static int dm_test_ofnode_string(struct unit_test_state *uts)
        ut_asserteq_str("test string", out);
        ut_asserteq(0, ofnode_stringlist_search(node, "str-value",
                                                "test string"));
+       ut_asserteq(1, ofnode_read_string_list(node, "str-value", &val));
+       ut_asserteq_str("test string", val[0]);
+       ut_assertnull(val[1]);
+       free(val);
 
        /* list of strings */
        ut_asserteq(5, ofnode_read_string_count(node, "mux-control-names"));
@@ -374,6 +379,15 @@ static int dm_test_ofnode_string(struct unit_test_state *uts)
        ut_asserteq_str("mux0", out);
        ut_asserteq(0, ofnode_stringlist_search(node, "mux-control-names",
                                                "mux0"));
+       ut_asserteq(5, ofnode_read_string_list(node, "mux-control-names",
+                                              &val));
+       ut_asserteq_str("mux0", val[0]);
+       ut_asserteq_str("mux1", val[1]);
+       ut_asserteq_str("mux2", val[2]);
+       ut_asserteq_str("mux3", val[3]);
+       ut_asserteq_str("mux4", val[4]);
+       ut_assertnull(val[5]);
+       free(val);
 
        ut_assertok(ofnode_read_string_index(node, "mux-control-names", 4,
                                             &out));
@@ -387,6 +401,7 @@ DM_TEST(dm_test_ofnode_string, 0);
 
 static int dm_test_ofnode_string_err(struct unit_test_state *uts)
 {
+       const char **val;
        const char *out;
        ofnode node;
 
@@ -401,16 +416,21 @@ static int dm_test_ofnode_string_err(struct unit_test_state *uts)
        ut_asserteq(-EINVAL, ofnode_read_string_count(node, "missing"));
        ut_asserteq(-EINVAL, ofnode_read_string_index(node, "missing", 0,
                                                      &out));
+       ut_asserteq(-EINVAL, ofnode_read_string_list(node, "missing", &val));
 
        /* empty property */
        ut_asserteq(-ENODATA, ofnode_read_string_count(node, "bool-value"));
        ut_asserteq(-ENODATA, ofnode_read_string_index(node, "bool-value", 0,
                                                       &out));
+       ut_asserteq(-ENODATA, ofnode_read_string_list(node, "bool-value",
+                                                    &val));
 
        /* badly formatted string list */
        ut_asserteq(-EILSEQ, ofnode_read_string_count(node, "int64-value"));
        ut_asserteq(-EILSEQ, ofnode_read_string_index(node, "int64-value", 0,
                                                       &out));
+       ut_asserteq(-EILSEQ, ofnode_read_string_list(node, "int64-value",
+                                                    &val));
 
        /* out of range / not found */
        ut_asserteq(-ENODATA, ofnode_read_string_index(node, "str-value", 1,