All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
@ 2011-09-22 20:52 ` Benoit Cousson
  0 siblings, 0 replies; 20+ messages in thread
From: Benoit Cousson @ 2011-09-22 20:52 UTC (permalink / raw)
  To: khilman; +Cc: linux-omap, linux-arm-kernel, grant.likely, Benoit Cousson

Hi Kevin,

This is the updated version of the initial series that introduced a
notifier in order to create an omap_device from a platform_device bound
to DT node as suggested by Grant.

For the moment, the informations are all extracted from the hwmod data.
The idea is to focus first on the devices / board static init removal.
The other issue is that some bindings, like dma, are still not present
in the DT core code. The reg and irq bindings are there, but cannot
be used by some drivers due to the lack of named resources in DT for
the moment.
We agreed with Grant about the strategy to introduce the name without
breaking the compatibility and the default assumption about the order.

I'll update that in another series after 3.2 and then these informations
will be moved from hwmod to DT.

Patches are based on my for_3.2/1_omap_device_cleanup branch and are
available here:
git://gitorious.org/omap-pm/linux.git for_3.2/2_omap_device_dt

It is tested on OMAP4 SDP, Panda and Beagle-xM with and without CONFIG_OF.

Regards,
Benoit


Changes since v1: http://www.spinics.net/lists/linux-omap/msg55814.html
 - delete omap_device structure during BUS_NOTIFY_DEL_DEVICE callback
   as suggested by Kevin
 - merge previous patches 2&3 as suggested by Kevin
 - delete pm_lats in omap_device_delete since this is now kmalloc-ed
 - use kmemdup instead of kzalloc + memcopy for hmwods creation
 - Fix the wrong usage of of_*.h includes to build properly without
   CONFIG_OF.

Changes since v2: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg55892.html
 - Add binding documentation for the OMAP attributes
 - Add "ti," prefix to hwmods and no_idle_on_suspend attributes
 - Change the static init of the notifier_block structure as suggested by Grant
 - Add a comment to remove the helpers once the generic one from swarren will
   be merged


Benoit Cousson (2):
  OMAP: omap_device: Add omap_device_[alloc|delete] for DT integration
  OMAP: omap_device: Add a method to build an omap_device from a DT node

 .../devicetree/bindings/arm/omap/omap.txt          |   42 +++
 arch/arm/plat-omap/omap_device.c                   |  322 ++++++++++++++++----
 2 files changed, 306 insertions(+), 58 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/omap/omap.txt


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

* [PATCH v3 0/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
@ 2011-09-22 20:52 ` Benoit Cousson
  0 siblings, 0 replies; 20+ messages in thread
From: Benoit Cousson @ 2011-09-22 20:52 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Kevin,

This is the updated version of the initial series that introduced a
notifier in order to create an omap_device from a platform_device bound
to DT node as suggested by Grant.

For the moment, the informations are all extracted from the hwmod data.
The idea is to focus first on the devices / board static init removal.
The other issue is that some bindings, like dma, are still not present
in the DT core code. The reg and irq bindings are there, but cannot
be used by some drivers due to the lack of named resources in DT for
the moment.
We agreed with Grant about the strategy to introduce the name without
breaking the compatibility and the default assumption about the order.

I'll update that in another series after 3.2 and then these informations
will be moved from hwmod to DT.

Patches are based on my for_3.2/1_omap_device_cleanup branch and are
available here:
git://gitorious.org/omap-pm/linux.git for_3.2/2_omap_device_dt

It is tested on OMAP4 SDP, Panda and Beagle-xM with and without CONFIG_OF.

Regards,
Benoit


Changes since v1: http://www.spinics.net/lists/linux-omap/msg55814.html
 - delete omap_device structure during BUS_NOTIFY_DEL_DEVICE callback
   as suggested by Kevin
 - merge previous patches 2&3 as suggested by Kevin
 - delete pm_lats in omap_device_delete since this is now kmalloc-ed
 - use kmemdup instead of kzalloc + memcopy for hmwods creation
 - Fix the wrong usage of of_*.h includes to build properly without
   CONFIG_OF.

Changes since v2: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg55892.html
 - Add binding documentation for the OMAP attributes
 - Add "ti," prefix to hwmods and no_idle_on_suspend attributes
 - Change the static init of the notifier_block structure as suggested by Grant
 - Add a comment to remove the helpers once the generic one from swarren will
   be merged


Benoit Cousson (2):
  OMAP: omap_device: Add omap_device_[alloc|delete] for DT integration
  OMAP: omap_device: Add a method to build an omap_device from a DT node

 .../devicetree/bindings/arm/omap/omap.txt          |   42 +++
 arch/arm/plat-omap/omap_device.c                   |  322 ++++++++++++++++----
 2 files changed, 306 insertions(+), 58 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/omap/omap.txt

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

* [PATCH v3 1/2] OMAP: omap_device: Add omap_device_[alloc|delete] for DT integration
  2011-09-22 20:52 ` Benoit Cousson
@ 2011-09-22 20:52   ` Benoit Cousson
  -1 siblings, 0 replies; 20+ messages in thread
From: Benoit Cousson @ 2011-09-22 20:52 UTC (permalink / raw)
  To: khilman; +Cc: linux-omap, linux-arm-kernel, grant.likely, Benoit Cousson

Split the omap_device_build_ss into two smaller functions
that will allow to populate a platform_device already allocated by
device-tree.
The functionality of the omap_device_build_ss is still the same, but
the omap_device_alloc will be usable with devices already built by
device-tree.

Signed-off-by: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@ti.com>
---
 arch/arm/plat-omap/omap_device.c |  177 +++++++++++++++++++++++++------------
 1 files changed, 119 insertions(+), 58 deletions(-)

diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index 54bbe7b..cac7b9a 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -96,6 +96,11 @@
 
 static int omap_device_register(struct platform_device *pdev);
 static int omap_early_device_register(struct platform_device *pdev);
+static struct omap_device *omap_device_alloc(struct platform_device *pdev,
+				      struct omap_hwmod **ohs, int oh_cnt,
+				      struct omap_device_pm_latency *pm_lats,
+				      int pm_lats_cnt);
+
 
 static struct omap_device_pm_latency omap_default_latency[] = {
 	{
@@ -397,6 +402,110 @@ static int omap_device_fill_resources(struct omap_device *od,
 }
 
 /**
+ * omap_device_alloc - allocate an omap_device
+ * @pdev: platform_device that will be included in this omap_device
+ * @oh: ptr to the single omap_hwmod that backs this omap_device
+ * @pdata: platform_data ptr to associate with the platform_device
+ * @pdata_len: amount of memory pointed to by @pdata
+ * @pm_lats: pointer to a omap_device_pm_latency array for this device
+ * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
+ *
+ * Convenience function for allocating an omap_device structure and filling
+ * hwmods, resources and pm_latency attributes.
+ *
+ * Returns an struct omap_device pointer or ERR_PTR() on error;
+ */
+static struct omap_device *omap_device_alloc(struct platform_device *pdev,
+					struct omap_hwmod **ohs, int oh_cnt,
+					struct omap_device_pm_latency *pm_lats,
+					int pm_lats_cnt)
+{
+	int ret = -ENOMEM;
+	struct omap_device *od;
+	struct resource *res = NULL;
+	int i, res_count;
+	struct omap_hwmod **hwmods;
+
+	od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
+	if (!od) {
+		ret = -ENOMEM;
+		goto oda_exit1;
+	}
+	od->hwmods_cnt = oh_cnt;
+
+	hwmods = kmemdup(ohs, sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
+	if (!hwmods)
+		goto oda_exit2;
+
+	od->hwmods = hwmods;
+	od->pdev = pdev;
+
+	/*
+	 * HACK: Ideally the resources from DT should match, and hwmod
+	 * should just add the missing ones. Since the name is not
+	 * properly populated by DT, stick to hwmod resources only.
+	 */
+	if (pdev->num_resources && pdev->resource)
+		dev_warn(&pdev->dev, "%s(): resources already allocated %d\n",
+			__func__, pdev->num_resources);
+
+	res_count = omap_device_count_resources(od);
+	if (res_count > 0) {
+		dev_dbg(&pdev->dev, "%s(): resources allocated from hwmod %d\n",
+			__func__, res_count);
+		res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
+		if (!res)
+			goto oda_exit3;
+
+		omap_device_fill_resources(od, res);
+
+		ret = platform_device_add_resources(pdev, res, res_count);
+		kfree(res);
+
+		if (ret)
+			goto oda_exit3;
+	}
+
+	if (!pm_lats) {
+		pm_lats = omap_default_latency;
+		pm_lats_cnt = ARRAY_SIZE(omap_default_latency);
+	}
+
+	od->pm_lats_cnt = pm_lats_cnt;
+	od->pm_lats = kmemdup(pm_lats,
+			sizeof(struct omap_device_pm_latency) * pm_lats_cnt,
+			GFP_KERNEL);
+	if (!od->pm_lats)
+		goto oda_exit3;
+
+	pdev->archdata.od = od;
+
+	for (i = 0; i < oh_cnt; i++) {
+		hwmods[i]->od = od;
+		_add_hwmod_clocks_clkdev(od, hwmods[i]);
+	}
+
+	return od;
+
+oda_exit3:
+	kfree(hwmods);
+oda_exit2:
+	kfree(od);
+oda_exit1:
+	dev_err(&pdev->dev, "omap_device: build failed (%d)\n", ret);
+
+	return ERR_PTR(ret);
+}
+
+static void omap_device_delete(struct omap_device *od)
+{
+	od->pdev->archdata.od = NULL;
+	kfree(od->pm_lats);
+	kfree(od->hwmods);
+	kfree(od);
+}
+
+/**
  * omap_device_build - build and register an omap_device with one omap_hwmod
  * @pdev_name: name of the platform_device driver to use
  * @pdev_id: this platform_device's connection ID
@@ -455,9 +564,6 @@ struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
 	int ret = -ENOMEM;
 	struct platform_device *pdev;
 	struct omap_device *od;
-	struct resource *res = NULL;
-	int i, res_count;
-	struct omap_hwmod **hwmods;
 
 	if (!ohs || oh_cnt == 0 || !pdev_name)
 		return ERR_PTR(-EINVAL);
@@ -471,76 +577,31 @@ struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
 		goto odbs_exit;
 	}
 
-	pr_debug("omap_device: %s: building with %d hwmods\n", pdev_name,
-		 oh_cnt);
+	/* Set the dev_name early to allow dev_xxx in omap_device_alloc */
+	if (pdev->id != -1)
+		dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);
+	else
+		dev_set_name(&pdev->dev, "%s", pdev->name);
 
-	od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
-	if (!od) {
-		ret = -ENOMEM;
+	od = omap_device_alloc(pdev, ohs, oh_cnt, pm_lats, pm_lats_cnt);
+	if (!od)
 		goto odbs_exit1;
-	}
-	od->hwmods_cnt = oh_cnt;
-
-	hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt,
-			 GFP_KERNEL);
-	if (!hwmods)
-		goto odbs_exit2;
-
-	memcpy(hwmods, ohs, sizeof(struct omap_hwmod *) * oh_cnt);
-	od->hwmods = hwmods;
-	od->pdev = pdev;
-
-	res_count = omap_device_count_resources(od);
-	if (res_count > 0) {
-		res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
-		if (!res)
-			goto odbs_exit3;
-
-		omap_device_fill_resources(od, res);
-
-		ret = platform_device_add_resources(pdev, res, res_count);
-		kfree(res);
-
-		if (ret)
-			goto odbs_exit3;
-	}
 
 	ret = platform_device_add_data(pdev, pdata, pdata_len);
 	if (ret)
-		goto odbs_exit3;
-
-	pdev->archdata.od = od;
+		goto odbs_exit2;
 
 	if (is_early_device)
 		ret = omap_early_device_register(pdev);
 	else
 		ret = omap_device_register(pdev);
 	if (ret)
-		goto odbs_exit3;
-
-	if (!pm_lats) {
-		pm_lats = omap_default_latency;
-		pm_lats_cnt = ARRAY_SIZE(omap_default_latency);
-	}
-
-	od->pm_lats_cnt = pm_lats_cnt;
-	od->pm_lats = kmemdup(pm_lats,
-			sizeof(struct omap_device_pm_latency) * pm_lats_cnt,
-			GFP_KERNEL);
-	if (!od->pm_lats)
-		goto odbs_exit3;
-
-	for (i = 0; i < oh_cnt; i++) {
-		hwmods[i]->od = od;
-		_add_hwmod_clocks_clkdev(od, hwmods[i]);
-	}
+		goto odbs_exit2;
 
 	return pdev;
 
-odbs_exit3:
-	kfree(hwmods);
 odbs_exit2:
-	kfree(od);
+	omap_device_delete(od);
 odbs_exit1:
 	platform_device_put(pdev);
 odbs_exit:
-- 
1.7.0.4


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

* [PATCH v3 1/2] OMAP: omap_device: Add omap_device_[alloc|delete] for DT integration
@ 2011-09-22 20:52   ` Benoit Cousson
  0 siblings, 0 replies; 20+ messages in thread
From: Benoit Cousson @ 2011-09-22 20:52 UTC (permalink / raw)
  To: linux-arm-kernel

Split the omap_device_build_ss into two smaller functions
that will allow to populate a platform_device already allocated by
device-tree.
The functionality of the omap_device_build_ss is still the same, but
the omap_device_alloc will be usable with devices already built by
device-tree.

Signed-off-by: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@ti.com>
---
 arch/arm/plat-omap/omap_device.c |  177 +++++++++++++++++++++++++------------
 1 files changed, 119 insertions(+), 58 deletions(-)

diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index 54bbe7b..cac7b9a 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -96,6 +96,11 @@
 
 static int omap_device_register(struct platform_device *pdev);
 static int omap_early_device_register(struct platform_device *pdev);
+static struct omap_device *omap_device_alloc(struct platform_device *pdev,
+				      struct omap_hwmod **ohs, int oh_cnt,
+				      struct omap_device_pm_latency *pm_lats,
+				      int pm_lats_cnt);
+
 
 static struct omap_device_pm_latency omap_default_latency[] = {
 	{
@@ -397,6 +402,110 @@ static int omap_device_fill_resources(struct omap_device *od,
 }
 
 /**
+ * omap_device_alloc - allocate an omap_device
+ * @pdev: platform_device that will be included in this omap_device
+ * @oh: ptr to the single omap_hwmod that backs this omap_device
+ * @pdata: platform_data ptr to associate with the platform_device
+ * @pdata_len: amount of memory pointed to by @pdata
+ * @pm_lats: pointer to a omap_device_pm_latency array for this device
+ * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
+ *
+ * Convenience function for allocating an omap_device structure and filling
+ * hwmods, resources and pm_latency attributes.
+ *
+ * Returns an struct omap_device pointer or ERR_PTR() on error;
+ */
+static struct omap_device *omap_device_alloc(struct platform_device *pdev,
+					struct omap_hwmod **ohs, int oh_cnt,
+					struct omap_device_pm_latency *pm_lats,
+					int pm_lats_cnt)
+{
+	int ret = -ENOMEM;
+	struct omap_device *od;
+	struct resource *res = NULL;
+	int i, res_count;
+	struct omap_hwmod **hwmods;
+
+	od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
+	if (!od) {
+		ret = -ENOMEM;
+		goto oda_exit1;
+	}
+	od->hwmods_cnt = oh_cnt;
+
+	hwmods = kmemdup(ohs, sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
+	if (!hwmods)
+		goto oda_exit2;
+
+	od->hwmods = hwmods;
+	od->pdev = pdev;
+
+	/*
+	 * HACK: Ideally the resources from DT should match, and hwmod
+	 * should just add the missing ones. Since the name is not
+	 * properly populated by DT, stick to hwmod resources only.
+	 */
+	if (pdev->num_resources && pdev->resource)
+		dev_warn(&pdev->dev, "%s(): resources already allocated %d\n",
+			__func__, pdev->num_resources);
+
+	res_count = omap_device_count_resources(od);
+	if (res_count > 0) {
+		dev_dbg(&pdev->dev, "%s(): resources allocated from hwmod %d\n",
+			__func__, res_count);
+		res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
+		if (!res)
+			goto oda_exit3;
+
+		omap_device_fill_resources(od, res);
+
+		ret = platform_device_add_resources(pdev, res, res_count);
+		kfree(res);
+
+		if (ret)
+			goto oda_exit3;
+	}
+
+	if (!pm_lats) {
+		pm_lats = omap_default_latency;
+		pm_lats_cnt = ARRAY_SIZE(omap_default_latency);
+	}
+
+	od->pm_lats_cnt = pm_lats_cnt;
+	od->pm_lats = kmemdup(pm_lats,
+			sizeof(struct omap_device_pm_latency) * pm_lats_cnt,
+			GFP_KERNEL);
+	if (!od->pm_lats)
+		goto oda_exit3;
+
+	pdev->archdata.od = od;
+
+	for (i = 0; i < oh_cnt; i++) {
+		hwmods[i]->od = od;
+		_add_hwmod_clocks_clkdev(od, hwmods[i]);
+	}
+
+	return od;
+
+oda_exit3:
+	kfree(hwmods);
+oda_exit2:
+	kfree(od);
+oda_exit1:
+	dev_err(&pdev->dev, "omap_device: build failed (%d)\n", ret);
+
+	return ERR_PTR(ret);
+}
+
+static void omap_device_delete(struct omap_device *od)
+{
+	od->pdev->archdata.od = NULL;
+	kfree(od->pm_lats);
+	kfree(od->hwmods);
+	kfree(od);
+}
+
+/**
  * omap_device_build - build and register an omap_device with one omap_hwmod
  * @pdev_name: name of the platform_device driver to use
  * @pdev_id: this platform_device's connection ID
@@ -455,9 +564,6 @@ struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
 	int ret = -ENOMEM;
 	struct platform_device *pdev;
 	struct omap_device *od;
-	struct resource *res = NULL;
-	int i, res_count;
-	struct omap_hwmod **hwmods;
 
 	if (!ohs || oh_cnt == 0 || !pdev_name)
 		return ERR_PTR(-EINVAL);
@@ -471,76 +577,31 @@ struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
 		goto odbs_exit;
 	}
 
-	pr_debug("omap_device: %s: building with %d hwmods\n", pdev_name,
-		 oh_cnt);
+	/* Set the dev_name early to allow dev_xxx in omap_device_alloc */
+	if (pdev->id != -1)
+		dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);
+	else
+		dev_set_name(&pdev->dev, "%s", pdev->name);
 
-	od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
-	if (!od) {
-		ret = -ENOMEM;
+	od = omap_device_alloc(pdev, ohs, oh_cnt, pm_lats, pm_lats_cnt);
+	if (!od)
 		goto odbs_exit1;
-	}
-	od->hwmods_cnt = oh_cnt;
-
-	hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt,
-			 GFP_KERNEL);
-	if (!hwmods)
-		goto odbs_exit2;
-
-	memcpy(hwmods, ohs, sizeof(struct omap_hwmod *) * oh_cnt);
-	od->hwmods = hwmods;
-	od->pdev = pdev;
-
-	res_count = omap_device_count_resources(od);
-	if (res_count > 0) {
-		res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
-		if (!res)
-			goto odbs_exit3;
-
-		omap_device_fill_resources(od, res);
-
-		ret = platform_device_add_resources(pdev, res, res_count);
-		kfree(res);
-
-		if (ret)
-			goto odbs_exit3;
-	}
 
 	ret = platform_device_add_data(pdev, pdata, pdata_len);
 	if (ret)
-		goto odbs_exit3;
-
-	pdev->archdata.od = od;
+		goto odbs_exit2;
 
 	if (is_early_device)
 		ret = omap_early_device_register(pdev);
 	else
 		ret = omap_device_register(pdev);
 	if (ret)
-		goto odbs_exit3;
-
-	if (!pm_lats) {
-		pm_lats = omap_default_latency;
-		pm_lats_cnt = ARRAY_SIZE(omap_default_latency);
-	}
-
-	od->pm_lats_cnt = pm_lats_cnt;
-	od->pm_lats = kmemdup(pm_lats,
-			sizeof(struct omap_device_pm_latency) * pm_lats_cnt,
-			GFP_KERNEL);
-	if (!od->pm_lats)
-		goto odbs_exit3;
-
-	for (i = 0; i < oh_cnt; i++) {
-		hwmods[i]->od = od;
-		_add_hwmod_clocks_clkdev(od, hwmods[i]);
-	}
+		goto odbs_exit2;
 
 	return pdev;
 
-odbs_exit3:
-	kfree(hwmods);
 odbs_exit2:
-	kfree(od);
+	omap_device_delete(od);
 odbs_exit1:
 	platform_device_put(pdev);
 odbs_exit:
-- 
1.7.0.4

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

* [PATCH v3 2/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
  2011-09-22 20:52 ` Benoit Cousson
@ 2011-09-22 20:52   ` Benoit Cousson
  -1 siblings, 0 replies; 20+ messages in thread
From: Benoit Cousson @ 2011-09-22 20:52 UTC (permalink / raw)
  To: khilman; +Cc: linux-omap, linux-arm-kernel, grant.likely, Benoit Cousson

Add a notifier called during device_add phase. If an of_node is present,
retrieve the hwmod entry in order to populate properly the omap_device
structure.
For the moment the resource from the device-tree are overloaded.
DT does not support named resource yet, and thus, most driver
will not work without that information.

Add two helpers function to parse a property that contains multiple
strings. Please note that these helpers will be replaced by a more generic
iterator currently proposed on devicetree mailing list as soon as it
will be merged.

Add a documentation to capture the specifics OMAP bindings
needed for device-tree support.

Signed-off-by: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@ti.com>
---
 .../devicetree/bindings/arm/omap/omap.txt          |   42 ++++++
 arch/arm/plat-omap/omap_device.c                   |  145 ++++++++++++++++++++
 2 files changed, 187 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/omap/omap.txt

diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt
new file mode 100644
index 0000000..6513d05
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/omap.txt
@@ -0,0 +1,42 @@
+* Texas Instruments OMAP
+
+OMAP is currently using a static file per SoC family to describe the
+IPs present in the SoC.
+On top of that an omap_device is created to extend the platform_device
+capabilities and to allow binding with one or several hwmods.
+The hwmods will contain all the information to build the device:
+adresse range, irq lines, dma lines, interconnect, PRCM register,
+clock domain, input clocks.
+For the moment just point to the existing hwmod, the next step will be
+to move data from hwmod to device-tree representation.
+
+
+Required properties:
+- compatible: Every devices present in OMAP SoC should be in the
+  form: "ti,XXX"
+- ti,hwmods: list of hwmods attached to a device. Must contain at least
+  one hwmod.
+
+Optional properties:
+- ti,no_idle_on_suspend: When present, it prevents the PM to idle the module
+  during suspend.
+
+
+Example:
+
+spinlock@1 {
+    compatible = "ti,omap-spinlock";
+    ti,hwmods = "spinlock";
+};
+
+
+Boards:
+
+- OMAP3 BeagleBoard : Low cost community board
+  compatible = "ti,omap3-beagle", "ti,omap3"
+
+- OMAP4 SDP : Software Developement Board
+  compatible = "ti,omap4-sdp", "ti,omap4430"
+
+- OMAP4 PandaBoard : Low cost community board
+  compatible = "ti,omap4-panda", "ti,omap4430"
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index cac7b9a..5b63989 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -85,6 +85,8 @@
 #include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/notifier.h>
 
 #include <plat/omap_device.h>
 #include <plat/omap_hwmod.h>
@@ -94,12 +96,15 @@
 #define USE_WAKEUP_LAT			0
 #define IGNORE_WAKEUP_LAT		1
 
+#define MAX_HWMOD_NAME_SIZE		32
+
 static int omap_device_register(struct platform_device *pdev);
 static int omap_early_device_register(struct platform_device *pdev);
 static struct omap_device *omap_device_alloc(struct platform_device *pdev,
 				      struct omap_hwmod **ohs, int oh_cnt,
 				      struct omap_device_pm_latency *pm_lats,
 				      int pm_lats_cnt);
+static void omap_device_delete(struct omap_device *od);
 
 
 static struct omap_device_pm_latency omap_default_latency[] = {
@@ -315,6 +320,138 @@ static void _add_hwmod_clocks_clkdev(struct omap_device *od,
 		_add_clkdev(od, oh->opt_clks[i].role, oh->opt_clks[i].clk);
 }
 
+/*
+ * XXX: DT helper functions that should be replaced by more generic
+ * API introduced by Stephen Warren once they'll be in mainline.
+ */
+static int _dt_count_property_string(const char *prop, int len)
+{
+	int i = 0;
+	size_t l = 0, total = 0;
+
+	if (!prop || !len)
+		return -EINVAL;
+
+	for (i = 0; len >= total; total += l, prop += l) {
+		l = strlen(prop) + 1;
+		if (*prop != 0)
+			i++;
+	}
+	return i;
+}
+
+static int _dt_get_property(const char *prop, int len, int index, char *output,
+			    int size)
+{
+	int i = 0;
+	size_t l = 0, total = 0;
+
+	if (!prop || !len)
+		return -EINVAL;
+
+	for (i = 0; len >= total; total += l, prop += l) {
+		l = strlcpy(output, prop, size) + 1;
+		if (*prop != 0) {
+			if (i++ == index)
+				return 0;
+		}
+	}
+	return -ENODEV;
+}
+
+static struct dev_pm_domain omap_device_pm_domain;
+
+/**
+ * omap_device_build_from_dt - build an omap_device with multiple hwmods
+ * @pdev_name: name of the platform_device driver to use
+ * @pdev_id: this platform_device's connection ID
+ * @oh: ptr to the single omap_hwmod that backs this omap_device
+ * @pdata: platform_data ptr to associate with the platform_device
+ * @pdata_len: amount of memory pointed to by @pdata
+ * @pm_lats: pointer to a omap_device_pm_latency array for this device
+ * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
+ * @is_early_device: should the device be registered as an early device or not
+ *
+ * Function for building an omap_device already registered from device-tree
+ *
+ * Returns 0 or PTR_ERR() on error.
+ */
+static int omap_device_build_from_dt(struct platform_device *pdev)
+{
+	struct omap_hwmod **hwmods;
+	struct omap_device *od;
+	struct omap_hwmod *oh;
+	char oh_name[MAX_HWMOD_NAME_SIZE];
+	const char *prop;
+	int oh_cnt, i, prop_len;
+	int ret = 0;
+
+	prop = of_get_property(pdev->dev.of_node, "ti,hwmods", &prop_len);
+	oh_cnt = _dt_count_property_string(prop, prop_len);
+	if (!oh_cnt || IS_ERR_VALUE(oh_cnt)) {
+		dev_warn(&pdev->dev, "No 'hwmods' to build omap_device\n");
+		return -ENODEV;
+	}
+
+	hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
+	if (!hwmods) {
+		ret = -ENOMEM;
+		goto odbfd_exit;
+	}
+
+	for (i = 0; i < oh_cnt; i++) {
+		_dt_get_property(prop, prop_len, i, oh_name,
+				 MAX_HWMOD_NAME_SIZE);
+
+		oh = omap_hwmod_lookup(oh_name);
+		if (!oh) {
+			dev_err(&pdev->dev, "Cannot lookup hwmod '%s'\n",
+				oh_name);
+			ret = -EINVAL;
+			goto odbfd_exit1;
+		}
+		hwmods[i] = oh;
+	}
+
+	od = omap_device_alloc(pdev, hwmods, oh_cnt, NULL, 0);
+	if (!od) {
+		dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n",
+			oh_name);
+		ret = PTR_ERR(od);
+		goto odbfd_exit1;
+	}
+
+	if (of_get_property(pdev->dev.of_node, "ti,no_idle_on_suspend", NULL))
+		omap_device_disable_idle_on_suspend(pdev);
+
+	pdev->dev.pm_domain = &omap_device_pm_domain;
+
+odbfd_exit1:
+	kfree(hwmods);
+odbfd_exit:
+	return ret;
+}
+
+static int _omap_device_notifier_call(struct notifier_block *nb,
+				      unsigned long event, void *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	switch (event) {
+	case BUS_NOTIFY_ADD_DEVICE:
+		if (pdev->dev.of_node)
+			omap_device_build_from_dt(pdev);
+		break;
+
+	case BUS_NOTIFY_DEL_DEVICE:
+		if (pdev->archdata.od)
+			omap_device_delete(pdev->archdata.od);
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
 
 /* Public functions for use by core code */
 
@@ -499,6 +636,9 @@ oda_exit1:
 
 static void omap_device_delete(struct omap_device *od)
 {
+	if (!od)
+		return;
+
 	od->pdev->archdata.od = NULL;
 	kfree(od->pm_lats);
 	kfree(od->hwmods);
@@ -1034,8 +1174,13 @@ struct device omap_device_parent = {
 	.parent         = &platform_bus,
 };
 
+static struct notifier_block platform_nb = {
+	.notifier_call = _omap_device_notifier_call,
+};
+
 static int __init omap_device_init(void)
 {
+	bus_register_notifier(&platform_bus_type, &platform_nb);
 	return device_register(&omap_device_parent);
 }
 core_initcall(omap_device_init);
-- 
1.7.0.4


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

* [PATCH v3 2/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
@ 2011-09-22 20:52   ` Benoit Cousson
  0 siblings, 0 replies; 20+ messages in thread
From: Benoit Cousson @ 2011-09-22 20:52 UTC (permalink / raw)
  To: linux-arm-kernel

Add a notifier called during device_add phase. If an of_node is present,
retrieve the hwmod entry in order to populate properly the omap_device
structure.
For the moment the resource from the device-tree are overloaded.
DT does not support named resource yet, and thus, most driver
will not work without that information.

Add two helpers function to parse a property that contains multiple
strings. Please note that these helpers will be replaced by a more generic
iterator currently proposed on devicetree mailing list as soon as it
will be merged.

Add a documentation to capture the specifics OMAP bindings
needed for device-tree support.

Signed-off-by: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@ti.com>
---
 .../devicetree/bindings/arm/omap/omap.txt          |   42 ++++++
 arch/arm/plat-omap/omap_device.c                   |  145 ++++++++++++++++++++
 2 files changed, 187 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/omap/omap.txt

diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt
new file mode 100644
index 0000000..6513d05
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/omap.txt
@@ -0,0 +1,42 @@
+* Texas Instruments OMAP
+
+OMAP is currently using a static file per SoC family to describe the
+IPs present in the SoC.
+On top of that an omap_device is created to extend the platform_device
+capabilities and to allow binding with one or several hwmods.
+The hwmods will contain all the information to build the device:
+adresse range, irq lines, dma lines, interconnect, PRCM register,
+clock domain, input clocks.
+For the moment just point to the existing hwmod, the next step will be
+to move data from hwmod to device-tree representation.
+
+
+Required properties:
+- compatible: Every devices present in OMAP SoC should be in the
+  form: "ti,XXX"
+- ti,hwmods: list of hwmods attached to a device. Must contain at least
+  one hwmod.
+
+Optional properties:
+- ti,no_idle_on_suspend: When present, it prevents the PM to idle the module
+  during suspend.
+
+
+Example:
+
+spinlock at 1 {
+    compatible = "ti,omap-spinlock";
+    ti,hwmods = "spinlock";
+};
+
+
+Boards:
+
+- OMAP3 BeagleBoard : Low cost community board
+  compatible = "ti,omap3-beagle", "ti,omap3"
+
+- OMAP4 SDP : Software Developement Board
+  compatible = "ti,omap4-sdp", "ti,omap4430"
+
+- OMAP4 PandaBoard : Low cost community board
+  compatible = "ti,omap4-panda", "ti,omap4430"
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index cac7b9a..5b63989 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -85,6 +85,8 @@
 #include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/notifier.h>
 
 #include <plat/omap_device.h>
 #include <plat/omap_hwmod.h>
@@ -94,12 +96,15 @@
 #define USE_WAKEUP_LAT			0
 #define IGNORE_WAKEUP_LAT		1
 
+#define MAX_HWMOD_NAME_SIZE		32
+
 static int omap_device_register(struct platform_device *pdev);
 static int omap_early_device_register(struct platform_device *pdev);
 static struct omap_device *omap_device_alloc(struct platform_device *pdev,
 				      struct omap_hwmod **ohs, int oh_cnt,
 				      struct omap_device_pm_latency *pm_lats,
 				      int pm_lats_cnt);
+static void omap_device_delete(struct omap_device *od);
 
 
 static struct omap_device_pm_latency omap_default_latency[] = {
@@ -315,6 +320,138 @@ static void _add_hwmod_clocks_clkdev(struct omap_device *od,
 		_add_clkdev(od, oh->opt_clks[i].role, oh->opt_clks[i].clk);
 }
 
+/*
+ * XXX: DT helper functions that should be replaced by more generic
+ * API introduced by Stephen Warren once they'll be in mainline.
+ */
+static int _dt_count_property_string(const char *prop, int len)
+{
+	int i = 0;
+	size_t l = 0, total = 0;
+
+	if (!prop || !len)
+		return -EINVAL;
+
+	for (i = 0; len >= total; total += l, prop += l) {
+		l = strlen(prop) + 1;
+		if (*prop != 0)
+			i++;
+	}
+	return i;
+}
+
+static int _dt_get_property(const char *prop, int len, int index, char *output,
+			    int size)
+{
+	int i = 0;
+	size_t l = 0, total = 0;
+
+	if (!prop || !len)
+		return -EINVAL;
+
+	for (i = 0; len >= total; total += l, prop += l) {
+		l = strlcpy(output, prop, size) + 1;
+		if (*prop != 0) {
+			if (i++ == index)
+				return 0;
+		}
+	}
+	return -ENODEV;
+}
+
+static struct dev_pm_domain omap_device_pm_domain;
+
+/**
+ * omap_device_build_from_dt - build an omap_device with multiple hwmods
+ * @pdev_name: name of the platform_device driver to use
+ * @pdev_id: this platform_device's connection ID
+ * @oh: ptr to the single omap_hwmod that backs this omap_device
+ * @pdata: platform_data ptr to associate with the platform_device
+ * @pdata_len: amount of memory pointed to by @pdata
+ * @pm_lats: pointer to a omap_device_pm_latency array for this device
+ * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
+ * @is_early_device: should the device be registered as an early device or not
+ *
+ * Function for building an omap_device already registered from device-tree
+ *
+ * Returns 0 or PTR_ERR() on error.
+ */
+static int omap_device_build_from_dt(struct platform_device *pdev)
+{
+	struct omap_hwmod **hwmods;
+	struct omap_device *od;
+	struct omap_hwmod *oh;
+	char oh_name[MAX_HWMOD_NAME_SIZE];
+	const char *prop;
+	int oh_cnt, i, prop_len;
+	int ret = 0;
+
+	prop = of_get_property(pdev->dev.of_node, "ti,hwmods", &prop_len);
+	oh_cnt = _dt_count_property_string(prop, prop_len);
+	if (!oh_cnt || IS_ERR_VALUE(oh_cnt)) {
+		dev_warn(&pdev->dev, "No 'hwmods' to build omap_device\n");
+		return -ENODEV;
+	}
+
+	hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
+	if (!hwmods) {
+		ret = -ENOMEM;
+		goto odbfd_exit;
+	}
+
+	for (i = 0; i < oh_cnt; i++) {
+		_dt_get_property(prop, prop_len, i, oh_name,
+				 MAX_HWMOD_NAME_SIZE);
+
+		oh = omap_hwmod_lookup(oh_name);
+		if (!oh) {
+			dev_err(&pdev->dev, "Cannot lookup hwmod '%s'\n",
+				oh_name);
+			ret = -EINVAL;
+			goto odbfd_exit1;
+		}
+		hwmods[i] = oh;
+	}
+
+	od = omap_device_alloc(pdev, hwmods, oh_cnt, NULL, 0);
+	if (!od) {
+		dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n",
+			oh_name);
+		ret = PTR_ERR(od);
+		goto odbfd_exit1;
+	}
+
+	if (of_get_property(pdev->dev.of_node, "ti,no_idle_on_suspend", NULL))
+		omap_device_disable_idle_on_suspend(pdev);
+
+	pdev->dev.pm_domain = &omap_device_pm_domain;
+
+odbfd_exit1:
+	kfree(hwmods);
+odbfd_exit:
+	return ret;
+}
+
+static int _omap_device_notifier_call(struct notifier_block *nb,
+				      unsigned long event, void *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	switch (event) {
+	case BUS_NOTIFY_ADD_DEVICE:
+		if (pdev->dev.of_node)
+			omap_device_build_from_dt(pdev);
+		break;
+
+	case BUS_NOTIFY_DEL_DEVICE:
+		if (pdev->archdata.od)
+			omap_device_delete(pdev->archdata.od);
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
 
 /* Public functions for use by core code */
 
@@ -499,6 +636,9 @@ oda_exit1:
 
 static void omap_device_delete(struct omap_device *od)
 {
+	if (!od)
+		return;
+
 	od->pdev->archdata.od = NULL;
 	kfree(od->pm_lats);
 	kfree(od->hwmods);
@@ -1034,8 +1174,13 @@ struct device omap_device_parent = {
 	.parent         = &platform_bus,
 };
 
+static struct notifier_block platform_nb = {
+	.notifier_call = _omap_device_notifier_call,
+};
+
 static int __init omap_device_init(void)
 {
+	bus_register_notifier(&platform_bus_type, &platform_nb);
 	return device_register(&omap_device_parent);
 }
 core_initcall(omap_device_init);
-- 
1.7.0.4

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

* Re: [PATCH v3 0/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
  2011-09-22 20:52 ` Benoit Cousson
@ 2011-09-26 22:38   ` Kevin Hilman
  -1 siblings, 0 replies; 20+ messages in thread
From: Kevin Hilman @ 2011-09-26 22:38 UTC (permalink / raw)
  To: Benoit Cousson; +Cc: grant.likely, linux-omap, linux-arm-kernel

Hi Benoit,

Benoit Cousson <b-cousson@ti.com> writes:

> This is the updated version of the initial series that introduced a
> notifier in order to create an omap_device from a platform_device bound
> to DT node as suggested by Grant.

This series looks good to me.

Barring any final comments (Grant?), I'll be queueing this for 3.2 in my
omap_device queue on top of your previous cleanup series.

Kevin

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

* [PATCH v3 0/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
@ 2011-09-26 22:38   ` Kevin Hilman
  0 siblings, 0 replies; 20+ messages in thread
From: Kevin Hilman @ 2011-09-26 22:38 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Benoit,

Benoit Cousson <b-cousson@ti.com> writes:

> This is the updated version of the initial series that introduced a
> notifier in order to create an omap_device from a platform_device bound
> to DT node as suggested by Grant.

This series looks good to me.

Barring any final comments (Grant?), I'll be queueing this for 3.2 in my
omap_device queue on top of your previous cleanup series.

Kevin

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

* Re: [PATCH v3 2/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
  2011-09-22 20:52   ` Benoit Cousson
@ 2011-09-27  1:46     ` Grant Likely
  -1 siblings, 0 replies; 20+ messages in thread
From: Grant Likely @ 2011-09-27  1:46 UTC (permalink / raw)
  To: Benoit Cousson; +Cc: khilman, linux-omap, linux-arm-kernel

On Thu, Sep 22, 2011 at 10:52:25PM +0200, Benoit Cousson wrote:
> Add a notifier called during device_add phase. If an of_node is present,
> retrieve the hwmod entry in order to populate properly the omap_device
> structure.
> For the moment the resource from the device-tree are overloaded.
> DT does not support named resource yet, and thus, most driver
> will not work without that information.
> 
> Add two helpers function to parse a property that contains multiple
> strings. Please note that these helpers will be replaced by a more generic
> iterator currently proposed on devicetree mailing list as soon as it
> will be merged.
> 
> Add a documentation to capture the specifics OMAP bindings
> needed for device-tree support.
> 
> Signed-off-by: Benoit Cousson <b-cousson@ti.com>
> Cc: Kevin Hilman <khilman@ti.com>
> ---
>  .../devicetree/bindings/arm/omap/omap.txt          |   42 ++++++
>  arch/arm/plat-omap/omap_device.c                   |  145 ++++++++++++++++++++
>  2 files changed, 187 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/omap/omap.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt
> new file mode 100644
> index 0000000..6513d05
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/omap/omap.txt
> @@ -0,0 +1,42 @@
> +* Texas Instruments OMAP
> +
> +OMAP is currently using a static file per SoC family to describe the
> +IPs present in the SoC.
> +On top of that an omap_device is created to extend the platform_device
> +capabilities and to allow binding with one or several hwmods.
> +The hwmods will contain all the information to build the device:
> +adresse range, irq lines, dma lines, interconnect, PRCM register,
> +clock domain, input clocks.
> +For the moment just point to the existing hwmod, the next step will be
> +to move data from hwmod to device-tree representation.
> +
> +
> +Required properties:
> +- compatible: Every devices present in OMAP SoC should be in the
> +  form: "ti,XXX"
> +- ti,hwmods: list of hwmods attached to a device. Must contain at least
> +  one hwmod.

Nit: This should specify that ti,hwmods is a list of hwmod names
(ascii strings), and that the hwmod names come from the OMAP
documentation.  Don't respin the patch over this though, just do a
follow-up patch.

> +
> +Optional properties:
> +- ti,no_idle_on_suspend: When present, it prevents the PM to idle the module
> +  during suspend.
> +
> +
> +Example:
> +
> +spinlock@1 {
> +    compatible = "ti,omap-spinlock";
> +    ti,hwmods = "spinlock";
> +};
> +
> +
> +Boards:
> +
> +- OMAP3 BeagleBoard : Low cost community board
> +  compatible = "ti,omap3-beagle", "ti,omap3"
> +
> +- OMAP4 SDP : Software Developement Board
> +  compatible = "ti,omap4-sdp", "ti,omap4430"
> +
> +- OMAP4 PandaBoard : Low cost community board
> +  compatible = "ti,omap4-panda", "ti,omap4430"
> diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
> index cac7b9a..5b63989 100644
> --- a/arch/arm/plat-omap/omap_device.c
> +++ b/arch/arm/plat-omap/omap_device.c
> @@ -85,6 +85,8 @@
>  #include <linux/clk.h>
>  #include <linux/clkdev.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/of.h>
> +#include <linux/notifier.h>
>  
>  #include <plat/omap_device.h>
>  #include <plat/omap_hwmod.h>
> @@ -94,12 +96,15 @@
>  #define USE_WAKEUP_LAT			0
>  #define IGNORE_WAKEUP_LAT		1
>  
> +#define MAX_HWMOD_NAME_SIZE		32
> +
>  static int omap_device_register(struct platform_device *pdev);
>  static int omap_early_device_register(struct platform_device *pdev);
>  static struct omap_device *omap_device_alloc(struct platform_device *pdev,
>  				      struct omap_hwmod **ohs, int oh_cnt,
>  				      struct omap_device_pm_latency *pm_lats,
>  				      int pm_lats_cnt);
> +static void omap_device_delete(struct omap_device *od);
>  
>  
>  static struct omap_device_pm_latency omap_default_latency[] = {
> @@ -315,6 +320,138 @@ static void _add_hwmod_clocks_clkdev(struct omap_device *od,
>  		_add_clkdev(od, oh->opt_clks[i].role, oh->opt_clks[i].clk);
>  }
>  
> +/*
> + * XXX: DT helper functions that should be replaced by more generic
> + * API introduced by Stephen Warren once they'll be in mainline.
> + */
> +static int _dt_count_property_string(const char *prop, int len)
> +{
> +	int i = 0;
> +	size_t l = 0, total = 0;
> +
> +	if (!prop || !len)
> +		return -EINVAL;
> +
> +	for (i = 0; len >= total; total += l, prop += l) {
> +		l = strlen(prop) + 1;
> +		if (*prop != 0)
> +			i++;
> +	}
> +	return i;
> +}
> +
> +static int _dt_get_property(const char *prop, int len, int index, char *output,
> +			    int size)
> +{
> +	int i = 0;
> +	size_t l = 0, total = 0;
> +
> +	if (!prop || !len)
> +		return -EINVAL;
> +
> +	for (i = 0; len >= total; total += l, prop += l) {
> +		l = strlcpy(output, prop, size) + 1;
> +		if (*prop != 0) {
> +			if (i++ == index)
> +				return 0;
> +		}
> +	}
> +	return -ENODEV;
> +}

Don't merge this.  Kevin or I could put Stephen's patch into a separate
branch that both Kevin and I pull.  There's no need to merge temporary
code.

That said, I just looked at Stephen's iterator, and even without it
this particular hunk shouldn't be merged here.  A
of_property_count_strings() function is useful in and of itself, and
of_property_read_string() could be extended with an
of_property_read_string_index() version.  Both changes should be in
the common drivers/of code, and you can easily do them.

Otherwise, both patches look good to me.

g.

> +
> +static struct dev_pm_domain omap_device_pm_domain;
> +
> +/**
> + * omap_device_build_from_dt - build an omap_device with multiple hwmods
> + * @pdev_name: name of the platform_device driver to use
> + * @pdev_id: this platform_device's connection ID
> + * @oh: ptr to the single omap_hwmod that backs this omap_device
> + * @pdata: platform_data ptr to associate with the platform_device
> + * @pdata_len: amount of memory pointed to by @pdata
> + * @pm_lats: pointer to a omap_device_pm_latency array for this device
> + * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
> + * @is_early_device: should the device be registered as an early device or not
> + *
> + * Function for building an omap_device already registered from device-tree
> + *
> + * Returns 0 or PTR_ERR() on error.
> + */
> +static int omap_device_build_from_dt(struct platform_device *pdev)
> +{
> +	struct omap_hwmod **hwmods;
> +	struct omap_device *od;
> +	struct omap_hwmod *oh;
> +	char oh_name[MAX_HWMOD_NAME_SIZE];
> +	const char *prop;
> +	int oh_cnt, i, prop_len;
> +	int ret = 0;
> +
> +	prop = of_get_property(pdev->dev.of_node, "ti,hwmods", &prop_len);
> +	oh_cnt = _dt_count_property_string(prop, prop_len);
> +	if (!oh_cnt || IS_ERR_VALUE(oh_cnt)) {
> +		dev_warn(&pdev->dev, "No 'hwmods' to build omap_device\n");
> +		return -ENODEV;
> +	}
> +
> +	hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
> +	if (!hwmods) {
> +		ret = -ENOMEM;
> +		goto odbfd_exit;
> +	}
> +
> +	for (i = 0; i < oh_cnt; i++) {
> +		_dt_get_property(prop, prop_len, i, oh_name,
> +				 MAX_HWMOD_NAME_SIZE);
> +
> +		oh = omap_hwmod_lookup(oh_name);
> +		if (!oh) {
> +			dev_err(&pdev->dev, "Cannot lookup hwmod '%s'\n",
> +				oh_name);
> +			ret = -EINVAL;
> +			goto odbfd_exit1;
> +		}
> +		hwmods[i] = oh;
> +	}
> +
> +	od = omap_device_alloc(pdev, hwmods, oh_cnt, NULL, 0);
> +	if (!od) {
> +		dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n",
> +			oh_name);
> +		ret = PTR_ERR(od);
> +		goto odbfd_exit1;
> +	}
> +
> +	if (of_get_property(pdev->dev.of_node, "ti,no_idle_on_suspend", NULL))
> +		omap_device_disable_idle_on_suspend(pdev);
> +
> +	pdev->dev.pm_domain = &omap_device_pm_domain;
> +
> +odbfd_exit1:
> +	kfree(hwmods);
> +odbfd_exit:
> +	return ret;
> +}
> +
> +static int _omap_device_notifier_call(struct notifier_block *nb,
> +				      unsigned long event, void *dev)
> +{
> +	struct platform_device *pdev = to_platform_device(dev);
> +
> +	switch (event) {
> +	case BUS_NOTIFY_ADD_DEVICE:
> +		if (pdev->dev.of_node)
> +			omap_device_build_from_dt(pdev);
> +		break;
> +
> +	case BUS_NOTIFY_DEL_DEVICE:
> +		if (pdev->archdata.od)
> +			omap_device_delete(pdev->archdata.od);
> +		break;
> +	}
> +
> +	return NOTIFY_DONE;
> +}
> +
>  
>  /* Public functions for use by core code */
>  
> @@ -499,6 +636,9 @@ oda_exit1:
>  
>  static void omap_device_delete(struct omap_device *od)
>  {
> +	if (!od)
> +		return;
> +
>  	od->pdev->archdata.od = NULL;
>  	kfree(od->pm_lats);
>  	kfree(od->hwmods);
> @@ -1034,8 +1174,13 @@ struct device omap_device_parent = {
>  	.parent         = &platform_bus,
>  };
>  
> +static struct notifier_block platform_nb = {
> +	.notifier_call = _omap_device_notifier_call,
> +};
> +
>  static int __init omap_device_init(void)
>  {
> +	bus_register_notifier(&platform_bus_type, &platform_nb);
>  	return device_register(&omap_device_parent);
>  }
>  core_initcall(omap_device_init);
> -- 
> 1.7.0.4
> 

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

* [PATCH v3 2/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
@ 2011-09-27  1:46     ` Grant Likely
  0 siblings, 0 replies; 20+ messages in thread
From: Grant Likely @ 2011-09-27  1:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 22, 2011 at 10:52:25PM +0200, Benoit Cousson wrote:
> Add a notifier called during device_add phase. If an of_node is present,
> retrieve the hwmod entry in order to populate properly the omap_device
> structure.
> For the moment the resource from the device-tree are overloaded.
> DT does not support named resource yet, and thus, most driver
> will not work without that information.
> 
> Add two helpers function to parse a property that contains multiple
> strings. Please note that these helpers will be replaced by a more generic
> iterator currently proposed on devicetree mailing list as soon as it
> will be merged.
> 
> Add a documentation to capture the specifics OMAP bindings
> needed for device-tree support.
> 
> Signed-off-by: Benoit Cousson <b-cousson@ti.com>
> Cc: Kevin Hilman <khilman@ti.com>
> ---
>  .../devicetree/bindings/arm/omap/omap.txt          |   42 ++++++
>  arch/arm/plat-omap/omap_device.c                   |  145 ++++++++++++++++++++
>  2 files changed, 187 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/omap/omap.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt
> new file mode 100644
> index 0000000..6513d05
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/omap/omap.txt
> @@ -0,0 +1,42 @@
> +* Texas Instruments OMAP
> +
> +OMAP is currently using a static file per SoC family to describe the
> +IPs present in the SoC.
> +On top of that an omap_device is created to extend the platform_device
> +capabilities and to allow binding with one or several hwmods.
> +The hwmods will contain all the information to build the device:
> +adresse range, irq lines, dma lines, interconnect, PRCM register,
> +clock domain, input clocks.
> +For the moment just point to the existing hwmod, the next step will be
> +to move data from hwmod to device-tree representation.
> +
> +
> +Required properties:
> +- compatible: Every devices present in OMAP SoC should be in the
> +  form: "ti,XXX"
> +- ti,hwmods: list of hwmods attached to a device. Must contain at least
> +  one hwmod.

Nit: This should specify that ti,hwmods is a list of hwmod names
(ascii strings), and that the hwmod names come from the OMAP
documentation.  Don't respin the patch over this though, just do a
follow-up patch.

> +
> +Optional properties:
> +- ti,no_idle_on_suspend: When present, it prevents the PM to idle the module
> +  during suspend.
> +
> +
> +Example:
> +
> +spinlock at 1 {
> +    compatible = "ti,omap-spinlock";
> +    ti,hwmods = "spinlock";
> +};
> +
> +
> +Boards:
> +
> +- OMAP3 BeagleBoard : Low cost community board
> +  compatible = "ti,omap3-beagle", "ti,omap3"
> +
> +- OMAP4 SDP : Software Developement Board
> +  compatible = "ti,omap4-sdp", "ti,omap4430"
> +
> +- OMAP4 PandaBoard : Low cost community board
> +  compatible = "ti,omap4-panda", "ti,omap4430"
> diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
> index cac7b9a..5b63989 100644
> --- a/arch/arm/plat-omap/omap_device.c
> +++ b/arch/arm/plat-omap/omap_device.c
> @@ -85,6 +85,8 @@
>  #include <linux/clk.h>
>  #include <linux/clkdev.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/of.h>
> +#include <linux/notifier.h>
>  
>  #include <plat/omap_device.h>
>  #include <plat/omap_hwmod.h>
> @@ -94,12 +96,15 @@
>  #define USE_WAKEUP_LAT			0
>  #define IGNORE_WAKEUP_LAT		1
>  
> +#define MAX_HWMOD_NAME_SIZE		32
> +
>  static int omap_device_register(struct platform_device *pdev);
>  static int omap_early_device_register(struct platform_device *pdev);
>  static struct omap_device *omap_device_alloc(struct platform_device *pdev,
>  				      struct omap_hwmod **ohs, int oh_cnt,
>  				      struct omap_device_pm_latency *pm_lats,
>  				      int pm_lats_cnt);
> +static void omap_device_delete(struct omap_device *od);
>  
>  
>  static struct omap_device_pm_latency omap_default_latency[] = {
> @@ -315,6 +320,138 @@ static void _add_hwmod_clocks_clkdev(struct omap_device *od,
>  		_add_clkdev(od, oh->opt_clks[i].role, oh->opt_clks[i].clk);
>  }
>  
> +/*
> + * XXX: DT helper functions that should be replaced by more generic
> + * API introduced by Stephen Warren once they'll be in mainline.
> + */
> +static int _dt_count_property_string(const char *prop, int len)
> +{
> +	int i = 0;
> +	size_t l = 0, total = 0;
> +
> +	if (!prop || !len)
> +		return -EINVAL;
> +
> +	for (i = 0; len >= total; total += l, prop += l) {
> +		l = strlen(prop) + 1;
> +		if (*prop != 0)
> +			i++;
> +	}
> +	return i;
> +}
> +
> +static int _dt_get_property(const char *prop, int len, int index, char *output,
> +			    int size)
> +{
> +	int i = 0;
> +	size_t l = 0, total = 0;
> +
> +	if (!prop || !len)
> +		return -EINVAL;
> +
> +	for (i = 0; len >= total; total += l, prop += l) {
> +		l = strlcpy(output, prop, size) + 1;
> +		if (*prop != 0) {
> +			if (i++ == index)
> +				return 0;
> +		}
> +	}
> +	return -ENODEV;
> +}

Don't merge this.  Kevin or I could put Stephen's patch into a separate
branch that both Kevin and I pull.  There's no need to merge temporary
code.

That said, I just looked at Stephen's iterator, and even without it
this particular hunk shouldn't be merged here.  A
of_property_count_strings() function is useful in and of itself, and
of_property_read_string() could be extended with an
of_property_read_string_index() version.  Both changes should be in
the common drivers/of code, and you can easily do them.

Otherwise, both patches look good to me.

g.

> +
> +static struct dev_pm_domain omap_device_pm_domain;
> +
> +/**
> + * omap_device_build_from_dt - build an omap_device with multiple hwmods
> + * @pdev_name: name of the platform_device driver to use
> + * @pdev_id: this platform_device's connection ID
> + * @oh: ptr to the single omap_hwmod that backs this omap_device
> + * @pdata: platform_data ptr to associate with the platform_device
> + * @pdata_len: amount of memory pointed to by @pdata
> + * @pm_lats: pointer to a omap_device_pm_latency array for this device
> + * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
> + * @is_early_device: should the device be registered as an early device or not
> + *
> + * Function for building an omap_device already registered from device-tree
> + *
> + * Returns 0 or PTR_ERR() on error.
> + */
> +static int omap_device_build_from_dt(struct platform_device *pdev)
> +{
> +	struct omap_hwmod **hwmods;
> +	struct omap_device *od;
> +	struct omap_hwmod *oh;
> +	char oh_name[MAX_HWMOD_NAME_SIZE];
> +	const char *prop;
> +	int oh_cnt, i, prop_len;
> +	int ret = 0;
> +
> +	prop = of_get_property(pdev->dev.of_node, "ti,hwmods", &prop_len);
> +	oh_cnt = _dt_count_property_string(prop, prop_len);
> +	if (!oh_cnt || IS_ERR_VALUE(oh_cnt)) {
> +		dev_warn(&pdev->dev, "No 'hwmods' to build omap_device\n");
> +		return -ENODEV;
> +	}
> +
> +	hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
> +	if (!hwmods) {
> +		ret = -ENOMEM;
> +		goto odbfd_exit;
> +	}
> +
> +	for (i = 0; i < oh_cnt; i++) {
> +		_dt_get_property(prop, prop_len, i, oh_name,
> +				 MAX_HWMOD_NAME_SIZE);
> +
> +		oh = omap_hwmod_lookup(oh_name);
> +		if (!oh) {
> +			dev_err(&pdev->dev, "Cannot lookup hwmod '%s'\n",
> +				oh_name);
> +			ret = -EINVAL;
> +			goto odbfd_exit1;
> +		}
> +		hwmods[i] = oh;
> +	}
> +
> +	od = omap_device_alloc(pdev, hwmods, oh_cnt, NULL, 0);
> +	if (!od) {
> +		dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n",
> +			oh_name);
> +		ret = PTR_ERR(od);
> +		goto odbfd_exit1;
> +	}
> +
> +	if (of_get_property(pdev->dev.of_node, "ti,no_idle_on_suspend", NULL))
> +		omap_device_disable_idle_on_suspend(pdev);
> +
> +	pdev->dev.pm_domain = &omap_device_pm_domain;
> +
> +odbfd_exit1:
> +	kfree(hwmods);
> +odbfd_exit:
> +	return ret;
> +}
> +
> +static int _omap_device_notifier_call(struct notifier_block *nb,
> +				      unsigned long event, void *dev)
> +{
> +	struct platform_device *pdev = to_platform_device(dev);
> +
> +	switch (event) {
> +	case BUS_NOTIFY_ADD_DEVICE:
> +		if (pdev->dev.of_node)
> +			omap_device_build_from_dt(pdev);
> +		break;
> +
> +	case BUS_NOTIFY_DEL_DEVICE:
> +		if (pdev->archdata.od)
> +			omap_device_delete(pdev->archdata.od);
> +		break;
> +	}
> +
> +	return NOTIFY_DONE;
> +}
> +
>  
>  /* Public functions for use by core code */
>  
> @@ -499,6 +636,9 @@ oda_exit1:
>  
>  static void omap_device_delete(struct omap_device *od)
>  {
> +	if (!od)
> +		return;
> +
>  	od->pdev->archdata.od = NULL;
>  	kfree(od->pm_lats);
>  	kfree(od->hwmods);
> @@ -1034,8 +1174,13 @@ struct device omap_device_parent = {
>  	.parent         = &platform_bus,
>  };
>  
> +static struct notifier_block platform_nb = {
> +	.notifier_call = _omap_device_notifier_call,
> +};
> +
>  static int __init omap_device_init(void)
>  {
> +	bus_register_notifier(&platform_bus_type, &platform_nb);
>  	return device_register(&omap_device_parent);
>  }
>  core_initcall(omap_device_init);
> -- 
> 1.7.0.4
> 

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

* Re: [PATCH v3 2/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
  2011-09-27  1:46     ` Grant Likely
@ 2011-09-27 16:04       ` Cousson, Benoit
  -1 siblings, 0 replies; 20+ messages in thread
From: Cousson, Benoit @ 2011-09-27 16:04 UTC (permalink / raw)
  To: Grant Likely; +Cc: Hilman, Kevin, linux-omap, linux-arm-kernel

On 9/27/2011 3:46 AM, Grant Likely wrote:
> On Thu, Sep 22, 2011 at 10:52:25PM +0200, Benoit Cousson wrote:

[...]

>> +Required properties:
>> +- compatible: Every devices present in OMAP SoC should be in the
>> +  form: "ti,XXX"
>> +- ti,hwmods: list of hwmods attached to a device. Must contain at least
>> +  one hwmod.
> 
> Nit: This should specify that ti,hwmods is a list of hwmod names
> (ascii strings), and that the hwmod names come from the OMAP
> documentation.  Don't respin the patch over this though, just do a
> follow-up patch.

OK, but since you asked later to remove the DT helpers, I will have to resend it anyway:-)

[...]

>> +/*
>> + * XXX: DT helper functions that should be replaced by more generic
>> + * API introduced by Stephen Warren once they'll be in mainline.
>> + */
>> +static int _dt_count_property_string(const char *prop, int len)
>> +{
>> +	int i = 0;
>> +	size_t l = 0, total = 0;
>> +
>> +	if (!prop || !len)
>> +		return -EINVAL;
>> +
>> +	for (i = 0; len>= total; total += l, prop += l) {
>> +		l = strlen(prop) + 1;
>> +		if (*prop != 0)
>> +			i++;
>> +	}
>> +	return i;
>> +}
>> +
>> +static int _dt_get_property(const char *prop, int len, int index, char *output,
>> +			    int size)
>> +{
>> +	int i = 0;
>> +	size_t l = 0, total = 0;
>> +
>> +	if (!prop || !len)
>> +		return -EINVAL;
>> +
>> +	for (i = 0; len>= total; total += l, prop += l) {
>> +		l = strlcpy(output, prop, size) + 1;
>> +		if (*prop != 0) {
>> +			if (i++ == index)
>> +				return 0;
>> +		}
>> +	}
>> +	return -ENODEV;
>> +}
> 
> Don't merge this.  Kevin or I could put Stephen's patch into a separate
> branch that both Kevin and I pull.  There's no need to merge temporary
> code.
> 
> That said, I just looked at Stephen's iterator, and even without it
> this particular hunk shouldn't be merged here.  A
> of_property_count_strings() function is useful in and of itself, and
> of_property_read_string() could be extended with an
> of_property_read_string_index() version.  Both changes should be in
> the common drivers/of code, and you can easily do them.

I'm fine with that, but in that case, and in order to be consistent with the existing of_property_read_string, I should include the find_property in these functions. Whereas in my case, it was supposed to be done before.

Please find below a first version of this patch.

Regards,
Benoit

---
>From 4403f8a00090e5ea1814a5242947b81c348947a1 Mon Sep 17 00:00:00 2001
From: Benoit Cousson <b-cousson@ti.com>
Date: Tue, 27 Sep 2011 17:45:43 +0200
Subject: [PATCH] of: Add helpers to get one string in multiple strings property

Add of_property_read_string_index and of_property_count_strings
to retrieve one string inside a property that will contains
severals strings.

Signed-off-by: Benoit Cousson <b-cousson@ti.com>
---
 drivers/of/base.c  |   85 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/of.h |   18 +++++++++++
 2 files changed, 103 insertions(+), 0 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 3ff22e3..d97d53e 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -662,6 +662,91 @@ int of_property_read_string(struct device_node *np, const char *propname,
 EXPORT_SYMBOL_GPL(of_property_read_string);
 
 /**
+ * of_property_read_string_index - Find and read a string from a multiple
+ * strings property.
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ * @index:	index of the string in the list of strings
+ * @out_string:	pointer to null terminated return string, modified only if
+ *		return value is 0.
+ *
+ * Search for a property in a device tree node and retrieve a null
+ * terminated string value (pointer to data, not a copy) in the list of strings
+ * contained in that property.
+ * Returns 0 on
+ * success, -EINVAL if the property does not exist, -ENODATA if property
+ * does not have a value, and -EILSEQ if the string is not null-terminated
+ * within the length of the property data.
+ *
+ * The out_string pointer is modified only if a valid string can be decoded.
+ */
+int of_property_read_string_index(struct device_node *np, const char *propname,
+				  int index, const char **output)
+{
+	struct property *prop = of_find_property(np, propname, NULL);
+	int i = 0;
+	size_t l = 0, total = 0;
+	const char *p;
+
+	if (!prop)
+		return -EINVAL;
+	if (!prop->value)
+		return -ENODATA;
+	if (strnlen(prop->value, prop->length) >= prop->length)
+		return -EILSEQ;
+
+	p = prop->value;
+
+	for (i = 0; total < prop->length; total += l, p += l) {
+		l = strlen(p) + 1;
+		if ((*p != 0) && (i++ == index)) {
+			*output = p;
+			return 0;
+		}
+	}
+	return -ENODATA;
+}
+EXPORT_SYMBOL_GPL(of_property_read_string_index);
+
+
+/**
+ * of_property_count_strings - Find and return the number of strings from a
+ * multiple strings property.
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ *
+ * Search for a property in a device tree node and retrieve the number of null
+ * terminated string contain in it. Returns the number of strings on
+ * success, -EINVAL if the property does not exist, -ENODATA if property
+ * does not have a value, and -EILSEQ if the string is not null-terminated
+ * within the length of the property data.
+ */
+int of_property_count_strings(struct device_node *np, const char *propname)
+{
+	struct property *prop = of_find_property(np, propname, NULL);
+	int i = 0;
+	size_t l = 0, total = 0;
+	const char *p;
+
+	if (!prop)
+		return -EINVAL;
+	if (!prop->value)
+		return -ENODATA;
+	if (strnlen(prop->value, prop->length) >= prop->length)
+		return -EILSEQ;
+
+	p = prop->value;
+
+	for (i = 0; total < prop->length; total += l, p += l) {
+		l = strlen(p) + 1;
+		if (*p != 0)
+			i++;
+	}
+	return i;
+}
+EXPORT_SYMBOL_GPL(of_property_count_strings);
+
+/**
  * of_parse_phandle - Resolve a phandle property to a device_node pointer
  * @np: Pointer to device node holding phandle property
  * @phandle_name: Name of property holding a phandle value
diff --git a/include/linux/of.h b/include/linux/of.h
index 9180dc5..9eadc4e 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -203,6 +203,11 @@ extern int of_property_read_u32_array(const struct device_node *np,
 extern int of_property_read_string(struct device_node *np,
 				   const char *propname,
 				   const char **out_string);
+extern int of_property_read_string_index(struct device_node *np,
+					 const char *propname,
+					 int index, const char **output);
+extern int of_property_count_strings(struct device_node *np,
+				     const char *propname);
 extern int of_device_is_compatible(const struct device_node *device,
 				   const char *);
 extern int of_device_is_available(const struct device_node *device);
@@ -256,6 +261,19 @@ static inline int of_property_read_string(struct device_node *np,
 	return -ENOSYS;
 }
 
+static inline int of_property_read_string_index(struct device_node *np,
+						const char *propname, index,
+						const char **out_string)
+{
+	return -ENOSYS;
+}
+
+static inline int of_property_count_strings(struct device_node *np,
+					    const char *propname)
+{
+	return -ENOSYS;
+}
+
 static inline const void *of_get_property(const struct device_node *node,
 				const char *name,
 				int *lenp)
-- 
1.7.0.4



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

* [PATCH v3 2/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
@ 2011-09-27 16:04       ` Cousson, Benoit
  0 siblings, 0 replies; 20+ messages in thread
From: Cousson, Benoit @ 2011-09-27 16:04 UTC (permalink / raw)
  To: linux-arm-kernel

On 9/27/2011 3:46 AM, Grant Likely wrote:
> On Thu, Sep 22, 2011 at 10:52:25PM +0200, Benoit Cousson wrote:

[...]

>> +Required properties:
>> +- compatible: Every devices present in OMAP SoC should be in the
>> +  form: "ti,XXX"
>> +- ti,hwmods: list of hwmods attached to a device. Must contain at least
>> +  one hwmod.
> 
> Nit: This should specify that ti,hwmods is a list of hwmod names
> (ascii strings), and that the hwmod names come from the OMAP
> documentation.  Don't respin the patch over this though, just do a
> follow-up patch.

OK, but since you asked later to remove the DT helpers, I will have to resend it anyway:-)

[...]

>> +/*
>> + * XXX: DT helper functions that should be replaced by more generic
>> + * API introduced by Stephen Warren once they'll be in mainline.
>> + */
>> +static int _dt_count_property_string(const char *prop, int len)
>> +{
>> +	int i = 0;
>> +	size_t l = 0, total = 0;
>> +
>> +	if (!prop || !len)
>> +		return -EINVAL;
>> +
>> +	for (i = 0; len>= total; total += l, prop += l) {
>> +		l = strlen(prop) + 1;
>> +		if (*prop != 0)
>> +			i++;
>> +	}
>> +	return i;
>> +}
>> +
>> +static int _dt_get_property(const char *prop, int len, int index, char *output,
>> +			    int size)
>> +{
>> +	int i = 0;
>> +	size_t l = 0, total = 0;
>> +
>> +	if (!prop || !len)
>> +		return -EINVAL;
>> +
>> +	for (i = 0; len>= total; total += l, prop += l) {
>> +		l = strlcpy(output, prop, size) + 1;
>> +		if (*prop != 0) {
>> +			if (i++ == index)
>> +				return 0;
>> +		}
>> +	}
>> +	return -ENODEV;
>> +}
> 
> Don't merge this.  Kevin or I could put Stephen's patch into a separate
> branch that both Kevin and I pull.  There's no need to merge temporary
> code.
> 
> That said, I just looked at Stephen's iterator, and even without it
> this particular hunk shouldn't be merged here.  A
> of_property_count_strings() function is useful in and of itself, and
> of_property_read_string() could be extended with an
> of_property_read_string_index() version.  Both changes should be in
> the common drivers/of code, and you can easily do them.

I'm fine with that, but in that case, and in order to be consistent with the existing of_property_read_string, I should include the find_property in these functions. Whereas in my case, it was supposed to be done before.

Please find below a first version of this patch.

Regards,
Benoit

---

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

* Re: [PATCH v3 2/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
  2011-09-27 16:04       ` Cousson, Benoit
@ 2011-09-28 16:11         ` Cousson, Benoit
  -1 siblings, 0 replies; 20+ messages in thread
From: Cousson, Benoit @ 2011-09-28 16:11 UTC (permalink / raw)
  To: Grant Likely, Hilman, Kevin; +Cc: linux-omap, linux-arm-kernel

Hi Grant, Kevin,

Should I go ahead with this version and repost the series with that 
third patch?

Thanks,
Benoit


On 9/27/2011 6:04 PM, Cousson, Benoit wrote:

[...]

> From 4403f8a00090e5ea1814a5242947b81c348947a1 Mon Sep 17 00:00:00 2001
> From: Benoit Cousson<b-cousson@ti.com>
> Date: Tue, 27 Sep 2011 17:45:43 +0200
> Subject: [PATCH] of: Add helpers to get one string in multiple strings property
>
> Add of_property_read_string_index and of_property_count_strings
> to retrieve one string inside a property that will contains
> severals strings.
>
> Signed-off-by: Benoit Cousson<b-cousson@ti.com>
> ---
>   drivers/of/base.c  |   85 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>   include/linux/of.h |   18 +++++++++++
>   2 files changed, 103 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index 3ff22e3..d97d53e 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -662,6 +662,91 @@ int of_property_read_string(struct device_node *np, const char *propname,
>   EXPORT_SYMBOL_GPL(of_property_read_string);
>
>   /**
> + * of_property_read_string_index - Find and read a string from a multiple
> + * strings property.
> + * @np:		device node from which the property value is to be read.
> + * @propname:	name of the property to be searched.
> + * @index:	index of the string in the list of strings
> + * @out_string:	pointer to null terminated return string, modified only if
> + *		return value is 0.
> + *
> + * Search for a property in a device tree node and retrieve a null
> + * terminated string value (pointer to data, not a copy) in the list of strings
> + * contained in that property.
> + * Returns 0 on
> + * success, -EINVAL if the property does not exist, -ENODATA if property
> + * does not have a value, and -EILSEQ if the string is not null-terminated
> + * within the length of the property data.
> + *
> + * The out_string pointer is modified only if a valid string can be decoded.
> + */
> +int of_property_read_string_index(struct device_node *np, const char *propname,
> +				  int index, const char **output)
> +{
> +	struct property *prop = of_find_property(np, propname, NULL);
> +	int i = 0;
> +	size_t l = 0, total = 0;
> +	const char *p;
> +
> +	if (!prop)
> +		return -EINVAL;
> +	if (!prop->value)
> +		return -ENODATA;
> +	if (strnlen(prop->value, prop->length)>= prop->length)
> +		return -EILSEQ;
> +
> +	p = prop->value;
> +
> +	for (i = 0; total<  prop->length; total += l, p += l) {
> +		l = strlen(p) + 1;
> +		if ((*p != 0)&&  (i++ == index)) {
> +			*output = p;
> +			return 0;
> +		}
> +	}
> +	return -ENODATA;
> +}
> +EXPORT_SYMBOL_GPL(of_property_read_string_index);
> +
> +
> +/**
> + * of_property_count_strings - Find and return the number of strings from a
> + * multiple strings property.
> + * @np:		device node from which the property value is to be read.
> + * @propname:	name of the property to be searched.
> + *
> + * Search for a property in a device tree node and retrieve the number of null
> + * terminated string contain in it. Returns the number of strings on
> + * success, -EINVAL if the property does not exist, -ENODATA if property
> + * does not have a value, and -EILSEQ if the string is not null-terminated
> + * within the length of the property data.
> + */
> +int of_property_count_strings(struct device_node *np, const char *propname)
> +{
> +	struct property *prop = of_find_property(np, propname, NULL);
> +	int i = 0;
> +	size_t l = 0, total = 0;
> +	const char *p;
> +
> +	if (!prop)
> +		return -EINVAL;
> +	if (!prop->value)
> +		return -ENODATA;
> +	if (strnlen(prop->value, prop->length)>= prop->length)
> +		return -EILSEQ;
> +
> +	p = prop->value;
> +
> +	for (i = 0; total<  prop->length; total += l, p += l) {
> +		l = strlen(p) + 1;
> +		if (*p != 0)
> +			i++;
> +	}
> +	return i;
> +}
> +EXPORT_SYMBOL_GPL(of_property_count_strings);
> +
> +/**
>    * of_parse_phandle - Resolve a phandle property to a device_node pointer
>    * @np: Pointer to device node holding phandle property
>    * @phandle_name: Name of property holding a phandle value
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 9180dc5..9eadc4e 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -203,6 +203,11 @@ extern int of_property_read_u32_array(const struct device_node *np,
>   extern int of_property_read_string(struct device_node *np,
>   				   const char *propname,
>   				   const char **out_string);
> +extern int of_property_read_string_index(struct device_node *np,
> +					 const char *propname,
> +					 int index, const char **output);
> +extern int of_property_count_strings(struct device_node *np,
> +				     const char *propname);
>   extern int of_device_is_compatible(const struct device_node *device,
>   				   const char *);
>   extern int of_device_is_available(const struct device_node *device);
> @@ -256,6 +261,19 @@ static inline int of_property_read_string(struct device_node *np,
>   	return -ENOSYS;
>   }
>
> +static inline int of_property_read_string_index(struct device_node *np,
> +						const char *propname, index,
> +						const char **out_string)
> +{
> +	return -ENOSYS;
> +}
> +
> +static inline int of_property_count_strings(struct device_node *np,
> +					    const char *propname)
> +{
> +	return -ENOSYS;
> +}
> +
>   static inline const void *of_get_property(const struct device_node *node,
>   				const char *name,
>   				int *lenp)


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

* [PATCH v3 2/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
@ 2011-09-28 16:11         ` Cousson, Benoit
  0 siblings, 0 replies; 20+ messages in thread
From: Cousson, Benoit @ 2011-09-28 16:11 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Grant, Kevin,

Should I go ahead with this version and repost the series with that 
third patch?

Thanks,
Benoit


On 9/27/2011 6:04 PM, Cousson, Benoit wrote:

[...]

> From 4403f8a00090e5ea1814a5242947b81c348947a1 Mon Sep 17 00:00:00 2001
> From: Benoit Cousson<b-cousson@ti.com>
> Date: Tue, 27 Sep 2011 17:45:43 +0200
> Subject: [PATCH] of: Add helpers to get one string in multiple strings property
>
> Add of_property_read_string_index and of_property_count_strings
> to retrieve one string inside a property that will contains
> severals strings.
>
> Signed-off-by: Benoit Cousson<b-cousson@ti.com>
> ---
>   drivers/of/base.c  |   85 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>   include/linux/of.h |   18 +++++++++++
>   2 files changed, 103 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index 3ff22e3..d97d53e 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -662,6 +662,91 @@ int of_property_read_string(struct device_node *np, const char *propname,
>   EXPORT_SYMBOL_GPL(of_property_read_string);
>
>   /**
> + * of_property_read_string_index - Find and read a string from a multiple
> + * strings property.
> + * @np:		device node from which the property value is to be read.
> + * @propname:	name of the property to be searched.
> + * @index:	index of the string in the list of strings
> + * @out_string:	pointer to null terminated return string, modified only if
> + *		return value is 0.
> + *
> + * Search for a property in a device tree node and retrieve a null
> + * terminated string value (pointer to data, not a copy) in the list of strings
> + * contained in that property.
> + * Returns 0 on
> + * success, -EINVAL if the property does not exist, -ENODATA if property
> + * does not have a value, and -EILSEQ if the string is not null-terminated
> + * within the length of the property data.
> + *
> + * The out_string pointer is modified only if a valid string can be decoded.
> + */
> +int of_property_read_string_index(struct device_node *np, const char *propname,
> +				  int index, const char **output)
> +{
> +	struct property *prop = of_find_property(np, propname, NULL);
> +	int i = 0;
> +	size_t l = 0, total = 0;
> +	const char *p;
> +
> +	if (!prop)
> +		return -EINVAL;
> +	if (!prop->value)
> +		return -ENODATA;
> +	if (strnlen(prop->value, prop->length)>= prop->length)
> +		return -EILSEQ;
> +
> +	p = prop->value;
> +
> +	for (i = 0; total<  prop->length; total += l, p += l) {
> +		l = strlen(p) + 1;
> +		if ((*p != 0)&&  (i++ == index)) {
> +			*output = p;
> +			return 0;
> +		}
> +	}
> +	return -ENODATA;
> +}
> +EXPORT_SYMBOL_GPL(of_property_read_string_index);
> +
> +
> +/**
> + * of_property_count_strings - Find and return the number of strings from a
> + * multiple strings property.
> + * @np:		device node from which the property value is to be read.
> + * @propname:	name of the property to be searched.
> + *
> + * Search for a property in a device tree node and retrieve the number of null
> + * terminated string contain in it. Returns the number of strings on
> + * success, -EINVAL if the property does not exist, -ENODATA if property
> + * does not have a value, and -EILSEQ if the string is not null-terminated
> + * within the length of the property data.
> + */
> +int of_property_count_strings(struct device_node *np, const char *propname)
> +{
> +	struct property *prop = of_find_property(np, propname, NULL);
> +	int i = 0;
> +	size_t l = 0, total = 0;
> +	const char *p;
> +
> +	if (!prop)
> +		return -EINVAL;
> +	if (!prop->value)
> +		return -ENODATA;
> +	if (strnlen(prop->value, prop->length)>= prop->length)
> +		return -EILSEQ;
> +
> +	p = prop->value;
> +
> +	for (i = 0; total<  prop->length; total += l, p += l) {
> +		l = strlen(p) + 1;
> +		if (*p != 0)
> +			i++;
> +	}
> +	return i;
> +}
> +EXPORT_SYMBOL_GPL(of_property_count_strings);
> +
> +/**
>    * of_parse_phandle - Resolve a phandle property to a device_node pointer
>    * @np: Pointer to device node holding phandle property
>    * @phandle_name: Name of property holding a phandle value
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 9180dc5..9eadc4e 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -203,6 +203,11 @@ extern int of_property_read_u32_array(const struct device_node *np,
>   extern int of_property_read_string(struct device_node *np,
>   				   const char *propname,
>   				   const char **out_string);
> +extern int of_property_read_string_index(struct device_node *np,
> +					 const char *propname,
> +					 int index, const char **output);
> +extern int of_property_count_strings(struct device_node *np,
> +				     const char *propname);
>   extern int of_device_is_compatible(const struct device_node *device,
>   				   const char *);
>   extern int of_device_is_available(const struct device_node *device);
> @@ -256,6 +261,19 @@ static inline int of_property_read_string(struct device_node *np,
>   	return -ENOSYS;
>   }
>
> +static inline int of_property_read_string_index(struct device_node *np,
> +						const char *propname, index,
> +						const char **out_string)
> +{
> +	return -ENOSYS;
> +}
> +
> +static inline int of_property_count_strings(struct device_node *np,
> +					    const char *propname)
> +{
> +	return -ENOSYS;
> +}
> +
>   static inline const void *of_get_property(const struct device_node *node,
>   				const char *name,
>   				int *lenp)

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

* Re: [PATCH v3 2/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
  2011-09-28 16:11         ` Cousson, Benoit
@ 2011-09-28 17:47           ` Kevin Hilman
  -1 siblings, 0 replies; 20+ messages in thread
From: Kevin Hilman @ 2011-09-28 17:47 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Grant Likely, linux-omap, linux-arm-kernel

"Cousson, Benoit" <b-cousson@ti.com> writes:

> Hi Grant, Kevin,
>
> Should I go ahead with this version and repost the series with that
> third patch?

Fine with me.

Grant let me know if you prefer if I merge it (with your ack) with the
rest of the series or if you want to take it to avoid conflicts.

Kevin

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

* [PATCH v3 2/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
@ 2011-09-28 17:47           ` Kevin Hilman
  0 siblings, 0 replies; 20+ messages in thread
From: Kevin Hilman @ 2011-09-28 17:47 UTC (permalink / raw)
  To: linux-arm-kernel

"Cousson, Benoit" <b-cousson@ti.com> writes:

> Hi Grant, Kevin,
>
> Should I go ahead with this version and repost the series with that
> third patch?

Fine with me.

Grant let me know if you prefer if I merge it (with your ack) with the
rest of the series or if you want to take it to avoid conflicts.

Kevin

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

* Re: [PATCH v3 2/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
  2011-09-28 17:47           ` Kevin Hilman
@ 2011-09-29 17:30             ` Grant Likely
  -1 siblings, 0 replies; 20+ messages in thread
From: Grant Likely @ 2011-09-29 17:30 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: Cousson, Benoit, linux-omap, linux-arm-kernel

On Wed, Sep 28, 2011 at 10:47:32AM -0700, Kevin Hilman wrote:
> "Cousson, Benoit" <b-cousson@ti.com> writes:
> 
> > Hi Grant, Kevin,
> >
> > Should I go ahead with this version and repost the series with that
> > third patch?
> 
> Fine with me.
> 
> Grant let me know if you prefer if I merge it (with your ack) with the
> rest of the series or if you want to take it to avoid conflicts.

I'm happy with the way things have gone.  Go ahead and add my Ack and
merge it through your tree.  I'd like to avoid the conflicts.

g.


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

* [PATCH v3 2/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
@ 2011-09-29 17:30             ` Grant Likely
  0 siblings, 0 replies; 20+ messages in thread
From: Grant Likely @ 2011-09-29 17:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Sep 28, 2011 at 10:47:32AM -0700, Kevin Hilman wrote:
> "Cousson, Benoit" <b-cousson@ti.com> writes:
> 
> > Hi Grant, Kevin,
> >
> > Should I go ahead with this version and repost the series with that
> > third patch?
> 
> Fine with me.
> 
> Grant let me know if you prefer if I merge it (with your ack) with the
> rest of the series or if you want to take it to avoid conflicts.

I'm happy with the way things have gone.  Go ahead and add my Ack and
merge it through your tree.  I'd like to avoid the conflicts.

g.

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

* Re: [PATCH v3 2/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
  2011-09-29 17:30             ` Grant Likely
@ 2011-09-29 20:46               ` Kevin Hilman
  -1 siblings, 0 replies; 20+ messages in thread
From: Kevin Hilman @ 2011-09-29 20:46 UTC (permalink / raw)
  To: Grant Likely; +Cc: Cousson, Benoit, linux-omap, linux-arm-kernel

Grant Likely <grant.likely@secretlab.ca> writes:

> On Wed, Sep 28, 2011 at 10:47:32AM -0700, Kevin Hilman wrote:
>> "Cousson, Benoit" <b-cousson@ti.com> writes:
>> 
>> > Hi Grant, Kevin,
>> >
>> > Should I go ahead with this version and repost the series with that
>> > third patch?
>> 
>> Fine with me.
>> 
>> Grant let me know if you prefer if I merge it (with your ack) with the
>> rest of the series or if you want to take it to avoid conflicts.
>
> I'm happy with the way things have gone.  Go ahead and add my Ack and
> merge it through your tree.  I'd like to avoid the conflicts.

Thanks, I think keeping this series together will be smoothest.

Adding your ack, and queuing for v3.2 (branch: for_3.2/omap_device-2)

Kevin


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

* [PATCH v3 2/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
@ 2011-09-29 20:46               ` Kevin Hilman
  0 siblings, 0 replies; 20+ messages in thread
From: Kevin Hilman @ 2011-09-29 20:46 UTC (permalink / raw)
  To: linux-arm-kernel

Grant Likely <grant.likely@secretlab.ca> writes:

> On Wed, Sep 28, 2011 at 10:47:32AM -0700, Kevin Hilman wrote:
>> "Cousson, Benoit" <b-cousson@ti.com> writes:
>> 
>> > Hi Grant, Kevin,
>> >
>> > Should I go ahead with this version and repost the series with that
>> > third patch?
>> 
>> Fine with me.
>> 
>> Grant let me know if you prefer if I merge it (with your ack) with the
>> rest of the series or if you want to take it to avoid conflicts.
>
> I'm happy with the way things have gone.  Go ahead and add my Ack and
> merge it through your tree.  I'd like to avoid the conflicts.

Thanks, I think keeping this series together will be smoothest.

Adding your ack, and queuing for v3.2 (branch: for_3.2/omap_device-2)

Kevin

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

end of thread, other threads:[~2011-09-29 20:46 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-22 20:52 [PATCH v3 0/2] OMAP: omap_device: Add a method to build an omap_device from a DT node Benoit Cousson
2011-09-22 20:52 ` Benoit Cousson
2011-09-22 20:52 ` [PATCH v3 1/2] OMAP: omap_device: Add omap_device_[alloc|delete] for DT integration Benoit Cousson
2011-09-22 20:52   ` Benoit Cousson
2011-09-22 20:52 ` [PATCH v3 2/2] OMAP: omap_device: Add a method to build an omap_device from a DT node Benoit Cousson
2011-09-22 20:52   ` Benoit Cousson
2011-09-27  1:46   ` Grant Likely
2011-09-27  1:46     ` Grant Likely
2011-09-27 16:04     ` Cousson, Benoit
2011-09-27 16:04       ` Cousson, Benoit
2011-09-28 16:11       ` Cousson, Benoit
2011-09-28 16:11         ` Cousson, Benoit
2011-09-28 17:47         ` Kevin Hilman
2011-09-28 17:47           ` Kevin Hilman
2011-09-29 17:30           ` Grant Likely
2011-09-29 17:30             ` Grant Likely
2011-09-29 20:46             ` Kevin Hilman
2011-09-29 20:46               ` Kevin Hilman
2011-09-26 22:38 ` [PATCH v3 0/2] " Kevin Hilman
2011-09-26 22:38   ` Kevin Hilman

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.