From: Julien Grall <julien.grall@linaro.org>
To: Ian Campbell <Ian.Campbell@citrix.com>
Cc: stefano.stabellini@eu.citrix.com, andre.przywara@linaro.org,
patches@linaro.org, xen-devel@lists.xen.org
Subject: Re: [PATCH V1 09/29] xen/dts: Add new helpers to use the device tree
Date: Mon, 09 Sep 2013 10:38:31 +0100 [thread overview]
Message-ID: <522D9717.7090703@linaro.org> (raw)
In-Reply-To: <1378485067.14745.160.camel@kazak.uk.xensource.com>
On 09/06/2013 05:31 PM, Ian Campbell wrote:
> On Wed, 2013-08-28 at 15:47 +0100, Julien Grall wrote:
>> List of new helpers taken from linux (commit 74b9272):
>> - dt_property_read_string
>> - dt_match_node
>> - dt_find_maching_node
>> - dt_device_is_available
>> - dt_prop_cmp
>>
>> Other new helpers:
>> - dt_set_cell
>> - for_each_child
>
> This seems too generic. Perhaps dt_for_each_child or for_each_dt_child?
Right, I will rename the function to dt_for_each_child.
>> - dt_set_range
>> - dt_cells_to_size
>> - dt_next_cell
>> - dt_get_range
>> - dt_node_name_is_equal
>> - dt_node_path_is_equal
>> - dt_property_name_is_equal
>>
>> Signed-off-by: Julien Grall <julien.grall@linaro.org>
>>
>> ---
>> Changes in v2:
>> - Update commit message
>> - Add for_each_child
>> - Add dt_get_range
>> - Update documentation
>> - Typoes
>> ---
>> xen/common/device_tree.c | 109 +++++++++++++++++++++++++++--
>> xen/include/xen/device_tree.h | 151 ++++++++++++++++++++++++++++++++++++++++-
>> 2 files changed, 252 insertions(+), 8 deletions(-)
>>
>> diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
>> index 07a19ac..833d67d 100644
>> --- a/xen/common/device_tree.c
>> +++ b/xen/common/device_tree.c
>> @@ -182,23 +182,38 @@ void __init device_tree_get_reg(const u32 **cell, u32 address_cells,
>> get_val(cell, size_cells, size);
>> }
>>
>> -static void __init set_val(u32 **cell, u32 cells, u64 val)
>> +void dt_get_range(const __be32 **cell, const struct dt_device_node *np,
>> + u64 *address, u64 *size)
>> {
>> - u32 c = cells;
>> + *address = dt_next_cell(dt_n_addr_cells(np), cell);
>> + *size = dt_next_cell(dt_n_size_cells(np), cell);
>> +}
>> +
>> +void dt_set_cell(__be32 **cellp, int size, u64 val)
>> +{
>> + int cells = size;
>>
>> - while ( c-- )
>> + while ( size-- )
>> {
>> - (*cell)[c] = cpu_to_fdt32(val);
>> + (*cellp)[size] = cpu_to_fdt32(val);
>> val >>= 32;
>> }
>> - (*cell) += cells;
>> +
>> + (*cellp) += cells;
>> }
>>
>> void __init device_tree_set_reg(u32 **cell, u32 address_cells, u32 size_cells,
>> u64 start, u64 size)
>> {
>> - set_val(cell, address_cells, start);
>> - set_val(cell, size_cells, size);
>> + dt_set_cell(cell, address_cells, start);
>> + dt_set_cell(cell, size_cells, size);
>> +}
>> +
>> +void dt_set_range(__be32 **cellp, const struct dt_device_node *np,
>> + u64 address, u64 size)
>> +{
>> + dt_set_cell(cellp, dt_n_addr_cells(np), address);
>> + dt_set_cell(cellp, dt_n_size_cells(np), size);
>> }
>>
>> u32 __init device_tree_get_u32(const void *fdt, int node, const char *prop_name,
>> @@ -583,6 +598,23 @@ bool_t dt_property_read_u32(const struct dt_device_node *np,
>> return 1;
>> }
>>
>> +int dt_property_read_string(const struct dt_device_node *np,
>> + const char *propname, const char **out_string)
>> +{
>> + const struct dt_property *pp = dt_find_property(np, propname, NULL);
>> +
>> + if ( !pp )
>> + return -EINVAL;
>> + if ( !pp->value )
>> + return -ENODATA;
>> + if ( strnlen(pp->value, pp->length) >= pp->length )
>> + return -EILSEQ;
>> +
>> + *out_string = pp->value;
>> +
>> + return 0;
>> +}
>> +
>> bool_t dt_device_is_compatible(const struct dt_device_node *device,
>> const char *compat)
>> {
>> @@ -655,6 +687,34 @@ struct dt_device_node *dt_find_node_by_alias(const char *alias)
>> return NULL;
>> }
>>
>> +bool_t dt_match_node(const struct dt_device_match *matches,
>> + const struct dt_device_node *node)
>> +{
>> + if ( !matches )
>> + return 0;
>> +
>> + while ( matches->path || matches->type || matches->compatible )
>> + {
>> + bool_t match = 1;
>> +
>> + if ( matches->path )
>> + match &= dt_node_path_is_equal(node, matches->path);
>> +
>> + if ( matches->type )
>> + match &= dt_device_type_is_equal(node, matches->type);
>> +
>> + if ( matches->compatible )
>> + match &= dt_device_is_compatible(node, matches->compatible);
>> +
>> + if ( match )
>> + return match;
>> +
>> + matches++;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> const struct dt_device_node *dt_get_parent(const struct dt_device_node *node)
>> {
>> if ( !node )
>> @@ -684,6 +744,23 @@ dt_find_compatible_node(struct dt_device_node *from,
>> return np;
>> }
>>
>> +struct dt_device_node *
>> +dt_find_matching_node(struct dt_device_node *from,
>> + const struct dt_device_match *matches)
>> +{
>> + struct dt_device_node *np;
>> + struct dt_device_node *dt;
>> +
>> + dt = from ? from->allnext : dt_host;
>> + for_each_device_node(dt, np)
>> + {
>> + if ( dt_match_node(matches, np) )
>> + return np;
>> + }
>> +
>> + return NULL;
>> +}
>> +
>> int dt_n_addr_cells(const struct dt_device_node *np)
>> {
>> const __be32 *ip;
>> @@ -1372,6 +1449,24 @@ int dt_device_get_irq(const struct dt_device_node *device, int index,
>> return dt_irq_translate(&raw, out_irq);
>> }
>>
>> +bool_t dt_device_is_available(const struct dt_device_node *device)
>> +{
>> + const char *status;
>> + u32 statlen;
>> +
>> + status = dt_get_property(device, "status", &statlen);
>> + if ( status == NULL )
>> + return 1;
>> +
>> + if ( statlen > 0 )
>> + {
>> + if ( !strcmp(status, "okay") || !strcmp(status, "ok") )
>> + return 1;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> /**
>> * unflatten_dt_node - Alloc and populate a device_node from the flat tree
>> * @fdt: The parent device tree blob
>> diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
>> index 7cbf736..fa4f314 100644
>> --- a/xen/include/xen/device_tree.h
>> +++ b/xen/include/xen/device_tree.h
>> @@ -54,6 +54,19 @@ struct dt_early_info {
>> struct dt_module_info modules;
>> };
>>
>> +/*
>> + * Struct used for matching a device
>> + */
>> +struct dt_device_match {
>> + const char *path;
>> + const char *type;
>> + const char *compatible;
>> +};
>> +
>> +#define DT_MATCH_PATH(p) { .path = p }
>> +#define DT_MATCH_TYPE(typ) { .type = typ }
>> +#define DT_MATCH_COMPATIBLE(compat) { .compatible = compat }
>> +
>> typedef u32 dt_phandle;
>>
>> /**
>> @@ -229,6 +242,7 @@ extern const struct dt_device_node *dt_interrupt_controller;
>> */
>> struct dt_device_node * __init dt_find_interrupt_controller(const char *compat);
>>
>> +#define dt_prop_cmp(s1, s2) strcmp((s1), (s2))
>> #define dt_node_cmp(s1, s2) strcasecmp((s1), (s2))
>> #define dt_compat_cmp(s1, s2) strcasecmp((s1), (s2))
>>
>> @@ -242,6 +256,9 @@ struct dt_device_node * __init dt_find_interrupt_controller(const char *compat);
>> #define for_each_device_node(dt, dn) \
>> for ( dn = dt; dn != NULL; dn = dn->allnext )
>>
>> +#define for_each_child_node(dt, dn) \
>> + for ( dn = dt->child; dn != NULL; dn = dn->sibling )
>> +
>> /* Helper to read a big number; size is in cells (not bytes) */
>> static inline u64 dt_read_number(const __be32 *cell, int size)
>> {
>> @@ -252,6 +269,20 @@ static inline u64 dt_read_number(const __be32 *cell, int size)
>> return r;
>> }
>>
>> +/* Helper to convert a number of cells in bytes */
>> +static inline int dt_cells_to_size(int size)
>> +{
>> + return (size * sizeof (u32));
>> +}
>> +
>> +static inline u64 dt_next_cell(int s, const __be32 **cellp)
>> +{
>> + const __be32 *p = *cellp;
>> +
>> + *cellp = p + s;
>> + return dt_read_number(p, s);
>> +}
>> +
>> static inline const char *dt_node_full_name(const struct dt_device_node *np)
>> {
>> return (np && np->full_name) ? np->full_name : "<no-node>";
>> @@ -262,6 +293,18 @@ static inline const char *dt_node_name(const struct dt_device_node *np)
>> return (np && np->name) ? np->name : "<no-node>";
>> }
>>
>> +static inline bool_t dt_node_name_is_equal(const struct dt_device_node *np,
>> + const char *name)
>> +{
>> + return !dt_node_cmp(np->name, name);
>> +}
>> +
>> +static inline bool_t dt_node_path_is_equal(const struct dt_device_node *np,
>> + const char *path)
>> +{
>> + return !dt_node_cmp(np->full_name, path);
>> +}
>> +
>> static inline bool_t
>> dt_device_type_is_equal(const struct dt_device_node *device,
>> const char *type)
>> @@ -281,6 +324,12 @@ static inline domid_t dt_device_used_by(const struct dt_device_node *device)
>> return device->used_by;
>> }
>>
>> +static inline bool_t dt_property_name_is_equal(const struct dt_property *pp,
>> + const char *name)
>> +{
>> + return !dt_prop_cmp(pp->name, name);
>> +}
>> +
>> /**
>> * dt_find_compatible_node - Find a node based on type and one of the
>> * tokens in its "compatible" property
>> @@ -315,6 +364,23 @@ const void *dt_get_property(const struct dt_device_node *np,
>> */
>> bool_t dt_property_read_u32(const struct dt_device_node *np,
>> const char *name, u32 *out_value);
>> +/**
>> + * dt_property_read_string - Find and read a string from a property
>> + * @np: Device node from which the property value is to be read
>> + * @propname: Name of the property to be searched
>> + * @out_string: Pointer to null terminated return string, modified only
>> + * if return value if 0.
>> + *
>> + * Search for a property in a device tree node and retrieve a null
>> + * terminated string value (pointer to data, not a copy). Returns 0 on
>> + * success, -EINVAL if the property does not exist, -ENODATA if property
>> + * doest not have value, and -EILSEQ if the string is not
>> + * null-terminated with the length of the property data.
>> + *
>> + * The out_string pointer is modified only if a valid string can be decoded.
>> + */
>> +int dt_property_read_string(const struct dt_device_node *np,
>> + const char *propname, const char **out_string);
>>
>> /**
>> * Checks if the given "compat" string matches one of the strings in
>> @@ -450,4 +516,87 @@ int dt_n_size_cells(const struct dt_device_node *np);
>> */
>> int dt_n_addr_cells(const struct dt_device_node *np);
>>
>> -#endif
>> +/**
>> + * dt_device_is_available - Check if a device is available for use
>> + *
>> + * @device: Node to check for availability
>> + *
>> + * Returns true if the status property is absent or set to "okay" or "ok",
>> + * false otherwise.
>> + */
>> +bool_t dt_device_is_available(const struct dt_device_node *device);
>> +
>> +/**
>> + * dt_match_node - Tell if a device_node has a matching of dt_device_match
>> + * @matches: array of dt_device_match structures to search in
>> + * @node: the dt_device_node structure to match against
>> + *
>> + * Returns true if the device node match one of dt_device_match.
>> + */
>> +bool_t dt_match_node(const struct dt_device_match *matches,
>> + const struct dt_device_node *node);
>> +
>> +/**
>> + * dt_find_matching_node - Find a node based on an dt_device_match match table
>> + * @from: The node to start searching from or NULL, the node you pass
>> + * will not be searched, only the next one will; typically, you pass
>> + * what the returned call returned
>> + * @matches: array of dt_device_match structures to search in
>> + *
>> + * Returns a node pointer.
>> + */
>> +struct dt_device_node *
>> +dt_find_matching_node(struct dt_device_node *from,
>> + const struct dt_device_match *matches);
>> +
>> +/**
>> + * dt_set_cell - Write a value into a series of cells
>> + *
>> + * @cellp: Pointer to cells
>> + * @size: number of cells to write the value
>> + * @value: number to write
>> + *
>> + * Write a value into a series of cells and update cellp to point to the
>> + * cell just after.
>> + */
>> +void dt_set_cell(__be32 **cellp, int size, u64 val);
>> +
>> +/**
>> + * dt_set_range - Write range into a series of cells
>> + *
>> + * @cellp: Pointer to cells
>> + * @np: Node which contains the encoding for the address and the size
>> + * @address: Start of range
>> + * @size: Size of the range
>> + *
>> + * Write a range into a series of cells and update cellp to point to the
>> + * cell just after.
>> + */
>> +void dt_set_range(__be32 **cellp, const struct dt_device_node *np,
>> + u64 address, u64 size);
>> +
>> +/**
>> + * dt_get_range - Read a range (address/size) from a series of cells
>> + *
>> + * @cellp: Pointer to cells
>> + * @np Node which contains the encoding for the addresss and the size
>> + * @address: Address filled by this function
>> + * @size: Size filled by this function
>> + *
>> + * WARNING: This function should not be used to decode an address
>> + * This function reads a range (address/size) from a series of cells and
>> + * update cellp to point to the cell just after.
>> + */
>> +void dt_get_range(const __be32 **cellp, const struct dt_device_node *np,
>> + u64 *address, u64 *size);
>> +
>> +#endif /* __XEN_DEVICE_TREE_H */
>> +
>> +/*
>> + * Local variables:
>> + * mode: C
>> + * c-file-style: "BSD"
>> + * c-basic-offset: 4
>> + * indent-tabs-mode: nil
>> + * End:
>> + */
>
>
--
Julien Grall
next prev parent reply other threads:[~2013-09-09 9:38 UTC|newest]
Thread overview: 90+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-08-28 14:47 [PATCH V1 00/29] Allow Xen to boot with a raw Device Tree Julien Grall
2013-08-28 14:47 ` [PATCH V1 01/29] xen/char: dt-uart: Allow the user to give a path to the node Julien Grall
2013-09-06 13:08 ` Ian Campbell
2013-09-06 13:34 ` Julien Grall
2013-08-28 14:47 ` [PATCH V1 02/29] xen: Introduce __initconst to store initial const data Julien Grall
2013-09-10 10:50 ` Ian Campbell
2013-08-28 14:47 ` [PATCH V1 03/29] xen/dts: Don't check the number of address and size cells in process_cpu_node Julien Grall
2013-09-06 16:24 ` Ian Campbell
2013-09-10 10:52 ` Ian Campbell
2013-09-10 10:54 ` Julien Grall
2013-09-10 11:03 ` Ian Campbell
2013-08-28 14:47 ` [PATCH V1 04/29] xen/dts: Constify device_tree_flattened Julien Grall
2013-09-10 10:44 ` Ian Campbell
2013-08-28 14:47 ` [PATCH V1 05/29] xen/arm: Move __PSCI* from traps.c to the header Julien Grall
2013-08-28 14:47 ` [PATCH V1 06/29] xen: Add new string function Julien Grall
2013-09-06 16:26 ` Ian Campbell
2013-09-09 9:23 ` Julien Grall
2013-08-28 14:47 ` [PATCH V1 07/29] xen: Use the right string comparison function in device tree Julien Grall
2013-09-10 10:35 ` Ian Campbell
2013-09-10 12:51 ` Julien Grall
2013-08-28 14:47 ` [PATCH V1 08/29] xen/dts: Don't add a fake property "name" in the " Julien Grall
2013-09-06 16:28 ` Ian Campbell
2013-09-09 9:30 ` Julien Grall
2013-09-09 9:40 ` Ian Campbell
2013-09-09 9:59 ` Julien Grall
2013-09-09 10:03 ` Ian Campbell
2013-08-28 14:47 ` [PATCH V1 09/29] xen/dts: Add new helpers to use " Julien Grall
2013-09-06 16:31 ` Ian Campbell
2013-09-09 9:38 ` Julien Grall [this message]
2013-08-28 14:47 ` [PATCH V1 10/29] xen/dts: Remove device_get_reg call in process_cpu_node Julien Grall
2013-09-06 16:36 ` Ian Campbell
2013-09-09 9:43 ` Julien Grall
2013-08-28 14:47 ` [PATCH V1 11/29] xen/dts: Check "reg" property length in process_multiboot_node Julien Grall
2013-09-06 16:40 ` Ian Campbell
2013-09-09 11:11 ` Julien Grall
2013-08-28 14:47 ` [PATCH V1 12/29] xen/dts: Check the CPU ID is not greater than NR_CPUS Julien Grall
2013-08-28 14:47 ` [PATCH V1 13/29] xen/video: hdlcd: Convert the driver to the new device tree API Julien Grall
2013-09-06 16:44 ` Ian Campbell
2013-08-28 14:47 ` [PATCH V1 14/29] xen/video: hdlcd: Use early_printk instead of printk Julien Grall
2013-09-06 16:48 ` Ian Campbell
2013-09-09 11:21 ` Julien Grall
2013-08-28 14:47 ` [PATCH V1 15/29] xen/arm: Use dt_device_match to avoid multiple if conditions Julien Grall
2013-09-06 16:50 ` Ian Campbell
2013-08-28 14:47 ` [PATCH V1 16/29] xen/arm: Build DOM0 FDT by browsing the device tree structure Julien Grall
2013-09-09 11:33 ` Ian Campbell
2013-09-09 12:26 ` Julien Grall
2013-09-09 12:39 ` Ian Campbell
2013-09-09 21:53 ` Julien Grall
2013-09-10 8:58 ` Ian Campbell
2013-09-10 10:39 ` Julien Grall
2013-09-10 10:47 ` Ian Campbell
2013-09-10 10:51 ` Julien Grall
2013-08-28 14:47 ` [PATCH V1 17/29] xen/arm: Mark each device used by Xen as disabled in DOM0 FDT Julien Grall
2013-09-09 11:37 ` Ian Campbell
2013-09-09 21:53 ` Julien Grall
2013-09-10 9:01 ` Ian Campbell
2013-08-28 14:47 ` [PATCH V1 18/29] xen/arm: Don't map disabled device in DOM0 Julien Grall
2013-09-09 11:40 ` Ian Campbell
2013-09-09 21:59 ` Julien Grall
2013-09-10 9:03 ` Ian Campbell
2013-08-28 14:47 ` [PATCH V1 19/29] xen/arm: Create a fake PSCI node in dom0 device tree Julien Grall
2013-09-09 11:41 ` Ian Campbell
2013-09-09 22:04 ` Julien Grall
2013-09-10 9:04 ` Ian Campbell
2013-08-28 14:47 ` [PATCH V1 20/29] xen/arm: Create a fake cpus " Julien Grall
2013-09-09 11:44 ` Ian Campbell
2013-08-28 14:47 ` [PATCH V1 21/29] xen/arm: Create a fake GIC " Julien Grall
2013-09-09 11:49 ` Ian Campbell
2013-09-10 10:49 ` Julien Grall
2013-09-10 13:02 ` Ian Campbell
2013-08-28 14:47 ` [PATCH V1 22/29] xen/arm: Create a fake timer " Julien Grall
2013-09-09 11:51 ` Ian Campbell
2013-09-10 10:56 ` Julien Grall
2013-09-10 13:02 ` Ian Campbell
2013-08-28 14:47 ` [PATCH V1 23/29] xen/arm: Add new platform specific callback device_is_blacklist Julien Grall
2013-09-09 11:52 ` Ian Campbell
2013-08-28 14:47 ` [PATCH V1 24/29] xen/arm: vexpress: Blacklist a list of board specific devices Julien Grall
2013-09-09 11:54 ` Ian Campbell
2013-09-10 11:03 ` Julien Grall
2013-08-28 14:47 ` [PATCH V1 25/29] xen/arm: exynos5: Blacklist MCT device Julien Grall
2013-09-09 11:55 ` Ian Campbell
2013-08-28 14:47 ` [PATCH V1 26/29] xen/dts: Clean up the exported API for device tree Julien Grall
2013-08-28 14:47 ` [PATCH V1 27/29] xen/dts: device_get_reg: cells are 32 bits big endian value Julien Grall
2013-09-09 11:57 ` Ian Campbell
2013-09-10 11:08 ` Julien Grall
2013-08-28 14:47 ` [PATCH V1 28/29] xen/arm: Check if the device is available before using it Julien Grall
2013-08-28 14:47 ` [PATCH V1 29/29] ARM: parse separate DT properties for different commandlines Julien Grall
2013-09-09 11:59 ` Ian Campbell
2013-09-09 14:06 ` Andre Przywara
2013-09-10 10:50 ` [PATCH V1 00/29] Allow Xen to boot with a raw Device Tree Ian Campbell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=522D9717.7090703@linaro.org \
--to=julien.grall@linaro.org \
--cc=Ian.Campbell@citrix.com \
--cc=andre.przywara@linaro.org \
--cc=patches@linaro.org \
--cc=stefano.stabellini@eu.citrix.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.