189 lines
6.8 KiB
Diff
189 lines
6.8 KiB
Diff
|
From 362c0b30249e8639489b428ff5acc4a9d81c087f Mon Sep 17 00:00:00 2001
|
||
|
From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
||
|
Date: Mon, 30 Nov 2015 17:11:36 +0200
|
||
|
Subject: [PATCH 08/16] device property: Fallback to secondary fwnode if
|
||
|
primary misses the property
|
||
|
|
||
|
The struct fwnode has notion of secondary fwnode. This is supposed to used
|
||
|
as fallback if the primary firmware interface (DT, ACPI) does not have the
|
||
|
property in question.
|
||
|
|
||
|
However, the current implementation never checks the secondary node which
|
||
|
prevents one to add default "built-in" properties to devices.
|
||
|
|
||
|
This patch adds fallback to the secondary fwnode if the primary fwnode
|
||
|
returns that the property does not exists.
|
||
|
|
||
|
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
|
||
|
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
||
|
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
||
|
---
|
||
|
drivers/base/property.c | 109 ++++++++++++++++++++++++++++++++++--------------
|
||
|
1 file changed, 78 insertions(+), 31 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/base/property.c b/drivers/base/property.c
|
||
|
index a3538cb..ebcbe34 100644
|
||
|
--- a/drivers/base/property.c
|
||
|
+++ b/drivers/base/property.c
|
||
|
@@ -214,12 +214,8 @@ bool device_property_present(struct device *dev, const char *propname)
|
||
|
}
|
||
|
EXPORT_SYMBOL_GPL(device_property_present);
|
||
|
|
||
|
-/**
|
||
|
- * fwnode_property_present - check if a property of a firmware node is present
|
||
|
- * @fwnode: Firmware node whose property to check
|
||
|
- * @propname: Name of the property
|
||
|
- */
|
||
|
-bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
|
||
|
+static bool __fwnode_property_present(struct fwnode_handle *fwnode,
|
||
|
+ const char *propname)
|
||
|
{
|
||
|
if (is_of_node(fwnode))
|
||
|
return of_property_read_bool(to_of_node(fwnode), propname);
|
||
|
@@ -229,6 +225,21 @@ bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
|
||
|
return !!pset_prop_get(to_pset_node(fwnode), propname);
|
||
|
return false;
|
||
|
}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fwnode_property_present - check if a property of a firmware node is present
|
||
|
+ * @fwnode: Firmware node whose property to check
|
||
|
+ * @propname: Name of the property
|
||
|
+ */
|
||
|
+bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
|
||
|
+{
|
||
|
+ bool ret;
|
||
|
+
|
||
|
+ ret = __fwnode_property_present(fwnode, propname);
|
||
|
+ if (ret == false && fwnode->secondary)
|
||
|
+ ret = __fwnode_property_present(fwnode->secondary, propname);
|
||
|
+ return ret;
|
||
|
+}
|
||
|
EXPORT_SYMBOL_GPL(fwnode_property_present);
|
||
|
|
||
|
/**
|
||
|
@@ -408,7 +419,7 @@ EXPORT_SYMBOL_GPL(device_property_match_string);
|
||
|
(val) ? pset_prop_read_##type##_array((node), (propname), (val), (nval)) \
|
||
|
: pset_prop_count_elems_of_size((node), (propname), sizeof(type))
|
||
|
|
||
|
-#define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \
|
||
|
+#define FWNODE_PROP_READ(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \
|
||
|
({ \
|
||
|
int _ret_; \
|
||
|
if (is_of_node(_fwnode_)) \
|
||
|
@@ -425,6 +436,17 @@ EXPORT_SYMBOL_GPL(device_property_match_string);
|
||
|
_ret_; \
|
||
|
})
|
||
|
|
||
|
+#define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \
|
||
|
+({ \
|
||
|
+ int _ret_; \
|
||
|
+ _ret_ = FWNODE_PROP_READ(_fwnode_, _propname_, _type_, _proptype_, \
|
||
|
+ _val_, _nval_); \
|
||
|
+ if (_ret_ == -EINVAL && _fwnode_->secondary) \
|
||
|
+ _ret_ = FWNODE_PROP_READ(_fwnode_->secondary, _propname_, _type_, \
|
||
|
+ _proptype_, _val_, _nval_); \
|
||
|
+ _ret_; \
|
||
|
+})
|
||
|
+
|
||
|
/**
|
||
|
* fwnode_property_read_u8_array - return a u8 array property of firmware node
|
||
|
* @fwnode: Firmware node to get the property of
|
||
|
@@ -529,6 +551,41 @@ int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
|
||
|
}
|
||
|
EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array);
|
||
|
|
||
|
+static int __fwnode_property_read_string_array(struct fwnode_handle *fwnode,
|
||
|
+ const char *propname,
|
||
|
+ const char **val, size_t nval)
|
||
|
+{
|
||
|
+ if (is_of_node(fwnode))
|
||
|
+ return val ?
|
||
|
+ of_property_read_string_array(to_of_node(fwnode),
|
||
|
+ propname, val, nval) :
|
||
|
+ of_property_count_strings(to_of_node(fwnode), propname);
|
||
|
+ else if (is_acpi_node(fwnode))
|
||
|
+ return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
|
||
|
+ val, nval);
|
||
|
+ else if (is_pset_node(fwnode))
|
||
|
+ return val ?
|
||
|
+ pset_prop_read_string_array(to_pset_node(fwnode),
|
||
|
+ propname, val, nval) :
|
||
|
+ pset_prop_count_elems_of_size(to_pset_node(fwnode),
|
||
|
+ propname,
|
||
|
+ sizeof(const char *));
|
||
|
+ return -ENXIO;
|
||
|
+}
|
||
|
+
|
||
|
+static int __fwnode_property_read_string(struct fwnode_handle *fwnode,
|
||
|
+ const char *propname, const char **val)
|
||
|
+{
|
||
|
+ if (is_of_node(fwnode))
|
||
|
+ return of_property_read_string(to_of_node(fwnode), propname, val);
|
||
|
+ else if (is_acpi_node(fwnode))
|
||
|
+ return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
|
||
|
+ val, 1);
|
||
|
+ else if (is_pset_node(fwnode))
|
||
|
+ return pset_prop_read_string(to_pset_node(fwnode), propname, val);
|
||
|
+ return -ENXIO;
|
||
|
+}
|
||
|
+
|
||
|
/**
|
||
|
* fwnode_property_read_string_array - return string array property of a node
|
||
|
* @fwnode: Firmware node to get the property of
|
||
|
@@ -551,22 +608,13 @@ int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
|
||
|
const char *propname, const char **val,
|
||
|
size_t nval)
|
||
|
{
|
||
|
- if (is_of_node(fwnode))
|
||
|
- return val ?
|
||
|
- of_property_read_string_array(to_of_node(fwnode),
|
||
|
- propname, val, nval) :
|
||
|
- of_property_count_strings(to_of_node(fwnode), propname);
|
||
|
- else if (is_acpi_node(fwnode))
|
||
|
- return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
|
||
|
- val, nval);
|
||
|
- else if (is_pset_node(fwnode))
|
||
|
- return val ?
|
||
|
- pset_prop_read_string_array(to_pset_node(fwnode),
|
||
|
- propname, val, nval) :
|
||
|
- pset_prop_count_elems_of_size(to_pset_node(fwnode),
|
||
|
- propname,
|
||
|
- sizeof(const char *));
|
||
|
- return -ENXIO;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ ret = __fwnode_property_read_string_array(fwnode, propname, val, nval);
|
||
|
+ if (ret == -EINVAL && fwnode->secondary)
|
||
|
+ ret = __fwnode_property_read_string_array(fwnode->secondary,
|
||
|
+ propname, val, nval);
|
||
|
+ return ret;
|
||
|
}
|
||
|
EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
|
||
|
|
||
|
@@ -588,14 +636,13 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
|
||
|
int fwnode_property_read_string(struct fwnode_handle *fwnode,
|
||
|
const char *propname, const char **val)
|
||
|
{
|
||
|
- if (is_of_node(fwnode))
|
||
|
- return of_property_read_string(to_of_node(fwnode), propname, val);
|
||
|
- else if (is_acpi_node(fwnode))
|
||
|
- return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
|
||
|
- val, 1);
|
||
|
- else if (is_pset_node(fwnode))
|
||
|
- return pset_prop_read_string(to_pset_node(fwnode), propname, val);
|
||
|
- return -ENXIO;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ ret = __fwnode_property_read_string(fwnode, propname, val);
|
||
|
+ if (ret == -EINVAL && fwnode->secondary)
|
||
|
+ ret = __fwnode_property_read_string(fwnode->secondary,
|
||
|
+ propname, val);
|
||
|
+ return ret;
|
||
|
}
|
||
|
EXPORT_SYMBOL_GPL(fwnode_property_read_string);
|
||
|
|
||
|
--
|
||
|
2.5.0
|
||
|
|