device property: Add fwnode_property_match_string()
authorMika Westerberg <mika.westerberg@linux.intel.com>
Mon, 14 Sep 2015 14:37:35 +0000 (17:37 +0300)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 25 Sep 2015 00:00:19 +0000 (02:00 +0200)
Sometimes it is useful to be able to extract an index of certain string
value from an array of strings. A typical use case is to give a name to a
DMA channel, PWM, clock and so on.

Provide an implementation using unified device property accessors that
follows of_property_match_string() but works for all supported fwnodes.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/base/property.c
include/linux/property.h

index 660ecec60bdf5a6b4046725eb0e18e76b735a8fc..de40623bbd8a748fd81f3208810046d05861a75c 100644 (file)
@@ -287,6 +287,28 @@ int device_property_read_string(struct device *dev, const char *propname,
 }
 EXPORT_SYMBOL_GPL(device_property_read_string);
 
+/**
+ * device_property_match_string - find a string in an array and return index
+ * @dev: Device to get the property of
+ * @propname: Name of the property holding the array
+ * @string: String to look for
+ *
+ * Find a given string in a string array and if it is found return the
+ * index back.
+ *
+ * Return: %0 if the property was found (success),
+ *        %-EINVAL if given arguments are not valid,
+ *        %-ENODATA if the property does not have a value,
+ *        %-EPROTO if the property is not an array of strings,
+ *        %-ENXIO if no suitable firmware interface is present.
+ */
+int device_property_match_string(struct device *dev, const char *propname,
+                                const char *string)
+{
+       return fwnode_property_match_string(dev_fwnode(dev), propname, string);
+}
+EXPORT_SYMBOL_GPL(device_property_match_string);
+
 #define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \
        (val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \
              : of_property_count_elems_of_size((node), (propname), sizeof(type))
@@ -478,6 +500,52 @@ int fwnode_property_read_string(struct fwnode_handle *fwnode,
 }
 EXPORT_SYMBOL_GPL(fwnode_property_read_string);
 
+/**
+ * fwnode_property_match_string - find a string in an array and return index
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property holding the array
+ * @string: String to look for
+ *
+ * Find a given string in a string array and if it is found return the
+ * index back.
+ *
+ * Return: %0 if the property was found (success),
+ *        %-EINVAL if given arguments are not valid,
+ *        %-ENODATA if the property does not have a value,
+ *        %-EPROTO if the property is not an array of strings,
+ *        %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_match_string(struct fwnode_handle *fwnode,
+       const char *propname, const char *string)
+{
+       const char **values;
+       int nval, ret, i;
+
+       nval = fwnode_property_read_string_array(fwnode, propname, NULL, 0);
+       if (nval < 0)
+               return nval;
+
+       values = kcalloc(nval, sizeof(*values), GFP_KERNEL);
+       if (!values)
+               return -ENOMEM;
+
+       ret = fwnode_property_read_string_array(fwnode, propname, values, nval);
+       if (ret < 0)
+               goto out;
+
+       ret = -ENODATA;
+       for (i = 0; i < nval; i++) {
+               if (!strcmp(values[i], string)) {
+                       ret = i;
+                       break;
+               }
+       }
+out:
+       kfree(values);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(fwnode_property_match_string);
+
 /**
  * device_get_next_child_node - Return the next child node handle for a device
  * @dev: Device to find the next child node for.
index a59c6ee566c2cf908ca7c6ec5512768e90d4a3b0..463de52fe8915486d2e2159bde7edf12834f8dcc 100644 (file)
@@ -40,6 +40,8 @@ int device_property_read_string_array(struct device *dev, const char *propname,
                                      const char **val, size_t nval);
 int device_property_read_string(struct device *dev, const char *propname,
                                const char **val);
+int device_property_match_string(struct device *dev,
+                                const char *propname, const char *string);
 
 bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname);
 int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
@@ -59,6 +61,8 @@ int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
                                      size_t nval);
 int fwnode_property_read_string(struct fwnode_handle *fwnode,
                                const char *propname, const char **val);
+int fwnode_property_match_string(struct fwnode_handle *fwnode,
+                                const char *propname, const char *string);
 
 struct fwnode_handle *device_get_next_child_node(struct device *dev,
                                                 struct fwnode_handle *child);