mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 04:18:39 +08:00
9722c3b66e
The of_property_for_each_u32() macro needs five parameters, two of which are primarily meant as internal variables for the macro itself (in the for() clause). Yet these two parameters are used by a few drivers, and this can be considered misuse or at least bad practice. Now that the kernel uses C11 to build, these two parameters can be avoided by declaring them internally, thus changing this pattern: struct property *prop; const __be32 *p; u32 val; of_property_for_each_u32(np, "xyz", prop, p, val) { ... } to this: u32 val; of_property_for_each_u32(np, "xyz", val) { ... } However two variables cannot be declared in the for clause even with C11, so declare one struct that contain the two variables we actually need. As the variables inside this struct are not meant to be used by users of this macro, give the struct instance the noticeable name "_it" so it is visible during code reviews, helping to avoid new code to use it directly. Most usages are trivially converted as they do not use those two parameters, as expected. The non-trivial cases are: - drivers/clk/clk.c, of_clk_get_parent_name(): easily doable anyway - drivers/clk/clk-si5351.c, si5351_dt_parse(): this is more complex as the checks had to be replicated in a different way, making code more verbose and somewhat uglier, but I refrained from a full rework to keep as much of the original code untouched having no hardware to test my changes All the changes have been build tested. The few for which I have the hardware have been runtime-tested too. Reviewed-by: Andre Przywara <andre.przywara@arm.com> # drivers/clk/sunxi/clk-simple-gates.c, drivers/clk/sunxi/clk-sun8i-bus-gates.c Acked-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> # drivers/gpio/gpio-brcmstb.c Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com> # drivers/irqchip/irq-atmel-aic-common.c Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> # drivers/iio/adc/ti_am335x_adc.c Acked-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com> # drivers/pwm/pwm-samsung.c Acked-by: Richard Leitner <richard.leitner@linux.dev> # drivers/usb/misc/usb251xb.c Acked-by: Mark Brown <broonie@kernel.org> # sound/soc/codecs/arizona.c Reviewed-by: Richard Fitzgerald <rf@opensource.cirrus.com> # sound/soc/codecs/arizona.c Acked-by: Michael Ellerman <mpe@ellerman.id.au> # arch/powerpc/sysdev/xive/spapr.c Acked-by: Stephen Boyd <sboyd@kernel.org> # clk Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com> Acked-by: Lee Jones <lee@kernel.org> Link: https://lore.kernel.org/r/20240724-of_property_for_each_u32-v3-1-bea82ce429e2@bootlin.com Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
1775 lines
51 KiB
C
1775 lines
51 KiB
C
/* SPDX-License-Identifier: GPL-2.0+ */
|
|
#ifndef _LINUX_OF_H
|
|
#define _LINUX_OF_H
|
|
/*
|
|
* Definitions for talking to the Open Firmware PROM on
|
|
* Power Macintosh and other computers.
|
|
*
|
|
* Copyright (C) 1996-2005 Paul Mackerras.
|
|
*
|
|
* Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp.
|
|
* Updates for SPARC64 by David S. Miller
|
|
* Derived from PowerPC and Sparc prom.h files by Stephen Rothwell, IBM Corp.
|
|
*/
|
|
#include <linux/types.h>
|
|
#include <linux/bitops.h>
|
|
#include <linux/cleanup.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/kobject.h>
|
|
#include <linux/mod_devicetable.h>
|
|
#include <linux/property.h>
|
|
#include <linux/list.h>
|
|
|
|
#include <asm/byteorder.h>
|
|
|
|
typedef u32 phandle;
|
|
typedef u32 ihandle;
|
|
|
|
struct property {
|
|
char *name;
|
|
int length;
|
|
void *value;
|
|
struct property *next;
|
|
#if defined(CONFIG_OF_DYNAMIC) || defined(CONFIG_SPARC)
|
|
unsigned long _flags;
|
|
#endif
|
|
#if defined(CONFIG_OF_PROMTREE)
|
|
unsigned int unique_id;
|
|
#endif
|
|
#if defined(CONFIG_OF_KOBJ)
|
|
struct bin_attribute attr;
|
|
#endif
|
|
};
|
|
|
|
#if defined(CONFIG_SPARC)
|
|
struct of_irq_controller;
|
|
#endif
|
|
|
|
struct device_node {
|
|
const char *name;
|
|
phandle phandle;
|
|
const char *full_name;
|
|
struct fwnode_handle fwnode;
|
|
|
|
struct property *properties;
|
|
struct property *deadprops; /* removed properties */
|
|
struct device_node *parent;
|
|
struct device_node *child;
|
|
struct device_node *sibling;
|
|
#if defined(CONFIG_OF_KOBJ)
|
|
struct kobject kobj;
|
|
#endif
|
|
unsigned long _flags;
|
|
void *data;
|
|
#if defined(CONFIG_SPARC)
|
|
unsigned int unique_id;
|
|
struct of_irq_controller *irq_trans;
|
|
#endif
|
|
};
|
|
|
|
#define MAX_PHANDLE_ARGS 16
|
|
struct of_phandle_args {
|
|
struct device_node *np;
|
|
int args_count;
|
|
uint32_t args[MAX_PHANDLE_ARGS];
|
|
};
|
|
|
|
struct of_phandle_iterator {
|
|
/* Common iterator information */
|
|
const char *cells_name;
|
|
int cell_count;
|
|
const struct device_node *parent;
|
|
|
|
/* List size information */
|
|
const __be32 *list_end;
|
|
const __be32 *phandle_end;
|
|
|
|
/* Current position state */
|
|
const __be32 *cur;
|
|
uint32_t cur_count;
|
|
phandle phandle;
|
|
struct device_node *node;
|
|
};
|
|
|
|
struct of_reconfig_data {
|
|
struct device_node *dn;
|
|
struct property *prop;
|
|
struct property *old_prop;
|
|
};
|
|
|
|
extern const struct kobj_type of_node_ktype;
|
|
extern const struct fwnode_operations of_fwnode_ops;
|
|
|
|
/**
|
|
* of_node_init - initialize a devicetree node
|
|
* @node: Pointer to device node that has been created by kzalloc()
|
|
*
|
|
* On return the device_node refcount is set to one. Use of_node_put()
|
|
* on @node when done to free the memory allocated for it. If the node
|
|
* is NOT a dynamic node the memory will not be freed. The decision of
|
|
* whether to free the memory will be done by node->release(), which is
|
|
* of_node_release().
|
|
*/
|
|
static inline void of_node_init(struct device_node *node)
|
|
{
|
|
#if defined(CONFIG_OF_KOBJ)
|
|
kobject_init(&node->kobj, &of_node_ktype);
|
|
#endif
|
|
fwnode_init(&node->fwnode, &of_fwnode_ops);
|
|
}
|
|
|
|
#if defined(CONFIG_OF_KOBJ)
|
|
#define of_node_kobj(n) (&(n)->kobj)
|
|
#else
|
|
#define of_node_kobj(n) NULL
|
|
#endif
|
|
|
|
#ifdef CONFIG_OF_DYNAMIC
|
|
extern struct device_node *of_node_get(struct device_node *node);
|
|
extern void of_node_put(struct device_node *node);
|
|
#else /* CONFIG_OF_DYNAMIC */
|
|
/* Dummy ref counting routines - to be implemented later */
|
|
static inline struct device_node *of_node_get(struct device_node *node)
|
|
{
|
|
return node;
|
|
}
|
|
static inline void of_node_put(struct device_node *node) { }
|
|
#endif /* !CONFIG_OF_DYNAMIC */
|
|
DEFINE_FREE(device_node, struct device_node *, if (_T) of_node_put(_T))
|
|
|
|
/* Pointer for first entry in chain of all nodes. */
|
|
extern struct device_node *of_root;
|
|
extern struct device_node *of_chosen;
|
|
extern struct device_node *of_aliases;
|
|
extern struct device_node *of_stdout;
|
|
|
|
/*
|
|
* struct device_node flag descriptions
|
|
* (need to be visible even when !CONFIG_OF)
|
|
*/
|
|
#define OF_DYNAMIC 1 /* (and properties) allocated via kmalloc */
|
|
#define OF_DETACHED 2 /* detached from the device tree */
|
|
#define OF_POPULATED 3 /* device already created */
|
|
#define OF_POPULATED_BUS 4 /* platform bus created for children */
|
|
#define OF_OVERLAY 5 /* allocated for an overlay */
|
|
#define OF_OVERLAY_FREE_CSET 6 /* in overlay cset being freed */
|
|
|
|
#define OF_BAD_ADDR ((u64)-1)
|
|
|
|
#ifdef CONFIG_OF
|
|
void of_core_init(void);
|
|
|
|
static inline bool is_of_node(const struct fwnode_handle *fwnode)
|
|
{
|
|
return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &of_fwnode_ops;
|
|
}
|
|
|
|
#define to_of_node(__fwnode) \
|
|
({ \
|
|
typeof(__fwnode) __to_of_node_fwnode = (__fwnode); \
|
|
\
|
|
is_of_node(__to_of_node_fwnode) ? \
|
|
container_of(__to_of_node_fwnode, \
|
|
struct device_node, fwnode) : \
|
|
NULL; \
|
|
})
|
|
|
|
#define of_fwnode_handle(node) \
|
|
({ \
|
|
typeof(node) __of_fwnode_handle_node = (node); \
|
|
\
|
|
__of_fwnode_handle_node ? \
|
|
&__of_fwnode_handle_node->fwnode : NULL; \
|
|
})
|
|
|
|
static inline bool of_node_is_root(const struct device_node *node)
|
|
{
|
|
return node && (node->parent == NULL);
|
|
}
|
|
|
|
static inline int of_node_check_flag(const struct device_node *n, unsigned long flag)
|
|
{
|
|
return test_bit(flag, &n->_flags);
|
|
}
|
|
|
|
static inline int of_node_test_and_set_flag(struct device_node *n,
|
|
unsigned long flag)
|
|
{
|
|
return test_and_set_bit(flag, &n->_flags);
|
|
}
|
|
|
|
static inline void of_node_set_flag(struct device_node *n, unsigned long flag)
|
|
{
|
|
set_bit(flag, &n->_flags);
|
|
}
|
|
|
|
static inline void of_node_clear_flag(struct device_node *n, unsigned long flag)
|
|
{
|
|
clear_bit(flag, &n->_flags);
|
|
}
|
|
|
|
#if defined(CONFIG_OF_DYNAMIC) || defined(CONFIG_SPARC)
|
|
static inline int of_property_check_flag(const struct property *p, unsigned long flag)
|
|
{
|
|
return test_bit(flag, &p->_flags);
|
|
}
|
|
|
|
static inline void of_property_set_flag(struct property *p, unsigned long flag)
|
|
{
|
|
set_bit(flag, &p->_flags);
|
|
}
|
|
|
|
static inline void of_property_clear_flag(struct property *p, unsigned long flag)
|
|
{
|
|
clear_bit(flag, &p->_flags);
|
|
}
|
|
#endif
|
|
|
|
extern struct device_node *__of_find_all_nodes(struct device_node *prev);
|
|
extern struct device_node *of_find_all_nodes(struct device_node *prev);
|
|
|
|
/*
|
|
* OF address retrieval & translation
|
|
*/
|
|
|
|
/* Helper to read a big number; size is in cells (not bytes) */
|
|
static inline u64 of_read_number(const __be32 *cell, int size)
|
|
{
|
|
u64 r = 0;
|
|
for (; size--; cell++)
|
|
r = (r << 32) | be32_to_cpu(*cell);
|
|
return r;
|
|
}
|
|
|
|
/* Like of_read_number, but we want an unsigned long result */
|
|
static inline unsigned long of_read_ulong(const __be32 *cell, int size)
|
|
{
|
|
/* toss away upper bits if unsigned long is smaller than u64 */
|
|
return of_read_number(cell, size);
|
|
}
|
|
|
|
#if defined(CONFIG_SPARC)
|
|
#include <asm/prom.h>
|
|
#endif
|
|
|
|
#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
|
|
#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
|
|
|
|
extern bool of_node_name_eq(const struct device_node *np, const char *name);
|
|
extern bool of_node_name_prefix(const struct device_node *np, const char *prefix);
|
|
|
|
static inline const char *of_node_full_name(const struct device_node *np)
|
|
{
|
|
return np ? np->full_name : "<no-node>";
|
|
}
|
|
|
|
#define for_each_of_allnodes_from(from, dn) \
|
|
for (dn = __of_find_all_nodes(from); dn; dn = __of_find_all_nodes(dn))
|
|
#define for_each_of_allnodes(dn) for_each_of_allnodes_from(NULL, dn)
|
|
extern struct device_node *of_find_node_by_name(struct device_node *from,
|
|
const char *name);
|
|
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,
|
|
const char *type, const char *compat);
|
|
extern struct device_node *of_find_matching_node_and_match(
|
|
struct device_node *from,
|
|
const struct of_device_id *matches,
|
|
const struct of_device_id **match);
|
|
|
|
extern struct device_node *of_find_node_opts_by_path(const char *path,
|
|
const char **opts);
|
|
static inline struct device_node *of_find_node_by_path(const char *path)
|
|
{
|
|
return of_find_node_opts_by_path(path, NULL);
|
|
}
|
|
|
|
extern struct device_node *of_find_node_by_phandle(phandle handle);
|
|
extern struct device_node *of_get_parent(const struct device_node *node);
|
|
extern struct device_node *of_get_next_parent(struct device_node *node);
|
|
extern struct device_node *of_get_next_child(const struct device_node *node,
|
|
struct device_node *prev);
|
|
extern struct device_node *of_get_next_available_child(
|
|
const struct device_node *node, struct device_node *prev);
|
|
extern struct device_node *of_get_next_reserved_child(
|
|
const struct device_node *node, struct device_node *prev);
|
|
|
|
extern struct device_node *of_get_compatible_child(const struct device_node *parent,
|
|
const char *compatible);
|
|
extern struct device_node *of_get_child_by_name(const struct device_node *node,
|
|
const char *name);
|
|
|
|
/* cache lookup */
|
|
extern struct device_node *of_find_next_cache_node(const struct device_node *);
|
|
extern int of_find_last_cache_level(unsigned int cpu);
|
|
extern struct device_node *of_find_node_with_property(
|
|
struct device_node *from, const char *prop_name);
|
|
|
|
extern struct property *of_find_property(const struct device_node *np,
|
|
const char *name,
|
|
int *lenp);
|
|
extern int of_property_count_elems_of_size(const struct device_node *np,
|
|
const char *propname, int elem_size);
|
|
extern int of_property_read_u32_index(const struct device_node *np,
|
|
const char *propname,
|
|
u32 index, u32 *out_value);
|
|
extern int of_property_read_u64_index(const struct device_node *np,
|
|
const char *propname,
|
|
u32 index, u64 *out_value);
|
|
extern int of_property_read_variable_u8_array(const struct device_node *np,
|
|
const char *propname, u8 *out_values,
|
|
size_t sz_min, size_t sz_max);
|
|
extern int of_property_read_variable_u16_array(const struct device_node *np,
|
|
const char *propname, u16 *out_values,
|
|
size_t sz_min, size_t sz_max);
|
|
extern int of_property_read_variable_u32_array(const struct device_node *np,
|
|
const char *propname,
|
|
u32 *out_values,
|
|
size_t sz_min,
|
|
size_t sz_max);
|
|
extern int of_property_read_u64(const struct device_node *np,
|
|
const char *propname, u64 *out_value);
|
|
extern int of_property_read_variable_u64_array(const struct device_node *np,
|
|
const char *propname,
|
|
u64 *out_values,
|
|
size_t sz_min,
|
|
size_t sz_max);
|
|
|
|
extern int of_property_read_string(const struct device_node *np,
|
|
const char *propname,
|
|
const char **out_string);
|
|
extern int of_property_match_string(const struct device_node *np,
|
|
const char *propname,
|
|
const char *string);
|
|
extern int of_property_read_string_helper(const struct device_node *np,
|
|
const char *propname,
|
|
const char **out_strs, size_t sz, int index);
|
|
extern int of_device_is_compatible(const struct device_node *device,
|
|
const char *);
|
|
extern int of_device_compatible_match(const struct device_node *device,
|
|
const char *const *compat);
|
|
extern bool of_device_is_available(const struct device_node *device);
|
|
extern bool of_device_is_big_endian(const struct device_node *device);
|
|
extern const void *of_get_property(const struct device_node *node,
|
|
const char *name,
|
|
int *lenp);
|
|
extern struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
|
|
extern struct device_node *of_cpu_device_node_get(int cpu);
|
|
extern int of_cpu_node_to_id(struct device_node *np);
|
|
extern struct device_node *of_get_next_cpu_node(struct device_node *prev);
|
|
extern struct device_node *of_get_cpu_state_node(struct device_node *cpu_node,
|
|
int index);
|
|
extern u64 of_get_cpu_hwid(struct device_node *cpun, unsigned int thread);
|
|
|
|
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(
|
|
const struct of_device_id *matches, const struct device_node *node);
|
|
extern const void *of_device_get_match_data(const struct device *dev);
|
|
extern int of_alias_from_compatible(const struct device_node *node, char *alias,
|
|
int len);
|
|
extern void of_print_phandle_args(const char *msg, const struct of_phandle_args *args);
|
|
extern int __of_parse_phandle_with_args(const struct device_node *np,
|
|
const char *list_name, const char *cells_name, int cell_count,
|
|
int index, struct of_phandle_args *out_args);
|
|
extern int of_parse_phandle_with_args_map(const struct device_node *np,
|
|
const char *list_name, const char *stem_name, int index,
|
|
struct of_phandle_args *out_args);
|
|
extern int of_count_phandle_with_args(const struct device_node *np,
|
|
const char *list_name, const char *cells_name);
|
|
|
|
/* module functions */
|
|
extern ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len);
|
|
extern int of_request_module(const struct device_node *np);
|
|
|
|
/* phandle iterator functions */
|
|
extern int of_phandle_iterator_init(struct of_phandle_iterator *it,
|
|
const struct device_node *np,
|
|
const char *list_name,
|
|
const char *cells_name,
|
|
int cell_count);
|
|
|
|
extern int of_phandle_iterator_next(struct of_phandle_iterator *it);
|
|
extern int of_phandle_iterator_args(struct of_phandle_iterator *it,
|
|
uint32_t *args,
|
|
int size);
|
|
|
|
extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align));
|
|
extern int of_alias_get_id(struct device_node *np, const char *stem);
|
|
extern int of_alias_get_highest_id(const char *stem);
|
|
|
|
bool of_machine_compatible_match(const char *const *compats);
|
|
|
|
/**
|
|
* of_machine_is_compatible - Test root of device tree for a given compatible value
|
|
* @compat: compatible string to look for in root node's compatible property.
|
|
*
|
|
* Return: true if the root node has the given value in its compatible property.
|
|
*/
|
|
static inline bool of_machine_is_compatible(const char *compat)
|
|
{
|
|
const char *compats[] = { compat, NULL };
|
|
|
|
return of_machine_compatible_match(compats);
|
|
}
|
|
|
|
extern int of_add_property(struct device_node *np, struct property *prop);
|
|
extern int of_remove_property(struct device_node *np, struct property *prop);
|
|
extern int of_update_property(struct device_node *np, struct property *newprop);
|
|
|
|
/* For updating the device tree at runtime */
|
|
#define OF_RECONFIG_ATTACH_NODE 0x0001
|
|
#define OF_RECONFIG_DETACH_NODE 0x0002
|
|
#define OF_RECONFIG_ADD_PROPERTY 0x0003
|
|
#define OF_RECONFIG_REMOVE_PROPERTY 0x0004
|
|
#define OF_RECONFIG_UPDATE_PROPERTY 0x0005
|
|
|
|
extern int of_attach_node(struct device_node *);
|
|
extern int of_detach_node(struct device_node *);
|
|
|
|
#define of_match_ptr(_ptr) (_ptr)
|
|
|
|
/*
|
|
* u32 u;
|
|
*
|
|
* of_property_for_each_u32(np, "propname", u)
|
|
* printk("U32 value: %x\n", u);
|
|
*/
|
|
const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
|
|
u32 *pu);
|
|
/*
|
|
* struct property *prop;
|
|
* const char *s;
|
|
*
|
|
* of_property_for_each_string(np, "propname", prop, s)
|
|
* printk("String value: %s\n", s);
|
|
*/
|
|
const char *of_prop_next_string(struct property *prop, const char *cur);
|
|
|
|
bool of_console_check(struct device_node *dn, char *name, int index);
|
|
|
|
int of_map_id(struct device_node *np, u32 id,
|
|
const char *map_name, const char *map_mask_name,
|
|
struct device_node **target, u32 *id_out);
|
|
|
|
phys_addr_t of_dma_get_max_cpu_address(struct device_node *np);
|
|
|
|
struct kimage;
|
|
void *of_kexec_alloc_and_setup_fdt(const struct kimage *image,
|
|
unsigned long initrd_load_addr,
|
|
unsigned long initrd_len,
|
|
const char *cmdline, size_t extra_fdt_size);
|
|
#else /* CONFIG_OF */
|
|
|
|
static inline void of_core_init(void)
|
|
{
|
|
}
|
|
|
|
static inline bool is_of_node(const struct fwnode_handle *fwnode)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static inline struct device_node *to_of_node(const struct fwnode_handle *fwnode)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline bool of_node_name_eq(const struct device_node *np, const char *name)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static inline bool of_node_name_prefix(const struct device_node *np, const char *prefix)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static inline const char* of_node_full_name(const struct device_node *np)
|
|
{
|
|
return "<no-node>";
|
|
}
|
|
|
|
static inline struct device_node *of_find_node_by_name(struct device_node *from,
|
|
const char *name)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline struct device_node *of_find_node_by_type(struct device_node *from,
|
|
const char *type)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline struct device_node *of_find_matching_node_and_match(
|
|
struct device_node *from,
|
|
const struct of_device_id *matches,
|
|
const struct of_device_id **match)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline struct device_node *of_find_node_by_path(const char *path)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline struct device_node *of_find_node_opts_by_path(const char *path,
|
|
const char **opts)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline struct device_node *of_find_node_by_phandle(phandle handle)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline struct device_node *of_get_parent(const struct device_node *node)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline struct device_node *of_get_next_parent(struct device_node *node)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline struct device_node *of_get_next_child(
|
|
const struct device_node *node, struct device_node *prev)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline struct device_node *of_get_next_available_child(
|
|
const struct device_node *node, struct device_node *prev)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline struct device_node *of_get_next_reserved_child(
|
|
const struct device_node *node, struct device_node *prev)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline struct device_node *of_find_node_with_property(
|
|
struct device_node *from, const char *prop_name)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
#define of_fwnode_handle(node) NULL
|
|
|
|
static inline struct device_node *of_get_compatible_child(const struct device_node *parent,
|
|
const char *compatible)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline struct device_node *of_get_child_by_name(
|
|
const struct device_node *node,
|
|
const char *name)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline int of_device_is_compatible(const struct device_node *device,
|
|
const char *name)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline int of_device_compatible_match(const struct device_node *device,
|
|
const char *const *compat)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline bool of_device_is_available(const struct device_node *device)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static inline bool of_device_is_big_endian(const struct device_node *device)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static inline struct property *of_find_property(const struct device_node *np,
|
|
const char *name,
|
|
int *lenp)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline struct device_node *of_find_compatible_node(
|
|
struct device_node *from,
|
|
const char *type,
|
|
const char *compat)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline int of_property_count_elems_of_size(const struct device_node *np,
|
|
const char *propname, int elem_size)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_property_read_u32_index(const struct device_node *np,
|
|
const char *propname, u32 index, u32 *out_value)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_property_read_u64_index(const struct device_node *np,
|
|
const char *propname, u32 index, u64 *out_value)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline const void *of_get_property(const struct device_node *node,
|
|
const char *name,
|
|
int *lenp)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline struct device_node *of_get_cpu_node(int cpu,
|
|
unsigned int *thread)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline struct device_node *of_cpu_device_node_get(int cpu)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline int of_cpu_node_to_id(struct device_node *np)
|
|
{
|
|
return -ENODEV;
|
|
}
|
|
|
|
static inline struct device_node *of_get_next_cpu_node(struct device_node *prev)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline struct device_node *of_get_cpu_state_node(struct device_node *cpu_node,
|
|
int index)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline int of_n_addr_cells(struct device_node *np)
|
|
{
|
|
return 0;
|
|
|
|
}
|
|
static inline int of_n_size_cells(struct device_node *np)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline int of_property_read_variable_u8_array(const struct device_node *np,
|
|
const char *propname, u8 *out_values,
|
|
size_t sz_min, size_t sz_max)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_property_read_variable_u16_array(const struct device_node *np,
|
|
const char *propname, u16 *out_values,
|
|
size_t sz_min, size_t sz_max)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_property_read_variable_u32_array(const struct device_node *np,
|
|
const char *propname,
|
|
u32 *out_values,
|
|
size_t sz_min,
|
|
size_t sz_max)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_property_read_u64(const struct device_node *np,
|
|
const char *propname, u64 *out_value)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_property_read_variable_u64_array(const struct device_node *np,
|
|
const char *propname,
|
|
u64 *out_values,
|
|
size_t sz_min,
|
|
size_t sz_max)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_property_read_string(const struct device_node *np,
|
|
const char *propname,
|
|
const char **out_string)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_property_match_string(const struct device_node *np,
|
|
const char *propname,
|
|
const char *string)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_property_read_string_helper(const struct device_node *np,
|
|
const char *propname,
|
|
const char **out_strs, size_t sz, int index)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int __of_parse_phandle_with_args(const struct device_node *np,
|
|
const char *list_name,
|
|
const char *cells_name,
|
|
int cell_count,
|
|
int index,
|
|
struct of_phandle_args *out_args)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_parse_phandle_with_args_map(const struct device_node *np,
|
|
const char *list_name,
|
|
const char *stem_name,
|
|
int index,
|
|
struct of_phandle_args *out_args)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_count_phandle_with_args(const struct device_node *np,
|
|
const char *list_name,
|
|
const char *cells_name)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline ssize_t of_modalias(const struct device_node *np, char *str,
|
|
ssize_t len)
|
|
{
|
|
return -ENODEV;
|
|
}
|
|
|
|
static inline int of_request_module(const struct device_node *np)
|
|
{
|
|
return -ENODEV;
|
|
}
|
|
|
|
static inline int of_phandle_iterator_init(struct of_phandle_iterator *it,
|
|
const struct device_node *np,
|
|
const char *list_name,
|
|
const char *cells_name,
|
|
int cell_count)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_phandle_iterator_next(struct of_phandle_iterator *it)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_phandle_iterator_args(struct of_phandle_iterator *it,
|
|
uint32_t *args,
|
|
int size)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline int of_alias_get_id(struct device_node *np, const char *stem)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_alias_get_highest_id(const char *stem)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_machine_is_compatible(const char *compat)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline int of_add_property(struct device_node *np, struct property *prop)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline int of_remove_property(struct device_node *np, struct property *prop)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline bool of_machine_compatible_match(const char *const *compats)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static inline bool of_console_check(const struct device_node *dn, const char *name, int index)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static inline const __be32 *of_prop_next_u32(struct property *prop,
|
|
const __be32 *cur, u32 *pu)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline const char *of_prop_next_string(struct property *prop,
|
|
const char *cur)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline int of_node_check_flag(struct device_node *n, unsigned long flag)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline int of_node_test_and_set_flag(struct device_node *n,
|
|
unsigned long flag)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline void of_node_set_flag(struct device_node *n, unsigned long flag)
|
|
{
|
|
}
|
|
|
|
static inline void of_node_clear_flag(struct device_node *n, unsigned long flag)
|
|
{
|
|
}
|
|
|
|
static inline int of_property_check_flag(const struct property *p,
|
|
unsigned long flag)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline void of_property_set_flag(struct property *p, unsigned long flag)
|
|
{
|
|
}
|
|
|
|
static inline void of_property_clear_flag(struct property *p, unsigned long flag)
|
|
{
|
|
}
|
|
|
|
static inline int of_map_id(struct device_node *np, u32 id,
|
|
const char *map_name, const char *map_mask_name,
|
|
struct device_node **target, u32 *id_out)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
|
|
static inline phys_addr_t of_dma_get_max_cpu_address(struct device_node *np)
|
|
{
|
|
return PHYS_ADDR_MAX;
|
|
}
|
|
|
|
static inline const void *of_device_get_match_data(const struct device *dev)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
#define of_match_ptr(_ptr) NULL
|
|
#define of_match_node(_matches, _node) NULL
|
|
#endif /* CONFIG_OF */
|
|
|
|
/* Default string compare functions, Allow arch asm/prom.h to override */
|
|
#if !defined(of_compat_cmp)
|
|
#define of_compat_cmp(s1, s2, l) strcasecmp((s1), (s2))
|
|
#define of_prop_cmp(s1, s2) strcmp((s1), (s2))
|
|
#define of_node_cmp(s1, s2) strcasecmp((s1), (s2))
|
|
#endif
|
|
|
|
static inline int of_prop_val_eq(struct property *p1, struct property *p2)
|
|
{
|
|
return p1->length == p2->length &&
|
|
!memcmp(p1->value, p2->value, (size_t)p1->length);
|
|
}
|
|
|
|
#define for_each_property_of_node(dn, pp) \
|
|
for (pp = dn->properties; pp != NULL; pp = pp->next)
|
|
|
|
#if defined(CONFIG_OF) && defined(CONFIG_NUMA)
|
|
extern int of_node_to_nid(struct device_node *np);
|
|
#else
|
|
static inline int of_node_to_nid(struct device_node *device)
|
|
{
|
|
return NUMA_NO_NODE;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_OF_NUMA
|
|
extern int of_numa_init(void);
|
|
#else
|
|
static inline int of_numa_init(void)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
#endif
|
|
|
|
static inline struct device_node *of_find_matching_node(
|
|
struct device_node *from,
|
|
const struct of_device_id *matches)
|
|
{
|
|
return of_find_matching_node_and_match(from, matches, NULL);
|
|
}
|
|
|
|
static inline const char *of_node_get_device_type(const struct device_node *np)
|
|
{
|
|
return of_get_property(np, "device_type", NULL);
|
|
}
|
|
|
|
static inline bool of_node_is_type(const struct device_node *np, const char *type)
|
|
{
|
|
const char *match = of_node_get_device_type(np);
|
|
|
|
return np && match && type && !strcmp(match, type);
|
|
}
|
|
|
|
/**
|
|
* 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
|
|
*
|
|
* Return: The device_node pointer with refcount incremented. Use
|
|
* of_node_put() on it when done.
|
|
*/
|
|
static inline struct device_node *of_parse_phandle(const struct device_node *np,
|
|
const char *phandle_name,
|
|
int index)
|
|
{
|
|
struct of_phandle_args args;
|
|
|
|
if (__of_parse_phandle_with_args(np, phandle_name, NULL, 0,
|
|
index, &args))
|
|
return NULL;
|
|
|
|
return args.np;
|
|
}
|
|
|
|
/**
|
|
* of_parse_phandle_with_args() - Find a node pointed by phandle in a list
|
|
* @np: pointer to a device tree node containing a list
|
|
* @list_name: property name that contains a list
|
|
* @cells_name: property name that specifies phandles' arguments count
|
|
* @index: index of a phandle to parse out
|
|
* @out_args: optional pointer to output arguments structure (will be filled)
|
|
*
|
|
* This function is useful to parse lists of phandles and their arguments.
|
|
* Returns 0 on success and fills out_args, on error returns appropriate
|
|
* errno value.
|
|
*
|
|
* Caller is responsible to call of_node_put() on the returned out_args->np
|
|
* pointer.
|
|
*
|
|
* Example::
|
|
*
|
|
* phandle1: node1 {
|
|
* #list-cells = <2>;
|
|
* };
|
|
*
|
|
* phandle2: node2 {
|
|
* #list-cells = <1>;
|
|
* };
|
|
*
|
|
* node3 {
|
|
* list = <&phandle1 1 2 &phandle2 3>;
|
|
* };
|
|
*
|
|
* To get a device_node of the ``node2`` node you may call this:
|
|
* of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args);
|
|
*/
|
|
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)
|
|
{
|
|
int cell_count = -1;
|
|
|
|
/* If cells_name is NULL we assume a cell count of 0 */
|
|
if (!cells_name)
|
|
cell_count = 0;
|
|
|
|
return __of_parse_phandle_with_args(np, list_name, cells_name,
|
|
cell_count, index, out_args);
|
|
}
|
|
|
|
/**
|
|
* of_parse_phandle_with_fixed_args() - Find a node pointed by phandle in a list
|
|
* @np: pointer to a device tree node containing a list
|
|
* @list_name: property name that contains a list
|
|
* @cell_count: number of argument cells following the phandle
|
|
* @index: index of a phandle to parse out
|
|
* @out_args: optional pointer to output arguments structure (will be filled)
|
|
*
|
|
* This function is useful to parse lists of phandles and their arguments.
|
|
* Returns 0 on success and fills out_args, on error returns appropriate
|
|
* errno value.
|
|
*
|
|
* Caller is responsible to call of_node_put() on the returned out_args->np
|
|
* pointer.
|
|
*
|
|
* Example::
|
|
*
|
|
* phandle1: node1 {
|
|
* };
|
|
*
|
|
* phandle2: node2 {
|
|
* };
|
|
*
|
|
* node3 {
|
|
* list = <&phandle1 0 2 &phandle2 2 3>;
|
|
* };
|
|
*
|
|
* To get a device_node of the ``node2`` node you may call this:
|
|
* of_parse_phandle_with_fixed_args(node3, "list", 2, 1, &args);
|
|
*/
|
|
static inline int of_parse_phandle_with_fixed_args(const struct device_node *np,
|
|
const char *list_name,
|
|
int cell_count,
|
|
int index,
|
|
struct of_phandle_args *out_args)
|
|
{
|
|
return __of_parse_phandle_with_args(np, list_name, NULL, cell_count,
|
|
index, out_args);
|
|
}
|
|
|
|
/**
|
|
* of_parse_phandle_with_optional_args() - Find a node pointed by phandle in a list
|
|
* @np: pointer to a device tree node containing a list
|
|
* @list_name: property name that contains a list
|
|
* @cells_name: property name that specifies phandles' arguments count
|
|
* @index: index of a phandle to parse out
|
|
* @out_args: optional pointer to output arguments structure (will be filled)
|
|
*
|
|
* Same as of_parse_phandle_with_args() except that if the cells_name property
|
|
* is not found, cell_count of 0 is assumed.
|
|
*
|
|
* This is used to useful, if you have a phandle which didn't have arguments
|
|
* before and thus doesn't have a '#*-cells' property but is now migrated to
|
|
* having arguments while retaining backwards compatibility.
|
|
*/
|
|
static inline int of_parse_phandle_with_optional_args(const struct device_node *np,
|
|
const char *list_name,
|
|
const char *cells_name,
|
|
int index,
|
|
struct of_phandle_args *out_args)
|
|
{
|
|
return __of_parse_phandle_with_args(np, list_name, cells_name,
|
|
0, index, out_args);
|
|
}
|
|
|
|
/**
|
|
* of_phandle_args_equal() - Compare two of_phandle_args
|
|
* @a1: First of_phandle_args to compare
|
|
* @a2: Second of_phandle_args to compare
|
|
*
|
|
* Return: True if a1 and a2 are the same (same node pointer, same phandle
|
|
* args), false otherwise.
|
|
*/
|
|
static inline bool of_phandle_args_equal(const struct of_phandle_args *a1,
|
|
const struct of_phandle_args *a2)
|
|
{
|
|
return a1->np == a2->np &&
|
|
a1->args_count == a2->args_count &&
|
|
!memcmp(a1->args, a2->args, sizeof(a1->args[0]) * a1->args_count);
|
|
}
|
|
|
|
/**
|
|
* of_property_count_u8_elems - Count the number of u8 elements in a property
|
|
*
|
|
* @np: device node from which the property value is to be read.
|
|
* @propname: name of the property to be searched.
|
|
*
|
|
* Search for a property in a device node and count the number of u8 elements
|
|
* in it.
|
|
*
|
|
* Return: The number of elements on sucess, -EINVAL if the property does
|
|
* not exist or its length does not match a multiple of u8 and -ENODATA if the
|
|
* property does not have a value.
|
|
*/
|
|
static inline int of_property_count_u8_elems(const struct device_node *np,
|
|
const char *propname)
|
|
{
|
|
return of_property_count_elems_of_size(np, propname, sizeof(u8));
|
|
}
|
|
|
|
/**
|
|
* of_property_count_u16_elems - Count the number of u16 elements in a property
|
|
*
|
|
* @np: device node from which the property value is to be read.
|
|
* @propname: name of the property to be searched.
|
|
*
|
|
* Search for a property in a device node and count the number of u16 elements
|
|
* in it.
|
|
*
|
|
* Return: The number of elements on sucess, -EINVAL if the property does
|
|
* not exist or its length does not match a multiple of u16 and -ENODATA if the
|
|
* property does not have a value.
|
|
*/
|
|
static inline int of_property_count_u16_elems(const struct device_node *np,
|
|
const char *propname)
|
|
{
|
|
return of_property_count_elems_of_size(np, propname, sizeof(u16));
|
|
}
|
|
|
|
/**
|
|
* of_property_count_u32_elems - Count the number of u32 elements in a property
|
|
*
|
|
* @np: device node from which the property value is to be read.
|
|
* @propname: name of the property to be searched.
|
|
*
|
|
* Search for a property in a device node and count the number of u32 elements
|
|
* in it.
|
|
*
|
|
* Return: The number of elements on sucess, -EINVAL if the property does
|
|
* not exist or its length does not match a multiple of u32 and -ENODATA if the
|
|
* property does not have a value.
|
|
*/
|
|
static inline int of_property_count_u32_elems(const struct device_node *np,
|
|
const char *propname)
|
|
{
|
|
return of_property_count_elems_of_size(np, propname, sizeof(u32));
|
|
}
|
|
|
|
/**
|
|
* of_property_count_u64_elems - Count the number of u64 elements in a property
|
|
*
|
|
* @np: device node from which the property value is to be read.
|
|
* @propname: name of the property to be searched.
|
|
*
|
|
* Search for a property in a device node and count the number of u64 elements
|
|
* in it.
|
|
*
|
|
* Return: The number of elements on sucess, -EINVAL if the property does
|
|
* not exist or its length does not match a multiple of u64 and -ENODATA if the
|
|
* property does not have a value.
|
|
*/
|
|
static inline int of_property_count_u64_elems(const struct device_node *np,
|
|
const char *propname)
|
|
{
|
|
return of_property_count_elems_of_size(np, propname, sizeof(u64));
|
|
}
|
|
|
|
/**
|
|
* of_property_read_string_array() - Read an array of strings from a multiple
|
|
* strings property.
|
|
* @np: device node from which the property value is to be read.
|
|
* @propname: name of the property to be searched.
|
|
* @out_strs: output array of string pointers.
|
|
* @sz: number of array elements to read.
|
|
*
|
|
* Search for a property in a device tree node and retrieve a list of
|
|
* terminated string values (pointer to data, not a copy) in that property.
|
|
*
|
|
* Return: If @out_strs is NULL, the number of strings in the property is returned.
|
|
*/
|
|
static inline int of_property_read_string_array(const struct device_node *np,
|
|
const char *propname, const char **out_strs,
|
|
size_t sz)
|
|
{
|
|
return of_property_read_string_helper(np, propname, out_strs, sz, 0);
|
|
}
|
|
|
|
/**
|
|
* of_property_count_strings() - Find and return the number of strings from a
|
|
* multiple strings property.
|
|
* @np: device node from which the property value is to be read.
|
|
* @propname: name of the property to be searched.
|
|
*
|
|
* Search for a property in a device tree node and retrieve the number of null
|
|
* terminated string contain in it.
|
|
*
|
|
* Return: The number of strings on success, -EINVAL if the property does not
|
|
* exist, -ENODATA if property does not have a value, and -EILSEQ if the string
|
|
* is not null-terminated within the length of the property data.
|
|
*/
|
|
static inline int of_property_count_strings(const struct device_node *np,
|
|
const char *propname)
|
|
{
|
|
return of_property_read_string_helper(np, propname, NULL, 0, 0);
|
|
}
|
|
|
|
/**
|
|
* of_property_read_string_index() - Find and read a string from a multiple
|
|
* strings property.
|
|
* @np: device node from which the property value is to be read.
|
|
* @propname: name of the property to be searched.
|
|
* @index: index of the string in the list of strings
|
|
* @output: pointer to null terminated return string, modified only if
|
|
* return value is 0.
|
|
*
|
|
* Search for a property in a device tree node and retrieve a null
|
|
* terminated string value (pointer to data, not a copy) in the list of strings
|
|
* contained in that property.
|
|
*
|
|
* Return: 0 on success, -EINVAL if the property does not exist, -ENODATA if
|
|
* property does not have a value, and -EILSEQ if the string is not
|
|
* null-terminated within the length of the property data.
|
|
*
|
|
* The out_string pointer is modified only if a valid string can be decoded.
|
|
*/
|
|
static inline int of_property_read_string_index(const struct device_node *np,
|
|
const char *propname,
|
|
int index, const char **output)
|
|
{
|
|
int rc = of_property_read_string_helper(np, propname, output, 1, index);
|
|
return rc < 0 ? rc : 0;
|
|
}
|
|
|
|
/**
|
|
* of_property_read_bool - Find a property
|
|
* @np: device node from which the property value is to be read.
|
|
* @propname: name of the property to be searched.
|
|
*
|
|
* Search for a boolean property in a device node. Usage on non-boolean
|
|
* property types is deprecated.
|
|
*
|
|
* Return: true if the property exists false otherwise.
|
|
*/
|
|
static inline bool of_property_read_bool(const struct device_node *np,
|
|
const char *propname)
|
|
{
|
|
struct property *prop = of_find_property(np, propname, NULL);
|
|
|
|
return prop ? true : false;
|
|
}
|
|
|
|
/**
|
|
* of_property_present - Test if a property is present in a node
|
|
* @np: device node to search for the property.
|
|
* @propname: name of the property to be searched.
|
|
*
|
|
* Test for a property present in a device node.
|
|
*
|
|
* Return: true if the property exists false otherwise.
|
|
*/
|
|
static inline bool of_property_present(const struct device_node *np, const char *propname)
|
|
{
|
|
return of_property_read_bool(np, propname);
|
|
}
|
|
|
|
/**
|
|
* of_property_read_u8_array - Find and read an array of u8 from a property.
|
|
*
|
|
* @np: device node from which the property value is to be read.
|
|
* @propname: name of the property to be searched.
|
|
* @out_values: pointer to return value, modified only if return value is 0.
|
|
* @sz: number of array elements to read
|
|
*
|
|
* Search for a property in a device node and read 8-bit value(s) from
|
|
* it.
|
|
*
|
|
* dts entry of array should be like:
|
|
* ``property = /bits/ 8 <0x50 0x60 0x70>;``
|
|
*
|
|
* Return: 0 on success, -EINVAL if the property does not exist,
|
|
* -ENODATA if property does not have a value, and -EOVERFLOW if the
|
|
* property data isn't large enough.
|
|
*
|
|
* The out_values is modified only if a valid u8 value can be decoded.
|
|
*/
|
|
static inline int of_property_read_u8_array(const struct device_node *np,
|
|
const char *propname,
|
|
u8 *out_values, size_t sz)
|
|
{
|
|
int ret = of_property_read_variable_u8_array(np, propname, out_values,
|
|
sz, 0);
|
|
if (ret >= 0)
|
|
return 0;
|
|
else
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* of_property_read_u16_array - Find and read an array of u16 from a property.
|
|
*
|
|
* @np: device node from which the property value is to be read.
|
|
* @propname: name of the property to be searched.
|
|
* @out_values: pointer to return value, modified only if return value is 0.
|
|
* @sz: number of array elements to read
|
|
*
|
|
* Search for a property in a device node and read 16-bit value(s) from
|
|
* it.
|
|
*
|
|
* dts entry of array should be like:
|
|
* ``property = /bits/ 16 <0x5000 0x6000 0x7000>;``
|
|
*
|
|
* Return: 0 on success, -EINVAL if the property does not exist,
|
|
* -ENODATA if property does not have a value, and -EOVERFLOW if the
|
|
* property data isn't large enough.
|
|
*
|
|
* The out_values is modified only if a valid u16 value can be decoded.
|
|
*/
|
|
static inline int of_property_read_u16_array(const struct device_node *np,
|
|
const char *propname,
|
|
u16 *out_values, size_t sz)
|
|
{
|
|
int ret = of_property_read_variable_u16_array(np, propname, out_values,
|
|
sz, 0);
|
|
if (ret >= 0)
|
|
return 0;
|
|
else
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* of_property_read_u32_array - Find and read an array of 32 bit integers
|
|
* from a property.
|
|
*
|
|
* @np: device node from which the property value is to be read.
|
|
* @propname: name of the property to be searched.
|
|
* @out_values: pointer to return value, modified only if return value is 0.
|
|
* @sz: number of array elements to read
|
|
*
|
|
* Search for a property in a device node and read 32-bit value(s) from
|
|
* it.
|
|
*
|
|
* Return: 0 on success, -EINVAL if the property does not exist,
|
|
* -ENODATA if property does not have a value, and -EOVERFLOW if the
|
|
* property data isn't large enough.
|
|
*
|
|
* The out_values is modified only if a valid u32 value can be decoded.
|
|
*/
|
|
static inline int of_property_read_u32_array(const struct device_node *np,
|
|
const char *propname,
|
|
u32 *out_values, size_t sz)
|
|
{
|
|
int ret = of_property_read_variable_u32_array(np, propname, out_values,
|
|
sz, 0);
|
|
if (ret >= 0)
|
|
return 0;
|
|
else
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* of_property_read_u64_array - Find and read an array of 64 bit integers
|
|
* from a property.
|
|
*
|
|
* @np: device node from which the property value is to be read.
|
|
* @propname: name of the property to be searched.
|
|
* @out_values: pointer to return value, modified only if return value is 0.
|
|
* @sz: number of array elements to read
|
|
*
|
|
* Search for a property in a device node and read 64-bit value(s) from
|
|
* it.
|
|
*
|
|
* Return: 0 on success, -EINVAL if the property does not exist,
|
|
* -ENODATA if property does not have a value, and -EOVERFLOW if the
|
|
* property data isn't large enough.
|
|
*
|
|
* The out_values is modified only if a valid u64 value can be decoded.
|
|
*/
|
|
static inline int of_property_read_u64_array(const struct device_node *np,
|
|
const char *propname,
|
|
u64 *out_values, size_t sz)
|
|
{
|
|
int ret = of_property_read_variable_u64_array(np, propname, out_values,
|
|
sz, 0);
|
|
if (ret >= 0)
|
|
return 0;
|
|
else
|
|
return ret;
|
|
}
|
|
|
|
static inline int of_property_read_u8(const struct device_node *np,
|
|
const char *propname,
|
|
u8 *out_value)
|
|
{
|
|
return of_property_read_u8_array(np, propname, out_value, 1);
|
|
}
|
|
|
|
static inline int of_property_read_u16(const struct device_node *np,
|
|
const char *propname,
|
|
u16 *out_value)
|
|
{
|
|
return of_property_read_u16_array(np, propname, out_value, 1);
|
|
}
|
|
|
|
static inline int of_property_read_u32(const struct device_node *np,
|
|
const char *propname,
|
|
u32 *out_value)
|
|
{
|
|
return of_property_read_u32_array(np, propname, out_value, 1);
|
|
}
|
|
|
|
static inline int of_property_read_s32(const struct device_node *np,
|
|
const char *propname,
|
|
s32 *out_value)
|
|
{
|
|
return of_property_read_u32(np, propname, (u32*) out_value);
|
|
}
|
|
|
|
#define of_for_each_phandle(it, err, np, ln, cn, cc) \
|
|
for (of_phandle_iterator_init((it), (np), (ln), (cn), (cc)), \
|
|
err = of_phandle_iterator_next(it); \
|
|
err == 0; \
|
|
err = of_phandle_iterator_next(it))
|
|
|
|
#define of_property_for_each_u32(np, propname, u) \
|
|
for (struct {struct property *prop; const __be32 *item; } _it = \
|
|
{of_find_property(np, propname, NULL), \
|
|
of_prop_next_u32(_it.prop, NULL, &u)}; \
|
|
_it.item; \
|
|
_it.item = of_prop_next_u32(_it.prop, _it.item, &u))
|
|
|
|
#define of_property_for_each_string(np, propname, prop, s) \
|
|
for (prop = of_find_property(np, propname, NULL), \
|
|
s = of_prop_next_string(prop, NULL); \
|
|
s; \
|
|
s = of_prop_next_string(prop, s))
|
|
|
|
#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_type(dn, type) \
|
|
for (dn = of_find_node_by_type(NULL, type); dn; \
|
|
dn = of_find_node_by_type(dn, type))
|
|
#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))
|
|
#define for_each_matching_node(dn, matches) \
|
|
for (dn = of_find_matching_node(NULL, matches); dn; \
|
|
dn = of_find_matching_node(dn, matches))
|
|
#define for_each_matching_node_and_match(dn, matches, match) \
|
|
for (dn = of_find_matching_node_and_match(NULL, matches, match); \
|
|
dn; dn = of_find_matching_node_and_match(dn, matches, match))
|
|
|
|
#define for_each_child_of_node(parent, child) \
|
|
for (child = of_get_next_child(parent, NULL); child != NULL; \
|
|
child = of_get_next_child(parent, child))
|
|
|
|
#define for_each_child_of_node_scoped(parent, child) \
|
|
for (struct device_node *child __free(device_node) = \
|
|
of_get_next_child(parent, NULL); \
|
|
child != NULL; \
|
|
child = of_get_next_child(parent, child))
|
|
|
|
#define for_each_available_child_of_node(parent, child) \
|
|
for (child = of_get_next_available_child(parent, NULL); child != NULL; \
|
|
child = of_get_next_available_child(parent, child))
|
|
#define for_each_reserved_child_of_node(parent, child) \
|
|
for (child = of_get_next_reserved_child(parent, NULL); child != NULL; \
|
|
child = of_get_next_reserved_child(parent, child))
|
|
|
|
#define for_each_available_child_of_node_scoped(parent, child) \
|
|
for (struct device_node *child __free(device_node) = \
|
|
of_get_next_available_child(parent, NULL); \
|
|
child != NULL; \
|
|
child = of_get_next_available_child(parent, child))
|
|
|
|
#define for_each_of_cpu_node(cpu) \
|
|
for (cpu = of_get_next_cpu_node(NULL); cpu != NULL; \
|
|
cpu = of_get_next_cpu_node(cpu))
|
|
|
|
#define for_each_node_with_property(dn, prop_name) \
|
|
for (dn = of_find_node_with_property(NULL, prop_name); dn; \
|
|
dn = of_find_node_with_property(dn, prop_name))
|
|
|
|
static inline int of_get_child_count(const struct device_node *np)
|
|
{
|
|
struct device_node *child;
|
|
int num = 0;
|
|
|
|
for_each_child_of_node(np, child)
|
|
num++;
|
|
|
|
return num;
|
|
}
|
|
|
|
static inline int of_get_available_child_count(const struct device_node *np)
|
|
{
|
|
struct device_node *child;
|
|
int num = 0;
|
|
|
|
for_each_available_child_of_node(np, child)
|
|
num++;
|
|
|
|
return num;
|
|
}
|
|
|
|
#define _OF_DECLARE_STUB(table, name, compat, fn, fn_type) \
|
|
static const struct of_device_id __of_table_##name \
|
|
__attribute__((unused)) \
|
|
= { .compatible = compat, \
|
|
.data = (fn == (fn_type)NULL) ? fn : fn }
|
|
|
|
#if defined(CONFIG_OF) && !defined(MODULE)
|
|
#define _OF_DECLARE(table, name, compat, fn, fn_type) \
|
|
static const struct of_device_id __of_table_##name \
|
|
__used __section("__" #table "_of_table") \
|
|
__aligned(__alignof__(struct of_device_id)) \
|
|
= { .compatible = compat, \
|
|
.data = (fn == (fn_type)NULL) ? fn : fn }
|
|
#else
|
|
#define _OF_DECLARE(table, name, compat, fn, fn_type) \
|
|
_OF_DECLARE_STUB(table, name, compat, fn, fn_type)
|
|
#endif
|
|
|
|
typedef int (*of_init_fn_2)(struct device_node *, struct device_node *);
|
|
typedef int (*of_init_fn_1_ret)(struct device_node *);
|
|
typedef void (*of_init_fn_1)(struct device_node *);
|
|
|
|
#define OF_DECLARE_1(table, name, compat, fn) \
|
|
_OF_DECLARE(table, name, compat, fn, of_init_fn_1)
|
|
#define OF_DECLARE_1_RET(table, name, compat, fn) \
|
|
_OF_DECLARE(table, name, compat, fn, of_init_fn_1_ret)
|
|
#define OF_DECLARE_2(table, name, compat, fn) \
|
|
_OF_DECLARE(table, name, compat, fn, of_init_fn_2)
|
|
|
|
/**
|
|
* struct of_changeset_entry - Holds a changeset entry
|
|
*
|
|
* @node: list_head for the log list
|
|
* @action: notifier action
|
|
* @np: pointer to the device node affected
|
|
* @prop: pointer to the property affected
|
|
* @old_prop: hold a pointer to the original property
|
|
*
|
|
* Every modification of the device tree during a changeset
|
|
* is held in a list of of_changeset_entry structures.
|
|
* That way we can recover from a partial application, or we can
|
|
* revert the changeset
|
|
*/
|
|
struct of_changeset_entry {
|
|
struct list_head node;
|
|
unsigned long action;
|
|
struct device_node *np;
|
|
struct property *prop;
|
|
struct property *old_prop;
|
|
};
|
|
|
|
/**
|
|
* struct of_changeset - changeset tracker structure
|
|
*
|
|
* @entries: list_head for the changeset entries
|
|
*
|
|
* changesets are a convenient way to apply bulk changes to the
|
|
* live tree. In case of an error, changes are rolled-back.
|
|
* changesets live on after initial application, and if not
|
|
* destroyed after use, they can be reverted in one single call.
|
|
*/
|
|
struct of_changeset {
|
|
struct list_head entries;
|
|
};
|
|
|
|
enum of_reconfig_change {
|
|
OF_RECONFIG_NO_CHANGE = 0,
|
|
OF_RECONFIG_CHANGE_ADD,
|
|
OF_RECONFIG_CHANGE_REMOVE,
|
|
};
|
|
|
|
struct notifier_block;
|
|
|
|
#ifdef CONFIG_OF_DYNAMIC
|
|
extern int of_reconfig_notifier_register(struct notifier_block *);
|
|
extern int of_reconfig_notifier_unregister(struct notifier_block *);
|
|
extern int of_reconfig_notify(unsigned long, struct of_reconfig_data *rd);
|
|
extern int of_reconfig_get_state_change(unsigned long action,
|
|
struct of_reconfig_data *arg);
|
|
|
|
extern void of_changeset_init(struct of_changeset *ocs);
|
|
extern void of_changeset_destroy(struct of_changeset *ocs);
|
|
extern int of_changeset_apply(struct of_changeset *ocs);
|
|
extern int of_changeset_revert(struct of_changeset *ocs);
|
|
extern int of_changeset_action(struct of_changeset *ocs,
|
|
unsigned long action, struct device_node *np,
|
|
struct property *prop);
|
|
|
|
static inline int of_changeset_attach_node(struct of_changeset *ocs,
|
|
struct device_node *np)
|
|
{
|
|
return of_changeset_action(ocs, OF_RECONFIG_ATTACH_NODE, np, NULL);
|
|
}
|
|
|
|
static inline int of_changeset_detach_node(struct of_changeset *ocs,
|
|
struct device_node *np)
|
|
{
|
|
return of_changeset_action(ocs, OF_RECONFIG_DETACH_NODE, np, NULL);
|
|
}
|
|
|
|
static inline int of_changeset_add_property(struct of_changeset *ocs,
|
|
struct device_node *np, struct property *prop)
|
|
{
|
|
return of_changeset_action(ocs, OF_RECONFIG_ADD_PROPERTY, np, prop);
|
|
}
|
|
|
|
static inline int of_changeset_remove_property(struct of_changeset *ocs,
|
|
struct device_node *np, struct property *prop)
|
|
{
|
|
return of_changeset_action(ocs, OF_RECONFIG_REMOVE_PROPERTY, np, prop);
|
|
}
|
|
|
|
static inline int of_changeset_update_property(struct of_changeset *ocs,
|
|
struct device_node *np, struct property *prop)
|
|
{
|
|
return of_changeset_action(ocs, OF_RECONFIG_UPDATE_PROPERTY, np, prop);
|
|
}
|
|
|
|
struct device_node *of_changeset_create_node(struct of_changeset *ocs,
|
|
struct device_node *parent,
|
|
const char *full_name);
|
|
int of_changeset_add_prop_string(struct of_changeset *ocs,
|
|
struct device_node *np,
|
|
const char *prop_name, const char *str);
|
|
int of_changeset_add_prop_string_array(struct of_changeset *ocs,
|
|
struct device_node *np,
|
|
const char *prop_name,
|
|
const char * const *str_array, size_t sz);
|
|
int of_changeset_add_prop_u32_array(struct of_changeset *ocs,
|
|
struct device_node *np,
|
|
const char *prop_name,
|
|
const u32 *array, size_t sz);
|
|
static inline int of_changeset_add_prop_u32(struct of_changeset *ocs,
|
|
struct device_node *np,
|
|
const char *prop_name,
|
|
const u32 val)
|
|
{
|
|
return of_changeset_add_prop_u32_array(ocs, np, prop_name, &val, 1);
|
|
}
|
|
|
|
int of_changeset_add_prop_bool(struct of_changeset *ocs, struct device_node *np,
|
|
const char *prop_name);
|
|
|
|
#else /* CONFIG_OF_DYNAMIC */
|
|
static inline int of_reconfig_notifier_register(struct notifier_block *nb)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
static inline int of_reconfig_notifier_unregister(struct notifier_block *nb)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
static inline int of_reconfig_notify(unsigned long action,
|
|
struct of_reconfig_data *arg)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
static inline int of_reconfig_get_state_change(unsigned long action,
|
|
struct of_reconfig_data *arg)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
#endif /* CONFIG_OF_DYNAMIC */
|
|
|
|
/**
|
|
* of_device_is_system_power_controller - Tells if system-power-controller is found for device_node
|
|
* @np: Pointer to the given device_node
|
|
*
|
|
* Return: true if present false otherwise
|
|
*/
|
|
static inline bool of_device_is_system_power_controller(const struct device_node *np)
|
|
{
|
|
return of_property_read_bool(np, "system-power-controller");
|
|
}
|
|
|
|
/**
|
|
* of_have_populated_dt() - Has DT been populated by bootloader
|
|
*
|
|
* Return: True if a DTB has been populated by the bootloader and it isn't the
|
|
* empty builtin one. False otherwise.
|
|
*/
|
|
static inline bool of_have_populated_dt(void)
|
|
{
|
|
#ifdef CONFIG_OF
|
|
return of_property_present(of_root, "compatible");
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Overlay support
|
|
*/
|
|
|
|
enum of_overlay_notify_action {
|
|
OF_OVERLAY_INIT = 0, /* kzalloc() of ovcs sets this value */
|
|
OF_OVERLAY_PRE_APPLY,
|
|
OF_OVERLAY_POST_APPLY,
|
|
OF_OVERLAY_PRE_REMOVE,
|
|
OF_OVERLAY_POST_REMOVE,
|
|
};
|
|
|
|
static inline const char *of_overlay_action_name(enum of_overlay_notify_action action)
|
|
{
|
|
static const char *const of_overlay_action_name[] = {
|
|
"init",
|
|
"pre-apply",
|
|
"post-apply",
|
|
"pre-remove",
|
|
"post-remove",
|
|
};
|
|
|
|
return of_overlay_action_name[action];
|
|
}
|
|
|
|
struct of_overlay_notify_data {
|
|
struct device_node *overlay;
|
|
struct device_node *target;
|
|
};
|
|
|
|
#ifdef CONFIG_OF_OVERLAY
|
|
|
|
int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size,
|
|
int *ovcs_id, struct device_node *target_base);
|
|
int of_overlay_remove(int *ovcs_id);
|
|
int of_overlay_remove_all(void);
|
|
|
|
int of_overlay_notifier_register(struct notifier_block *nb);
|
|
int of_overlay_notifier_unregister(struct notifier_block *nb);
|
|
|
|
#else
|
|
|
|
static inline int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size,
|
|
int *ovcs_id, struct device_node *target_base)
|
|
{
|
|
return -ENOTSUPP;
|
|
}
|
|
|
|
static inline int of_overlay_remove(int *ovcs_id)
|
|
{
|
|
return -ENOTSUPP;
|
|
}
|
|
|
|
static inline int of_overlay_remove_all(void)
|
|
{
|
|
return -ENOTSUPP;
|
|
}
|
|
|
|
static inline int of_overlay_notifier_register(struct notifier_block *nb)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline int of_overlay_notifier_unregister(struct notifier_block *nb)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif /* _LINUX_OF_H */
|