All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/5] Add basic device support for imx51 babbage
@ 2011-06-24 18:04 ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-24 18:04 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, netdev, linux-serial, devicetree-discuss, patches

This patch set adds the basic device tree support for imx51 babbage
board.  With uart and fec dt support added, the dt kernel can boot
into console with nfs root on babbage, so that we get a good base
to start playing dt and converting further drivers to use dt on
imx51.

It creates the platform imx51-dt for using the device tree, and
leaves existing board support files alone, so nothing should be
broken.  The plan is to add stuff step by step into imx51-dt to
get it support every existing imx51 boards, and then remove the
existing board files.

It works against Linus tree plus the dt infrastructure patches
recently posted by Grant Likely.

Changes since v1:
 * Add functions dealing with aliases node
 * Add one patch to remove the use of cpu_is_mx1 in serial driver
 * Address comments on v1 given by Grant and Arnd

Shawn Guo (5):
      dt: add of_alias_scan and of_alias_get_id
      serial/imx: get rid of the use of cpu_is_mx1()
      serial/imx: add device tree support
      net/fec: add device tree support
      ARM: mx5: add basic device tree support for imx51 babbage

Documentation/devicetree/bindings/net/fsl-fec.txt  |   22 +++
 .../bindings/tty/serial/fsl-imx-uart.txt           |   20 +++
 arch/arm/boot/dts/imx51-babbage.dts                |   93 ++++++++++
 arch/arm/mach-imx/clock-imx1.c                     |    6 +-
 arch/arm/mach-mx5/Kconfig                          |    8 +
 arch/arm/mach-mx5/Makefile                         |    1 +
 arch/arm/mach-mx5/imx51-dt.c                       |   70 ++++++++
 arch/arm/plat-mxc/devices/platform-imx-uart.c      |    2 +-
 drivers/net/fec.c                                  |   81 ++++++++-
 drivers/of/base.c                                  |  181 ++++++++++++++++++++
 drivers/of/fdt.c                                   |    6 +
 drivers/tty/serial/imx.c                           |  132 +++++++++++++--
 include/linux/of.h                                 |    7 +
 13 files changed, 606 insertions(+), 23 deletions(-)

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

* [PATCH v2 0/5] Add basic device support for imx51 babbage
@ 2011-06-24 18:04 ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-24 18:04 UTC (permalink / raw)
  To: linux-arm-kernel

This patch set adds the basic device tree support for imx51 babbage
board.  With uart and fec dt support added, the dt kernel can boot
into console with nfs root on babbage, so that we get a good base
to start playing dt and converting further drivers to use dt on
imx51.

It creates the platform imx51-dt for using the device tree, and
leaves existing board support files alone, so nothing should be
broken.  The plan is to add stuff step by step into imx51-dt to
get it support every existing imx51 boards, and then remove the
existing board files.

It works against Linus tree plus the dt infrastructure patches
recently posted by Grant Likely.

Changes since v1:
 * Add functions dealing with aliases node
 * Add one patch to remove the use of cpu_is_mx1 in serial driver
 * Address comments on v1 given by Grant and Arnd

Shawn Guo (5):
      dt: add of_alias_scan and of_alias_get_id
      serial/imx: get rid of the use of cpu_is_mx1()
      serial/imx: add device tree support
      net/fec: add device tree support
      ARM: mx5: add basic device tree support for imx51 babbage

Documentation/devicetree/bindings/net/fsl-fec.txt  |   22 +++
 .../bindings/tty/serial/fsl-imx-uart.txt           |   20 +++
 arch/arm/boot/dts/imx51-babbage.dts                |   93 ++++++++++
 arch/arm/mach-imx/clock-imx1.c                     |    6 +-
 arch/arm/mach-mx5/Kconfig                          |    8 +
 arch/arm/mach-mx5/Makefile                         |    1 +
 arch/arm/mach-mx5/imx51-dt.c                       |   70 ++++++++
 arch/arm/plat-mxc/devices/platform-imx-uart.c      |    2 +-
 drivers/net/fec.c                                  |   81 ++++++++-
 drivers/of/base.c                                  |  181 ++++++++++++++++++++
 drivers/of/fdt.c                                   |    6 +
 drivers/tty/serial/imx.c                           |  132 +++++++++++++--
 include/linux/of.h                                 |    7 +
 13 files changed, 606 insertions(+), 23 deletions(-)

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

* [PATCH v2 1/5] dt: add of_alias_scan and of_alias_get_id
@ 2011-06-24 18:04   ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-24 18:04 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, netdev, linux-serial, devicetree-discuss, patches,
	Shawn Guo, Grant Likely

The patch adds function of_alias_scan to populate a global lookup
table with the properties of 'aliases' node and function
of_alias_get_id for drivers to find alias id from the lookup table.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
---
 drivers/of/base.c  |  181 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/of/fdt.c   |    6 ++
 include/linux/of.h |    7 ++
 3 files changed, 194 insertions(+), 0 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 632ebae..89efd10 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -17,14 +17,38 @@
  *      as published by the Free Software Foundation; either version
  *      2 of the License, or (at your option) any later version.
  */
+#include <linux/bootmem.h>
+#include <linux/ctype.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
 
+/**
+ * struct alias_prop - Alias property in 'aliases' node
+ * @link:	List node to link the structure in aliases_lookup list
+ * @alias:	Alias property name
+ * @np:		Pointer to device_node that the alias stands for
+ * @alias_id:	Alias id decoded from alias
+ * @alias_stem:	Alias stem name decoded from alias
+ *
+ * The structure represents one alias property of 'aliases' node as
+ * an entry in aliases_lookup list.
+ */
+struct alias_prop {
+	struct list_head link;
+	const char *alias;
+	struct device_node *np;
+	int alias_id;
+	char alias_stem[0];
+};
+
+static LIST_HEAD(aliases_lookup);
+
 struct device_node *allnodes;
 struct device_node *of_chosen;
+struct device_node *of_aliases;
 
 /* use when traversing tree through the allnext, child, sibling,
  * or parent members of struct device_node.
@@ -922,3 +946,160 @@ out_unlock:
 }
 #endif /* defined(CONFIG_OF_DYNAMIC) */
 
+/*
+ * of_alias_find_available_id - Find an available id for the given device_node
+ * @np:		Pointer to the given device_node
+ * @stem:	Alias stem of the given device_node
+ *
+ * The function travels the lookup table to find an available id for the
+ * given device_node with given alias stem.  It returns the id found.
+ */
+static int of_alias_find_available_id(struct device_node *np, const char *stem)
+{
+	struct alias_prop *app;
+	int id = 0;
+
+	while (1) {
+		bool used = false;
+		list_for_each_entry(app, &aliases_lookup, link) {
+			if (!strcmp(app->alias_stem, stem) &&
+			    app->alias_id == id) {
+				used = true;
+				break;
+			}
+		}
+
+		if (used)
+			id++;
+		else
+			return id;
+	}
+}
+
+/**
+ * of_alias_lookup_add - Add alias into lookup table
+ * @alias:	Alias name
+ * @id:		Alias id
+ * @stem:	Alias stem name
+ * @np:		Pointer to device_node
+ *
+ * The function adds one alias into the lookup table and populate it
+ * with the info passed in.  It returns 0 in sucess, or error code.
+ */
+static int of_alias_lookup_add(char *alias, int id, const char *stem,
+			       struct device_node *np)
+{
+	struct alias_prop *app;
+	size_t sz = sizeof(*app) + strlen(stem) + 1;
+
+	app = kzalloc(sz, GFP_KERNEL);
+	if (!app) {
+		/*
+		 * It may fail due to being called by boot code,
+		 * so try alloc_bootmem before return error.
+		 */
+		app = alloc_bootmem(sz);
+		if (!app)
+			return -ENOMEM;
+	}
+
+	app->np = np;
+	app->alias = alias;
+	app->alias_id = id;
+	strcpy(app->alias_stem, stem);
+	list_add_tail(&app->link, &aliases_lookup);
+
+	return 0;
+}
+
+/**
+ * of_alias_decode - Decode alias stem and id from alias name
+ * @alias:	Alias name to be decoded
+ * @stem:	Pointer used to return stem name
+ *
+ * The function decodes alias stem name and alias id from the given
+ * alias name.  It returns stem name via parameter 'stem', and stem id
+ * via the return value.  If no id is found in alias name, it returns 0
+ * as the default.
+ */
+static int of_alias_decode(char *alias, char *stem)
+{
+	int len = strlen(alias);
+	char *end = alias + len;
+
+	while (isdigit(*--end))
+		len--;
+
+	strncpy(stem, alias, len);
+	stem[len] = '\0';
+
+	return strlen(++end) ? simple_strtoul(end, NULL, 10) : 0;
+}
+
+/**
+ * of_alias_scan - Scan all properties of 'aliases' node
+ *
+ * The function scans all the properties of 'aliases' node and populate
+ * the the global lookup table with the properties.  It returns the
+ * number of alias_prop found, or error code in error case.
+ */
+int of_alias_scan(void)
+{
+	struct property *pp;
+	int ret, num = 0;
+
+	if (!of_aliases)
+		return -ENODEV;
+
+	for_each_property(pp, of_aliases->properties) {
+		char stem[32];
+		int id = of_alias_decode(pp->name, stem);
+
+		/* Skip those we do not want to proceed */
+		if (!strcmp(pp->name, "name") ||
+		    !strcmp(pp->name, "phandle") ||
+		    !strcmp(pp->name, "linux,phandle"))
+			continue;
+
+		ret = of_alias_lookup_add(pp->name, id, stem,
+					  of_find_node_by_path(pp->value));
+		if (ret < 0)
+			return ret;
+		else
+			num++;
+	}
+
+	return num;
+}
+
+/**
+ * of_alias_get_id - Get alias id for the given device_node
+ * @np:		Pointer to the given device_node
+ * @stem:	Alias stem of the given device_node
+ *
+ * The function travels the lookup table to get alias id for the given
+ * device_node and alias stem.  It returns the alias id if find it.
+ * If not, dynamically creates one in the lookup table and returns it,
+ * or returns error code if fail to create.
+ */
+int of_alias_get_id(struct device_node *np, const char *stem)
+{
+	struct alias_prop *app;
+	int id = -1;
+
+	list_for_each_entry(app, &aliases_lookup, link) {
+		if (np == app->np) {
+			id = app->alias_id;
+			break;
+		}
+	}
+
+	if (id == -1) {
+		id = of_alias_find_available_id(np, stem);
+		if (of_alias_lookup_add(NULL, id, stem, np) < 0)
+			return -ENODEV;
+	}
+
+	return id;
+}
+EXPORT_SYMBOL_GPL(of_alias_get_id);
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 65200af..998dc63 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -711,6 +711,12 @@ void __init unflatten_device_tree(void)
 	of_chosen = of_find_node_by_path("/chosen");
 	if (of_chosen == NULL)
 		of_chosen = of_find_node_by_path("/chosen@0");
+
+	of_aliases = of_find_node_by_path("/aliases");
+	if (of_aliases == NULL)
+		of_aliases = of_find_node_by_path("/aliases@0");
+
+	of_alias_scan();
 }
 
 #endif /* CONFIG_OF_EARLY_FLATTREE */
diff --git a/include/linux/of.h b/include/linux/of.h
index bfc0ed1..c35cc47 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -68,6 +68,7 @@ struct device_node {
 /* Pointer for first entry in chain of all nodes. */
 extern struct device_node *allnodes;
 extern struct device_node *of_chosen;
+extern struct device_node *of_aliases;
 extern rwlock_t devtree_lock;
 
 static inline bool of_have_populated_dt(void)
@@ -201,6 +202,9 @@ extern int of_device_is_available(const struct device_node *device);
 extern const void *of_get_property(const struct device_node *node,
 				const char *name,
 				int *lenp);
+#define for_each_property(pp, properties) \
+	for (pp = properties; pp != NULL; pp = pp->next)
+
 extern int of_n_addr_cells(struct device_node *np);
 extern int of_n_size_cells(struct device_node *np);
 extern const struct of_device_id *of_match_node(
@@ -213,6 +217,9 @@ extern int of_parse_phandles_with_args(struct device_node *np,
 	const char *list_name, const char *cells_name, int index,
 	struct device_node **out_node, const void **out_args);
 
+extern int of_alias_scan(void);
+extern int of_alias_get_id(struct device_node *np, const char *stem);
+
 extern int of_machine_is_compatible(const char *compat);
 
 extern int prom_add_property(struct device_node* np, struct property* prop);
-- 
1.7.4.1


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

* [PATCH v2 1/5] dt: add of_alias_scan and of_alias_get_id
@ 2011-06-24 18:04   ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-24 18:04 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: patches-QSEj5FYQhm4dnm+yROfE0A, netdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA

The patch adds function of_alias_scan to populate a global lookup
table with the properties of 'aliases' node and function
of_alias_get_id for drivers to find alias id from the lookup table.

Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
---
 drivers/of/base.c  |  181 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/of/fdt.c   |    6 ++
 include/linux/of.h |    7 ++
 3 files changed, 194 insertions(+), 0 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 632ebae..89efd10 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -17,14 +17,38 @@
  *      as published by the Free Software Foundation; either version
  *      2 of the License, or (at your option) any later version.
  */
+#include <linux/bootmem.h>
+#include <linux/ctype.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
 
+/**
+ * struct alias_prop - Alias property in 'aliases' node
+ * @link:	List node to link the structure in aliases_lookup list
+ * @alias:	Alias property name
+ * @np:		Pointer to device_node that the alias stands for
+ * @alias_id:	Alias id decoded from alias
+ * @alias_stem:	Alias stem name decoded from alias
+ *
+ * The structure represents one alias property of 'aliases' node as
+ * an entry in aliases_lookup list.
+ */
+struct alias_prop {
+	struct list_head link;
+	const char *alias;
+	struct device_node *np;
+	int alias_id;
+	char alias_stem[0];
+};
+
+static LIST_HEAD(aliases_lookup);
+
 struct device_node *allnodes;
 struct device_node *of_chosen;
+struct device_node *of_aliases;
 
 /* use when traversing tree through the allnext, child, sibling,
  * or parent members of struct device_node.
@@ -922,3 +946,160 @@ out_unlock:
 }
 #endif /* defined(CONFIG_OF_DYNAMIC) */
 
+/*
+ * of_alias_find_available_id - Find an available id for the given device_node
+ * @np:		Pointer to the given device_node
+ * @stem:	Alias stem of the given device_node
+ *
+ * The function travels the lookup table to find an available id for the
+ * given device_node with given alias stem.  It returns the id found.
+ */
+static int of_alias_find_available_id(struct device_node *np, const char *stem)
+{
+	struct alias_prop *app;
+	int id = 0;
+
+	while (1) {
+		bool used = false;
+		list_for_each_entry(app, &aliases_lookup, link) {
+			if (!strcmp(app->alias_stem, stem) &&
+			    app->alias_id == id) {
+				used = true;
+				break;
+			}
+		}
+
+		if (used)
+			id++;
+		else
+			return id;
+	}
+}
+
+/**
+ * of_alias_lookup_add - Add alias into lookup table
+ * @alias:	Alias name
+ * @id:		Alias id
+ * @stem:	Alias stem name
+ * @np:		Pointer to device_node
+ *
+ * The function adds one alias into the lookup table and populate it
+ * with the info passed in.  It returns 0 in sucess, or error code.
+ */
+static int of_alias_lookup_add(char *alias, int id, const char *stem,
+			       struct device_node *np)
+{
+	struct alias_prop *app;
+	size_t sz = sizeof(*app) + strlen(stem) + 1;
+
+	app = kzalloc(sz, GFP_KERNEL);
+	if (!app) {
+		/*
+		 * It may fail due to being called by boot code,
+		 * so try alloc_bootmem before return error.
+		 */
+		app = alloc_bootmem(sz);
+		if (!app)
+			return -ENOMEM;
+	}
+
+	app->np = np;
+	app->alias = alias;
+	app->alias_id = id;
+	strcpy(app->alias_stem, stem);
+	list_add_tail(&app->link, &aliases_lookup);
+
+	return 0;
+}
+
+/**
+ * of_alias_decode - Decode alias stem and id from alias name
+ * @alias:	Alias name to be decoded
+ * @stem:	Pointer used to return stem name
+ *
+ * The function decodes alias stem name and alias id from the given
+ * alias name.  It returns stem name via parameter 'stem', and stem id
+ * via the return value.  If no id is found in alias name, it returns 0
+ * as the default.
+ */
+static int of_alias_decode(char *alias, char *stem)
+{
+	int len = strlen(alias);
+	char *end = alias + len;
+
+	while (isdigit(*--end))
+		len--;
+
+	strncpy(stem, alias, len);
+	stem[len] = '\0';
+
+	return strlen(++end) ? simple_strtoul(end, NULL, 10) : 0;
+}
+
+/**
+ * of_alias_scan - Scan all properties of 'aliases' node
+ *
+ * The function scans all the properties of 'aliases' node and populate
+ * the the global lookup table with the properties.  It returns the
+ * number of alias_prop found, or error code in error case.
+ */
+int of_alias_scan(void)
+{
+	struct property *pp;
+	int ret, num = 0;
+
+	if (!of_aliases)
+		return -ENODEV;
+
+	for_each_property(pp, of_aliases->properties) {
+		char stem[32];
+		int id = of_alias_decode(pp->name, stem);
+
+		/* Skip those we do not want to proceed */
+		if (!strcmp(pp->name, "name") ||
+		    !strcmp(pp->name, "phandle") ||
+		    !strcmp(pp->name, "linux,phandle"))
+			continue;
+
+		ret = of_alias_lookup_add(pp->name, id, stem,
+					  of_find_node_by_path(pp->value));
+		if (ret < 0)
+			return ret;
+		else
+			num++;
+	}
+
+	return num;
+}
+
+/**
+ * of_alias_get_id - Get alias id for the given device_node
+ * @np:		Pointer to the given device_node
+ * @stem:	Alias stem of the given device_node
+ *
+ * The function travels the lookup table to get alias id for the given
+ * device_node and alias stem.  It returns the alias id if find it.
+ * If not, dynamically creates one in the lookup table and returns it,
+ * or returns error code if fail to create.
+ */
+int of_alias_get_id(struct device_node *np, const char *stem)
+{
+	struct alias_prop *app;
+	int id = -1;
+
+	list_for_each_entry(app, &aliases_lookup, link) {
+		if (np == app->np) {
+			id = app->alias_id;
+			break;
+		}
+	}
+
+	if (id == -1) {
+		id = of_alias_find_available_id(np, stem);
+		if (of_alias_lookup_add(NULL, id, stem, np) < 0)
+			return -ENODEV;
+	}
+
+	return id;
+}
+EXPORT_SYMBOL_GPL(of_alias_get_id);
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 65200af..998dc63 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -711,6 +711,12 @@ void __init unflatten_device_tree(void)
 	of_chosen = of_find_node_by_path("/chosen");
 	if (of_chosen == NULL)
 		of_chosen = of_find_node_by_path("/chosen@0");
+
+	of_aliases = of_find_node_by_path("/aliases");
+	if (of_aliases == NULL)
+		of_aliases = of_find_node_by_path("/aliases@0");
+
+	of_alias_scan();
 }
 
 #endif /* CONFIG_OF_EARLY_FLATTREE */
diff --git a/include/linux/of.h b/include/linux/of.h
index bfc0ed1..c35cc47 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -68,6 +68,7 @@ struct device_node {
 /* Pointer for first entry in chain of all nodes. */
 extern struct device_node *allnodes;
 extern struct device_node *of_chosen;
+extern struct device_node *of_aliases;
 extern rwlock_t devtree_lock;
 
 static inline bool of_have_populated_dt(void)
@@ -201,6 +202,9 @@ extern int of_device_is_available(const struct device_node *device);
 extern const void *of_get_property(const struct device_node *node,
 				const char *name,
 				int *lenp);
+#define for_each_property(pp, properties) \
+	for (pp = properties; pp != NULL; pp = pp->next)
+
 extern int of_n_addr_cells(struct device_node *np);
 extern int of_n_size_cells(struct device_node *np);
 extern const struct of_device_id *of_match_node(
@@ -213,6 +217,9 @@ extern int of_parse_phandles_with_args(struct device_node *np,
 	const char *list_name, const char *cells_name, int index,
 	struct device_node **out_node, const void **out_args);
 
+extern int of_alias_scan(void);
+extern int of_alias_get_id(struct device_node *np, const char *stem);
+
 extern int of_machine_is_compatible(const char *compat);
 
 extern int prom_add_property(struct device_node* np, struct property* prop);
-- 
1.7.4.1

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

* [PATCH v2 1/5] dt: add of_alias_scan and of_alias_get_id
@ 2011-06-24 18:04   ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-24 18:04 UTC (permalink / raw)
  To: linux-arm-kernel

The patch adds function of_alias_scan to populate a global lookup
table with the properties of 'aliases' node and function
of_alias_get_id for drivers to find alias id from the lookup table.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
---
 drivers/of/base.c  |  181 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/of/fdt.c   |    6 ++
 include/linux/of.h |    7 ++
 3 files changed, 194 insertions(+), 0 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 632ebae..89efd10 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -17,14 +17,38 @@
  *      as published by the Free Software Foundation; either version
  *      2 of the License, or (at your option) any later version.
  */
+#include <linux/bootmem.h>
+#include <linux/ctype.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
 
+/**
+ * struct alias_prop - Alias property in 'aliases' node
+ * @link:	List node to link the structure in aliases_lookup list
+ * @alias:	Alias property name
+ * @np:		Pointer to device_node that the alias stands for
+ * @alias_id:	Alias id decoded from alias
+ * @alias_stem:	Alias stem name decoded from alias
+ *
+ * The structure represents one alias property of 'aliases' node as
+ * an entry in aliases_lookup list.
+ */
+struct alias_prop {
+	struct list_head link;
+	const char *alias;
+	struct device_node *np;
+	int alias_id;
+	char alias_stem[0];
+};
+
+static LIST_HEAD(aliases_lookup);
+
 struct device_node *allnodes;
 struct device_node *of_chosen;
+struct device_node *of_aliases;
 
 /* use when traversing tree through the allnext, child, sibling,
  * or parent members of struct device_node.
@@ -922,3 +946,160 @@ out_unlock:
 }
 #endif /* defined(CONFIG_OF_DYNAMIC) */
 
+/*
+ * of_alias_find_available_id - Find an available id for the given device_node
+ * @np:		Pointer to the given device_node
+ * @stem:	Alias stem of the given device_node
+ *
+ * The function travels the lookup table to find an available id for the
+ * given device_node with given alias stem.  It returns the id found.
+ */
+static int of_alias_find_available_id(struct device_node *np, const char *stem)
+{
+	struct alias_prop *app;
+	int id = 0;
+
+	while (1) {
+		bool used = false;
+		list_for_each_entry(app, &aliases_lookup, link) {
+			if (!strcmp(app->alias_stem, stem) &&
+			    app->alias_id == id) {
+				used = true;
+				break;
+			}
+		}
+
+		if (used)
+			id++;
+		else
+			return id;
+	}
+}
+
+/**
+ * of_alias_lookup_add - Add alias into lookup table
+ * @alias:	Alias name
+ * @id:		Alias id
+ * @stem:	Alias stem name
+ * @np:		Pointer to device_node
+ *
+ * The function adds one alias into the lookup table and populate it
+ * with the info passed in.  It returns 0 in sucess, or error code.
+ */
+static int of_alias_lookup_add(char *alias, int id, const char *stem,
+			       struct device_node *np)
+{
+	struct alias_prop *app;
+	size_t sz = sizeof(*app) + strlen(stem) + 1;
+
+	app = kzalloc(sz, GFP_KERNEL);
+	if (!app) {
+		/*
+		 * It may fail due to being called by boot code,
+		 * so try alloc_bootmem before return error.
+		 */
+		app = alloc_bootmem(sz);
+		if (!app)
+			return -ENOMEM;
+	}
+
+	app->np = np;
+	app->alias = alias;
+	app->alias_id = id;
+	strcpy(app->alias_stem, stem);
+	list_add_tail(&app->link, &aliases_lookup);
+
+	return 0;
+}
+
+/**
+ * of_alias_decode - Decode alias stem and id from alias name
+ * @alias:	Alias name to be decoded
+ * @stem:	Pointer used to return stem name
+ *
+ * The function decodes alias stem name and alias id from the given
+ * alias name.  It returns stem name via parameter 'stem', and stem id
+ * via the return value.  If no id is found in alias name, it returns 0
+ * as the default.
+ */
+static int of_alias_decode(char *alias, char *stem)
+{
+	int len = strlen(alias);
+	char *end = alias + len;
+
+	while (isdigit(*--end))
+		len--;
+
+	strncpy(stem, alias, len);
+	stem[len] = '\0';
+
+	return strlen(++end) ? simple_strtoul(end, NULL, 10) : 0;
+}
+
+/**
+ * of_alias_scan - Scan all properties of 'aliases' node
+ *
+ * The function scans all the properties of 'aliases' node and populate
+ * the the global lookup table with the properties.  It returns the
+ * number of alias_prop found, or error code in error case.
+ */
+int of_alias_scan(void)
+{
+	struct property *pp;
+	int ret, num = 0;
+
+	if (!of_aliases)
+		return -ENODEV;
+
+	for_each_property(pp, of_aliases->properties) {
+		char stem[32];
+		int id = of_alias_decode(pp->name, stem);
+
+		/* Skip those we do not want to proceed */
+		if (!strcmp(pp->name, "name") ||
+		    !strcmp(pp->name, "phandle") ||
+		    !strcmp(pp->name, "linux,phandle"))
+			continue;
+
+		ret = of_alias_lookup_add(pp->name, id, stem,
+					  of_find_node_by_path(pp->value));
+		if (ret < 0)
+			return ret;
+		else
+			num++;
+	}
+
+	return num;
+}
+
+/**
+ * of_alias_get_id - Get alias id for the given device_node
+ * @np:		Pointer to the given device_node
+ * @stem:	Alias stem of the given device_node
+ *
+ * The function travels the lookup table to get alias id for the given
+ * device_node and alias stem.  It returns the alias id if find it.
+ * If not, dynamically creates one in the lookup table and returns it,
+ * or returns error code if fail to create.
+ */
+int of_alias_get_id(struct device_node *np, const char *stem)
+{
+	struct alias_prop *app;
+	int id = -1;
+
+	list_for_each_entry(app, &aliases_lookup, link) {
+		if (np == app->np) {
+			id = app->alias_id;
+			break;
+		}
+	}
+
+	if (id == -1) {
+		id = of_alias_find_available_id(np, stem);
+		if (of_alias_lookup_add(NULL, id, stem, np) < 0)
+			return -ENODEV;
+	}
+
+	return id;
+}
+EXPORT_SYMBOL_GPL(of_alias_get_id);
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 65200af..998dc63 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -711,6 +711,12 @@ void __init unflatten_device_tree(void)
 	of_chosen = of_find_node_by_path("/chosen");
 	if (of_chosen == NULL)
 		of_chosen = of_find_node_by_path("/chosen at 0");
+
+	of_aliases = of_find_node_by_path("/aliases");
+	if (of_aliases == NULL)
+		of_aliases = of_find_node_by_path("/aliases@0");
+
+	of_alias_scan();
 }
 
 #endif /* CONFIG_OF_EARLY_FLATTREE */
diff --git a/include/linux/of.h b/include/linux/of.h
index bfc0ed1..c35cc47 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -68,6 +68,7 @@ struct device_node {
 /* Pointer for first entry in chain of all nodes. */
 extern struct device_node *allnodes;
 extern struct device_node *of_chosen;
+extern struct device_node *of_aliases;
 extern rwlock_t devtree_lock;
 
 static inline bool of_have_populated_dt(void)
@@ -201,6 +202,9 @@ extern int of_device_is_available(const struct device_node *device);
 extern const void *of_get_property(const struct device_node *node,
 				const char *name,
 				int *lenp);
+#define for_each_property(pp, properties) \
+	for (pp = properties; pp != NULL; pp = pp->next)
+
 extern int of_n_addr_cells(struct device_node *np);
 extern int of_n_size_cells(struct device_node *np);
 extern const struct of_device_id *of_match_node(
@@ -213,6 +217,9 @@ extern int of_parse_phandles_with_args(struct device_node *np,
 	const char *list_name, const char *cells_name, int index,
 	struct device_node **out_node, const void **out_args);
 
+extern int of_alias_scan(void);
+extern int of_alias_get_id(struct device_node *np, const char *stem);
+
 extern int of_machine_is_compatible(const char *compat);
 
 extern int prom_add_property(struct device_node* np, struct property* prop);
-- 
1.7.4.1

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

* [PATCH v2 2/5] serial/imx: get rid of the use of cpu_is_mx1()
@ 2011-06-24 18:04   ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-24 18:04 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, netdev, linux-serial, devicetree-discuss, patches,
	Shawn Guo, Sascha Hauer, Alan Cox

The patch removes all the uses of cpu_is_mx1().  Instead, it uses
the .id_table of platform_driver to distinguish the uart device type.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
---
 arch/arm/mach-imx/clock-imx1.c                |    6 +-
 arch/arm/plat-mxc/devices/platform-imx-uart.c |    2 +-
 drivers/tty/serial/imx.c                      |   52 ++++++++++++++++++++++--
 3 files changed, 51 insertions(+), 9 deletions(-)

diff --git a/arch/arm/mach-imx/clock-imx1.c b/arch/arm/mach-imx/clock-imx1.c
index dcc4172..4aabeb2 100644
--- a/arch/arm/mach-imx/clock-imx1.c
+++ b/arch/arm/mach-imx/clock-imx1.c
@@ -587,9 +587,9 @@ static struct clk_lookup lookups[] __initdata = {
 	_REGISTER_CLOCK(NULL, "mma", mma_clk)
 	_REGISTER_CLOCK("imx_udc.0", NULL, usbd_clk)
 	_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
-	_REGISTER_CLOCK("imx-uart.0", NULL, uart_clk)
-	_REGISTER_CLOCK("imx-uart.1", NULL, uart_clk)
-	_REGISTER_CLOCK("imx-uart.2", NULL, uart_clk)
+	_REGISTER_CLOCK("imx1-uart.0", NULL, uart_clk)
+	_REGISTER_CLOCK("imx1-uart.1", NULL, uart_clk)
+	_REGISTER_CLOCK("imx1-uart.2", NULL, uart_clk)
 	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
 	_REGISTER_CLOCK("imx1-cspi.0", NULL, spi_clk)
 	_REGISTER_CLOCK("imx1-cspi.1", NULL, spi_clk)
diff --git a/arch/arm/plat-mxc/devices/platform-imx-uart.c b/arch/arm/plat-mxc/devices/platform-imx-uart.c
index 3c854c2..01982a1 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-uart.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-uart.c
@@ -150,7 +150,7 @@ struct platform_device *__init imx_add_imx_uart_3irq(
 		},
 	};
 
-	return imx_add_platform_device("imx-uart", data->id, res,
+	return imx_add_platform_device("imx1-uart", data->id, res,
 			ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
 
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index a544731..8a6f4e1 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -48,7 +48,6 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <mach/hardware.h>
 #include <mach/imx-uart.h>
 
 /* Register definitions */
@@ -67,7 +66,8 @@
 #define UBMR  0xa8 /* BRM Modulator Register */
 #define UBRC  0xac /* Baud Rate Count Register */
 #define MX2_ONEMS 0xb0 /* One Millisecond register */
-#define UTS (cpu_is_mx1() ? 0xd0 : 0xb4) /* UART Test Register */
+#define MX1_UTS 0xd0 /* UART Test Register on mx1 */
+#define MX2_UTS 0xb4 /* UART Test Register on mx2 and later */
 
 /* UART Control Register Bit Fields.*/
 #define  URXD_CHARRDY    (1<<15)
@@ -181,6 +181,17 @@
 
 #define UART_NR 8
 
+enum imx_uart_type {
+	IMX1_UART,
+	IMX2_UART,
+};
+
+/* device type dependent stuff */
+struct imx_uart_data {
+	unsigned uts_reg;
+	unsigned type;
+};
+
 struct imx_port {
 	struct uart_port	port;
 	struct timer_list	timer;
@@ -192,6 +203,7 @@ struct imx_port {
 	unsigned int		irda_inv_tx:1;
 	unsigned short		trcv_delay; /* transceiver delay */
 	struct clk		*clk;
+	struct imx_uart_data	*devdata;
 };
 
 #ifdef CONFIG_IRDA
@@ -200,6 +212,21 @@ struct imx_port {
 #define USE_IRDA(sport)	(0)
 #endif
 
+static struct imx_uart_data imx_uart_devdata[] = {
+	[IMX1_UART] = {
+		.uts_reg = MX1_UTS,
+		.type = IMX1_UART,
+	},
+	[IMX2_UART] = {
+		.uts_reg = MX2_UTS,
+		.type = IMX2_UART,
+	},
+};
+
+#define UTS (sport->devdata->uts_reg)
+#define IS_IMX1_UART(sport) (sport->devdata->type == IMX1_UART)
+#define IS_IMX2_UART(sport) (sport->devdata->type == IMX2_UART)
+
 /*
  * Handle any change of modem status signal since we were last called.
  */
@@ -689,7 +716,7 @@ static int imx_startup(struct uart_port *port)
 		}
 	}
 
-	if (!cpu_is_mx1()) {
+	if (IS_IMX2_UART(sport)) {
 		temp = readl(sport->port.membase + UCR3);
 		temp |= MX2_UCR3_RXDMUXSEL;
 		writel(temp, sport->port.membase + UCR3);
@@ -923,7 +950,7 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 	writel(num, sport->port.membase + UBIR);
 	writel(denom, sport->port.membase + UBMR);
 
-	if (!cpu_is_mx1())
+	if (IS_IMX2_UART(sport))
 		writel(sport->port.uartclk / div / 1000,
 				sport->port.membase + MX2_ONEMS);
 
@@ -1063,7 +1090,7 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
 	ucr1 = old_ucr1 = readl(sport->port.membase + UCR1);
 	old_ucr2 = readl(sport->port.membase + UCR2);
 
-	if (cpu_is_mx1())
+	if (IS_IMX1_UART(sport))
 		ucr1 |= MX1_UCR1_UARTCLKEN;
 	ucr1 |= UCR1_UARTEN;
 	ucr1 &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN);
@@ -1263,6 +1290,7 @@ static int serial_imx_probe(struct platform_device *pdev)
 	init_timer(&sport->timer);
 	sport->timer.function = imx_timeout;
 	sport->timer.data     = (unsigned long)sport;
+	sport->devdata = &imx_uart_devdata[pdev->id_entry->driver_data];
 
 	sport->clk = clk_get(&pdev->dev, "uart");
 	if (IS_ERR(sport->clk)) {
@@ -1335,12 +1363,26 @@ static int serial_imx_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static struct platform_device_id imx_uart_devtype[] = {
+	{
+		.name = "imx1-uart",
+		.driver_data = IMX1_UART,
+	}, {
+		.name = "imx-uart",
+		.driver_data = IMX2_UART,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(platform, imx_uart_devtype);
+
 static struct platform_driver serial_imx_driver = {
 	.probe		= serial_imx_probe,
 	.remove		= serial_imx_remove,
 
 	.suspend	= serial_imx_suspend,
 	.resume		= serial_imx_resume,
+	.id_table	= imx_uart_devtype,
 	.driver		= {
 		.name	= "imx-uart",
 		.owner	= THIS_MODULE,
-- 
1.7.4.1


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

* [PATCH v2 2/5] serial/imx: get rid of the use of cpu_is_mx1()
@ 2011-06-24 18:04   ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-24 18:04 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: patches-QSEj5FYQhm4dnm+yROfE0A, netdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA, Sascha Hauer, Alan Cox

The patch removes all the uses of cpu_is_mx1().  Instead, it uses
the .id_table of platform_driver to distinguish the uart device type.

Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Cc: Alan Cox <alan-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org>
---
 arch/arm/mach-imx/clock-imx1.c                |    6 +-
 arch/arm/plat-mxc/devices/platform-imx-uart.c |    2 +-
 drivers/tty/serial/imx.c                      |   52 ++++++++++++++++++++++--
 3 files changed, 51 insertions(+), 9 deletions(-)

diff --git a/arch/arm/mach-imx/clock-imx1.c b/arch/arm/mach-imx/clock-imx1.c
index dcc4172..4aabeb2 100644
--- a/arch/arm/mach-imx/clock-imx1.c
+++ b/arch/arm/mach-imx/clock-imx1.c
@@ -587,9 +587,9 @@ static struct clk_lookup lookups[] __initdata = {
 	_REGISTER_CLOCK(NULL, "mma", mma_clk)
 	_REGISTER_CLOCK("imx_udc.0", NULL, usbd_clk)
 	_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
-	_REGISTER_CLOCK("imx-uart.0", NULL, uart_clk)
-	_REGISTER_CLOCK("imx-uart.1", NULL, uart_clk)
-	_REGISTER_CLOCK("imx-uart.2", NULL, uart_clk)
+	_REGISTER_CLOCK("imx1-uart.0", NULL, uart_clk)
+	_REGISTER_CLOCK("imx1-uart.1", NULL, uart_clk)
+	_REGISTER_CLOCK("imx1-uart.2", NULL, uart_clk)
 	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
 	_REGISTER_CLOCK("imx1-cspi.0", NULL, spi_clk)
 	_REGISTER_CLOCK("imx1-cspi.1", NULL, spi_clk)
diff --git a/arch/arm/plat-mxc/devices/platform-imx-uart.c b/arch/arm/plat-mxc/devices/platform-imx-uart.c
index 3c854c2..01982a1 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-uart.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-uart.c
@@ -150,7 +150,7 @@ struct platform_device *__init imx_add_imx_uart_3irq(
 		},
 	};
 
-	return imx_add_platform_device("imx-uart", data->id, res,
+	return imx_add_platform_device("imx1-uart", data->id, res,
 			ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
 
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index a544731..8a6f4e1 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -48,7 +48,6 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <mach/hardware.h>
 #include <mach/imx-uart.h>
 
 /* Register definitions */
@@ -67,7 +66,8 @@
 #define UBMR  0xa8 /* BRM Modulator Register */
 #define UBRC  0xac /* Baud Rate Count Register */
 #define MX2_ONEMS 0xb0 /* One Millisecond register */
-#define UTS (cpu_is_mx1() ? 0xd0 : 0xb4) /* UART Test Register */
+#define MX1_UTS 0xd0 /* UART Test Register on mx1 */
+#define MX2_UTS 0xb4 /* UART Test Register on mx2 and later */
 
 /* UART Control Register Bit Fields.*/
 #define  URXD_CHARRDY    (1<<15)
@@ -181,6 +181,17 @@
 
 #define UART_NR 8
 
+enum imx_uart_type {
+	IMX1_UART,
+	IMX2_UART,
+};
+
+/* device type dependent stuff */
+struct imx_uart_data {
+	unsigned uts_reg;
+	unsigned type;
+};
+
 struct imx_port {
 	struct uart_port	port;
 	struct timer_list	timer;
@@ -192,6 +203,7 @@ struct imx_port {
 	unsigned int		irda_inv_tx:1;
 	unsigned short		trcv_delay; /* transceiver delay */
 	struct clk		*clk;
+	struct imx_uart_data	*devdata;
 };
 
 #ifdef CONFIG_IRDA
@@ -200,6 +212,21 @@ struct imx_port {
 #define USE_IRDA(sport)	(0)
 #endif
 
+static struct imx_uart_data imx_uart_devdata[] = {
+	[IMX1_UART] = {
+		.uts_reg = MX1_UTS,
+		.type = IMX1_UART,
+	},
+	[IMX2_UART] = {
+		.uts_reg = MX2_UTS,
+		.type = IMX2_UART,
+	},
+};
+
+#define UTS (sport->devdata->uts_reg)
+#define IS_IMX1_UART(sport) (sport->devdata->type == IMX1_UART)
+#define IS_IMX2_UART(sport) (sport->devdata->type == IMX2_UART)
+
 /*
  * Handle any change of modem status signal since we were last called.
  */
@@ -689,7 +716,7 @@ static int imx_startup(struct uart_port *port)
 		}
 	}
 
-	if (!cpu_is_mx1()) {
+	if (IS_IMX2_UART(sport)) {
 		temp = readl(sport->port.membase + UCR3);
 		temp |= MX2_UCR3_RXDMUXSEL;
 		writel(temp, sport->port.membase + UCR3);
@@ -923,7 +950,7 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 	writel(num, sport->port.membase + UBIR);
 	writel(denom, sport->port.membase + UBMR);
 
-	if (!cpu_is_mx1())
+	if (IS_IMX2_UART(sport))
 		writel(sport->port.uartclk / div / 1000,
 				sport->port.membase + MX2_ONEMS);
 
@@ -1063,7 +1090,7 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
 	ucr1 = old_ucr1 = readl(sport->port.membase + UCR1);
 	old_ucr2 = readl(sport->port.membase + UCR2);
 
-	if (cpu_is_mx1())
+	if (IS_IMX1_UART(sport))
 		ucr1 |= MX1_UCR1_UARTCLKEN;
 	ucr1 |= UCR1_UARTEN;
 	ucr1 &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN);
@@ -1263,6 +1290,7 @@ static int serial_imx_probe(struct platform_device *pdev)
 	init_timer(&sport->timer);
 	sport->timer.function = imx_timeout;
 	sport->timer.data     = (unsigned long)sport;
+	sport->devdata = &imx_uart_devdata[pdev->id_entry->driver_data];
 
 	sport->clk = clk_get(&pdev->dev, "uart");
 	if (IS_ERR(sport->clk)) {
@@ -1335,12 +1363,26 @@ static int serial_imx_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static struct platform_device_id imx_uart_devtype[] = {
+	{
+		.name = "imx1-uart",
+		.driver_data = IMX1_UART,
+	}, {
+		.name = "imx-uart",
+		.driver_data = IMX2_UART,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(platform, imx_uart_devtype);
+
 static struct platform_driver serial_imx_driver = {
 	.probe		= serial_imx_probe,
 	.remove		= serial_imx_remove,
 
 	.suspend	= serial_imx_suspend,
 	.resume		= serial_imx_resume,
+	.id_table	= imx_uart_devtype,
 	.driver		= {
 		.name	= "imx-uart",
 		.owner	= THIS_MODULE,
-- 
1.7.4.1

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

* [PATCH v2 2/5] serial/imx: get rid of the use of cpu_is_mx1()
@ 2011-06-24 18:04   ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-24 18:04 UTC (permalink / raw)
  To: linux-arm-kernel

The patch removes all the uses of cpu_is_mx1().  Instead, it uses
the .id_table of platform_driver to distinguish the uart device type.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
---
 arch/arm/mach-imx/clock-imx1.c                |    6 +-
 arch/arm/plat-mxc/devices/platform-imx-uart.c |    2 +-
 drivers/tty/serial/imx.c                      |   52 ++++++++++++++++++++++--
 3 files changed, 51 insertions(+), 9 deletions(-)

diff --git a/arch/arm/mach-imx/clock-imx1.c b/arch/arm/mach-imx/clock-imx1.c
index dcc4172..4aabeb2 100644
--- a/arch/arm/mach-imx/clock-imx1.c
+++ b/arch/arm/mach-imx/clock-imx1.c
@@ -587,9 +587,9 @@ static struct clk_lookup lookups[] __initdata = {
 	_REGISTER_CLOCK(NULL, "mma", mma_clk)
 	_REGISTER_CLOCK("imx_udc.0", NULL, usbd_clk)
 	_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
-	_REGISTER_CLOCK("imx-uart.0", NULL, uart_clk)
-	_REGISTER_CLOCK("imx-uart.1", NULL, uart_clk)
-	_REGISTER_CLOCK("imx-uart.2", NULL, uart_clk)
+	_REGISTER_CLOCK("imx1-uart.0", NULL, uart_clk)
+	_REGISTER_CLOCK("imx1-uart.1", NULL, uart_clk)
+	_REGISTER_CLOCK("imx1-uart.2", NULL, uart_clk)
 	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
 	_REGISTER_CLOCK("imx1-cspi.0", NULL, spi_clk)
 	_REGISTER_CLOCK("imx1-cspi.1", NULL, spi_clk)
diff --git a/arch/arm/plat-mxc/devices/platform-imx-uart.c b/arch/arm/plat-mxc/devices/platform-imx-uart.c
index 3c854c2..01982a1 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-uart.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-uart.c
@@ -150,7 +150,7 @@ struct platform_device *__init imx_add_imx_uart_3irq(
 		},
 	};
 
-	return imx_add_platform_device("imx-uart", data->id, res,
+	return imx_add_platform_device("imx1-uart", data->id, res,
 			ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
 
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index a544731..8a6f4e1 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -48,7 +48,6 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <mach/hardware.h>
 #include <mach/imx-uart.h>
 
 /* Register definitions */
@@ -67,7 +66,8 @@
 #define UBMR  0xa8 /* BRM Modulator Register */
 #define UBRC  0xac /* Baud Rate Count Register */
 #define MX2_ONEMS 0xb0 /* One Millisecond register */
-#define UTS (cpu_is_mx1() ? 0xd0 : 0xb4) /* UART Test Register */
+#define MX1_UTS 0xd0 /* UART Test Register on mx1 */
+#define MX2_UTS 0xb4 /* UART Test Register on mx2 and later */
 
 /* UART Control Register Bit Fields.*/
 #define  URXD_CHARRDY    (1<<15)
@@ -181,6 +181,17 @@
 
 #define UART_NR 8
 
+enum imx_uart_type {
+	IMX1_UART,
+	IMX2_UART,
+};
+
+/* device type dependent stuff */
+struct imx_uart_data {
+	unsigned uts_reg;
+	unsigned type;
+};
+
 struct imx_port {
 	struct uart_port	port;
 	struct timer_list	timer;
@@ -192,6 +203,7 @@ struct imx_port {
 	unsigned int		irda_inv_tx:1;
 	unsigned short		trcv_delay; /* transceiver delay */
 	struct clk		*clk;
+	struct imx_uart_data	*devdata;
 };
 
 #ifdef CONFIG_IRDA
@@ -200,6 +212,21 @@ struct imx_port {
 #define USE_IRDA(sport)	(0)
 #endif
 
+static struct imx_uart_data imx_uart_devdata[] = {
+	[IMX1_UART] = {
+		.uts_reg = MX1_UTS,
+		.type = IMX1_UART,
+	},
+	[IMX2_UART] = {
+		.uts_reg = MX2_UTS,
+		.type = IMX2_UART,
+	},
+};
+
+#define UTS (sport->devdata->uts_reg)
+#define IS_IMX1_UART(sport) (sport->devdata->type == IMX1_UART)
+#define IS_IMX2_UART(sport) (sport->devdata->type == IMX2_UART)
+
 /*
  * Handle any change of modem status signal since we were last called.
  */
@@ -689,7 +716,7 @@ static int imx_startup(struct uart_port *port)
 		}
 	}
 
-	if (!cpu_is_mx1()) {
+	if (IS_IMX2_UART(sport)) {
 		temp = readl(sport->port.membase + UCR3);
 		temp |= MX2_UCR3_RXDMUXSEL;
 		writel(temp, sport->port.membase + UCR3);
@@ -923,7 +950,7 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 	writel(num, sport->port.membase + UBIR);
 	writel(denom, sport->port.membase + UBMR);
 
-	if (!cpu_is_mx1())
+	if (IS_IMX2_UART(sport))
 		writel(sport->port.uartclk / div / 1000,
 				sport->port.membase + MX2_ONEMS);
 
@@ -1063,7 +1090,7 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
 	ucr1 = old_ucr1 = readl(sport->port.membase + UCR1);
 	old_ucr2 = readl(sport->port.membase + UCR2);
 
-	if (cpu_is_mx1())
+	if (IS_IMX1_UART(sport))
 		ucr1 |= MX1_UCR1_UARTCLKEN;
 	ucr1 |= UCR1_UARTEN;
 	ucr1 &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN);
@@ -1263,6 +1290,7 @@ static int serial_imx_probe(struct platform_device *pdev)
 	init_timer(&sport->timer);
 	sport->timer.function = imx_timeout;
 	sport->timer.data     = (unsigned long)sport;
+	sport->devdata = &imx_uart_devdata[pdev->id_entry->driver_data];
 
 	sport->clk = clk_get(&pdev->dev, "uart");
 	if (IS_ERR(sport->clk)) {
@@ -1335,12 +1363,26 @@ static int serial_imx_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static struct platform_device_id imx_uart_devtype[] = {
+	{
+		.name = "imx1-uart",
+		.driver_data = IMX1_UART,
+	}, {
+		.name = "imx-uart",
+		.driver_data = IMX2_UART,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(platform, imx_uart_devtype);
+
 static struct platform_driver serial_imx_driver = {
 	.probe		= serial_imx_probe,
 	.remove		= serial_imx_remove,
 
 	.suspend	= serial_imx_suspend,
 	.resume		= serial_imx_resume,
+	.id_table	= imx_uart_devtype,
 	.driver		= {
 		.name	= "imx-uart",
 		.owner	= THIS_MODULE,
-- 
1.7.4.1

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

* [PATCH v2 3/5] serial/imx: add device tree support
  2011-06-24 18:04 ` Shawn Guo
@ 2011-06-24 18:04   ` Shawn Guo
  -1 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-24 18:04 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, netdev, linux-serial, devicetree-discuss, patches,
	Shawn Guo, Jeremy Kerr, Jason Liu, Sascha Hauer, Alan Cox

It adds device tree data parsing support for imx tty/serial driver.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
Signed-off-by: Jason Liu <jason.hui@linaro.org>
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
---
 .../bindings/tty/serial/fsl-imx-uart.txt           |   20 +++++
 drivers/tty/serial/imx.c                           |   82 +++++++++++++++++---
 2 files changed, 92 insertions(+), 10 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/tty/serial/fsl-imx-uart.txt

diff --git a/Documentation/devicetree/bindings/tty/serial/fsl-imx-uart.txt b/Documentation/devicetree/bindings/tty/serial/fsl-imx-uart.txt
new file mode 100644
index 0000000..9aafe0a
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/fsl-imx-uart.txt
@@ -0,0 +1,20 @@
+* Freescale i.MX Universal Asynchronous Receiver/Transmitter (UART)
+
+Required properties:
+- compatible : should be "fsl,<soc>-uart"
+- reg : address and length of the register set for the device
+- interrupts : should contain uart interrupt
+- id : should be the port ID defined by soc
+
+Optional properties:
+- fsl,uart-has-rtscts : indicate the uart has rts and cts
+- fsl,irda-mode : support irda mode
+
+Example:
+
+uart@73fbc000 {
+	compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+	reg = <0x73fbc000 0x4000>;
+	interrupts = <31>;
+	fsl,uart-has-rtscts;
+};
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 8a6f4e1..bef27b3 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -45,6 +45,8 @@
 #include <linux/delay.h>
 #include <linux/rational.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -227,6 +229,12 @@ static struct imx_uart_data imx_uart_devdata[] = {
 #define IS_IMX1_UART(sport) (sport->devdata->type == IMX1_UART)
 #define IS_IMX2_UART(sport) (sport->devdata->type == IMX2_UART)
 
+static struct of_device_id imx_uart_dt_ids[] = {
+	{ .compatible = "fsl,imx1-uart", .data = &imx_uart_devdata[IMX1_UART], },
+	{ .compatible = "fsl,imx21-uart", .data = &imx_uart_devdata[IMX2_UART], },
+	{ /* sentinel */ },
+};
+
 /*
  * Handle any change of modem status signal since we were last called.
  */
@@ -1250,6 +1258,58 @@ static int serial_imx_resume(struct platform_device *dev)
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static int serial_imx_probe_dt(struct imx_port *sport,
+		struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
+	const struct of_device_id *of_id =
+			of_match_device(imx_uart_dt_ids, &pdev->dev);
+
+	if (!node)
+		return -ENODEV;
+
+	pdev->id = of_alias_get_id(node, "serial");
+	if (pdev->id < 0)
+		return -ENODEV;
+
+	if (of_get_property(node, "fsl,uart-has-rtscts", NULL))
+		sport->have_rtscts = 1;
+
+	if (of_get_property(node, "fsl,irda-mode", NULL))
+		sport->use_irda = 1;
+
+	sport->devdata = of_id->data;
+
+	return 0;
+}
+#else
+static int serial_imx_probe_dt(struct imx_port *sport,
+		struct platform_device *pdev)
+{
+	return -ENODEV;
+}
+#endif
+
+static int serial_imx_probe_pdata(struct imx_port *sport,
+		struct platform_device *pdev)
+{
+	struct imxuart_platform_data *pdata = pdev->dev.platform_data;
+
+	if (!pdata)
+		return 0;
+
+	if (pdata->flags & IMXUART_HAVE_RTSCTS)
+		sport->have_rtscts = 1;
+
+	if (pdata->flags & IMXUART_IRDA)
+		sport->use_irda = 1;
+
+	sport->devdata = &imx_uart_devdata[pdev->id_entry->driver_data];
+
+	return 0;
+}
+
 static int serial_imx_probe(struct platform_device *pdev)
 {
 	struct imx_port *sport;
@@ -1262,6 +1322,12 @@ static int serial_imx_probe(struct platform_device *pdev)
 	if (!sport)
 		return -ENOMEM;
 
+	ret = serial_imx_probe_dt(sport, pdev);
+	if (ret == -ENODEV)
+		ret = serial_imx_probe_pdata(sport, pdev);
+	if (ret)
+		goto free;
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		ret = -ENODEV;
@@ -1290,7 +1356,6 @@ static int serial_imx_probe(struct platform_device *pdev)
 	init_timer(&sport->timer);
 	sport->timer.function = imx_timeout;
 	sport->timer.data     = (unsigned long)sport;
-	sport->devdata = &imx_uart_devdata[pdev->id_entry->driver_data];
 
 	sport->clk = clk_get(&pdev->dev, "uart");
 	if (IS_ERR(sport->clk)) {
@@ -1301,17 +1366,13 @@ static int serial_imx_probe(struct platform_device *pdev)
 
 	sport->port.uartclk = clk_get_rate(sport->clk);
 
-	imx_ports[pdev->id] = sport;
+	if (imx_ports[sport->port.line]) {
+		ret = -EBUSY;
+		goto clkput;
+	}
+	imx_ports[sport->port.line] = sport;
 
 	pdata = pdev->dev.platform_data;
-	if (pdata && (pdata->flags & IMXUART_HAVE_RTSCTS))
-		sport->have_rtscts = 1;
-
-#ifdef CONFIG_IRDA
-	if (pdata && (pdata->flags & IMXUART_IRDA))
-		sport->use_irda = 1;
-#endif
-
 	if (pdata && pdata->init) {
 		ret = pdata->init(pdev);
 		if (ret)
@@ -1386,6 +1447,7 @@ static struct platform_driver serial_imx_driver = {
 	.driver		= {
 		.name	= "imx-uart",
 		.owner	= THIS_MODULE,
+		.of_match_table = imx_uart_dt_ids,
 	},
 };
 
-- 
1.7.4.1


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

* [PATCH v2 3/5] serial/imx: add device tree support
@ 2011-06-24 18:04   ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-24 18:04 UTC (permalink / raw)
  To: linux-arm-kernel

It adds device tree data parsing support for imx tty/serial driver.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
Signed-off-by: Jason Liu <jason.hui@linaro.org>
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
---
 .../bindings/tty/serial/fsl-imx-uart.txt           |   20 +++++
 drivers/tty/serial/imx.c                           |   82 +++++++++++++++++---
 2 files changed, 92 insertions(+), 10 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/tty/serial/fsl-imx-uart.txt

diff --git a/Documentation/devicetree/bindings/tty/serial/fsl-imx-uart.txt b/Documentation/devicetree/bindings/tty/serial/fsl-imx-uart.txt
new file mode 100644
index 0000000..9aafe0a
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/fsl-imx-uart.txt
@@ -0,0 +1,20 @@
+* Freescale i.MX Universal Asynchronous Receiver/Transmitter (UART)
+
+Required properties:
+- compatible : should be "fsl,<soc>-uart"
+- reg : address and length of the register set for the device
+- interrupts : should contain uart interrupt
+- id : should be the port ID defined by soc
+
+Optional properties:
+- fsl,uart-has-rtscts : indicate the uart has rts and cts
+- fsl,irda-mode : support irda mode
+
+Example:
+
+uart at 73fbc000 {
+	compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+	reg = <0x73fbc000 0x4000>;
+	interrupts = <31>;
+	fsl,uart-has-rtscts;
+};
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 8a6f4e1..bef27b3 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -45,6 +45,8 @@
 #include <linux/delay.h>
 #include <linux/rational.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -227,6 +229,12 @@ static struct imx_uart_data imx_uart_devdata[] = {
 #define IS_IMX1_UART(sport) (sport->devdata->type == IMX1_UART)
 #define IS_IMX2_UART(sport) (sport->devdata->type == IMX2_UART)
 
+static struct of_device_id imx_uart_dt_ids[] = {
+	{ .compatible = "fsl,imx1-uart", .data = &imx_uart_devdata[IMX1_UART], },
+	{ .compatible = "fsl,imx21-uart", .data = &imx_uart_devdata[IMX2_UART], },
+	{ /* sentinel */ },
+};
+
 /*
  * Handle any change of modem status signal since we were last called.
  */
@@ -1250,6 +1258,58 @@ static int serial_imx_resume(struct platform_device *dev)
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static int serial_imx_probe_dt(struct imx_port *sport,
+		struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
+	const struct of_device_id *of_id =
+			of_match_device(imx_uart_dt_ids, &pdev->dev);
+
+	if (!node)
+		return -ENODEV;
+
+	pdev->id = of_alias_get_id(node, "serial");
+	if (pdev->id < 0)
+		return -ENODEV;
+
+	if (of_get_property(node, "fsl,uart-has-rtscts", NULL))
+		sport->have_rtscts = 1;
+
+	if (of_get_property(node, "fsl,irda-mode", NULL))
+		sport->use_irda = 1;
+
+	sport->devdata = of_id->data;
+
+	return 0;
+}
+#else
+static int serial_imx_probe_dt(struct imx_port *sport,
+		struct platform_device *pdev)
+{
+	return -ENODEV;
+}
+#endif
+
+static int serial_imx_probe_pdata(struct imx_port *sport,
+		struct platform_device *pdev)
+{
+	struct imxuart_platform_data *pdata = pdev->dev.platform_data;
+
+	if (!pdata)
+		return 0;
+
+	if (pdata->flags & IMXUART_HAVE_RTSCTS)
+		sport->have_rtscts = 1;
+
+	if (pdata->flags & IMXUART_IRDA)
+		sport->use_irda = 1;
+
+	sport->devdata = &imx_uart_devdata[pdev->id_entry->driver_data];
+
+	return 0;
+}
+
 static int serial_imx_probe(struct platform_device *pdev)
 {
 	struct imx_port *sport;
@@ -1262,6 +1322,12 @@ static int serial_imx_probe(struct platform_device *pdev)
 	if (!sport)
 		return -ENOMEM;
 
+	ret = serial_imx_probe_dt(sport, pdev);
+	if (ret == -ENODEV)
+		ret = serial_imx_probe_pdata(sport, pdev);
+	if (ret)
+		goto free;
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		ret = -ENODEV;
@@ -1290,7 +1356,6 @@ static int serial_imx_probe(struct platform_device *pdev)
 	init_timer(&sport->timer);
 	sport->timer.function = imx_timeout;
 	sport->timer.data     = (unsigned long)sport;
-	sport->devdata = &imx_uart_devdata[pdev->id_entry->driver_data];
 
 	sport->clk = clk_get(&pdev->dev, "uart");
 	if (IS_ERR(sport->clk)) {
@@ -1301,17 +1366,13 @@ static int serial_imx_probe(struct platform_device *pdev)
 
 	sport->port.uartclk = clk_get_rate(sport->clk);
 
-	imx_ports[pdev->id] = sport;
+	if (imx_ports[sport->port.line]) {
+		ret = -EBUSY;
+		goto clkput;
+	}
+	imx_ports[sport->port.line] = sport;
 
 	pdata = pdev->dev.platform_data;
-	if (pdata && (pdata->flags & IMXUART_HAVE_RTSCTS))
-		sport->have_rtscts = 1;
-
-#ifdef CONFIG_IRDA
-	if (pdata && (pdata->flags & IMXUART_IRDA))
-		sport->use_irda = 1;
-#endif
-
 	if (pdata && pdata->init) {
 		ret = pdata->init(pdev);
 		if (ret)
@@ -1386,6 +1447,7 @@ static struct platform_driver serial_imx_driver = {
 	.driver		= {
 		.name	= "imx-uart",
 		.owner	= THIS_MODULE,
+		.of_match_table = imx_uart_dt_ids,
 	},
 };
 
-- 
1.7.4.1

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

* [PATCH v2 4/5] net/fec: add device tree support
@ 2011-06-24 18:04   ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-24 18:04 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, netdev, linux-serial, devicetree-discuss, patches,
	Shawn Guo, Jason Liu, David S. Miller

It adds device tree data parsing support for fec driver.

Signed-off-by: Jason Liu <jason.hui@linaro.org>
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Cc: David S. Miller <davem@davemloft.net>
---
 Documentation/devicetree/bindings/net/fsl-fec.txt |   22 ++++++
 drivers/net/fec.c                                 |   81 +++++++++++++++++++--
 2 files changed, 98 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/fsl-fec.txt

diff --git a/Documentation/devicetree/bindings/net/fsl-fec.txt b/Documentation/devicetree/bindings/net/fsl-fec.txt
new file mode 100644
index 0000000..345ecb6
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/fsl-fec.txt
@@ -0,0 +1,22 @@
+* Freescale Fast Ethernet Controller (FEC)
+
+Required properties:
+- compatible : should be "fsl,<soc>-fec"
+- reg : address and length of the register set for the device
+- interrupts : should contain fec interrupt
+- phy-mode : string, operation mode of the PHY interface.
+  Supported values are: "mii", "gmii", "sgmii", "tbi", "rmii",
+  "rgmii", "rgmii-id", "rgmii-rxid", "rgmii-txid", "rtbi".
+
+Optional properties:
+- local-mac-address : 6 bytes, mac address
+
+Example:
+
+fec@83fec000 {
+	compatible = "fsl,imx51-fec", "fsl,imx27-fec";
+	reg = <0x83fec000 0x4000>;
+	interrupts = <87>;
+	phy-mode = "mii";
+	local-mac-address = [00 04 9F 01 1B B9];
+};
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 885d8ba..16ac1dd 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -44,6 +44,8 @@
 #include <linux/platform_device.h>
 #include <linux/phy.h>
 #include <linux/fec.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <asm/cacheflush.h>
 
@@ -78,6 +80,12 @@ static struct platform_device_id fec_devtype[] = {
 	{ }
 };
 
+static const struct of_device_id fec_dt_ids[] = {
+	{ .compatible = "fsl,imx27-fec", .data = &fec_devtype[0], },
+	{ .compatible = "fsl,imx28-fec", .data = &fec_devtype[1], },
+	{},
+};
+
 static unsigned char macaddr[ETH_ALEN];
 module_param_array(macaddr, byte, NULL, 0);
 MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
@@ -731,8 +739,23 @@ static void __inline__ fec_get_mac(struct net_device *ndev)
 	 */
 	iap = macaddr;
 
+#ifdef CONFIG_OF
+	/*
+	 * 2) from device tree data
+	 */
+	if (!is_valid_ether_addr(iap)) {
+		struct device_node *np = fep->pdev->dev.of_node;
+		if (np) {
+			const void *p = of_get_property(np,
+						"local-mac-address", NULL);
+			if (p)
+				iap = (unsigned char *) p;
+		}
+	}
+#endif
+
 	/*
-	 * 2) from flash or fuse (via platform data)
+	 * 3) from flash or fuse (via platform data)
 	 */
 	if (!is_valid_ether_addr(iap)) {
 #ifdef CONFIG_M5272
@@ -745,7 +768,7 @@ static void __inline__ fec_get_mac(struct net_device *ndev)
 	}
 
 	/*
-	 * 3) FEC mac registers set by bootloader
+	 * 4) FEC mac registers set by bootloader
 	 */
 	if (!is_valid_ether_addr(iap)) {
 		*((unsigned long *) &tmpaddr[0]) =
@@ -1355,6 +1378,43 @@ static int fec_enet_init(struct net_device *ndev)
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static int __devinit fec_get_phy_mode_dt(struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct device_node *np = fep->pdev->dev.of_node;
+	const char *pm, *phy_modes[] = {
+		[PHY_INTERFACE_MODE_MII]	= "mii",
+		[PHY_INTERFACE_MODE_GMII]	= "gmii",
+		[PHY_INTERFACE_MODE_SGMII]	= "sgmii",
+		[PHY_INTERFACE_MODE_TBI]	= "tbi",
+		[PHY_INTERFACE_MODE_RMII]	= "rmii",
+		[PHY_INTERFACE_MODE_RGMII]	= "rgmii",
+		[PHY_INTERFACE_MODE_RGMII_ID]	= "rgmii-id",
+		[PHY_INTERFACE_MODE_RGMII_RXID]	= "rgmii-rxid",
+		[PHY_INTERFACE_MODE_RGMII_TXID] = "rgmii-txid",
+		[PHY_INTERFACE_MODE_RTBI]	= "rtbi",
+	};
+
+	if (np) {
+		pm = of_get_property(np, "phy-mode", NULL);
+		if (pm) {
+			int i;
+			for (i = 0; i < ARRAY_SIZE(phy_modes); i++)
+				if (!strcasecmp(pm, phy_modes[i]))
+					return i;
+		}
+	}
+
+	return -ENODEV;
+}
+#else
+static int __devinit fec_get_phy_mode_dt(struct net_device *ndev)
+{
+	return -ENODEV;
+}
+#endif
+
 static int __devinit
 fec_probe(struct platform_device *pdev)
 {
@@ -1363,6 +1423,11 @@ fec_probe(struct platform_device *pdev)
 	struct net_device *ndev;
 	int i, irq, ret = 0;
 	struct resource *r;
+	const struct of_device_id *of_id;
+
+	of_id = of_match_device(fec_dt_ids, &pdev->dev);
+	if (of_id)
+		pdev->id_entry = (struct platform_device_id *) of_id->data;
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!r)
@@ -1394,9 +1459,14 @@ fec_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, ndev);
 
-	pdata = pdev->dev.platform_data;
-	if (pdata)
-		fep->phy_interface = pdata->phy;
+	fep->phy_interface = fec_get_phy_mode_dt(ndev);
+	if (fep->phy_interface == -ENODEV) {
+		pdata = pdev->dev.platform_data;
+		if (pdata)
+			fep->phy_interface = pdata->phy;
+		else
+			fep->phy_interface = PHY_INTERFACE_MODE_MII;
+	}
 
 	/* This device has up to three irqs on some platforms */
 	for (i = 0; i < 3; i++) {
@@ -1531,6 +1601,7 @@ static struct platform_driver fec_driver = {
 #ifdef CONFIG_PM
 		.pm	= &fec_pm_ops,
 #endif
+		.of_match_table = fec_dt_ids,
 	},
 	.id_table = fec_devtype,
 	.probe	= fec_probe,
-- 
1.7.4.1


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

* [PATCH v2 4/5] net/fec: add device tree support
@ 2011-06-24 18:04   ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-24 18:04 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: patches-QSEj5FYQhm4dnm+yROfE0A, netdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Jason Liu,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA, David S. Miller

It adds device tree data parsing support for fec driver.

Signed-off-by: Jason Liu <jason.hui-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: David S. Miller <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
---
 Documentation/devicetree/bindings/net/fsl-fec.txt |   22 ++++++
 drivers/net/fec.c                                 |   81 +++++++++++++++++++--
 2 files changed, 98 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/fsl-fec.txt

diff --git a/Documentation/devicetree/bindings/net/fsl-fec.txt b/Documentation/devicetree/bindings/net/fsl-fec.txt
new file mode 100644
index 0000000..345ecb6
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/fsl-fec.txt
@@ -0,0 +1,22 @@
+* Freescale Fast Ethernet Controller (FEC)
+
+Required properties:
+- compatible : should be "fsl,<soc>-fec"
+- reg : address and length of the register set for the device
+- interrupts : should contain fec interrupt
+- phy-mode : string, operation mode of the PHY interface.
+  Supported values are: "mii", "gmii", "sgmii", "tbi", "rmii",
+  "rgmii", "rgmii-id", "rgmii-rxid", "rgmii-txid", "rtbi".
+
+Optional properties:
+- local-mac-address : 6 bytes, mac address
+
+Example:
+
+fec@83fec000 {
+	compatible = "fsl,imx51-fec", "fsl,imx27-fec";
+	reg = <0x83fec000 0x4000>;
+	interrupts = <87>;
+	phy-mode = "mii";
+	local-mac-address = [00 04 9F 01 1B B9];
+};
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 885d8ba..16ac1dd 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -44,6 +44,8 @@
 #include <linux/platform_device.h>
 #include <linux/phy.h>
 #include <linux/fec.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <asm/cacheflush.h>
 
@@ -78,6 +80,12 @@ static struct platform_device_id fec_devtype[] = {
 	{ }
 };
 
+static const struct of_device_id fec_dt_ids[] = {
+	{ .compatible = "fsl,imx27-fec", .data = &fec_devtype[0], },
+	{ .compatible = "fsl,imx28-fec", .data = &fec_devtype[1], },
+	{},
+};
+
 static unsigned char macaddr[ETH_ALEN];
 module_param_array(macaddr, byte, NULL, 0);
 MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
@@ -731,8 +739,23 @@ static void __inline__ fec_get_mac(struct net_device *ndev)
 	 */
 	iap = macaddr;
 
+#ifdef CONFIG_OF
+	/*
+	 * 2) from device tree data
+	 */
+	if (!is_valid_ether_addr(iap)) {
+		struct device_node *np = fep->pdev->dev.of_node;
+		if (np) {
+			const void *p = of_get_property(np,
+						"local-mac-address", NULL);
+			if (p)
+				iap = (unsigned char *) p;
+		}
+	}
+#endif
+
 	/*
-	 * 2) from flash or fuse (via platform data)
+	 * 3) from flash or fuse (via platform data)
 	 */
 	if (!is_valid_ether_addr(iap)) {
 #ifdef CONFIG_M5272
@@ -745,7 +768,7 @@ static void __inline__ fec_get_mac(struct net_device *ndev)
 	}
 
 	/*
-	 * 3) FEC mac registers set by bootloader
+	 * 4) FEC mac registers set by bootloader
 	 */
 	if (!is_valid_ether_addr(iap)) {
 		*((unsigned long *) &tmpaddr[0]) =
@@ -1355,6 +1378,43 @@ static int fec_enet_init(struct net_device *ndev)
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static int __devinit fec_get_phy_mode_dt(struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct device_node *np = fep->pdev->dev.of_node;
+	const char *pm, *phy_modes[] = {
+		[PHY_INTERFACE_MODE_MII]	= "mii",
+		[PHY_INTERFACE_MODE_GMII]	= "gmii",
+		[PHY_INTERFACE_MODE_SGMII]	= "sgmii",
+		[PHY_INTERFACE_MODE_TBI]	= "tbi",
+		[PHY_INTERFACE_MODE_RMII]	= "rmii",
+		[PHY_INTERFACE_MODE_RGMII]	= "rgmii",
+		[PHY_INTERFACE_MODE_RGMII_ID]	= "rgmii-id",
+		[PHY_INTERFACE_MODE_RGMII_RXID]	= "rgmii-rxid",
+		[PHY_INTERFACE_MODE_RGMII_TXID] = "rgmii-txid",
+		[PHY_INTERFACE_MODE_RTBI]	= "rtbi",
+	};
+
+	if (np) {
+		pm = of_get_property(np, "phy-mode", NULL);
+		if (pm) {
+			int i;
+			for (i = 0; i < ARRAY_SIZE(phy_modes); i++)
+				if (!strcasecmp(pm, phy_modes[i]))
+					return i;
+		}
+	}
+
+	return -ENODEV;
+}
+#else
+static int __devinit fec_get_phy_mode_dt(struct net_device *ndev)
+{
+	return -ENODEV;
+}
+#endif
+
 static int __devinit
 fec_probe(struct platform_device *pdev)
 {
@@ -1363,6 +1423,11 @@ fec_probe(struct platform_device *pdev)
 	struct net_device *ndev;
 	int i, irq, ret = 0;
 	struct resource *r;
+	const struct of_device_id *of_id;
+
+	of_id = of_match_device(fec_dt_ids, &pdev->dev);
+	if (of_id)
+		pdev->id_entry = (struct platform_device_id *) of_id->data;
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!r)
@@ -1394,9 +1459,14 @@ fec_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, ndev);
 
-	pdata = pdev->dev.platform_data;
-	if (pdata)
-		fep->phy_interface = pdata->phy;
+	fep->phy_interface = fec_get_phy_mode_dt(ndev);
+	if (fep->phy_interface == -ENODEV) {
+		pdata = pdev->dev.platform_data;
+		if (pdata)
+			fep->phy_interface = pdata->phy;
+		else
+			fep->phy_interface = PHY_INTERFACE_MODE_MII;
+	}
 
 	/* This device has up to three irqs on some platforms */
 	for (i = 0; i < 3; i++) {
@@ -1531,6 +1601,7 @@ static struct platform_driver fec_driver = {
 #ifdef CONFIG_PM
 		.pm	= &fec_pm_ops,
 #endif
+		.of_match_table = fec_dt_ids,
 	},
 	.id_table = fec_devtype,
 	.probe	= fec_probe,
-- 
1.7.4.1

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

* [PATCH v2 4/5] net/fec: add device tree support
@ 2011-06-24 18:04   ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-24 18:04 UTC (permalink / raw)
  To: linux-arm-kernel

It adds device tree data parsing support for fec driver.

Signed-off-by: Jason Liu <jason.hui@linaro.org>
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Cc: David S. Miller <davem@davemloft.net>
---
 Documentation/devicetree/bindings/net/fsl-fec.txt |   22 ++++++
 drivers/net/fec.c                                 |   81 +++++++++++++++++++--
 2 files changed, 98 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/fsl-fec.txt

diff --git a/Documentation/devicetree/bindings/net/fsl-fec.txt b/Documentation/devicetree/bindings/net/fsl-fec.txt
new file mode 100644
index 0000000..345ecb6
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/fsl-fec.txt
@@ -0,0 +1,22 @@
+* Freescale Fast Ethernet Controller (FEC)
+
+Required properties:
+- compatible : should be "fsl,<soc>-fec"
+- reg : address and length of the register set for the device
+- interrupts : should contain fec interrupt
+- phy-mode : string, operation mode of the PHY interface.
+  Supported values are: "mii", "gmii", "sgmii", "tbi", "rmii",
+  "rgmii", "rgmii-id", "rgmii-rxid", "rgmii-txid", "rtbi".
+
+Optional properties:
+- local-mac-address : 6 bytes, mac address
+
+Example:
+
+fec at 83fec000 {
+	compatible = "fsl,imx51-fec", "fsl,imx27-fec";
+	reg = <0x83fec000 0x4000>;
+	interrupts = <87>;
+	phy-mode = "mii";
+	local-mac-address = [00 04 9F 01 1B B9];
+};
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 885d8ba..16ac1dd 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -44,6 +44,8 @@
 #include <linux/platform_device.h>
 #include <linux/phy.h>
 #include <linux/fec.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <asm/cacheflush.h>
 
@@ -78,6 +80,12 @@ static struct platform_device_id fec_devtype[] = {
 	{ }
 };
 
+static const struct of_device_id fec_dt_ids[] = {
+	{ .compatible = "fsl,imx27-fec", .data = &fec_devtype[0], },
+	{ .compatible = "fsl,imx28-fec", .data = &fec_devtype[1], },
+	{},
+};
+
 static unsigned char macaddr[ETH_ALEN];
 module_param_array(macaddr, byte, NULL, 0);
 MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
@@ -731,8 +739,23 @@ static void __inline__ fec_get_mac(struct net_device *ndev)
 	 */
 	iap = macaddr;
 
+#ifdef CONFIG_OF
+	/*
+	 * 2) from device tree data
+	 */
+	if (!is_valid_ether_addr(iap)) {
+		struct device_node *np = fep->pdev->dev.of_node;
+		if (np) {
+			const void *p = of_get_property(np,
+						"local-mac-address", NULL);
+			if (p)
+				iap = (unsigned char *) p;
+		}
+	}
+#endif
+
 	/*
-	 * 2) from flash or fuse (via platform data)
+	 * 3) from flash or fuse (via platform data)
 	 */
 	if (!is_valid_ether_addr(iap)) {
 #ifdef CONFIG_M5272
@@ -745,7 +768,7 @@ static void __inline__ fec_get_mac(struct net_device *ndev)
 	}
 
 	/*
-	 * 3) FEC mac registers set by bootloader
+	 * 4) FEC mac registers set by bootloader
 	 */
 	if (!is_valid_ether_addr(iap)) {
 		*((unsigned long *) &tmpaddr[0]) =
@@ -1355,6 +1378,43 @@ static int fec_enet_init(struct net_device *ndev)
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static int __devinit fec_get_phy_mode_dt(struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct device_node *np = fep->pdev->dev.of_node;
+	const char *pm, *phy_modes[] = {
+		[PHY_INTERFACE_MODE_MII]	= "mii",
+		[PHY_INTERFACE_MODE_GMII]	= "gmii",
+		[PHY_INTERFACE_MODE_SGMII]	= "sgmii",
+		[PHY_INTERFACE_MODE_TBI]	= "tbi",
+		[PHY_INTERFACE_MODE_RMII]	= "rmii",
+		[PHY_INTERFACE_MODE_RGMII]	= "rgmii",
+		[PHY_INTERFACE_MODE_RGMII_ID]	= "rgmii-id",
+		[PHY_INTERFACE_MODE_RGMII_RXID]	= "rgmii-rxid",
+		[PHY_INTERFACE_MODE_RGMII_TXID] = "rgmii-txid",
+		[PHY_INTERFACE_MODE_RTBI]	= "rtbi",
+	};
+
+	if (np) {
+		pm = of_get_property(np, "phy-mode", NULL);
+		if (pm) {
+			int i;
+			for (i = 0; i < ARRAY_SIZE(phy_modes); i++)
+				if (!strcasecmp(pm, phy_modes[i]))
+					return i;
+		}
+	}
+
+	return -ENODEV;
+}
+#else
+static int __devinit fec_get_phy_mode_dt(struct net_device *ndev)
+{
+	return -ENODEV;
+}
+#endif
+
 static int __devinit
 fec_probe(struct platform_device *pdev)
 {
@@ -1363,6 +1423,11 @@ fec_probe(struct platform_device *pdev)
 	struct net_device *ndev;
 	int i, irq, ret = 0;
 	struct resource *r;
+	const struct of_device_id *of_id;
+
+	of_id = of_match_device(fec_dt_ids, &pdev->dev);
+	if (of_id)
+		pdev->id_entry = (struct platform_device_id *) of_id->data;
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!r)
@@ -1394,9 +1459,14 @@ fec_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, ndev);
 
-	pdata = pdev->dev.platform_data;
-	if (pdata)
-		fep->phy_interface = pdata->phy;
+	fep->phy_interface = fec_get_phy_mode_dt(ndev);
+	if (fep->phy_interface == -ENODEV) {
+		pdata = pdev->dev.platform_data;
+		if (pdata)
+			fep->phy_interface = pdata->phy;
+		else
+			fep->phy_interface = PHY_INTERFACE_MODE_MII;
+	}
 
 	/* This device has up to three irqs on some platforms */
 	for (i = 0; i < 3; i++) {
@@ -1531,6 +1601,7 @@ static struct platform_driver fec_driver = {
 #ifdef CONFIG_PM
 		.pm	= &fec_pm_ops,
 #endif
+		.of_match_table = fec_dt_ids,
 	},
 	.id_table = fec_devtype,
 	.probe	= fec_probe,
-- 
1.7.4.1

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

* [PATCH v2 5/5] ARM: mx5: add basic device tree support for imx51 babbage
@ 2011-06-24 18:04   ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-24 18:04 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, netdev, linux-serial, devicetree-discuss, patches,
	Shawn Guo

This patch adds the i.mx51 dt platform with uart and fec support.
It also adds the dts file imx51 babbage, so that we can have a dt
kernel on babbage booting into console with nfs root.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
 arch/arm/boot/dts/imx51-babbage.dts |   93 +++++++++++++++++++++++++++++++++++
 arch/arm/mach-mx5/Kconfig           |    8 +++
 arch/arm/mach-mx5/Makefile          |    1 +
 arch/arm/mach-mx5/imx51-dt.c        |   70 ++++++++++++++++++++++++++
 4 files changed, 172 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/boot/dts/imx51-babbage.dts
 create mode 100644 arch/arm/mach-mx5/imx51-dt.c

diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts
new file mode 100644
index 0000000..402cc44
--- /dev/null
+++ b/arch/arm/boot/dts/imx51-babbage.dts
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Freescale i.MX51 Babbage";
+	compatible = "fsl,imx51-babbage", "fsl,imx51";
+	interrupt-parent = <&tzic>;
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+	};
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+	};
+
+	memory {
+		reg = <0x90000000 0x20000000>;
+	};
+
+	tzic: tz-interrupt-controller@e0000000 {
+		compatible = "fsl,imx51-tzic", "fsl,tzic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0xe0000000 0x4000>;
+	};
+
+	aips@70000000 { /* aips-1 */
+		compatible = "fsl,aips-bus", "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x70000000 0x10000000>;
+		ranges;
+
+		spba {
+			compatible = "fsl,spba-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x70000000 0x40000>;
+			ranges;
+
+			uart2: uart@7000c000 {
+				compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+				reg = <0x7000c000 0x4000>;
+				interrupts = <33>;
+				fsl,uart-has-rtscts;
+			};
+		};
+
+		uart0: uart@73fbc000 {
+			compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+			reg = <0x73fbc000 0x4000>;
+			interrupts = <31>;
+			fsl,uart-has-rtscts;
+		};
+
+		uart1: uart@73fc0000 {
+			compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+			reg = <0x73fc0000 0x4000>;
+			interrupts = <32>;
+			fsl,uart-has-rtscts;
+		};
+	};
+
+	aips@80000000 {	/* aips-2 */
+		compatible = "fsl,aips-bus", "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x80000000 0x10000000>;
+		ranges;
+
+		fec@83fec000 {
+			compatible = "fsl,imx51-fec", "fsl,imx27-fec";
+			reg = <0x83fec000 0x4000>;
+			interrupts = <87>;
+			phy-mode = "mii";
+		};
+	};
+};
diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
index 799fbc4..8bdd0c4 100644
--- a/arch/arm/mach-mx5/Kconfig
+++ b/arch/arm/mach-mx5/Kconfig
@@ -62,6 +62,14 @@ endif # ARCH_MX50_SUPPORTED
 if ARCH_MX51
 comment "i.MX51 machines:"
 
+config MACH_IMX51_DT
+	bool "Support i.MX51 platforms from device tree"
+	select SOC_IMX51
+	select USE_OF
+	help
+	  Include support for Freescale i.MX51 based platforms
+	  using the device tree for discovery
+
 config MACH_MX51_BABBAGE
 	bool "Support MX51 BABBAGE platforms"
 	select SOC_IMX51
diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile
index 0b9338c..47b483f 100644
--- a/arch/arm/mach-mx5/Makefile
+++ b/arch/arm/mach-mx5/Makefile
@@ -7,6 +7,7 @@ obj-y   := cpu.o mm.o clock-mx51-mx53.o devices.o ehci.o system.o
 obj-$(CONFIG_SOC_IMX50) += mm-mx50.o
 
 obj-$(CONFIG_CPU_FREQ_IMX)    += cpu_op-mx51.o
+obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o
 obj-$(CONFIG_MACH_MX51_BABBAGE) += board-mx51_babbage.o
 obj-$(CONFIG_MACH_MX51_3DS) += board-mx51_3ds.o
 obj-$(CONFIG_MACH_MX53_EVK) += board-mx53_evk.o
diff --git a/arch/arm/mach-mx5/imx51-dt.c b/arch/arm/mach-mx5/imx51-dt.c
new file mode 100644
index 0000000..8bfdb91
--- /dev/null
+++ b/arch/arm/mach-mx5/imx51-dt.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/irq.h>
+#include <linux/of_platform.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include <mach/common.h>
+#include <mach/mx51.h>
+
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate().  Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART1_BASE_ADDR, "imx-uart.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART2_BASE_ADDR, "imx-uart.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART3_BASE_ADDR, "imx-uart.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-fec", MX51_FEC_BASE_ADDR, "fec.0", NULL),
+	{}
+};
+
+static const struct of_device_id tzic_of_match[] __initconst = {
+	{ .compatible = "fsl,imx51-tzic", },
+	{}
+};
+
+static void __init imx51_dt_init(void)
+{
+	irq_domain_generate_simple(tzic_of_match, MX51_TZIC_BASE_ADDR, 0);
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     imx51_auxdata_lookup, NULL);
+}
+
+static void __init imx51_timer_init(void)
+{
+	mx51_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer imx51_timer = {
+	.init = imx51_timer_init,
+};
+
+static const char *imx51_dt_board_compat[] __initdata = {
+	"fsl,imx51-babbage",
+	NULL
+};
+
+DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
+	.map_io		= mx51_map_io,
+	.init_early	= imx51_init_early,
+	.init_irq	= mx51_init_irq,
+	.timer		= &imx51_timer,
+	.init_machine	= imx51_dt_init,
+	.dt_compat	= imx51_dt_board_compat,
+MACHINE_END
-- 
1.7.4.1


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

* [PATCH v2 5/5] ARM: mx5: add basic device tree support for imx51 babbage
@ 2011-06-24 18:04   ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-24 18:04 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: patches-QSEj5FYQhm4dnm+yROfE0A, netdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA

This patch adds the i.mx51 dt platform with uart and fec support.
It also adds the dts file imx51 babbage, so that we can have a dt
kernel on babbage booting into console with nfs root.

Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 arch/arm/boot/dts/imx51-babbage.dts |   93 +++++++++++++++++++++++++++++++++++
 arch/arm/mach-mx5/Kconfig           |    8 +++
 arch/arm/mach-mx5/Makefile          |    1 +
 arch/arm/mach-mx5/imx51-dt.c        |   70 ++++++++++++++++++++++++++
 4 files changed, 172 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/boot/dts/imx51-babbage.dts
 create mode 100644 arch/arm/mach-mx5/imx51-dt.c

diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts
new file mode 100644
index 0000000..402cc44
--- /dev/null
+++ b/arch/arm/boot/dts/imx51-babbage.dts
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Freescale i.MX51 Babbage";
+	compatible = "fsl,imx51-babbage", "fsl,imx51";
+	interrupt-parent = <&tzic>;
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+	};
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+	};
+
+	memory {
+		reg = <0x90000000 0x20000000>;
+	};
+
+	tzic: tz-interrupt-controller@e0000000 {
+		compatible = "fsl,imx51-tzic", "fsl,tzic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0xe0000000 0x4000>;
+	};
+
+	aips@70000000 { /* aips-1 */
+		compatible = "fsl,aips-bus", "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x70000000 0x10000000>;
+		ranges;
+
+		spba {
+			compatible = "fsl,spba-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x70000000 0x40000>;
+			ranges;
+
+			uart2: uart@7000c000 {
+				compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+				reg = <0x7000c000 0x4000>;
+				interrupts = <33>;
+				fsl,uart-has-rtscts;
+			};
+		};
+
+		uart0: uart@73fbc000 {
+			compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+			reg = <0x73fbc000 0x4000>;
+			interrupts = <31>;
+			fsl,uart-has-rtscts;
+		};
+
+		uart1: uart@73fc0000 {
+			compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+			reg = <0x73fc0000 0x4000>;
+			interrupts = <32>;
+			fsl,uart-has-rtscts;
+		};
+	};
+
+	aips@80000000 {	/* aips-2 */
+		compatible = "fsl,aips-bus", "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x80000000 0x10000000>;
+		ranges;
+
+		fec@83fec000 {
+			compatible = "fsl,imx51-fec", "fsl,imx27-fec";
+			reg = <0x83fec000 0x4000>;
+			interrupts = <87>;
+			phy-mode = "mii";
+		};
+	};
+};
diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
index 799fbc4..8bdd0c4 100644
--- a/arch/arm/mach-mx5/Kconfig
+++ b/arch/arm/mach-mx5/Kconfig
@@ -62,6 +62,14 @@ endif # ARCH_MX50_SUPPORTED
 if ARCH_MX51
 comment "i.MX51 machines:"
 
+config MACH_IMX51_DT
+	bool "Support i.MX51 platforms from device tree"
+	select SOC_IMX51
+	select USE_OF
+	help
+	  Include support for Freescale i.MX51 based platforms
+	  using the device tree for discovery
+
 config MACH_MX51_BABBAGE
 	bool "Support MX51 BABBAGE platforms"
 	select SOC_IMX51
diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile
index 0b9338c..47b483f 100644
--- a/arch/arm/mach-mx5/Makefile
+++ b/arch/arm/mach-mx5/Makefile
@@ -7,6 +7,7 @@ obj-y   := cpu.o mm.o clock-mx51-mx53.o devices.o ehci.o system.o
 obj-$(CONFIG_SOC_IMX50) += mm-mx50.o
 
 obj-$(CONFIG_CPU_FREQ_IMX)    += cpu_op-mx51.o
+obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o
 obj-$(CONFIG_MACH_MX51_BABBAGE) += board-mx51_babbage.o
 obj-$(CONFIG_MACH_MX51_3DS) += board-mx51_3ds.o
 obj-$(CONFIG_MACH_MX53_EVK) += board-mx53_evk.o
diff --git a/arch/arm/mach-mx5/imx51-dt.c b/arch/arm/mach-mx5/imx51-dt.c
new file mode 100644
index 0000000..8bfdb91
--- /dev/null
+++ b/arch/arm/mach-mx5/imx51-dt.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/irq.h>
+#include <linux/of_platform.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include <mach/common.h>
+#include <mach/mx51.h>
+
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate().  Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART1_BASE_ADDR, "imx-uart.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART2_BASE_ADDR, "imx-uart.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART3_BASE_ADDR, "imx-uart.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-fec", MX51_FEC_BASE_ADDR, "fec.0", NULL),
+	{}
+};
+
+static const struct of_device_id tzic_of_match[] __initconst = {
+	{ .compatible = "fsl,imx51-tzic", },
+	{}
+};
+
+static void __init imx51_dt_init(void)
+{
+	irq_domain_generate_simple(tzic_of_match, MX51_TZIC_BASE_ADDR, 0);
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     imx51_auxdata_lookup, NULL);
+}
+
+static void __init imx51_timer_init(void)
+{
+	mx51_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer imx51_timer = {
+	.init = imx51_timer_init,
+};
+
+static const char *imx51_dt_board_compat[] __initdata = {
+	"fsl,imx51-babbage",
+	NULL
+};
+
+DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
+	.map_io		= mx51_map_io,
+	.init_early	= imx51_init_early,
+	.init_irq	= mx51_init_irq,
+	.timer		= &imx51_timer,
+	.init_machine	= imx51_dt_init,
+	.dt_compat	= imx51_dt_board_compat,
+MACHINE_END
-- 
1.7.4.1

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

* [PATCH v2 5/5] ARM: mx5: add basic device tree support for imx51 babbage
@ 2011-06-24 18:04   ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-06-24 18:04 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds the i.mx51 dt platform with uart and fec support.
It also adds the dts file imx51 babbage, so that we can have a dt
kernel on babbage booting into console with nfs root.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
 arch/arm/boot/dts/imx51-babbage.dts |   93 +++++++++++++++++++++++++++++++++++
 arch/arm/mach-mx5/Kconfig           |    8 +++
 arch/arm/mach-mx5/Makefile          |    1 +
 arch/arm/mach-mx5/imx51-dt.c        |   70 ++++++++++++++++++++++++++
 4 files changed, 172 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/boot/dts/imx51-babbage.dts
 create mode 100644 arch/arm/mach-mx5/imx51-dt.c

diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts
new file mode 100644
index 0000000..402cc44
--- /dev/null
+++ b/arch/arm/boot/dts/imx51-babbage.dts
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Freescale i.MX51 Babbage";
+	compatible = "fsl,imx51-babbage", "fsl,imx51";
+	interrupt-parent = <&tzic>;
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+	};
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+	};
+
+	memory {
+		reg = <0x90000000 0x20000000>;
+	};
+
+	tzic: tz-interrupt-controller at e0000000 {
+		compatible = "fsl,imx51-tzic", "fsl,tzic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0xe0000000 0x4000>;
+	};
+
+	aips at 70000000 { /* aips-1 */
+		compatible = "fsl,aips-bus", "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x70000000 0x10000000>;
+		ranges;
+
+		spba {
+			compatible = "fsl,spba-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x70000000 0x40000>;
+			ranges;
+
+			uart2: uart at 7000c000 {
+				compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+				reg = <0x7000c000 0x4000>;
+				interrupts = <33>;
+				fsl,uart-has-rtscts;
+			};
+		};
+
+		uart0: uart at 73fbc000 {
+			compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+			reg = <0x73fbc000 0x4000>;
+			interrupts = <31>;
+			fsl,uart-has-rtscts;
+		};
+
+		uart1: uart at 73fc0000 {
+			compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+			reg = <0x73fc0000 0x4000>;
+			interrupts = <32>;
+			fsl,uart-has-rtscts;
+		};
+	};
+
+	aips at 80000000 {	/* aips-2 */
+		compatible = "fsl,aips-bus", "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x80000000 0x10000000>;
+		ranges;
+
+		fec at 83fec000 {
+			compatible = "fsl,imx51-fec", "fsl,imx27-fec";
+			reg = <0x83fec000 0x4000>;
+			interrupts = <87>;
+			phy-mode = "mii";
+		};
+	};
+};
diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
index 799fbc4..8bdd0c4 100644
--- a/arch/arm/mach-mx5/Kconfig
+++ b/arch/arm/mach-mx5/Kconfig
@@ -62,6 +62,14 @@ endif # ARCH_MX50_SUPPORTED
 if ARCH_MX51
 comment "i.MX51 machines:"
 
+config MACH_IMX51_DT
+	bool "Support i.MX51 platforms from device tree"
+	select SOC_IMX51
+	select USE_OF
+	help
+	  Include support for Freescale i.MX51 based platforms
+	  using the device tree for discovery
+
 config MACH_MX51_BABBAGE
 	bool "Support MX51 BABBAGE platforms"
 	select SOC_IMX51
diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile
index 0b9338c..47b483f 100644
--- a/arch/arm/mach-mx5/Makefile
+++ b/arch/arm/mach-mx5/Makefile
@@ -7,6 +7,7 @@ obj-y   := cpu.o mm.o clock-mx51-mx53.o devices.o ehci.o system.o
 obj-$(CONFIG_SOC_IMX50) += mm-mx50.o
 
 obj-$(CONFIG_CPU_FREQ_IMX)    += cpu_op-mx51.o
+obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o
 obj-$(CONFIG_MACH_MX51_BABBAGE) += board-mx51_babbage.o
 obj-$(CONFIG_MACH_MX51_3DS) += board-mx51_3ds.o
 obj-$(CONFIG_MACH_MX53_EVK) += board-mx53_evk.o
diff --git a/arch/arm/mach-mx5/imx51-dt.c b/arch/arm/mach-mx5/imx51-dt.c
new file mode 100644
index 0000000..8bfdb91
--- /dev/null
+++ b/arch/arm/mach-mx5/imx51-dt.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/irq.h>
+#include <linux/of_platform.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include <mach/common.h>
+#include <mach/mx51.h>
+
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate().  Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART1_BASE_ADDR, "imx-uart.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART2_BASE_ADDR, "imx-uart.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART3_BASE_ADDR, "imx-uart.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-fec", MX51_FEC_BASE_ADDR, "fec.0", NULL),
+	{}
+};
+
+static const struct of_device_id tzic_of_match[] __initconst = {
+	{ .compatible = "fsl,imx51-tzic", },
+	{}
+};
+
+static void __init imx51_dt_init(void)
+{
+	irq_domain_generate_simple(tzic_of_match, MX51_TZIC_BASE_ADDR, 0);
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     imx51_auxdata_lookup, NULL);
+}
+
+static void __init imx51_timer_init(void)
+{
+	mx51_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer imx51_timer = {
+	.init = imx51_timer_init,
+};
+
+static const char *imx51_dt_board_compat[] __initdata = {
+	"fsl,imx51-babbage",
+	NULL
+};
+
+DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
+	.map_io		= mx51_map_io,
+	.init_early	= imx51_init_early,
+	.init_irq	= mx51_init_irq,
+	.timer		= &imx51_timer,
+	.init_machine	= imx51_dt_init,
+	.dt_compat	= imx51_dt_board_compat,
+MACHINE_END
-- 
1.7.4.1

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

* Re: [PATCH v2 1/5] dt: add of_alias_scan and of_alias_get_id
  2011-06-24 18:04   ` Shawn Guo
  (?)
@ 2011-07-08  9:36     ` Shawn Guo
  -1 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-07-08  9:36 UTC (permalink / raw)
  To: Shawn Guo
  Cc: linux-arm-kernel, patches, netdev, devicetree-discuss,
	linux-kernel, linux-serial

Hi Grant,

I saw neither your comments nor ack on this patch.  Where does it go?

Regards,
Shawn

On Sat, Jun 25, 2011 at 02:04:32AM +0800, Shawn Guo wrote:
> The patch adds function of_alias_scan to populate a global lookup
> table with the properties of 'aliases' node and function
> of_alias_get_id for drivers to find alias id from the lookup table.
> 
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> ---


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

* Re: [PATCH v2 1/5] dt: add of_alias_scan and of_alias_get_id
@ 2011-07-08  9:36     ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-07-08  9:36 UTC (permalink / raw)
  To: Shawn Guo
  Cc: linux-arm-kernel, patches, netdev, devicetree-discuss,
	linux-kernel, linux-serial

Hi Grant,

I saw neither your comments nor ack on this patch.  Where does it go?

Regards,
Shawn

On Sat, Jun 25, 2011 at 02:04:32AM +0800, Shawn Guo wrote:
> The patch adds function of_alias_scan to populate a global lookup
> table with the properties of 'aliases' node and function
> of_alias_get_id for drivers to find alias id from the lookup table.
> 
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> ---


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

* [PATCH v2 1/5] dt: add of_alias_scan and of_alias_get_id
@ 2011-07-08  9:36     ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-07-08  9:36 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Grant,

I saw neither your comments nor ack on this patch.  Where does it go?

Regards,
Shawn

On Sat, Jun 25, 2011 at 02:04:32AM +0800, Shawn Guo wrote:
> The patch adds function of_alias_scan to populate a global lookup
> table with the properties of 'aliases' node and function
> of_alias_get_id for drivers to find alias id from the lookup table.
> 
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> ---

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

* Re: [PATCH v2 1/5] dt: add of_alias_scan and of_alias_get_id
  2011-06-24 18:04   ` Shawn Guo
@ 2011-07-15  2:53     ` Grant Likely
  -1 siblings, 0 replies; 24+ messages in thread
From: Grant Likely @ 2011-07-15  2:53 UTC (permalink / raw)
  To: Shawn Guo
  Cc: linux-arm-kernel, linux-kernel, netdev, linux-serial,
	devicetree-discuss, patches

On Sat, Jun 25, 2011 at 02:04:32AM +0800, Shawn Guo wrote:
> The patch adds function of_alias_scan to populate a global lookup
> table with the properties of 'aliases' node and function
> of_alias_get_id for drivers to find alias id from the lookup table.
> 
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> Cc: Grant Likely <grant.likely@secretlab.ca>

Hey Shawn,

Comments below, but I've gone ahead and fixed them because I'm keen to
get this patch merged.  I just wanted to let you know what I changed.
I'll post the modified version so you can test it.

> ---
>  drivers/of/base.c  |  181 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/of/fdt.c   |    6 ++
>  include/linux/of.h |    7 ++
>  3 files changed, 194 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index 632ebae..89efd10 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -17,14 +17,38 @@
>   *      as published by the Free Software Foundation; either version
>   *      2 of the License, or (at your option) any later version.
>   */
> +#include <linux/bootmem.h>
> +#include <linux/ctype.h>
>  #include <linux/module.h>
>  #include <linux/of.h>
>  #include <linux/spinlock.h>
>  #include <linux/slab.h>
>  #include <linux/proc_fs.h>
>  
> +/**
> + * struct alias_prop - Alias property in 'aliases' node
> + * @link:	List node to link the structure in aliases_lookup list
> + * @alias:	Alias property name
> + * @np:		Pointer to device_node that the alias stands for
> + * @alias_id:	Alias id decoded from alias
> + * @alias_stem:	Alias stem name decoded from alias
> + *
> + * The structure represents one alias property of 'aliases' node as
> + * an entry in aliases_lookup list.
> + */
> +struct alias_prop {
> +	struct list_head link;
> +	const char *alias;
> +	struct device_node *np;
> +	int alias_id;
> +	char alias_stem[0];
> +};
> +
> +static LIST_HEAD(aliases_lookup);
> +
>  struct device_node *allnodes;
>  struct device_node *of_chosen;
> +struct device_node *of_aliases;
>  
>  /* use when traversing tree through the allnext, child, sibling,
>   * or parent members of struct device_node.
> @@ -922,3 +946,160 @@ out_unlock:
>  }
>  #endif /* defined(CONFIG_OF_DYNAMIC) */
>  
> +/*
> + * of_alias_find_available_id - Find an available id for the given device_node

Nit: kerneldoc format is "/**" to start the comment, and function
names should have '()' on it.

> + * @np:		Pointer to the given device_node
> + * @stem:	Alias stem of the given device_node
> + *
> + * The function travels the lookup table to find an available id for the
> + * given device_node with given alias stem.  It returns the id found.
> + */
> +static int of_alias_find_available_id(struct device_node *np, const char *stem)
> +{
> +	struct alias_prop *app;
> +	int id = 0;
> +
> +	while (1) {
> +		bool used = false;
> +		list_for_each_entry(app, &aliases_lookup, link) {
> +			if (!strcmp(app->alias_stem, stem) &&
> +			    app->alias_id == id) {
> +				used = true;
> +				break;
> +			}
> +		}
> +
> +		if (used)
> +			id++;
> +		else
> +			return id;
> +	}
> +}

I've simplified this somewhat to do the list_for_each_entry() only
once, and to bump up the id to +1 the largest entry:

	list_for_each_entry(app, &aliases_lookup, link)
		if ((strcmp(app->stem, stem) == 0) && id <= app->id)
			id = app->id + 1;

.... actually, after looking further, I've rolled this code into the
of_alias_get_id() function.

> +
> +/**
> + * of_alias_lookup_add - Add alias into lookup table
> + * @alias:	Alias name
> + * @id:		Alias id
> + * @stem:	Alias stem name
> + * @np:		Pointer to device_node
> + *
> + * The function adds one alias into the lookup table and populate it
> + * with the info passed in.  It returns 0 in sucess, or error code.
> + */
> +static int of_alias_lookup_add(char *alias, int id, const char *stem,
> +			       struct device_node *np)
> +{
> +	struct alias_prop *app;
> +	size_t sz = sizeof(*app) + strlen(stem) + 1;
> +
> +	app = kzalloc(sz, GFP_KERNEL);
> +	if (!app) {
> +		/*
> +		 * It may fail due to being called by boot code,
> +		 * so try alloc_bootmem before return error.
> +		 */
> +		app = alloc_bootmem(sz);
> +		if (!app)
> +			return -ENOMEM;
> +	}

I'm not too fond of this since we *know* when this is going to be
called from early boot.  So, instead, I've changed the code to use the
already existing dt_alloc functions as an argument to of_alias_lookup_add().

Also, alloc_bootmem() doesn't work on all platforms.
early_init_dt_alloc_memory_arch() needs to be used instead.


> +
> +	app->np = np;
> +	app->alias = alias;
> +	app->alias_id = id;
> +	strcpy(app->alias_stem, stem);
> +	list_add_tail(&app->link, &aliases_lookup);
> +
> +	return 0;
> +}
> +
> +/**
> + * of_alias_decode - Decode alias stem and id from alias name
> + * @alias:	Alias name to be decoded
> + * @stem:	Pointer used to return stem name
> + *
> + * The function decodes alias stem name and alias id from the given
> + * alias name.  It returns stem name via parameter 'stem', and stem id
> + * via the return value.  If no id is found in alias name, it returns 0
> + * as the default.
> + */
> +static int of_alias_decode(char *alias, char *stem)
> +{
> +	int len = strlen(alias);
> +	char *end = alias + len;
> +
> +	while (isdigit(*--end))
> +		len--;

Need to protect against len < 0

> +
> +	strncpy(stem, alias, len);
> +	stem[len] = '\0';
> +
> +	return strlen(++end) ? simple_strtoul(end, NULL, 10) : 0;
> +}
> +
> +/**
> + * of_alias_scan - Scan all properties of 'aliases' node
> + *
> + * The function scans all the properties of 'aliases' node and populate
> + * the the global lookup table with the properties.  It returns the
> + * number of alias_prop found, or error code in error case.
> + */
> +int of_alias_scan(void)

Changed to '__init void of_aliases_scan(void)'.  There is no point in
returning an error code since it is never checked, and there is no
point in bailing on an error just in case it is a problem with only
one alias.

> +{
> +	struct property *pp;
> +	int ret, num = 0;
> +
> +	if (!of_aliases)
> +		return -ENODEV;
> +
> +	for_each_property(pp, of_aliases->properties) {
> +		char stem[32];
> +		int id = of_alias_decode(pp->name, stem);
> +
> +		/* Skip those we do not want to proceed */
> +		if (!strcmp(pp->name, "name") ||
> +		    !strcmp(pp->name, "phandle") ||
> +		    !strcmp(pp->name, "linux,phandle"))
> +			continue;
> +
> +		ret = of_alias_lookup_add(pp->name, id, stem,
> +					  of_find_node_by_path(pp->value));
> +		if (ret < 0)
> +			return ret;
> +		else
> +			num++;
> +	}
> +
> +	return num;
> +}
> +
> +/**
> + * of_alias_get_id - Get alias id for the given device_node
> + * @np:		Pointer to the given device_node
> + * @stem:	Alias stem of the given device_node
> + *
> + * The function travels the lookup table to get alias id for the given
> + * device_node and alias stem.  It returns the alias id if find it.
> + * If not, dynamically creates one in the lookup table and returns it,
> + * or returns error code if fail to create.
> + */
> +int of_alias_get_id(struct device_node *np, const char *stem)
> +{
> +	struct alias_prop *app;
> +	int id = -1;
> +
> +	list_for_each_entry(app, &aliases_lookup, link) {
> +		if (np == app->np) {
> +			id = app->alias_id;
> +			break;
> +		}
> +	}
> +
> +	if (id == -1) {
> +		id = of_alias_find_available_id(np, stem);
> +		if (of_alias_lookup_add(NULL, id, stem, np) < 0)
> +			return -ENODEV;
> +	}
> +
> +	return id;
> +}

This whole function needs to be protected by a mutex.

> +EXPORT_SYMBOL_GPL(of_alias_get_id);
> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> index 65200af..998dc63 100644
> --- a/drivers/of/fdt.c
> +++ b/drivers/of/fdt.c
> @@ -711,6 +711,12 @@ void __init unflatten_device_tree(void)
>  	of_chosen = of_find_node_by_path("/chosen");
>  	if (of_chosen == NULL)
>  		of_chosen = of_find_node_by_path("/chosen@0");
> +
> +	of_aliases = of_find_node_by_path("/aliases");
> +	if (of_aliases == NULL)
> +		of_aliases = of_find_node_by_path("/aliases@0");

I don't think the /aliases@0 variant is necessary.  I've dropped it.

g.

> +
> +	of_alias_scan();
>  }
>  
>  #endif /* CONFIG_OF_EARLY_FLATTREE */
> diff --git a/include/linux/of.h b/include/linux/of.h
> index bfc0ed1..c35cc47 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -68,6 +68,7 @@ struct device_node {
>  /* Pointer for first entry in chain of all nodes. */
>  extern struct device_node *allnodes;
>  extern struct device_node *of_chosen;
> +extern struct device_node *of_aliases;
>  extern rwlock_t devtree_lock;
>  
>  static inline bool of_have_populated_dt(void)
> @@ -201,6 +202,9 @@ extern int of_device_is_available(const struct device_node *device);
>  extern const void *of_get_property(const struct device_node *node,
>  				const char *name,
>  				int *lenp);
> +#define for_each_property(pp, properties) \
> +	for (pp = properties; pp != NULL; pp = pp->next)
> +
>  extern int of_n_addr_cells(struct device_node *np);
>  extern int of_n_size_cells(struct device_node *np);
>  extern const struct of_device_id *of_match_node(
> @@ -213,6 +217,9 @@ extern int of_parse_phandles_with_args(struct device_node *np,
>  	const char *list_name, const char *cells_name, int index,
>  	struct device_node **out_node, const void **out_args);
>  
> +extern int of_alias_scan(void);
> +extern int of_alias_get_id(struct device_node *np, const char *stem);
> +
>  extern int of_machine_is_compatible(const char *compat);
>  
>  extern int prom_add_property(struct device_node* np, struct property* prop);
> -- 
> 1.7.4.1
> 

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

* [PATCH v2 1/5] dt: add of_alias_scan and of_alias_get_id
@ 2011-07-15  2:53     ` Grant Likely
  0 siblings, 0 replies; 24+ messages in thread
From: Grant Likely @ 2011-07-15  2:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Jun 25, 2011 at 02:04:32AM +0800, Shawn Guo wrote:
> The patch adds function of_alias_scan to populate a global lookup
> table with the properties of 'aliases' node and function
> of_alias_get_id for drivers to find alias id from the lookup table.
> 
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> Cc: Grant Likely <grant.likely@secretlab.ca>

Hey Shawn,

Comments below, but I've gone ahead and fixed them because I'm keen to
get this patch merged.  I just wanted to let you know what I changed.
I'll post the modified version so you can test it.

> ---
>  drivers/of/base.c  |  181 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/of/fdt.c   |    6 ++
>  include/linux/of.h |    7 ++
>  3 files changed, 194 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index 632ebae..89efd10 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -17,14 +17,38 @@
>   *      as published by the Free Software Foundation; either version
>   *      2 of the License, or (at your option) any later version.
>   */
> +#include <linux/bootmem.h>
> +#include <linux/ctype.h>
>  #include <linux/module.h>
>  #include <linux/of.h>
>  #include <linux/spinlock.h>
>  #include <linux/slab.h>
>  #include <linux/proc_fs.h>
>  
> +/**
> + * struct alias_prop - Alias property in 'aliases' node
> + * @link:	List node to link the structure in aliases_lookup list
> + * @alias:	Alias property name
> + * @np:		Pointer to device_node that the alias stands for
> + * @alias_id:	Alias id decoded from alias
> + * @alias_stem:	Alias stem name decoded from alias
> + *
> + * The structure represents one alias property of 'aliases' node as
> + * an entry in aliases_lookup list.
> + */
> +struct alias_prop {
> +	struct list_head link;
> +	const char *alias;
> +	struct device_node *np;
> +	int alias_id;
> +	char alias_stem[0];
> +};
> +
> +static LIST_HEAD(aliases_lookup);
> +
>  struct device_node *allnodes;
>  struct device_node *of_chosen;
> +struct device_node *of_aliases;
>  
>  /* use when traversing tree through the allnext, child, sibling,
>   * or parent members of struct device_node.
> @@ -922,3 +946,160 @@ out_unlock:
>  }
>  #endif /* defined(CONFIG_OF_DYNAMIC) */
>  
> +/*
> + * of_alias_find_available_id - Find an available id for the given device_node

Nit: kerneldoc format is "/**" to start the comment, and function
names should have '()' on it.

> + * @np:		Pointer to the given device_node
> + * @stem:	Alias stem of the given device_node
> + *
> + * The function travels the lookup table to find an available id for the
> + * given device_node with given alias stem.  It returns the id found.
> + */
> +static int of_alias_find_available_id(struct device_node *np, const char *stem)
> +{
> +	struct alias_prop *app;
> +	int id = 0;
> +
> +	while (1) {
> +		bool used = false;
> +		list_for_each_entry(app, &aliases_lookup, link) {
> +			if (!strcmp(app->alias_stem, stem) &&
> +			    app->alias_id == id) {
> +				used = true;
> +				break;
> +			}
> +		}
> +
> +		if (used)
> +			id++;
> +		else
> +			return id;
> +	}
> +}

I've simplified this somewhat to do the list_for_each_entry() only
once, and to bump up the id to +1 the largest entry:

	list_for_each_entry(app, &aliases_lookup, link)
		if ((strcmp(app->stem, stem) == 0) && id <= app->id)
			id = app->id + 1;

.... actually, after looking further, I've rolled this code into the
of_alias_get_id() function.

> +
> +/**
> + * of_alias_lookup_add - Add alias into lookup table
> + * @alias:	Alias name
> + * @id:		Alias id
> + * @stem:	Alias stem name
> + * @np:		Pointer to device_node
> + *
> + * The function adds one alias into the lookup table and populate it
> + * with the info passed in.  It returns 0 in sucess, or error code.
> + */
> +static int of_alias_lookup_add(char *alias, int id, const char *stem,
> +			       struct device_node *np)
> +{
> +	struct alias_prop *app;
> +	size_t sz = sizeof(*app) + strlen(stem) + 1;
> +
> +	app = kzalloc(sz, GFP_KERNEL);
> +	if (!app) {
> +		/*
> +		 * It may fail due to being called by boot code,
> +		 * so try alloc_bootmem before return error.
> +		 */
> +		app = alloc_bootmem(sz);
> +		if (!app)
> +			return -ENOMEM;
> +	}

I'm not too fond of this since we *know* when this is going to be
called from early boot.  So, instead, I've changed the code to use the
already existing dt_alloc functions as an argument to of_alias_lookup_add().

Also, alloc_bootmem() doesn't work on all platforms.
early_init_dt_alloc_memory_arch() needs to be used instead.


> +
> +	app->np = np;
> +	app->alias = alias;
> +	app->alias_id = id;
> +	strcpy(app->alias_stem, stem);
> +	list_add_tail(&app->link, &aliases_lookup);
> +
> +	return 0;
> +}
> +
> +/**
> + * of_alias_decode - Decode alias stem and id from alias name
> + * @alias:	Alias name to be decoded
> + * @stem:	Pointer used to return stem name
> + *
> + * The function decodes alias stem name and alias id from the given
> + * alias name.  It returns stem name via parameter 'stem', and stem id
> + * via the return value.  If no id is found in alias name, it returns 0
> + * as the default.
> + */
> +static int of_alias_decode(char *alias, char *stem)
> +{
> +	int len = strlen(alias);
> +	char *end = alias + len;
> +
> +	while (isdigit(*--end))
> +		len--;

Need to protect against len < 0

> +
> +	strncpy(stem, alias, len);
> +	stem[len] = '\0';
> +
> +	return strlen(++end) ? simple_strtoul(end, NULL, 10) : 0;
> +}
> +
> +/**
> + * of_alias_scan - Scan all properties of 'aliases' node
> + *
> + * The function scans all the properties of 'aliases' node and populate
> + * the the global lookup table with the properties.  It returns the
> + * number of alias_prop found, or error code in error case.
> + */
> +int of_alias_scan(void)

Changed to '__init void of_aliases_scan(void)'.  There is no point in
returning an error code since it is never checked, and there is no
point in bailing on an error just in case it is a problem with only
one alias.

> +{
> +	struct property *pp;
> +	int ret, num = 0;
> +
> +	if (!of_aliases)
> +		return -ENODEV;
> +
> +	for_each_property(pp, of_aliases->properties) {
> +		char stem[32];
> +		int id = of_alias_decode(pp->name, stem);
> +
> +		/* Skip those we do not want to proceed */
> +		if (!strcmp(pp->name, "name") ||
> +		    !strcmp(pp->name, "phandle") ||
> +		    !strcmp(pp->name, "linux,phandle"))
> +			continue;
> +
> +		ret = of_alias_lookup_add(pp->name, id, stem,
> +					  of_find_node_by_path(pp->value));
> +		if (ret < 0)
> +			return ret;
> +		else
> +			num++;
> +	}
> +
> +	return num;
> +}
> +
> +/**
> + * of_alias_get_id - Get alias id for the given device_node
> + * @np:		Pointer to the given device_node
> + * @stem:	Alias stem of the given device_node
> + *
> + * The function travels the lookup table to get alias id for the given
> + * device_node and alias stem.  It returns the alias id if find it.
> + * If not, dynamically creates one in the lookup table and returns it,
> + * or returns error code if fail to create.
> + */
> +int of_alias_get_id(struct device_node *np, const char *stem)
> +{
> +	struct alias_prop *app;
> +	int id = -1;
> +
> +	list_for_each_entry(app, &aliases_lookup, link) {
> +		if (np == app->np) {
> +			id = app->alias_id;
> +			break;
> +		}
> +	}
> +
> +	if (id == -1) {
> +		id = of_alias_find_available_id(np, stem);
> +		if (of_alias_lookup_add(NULL, id, stem, np) < 0)
> +			return -ENODEV;
> +	}
> +
> +	return id;
> +}

This whole function needs to be protected by a mutex.

> +EXPORT_SYMBOL_GPL(of_alias_get_id);
> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> index 65200af..998dc63 100644
> --- a/drivers/of/fdt.c
> +++ b/drivers/of/fdt.c
> @@ -711,6 +711,12 @@ void __init unflatten_device_tree(void)
>  	of_chosen = of_find_node_by_path("/chosen");
>  	if (of_chosen == NULL)
>  		of_chosen = of_find_node_by_path("/chosen at 0");
> +
> +	of_aliases = of_find_node_by_path("/aliases");
> +	if (of_aliases == NULL)
> +		of_aliases = of_find_node_by_path("/aliases at 0");

I don't think the /aliases at 0 variant is necessary.  I've dropped it.

g.

> +
> +	of_alias_scan();
>  }
>  
>  #endif /* CONFIG_OF_EARLY_FLATTREE */
> diff --git a/include/linux/of.h b/include/linux/of.h
> index bfc0ed1..c35cc47 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -68,6 +68,7 @@ struct device_node {
>  /* Pointer for first entry in chain of all nodes. */
>  extern struct device_node *allnodes;
>  extern struct device_node *of_chosen;
> +extern struct device_node *of_aliases;
>  extern rwlock_t devtree_lock;
>  
>  static inline bool of_have_populated_dt(void)
> @@ -201,6 +202,9 @@ extern int of_device_is_available(const struct device_node *device);
>  extern const void *of_get_property(const struct device_node *node,
>  				const char *name,
>  				int *lenp);
> +#define for_each_property(pp, properties) \
> +	for (pp = properties; pp != NULL; pp = pp->next)
> +
>  extern int of_n_addr_cells(struct device_node *np);
>  extern int of_n_size_cells(struct device_node *np);
>  extern const struct of_device_id *of_match_node(
> @@ -213,6 +217,9 @@ extern int of_parse_phandles_with_args(struct device_node *np,
>  	const char *list_name, const char *cells_name, int index,
>  	struct device_node **out_node, const void **out_args);
>  
> +extern int of_alias_scan(void);
> +extern int of_alias_get_id(struct device_node *np, const char *stem);
> +
>  extern int of_machine_is_compatible(const char *compat);
>  
>  extern int prom_add_property(struct device_node* np, struct property* prop);
> -- 
> 1.7.4.1
> 

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

* Re: [PATCH v2 1/5] dt: add of_alias_scan and of_alias_get_id
@ 2011-07-15 15:24       ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-07-15 15:24 UTC (permalink / raw)
  To: Grant Likely
  Cc: Shawn Guo, linux-arm-kernel, linux-kernel, netdev, linux-serial,
	devicetree-discuss, patches

On Thu, Jul 14, 2011 at 08:53:20PM -0600, Grant Likely wrote:
> On Sat, Jun 25, 2011 at 02:04:32AM +0800, Shawn Guo wrote:
> > The patch adds function of_alias_scan to populate a global lookup
> > table with the properties of 'aliases' node and function
> > of_alias_get_id for drivers to find alias id from the lookup table.
> > 
> > Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> > Cc: Grant Likely <grant.likely@secretlab.ca>
> 
> Hey Shawn,
> 
> Comments below, but I've gone ahead and fixed them because I'm keen to
> get this patch merged.  I just wanted to let you know what I changed.
> I'll post the modified version so you can test it.
> 
Thanks for doing this.  It makes the wheel spin fast.  I respect
changes you made, and will give it a test once you post it.

Regards,
Shawn

> > ---
> >  drivers/of/base.c  |  181 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  drivers/of/fdt.c   |    6 ++
> >  include/linux/of.h |    7 ++
> >  3 files changed, 194 insertions(+), 0 deletions(-)
> > 
> > diff --git a/drivers/of/base.c b/drivers/of/base.c
> > index 632ebae..89efd10 100644
> > --- a/drivers/of/base.c
> > +++ b/drivers/of/base.c
> > @@ -17,14 +17,38 @@
> >   *      as published by the Free Software Foundation; either version
> >   *      2 of the License, or (at your option) any later version.
> >   */
> > +#include <linux/bootmem.h>
> > +#include <linux/ctype.h>
> >  #include <linux/module.h>
> >  #include <linux/of.h>
> >  #include <linux/spinlock.h>
> >  #include <linux/slab.h>
> >  #include <linux/proc_fs.h>
> >  
> > +/**
> > + * struct alias_prop - Alias property in 'aliases' node
> > + * @link:	List node to link the structure in aliases_lookup list
> > + * @alias:	Alias property name
> > + * @np:		Pointer to device_node that the alias stands for
> > + * @alias_id:	Alias id decoded from alias
> > + * @alias_stem:	Alias stem name decoded from alias
> > + *
> > + * The structure represents one alias property of 'aliases' node as
> > + * an entry in aliases_lookup list.
> > + */
> > +struct alias_prop {
> > +	struct list_head link;
> > +	const char *alias;
> > +	struct device_node *np;
> > +	int alias_id;
> > +	char alias_stem[0];
> > +};
> > +
> > +static LIST_HEAD(aliases_lookup);
> > +
> >  struct device_node *allnodes;
> >  struct device_node *of_chosen;
> > +struct device_node *of_aliases;
> >  
> >  /* use when traversing tree through the allnext, child, sibling,
> >   * or parent members of struct device_node.
> > @@ -922,3 +946,160 @@ out_unlock:
> >  }
> >  #endif /* defined(CONFIG_OF_DYNAMIC) */
> >  
> > +/*
> > + * of_alias_find_available_id - Find an available id for the given device_node
> 
> Nit: kerneldoc format is "/**" to start the comment, and function
> names should have '()' on it.
> 
> > + * @np:		Pointer to the given device_node
> > + * @stem:	Alias stem of the given device_node
> > + *
> > + * The function travels the lookup table to find an available id for the
> > + * given device_node with given alias stem.  It returns the id found.
> > + */
> > +static int of_alias_find_available_id(struct device_node *np, const char *stem)
> > +{
> > +	struct alias_prop *app;
> > +	int id = 0;
> > +
> > +	while (1) {
> > +		bool used = false;
> > +		list_for_each_entry(app, &aliases_lookup, link) {
> > +			if (!strcmp(app->alias_stem, stem) &&
> > +			    app->alias_id == id) {
> > +				used = true;
> > +				break;
> > +			}
> > +		}
> > +
> > +		if (used)
> > +			id++;
> > +		else
> > +			return id;
> > +	}
> > +}
> 
> I've simplified this somewhat to do the list_for_each_entry() only
> once, and to bump up the id to +1 the largest entry:
> 
> 	list_for_each_entry(app, &aliases_lookup, link)
> 		if ((strcmp(app->stem, stem) == 0) && id <= app->id)
> 			id = app->id + 1;
> 
> .... actually, after looking further, I've rolled this code into the
> of_alias_get_id() function.
> 
> > +
> > +/**
> > + * of_alias_lookup_add - Add alias into lookup table
> > + * @alias:	Alias name
> > + * @id:		Alias id
> > + * @stem:	Alias stem name
> > + * @np:		Pointer to device_node
> > + *
> > + * The function adds one alias into the lookup table and populate it
> > + * with the info passed in.  It returns 0 in sucess, or error code.
> > + */
> > +static int of_alias_lookup_add(char *alias, int id, const char *stem,
> > +			       struct device_node *np)
> > +{
> > +	struct alias_prop *app;
> > +	size_t sz = sizeof(*app) + strlen(stem) + 1;
> > +
> > +	app = kzalloc(sz, GFP_KERNEL);
> > +	if (!app) {
> > +		/*
> > +		 * It may fail due to being called by boot code,
> > +		 * so try alloc_bootmem before return error.
> > +		 */
> > +		app = alloc_bootmem(sz);
> > +		if (!app)
> > +			return -ENOMEM;
> > +	}
> 
> I'm not too fond of this since we *know* when this is going to be
> called from early boot.  So, instead, I've changed the code to use the
> already existing dt_alloc functions as an argument to of_alias_lookup_add().
> 
> Also, alloc_bootmem() doesn't work on all platforms.
> early_init_dt_alloc_memory_arch() needs to be used instead.
> 
> 
> > +
> > +	app->np = np;
> > +	app->alias = alias;
> > +	app->alias_id = id;
> > +	strcpy(app->alias_stem, stem);
> > +	list_add_tail(&app->link, &aliases_lookup);
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * of_alias_decode - Decode alias stem and id from alias name
> > + * @alias:	Alias name to be decoded
> > + * @stem:	Pointer used to return stem name
> > + *
> > + * The function decodes alias stem name and alias id from the given
> > + * alias name.  It returns stem name via parameter 'stem', and stem id
> > + * via the return value.  If no id is found in alias name, it returns 0
> > + * as the default.
> > + */
> > +static int of_alias_decode(char *alias, char *stem)
> > +{
> > +	int len = strlen(alias);
> > +	char *end = alias + len;
> > +
> > +	while (isdigit(*--end))
> > +		len--;
> 
> Need to protect against len < 0
> 
> > +
> > +	strncpy(stem, alias, len);
> > +	stem[len] = '\0';
> > +
> > +	return strlen(++end) ? simple_strtoul(end, NULL, 10) : 0;
> > +}
> > +
> > +/**
> > + * of_alias_scan - Scan all properties of 'aliases' node
> > + *
> > + * The function scans all the properties of 'aliases' node and populate
> > + * the the global lookup table with the properties.  It returns the
> > + * number of alias_prop found, or error code in error case.
> > + */
> > +int of_alias_scan(void)
> 
> Changed to '__init void of_aliases_scan(void)'.  There is no point in
> returning an error code since it is never checked, and there is no
> point in bailing on an error just in case it is a problem with only
> one alias.
> 
> > +{
> > +	struct property *pp;
> > +	int ret, num = 0;
> > +
> > +	if (!of_aliases)
> > +		return -ENODEV;
> > +
> > +	for_each_property(pp, of_aliases->properties) {
> > +		char stem[32];
> > +		int id = of_alias_decode(pp->name, stem);
> > +
> > +		/* Skip those we do not want to proceed */
> > +		if (!strcmp(pp->name, "name") ||
> > +		    !strcmp(pp->name, "phandle") ||
> > +		    !strcmp(pp->name, "linux,phandle"))
> > +			continue;
> > +
> > +		ret = of_alias_lookup_add(pp->name, id, stem,
> > +					  of_find_node_by_path(pp->value));
> > +		if (ret < 0)
> > +			return ret;
> > +		else
> > +			num++;
> > +	}
> > +
> > +	return num;
> > +}
> > +
> > +/**
> > + * of_alias_get_id - Get alias id for the given device_node
> > + * @np:		Pointer to the given device_node
> > + * @stem:	Alias stem of the given device_node
> > + *
> > + * The function travels the lookup table to get alias id for the given
> > + * device_node and alias stem.  It returns the alias id if find it.
> > + * If not, dynamically creates one in the lookup table and returns it,
> > + * or returns error code if fail to create.
> > + */
> > +int of_alias_get_id(struct device_node *np, const char *stem)
> > +{
> > +	struct alias_prop *app;
> > +	int id = -1;
> > +
> > +	list_for_each_entry(app, &aliases_lookup, link) {
> > +		if (np == app->np) {
> > +			id = app->alias_id;
> > +			break;
> > +		}
> > +	}
> > +
> > +	if (id == -1) {
> > +		id = of_alias_find_available_id(np, stem);
> > +		if (of_alias_lookup_add(NULL, id, stem, np) < 0)
> > +			return -ENODEV;
> > +	}
> > +
> > +	return id;
> > +}
> 
> This whole function needs to be protected by a mutex.
> 
> > +EXPORT_SYMBOL_GPL(of_alias_get_id);
> > diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> > index 65200af..998dc63 100644
> > --- a/drivers/of/fdt.c
> > +++ b/drivers/of/fdt.c
> > @@ -711,6 +711,12 @@ void __init unflatten_device_tree(void)
> >  	of_chosen = of_find_node_by_path("/chosen");
> >  	if (of_chosen == NULL)
> >  		of_chosen = of_find_node_by_path("/chosen@0");
> > +
> > +	of_aliases = of_find_node_by_path("/aliases");
> > +	if (of_aliases == NULL)
> > +		of_aliases = of_find_node_by_path("/aliases@0");
> 
> I don't think the /aliases@0 variant is necessary.  I've dropped it.
> 
> g.
> 
> > +
> > +	of_alias_scan();
> >  }
> >  
> >  #endif /* CONFIG_OF_EARLY_FLATTREE */
> > diff --git a/include/linux/of.h b/include/linux/of.h
> > index bfc0ed1..c35cc47 100644
> > --- a/include/linux/of.h
> > +++ b/include/linux/of.h
> > @@ -68,6 +68,7 @@ struct device_node {
> >  /* Pointer for first entry in chain of all nodes. */
> >  extern struct device_node *allnodes;
> >  extern struct device_node *of_chosen;
> > +extern struct device_node *of_aliases;
> >  extern rwlock_t devtree_lock;
> >  
> >  static inline bool of_have_populated_dt(void)
> > @@ -201,6 +202,9 @@ extern int of_device_is_available(const struct device_node *device);
> >  extern const void *of_get_property(const struct device_node *node,
> >  				const char *name,
> >  				int *lenp);
> > +#define for_each_property(pp, properties) \
> > +	for (pp = properties; pp != NULL; pp = pp->next)
> > +
> >  extern int of_n_addr_cells(struct device_node *np);
> >  extern int of_n_size_cells(struct device_node *np);
> >  extern const struct of_device_id *of_match_node(
> > @@ -213,6 +217,9 @@ extern int of_parse_phandles_with_args(struct device_node *np,
> >  	const char *list_name, const char *cells_name, int index,
> >  	struct device_node **out_node, const void **out_args);
> >  
> > +extern int of_alias_scan(void);
> > +extern int of_alias_get_id(struct device_node *np, const char *stem);
> > +
> >  extern int of_machine_is_compatible(const char *compat);
> >  
> >  extern int prom_add_property(struct device_node* np, struct property* prop);
> > -- 
> > 1.7.4.1
> > 
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


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

* Re: [PATCH v2 1/5] dt: add of_alias_scan and of_alias_get_id
@ 2011-07-15 15:24       ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-07-15 15:24 UTC (permalink / raw)
  To: Grant Likely
  Cc: patches-QSEj5FYQhm4dnm+yROfE0A, netdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On Thu, Jul 14, 2011 at 08:53:20PM -0600, Grant Likely wrote:
> On Sat, Jun 25, 2011 at 02:04:32AM +0800, Shawn Guo wrote:
> > The patch adds function of_alias_scan to populate a global lookup
> > table with the properties of 'aliases' node and function
> > of_alias_get_id for drivers to find alias id from the lookup table.
> > 
> > Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> > Cc: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> 
> Hey Shawn,
> 
> Comments below, but I've gone ahead and fixed them because I'm keen to
> get this patch merged.  I just wanted to let you know what I changed.
> I'll post the modified version so you can test it.
> 
Thanks for doing this.  It makes the wheel spin fast.  I respect
changes you made, and will give it a test once you post it.

Regards,
Shawn

> > ---
> >  drivers/of/base.c  |  181 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  drivers/of/fdt.c   |    6 ++
> >  include/linux/of.h |    7 ++
> >  3 files changed, 194 insertions(+), 0 deletions(-)
> > 
> > diff --git a/drivers/of/base.c b/drivers/of/base.c
> > index 632ebae..89efd10 100644
> > --- a/drivers/of/base.c
> > +++ b/drivers/of/base.c
> > @@ -17,14 +17,38 @@
> >   *      as published by the Free Software Foundation; either version
> >   *      2 of the License, or (at your option) any later version.
> >   */
> > +#include <linux/bootmem.h>
> > +#include <linux/ctype.h>
> >  #include <linux/module.h>
> >  #include <linux/of.h>
> >  #include <linux/spinlock.h>
> >  #include <linux/slab.h>
> >  #include <linux/proc_fs.h>
> >  
> > +/**
> > + * struct alias_prop - Alias property in 'aliases' node
> > + * @link:	List node to link the structure in aliases_lookup list
> > + * @alias:	Alias property name
> > + * @np:		Pointer to device_node that the alias stands for
> > + * @alias_id:	Alias id decoded from alias
> > + * @alias_stem:	Alias stem name decoded from alias
> > + *
> > + * The structure represents one alias property of 'aliases' node as
> > + * an entry in aliases_lookup list.
> > + */
> > +struct alias_prop {
> > +	struct list_head link;
> > +	const char *alias;
> > +	struct device_node *np;
> > +	int alias_id;
> > +	char alias_stem[0];
> > +};
> > +
> > +static LIST_HEAD(aliases_lookup);
> > +
> >  struct device_node *allnodes;
> >  struct device_node *of_chosen;
> > +struct device_node *of_aliases;
> >  
> >  /* use when traversing tree through the allnext, child, sibling,
> >   * or parent members of struct device_node.
> > @@ -922,3 +946,160 @@ out_unlock:
> >  }
> >  #endif /* defined(CONFIG_OF_DYNAMIC) */
> >  
> > +/*
> > + * of_alias_find_available_id - Find an available id for the given device_node
> 
> Nit: kerneldoc format is "/**" to start the comment, and function
> names should have '()' on it.
> 
> > + * @np:		Pointer to the given device_node
> > + * @stem:	Alias stem of the given device_node
> > + *
> > + * The function travels the lookup table to find an available id for the
> > + * given device_node with given alias stem.  It returns the id found.
> > + */
> > +static int of_alias_find_available_id(struct device_node *np, const char *stem)
> > +{
> > +	struct alias_prop *app;
> > +	int id = 0;
> > +
> > +	while (1) {
> > +		bool used = false;
> > +		list_for_each_entry(app, &aliases_lookup, link) {
> > +			if (!strcmp(app->alias_stem, stem) &&
> > +			    app->alias_id == id) {
> > +				used = true;
> > +				break;
> > +			}
> > +		}
> > +
> > +		if (used)
> > +			id++;
> > +		else
> > +			return id;
> > +	}
> > +}
> 
> I've simplified this somewhat to do the list_for_each_entry() only
> once, and to bump up the id to +1 the largest entry:
> 
> 	list_for_each_entry(app, &aliases_lookup, link)
> 		if ((strcmp(app->stem, stem) == 0) && id <= app->id)
> 			id = app->id + 1;
> 
> .... actually, after looking further, I've rolled this code into the
> of_alias_get_id() function.
> 
> > +
> > +/**
> > + * of_alias_lookup_add - Add alias into lookup table
> > + * @alias:	Alias name
> > + * @id:		Alias id
> > + * @stem:	Alias stem name
> > + * @np:		Pointer to device_node
> > + *
> > + * The function adds one alias into the lookup table and populate it
> > + * with the info passed in.  It returns 0 in sucess, or error code.
> > + */
> > +static int of_alias_lookup_add(char *alias, int id, const char *stem,
> > +			       struct device_node *np)
> > +{
> > +	struct alias_prop *app;
> > +	size_t sz = sizeof(*app) + strlen(stem) + 1;
> > +
> > +	app = kzalloc(sz, GFP_KERNEL);
> > +	if (!app) {
> > +		/*
> > +		 * It may fail due to being called by boot code,
> > +		 * so try alloc_bootmem before return error.
> > +		 */
> > +		app = alloc_bootmem(sz);
> > +		if (!app)
> > +			return -ENOMEM;
> > +	}
> 
> I'm not too fond of this since we *know* when this is going to be
> called from early boot.  So, instead, I've changed the code to use the
> already existing dt_alloc functions as an argument to of_alias_lookup_add().
> 
> Also, alloc_bootmem() doesn't work on all platforms.
> early_init_dt_alloc_memory_arch() needs to be used instead.
> 
> 
> > +
> > +	app->np = np;
> > +	app->alias = alias;
> > +	app->alias_id = id;
> > +	strcpy(app->alias_stem, stem);
> > +	list_add_tail(&app->link, &aliases_lookup);
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * of_alias_decode - Decode alias stem and id from alias name
> > + * @alias:	Alias name to be decoded
> > + * @stem:	Pointer used to return stem name
> > + *
> > + * The function decodes alias stem name and alias id from the given
> > + * alias name.  It returns stem name via parameter 'stem', and stem id
> > + * via the return value.  If no id is found in alias name, it returns 0
> > + * as the default.
> > + */
> > +static int of_alias_decode(char *alias, char *stem)
> > +{
> > +	int len = strlen(alias);
> > +	char *end = alias + len;
> > +
> > +	while (isdigit(*--end))
> > +		len--;
> 
> Need to protect against len < 0
> 
> > +
> > +	strncpy(stem, alias, len);
> > +	stem[len] = '\0';
> > +
> > +	return strlen(++end) ? simple_strtoul(end, NULL, 10) : 0;
> > +}
> > +
> > +/**
> > + * of_alias_scan - Scan all properties of 'aliases' node
> > + *
> > + * The function scans all the properties of 'aliases' node and populate
> > + * the the global lookup table with the properties.  It returns the
> > + * number of alias_prop found, or error code in error case.
> > + */
> > +int of_alias_scan(void)
> 
> Changed to '__init void of_aliases_scan(void)'.  There is no point in
> returning an error code since it is never checked, and there is no
> point in bailing on an error just in case it is a problem with only
> one alias.
> 
> > +{
> > +	struct property *pp;
> > +	int ret, num = 0;
> > +
> > +	if (!of_aliases)
> > +		return -ENODEV;
> > +
> > +	for_each_property(pp, of_aliases->properties) {
> > +		char stem[32];
> > +		int id = of_alias_decode(pp->name, stem);
> > +
> > +		/* Skip those we do not want to proceed */
> > +		if (!strcmp(pp->name, "name") ||
> > +		    !strcmp(pp->name, "phandle") ||
> > +		    !strcmp(pp->name, "linux,phandle"))
> > +			continue;
> > +
> > +		ret = of_alias_lookup_add(pp->name, id, stem,
> > +					  of_find_node_by_path(pp->value));
> > +		if (ret < 0)
> > +			return ret;
> > +		else
> > +			num++;
> > +	}
> > +
> > +	return num;
> > +}
> > +
> > +/**
> > + * of_alias_get_id - Get alias id for the given device_node
> > + * @np:		Pointer to the given device_node
> > + * @stem:	Alias stem of the given device_node
> > + *
> > + * The function travels the lookup table to get alias id for the given
> > + * device_node and alias stem.  It returns the alias id if find it.
> > + * If not, dynamically creates one in the lookup table and returns it,
> > + * or returns error code if fail to create.
> > + */
> > +int of_alias_get_id(struct device_node *np, const char *stem)
> > +{
> > +	struct alias_prop *app;
> > +	int id = -1;
> > +
> > +	list_for_each_entry(app, &aliases_lookup, link) {
> > +		if (np == app->np) {
> > +			id = app->alias_id;
> > +			break;
> > +		}
> > +	}
> > +
> > +	if (id == -1) {
> > +		id = of_alias_find_available_id(np, stem);
> > +		if (of_alias_lookup_add(NULL, id, stem, np) < 0)
> > +			return -ENODEV;
> > +	}
> > +
> > +	return id;
> > +}
> 
> This whole function needs to be protected by a mutex.
> 
> > +EXPORT_SYMBOL_GPL(of_alias_get_id);
> > diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> > index 65200af..998dc63 100644
> > --- a/drivers/of/fdt.c
> > +++ b/drivers/of/fdt.c
> > @@ -711,6 +711,12 @@ void __init unflatten_device_tree(void)
> >  	of_chosen = of_find_node_by_path("/chosen");
> >  	if (of_chosen == NULL)
> >  		of_chosen = of_find_node_by_path("/chosen@0");
> > +
> > +	of_aliases = of_find_node_by_path("/aliases");
> > +	if (of_aliases == NULL)
> > +		of_aliases = of_find_node_by_path("/aliases@0");
> 
> I don't think the /aliases@0 variant is necessary.  I've dropped it.
> 
> g.
> 
> > +
> > +	of_alias_scan();
> >  }
> >  
> >  #endif /* CONFIG_OF_EARLY_FLATTREE */
> > diff --git a/include/linux/of.h b/include/linux/of.h
> > index bfc0ed1..c35cc47 100644
> > --- a/include/linux/of.h
> > +++ b/include/linux/of.h
> > @@ -68,6 +68,7 @@ struct device_node {
> >  /* Pointer for first entry in chain of all nodes. */
> >  extern struct device_node *allnodes;
> >  extern struct device_node *of_chosen;
> > +extern struct device_node *of_aliases;
> >  extern rwlock_t devtree_lock;
> >  
> >  static inline bool of_have_populated_dt(void)
> > @@ -201,6 +202,9 @@ extern int of_device_is_available(const struct device_node *device);
> >  extern const void *of_get_property(const struct device_node *node,
> >  				const char *name,
> >  				int *lenp);
> > +#define for_each_property(pp, properties) \
> > +	for (pp = properties; pp != NULL; pp = pp->next)
> > +
> >  extern int of_n_addr_cells(struct device_node *np);
> >  extern int of_n_size_cells(struct device_node *np);
> >  extern const struct of_device_id *of_match_node(
> > @@ -213,6 +217,9 @@ extern int of_parse_phandles_with_args(struct device_node *np,
> >  	const char *list_name, const char *cells_name, int index,
> >  	struct device_node **out_node, const void **out_args);
> >  
> > +extern int of_alias_scan(void);
> > +extern int of_alias_get_id(struct device_node *np, const char *stem);
> > +
> >  extern int of_machine_is_compatible(const char *compat);
> >  
> >  extern int prom_add_property(struct device_node* np, struct property* prop);
> > -- 
> > 1.7.4.1
> > 
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" 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] 24+ messages in thread

* [PATCH v2 1/5] dt: add of_alias_scan and of_alias_get_id
@ 2011-07-15 15:24       ` Shawn Guo
  0 siblings, 0 replies; 24+ messages in thread
From: Shawn Guo @ 2011-07-15 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jul 14, 2011 at 08:53:20PM -0600, Grant Likely wrote:
> On Sat, Jun 25, 2011 at 02:04:32AM +0800, Shawn Guo wrote:
> > The patch adds function of_alias_scan to populate a global lookup
> > table with the properties of 'aliases' node and function
> > of_alias_get_id for drivers to find alias id from the lookup table.
> > 
> > Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> > Cc: Grant Likely <grant.likely@secretlab.ca>
> 
> Hey Shawn,
> 
> Comments below, but I've gone ahead and fixed them because I'm keen to
> get this patch merged.  I just wanted to let you know what I changed.
> I'll post the modified version so you can test it.
> 
Thanks for doing this.  It makes the wheel spin fast.  I respect
changes you made, and will give it a test once you post it.

Regards,
Shawn

> > ---
> >  drivers/of/base.c  |  181 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  drivers/of/fdt.c   |    6 ++
> >  include/linux/of.h |    7 ++
> >  3 files changed, 194 insertions(+), 0 deletions(-)
> > 
> > diff --git a/drivers/of/base.c b/drivers/of/base.c
> > index 632ebae..89efd10 100644
> > --- a/drivers/of/base.c
> > +++ b/drivers/of/base.c
> > @@ -17,14 +17,38 @@
> >   *      as published by the Free Software Foundation; either version
> >   *      2 of the License, or (at your option) any later version.
> >   */
> > +#include <linux/bootmem.h>
> > +#include <linux/ctype.h>
> >  #include <linux/module.h>
> >  #include <linux/of.h>
> >  #include <linux/spinlock.h>
> >  #include <linux/slab.h>
> >  #include <linux/proc_fs.h>
> >  
> > +/**
> > + * struct alias_prop - Alias property in 'aliases' node
> > + * @link:	List node to link the structure in aliases_lookup list
> > + * @alias:	Alias property name
> > + * @np:		Pointer to device_node that the alias stands for
> > + * @alias_id:	Alias id decoded from alias
> > + * @alias_stem:	Alias stem name decoded from alias
> > + *
> > + * The structure represents one alias property of 'aliases' node as
> > + * an entry in aliases_lookup list.
> > + */
> > +struct alias_prop {
> > +	struct list_head link;
> > +	const char *alias;
> > +	struct device_node *np;
> > +	int alias_id;
> > +	char alias_stem[0];
> > +};
> > +
> > +static LIST_HEAD(aliases_lookup);
> > +
> >  struct device_node *allnodes;
> >  struct device_node *of_chosen;
> > +struct device_node *of_aliases;
> >  
> >  /* use when traversing tree through the allnext, child, sibling,
> >   * or parent members of struct device_node.
> > @@ -922,3 +946,160 @@ out_unlock:
> >  }
> >  #endif /* defined(CONFIG_OF_DYNAMIC) */
> >  
> > +/*
> > + * of_alias_find_available_id - Find an available id for the given device_node
> 
> Nit: kerneldoc format is "/**" to start the comment, and function
> names should have '()' on it.
> 
> > + * @np:		Pointer to the given device_node
> > + * @stem:	Alias stem of the given device_node
> > + *
> > + * The function travels the lookup table to find an available id for the
> > + * given device_node with given alias stem.  It returns the id found.
> > + */
> > +static int of_alias_find_available_id(struct device_node *np, const char *stem)
> > +{
> > +	struct alias_prop *app;
> > +	int id = 0;
> > +
> > +	while (1) {
> > +		bool used = false;
> > +		list_for_each_entry(app, &aliases_lookup, link) {
> > +			if (!strcmp(app->alias_stem, stem) &&
> > +			    app->alias_id == id) {
> > +				used = true;
> > +				break;
> > +			}
> > +		}
> > +
> > +		if (used)
> > +			id++;
> > +		else
> > +			return id;
> > +	}
> > +}
> 
> I've simplified this somewhat to do the list_for_each_entry() only
> once, and to bump up the id to +1 the largest entry:
> 
> 	list_for_each_entry(app, &aliases_lookup, link)
> 		if ((strcmp(app->stem, stem) == 0) && id <= app->id)
> 			id = app->id + 1;
> 
> .... actually, after looking further, I've rolled this code into the
> of_alias_get_id() function.
> 
> > +
> > +/**
> > + * of_alias_lookup_add - Add alias into lookup table
> > + * @alias:	Alias name
> > + * @id:		Alias id
> > + * @stem:	Alias stem name
> > + * @np:		Pointer to device_node
> > + *
> > + * The function adds one alias into the lookup table and populate it
> > + * with the info passed in.  It returns 0 in sucess, or error code.
> > + */
> > +static int of_alias_lookup_add(char *alias, int id, const char *stem,
> > +			       struct device_node *np)
> > +{
> > +	struct alias_prop *app;
> > +	size_t sz = sizeof(*app) + strlen(stem) + 1;
> > +
> > +	app = kzalloc(sz, GFP_KERNEL);
> > +	if (!app) {
> > +		/*
> > +		 * It may fail due to being called by boot code,
> > +		 * so try alloc_bootmem before return error.
> > +		 */
> > +		app = alloc_bootmem(sz);
> > +		if (!app)
> > +			return -ENOMEM;
> > +	}
> 
> I'm not too fond of this since we *know* when this is going to be
> called from early boot.  So, instead, I've changed the code to use the
> already existing dt_alloc functions as an argument to of_alias_lookup_add().
> 
> Also, alloc_bootmem() doesn't work on all platforms.
> early_init_dt_alloc_memory_arch() needs to be used instead.
> 
> 
> > +
> > +	app->np = np;
> > +	app->alias = alias;
> > +	app->alias_id = id;
> > +	strcpy(app->alias_stem, stem);
> > +	list_add_tail(&app->link, &aliases_lookup);
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * of_alias_decode - Decode alias stem and id from alias name
> > + * @alias:	Alias name to be decoded
> > + * @stem:	Pointer used to return stem name
> > + *
> > + * The function decodes alias stem name and alias id from the given
> > + * alias name.  It returns stem name via parameter 'stem', and stem id
> > + * via the return value.  If no id is found in alias name, it returns 0
> > + * as the default.
> > + */
> > +static int of_alias_decode(char *alias, char *stem)
> > +{
> > +	int len = strlen(alias);
> > +	char *end = alias + len;
> > +
> > +	while (isdigit(*--end))
> > +		len--;
> 
> Need to protect against len < 0
> 
> > +
> > +	strncpy(stem, alias, len);
> > +	stem[len] = '\0';
> > +
> > +	return strlen(++end) ? simple_strtoul(end, NULL, 10) : 0;
> > +}
> > +
> > +/**
> > + * of_alias_scan - Scan all properties of 'aliases' node
> > + *
> > + * The function scans all the properties of 'aliases' node and populate
> > + * the the global lookup table with the properties.  It returns the
> > + * number of alias_prop found, or error code in error case.
> > + */
> > +int of_alias_scan(void)
> 
> Changed to '__init void of_aliases_scan(void)'.  There is no point in
> returning an error code since it is never checked, and there is no
> point in bailing on an error just in case it is a problem with only
> one alias.
> 
> > +{
> > +	struct property *pp;
> > +	int ret, num = 0;
> > +
> > +	if (!of_aliases)
> > +		return -ENODEV;
> > +
> > +	for_each_property(pp, of_aliases->properties) {
> > +		char stem[32];
> > +		int id = of_alias_decode(pp->name, stem);
> > +
> > +		/* Skip those we do not want to proceed */
> > +		if (!strcmp(pp->name, "name") ||
> > +		    !strcmp(pp->name, "phandle") ||
> > +		    !strcmp(pp->name, "linux,phandle"))
> > +			continue;
> > +
> > +		ret = of_alias_lookup_add(pp->name, id, stem,
> > +					  of_find_node_by_path(pp->value));
> > +		if (ret < 0)
> > +			return ret;
> > +		else
> > +			num++;
> > +	}
> > +
> > +	return num;
> > +}
> > +
> > +/**
> > + * of_alias_get_id - Get alias id for the given device_node
> > + * @np:		Pointer to the given device_node
> > + * @stem:	Alias stem of the given device_node
> > + *
> > + * The function travels the lookup table to get alias id for the given
> > + * device_node and alias stem.  It returns the alias id if find it.
> > + * If not, dynamically creates one in the lookup table and returns it,
> > + * or returns error code if fail to create.
> > + */
> > +int of_alias_get_id(struct device_node *np, const char *stem)
> > +{
> > +	struct alias_prop *app;
> > +	int id = -1;
> > +
> > +	list_for_each_entry(app, &aliases_lookup, link) {
> > +		if (np == app->np) {
> > +			id = app->alias_id;
> > +			break;
> > +		}
> > +	}
> > +
> > +	if (id == -1) {
> > +		id = of_alias_find_available_id(np, stem);
> > +		if (of_alias_lookup_add(NULL, id, stem, np) < 0)
> > +			return -ENODEV;
> > +	}
> > +
> > +	return id;
> > +}
> 
> This whole function needs to be protected by a mutex.
> 
> > +EXPORT_SYMBOL_GPL(of_alias_get_id);
> > diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> > index 65200af..998dc63 100644
> > --- a/drivers/of/fdt.c
> > +++ b/drivers/of/fdt.c
> > @@ -711,6 +711,12 @@ void __init unflatten_device_tree(void)
> >  	of_chosen = of_find_node_by_path("/chosen");
> >  	if (of_chosen == NULL)
> >  		of_chosen = of_find_node_by_path("/chosen at 0");
> > +
> > +	of_aliases = of_find_node_by_path("/aliases");
> > +	if (of_aliases == NULL)
> > +		of_aliases = of_find_node_by_path("/aliases at 0");
> 
> I don't think the /aliases at 0 variant is necessary.  I've dropped it.
> 
> g.
> 
> > +
> > +	of_alias_scan();
> >  }
> >  
> >  #endif /* CONFIG_OF_EARLY_FLATTREE */
> > diff --git a/include/linux/of.h b/include/linux/of.h
> > index bfc0ed1..c35cc47 100644
> > --- a/include/linux/of.h
> > +++ b/include/linux/of.h
> > @@ -68,6 +68,7 @@ struct device_node {
> >  /* Pointer for first entry in chain of all nodes. */
> >  extern struct device_node *allnodes;
> >  extern struct device_node *of_chosen;
> > +extern struct device_node *of_aliases;
> >  extern rwlock_t devtree_lock;
> >  
> >  static inline bool of_have_populated_dt(void)
> > @@ -201,6 +202,9 @@ extern int of_device_is_available(const struct device_node *device);
> >  extern const void *of_get_property(const struct device_node *node,
> >  				const char *name,
> >  				int *lenp);
> > +#define for_each_property(pp, properties) \
> > +	for (pp = properties; pp != NULL; pp = pp->next)
> > +
> >  extern int of_n_addr_cells(struct device_node *np);
> >  extern int of_n_size_cells(struct device_node *np);
> >  extern const struct of_device_id *of_match_node(
> > @@ -213,6 +217,9 @@ extern int of_parse_phandles_with_args(struct device_node *np,
> >  	const char *list_name, const char *cells_name, int index,
> >  	struct device_node **out_node, const void **out_args);
> >  
> > +extern int of_alias_scan(void);
> > +extern int of_alias_get_id(struct device_node *np, const char *stem);
> > +
> >  extern int of_machine_is_compatible(const char *compat);
> >  
> >  extern int prom_add_property(struct device_node* np, struct property* prop);
> > -- 
> > 1.7.4.1
> > 
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

end of thread, other threads:[~2011-07-15 15:24 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-24 18:04 [PATCH v2 0/5] Add basic device support for imx51 babbage Shawn Guo
2011-06-24 18:04 ` Shawn Guo
2011-06-24 18:04 ` [PATCH v2 1/5] dt: add of_alias_scan and of_alias_get_id Shawn Guo
2011-06-24 18:04   ` Shawn Guo
2011-06-24 18:04   ` Shawn Guo
2011-07-08  9:36   ` Shawn Guo
2011-07-08  9:36     ` Shawn Guo
2011-07-08  9:36     ` Shawn Guo
2011-07-15  2:53   ` Grant Likely
2011-07-15  2:53     ` Grant Likely
2011-07-15 15:24     ` Shawn Guo
2011-07-15 15:24       ` Shawn Guo
2011-07-15 15:24       ` Shawn Guo
2011-06-24 18:04 ` [PATCH v2 2/5] serial/imx: get rid of the use of cpu_is_mx1() Shawn Guo
2011-06-24 18:04   ` Shawn Guo
2011-06-24 18:04   ` Shawn Guo
2011-06-24 18:04 ` [PATCH v2 3/5] serial/imx: add device tree support Shawn Guo
2011-06-24 18:04   ` Shawn Guo
2011-06-24 18:04 ` [PATCH v2 4/5] net/fec: " Shawn Guo
2011-06-24 18:04   ` Shawn Guo
2011-06-24 18:04   ` Shawn Guo
2011-06-24 18:04 ` [PATCH v2 5/5] ARM: mx5: add basic device tree support for imx51 babbage Shawn Guo
2011-06-24 18:04   ` Shawn Guo
2011-06-24 18:04   ` Shawn Guo

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.