diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2014-10-02 08:54:42 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2014-10-02 08:54:42 +0200 |
commit | 9d7cd03e2a285c0bbe7271afe46f6d717b0c1dfe (patch) | |
tree | 7a6ec7cbb08d534b733d810c33105f2d303a73ae | |
parent | 815288c59895ea48ff677ad8f575d3eec679c11b (diff) | |
parent | d21f496abaafcf828bd2dc0ec74d275c524fae65 (diff) | |
download | barebox-9d7cd03e2a285c0bbe7271afe46f6d717b0c1dfe.tar.gz barebox-9d7cd03e2a285c0bbe7271afe46f6d717b0c1dfe.tar.xz |
Merge branch 'for-next/of'
-rw-r--r-- | commands/Kconfig | 15 | ||||
-rw-r--r-- | commands/Makefile | 1 | ||||
-rw-r--r-- | commands/of_display_timings.c | 164 | ||||
-rw-r--r-- | drivers/of/base.c | 77 | ||||
-rw-r--r-- | include/of.h | 23 |
5 files changed, 272 insertions, 8 deletions
diff --git a/commands/Kconfig b/commands/Kconfig index bd09ec2fb5..6528bf76c7 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -1989,6 +1989,21 @@ config CMD_OF_PROPERTY [00 11 22 .. nn] - byte stream If the value does not start with '<' or '[' it is interpreted as string +config CMD_OF_DISPLAY_TIMINGS + tristate + select OFTREE + prompt "of_display_timings" + help + List and select display timings + + Usage: of_display_timings [-lS] [-s path] [-f dtb] + + Options: + -l list path of all available display-timings + -S list path of all selected display-timings + -s path select display-timings and register oftree fixup + -f dtb work on dtb. Has no effect on -s option + config CMD_OFTREE tristate select OFTREE diff --git a/commands/Makefile b/commands/Makefile index 58e70fee1a..b1cdf331c4 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -76,6 +76,7 @@ obj-$(CONFIG_CMD_OFTREE) += oftree.o obj-$(CONFIG_CMD_OF_PROPERTY) += of_property.o obj-$(CONFIG_CMD_OF_NODE) += of_node.o obj-$(CONFIG_CMD_OF_DUMP) += of_dump.o +obj-$(CONFIG_CMD_OF_DISPLAY_TIMINGS) += of_display_timings.o obj-$(CONFIG_CMD_MAGICVAR) += magicvar.o obj-$(CONFIG_CMD_IOMEM) += iomemport.o obj-$(CONFIG_CMD_LINUX_EXEC) += linux_exec.o diff --git a/commands/of_display_timings.c b/commands/of_display_timings.c new file mode 100644 index 0000000000..ccf2db0da5 --- /dev/null +++ b/commands/of_display_timings.c @@ -0,0 +1,164 @@ +/* + * of_display_timings.c - list and select display_timings + * + * Copyright (c) 2014 Teresa Gámez <t.gamez@phytec.de> PHYTEC Messtechnik GmbH + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <common.h> +#include <filetype.h> +#include <libfile.h> +#include <of.h> +#include <command.h> +#include <malloc.h> +#include <complete.h> +#include <asm/byteorder.h> +#include <getopt.h> +#include <linux/err.h> +#include <string.h> + +static int of_display_timing(struct device_node *root, void *timingpath) +{ + int ret = 0; + struct device_node *display; + + display = of_find_node_by_path_from(root, timingpath); + if (!display) { + pr_err("Path to display-timings is not vaild.\n"); + ret = -EINVAL; + goto out; + } + + ret = of_set_property_to_child_phandle(display, "native-mode"); + if (ret) + pr_err("Could not set display\n"); +out: + return ret; +} + +static int do_of_display_timings(int argc, char *argv[]) +{ + int opt; + int list = 0; + int selected = 0; + struct device_node *root = NULL; + struct device_node *display = NULL; + struct device_node *timings = NULL; + char *timingpath = NULL; + char *dtbfile = NULL; + + while ((opt = getopt(argc, argv, "sS:lf:")) > 0) { + switch (opt) { + case 'l': + list = 1; + break; + case 'f': + dtbfile = optarg; + break; + case 's': + selected = 1; + break; + case 'S': + timingpath = xzalloc(strlen(optarg) + 1); + strcpy(timingpath, optarg); + break; + default: + return COMMAND_ERROR_USAGE; + } + } + + /* Check if external dtb given */ + if (dtbfile) { + void *fdt; + size_t size; + + fdt = read_file(dtbfile, &size); + if (!fdt) { + pr_err("unable to read %s: %s\n", dtbfile, + strerror(errno)); + return -errno; + } + + if (file_detect_type(fdt, size) != filetype_oftree) { + pr_err("%s is not a oftree file.\n", dtbfile); + free(fdt); + return -EINVAL; + } + + root = of_unflatten_dtb(fdt); + + free(fdt); + + if (IS_ERR(root)) + return PTR_ERR(root); + + } else { + root = of_get_root_node(); + } + + if (list) { + int found = 0; + const char *node = "display-timings"; + + for_each_node_by_name_from(display, root, node) { + for_each_child_of_node(display, timings) { + printf("%s\n", timings->full_name); + found = 1; + } + } + + if (!found) + printf("No display-timings found.\n"); + } + + if (selected) { + int found = 0; + const char *node = "display-timings"; + + for_each_node_by_name_from(display, root, node) { + timings = of_parse_phandle_from(display, root, + "native-mode", 0); + if (!timings) + continue; + + printf("%s\n", timings->full_name); + found = 1; + } + + if (!found) + printf("No selected display-timings found.\n"); + } + + if (timingpath) + of_register_fixup(of_display_timing, timingpath); + + return 0; +} + +BAREBOX_CMD_HELP_START(of_display_timings) +BAREBOX_CMD_HELP_TEXT("Options:") +BAREBOX_CMD_HELP_OPT("-l", "list path of all available display-timings\n") +BAREBOX_CMD_HELP_OPT("-s", "list path of all selected display-timings\n") +BAREBOX_CMD_HELP_OPT("-S path", "select display-timings and register oftree fixup\n") +BAREBOX_CMD_HELP_OPT("-f dtb", "work on dtb. Has no effect on -s option\n") +BAREBOX_CMD_HELP_END + +BAREBOX_CMD_START(of_display_timings) + .cmd = do_of_display_timings, + BAREBOX_CMD_DESC("print and select display-timings") + BAREBOX_CMD_OPTS("[-ls] [-S path] [-f dtb]") + BAREBOX_CMD_GROUP(CMD_GRP_MISC) + BAREBOX_CMD_COMPLETE(devicetree_file_complete) + BAREBOX_CMD_HELP(cmd_of_display_timings_help) +BAREBOX_CMD_END diff --git a/drivers/of/base.c b/drivers/of/base.c index c440a69e6c..e9f0883f47 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -265,19 +265,39 @@ struct device_node *of_find_node_by_alias(struct device_node *root, const char * EXPORT_SYMBOL_GPL(of_find_node_by_alias); /* - * of_find_node_by_phandle - Find a node given a phandle - * @handle: phandle of the node to find + * of_find_node_by_phandle_from - Find a node given a phandle from given + * root node. + * @handle: phandle of the node to find + * @root: root node of the tree to search in. If NULL use the + * internal tree. */ -struct device_node *of_find_node_by_phandle(phandle phandle) +struct device_node *of_find_node_by_phandle_from(phandle phandle, + struct device_node *root) { struct device_node *node; - of_tree_for_each_node_from(node, root_node) + if (!root) + root = root_node; + + if (!root) + return 0; + + of_tree_for_each_node_from(node, root) if (node->phandle == phandle) return node; return NULL; } +EXPORT_SYMBOL(of_find_node_by_phandle_from); + +/* + * of_find_node_by_phandle - Find a node given a phandle + * @handle: phandle of the node to find + */ +struct device_node *of_find_node_by_phandle(phandle phandle) +{ + return of_find_node_by_phandle_from(phandle, root_node); +} EXPORT_SYMBOL(of_find_node_by_phandle); /* @@ -336,6 +356,27 @@ phandle of_node_create_phandle(struct device_node *node) } EXPORT_SYMBOL(of_node_create_phandle); +int of_set_property_to_child_phandle(struct device_node *node, char *prop_name) +{ + int ret; + phandle p; + + /* Check if property exist */ + if (!of_get_property(of_get_parent(node), prop_name, NULL)) + return -EINVAL; + + /* Create or get existing phandle of child node */ + p = of_node_create_phandle(node); + p = cpu_to_be32(p); + + node = of_get_parent(node); + + ret = of_set_property(node, prop_name, &p, sizeof(p), 0); + + return ret; +} +EXPORT_SYMBOL(of_set_property_to_child_phandle); + /* * Find a property with a given name for a given node * and return the value. @@ -1110,16 +1151,19 @@ int of_property_write_u64_array(struct device_node *np, } /** - * of_parse_phandle - Resolve a phandle property to a device_node pointer + * of_parse_phandle_from - Resolve a phandle property to a device_node pointer from + * a given root node * @np: Pointer to device node holding phandle property + * @root: root node of the tree to search in. If NULL use the internal tree. * @phandle_name: Name of property holding a phandle value * @index: For properties holding a table of phandles, this is the index into * the table * * Returns the device_node pointer found or NULL. */ -struct device_node *of_parse_phandle(const struct device_node *np, - const char *phandle_name, int index) +struct device_node *of_parse_phandle_from(const struct device_node *np, + struct device_node *root, + const char *phandle_name, int index) { const __be32 *phandle; int size; @@ -1128,7 +1172,24 @@ struct device_node *of_parse_phandle(const struct device_node *np, if ((!phandle) || (size < sizeof(*phandle) * (index + 1))) return NULL; - return of_find_node_by_phandle(be32_to_cpup(phandle + index)); + return of_find_node_by_phandle_from(be32_to_cpup(phandle + index), + root); +} +EXPORT_SYMBOL(of_parse_phandle_from); + +/** + * of_parse_phandle - Resolve a phandle property to a device_node pointer + * @np: Pointer to device node holding phandle property + * @phandle_name: Name of property holding a phandle value + * @index: For properties holding a table of phandles, this is the index into + * the table + * + * Returns the device_node pointer found or NULL. + */ +struct device_node *of_parse_phandle(const struct device_node *np, + const char *phandle_name, int index) +{ + return of_parse_phandle_from(np, root_node, phandle_name, index); } EXPORT_SYMBOL(of_parse_phandle); diff --git a/include/of.h b/include/of.h index e6993fdde1..29694a9020 100644 --- a/include/of.h +++ b/include/of.h @@ -123,6 +123,8 @@ extern struct device_node *of_find_node_by_path_from(struct device_node *from, const char *path); extern struct device_node *of_find_node_by_path(const char *path); extern struct device_node *of_find_node_by_phandle(phandle phandle); +extern struct device_node *of_find_node_by_phandle_from(phandle phandle, + struct device_node *root); extern struct device_node *of_find_node_by_type(struct device_node *from, const char *type); extern struct device_node *of_find_compatible_node(struct device_node *from, @@ -203,6 +205,10 @@ extern int of_property_write_u64_array(struct device_node *np, extern struct device_node *of_parse_phandle(const struct device_node *np, const char *phandle_name, int index); +extern struct device_node *of_parse_phandle_from(const struct device_node *np, + struct device_node *root, + const char *phandle_name, + int index); extern int of_parse_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name, int index, struct of_phandle_args *out_args); @@ -437,6 +443,13 @@ static inline struct device_node *of_parse_phandle(const struct device_node *np, return NULL; } +static inline struct device_node *of_parse_phandle_from(const struct device_node *np, + struct device_node *root, + const char *phandle_name, int index) +{ + return NULL; +} + static inline int of_parse_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name, int index, struct of_phandle_args *out_args) @@ -472,6 +485,12 @@ static inline struct device_node *of_find_node_by_phandle(phandle phandle) return NULL; } +static inline struct device_node *of_find_node_by_phandle_from(phandle phandle, + struct device_node *root) +{ + return NULL; +} + static inline struct device_node *of_find_compatible_node( struct device_node *from, const char *type, @@ -568,6 +587,9 @@ static inline struct device_d *of_find_device_by_node(struct device_node *np) #define for_each_node_by_name(dn, name) \ for (dn = of_find_node_by_name(NULL, name); dn; \ dn = of_find_node_by_name(dn, name)) +#define for_each_node_by_name_from(dn, root, name) \ + for (dn = of_find_node_by_name(root, name); dn; \ + dn = of_find_node_by_name(dn, name)) #define for_each_compatible_node(dn, type, compatible) \ for (dn = of_find_compatible_node(NULL, type, compatible); dn; \ dn = of_find_compatible_node(dn, type, compatible)) @@ -692,6 +714,7 @@ int of_device_disable_path(const char *path); phandle of_get_tree_max_phandle(struct device_node *root); phandle of_node_create_phandle(struct device_node *node); +int of_set_property_to_child_phandle(struct device_node *node, char *prop_name); struct device_node *of_find_node_by_alias(struct device_node *root, const char *alias); struct device_node *of_find_node_by_path_or_alias(struct device_node *root, |