All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/5] Move firmware specific code to firmware specific locations
@ 2017-05-04  7:14 Sakari Ailus
  2017-05-04  7:14 ` [PATCH v5 1/5] of: Add of_graph_get_port_parent() to obtain a port's parent node Sakari Ailus
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Sakari Ailus @ 2017-05-04  7:14 UTC (permalink / raw)
  To: linux-acpi
  Cc: devicetree, sudeep.holla, lorenzo.pieralisi, mika.westerberg,
	rafael, mark.rutland, broonie, robh, ahs3, frowand.list

Hi folks,

This set moves firmware specific implementations of the device / fwnode 
property API to locations that are specific to firmware implementation, 
still leaving property set (which isn't really firmware) implementation in
drivers/base/property.c.

since v3 (the cover page for v4 was unfortunately lost):

- Rebased on linux-next.

- Depend on "of: Move OF property and graph API from base.c to property.c"
  posted to devicetree list yesterday. My thinking is this would be better
  go through Rob's tree. Thinking about it more, the first patch in this
  set should, too.

- In the old set, patch 1 ("device property: Read strings using string
  array reading functions") has since been merged to linux-pm tree. Patch
  2 ("device property: Implement fwnode_get_next_parent() using fwnode
  interface") was squashed to "device property: Add
  fwnode_get_next_parent()" which is in linux-pm as well.

- Refactor the implementation of fwnode graph operations in order to
  implement basic operations in a firmware specific way separately from
  the common part. In particular, graph_get_remote_port() and
  graph_get_remote_port_parent() have been replaced by
  graph_get_port_parent().

- Added patches 5 and 6 to implement fwnode variant of
  fwnode_graph_get_remote_node() which is seen as a better API for many
  (or most) drivers than the other graph API primitives.

since v2:

- Move patches changing the implementation of reading strings and
  implementing fwnode_get_next_parent() using the fwnode interface alone
  in front of the set. I kept them separate as they do change the
  implementation of these operations.

- Merge patches adding the fwnode_operations and moving the
  implementations of the non-graph portions of the fwnode property API to
  firmware specific locations.

- Merge moving graph operations to the same struct into another patch.
  The graph operations in the ops struct are also added in this patch now.

since v1: 

- Move the three bugfixes in front of the set into a separate patchset. 
  There are no dependencies to those from the rest of the patches.

- Rebase on current ACPI graph support patches (themselves on PM tree 
  4.11-rc1 merge).

<URL:http://www.spinics.net/lists/linux-acpi/msg72895.html>

Sakari Ailus (5):
  of: Add of_graph_get_port_parent() to obtain a port's parent node
  device property: Move FW type specific functionality to FW specific
    files
  device property: Move fwnode graph ops to firmware specific locations
  device property: Introduce fwnode_device_is_available()
  device property: Add FW type agnostic fwnode_graph_get_remote_node

 drivers/acpi/property.c  | 126 ++++++++++++++++++
 drivers/acpi/scan.c      |   1 +
 drivers/base/property.c  | 337 +++++++++++++++++++----------------------------
 drivers/of/property.c    | 197 +++++++++++++++++++++++++--
 include/linux/acpi.h     |   4 +
 include/linux/fwnode.h   |  66 ++++++++++
 include/linux/of.h       |   2 +
 include/linux/property.h |   3 +
 8 files changed, 524 insertions(+), 212 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v5 1/5] of: Add of_graph_get_port_parent() to obtain a port's parent node
  2017-05-04  7:14 [PATCH v5 0/5] Move firmware specific code to firmware specific locations Sakari Ailus
@ 2017-05-04  7:14 ` Sakari Ailus
  2017-05-04  7:14 ` [PATCH v5 2/5] device property: Move FW type specific functionality to FW specific files Sakari Ailus
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Sakari Ailus @ 2017-05-04  7:14 UTC (permalink / raw)
  To: linux-acpi
  Cc: devicetree, sudeep.holla, lorenzo.pieralisi, mika.westerberg,
	rafael, mark.rutland, broonie, robh, ahs3, frowand.list

Split off obtaining a port's parent node. This will be soon needed for
implementing the fwnode ops.

Depends-on: ("of: Move OF property and graph API from base.c to property.c")
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/of/property.c | 35 +++++++++++++++++++++++++++--------
 1 file changed, 27 insertions(+), 8 deletions(-)

diff --git a/drivers/of/property.c b/drivers/of/property.c
index e5d3e1f..cf704f4 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -681,6 +681,30 @@ struct device_node *of_graph_get_endpoint_by_regs(
 EXPORT_SYMBOL(of_graph_get_endpoint_by_regs);
 
 /**
+ * of_graph_get_port_parent() - get port's parent node
+ * @node: pointer to a port node
+ *
+ * Return: Device node which is the parent of the given port node
+ *	   @node. Use of_node_put() on it when done.
+ */
+static struct device_node *
+of_graph_get_port_parent(struct device_node *node)
+{
+	struct device_node *np;
+
+	/* Get the parent of the port */
+	np = of_get_next_parent(node);
+	if (!np)
+		return NULL;
+
+	/* Is there "ports" node? If not, return it. */
+	if (of_node_cmp(np->name, "ports"))
+		return np;
+
+	return of_get_next_parent(np);
+}
+
+/**
  * of_graph_get_remote_port_parent() - get remote port's parent node
  * @node: pointer to a local endpoint device_node
  *
@@ -691,18 +715,13 @@ struct device_node *of_graph_get_remote_port_parent(
 			       const struct device_node *node)
 {
 	struct device_node *np;
-	unsigned int depth;
 
 	/* Get remote endpoint node. */
 	np = of_parse_phandle(node, "remote-endpoint", 0);
+	if (!np)
+		return NULL;
 
-	/* Walk 3 levels up only if there is 'ports' node. */
-	for (depth = 3; depth && np; depth--) {
-		np = of_get_next_parent(np);
-		if (depth == 2 && of_node_cmp(np->name, "ports"))
-			break;
-	}
-	return np;
+	return of_graph_get_port_parent(of_get_next_parent(np));
 }
 EXPORT_SYMBOL(of_graph_get_remote_port_parent);
 
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v5 2/5] device property: Move FW type specific functionality to FW specific files
  2017-05-04  7:14 [PATCH v5 0/5] Move firmware specific code to firmware specific locations Sakari Ailus
  2017-05-04  7:14 ` [PATCH v5 1/5] of: Add of_graph_get_port_parent() to obtain a port's parent node Sakari Ailus
@ 2017-05-04  7:14 ` Sakari Ailus
  2017-05-04  7:14 ` [PATCH v5 3/5] device property: Move fwnode graph ops to firmware specific locations Sakari Ailus
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Sakari Ailus @ 2017-05-04  7:14 UTC (permalink / raw)
  To: linux-acpi
  Cc: devicetree, sudeep.holla, lorenzo.pieralisi, mika.westerberg,
	rafael, mark.rutland, broonie, robh, ahs3, frowand.list

The device and fwnode property API supports Devicetree, ACPI and pset
properties. The implementation of this functionality for each firmware
type was embedded in the fwnode property core. Move it out to firmware
type specific locations, making it easier to maintain.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/acpi/property.c |  72 +++++++++++++++++
 drivers/acpi/scan.c     |   1 +
 drivers/base/property.c | 206 +++++++++++++++++++-----------------------------
 drivers/of/property.c   |  99 +++++++++++++++++++++++
 include/linux/acpi.h    |   4 +
 include/linux/fwnode.h  |  53 +++++++++++++
 include/linux/of.h      |   2 +
 7 files changed, 312 insertions(+), 125 deletions(-)

diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index 9364398..fb3b96f 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -57,6 +57,7 @@ static bool acpi_nondev_subnode_extract(const union acpi_object *desc,
 
 	dn->name = link->package.elements[0].string.pointer;
 	dn->fwnode.type = FWNODE_ACPI_DATA;
+	dn->fwnode.ops = &acpi_fwnode_ops;
 	dn->parent = parent;
 	INIT_LIST_HEAD(&dn->data.subnodes);
 
@@ -1119,3 +1120,74 @@ int acpi_graph_get_remote_endpoint(struct fwnode_handle *fwnode,
 
 	return 0;
 }
+
+static bool acpi_fwnode_property_present(struct fwnode_handle *fwnode,
+					 const char *propname)
+{
+	return !acpi_node_prop_get(fwnode, propname, NULL);
+}
+
+static int acpi_fwnode_property_read_int_array(
+	struct fwnode_handle *fwnode, const char *propname,
+	unsigned int elem_size, void *val, size_t nval)
+{
+	enum dev_prop_type type;
+
+	switch (elem_size) {
+	case sizeof(u8):
+		type = DEV_PROP_U8;
+		break;
+	case sizeof(u16):
+		type = DEV_PROP_U16;
+		break;
+	case sizeof(u32):
+		type = DEV_PROP_U32;
+		break;
+	case sizeof(u64):
+		type = DEV_PROP_U64;
+		break;
+	default:
+		return -ENXIO;
+	}
+
+	return acpi_node_prop_read(fwnode, propname, type, val, nval);
+}
+
+static int acpi_fwnode_property_read_string_array(
+	struct fwnode_handle *fwnode, const char *propname, const char **val,
+	size_t nval)
+{
+	return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
+				   val, nval);
+}
+
+static struct fwnode_handle *acpi_fwnode_get_parent(
+	struct fwnode_handle *fwnode)
+{
+	return acpi_node_get_parent(fwnode);
+}
+
+static struct fwnode_handle *acpi_fwnode_get_named_child_node(
+	struct fwnode_handle *fwnode, const char *childname)
+{
+	struct fwnode_handle *child;
+
+	/*
+	 * Find first matching named child node of this fwnode.
+	 * For ACPI this will be a data only sub-node.
+	 */
+	fwnode_for_each_child_node(fwnode, child)
+		if (acpi_data_node_match(child, childname))
+			return child;
+
+	return NULL;
+}
+
+const struct fwnode_operations acpi_fwnode_ops = {
+	.property_present = acpi_fwnode_property_present,
+	.property_read_int_array = acpi_fwnode_property_read_int_array,
+	.property_read_string_array = acpi_fwnode_property_read_string_array,
+	.get_parent = acpi_fwnode_get_parent,
+	.get_next_child_node = acpi_get_next_subnode,
+	.get_named_child_node = acpi_fwnode_get_named_child_node,
+};
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index e39ec7b..3db9192 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1436,6 +1436,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
 	device->handle = handle;
 	device->parent = acpi_bus_get_parent(handle);
 	device->fwnode.type = FWNODE_ACPI;
+	device->fwnode.ops = &acpi_fwnode_ops;
 	acpi_set_device_status(device, sta);
 	acpi_device_get_busid(device);
 	acpi_set_pnp_ids(handle, &device->pnp, type);
diff --git a/drivers/base/property.c b/drivers/base/property.c
index 149de31..4dc5ab6 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -187,6 +187,49 @@ struct fwnode_handle *dev_fwnode(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(dev_fwnode);
 
+static bool pset_fwnode_property_present(struct fwnode_handle *fwnode,
+					 const char *propname)
+{
+	return !!pset_prop_get(to_pset_node(fwnode), propname);
+}
+
+static int pset_fwnode_read_int_array(
+	struct fwnode_handle *fwnode, const char *propname,
+	unsigned int elem_size, void *val, size_t nval)
+{
+	struct property_set *node = to_pset_node(fwnode);
+
+	if (!val)
+		return pset_prop_count_elems_of_size(node, propname, elem_size);
+
+	switch (elem_size) {
+	case sizeof(u8):
+		return pset_prop_read_u8_array(node, propname, val, nval);
+	case sizeof(u16):
+		return pset_prop_read_u16_array(node, propname, val, nval);
+	case sizeof(u32):
+		return pset_prop_read_u32_array(node, propname, val, nval);
+	case sizeof(u64):
+		return pset_prop_read_u64_array(node, propname, val, nval);
+	}
+
+	return -ENXIO;
+}
+
+static int pset_fwnode_property_read_string_array(
+	struct fwnode_handle *fwnode, const char *propname, const char **val,
+	size_t nval)
+{
+	return pset_prop_read_string_array(to_pset_node(fwnode), propname,
+					   val, nval);
+}
+
+static const struct fwnode_operations pset_fwnode_ops = {
+	.property_present = pset_fwnode_property_present,
+	.property_read_int_array = pset_fwnode_read_int_array,
+	.property_read_string_array = pset_fwnode_property_read_string_array,
+};
+
 /**
  * device_property_present - check if a property of a device is present
  * @dev: Device whose property is being checked
@@ -200,18 +243,6 @@ bool device_property_present(struct device *dev, const char *propname)
 }
 EXPORT_SYMBOL_GPL(device_property_present);
 
-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);
-	else if (is_acpi_node(fwnode))
-		return !acpi_node_prop_get(fwnode, propname, NULL);
-	else if (is_pset_node(fwnode))
-		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
@@ -221,10 +252,11 @@ bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
 {
 	bool ret;
 
-	ret = __fwnode_property_present(fwnode, propname);
+	ret = fwnode_call_int_op(fwnode, property_present, propname);
 	if (ret == false && !IS_ERR_OR_NULL(fwnode) &&
 	    !IS_ERR_OR_NULL(fwnode->secondary))
-		ret = __fwnode_property_present(fwnode->secondary, propname);
+		ret = fwnode_call_int_op(fwnode->secondary, property_present,
+					 propname);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(fwnode_property_present);
@@ -398,42 +430,22 @@ int device_property_match_string(struct device *dev, const char *propname,
 }
 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))
-
-#define PSET_PROP_READ_ARRAY(node, propname, type, val, nval)				\
-	(val) ? pset_prop_read_##type##_array((node), (propname), (val), (nval))	\
-	      : pset_prop_count_elems_of_size((node), (propname), sizeof(type))
-
-#define FWNODE_PROP_READ(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_)	\
-({											\
-	int _ret_;									\
-	if (is_of_node(_fwnode_))							\
-		_ret_ = OF_DEV_PROP_READ_ARRAY(to_of_node(_fwnode_), _propname_,	\
-					       _type_, _val_, _nval_);			\
-	else if (is_acpi_node(_fwnode_))						\
-		_ret_ = acpi_node_prop_read(_fwnode_, _propname_, _proptype_,		\
-					    _val_, _nval_);				\
-	else if (is_pset_node(_fwnode_)) 						\
-		_ret_ = PSET_PROP_READ_ARRAY(to_pset_node(_fwnode_), _propname_,	\
-					     _type_, _val_, _nval_);			\
-	else										\
-		_ret_ = -ENXIO;								\
-	_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 && !IS_ERR_OR_NULL(_fwnode_) &&				\
-	    !IS_ERR_OR_NULL(_fwnode_->secondary))					\
-		_ret_ = FWNODE_PROP_READ(_fwnode_->secondary, _propname_, _type_,	\
-				_proptype_, _val_, _nval_);				\
-	_ret_;										\
-})
+static int fwnode_property_read_int_array(
+	struct fwnode_handle *fwnode, const char *propname,
+	unsigned int elem_size, void *val, size_t nval)
+{
+	int ret;
+
+	ret = fwnode_call_int_op(fwnode, property_read_int_array, propname,
+				 elem_size, val, nval);
+	if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) &&
+	    !IS_ERR_OR_NULL(fwnode->secondary))
+		ret = fwnode_call_int_op(
+			fwnode->secondary, property_read_int_array, propname,
+			elem_size, val, nval);
+
+	return ret;
+}
 
 /**
  * fwnode_property_read_u8_array - return a u8 array property of firmware node
@@ -456,8 +468,8 @@ EXPORT_SYMBOL_GPL(device_property_match_string);
 int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
 				  const char *propname, u8 *val, size_t nval)
 {
-	return FWNODE_PROP_READ_ARRAY(fwnode, propname, u8, DEV_PROP_U8,
-				      val, nval);
+	return fwnode_property_read_int_array(fwnode, propname, sizeof(u8),
+					      val, nval);
 }
 EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array);
 
@@ -482,8 +494,8 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array);
 int fwnode_property_read_u16_array(struct fwnode_handle *fwnode,
 				   const char *propname, u16 *val, size_t nval)
 {
-	return FWNODE_PROP_READ_ARRAY(fwnode, propname, u16, DEV_PROP_U16,
-				      val, nval);
+	return fwnode_property_read_int_array(fwnode, propname, sizeof(u16),
+					      val, nval);
 }
 EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array);
 
@@ -508,8 +520,8 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array);
 int fwnode_property_read_u32_array(struct fwnode_handle *fwnode,
 				   const char *propname, u32 *val, size_t nval)
 {
-	return FWNODE_PROP_READ_ARRAY(fwnode, propname, u32, DEV_PROP_U32,
-				      val, nval);
+	return fwnode_property_read_int_array(fwnode, propname, sizeof(u32),
+					      val, nval);
 }
 EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array);
 
@@ -534,29 +546,11 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array);
 int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
 				   const char *propname, u64 *val, size_t nval)
 {
-	return FWNODE_PROP_READ_ARRAY(fwnode, propname, u64, DEV_PROP_U64,
-				      val, nval);
+	return fwnode_property_read_int_array(fwnode, propname, sizeof(u64),
+					      val, nval);
 }
 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 pset_prop_read_string_array(to_pset_node(fwnode),
-						   propname, val, nval);
-	return -ENXIO;
-}
-
 /**
  * fwnode_property_read_string_array - return string array property of a node
  * @fwnode: Firmware node to get the property of
@@ -581,11 +575,13 @@ int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
 {
 	int ret;
 
-	ret = __fwnode_property_read_string_array(fwnode, propname, val, nval);
+	ret = fwnode_call_int_op(fwnode, property_read_string_array, propname,
+				 val, nval);
 	if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) &&
 	    !IS_ERR_OR_NULL(fwnode->secondary))
-		ret = __fwnode_property_read_string_array(fwnode->secondary,
-							  propname, val, nval);
+		ret = fwnode_call_int_op(fwnode->secondary,
+					 property_read_string_array, propname,
+					 val, nval);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
@@ -903,6 +899,7 @@ int device_add_properties(struct device *dev,
 		return PTR_ERR(p);
 
 	p->fwnode.type = FWNODE_PDATA;
+	p->fwnode.ops = &pset_fwnode_ops;
 	set_secondary_fwnode(dev, &p->fwnode);
 	return 0;
 }
@@ -938,19 +935,7 @@ EXPORT_SYMBOL_GPL(fwnode_get_next_parent);
  */
 struct fwnode_handle *fwnode_get_parent(struct fwnode_handle *fwnode)
 {
-	struct fwnode_handle *parent = NULL;
-
-	if (is_of_node(fwnode)) {
-		struct device_node *node;
-
-		node = of_get_parent(to_of_node(fwnode));
-		if (node)
-			parent = &node->fwnode;
-	} else if (is_acpi_node(fwnode)) {
-		parent = acpi_node_get_parent(fwnode);
-	}
-
-	return parent;
+	return fwnode_call_ptr_op(fwnode, get_parent);
 }
 EXPORT_SYMBOL_GPL(fwnode_get_parent);
 
@@ -962,18 +947,7 @@ EXPORT_SYMBOL_GPL(fwnode_get_parent);
 struct fwnode_handle *fwnode_get_next_child_node(struct fwnode_handle *fwnode,
 						 struct fwnode_handle *child)
 {
-	if (is_of_node(fwnode)) {
-		struct device_node *node;
-
-		node = of_get_next_available_child(to_of_node(fwnode),
-						   to_of_node(child));
-		if (node)
-			return &node->fwnode;
-	} else if (is_acpi_node(fwnode)) {
-		return acpi_get_next_subnode(fwnode, child);
-	}
-
-	return NULL;
+	return fwnode_call_ptr_op(fwnode, get_next_child_node, child);
 }
 EXPORT_SYMBOL_GPL(fwnode_get_next_child_node);
 
@@ -1005,23 +979,7 @@ EXPORT_SYMBOL_GPL(device_get_next_child_node);
 struct fwnode_handle *fwnode_get_named_child_node(struct fwnode_handle *fwnode,
 						  const char *childname)
 {
-	struct fwnode_handle *child;
-
-	/*
-	 * Find first matching named child node of this fwnode.
-	 * For ACPI this will be a data only sub-node.
-	 */
-	fwnode_for_each_child_node(fwnode, child) {
-		if (is_of_node(child)) {
-			if (!of_node_cmp(to_of_node(child)->name, childname))
-				return child;
-		} else if (is_acpi_data_node(child)) {
-			if (acpi_data_node_match(child, childname))
-				return child;
-		}
-	}
-
-	return NULL;
+	return fwnode_call_ptr_op(fwnode, get_named_child_node, childname);
 }
 EXPORT_SYMBOL_GPL(fwnode_get_named_child_node);
 
@@ -1043,8 +1001,7 @@ EXPORT_SYMBOL_GPL(device_get_named_child_node);
  */
 void fwnode_handle_get(struct fwnode_handle *fwnode)
 {
-	if (is_of_node(fwnode))
-		of_node_get(to_of_node(fwnode));
+	fwnode_call_void_op(fwnode, get);
 }
 EXPORT_SYMBOL_GPL(fwnode_handle_get);
 
@@ -1058,8 +1015,7 @@ EXPORT_SYMBOL_GPL(fwnode_handle_get);
  */
 void fwnode_handle_put(struct fwnode_handle *fwnode)
 {
-	if (is_of_node(fwnode))
-		of_node_put(to_of_node(fwnode));
+	fwnode_call_void_op(fwnode, put);
 }
 EXPORT_SYMBOL_GPL(fwnode_handle_put);
 
diff --git a/drivers/of/property.c b/drivers/of/property.c
index cf704f4..984e37e 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -780,3 +780,102 @@ struct device_node *of_graph_get_remote_node(const struct device_node *node,
 	return remote;
 }
 EXPORT_SYMBOL(of_graph_get_remote_node);
+
+static void of_fwnode_get(struct fwnode_handle *fwnode)
+{
+	of_node_get(to_of_node(fwnode));
+}
+
+static void of_fwnode_put(struct fwnode_handle *fwnode)
+{
+	of_node_put(to_of_node(fwnode));
+}
+
+static bool of_fwnode_property_present(struct fwnode_handle *fwnode,
+				       const char *propname)
+{
+	return of_property_read_bool(to_of_node(fwnode), propname);
+}
+
+static int of_fwnode_property_read_int_array(
+	struct fwnode_handle *fwnode, const char *propname,
+	unsigned int elem_size, void *val, size_t nval)
+{
+	struct device_node *node = to_of_node(fwnode);
+
+	if (!val)
+		return of_property_count_elems_of_size(node, propname,
+						       elem_size);
+
+	switch (elem_size) {
+	case sizeof(u8):
+		return of_property_read_u8_array(node, propname, val, nval);
+	case sizeof(u16):
+		return of_property_read_u16_array(node, propname, val, nval);
+	case sizeof(u32):
+		return of_property_read_u32_array(node, propname, val, nval);
+	case sizeof(u64):
+		return of_property_read_u64_array(node, propname, val, nval);
+	}
+
+	return -ENXIO;
+}
+
+static int of_fwnode_property_read_string_array(
+	struct fwnode_handle *fwnode, const char *propname,
+	const char **val, size_t nval)
+{
+	struct device_node *node = to_of_node(fwnode);
+
+	return val ?
+		of_property_read_string_array(node, propname, val, nval) :
+		of_property_count_strings(node, propname);
+}
+
+static struct fwnode_handle *of_fwnode_get_parent(struct fwnode_handle *fwnode)
+{
+	struct device_node *node;
+
+	node = of_get_parent(to_of_node(fwnode));
+	if (node)
+		return of_fwnode_handle(node);
+
+	return NULL;
+}
+
+static struct fwnode_handle *of_fwnode_get_next_child_node(
+	struct fwnode_handle *fwnode, struct fwnode_handle *child)
+{
+	struct device_node *node;
+
+	node = of_get_next_available_child(to_of_node(fwnode),
+					   to_of_node(child));
+	if (node)
+		return of_fwnode_handle(node);
+
+	return NULL;
+}
+
+static struct fwnode_handle *of_fwnode_get_named_child_node(
+	struct fwnode_handle *fwnode, const char *childname)
+{
+	struct device_node *node = to_of_node(fwnode);
+	struct device_node *child;
+
+	for_each_available_child_of_node(node, child)
+		if (!of_node_cmp(child->name, childname))
+			return of_fwnode_handle(child);
+
+	return NULL;
+}
+
+const struct fwnode_operations of_fwnode_ops = {
+	.get = of_fwnode_get,
+	.put = of_fwnode_put,
+	.property_present = of_fwnode_property_present,
+	.property_read_int_array = of_fwnode_property_read_int_array,
+	.property_read_string_array = of_fwnode_property_read_string_array,
+	.get_parent = of_fwnode_get_parent,
+	.get_next_child_node = of_fwnode_get_next_child_node,
+	.get_named_child_node = of_fwnode_get_named_child_node,
+};
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 137e4a3..b8f23c5 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -56,6 +56,9 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev)
 	acpi_fwnode_handle(adev) : NULL)
 #define ACPI_HANDLE(dev)		acpi_device_handle(ACPI_COMPANION(dev))
 
+
+extern const struct fwnode_operations acpi_fwnode_ops;
+
 static inline struct fwnode_handle *acpi_alloc_fwnode_static(void)
 {
 	struct fwnode_handle *fwnode;
@@ -65,6 +68,7 @@ static inline struct fwnode_handle *acpi_alloc_fwnode_static(void)
 		return NULL;
 
 	fwnode->type = FWNODE_ACPI_STATIC;
+	fwnode->ops = &acpi_fwnode_ops;
 
 	return fwnode;
 }
diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
index 3dff239..e05aaef 100644
--- a/include/linux/fwnode.h
+++ b/include/linux/fwnode.h
@@ -12,6 +12,8 @@
 #ifndef _LINUX_FWNODE_H_
 #define _LINUX_FWNODE_H_
 
+#include <linux/types.h>
+
 enum fwnode_type {
 	FWNODE_INVALID = 0,
 	FWNODE_OF,
@@ -22,9 +24,12 @@ enum fwnode_type {
 	FWNODE_IRQCHIP
 };
 
+struct fwnode_operations;
+
 struct fwnode_handle {
 	enum fwnode_type type;
 	struct fwnode_handle *secondary;
+	const struct fwnode_operations *ops;
 };
 
 /**
@@ -39,4 +44,52 @@ struct fwnode_endpoint {
 	const struct fwnode_handle *local_fwnode;
 };
 
+/**
+ * struct fwnode_operations - Operations for fwnode interface
+ * @get: Get a reference to an fwnode.
+ * @put: Put a reference to an fwnode.
+ * @property_present: Return true if a property is present.
+ * @property_read_integer_array: Read an array of integer properties. Return
+ *				 zero on success, a negative error code
+ *				 otherwise.
+ * @property_read_string_array: Read an array of string properties. Return zero
+ *				on success, a negative error code otherwise.
+ * @get_parent: Return the parent of an fwnode.
+ * @get_next_child_node: Return the next child node in an iteration.
+ * @get_named_child_node: Return a child node with a given name.
+ */
+struct fwnode_operations {
+	void (*get)(struct fwnode_handle *fwnode);
+	void (*put)(struct fwnode_handle *fwnode);
+	bool (*property_present)(struct fwnode_handle *fwnode,
+				 const char *propname);
+	int (*property_read_int_array)(struct fwnode_handle *fwnode,
+				       const char *propname,
+				       unsigned int elem_size, void *val,
+				       size_t nval);
+	int (*property_read_string_array)(struct fwnode_handle *fwnode_handle,
+					  const char *propname,
+					  const char **val, size_t nval);
+	struct fwnode_handle *(*get_parent)(struct fwnode_handle *fwnode);
+	struct fwnode_handle *(*get_next_child_node)(
+		struct fwnode_handle *fwnode, struct fwnode_handle *child);
+	struct fwnode_handle *(*get_named_child_node)(
+		struct fwnode_handle *fwnode, const char *name);
+};
+
+#define fwnode_has_op(fwnode, op)				\
+	((fwnode) && (fwnode)->ops && (fwnode)->ops->op)
+#define fwnode_call_int_op(fwnode, op, ...)				\
+	(fwnode ? (fwnode_has_op(fwnode, op) ?				\
+		   (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : -ENXIO) : \
+	 -EINVAL)
+#define fwnode_call_ptr_op(fwnode, op, ...)		\
+	(fwnode_has_op(fwnode, op) ?			\
+	 (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : NULL)
+#define fwnode_call_void_op(fwnode, op, ...)				\
+	do {								\
+		if (fwnode_has_op(fwnode, op))				\
+			(fwnode)->ops->op(fwnode, ## __VA_ARGS__);	\
+	} while (false)
+
 #endif
diff --git a/include/linux/of.h b/include/linux/of.h
index 50fcdb5..64f4cd6 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -100,10 +100,12 @@ struct of_reconfig_data {
 
 /* initialize a node */
 extern struct kobj_type of_node_ktype;
+extern const struct fwnode_operations of_fwnode_ops;
 static inline void of_node_init(struct device_node *node)
 {
 	kobject_init(&node->kobj, &of_node_ktype);
 	node->fwnode.type = FWNODE_OF;
+	node->fwnode.ops = &of_fwnode_ops;
 }
 
 /* true when node is initialized */
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v5 3/5] device property: Move fwnode graph ops to firmware specific locations
  2017-05-04  7:14 [PATCH v5 0/5] Move firmware specific code to firmware specific locations Sakari Ailus
  2017-05-04  7:14 ` [PATCH v5 1/5] of: Add of_graph_get_port_parent() to obtain a port's parent node Sakari Ailus
  2017-05-04  7:14 ` [PATCH v5 2/5] device property: Move FW type specific functionality to FW specific files Sakari Ailus
@ 2017-05-04  7:14 ` Sakari Ailus
       [not found]   ` <1493882051-28814-4-git-send-email-sakari.ailus-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
  2017-05-04  7:14 ` [PATCH v5 4/5] device property: Introduce fwnode_device_is_available() Sakari Ailus
  2017-05-04  7:14 ` [PATCH v5 5/5] device property: Add FW type agnostic fwnode_graph_get_remote_node Sakari Ailus
  4 siblings, 1 reply; 8+ messages in thread
From: Sakari Ailus @ 2017-05-04  7:14 UTC (permalink / raw)
  To: linux-acpi
  Cc: devicetree, sudeep.holla, lorenzo.pieralisi, mika.westerberg,
	rafael, mark.rutland, broonie, robh, ahs3, frowand.list

Move firmware specific implementations of the fwnode graph operations to
firmware specific locations.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/acpi/property.c | 45 +++++++++++++++++++++++
 drivers/base/property.c | 96 ++++++-------------------------------------------
 drivers/of/property.c   | 57 +++++++++++++++++++++++++++++
 include/linux/fwnode.h  | 12 +++++++
 4 files changed, 125 insertions(+), 85 deletions(-)

diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index fb3b96f..d26f24d 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -1183,6 +1183,47 @@ static struct fwnode_handle *acpi_fwnode_get_named_child_node(
 	return NULL;
 }
 
+static struct fwnode_handle *acpi_fwnode_graph_get_next_endpoint(
+	struct fwnode_handle *fwnode, struct fwnode_handle *prev)
+{
+	struct fwnode_handle *endpoint;
+
+	endpoint = acpi_graph_get_next_endpoint(fwnode, prev);
+	if (IS_ERR(endpoint))
+		return NULL;
+
+	return endpoint;
+}
+
+static struct fwnode_handle *acpi_fwnode_graph_get_remote_endpoint(
+	struct fwnode_handle *fwnode)
+{
+	struct fwnode_handle *endpoint = NULL;
+
+	acpi_graph_get_remote_endpoint(fwnode, NULL, NULL, &endpoint);
+
+	return endpoint;
+}
+
+static struct fwnode_handle *acpi_fwnode_graph_get_port_parent(
+	struct fwnode_handle *fwnode)
+{
+	return acpi_node_get_parent(fwnode);
+}
+
+static int acpi_fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode,
+					    struct fwnode_endpoint *endpoint)
+{
+	struct fwnode_handle *port_fwnode = fwnode_get_parent(fwnode);
+
+	endpoint->local_fwnode = fwnode;
+
+	fwnode_property_read_u32(port_fwnode, "port", &endpoint->port);
+	fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id);
+
+	return 0;
+}
+
 const struct fwnode_operations acpi_fwnode_ops = {
 	.property_present = acpi_fwnode_property_present,
 	.property_read_int_array = acpi_fwnode_property_read_int_array,
@@ -1190,4 +1231,8 @@ const struct fwnode_operations acpi_fwnode_ops = {
 	.get_parent = acpi_fwnode_get_parent,
 	.get_next_child_node = acpi_get_next_subnode,
 	.get_named_child_node = acpi_fwnode_get_named_child_node,
+	.graph_get_next_endpoint = acpi_fwnode_graph_get_next_endpoint,
+	.graph_get_remote_endpoint = acpi_fwnode_graph_get_remote_endpoint,
+	.graph_get_port_parent = acpi_fwnode_graph_get_port_parent,
+	.graph_parse_endpoint = acpi_fwnode_graph_parse_endpoint,
 };
diff --git a/drivers/base/property.c b/drivers/base/property.c
index 4dc5ab6..6eccc4e 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1154,24 +1154,7 @@ struct fwnode_handle *
 fwnode_graph_get_next_endpoint(struct fwnode_handle *fwnode,
 			       struct fwnode_handle *prev)
 {
-	struct fwnode_handle *endpoint = NULL;
-
-	if (is_of_node(fwnode)) {
-		struct device_node *node;
-
-		node = of_graph_get_next_endpoint(to_of_node(fwnode),
-						  to_of_node(prev));
-
-		if (node)
-			endpoint = &node->fwnode;
-	} else if (is_acpi_node(fwnode)) {
-		endpoint = acpi_graph_get_next_endpoint(fwnode, prev);
-		if (IS_ERR(endpoint))
-			endpoint = NULL;
-	}
-
-	return endpoint;
-
+	return fwnode_call_ptr_op(fwnode, graph_get_next_endpoint, prev);
 }
 EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint);
 
@@ -1184,24 +1167,11 @@ EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint);
 struct fwnode_handle *
 fwnode_graph_get_remote_port_parent(struct fwnode_handle *fwnode)
 {
-	struct fwnode_handle *parent = NULL;
-
-	if (is_of_node(fwnode)) {
-		struct device_node *node;
-
-		node = of_graph_get_remote_port_parent(to_of_node(fwnode));
-		if (node)
-			parent = &node->fwnode;
-	} else if (is_acpi_node(fwnode)) {
-		int ret;
-
-		ret = acpi_graph_get_remote_endpoint(fwnode, &parent, NULL,
-						     NULL);
-		if (ret)
-			return NULL;
-	}
+	fwnode = fwnode_graph_get_remote_port(fwnode);
+	if (!fwnode)
+		return NULL;
 
-	return parent;
+	return fwnode_call_ptr_op(fwnode, graph_get_port_parent);
 }
 EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port_parent);
 
@@ -1213,23 +1183,11 @@ EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port_parent);
  */
 struct fwnode_handle *fwnode_graph_get_remote_port(struct fwnode_handle *fwnode)
 {
-	struct fwnode_handle *port = NULL;
-
-	if (is_of_node(fwnode)) {
-		struct device_node *node;
-
-		node = of_graph_get_remote_port(to_of_node(fwnode));
-		if (node)
-			port = &node->fwnode;
-	} else if (is_acpi_node(fwnode)) {
-		int ret;
-
-		ret = acpi_graph_get_remote_endpoint(fwnode, NULL, &port, NULL);
-		if (ret)
-			return NULL;
-	}
+	fwnode = fwnode_graph_get_remote_endpoint(fwnode);
+	if (!fwnode)
+		return NULL;
 
-	return port;
+	return fwnode_get_parent(fwnode);
 }
 EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port);
 
@@ -1242,25 +1200,7 @@ EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port);
 struct fwnode_handle *
 fwnode_graph_get_remote_endpoint(struct fwnode_handle *fwnode)
 {
-	struct fwnode_handle *endpoint = NULL;
-
-	if (is_of_node(fwnode)) {
-		struct device_node *node;
-
-		node = of_parse_phandle(to_of_node(fwnode), "remote-endpoint",
-					0);
-		if (node)
-			endpoint = &node->fwnode;
-	} else if (is_acpi_node(fwnode)) {
-		int ret;
-
-		ret = acpi_graph_get_remote_endpoint(fwnode, NULL, NULL,
-						     &endpoint);
-		if (ret)
-			return NULL;
-	}
-
-	return endpoint;
+	return fwnode_call_ptr_op(fwnode, graph_get_remote_endpoint);
 }
 EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_endpoint);
 
@@ -1276,22 +1216,8 @@ EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_endpoint);
 int fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode,
 				struct fwnode_endpoint *endpoint)
 {
-	struct fwnode_handle *port_fwnode = fwnode_get_parent(fwnode);
-
 	memset(endpoint, 0, sizeof(*endpoint));
 
-	endpoint->local_fwnode = fwnode;
-
-	if (is_acpi_node(port_fwnode)) {
-		fwnode_property_read_u32(port_fwnode, "port", &endpoint->port);
-		fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id);
-	} else {
-		fwnode_property_read_u32(port_fwnode, "reg", &endpoint->port);
-		fwnode_property_read_u32(fwnode, "reg", &endpoint->id);
-	}
-
-	fwnode_handle_put(port_fwnode);
-
-	return 0;
+	return fwnode_call_int_op(fwnode, graph_parse_endpoint, endpoint);
 }
 EXPORT_SYMBOL(fwnode_graph_parse_endpoint);
diff --git a/drivers/of/property.c b/drivers/of/property.c
index 984e37e..bb6ac73 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -869,6 +869,59 @@ static struct fwnode_handle *of_fwnode_get_named_child_node(
 	return NULL;
 }
 
+static struct fwnode_handle *of_fwnode_graph_get_next_endpoint(
+	struct fwnode_handle *fwnode, struct fwnode_handle *prev)
+{
+	struct device_node *node;
+
+	node = of_graph_get_next_endpoint(to_of_node(fwnode),
+					  to_of_node(prev));
+	if (node)
+		return of_fwnode_handle(node);
+
+	return NULL;
+}
+
+static struct fwnode_handle *of_fwnode_graph_get_remote_endpoint(
+	struct fwnode_handle *fwnode)
+{
+	struct device_node *node;
+
+	node = of_parse_phandle(to_of_node(fwnode), "remote-endpoint", 0);
+	if (node)
+		return of_fwnode_handle(node);
+
+	return NULL;
+}
+
+static struct fwnode_handle *of_fwnode_graph_get_port_parent(
+	struct fwnode_handle *fwnode)
+{
+	struct device_node *node;
+
+	node = of_graph_get_port_parent(to_of_node(fwnode));
+	if (node)
+		return of_fwnode_handle(node);
+
+	return NULL;
+}
+
+static int of_fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode,
+					  struct fwnode_endpoint *endpoint)
+{
+	struct device_node *node = to_of_node(fwnode);
+	struct device_node *port_node = of_get_parent(node);
+
+	endpoint->local_fwnode = fwnode;
+
+	of_property_read_u32(port_node, "reg", &endpoint->port);
+	of_property_read_u32(node, "reg", &endpoint->id);
+
+	of_node_put(port_node);
+
+	return 0;
+}
+
 const struct fwnode_operations of_fwnode_ops = {
 	.get = of_fwnode_get,
 	.put = of_fwnode_put,
@@ -878,4 +931,8 @@ const struct fwnode_operations of_fwnode_ops = {
 	.get_parent = of_fwnode_get_parent,
 	.get_next_child_node = of_fwnode_get_next_child_node,
 	.get_named_child_node = of_fwnode_get_named_child_node,
+	.graph_get_next_endpoint = of_fwnode_graph_get_next_endpoint,
+	.graph_get_remote_endpoint = of_fwnode_graph_get_remote_endpoint,
+	.graph_get_port_parent = of_fwnode_graph_get_port_parent,
+	.graph_parse_endpoint = of_fwnode_graph_parse_endpoint,
 };
diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
index e05aaef..35f6626 100644
--- a/include/linux/fwnode.h
+++ b/include/linux/fwnode.h
@@ -57,6 +57,10 @@ struct fwnode_endpoint {
  * @get_parent: Return the parent of an fwnode.
  * @get_next_child_node: Return the next child node in an iteration.
  * @get_named_child_node: Return a child node with a given name.
+ * @graph_get_next_endpoint: Return an endpoint node in an iteration.
+ * @graph_get_remote_endpoint: Return the remote endpoint node of a local
+ *			       endpoint node.
+ * @graph_get_port_parent: Return the parent node of a port node.
  */
 struct fwnode_operations {
 	void (*get)(struct fwnode_handle *fwnode);
@@ -75,6 +79,14 @@ struct fwnode_operations {
 		struct fwnode_handle *fwnode, struct fwnode_handle *child);
 	struct fwnode_handle *(*get_named_child_node)(
 		struct fwnode_handle *fwnode, const char *name);
+	struct fwnode_handle *(*graph_get_next_endpoint)(
+		struct fwnode_handle *fwnode, struct fwnode_handle *prev);
+	struct fwnode_handle *(*graph_get_remote_endpoint)(
+		struct fwnode_handle *fwnode);
+	struct fwnode_handle *(*graph_get_port_parent)(
+		struct fwnode_handle *fwnode);
+	int (*graph_parse_endpoint)(struct fwnode_handle *fwnode,
+				    struct fwnode_endpoint *endpoint);
 };
 
 #define fwnode_has_op(fwnode, op)				\
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v5 4/5] device property: Introduce fwnode_device_is_available()
  2017-05-04  7:14 [PATCH v5 0/5] Move firmware specific code to firmware specific locations Sakari Ailus
                   ` (2 preceding siblings ...)
  2017-05-04  7:14 ` [PATCH v5 3/5] device property: Move fwnode graph ops to firmware specific locations Sakari Ailus
@ 2017-05-04  7:14 ` Sakari Ailus
  2017-05-04  7:14 ` [PATCH v5 5/5] device property: Add FW type agnostic fwnode_graph_get_remote_node Sakari Ailus
  4 siblings, 0 replies; 8+ messages in thread
From: Sakari Ailus @ 2017-05-04  7:14 UTC (permalink / raw)
  To: linux-acpi
  Cc: devicetree, sudeep.holla, lorenzo.pieralisi, mika.westerberg,
	rafael, mark.rutland, broonie, robh, ahs3, frowand.list

Add fwnode_device_is_available() to tell whether the device corresponding
to a certain fwnode_handle is available for use.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/acpi/property.c  |  9 +++++++++
 drivers/base/property.c  | 10 ++++++++++
 drivers/of/property.c    |  6 ++++++
 include/linux/fwnode.h   |  1 +
 include/linux/property.h |  1 +
 5 files changed, 27 insertions(+)

diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index d26f24d..8df71bb 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -1121,6 +1121,14 @@ int acpi_graph_get_remote_endpoint(struct fwnode_handle *fwnode,
 	return 0;
 }
 
+static bool acpi_fwnode_device_is_available(struct fwnode_handle *fwnode)
+{
+	if (!is_acpi_device_node(fwnode))
+		return false;
+
+	return acpi_device_is_present(to_acpi_device_node(fwnode));
+}
+
 static bool acpi_fwnode_property_present(struct fwnode_handle *fwnode,
 					 const char *propname)
 {
@@ -1225,6 +1233,7 @@ static int acpi_fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode,
 }
 
 const struct fwnode_operations acpi_fwnode_ops = {
+	.device_is_available = acpi_fwnode_device_is_available,
 	.property_present = acpi_fwnode_property_present,
 	.property_read_int_array = acpi_fwnode_property_read_int_array,
 	.property_read_string_array = acpi_fwnode_property_read_string_array,
diff --git a/drivers/base/property.c b/drivers/base/property.c
index 6eccc4e..ad0de38 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1020,6 +1020,16 @@ void fwnode_handle_put(struct fwnode_handle *fwnode)
 EXPORT_SYMBOL_GPL(fwnode_handle_put);
 
 /**
+ * fwnode_device_is_available - check if a device is available for use
+ * @fwnode: Pointer to the fwnode of the device.
+ */
+bool fwnode_device_is_available(struct fwnode_handle *fwnode)
+{
+	return fwnode_call_int_op(fwnode, device_is_available);
+}
+EXPORT_SYMBOL_GPL(fwnode_device_is_available);
+
+/**
  * device_get_child_node_count - return the number of child nodes for device
  * @dev: Device to cound the child nodes for
  */
diff --git a/drivers/of/property.c b/drivers/of/property.c
index bb6ac73..7042f62 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -791,6 +791,11 @@ static void of_fwnode_put(struct fwnode_handle *fwnode)
 	of_node_put(to_of_node(fwnode));
 }
 
+static bool of_fwnode_device_is_available(struct fwnode_handle *fwnode)
+{
+	return of_device_is_available(to_of_node(fwnode));
+}
+
 static bool of_fwnode_property_present(struct fwnode_handle *fwnode,
 				       const char *propname)
 {
@@ -925,6 +930,7 @@ static int of_fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode,
 const struct fwnode_operations of_fwnode_ops = {
 	.get = of_fwnode_get,
 	.put = of_fwnode_put,
+	.device_is_available = of_fwnode_device_is_available,
 	.property_present = of_fwnode_property_present,
 	.property_read_int_array = of_fwnode_property_read_int_array,
 	.property_read_string_array = of_fwnode_property_read_string_array,
diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
index 35f6626..4e60b2b 100644
--- a/include/linux/fwnode.h
+++ b/include/linux/fwnode.h
@@ -65,6 +65,7 @@ struct fwnode_endpoint {
 struct fwnode_operations {
 	void (*get)(struct fwnode_handle *fwnode);
 	void (*put)(struct fwnode_handle *fwnode);
+	bool (*device_is_available)(struct fwnode_handle *fwnode);
 	bool (*property_present)(struct fwnode_handle *fwnode,
 				 const char *propname);
 	int (*property_read_int_array)(struct fwnode_handle *fwnode,
diff --git a/include/linux/property.h b/include/linux/property.h
index 2f48261..7be014a 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -51,6 +51,7 @@ int device_property_read_string(struct device *dev, const char *propname,
 int device_property_match_string(struct device *dev,
 				 const char *propname, const char *string);
 
+bool fwnode_device_is_available(struct fwnode_handle *fwnode);
 bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname);
 int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
 				  const char *propname, u8 *val,
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v5 5/5] device property: Add FW type agnostic fwnode_graph_get_remote_node
  2017-05-04  7:14 [PATCH v5 0/5] Move firmware specific code to firmware specific locations Sakari Ailus
                   ` (3 preceding siblings ...)
  2017-05-04  7:14 ` [PATCH v5 4/5] device property: Introduce fwnode_device_is_available() Sakari Ailus
@ 2017-05-04  7:14 ` Sakari Ailus
  4 siblings, 0 replies; 8+ messages in thread
From: Sakari Ailus @ 2017-05-04  7:14 UTC (permalink / raw)
  To: linux-acpi
  Cc: devicetree, sudeep.holla, lorenzo.pieralisi, mika.westerberg,
	rafael, mark.rutland, broonie, robh, ahs3, frowand.list

Add fwnode_graph_get_remote_node() function which is equivalent to
of_graph_get_remote_node() on OF.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/base/property.c  | 37 +++++++++++++++++++++++++++++++++++++
 include/linux/property.h |  2 ++
 2 files changed, 39 insertions(+)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index ad0de38..5914156 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1215,6 +1215,43 @@ fwnode_graph_get_remote_endpoint(struct fwnode_handle *fwnode)
 EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_endpoint);
 
 /**
+ * fwnode_graph_get_remote_node - get remote parent node for given port/endpoint
+ * @fwnode: pointer to parent fwnode_handle containing graph port/endpoint
+ * @port_id: identifier of the parent port node
+ * @endpoint_id: identifier of the endpoint node
+ *
+ * Return: Remote fwnode handle associated with remote endpoint node linked
+ *	   to @node. Use fwnode_node_put() on it when done.
+ */
+struct fwnode_handle *fwnode_graph_get_remote_node(
+	struct fwnode_handle *fwnode, u32 port_id, u32 endpoint_id)
+{
+	struct fwnode_handle *endpoint = NULL;
+
+	while ((endpoint = fwnode_graph_get_next_endpoint(fwnode, endpoint))) {
+		struct fwnode_endpoint fwnode_ep;
+		struct fwnode_handle *remote;
+		int ret;
+
+		ret = fwnode_graph_parse_endpoint(endpoint, &fwnode_ep);
+		if (ret < 0)
+			continue;
+
+		if (fwnode_ep.port != port_id || fwnode_ep.id != endpoint_id)
+			continue;
+
+		remote = fwnode_graph_get_remote_port_parent(endpoint);
+		if (!remote)
+			return NULL;
+
+		return fwnode_device_is_available(remote) ? remote : NULL;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_node);
+
+/**
  * fwnode_graph_parse_endpoint - parse common endpoint node properties
  * @fwnode: pointer to endpoint fwnode_handle
  * @endpoint: pointer to the fwnode endpoint data structure
diff --git a/include/linux/property.h b/include/linux/property.h
index 7be014a..b9f4838 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -281,6 +281,8 @@ struct fwnode_handle *fwnode_graph_get_remote_port(
 	struct fwnode_handle *fwnode);
 struct fwnode_handle *fwnode_graph_get_remote_endpoint(
 	struct fwnode_handle *fwnode);
+struct fwnode_handle *fwnode_graph_get_remote_node(
+	struct fwnode_handle *fwnode, u32 port, u32 endpoint);
 
 int fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode,
 				struct fwnode_endpoint *endpoint);
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v5 3/5] device property: Move fwnode graph ops to firmware specific locations
       [not found]   ` <1493882051-28814-4-git-send-email-sakari.ailus-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
@ 2017-05-08 18:23     ` Rob Herring
  2017-05-09 12:36       ` Sakari Ailus
  0 siblings, 1 reply; 8+ messages in thread
From: Rob Herring @ 2017-05-08 18:23 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Sudeep Holla,
	Lorenzo Pieralisi, mika.westerberg-VuQAYsv1563Yd54FQh9/CA,
	Rafael J. Wysocki, Mark Rutland, Mark Brown, Al Stone,
	Frank Rowand

On Thu, May 4, 2017 at 2:14 AM, Sakari Ailus
<sakari.ailus-VuQAYsv1563Yd54FQh9/CA@public.gmane.org> wrote:
> Move firmware specific implementations of the fwnode graph operations to
> firmware specific locations.
>
> Signed-off-by: Sakari Ailus <sakari.ailus-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
> ---
>  drivers/acpi/property.c | 45 +++++++++++++++++++++++
>  drivers/base/property.c | 96 ++++++-------------------------------------------
>  drivers/of/property.c   | 57 +++++++++++++++++++++++++++++
>  include/linux/fwnode.h  | 12 +++++++
>  4 files changed, 125 insertions(+), 85 deletions(-)
>
> diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
> index fb3b96f..d26f24d 100644
> --- a/drivers/acpi/property.c
> +++ b/drivers/acpi/property.c
> @@ -1183,6 +1183,47 @@ static struct fwnode_handle *acpi_fwnode_get_named_child_node(
>         return NULL;
>  }
>
> +static struct fwnode_handle *acpi_fwnode_graph_get_next_endpoint(
> +       struct fwnode_handle *fwnode, struct fwnode_handle *prev)
> +{
> +       struct fwnode_handle *endpoint;
> +
> +       endpoint = acpi_graph_get_next_endpoint(fwnode, prev);
> +       if (IS_ERR(endpoint))
> +               return NULL;
> +
> +       return endpoint;
> +}
> +
> +static struct fwnode_handle *acpi_fwnode_graph_get_remote_endpoint(
> +       struct fwnode_handle *fwnode)
> +{
> +       struct fwnode_handle *endpoint = NULL;
> +
> +       acpi_graph_get_remote_endpoint(fwnode, NULL, NULL, &endpoint);
> +
> +       return endpoint;
> +}
> +
> +static struct fwnode_handle *acpi_fwnode_graph_get_port_parent(
> +       struct fwnode_handle *fwnode)
> +{
> +       return acpi_node_get_parent(fwnode);
> +}
> +
> +static int acpi_fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode,
> +                                           struct fwnode_endpoint *endpoint)
> +{
> +       struct fwnode_handle *port_fwnode = fwnode_get_parent(fwnode);
> +
> +       endpoint->local_fwnode = fwnode;
> +
> +       fwnode_property_read_u32(port_fwnode, "port", &endpoint->port);
> +       fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id);
> +
> +       return 0;
> +}
> +
>  const struct fwnode_operations acpi_fwnode_ops = {
>         .property_present = acpi_fwnode_property_present,
>         .property_read_int_array = acpi_fwnode_property_read_int_array,
> @@ -1190,4 +1231,8 @@ const struct fwnode_operations acpi_fwnode_ops = {
>         .get_parent = acpi_fwnode_get_parent,
>         .get_next_child_node = acpi_get_next_subnode,
>         .get_named_child_node = acpi_fwnode_get_named_child_node,
> +       .graph_get_next_endpoint = acpi_fwnode_graph_get_next_endpoint,
> +       .graph_get_remote_endpoint = acpi_fwnode_graph_get_remote_endpoint,
> +       .graph_get_port_parent = acpi_fwnode_graph_get_port_parent,
> +       .graph_parse_endpoint = acpi_fwnode_graph_parse_endpoint,
>  };
> diff --git a/drivers/base/property.c b/drivers/base/property.c
> index 4dc5ab6..6eccc4e 100644
> --- a/drivers/base/property.c
> +++ b/drivers/base/property.c
> @@ -1154,24 +1154,7 @@ struct fwnode_handle *
>  fwnode_graph_get_next_endpoint(struct fwnode_handle *fwnode,
>                                struct fwnode_handle *prev)
>  {
> -       struct fwnode_handle *endpoint = NULL;
> -
> -       if (is_of_node(fwnode)) {
> -               struct device_node *node;
> -
> -               node = of_graph_get_next_endpoint(to_of_node(fwnode),
> -                                                 to_of_node(prev));
> -
> -               if (node)
> -                       endpoint = &node->fwnode;
> -       } else if (is_acpi_node(fwnode)) {
> -               endpoint = acpi_graph_get_next_endpoint(fwnode, prev);
> -               if (IS_ERR(endpoint))
> -                       endpoint = NULL;
> -       }
> -
> -       return endpoint;
> -
> +       return fwnode_call_ptr_op(fwnode, graph_get_next_endpoint, prev);
>  }
>  EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint);
>
> @@ -1184,24 +1167,11 @@ EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint);
>  struct fwnode_handle *
>  fwnode_graph_get_remote_port_parent(struct fwnode_handle *fwnode)
>  {
> -       struct fwnode_handle *parent = NULL;
> -
> -       if (is_of_node(fwnode)) {
> -               struct device_node *node;
> -
> -               node = of_graph_get_remote_port_parent(to_of_node(fwnode));
> -               if (node)
> -                       parent = &node->fwnode;
> -       } else if (is_acpi_node(fwnode)) {
> -               int ret;
> -
> -               ret = acpi_graph_get_remote_endpoint(fwnode, &parent, NULL,
> -                                                    NULL);
> -               if (ret)
> -                       return NULL;
> -       }
> +       fwnode = fwnode_graph_get_remote_port(fwnode);
> +       if (!fwnode)
> +               return NULL;
>
> -       return parent;
> +       return fwnode_call_ptr_op(fwnode, graph_get_port_parent);

Just make fwnode_call_ptr_op(NULL, ...) return NULL.

>  }
>  EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port_parent);
>
> @@ -1213,23 +1183,11 @@ EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port_parent);
>   */
>  struct fwnode_handle *fwnode_graph_get_remote_port(struct fwnode_handle *fwnode)
>  {
> -       struct fwnode_handle *port = NULL;
> -
> -       if (is_of_node(fwnode)) {
> -               struct device_node *node;
> -
> -               node = of_graph_get_remote_port(to_of_node(fwnode));
> -               if (node)
> -                       port = &node->fwnode;
> -       } else if (is_acpi_node(fwnode)) {
> -               int ret;
> -
> -               ret = acpi_graph_get_remote_endpoint(fwnode, NULL, &port, NULL);
> -               if (ret)
> -                       return NULL;
> -       }
> +       fwnode = fwnode_graph_get_remote_endpoint(fwnode);
> +       if (!fwnode)
> +               return NULL;
>
> -       return port;
> +       return fwnode_get_parent(fwnode);

Just make fwnode_get_parent(NULL) return NULL.

>  }
>  EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port);
>
> @@ -1242,25 +1200,7 @@ EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port);
>  struct fwnode_handle *
>  fwnode_graph_get_remote_endpoint(struct fwnode_handle *fwnode)
>  {
> -       struct fwnode_handle *endpoint = NULL;
> -
> -       if (is_of_node(fwnode)) {
> -               struct device_node *node;
> -
> -               node = of_parse_phandle(to_of_node(fwnode), "remote-endpoint",
> -                                       0);
> -               if (node)
> -                       endpoint = &node->fwnode;
> -       } else if (is_acpi_node(fwnode)) {
> -               int ret;
> -
> -               ret = acpi_graph_get_remote_endpoint(fwnode, NULL, NULL,
> -                                                    &endpoint);
> -               if (ret)
> -                       return NULL;
> -       }
> -
> -       return endpoint;
> +       return fwnode_call_ptr_op(fwnode, graph_get_remote_endpoint);
>  }
>  EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_endpoint);
>
> @@ -1276,22 +1216,8 @@ EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_endpoint);
>  int fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode,
>                                 struct fwnode_endpoint *endpoint)
>  {
> -       struct fwnode_handle *port_fwnode = fwnode_get_parent(fwnode);
> -
>         memset(endpoint, 0, sizeof(*endpoint));
>
> -       endpoint->local_fwnode = fwnode;
> -
> -       if (is_acpi_node(port_fwnode)) {
> -               fwnode_property_read_u32(port_fwnode, "port", &endpoint->port);
> -               fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id);
> -       } else {
> -               fwnode_property_read_u32(port_fwnode, "reg", &endpoint->port);
> -               fwnode_property_read_u32(fwnode, "reg", &endpoint->id);
> -       }
> -
> -       fwnode_handle_put(port_fwnode);
> -
> -       return 0;
> +       return fwnode_call_int_op(fwnode, graph_parse_endpoint, endpoint);
>  }
>  EXPORT_SYMBOL(fwnode_graph_parse_endpoint);
> diff --git a/drivers/of/property.c b/drivers/of/property.c
> index 984e37e..bb6ac73 100644
> --- a/drivers/of/property.c
> +++ b/drivers/of/property.c
> @@ -869,6 +869,59 @@ static struct fwnode_handle *of_fwnode_get_named_child_node(
>         return NULL;
>  }
>
> +static struct fwnode_handle *of_fwnode_graph_get_next_endpoint(
> +       struct fwnode_handle *fwnode, struct fwnode_handle *prev)
> +{
> +       struct device_node *node;
> +
> +       node = of_graph_get_next_endpoint(to_of_node(fwnode),
> +                                         to_of_node(prev));
> +       if (node)
> +               return of_fwnode_handle(node);
> +
> +       return NULL;

Can't of_fwnode_handle() return NULL when node is NULL? Then these
functions become one liners:

return of_fwnode_handle(of_graph_get_next_endpoint(to_of_node(fwnode),
                                         to_of_node(prev)));

> +}
> +
> +static struct fwnode_handle *of_fwnode_graph_get_remote_endpoint(
> +       struct fwnode_handle *fwnode)
> +{
> +       struct device_node *node;
> +
> +       node = of_parse_phandle(to_of_node(fwnode), "remote-endpoint", 0);
> +       if (node)
> +               return of_fwnode_handle(node);
> +
> +       return NULL;
> +}
> +
> +static struct fwnode_handle *of_fwnode_graph_get_port_parent(
> +       struct fwnode_handle *fwnode)
> +{
> +       struct device_node *node;
> +
> +       node = of_graph_get_port_parent(to_of_node(fwnode));
> +       if (node)
> +               return of_fwnode_handle(node);
> +
> +       return NULL;
> +}
> +
> +static int of_fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode,
> +                                         struct fwnode_endpoint *endpoint)
> +{
> +       struct device_node *node = to_of_node(fwnode);
> +       struct device_node *port_node = of_get_parent(node);
> +
> +       endpoint->local_fwnode = fwnode;
> +
> +       of_property_read_u32(port_node, "reg", &endpoint->port);
> +       of_property_read_u32(node, "reg", &endpoint->id);
> +
> +       of_node_put(port_node);
> +
> +       return 0;
> +}
> +
>  const struct fwnode_operations of_fwnode_ops = {
>         .get = of_fwnode_get,
>         .put = of_fwnode_put,
> @@ -878,4 +931,8 @@ const struct fwnode_operations of_fwnode_ops = {
>         .get_parent = of_fwnode_get_parent,
>         .get_next_child_node = of_fwnode_get_next_child_node,
>         .get_named_child_node = of_fwnode_get_named_child_node,
> +       .graph_get_next_endpoint = of_fwnode_graph_get_next_endpoint,
> +       .graph_get_remote_endpoint = of_fwnode_graph_get_remote_endpoint,
> +       .graph_get_port_parent = of_fwnode_graph_get_port_parent,
> +       .graph_parse_endpoint = of_fwnode_graph_parse_endpoint,
>  };
> diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
> index e05aaef..35f6626 100644
> --- a/include/linux/fwnode.h
> +++ b/include/linux/fwnode.h
> @@ -57,6 +57,10 @@ struct fwnode_endpoint {
>   * @get_parent: Return the parent of an fwnode.
>   * @get_next_child_node: Return the next child node in an iteration.
>   * @get_named_child_node: Return a child node with a given name.
> + * @graph_get_next_endpoint: Return an endpoint node in an iteration.
> + * @graph_get_remote_endpoint: Return the remote endpoint node of a local
> + *                            endpoint node.
> + * @graph_get_port_parent: Return the parent node of a port node.
>   */
>  struct fwnode_operations {
>         void (*get)(struct fwnode_handle *fwnode);
> @@ -75,6 +79,14 @@ struct fwnode_operations {
>                 struct fwnode_handle *fwnode, struct fwnode_handle *child);
>         struct fwnode_handle *(*get_named_child_node)(
>                 struct fwnode_handle *fwnode, const char *name);
> +       struct fwnode_handle *(*graph_get_next_endpoint)(
> +               struct fwnode_handle *fwnode, struct fwnode_handle *prev);
> +       struct fwnode_handle *(*graph_get_remote_endpoint)(
> +               struct fwnode_handle *fwnode);
> +       struct fwnode_handle *(*graph_get_port_parent)(
> +               struct fwnode_handle *fwnode);
> +       int (*graph_parse_endpoint)(struct fwnode_handle *fwnode,
> +                                   struct fwnode_endpoint *endpoint);
>  };
>
>  #define fwnode_has_op(fwnode, op)                              \
> --
> 2.7.4
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v5 3/5] device property: Move fwnode graph ops to firmware specific locations
  2017-05-08 18:23     ` Rob Herring
@ 2017-05-09 12:36       ` Sakari Ailus
  0 siblings, 0 replies; 8+ messages in thread
From: Sakari Ailus @ 2017-05-09 12:36 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-acpi, devicetree, Sudeep Holla, Lorenzo Pieralisi,
	mika.westerberg, Rafael J. Wysocki, Mark Rutland, Mark Brown,
	Al Stone, Frank Rowand

Hi Rob,

Thanks for the review.

On 05/08/17 21:23, Rob Herring wrote:
> On Thu, May 4, 2017 at 2:14 AM, Sakari Ailus
> <sakari.ailus@linux.intel.com> wrote:
...
>> @@ -1184,24 +1167,11 @@ EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint);
>>  struct fwnode_handle *
>>  fwnode_graph_get_remote_port_parent(struct fwnode_handle *fwnode)
>>  {
>> -       struct fwnode_handle *parent = NULL;
>> -
>> -       if (is_of_node(fwnode)) {
>> -               struct device_node *node;
>> -
>> -               node = of_graph_get_remote_port_parent(to_of_node(fwnode));
>> -               if (node)
>> -                       parent = &node->fwnode;
>> -       } else if (is_acpi_node(fwnode)) {
>> -               int ret;
>> -
>> -               ret = acpi_graph_get_remote_endpoint(fwnode, &parent, NULL,
>> -                                                    NULL);
>> -               if (ret)
>> -                       return NULL;
>> -       }
>> +       fwnode = fwnode_graph_get_remote_port(fwnode);
>> +       if (!fwnode)
>> +               return NULL;
>>
>> -       return parent;
>> +       return fwnode_call_ptr_op(fwnode, graph_get_port_parent);
> 
> Just make fwnode_call_ptr_op(NULL, ...) return NULL.

Hmm. That already appears to be the case... I'll take that account
above, too.

> 
>>  }
>>  EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port_parent);
>>
>> @@ -1213,23 +1183,11 @@ EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port_parent);
>>   */
>>  struct fwnode_handle *fwnode_graph_get_remote_port(struct fwnode_handle *fwnode)
>>  {
>> -       struct fwnode_handle *port = NULL;
>> -
>> -       if (is_of_node(fwnode)) {
>> -               struct device_node *node;
>> -
>> -               node = of_graph_get_remote_port(to_of_node(fwnode));
>> -               if (node)
>> -                       port = &node->fwnode;
>> -       } else if (is_acpi_node(fwnode)) {
>> -               int ret;
>> -
>> -               ret = acpi_graph_get_remote_endpoint(fwnode, NULL, &port, NULL);
>> -               if (ret)
>> -                       return NULL;
>> -       }
>> +       fwnode = fwnode_graph_get_remote_endpoint(fwnode);
>> +       if (!fwnode)
>> +               return NULL;
>>
>> -       return port;
>> +       return fwnode_get_parent(fwnode);
> 
> Just make fwnode_get_parent(NULL) return NULL.

The same.

> 
>>  }
>>  EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port);
>>
>> @@ -1242,25 +1200,7 @@ EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port);
>>  struct fwnode_handle *
>>  fwnode_graph_get_remote_endpoint(struct fwnode_handle *fwnode)
>>  {
>> -       struct fwnode_handle *endpoint = NULL;
>> -
>> -       if (is_of_node(fwnode)) {
>> -               struct device_node *node;
>> -
>> -               node = of_parse_phandle(to_of_node(fwnode), "remote-endpoint",
>> -                                       0);
>> -               if (node)
>> -                       endpoint = &node->fwnode;
>> -       } else if (is_acpi_node(fwnode)) {
>> -               int ret;
>> -
>> -               ret = acpi_graph_get_remote_endpoint(fwnode, NULL, NULL,
>> -                                                    &endpoint);
>> -               if (ret)
>> -                       return NULL;
>> -       }
>> -
>> -       return endpoint;
>> +       return fwnode_call_ptr_op(fwnode, graph_get_remote_endpoint);
>>  }
>>  EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_endpoint);
>>
>> @@ -1276,22 +1216,8 @@ EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_endpoint);
>>  int fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode,
>>                                 struct fwnode_endpoint *endpoint)
>>  {
>> -       struct fwnode_handle *port_fwnode = fwnode_get_parent(fwnode);
>> -
>>         memset(endpoint, 0, sizeof(*endpoint));
>>
>> -       endpoint->local_fwnode = fwnode;
>> -
>> -       if (is_acpi_node(port_fwnode)) {
>> -               fwnode_property_read_u32(port_fwnode, "port", &endpoint->port);
>> -               fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id);
>> -       } else {
>> -               fwnode_property_read_u32(port_fwnode, "reg", &endpoint->port);
>> -               fwnode_property_read_u32(fwnode, "reg", &endpoint->id);
>> -       }
>> -
>> -       fwnode_handle_put(port_fwnode);
>> -
>> -       return 0;
>> +       return fwnode_call_int_op(fwnode, graph_parse_endpoint, endpoint);
>>  }
>>  EXPORT_SYMBOL(fwnode_graph_parse_endpoint);
>> diff --git a/drivers/of/property.c b/drivers/of/property.c
>> index 984e37e..bb6ac73 100644
>> --- a/drivers/of/property.c
>> +++ b/drivers/of/property.c
>> @@ -869,6 +869,59 @@ static struct fwnode_handle *of_fwnode_get_named_child_node(
>>         return NULL;
>>  }
>>
>> +static struct fwnode_handle *of_fwnode_graph_get_next_endpoint(
>> +       struct fwnode_handle *fwnode, struct fwnode_handle *prev)
>> +{
>> +       struct device_node *node;
>> +
>> +       node = of_graph_get_next_endpoint(to_of_node(fwnode),
>> +                                         to_of_node(prev));
>> +       if (node)
>> +               return of_fwnode_handle(node);
>> +
>> +       return NULL;
> 
> Can't of_fwnode_handle() return NULL when node is NULL? Then these
> functions become one liners:
> 
> return of_fwnode_handle(of_graph_get_next_endpoint(to_of_node(fwnode),
>                                          to_of_node(prev)));

Good point. of_fwnode_handle() is a macro (in order to support const /
non-const cases) and it'll be a little bit more complex but I guess
that's not really an issue.

-- 
Kind regards,

Sakari Ailus
sakari.ailus@linux.intel.com

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-05-09 12:36 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-04  7:14 [PATCH v5 0/5] Move firmware specific code to firmware specific locations Sakari Ailus
2017-05-04  7:14 ` [PATCH v5 1/5] of: Add of_graph_get_port_parent() to obtain a port's parent node Sakari Ailus
2017-05-04  7:14 ` [PATCH v5 2/5] device property: Move FW type specific functionality to FW specific files Sakari Ailus
2017-05-04  7:14 ` [PATCH v5 3/5] device property: Move fwnode graph ops to firmware specific locations Sakari Ailus
     [not found]   ` <1493882051-28814-4-git-send-email-sakari.ailus-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2017-05-08 18:23     ` Rob Herring
2017-05-09 12:36       ` Sakari Ailus
2017-05-04  7:14 ` [PATCH v5 4/5] device property: Introduce fwnode_device_is_available() Sakari Ailus
2017-05-04  7:14 ` [PATCH v5 5/5] device property: Add FW type agnostic fwnode_graph_get_remote_node Sakari Ailus

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.