2017-12-28 02:55:14 +08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
2007-05-01 14:19:07 +08:00
|
|
|
#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>
|
2007-10-19 14:40:25 +08:00
|
|
|
#include <linux/bitops.h>
|
2011-10-06 20:40:44 +08:00
|
|
|
#include <linux/errno.h>
|
2014-02-21 02:02:11 +08:00
|
|
|
#include <linux/kobject.h>
|
2008-01-09 03:20:40 +08:00
|
|
|
#include <linux/mod_devicetable.h>
|
2010-02-15 05:13:57 +08:00
|
|
|
#include <linux/spinlock.h>
|
2012-06-04 13:04:34 +08:00
|
|
|
#include <linux/topology.h>
|
2012-10-03 00:57:57 +08:00
|
|
|
#include <linux/notifier.h>
|
2014-11-04 08:28:56 +08:00
|
|
|
#include <linux/property.h>
|
2014-10-29 04:35:58 +08:00
|
|
|
#include <linux/list.h>
|
2007-05-01 14:19:07 +08:00
|
|
|
|
2010-01-30 16:41:49 +08:00
|
|
|
#include <asm/byteorder.h>
|
2011-10-29 22:17:06 +08:00
|
|
|
#include <asm/errno.h>
|
2010-01-30 16:41:49 +08:00
|
|
|
|
2009-10-16 00:57:46 +08:00
|
|
|
typedef u32 phandle;
|
|
|
|
typedef u32 ihandle;
|
|
|
|
|
|
|
|
struct property {
|
|
|
|
char *name;
|
|
|
|
int length;
|
|
|
|
void *value;
|
|
|
|
struct property *next;
|
2017-10-05 03:30:02 +08:00
|
|
|
#if defined(CONFIG_OF_DYNAMIC) || defined(CONFIG_SPARC)
|
2009-10-16 00:57:46 +08:00
|
|
|
unsigned long _flags;
|
2017-10-05 03:30:02 +08:00
|
|
|
#endif
|
2017-09-30 09:08:28 +08:00
|
|
|
#if defined(CONFIG_OF_PROMTREE)
|
2009-10-16 00:57:46 +08:00
|
|
|
unsigned int unique_id;
|
2017-09-30 09:08:28 +08:00
|
|
|
#endif
|
2017-10-05 03:09:40 +08:00
|
|
|
#if defined(CONFIG_OF_KOBJ)
|
2014-02-21 02:02:11 +08:00
|
|
|
struct bin_attribute attr;
|
2017-10-05 03:09:40 +08:00
|
|
|
#endif
|
2009-10-16 00:57:46 +08:00
|
|
|
};
|
|
|
|
|
2009-10-16 00:57:49 +08:00
|
|
|
#if defined(CONFIG_SPARC)
|
|
|
|
struct of_irq_controller;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
struct device_node {
|
|
|
|
const char *name;
|
2010-01-29 05:06:53 +08:00
|
|
|
phandle phandle;
|
2012-11-15 06:37:12 +08:00
|
|
|
const char *full_name;
|
2014-11-04 21:03:59 +08:00
|
|
|
struct fwnode_handle fwnode;
|
2009-10-16 00:57:49 +08:00
|
|
|
|
|
|
|
struct property *properties;
|
|
|
|
struct property *deadprops; /* removed properties */
|
|
|
|
struct device_node *parent;
|
|
|
|
struct device_node *child;
|
|
|
|
struct device_node *sibling;
|
2017-10-05 03:09:40 +08:00
|
|
|
#if defined(CONFIG_OF_KOBJ)
|
2014-02-21 02:02:11 +08:00
|
|
|
struct kobject kobj;
|
2017-10-05 03:09:40 +08:00
|
|
|
#endif
|
2009-10-16 00:57:49 +08:00
|
|
|
unsigned long _flags;
|
|
|
|
void *data;
|
|
|
|
#if defined(CONFIG_SPARC)
|
|
|
|
unsigned int unique_id;
|
|
|
|
struct of_irq_controller *irq_trans;
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2014-01-17 19:08:30 +08:00
|
|
|
#define MAX_PHANDLE_ARGS 16
|
2011-12-13 00:25:57 +08:00
|
|
|
struct of_phandle_args {
|
|
|
|
struct device_node *np;
|
|
|
|
int args_count;
|
|
|
|
uint32_t args[MAX_PHANDLE_ARGS];
|
|
|
|
};
|
|
|
|
|
2016-04-04 23:49:17 +08:00
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2014-11-25 01:58:01 +08:00
|
|
|
struct of_reconfig_data {
|
|
|
|
struct device_node *dn;
|
|
|
|
struct property *prop;
|
|
|
|
struct property *old_prop;
|
|
|
|
};
|
|
|
|
|
2013-12-14 02:08:59 +08:00
|
|
|
/* initialize a node */
|
|
|
|
extern struct kobj_type of_node_ktype;
|
2017-06-06 17:37:37 +08:00
|
|
|
extern const struct fwnode_operations of_fwnode_ops;
|
2013-12-14 02:08:59 +08:00
|
|
|
static inline void of_node_init(struct device_node *node)
|
|
|
|
{
|
2017-10-05 03:09:40 +08:00
|
|
|
#if defined(CONFIG_OF_KOBJ)
|
2013-12-14 02:08:59 +08:00
|
|
|
kobject_init(&node->kobj, &of_node_ktype);
|
2017-10-05 03:09:40 +08:00
|
|
|
#endif
|
2020-11-21 10:02:22 +08:00
|
|
|
fwnode_init(&node->fwnode, &of_fwnode_ops);
|
2013-12-14 02:08:59 +08:00
|
|
|
}
|
|
|
|
|
2017-10-05 03:09:40 +08:00
|
|
|
#if defined(CONFIG_OF_KOBJ)
|
2017-10-05 03:04:01 +08:00
|
|
|
#define of_node_kobj(n) (&(n)->kobj)
|
2017-10-05 03:09:40 +08:00
|
|
|
#else
|
|
|
|
#define of_node_kobj(n) NULL
|
|
|
|
#endif
|
2013-12-14 02:08:59 +08:00
|
|
|
|
2012-02-16 11:38:40 +08:00
|
|
|
#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 */
|
2011-12-13 23:13:54 +08:00
|
|
|
/* Dummy ref counting routines - to be implemented later */
|
|
|
|
static inline struct device_node *of_node_get(struct device_node *node)
|
|
|
|
{
|
|
|
|
return node;
|
|
|
|
}
|
2012-02-16 11:38:40 +08:00
|
|
|
static inline void of_node_put(struct device_node *node) { }
|
|
|
|
#endif /* !CONFIG_OF_DYNAMIC */
|
2011-12-13 23:13:54 +08:00
|
|
|
|
2009-11-24 11:07:01 +08:00
|
|
|
/* Pointer for first entry in chain of all nodes. */
|
2014-10-03 23:28:27 +08:00
|
|
|
extern struct device_node *of_root;
|
2010-02-14 22:13:55 +08:00
|
|
|
extern struct device_node *of_chosen;
|
2011-08-15 15:28:14 +08:00
|
|
|
extern struct device_node *of_aliases;
|
2014-03-28 23:12:18 +08:00
|
|
|
extern struct device_node *of_stdout;
|
2013-02-07 04:30:56 +08:00
|
|
|
extern raw_spinlock_t devtree_lock;
|
2009-11-24 11:07:01 +08:00
|
|
|
|
2018-10-05 11:24:17 +08:00
|
|
|
/*
|
|
|
|
* 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 */
|
2015-04-24 17:41:56 +08:00
|
|
|
|
2015-11-07 11:28:22 +08:00
|
|
|
#define OF_BAD_ADDR ((u64)-1)
|
|
|
|
|
2014-11-14 20:26:52 +08:00
|
|
|
#ifdef CONFIG_OF
|
2015-05-14 22:28:24 +08:00
|
|
|
void of_core_init(void);
|
|
|
|
|
2017-05-24 22:53:55 +08:00
|
|
|
static inline bool is_of_node(const struct fwnode_handle *fwnode)
|
2014-11-04 21:03:59 +08:00
|
|
|
{
|
2017-07-21 19:39:31 +08:00
|
|
|
return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &of_fwnode_ops;
|
2014-11-04 21:03:59 +08:00
|
|
|
}
|
|
|
|
|
2017-05-24 22:53:55 +08:00
|
|
|
#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; \
|
|
|
|
})
|
2014-11-04 21:03:59 +08:00
|
|
|
|
2017-05-24 22:53:54 +08:00
|
|
|
#define of_fwnode_handle(node) \
|
|
|
|
({ \
|
|
|
|
typeof(node) __of_fwnode_handle_node = (node); \
|
|
|
|
\
|
|
|
|
__of_fwnode_handle_node ? \
|
|
|
|
&__of_fwnode_handle_node->fwnode : NULL; \
|
|
|
|
})
|
2017-03-28 15:52:23 +08:00
|
|
|
|
2011-02-23 04:07:46 +08:00
|
|
|
static inline bool of_have_populated_dt(void)
|
|
|
|
{
|
2014-10-03 23:28:27 +08:00
|
|
|
return of_root != NULL;
|
2011-02-23 04:07:46 +08:00
|
|
|
}
|
|
|
|
|
2010-07-13 17:42:26 +08:00
|
|
|
static inline bool of_node_is_root(const struct device_node *node)
|
|
|
|
{
|
|
|
|
return node && (node->parent == NULL);
|
|
|
|
}
|
|
|
|
|
2021-10-15 01:30:55 +08:00
|
|
|
static inline int of_node_check_flag(const struct device_node *n, unsigned long flag)
|
2009-10-16 00:57:58 +08:00
|
|
|
{
|
|
|
|
return test_bit(flag, &n->_flags);
|
|
|
|
}
|
|
|
|
|
2014-05-15 23:55:24 +08:00
|
|
|
static inline int of_node_test_and_set_flag(struct device_node *n,
|
|
|
|
unsigned long flag)
|
|
|
|
{
|
|
|
|
return test_and_set_bit(flag, &n->_flags);
|
|
|
|
}
|
|
|
|
|
2009-10-16 00:57:58 +08:00
|
|
|
static inline void of_node_set_flag(struct device_node *n, unsigned long flag)
|
|
|
|
{
|
|
|
|
set_bit(flag, &n->_flags);
|
|
|
|
}
|
|
|
|
|
2013-11-08 23:03:56 +08:00
|
|
|
static inline void of_node_clear_flag(struct device_node *n, unsigned long flag)
|
|
|
|
{
|
|
|
|
clear_bit(flag, &n->_flags);
|
|
|
|
}
|
|
|
|
|
2017-10-05 03:30:02 +08:00
|
|
|
#if defined(CONFIG_OF_DYNAMIC) || defined(CONFIG_SPARC)
|
2013-11-08 23:03:56 +08:00
|
|
|
static inline int of_property_check_flag(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);
|
|
|
|
}
|
2017-10-05 03:30:02 +08:00
|
|
|
#endif
|
2013-11-08 23:03:56 +08:00
|
|
|
|
2014-10-03 23:28:27 +08:00
|
|
|
extern struct device_node *__of_find_all_nodes(struct device_node *prev);
|
2009-10-16 00:58:09 +08:00
|
|
|
extern struct device_node *of_find_all_nodes(struct device_node *prev);
|
|
|
|
|
2009-10-16 00:58:00 +08:00
|
|
|
/*
|
2011-02-23 01:18:51 +08:00
|
|
|
* OF address retrieval & translation
|
2009-10-16 00:58:00 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* Helper to read a big number; size is in cells (not bytes) */
|
2010-01-30 16:41:49 +08:00
|
|
|
static inline u64 of_read_number(const __be32 *cell, int size)
|
2009-10-16 00:58:00 +08:00
|
|
|
{
|
|
|
|
u64 r = 0;
|
2019-04-30 22:56:24 +08:00
|
|
|
for (; size--; cell++)
|
|
|
|
r = (r << 32) | be32_to_cpu(*cell);
|
2009-10-16 00:58:00 +08:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Like of_read_number, but we want an unsigned long result */
|
2010-01-30 16:41:49 +08:00
|
|
|
static inline unsigned long of_read_ulong(const __be32 *cell, int size)
|
2009-10-16 00:58:00 +08:00
|
|
|
{
|
2009-11-24 11:16:46 +08:00
|
|
|
/* toss away upper bits if unsigned long is smaller than u64 */
|
|
|
|
return of_read_number(cell, size);
|
2009-10-16 00:58:00 +08:00
|
|
|
}
|
|
|
|
|
2013-09-08 03:08:20 +08:00
|
|
|
#if defined(CONFIG_SPARC)
|
2007-05-01 14:19:07 +08:00
|
|
|
#include <asm/prom.h>
|
2013-09-08 03:08:20 +08:00
|
|
|
#endif
|
2007-05-01 14:19:07 +08:00
|
|
|
|
2009-10-16 00:57:51 +08:00
|
|
|
#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
|
|
|
|
#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
|
|
|
|
|
2018-08-27 20:50:47 +08:00
|
|
|
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);
|
|
|
|
|
2012-12-18 18:32:03 +08:00
|
|
|
static inline const char *of_node_full_name(const struct device_node *np)
|
2012-06-16 01:50:25 +08:00
|
|
|
{
|
|
|
|
return np ? np->full_name : "<no-node>";
|
|
|
|
}
|
|
|
|
|
2014-10-03 23:28:27 +08:00
|
|
|
#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)
|
2007-05-01 14:19:07 +08:00
|
|
|
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);
|
2012-11-21 07:12:20 +08:00
|
|
|
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);
|
2014-02-03 22:53:44 +08:00
|
|
|
|
2014-11-28 19:34:28 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2007-05-01 14:19:07 +08:00
|
|
|
extern struct device_node *of_find_node_by_phandle(phandle handle);
|
|
|
|
extern struct device_node *of_get_parent(const struct device_node *node);
|
2007-10-26 14:54:31 +08:00
|
|
|
extern struct device_node *of_get_next_parent(struct device_node *node);
|
2007-05-01 14:19:07 +08:00
|
|
|
extern struct device_node *of_get_next_child(const struct device_node *node,
|
|
|
|
struct device_node *prev);
|
2012-08-14 21:20:23 +08:00
|
|
|
extern struct device_node *of_get_next_available_child(
|
|
|
|
const struct device_node *node, struct device_node *prev);
|
|
|
|
|
2018-08-27 16:21:45 +08:00
|
|
|
extern struct device_node *of_get_compatible_child(const struct device_node *parent,
|
|
|
|
const char *compatible);
|
2012-09-18 15:10:28 +08:00
|
|
|
extern struct device_node *of_get_child_by_name(const struct device_node *node,
|
|
|
|
const char *name);
|
2013-09-25 01:38:26 +08:00
|
|
|
|
2013-09-18 18:53:05 +08:00
|
|
|
/* cache lookup */
|
|
|
|
extern struct device_node *of_find_next_cache_node(const struct device_node *);
|
2017-01-16 18:40:43 +08:00
|
|
|
extern int of_find_last_cache_level(unsigned int cpu);
|
2008-11-13 02:54:42 +08:00
|
|
|
extern struct device_node *of_find_node_with_property(
|
|
|
|
struct device_node *from, const char *prop_name);
|
|
|
|
|
2007-05-01 14:19:07 +08:00
|
|
|
extern struct property *of_find_property(const struct device_node *np,
|
|
|
|
const char *name,
|
|
|
|
int *lenp);
|
2014-02-12 08:00:34 +08:00
|
|
|
extern int of_property_count_elems_of_size(const struct device_node *np,
|
|
|
|
const char *propname, int elem_size);
|
2013-03-23 12:02:15 +08:00
|
|
|
extern int of_property_read_u32_index(const struct device_node *np,
|
|
|
|
const char *propname,
|
|
|
|
u32 index, u32 *out_value);
|
2017-04-03 17:51:42 +08:00
|
|
|
extern int of_property_read_u64_index(const struct device_node *np,
|
|
|
|
const char *propname,
|
|
|
|
u32 index, u64 *out_value);
|
2016-09-12 21:01:29 +08:00
|
|
|
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);
|
2011-09-15 03:49:59 +08:00
|
|
|
extern int of_property_read_u64(const struct device_node *np,
|
|
|
|
const char *propname, u64 *out_value);
|
2016-09-12 21:01:29 +08:00
|
|
|
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);
|
2011-07-07 04:42:58 +08:00
|
|
|
|
2016-03-03 05:35:51 +08:00
|
|
|
extern int of_property_read_string(const struct device_node *np,
|
2011-08-02 22:45:07 +08:00
|
|
|
const char *propname,
|
|
|
|
const char **out_string);
|
2016-03-03 05:35:51 +08:00
|
|
|
extern int of_property_match_string(const struct device_node *np,
|
2011-12-13 00:25:58 +08:00
|
|
|
const char *propname,
|
|
|
|
const char *string);
|
2016-03-03 05:35:51 +08:00
|
|
|
extern int of_property_read_string_helper(const struct device_node *np,
|
2014-11-03 23:15:35 +08:00
|
|
|
const char *propname,
|
|
|
|
const char **out_strs, size_t sz, int index);
|
2007-05-01 14:19:07 +08:00
|
|
|
extern int of_device_is_compatible(const struct device_node *device,
|
|
|
|
const char *);
|
2016-07-08 06:35:59 +08:00
|
|
|
extern int of_device_compatible_match(struct device_node *device,
|
|
|
|
const char *const *compat);
|
2014-11-13 04:54:01 +08:00
|
|
|
extern bool of_device_is_available(const struct device_node *device);
|
2015-04-10 04:05:14 +08:00
|
|
|
extern bool of_device_is_big_endian(const struct device_node *device);
|
2007-05-01 14:19:07 +08:00
|
|
|
extern const void *of_get_property(const struct device_node *node,
|
|
|
|
const char *name,
|
|
|
|
int *lenp);
|
2013-08-15 21:01:40 +08:00
|
|
|
extern struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
|
2018-08-23 04:04:40 +08:00
|
|
|
extern struct device_node *of_get_next_cpu_node(struct device_node *prev);
|
of: base: Add of_get_cpu_state_node() to get idle states for a CPU node
The CPU's idle state nodes are currently parsed at the common cpuidle DT
library, but also when initializing data for specific CPU idle operations,
as in the PSCI cpuidle driver case and qcom-spm cpuidle case.
To avoid open-coding, let's introduce of_get_cpu_state_node(), which takes
the device node for the CPU and the index to the requested idle state node,
as in-parameters. In case a corresponding idle state node is found, it
returns the node with the refcount incremented for it, else it returns
NULL.
Moreover, for PSCI there are two options to describe the CPU's idle states
[1], either via a flattened description or a hierarchical layout. Hence,
let's take both options into account.
[1] Documentation/devicetree/bindings/arm/psci.yaml
Suggested-by: Sudeep Holla <sudeep.holla@arm.com>
Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Reviewed-by: Rob Herring <robh@kernel.org>
Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
2019-10-10 18:01:48 +08:00
|
|
|
extern struct device_node *of_get_cpu_state_node(struct device_node *cpu_node,
|
|
|
|
int index);
|
2021-10-07 00:43:21 +08:00
|
|
|
extern u64 of_get_cpu_hwid(struct device_node *cpun, unsigned int thread);
|
2018-08-23 04:04:40 +08:00
|
|
|
|
2011-12-22 20:19:24 +08:00
|
|
|
#define for_each_property_of_node(dn, pp) \
|
|
|
|
for (pp = dn->properties; pp != NULL; pp = pp->next)
|
2011-08-15 15:28:14 +08:00
|
|
|
|
2007-05-01 14:19:07 +08:00
|
|
|
extern int of_n_addr_cells(struct device_node *np);
|
|
|
|
extern int of_n_size_cells(struct device_node *np);
|
2008-01-09 03:20:40 +08:00
|
|
|
extern const struct of_device_id *of_match_node(
|
|
|
|
const struct of_device_id *matches, const struct device_node *node);
|
2008-07-26 10:25:13 +08:00
|
|
|
extern int of_modalias_node(struct device_node *node, char *modalias, int len);
|
2013-10-12 05:05:10 +08:00
|
|
|
extern void of_print_phandle_args(const char *msg, const struct of_phandle_args *args);
|
2022-01-19 01:35:02 +08:00
|
|
|
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);
|
of: Support parsing phandle argument lists through a nexus node
Platforms like 96boards have a standardized connector/expansion
slot that exposes signals like GPIOs to expansion boards in an
SoC agnostic way. We'd like the DT overlays for the expansion
boards to be written once without knowledge of the SoC on the
other side of the connector. This avoids the unscalable
combinatorial explosion of a different DT overlay for each
expansion board and SoC pair.
We need a way to describe the GPIOs routed through the connector
in an SoC agnostic way. Let's introduce nexus property parsing
into the OF core to do this. This is largely based on the
interrupt nexus support we already have. This allows us to remap
a phandle list in a consumer node (e.g. reset-gpios) through a
connector in a generic way (e.g. via gpio-map). Do this in a
generic routine so that we can remap any sort of variable length
phandle list.
Taking GPIOs as an example, the connector would be a GPIO nexus,
supporting the remapping of a GPIO specifier space to multiple
GPIO providers on the SoC. DT would look as shown below, where
'soc_gpio1' and 'soc_gpio2' are inside the SoC, 'connector' is an
expansion port where boards can be plugged in, and
'expansion_device' is a device on the expansion board.
soc {
soc_gpio1: gpio-controller1 {
#gpio-cells = <2>;
};
soc_gpio2: gpio-controller2 {
#gpio-cells = <2>;
};
};
connector: connector {
#gpio-cells = <2>;
gpio-map = <0 0 &soc_gpio1 1 0>,
<1 0 &soc_gpio2 4 0>,
<2 0 &soc_gpio1 3 0>,
<3 0 &soc_gpio2 2 0>;
gpio-map-mask = <0xf 0x0>;
gpio-map-pass-thru = <0x0 0x1>
};
expansion_device {
reset-gpios = <&connector 2 GPIO_ACTIVE_LOW>;
};
The GPIO core would use of_parse_phandle_with_args_map() instead
of of_parse_phandle_with_args() and arrive at the same type of
result, a phandle and argument list. The difference is that the
phandle and arguments will be remapped through the nexus node to
the underlying SoC GPIO controller node. In the example above,
we would remap 'reset-gpios' from <&connector 2 GPIO_ACTIVE_LOW>
to <&soc_gpio1 3 GPIO_ACTIVE_LOW>.
Cc: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Mark Brown <broonie@kernel.org>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
Signed-off-by: Rob Herring <robh@kernel.org>
2018-01-31 10:36:16 +08:00
|
|
|
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);
|
2013-02-11 06:57:21 +08:00
|
|
|
extern int of_count_phandle_with_args(const struct device_node *np,
|
|
|
|
const char *list_name, const char *cells_name);
|
2007-05-01 14:19:07 +08:00
|
|
|
|
2016-04-04 23:49:17 +08:00
|
|
|
/* 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);
|
|
|
|
|
2016-04-04 23:49:18 +08:00
|
|
|
extern int of_phandle_iterator_next(struct of_phandle_iterator *it);
|
2016-04-04 23:49:21 +08:00
|
|
|
extern int of_phandle_iterator_args(struct of_phandle_iterator *it,
|
|
|
|
uint32_t *args,
|
|
|
|
int size);
|
2016-04-04 23:49:18 +08:00
|
|
|
|
2011-08-15 15:28:14 +08:00
|
|
|
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);
|
2015-03-13 00:17:58 +08:00
|
|
|
extern int of_alias_get_highest_id(const char *stem);
|
2011-08-15 15:28:14 +08:00
|
|
|
|
2010-02-14 22:13:38 +08:00
|
|
|
extern int of_machine_is_compatible(const char *compat);
|
|
|
|
|
2012-10-03 00:58:46 +08:00
|
|
|
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);
|
2010-02-14 22:13:38 +08:00
|
|
|
|
2010-01-29 20:04:33 +08:00
|
|
|
/* For updating the device tree at runtime */
|
2012-10-03 00:57:57 +08:00
|
|
|
#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 *);
|
2010-01-29 20:04:33 +08:00
|
|
|
|
2011-08-03 17:11:42 +08:00
|
|
|
#define of_match_ptr(_ptr) (_ptr)
|
dt: add property iteration helpers
This patch adds macros of_property_for_each_u32() and
of_property_for_each_string(), which iterate over an array of values
within a device-tree property. Usage is for example:
struct property *prop;
const __be32 *p;
u32 u;
of_property_for_each_u32(np, "propname", prop, p, u)
printk("U32 value: %x\n", u);
struct property *prop;
const char *s;
of_property_for_each_string(np, "propname", prop, s)
printk("String value: %s\n", s);
Based on work by Rob Herring <robherring2@gmail.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Acked-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2012-04-04 23:27:46 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* struct property *prop;
|
|
|
|
* const __be32 *p;
|
|
|
|
* u32 u;
|
|
|
|
*
|
|
|
|
* of_property_for_each_u32(np, "propname", prop, p, 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);
|
|
|
|
|
2014-03-28 08:18:55 +08:00
|
|
|
bool of_console_check(struct device_node *dn, char *name, int index);
|
2013-08-05 20:40:44 +08:00
|
|
|
|
2018-01-02 19:25:27 +08:00
|
|
|
extern int of_cpu_node_to_id(struct device_node *np);
|
|
|
|
|
2020-06-19 16:20:07 +08:00
|
|
|
int of_map_id(struct device_node *np, u32 id,
|
2018-09-10 21:49:16 +08:00
|
|
|
const char *map_name, const char *map_mask_name,
|
|
|
|
struct device_node **target, u32 *id_out);
|
|
|
|
|
2020-11-20 01:53:55 +08:00
|
|
|
phys_addr_t of_dma_get_max_cpu_address(struct device_node *np);
|
|
|
|
|
2021-02-22 01:49:22 +08:00
|
|
|
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);
|
2021-02-22 01:49:27 +08:00
|
|
|
int ima_get_kexec_buffer(void **addr, size_t *size);
|
|
|
|
int ima_free_kexec_buffer(void);
|
2011-07-08 16:27:33 +08:00
|
|
|
#else /* CONFIG_OF */
|
2011-02-23 04:07:46 +08:00
|
|
|
|
2015-05-14 22:28:24 +08:00
|
|
|
static inline void of_core_init(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-05-24 22:53:55 +08:00
|
|
|
static inline bool is_of_node(const struct fwnode_handle *fwnode)
|
2014-11-04 21:03:59 +08:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-05-24 22:53:55 +08:00
|
|
|
static inline struct device_node *to_of_node(const struct fwnode_handle *fwnode)
|
2014-11-04 21:03:59 +08:00
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-08-27 20:50:47 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-05-15 12:44:30 +08:00
|
|
|
static inline const char* of_node_full_name(const struct device_node *np)
|
2012-06-16 01:50:25 +08:00
|
|
|
{
|
|
|
|
return "<no-node>";
|
|
|
|
}
|
|
|
|
|
2012-09-10 18:46:24 +08:00
|
|
|
static inline struct device_node *of_find_node_by_name(struct device_node *from,
|
|
|
|
const char *name)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-02-03 22:53:44 +08:00
|
|
|
static inline struct device_node *of_find_node_by_type(struct device_node *from,
|
|
|
|
const char *type)
|
2013-04-09 23:47:40 +08:00
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-02-03 22:53:44 +08:00
|
|
|
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)
|
2011-02-23 04:07:46 +08:00
|
|
|
{
|
2014-02-03 22:53:44 +08:00
|
|
|
return NULL;
|
2011-02-23 04:07:46 +08:00
|
|
|
}
|
|
|
|
|
2014-04-16 14:49:20 +08:00
|
|
|
static inline struct device_node *of_find_node_by_path(const char *path)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-11-28 19:34:28 +08:00
|
|
|
static inline struct device_node *of_find_node_opts_by_path(const char *path,
|
|
|
|
const char **opts)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-06-18 00:53:53 +08:00
|
|
|
static inline struct device_node *of_find_node_by_phandle(phandle handle)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-02-03 22:53:44 +08:00
|
|
|
static inline struct device_node *of_get_parent(const struct device_node *node)
|
2014-01-24 07:54:02 +08:00
|
|
|
{
|
2014-02-03 22:53:44 +08:00
|
|
|
return NULL;
|
2014-01-24 07:54:02 +08:00
|
|
|
}
|
|
|
|
|
2020-06-30 00:43:52 +08:00
|
|
|
static inline struct device_node *of_get_next_parent(struct device_node *node)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-02-03 22:53:44 +08:00
|
|
|
static inline struct device_node *of_get_next_child(
|
|
|
|
const struct device_node *node, struct device_node *prev)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
2011-09-22 03:23:10 +08:00
|
|
|
|
2014-02-03 22:53:44 +08:00
|
|
|
static inline struct device_node *of_get_next_available_child(
|
|
|
|
const struct device_node *node, struct device_node *prev)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
2013-10-29 02:12:35 +08:00
|
|
|
|
2014-02-03 22:53:44 +08:00
|
|
|
static inline struct device_node *of_find_node_with_property(
|
|
|
|
struct device_node *from, const char *prop_name)
|
2012-10-08 01:40:54 +08:00
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-03-28 15:52:23 +08:00
|
|
|
#define of_fwnode_handle(node) NULL
|
|
|
|
|
2014-02-03 22:53:44 +08:00
|
|
|
static inline bool of_have_populated_dt(void)
|
2012-04-27 11:36:20 +08:00
|
|
|
{
|
2014-02-03 22:53:44 +08:00
|
|
|
return false;
|
2012-04-27 11:36:20 +08:00
|
|
|
}
|
|
|
|
|
2018-08-27 16:21:45 +08:00
|
|
|
static inline struct device_node *of_get_compatible_child(const struct device_node *parent,
|
|
|
|
const char *compatible)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-02-03 22:53:44 +08:00
|
|
|
static inline struct device_node *of_get_child_by_name(
|
|
|
|
const struct device_node *node,
|
|
|
|
const char *name)
|
2013-09-25 01:38:26 +08:00
|
|
|
{
|
2014-02-03 22:53:44 +08:00
|
|
|
return NULL;
|
2013-09-25 01:38:26 +08:00
|
|
|
}
|
|
|
|
|
2011-10-11 00:19:35 +08:00
|
|
|
static inline int of_device_is_compatible(const struct device_node *device,
|
|
|
|
const char *name)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-26 01:38:48 +08:00
|
|
|
static inline int of_device_compatible_match(struct device_node *device,
|
|
|
|
const char *const *compat)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-11-13 04:54:01 +08:00
|
|
|
static inline bool of_device_is_available(const struct device_node *device)
|
2013-03-21 05:56:18 +08:00
|
|
|
{
|
2014-11-13 04:54:01 +08:00
|
|
|
return false;
|
2013-03-21 05:56:18 +08:00
|
|
|
}
|
|
|
|
|
2015-04-10 04:05:14 +08:00
|
|
|
static inline bool of_device_is_big_endian(const struct device_node *device)
|
|
|
|
{
|
|
|
|
return false;
|
2013-03-21 05:56:18 +08:00
|
|
|
}
|
|
|
|
|
2011-09-22 03:23:10 +08:00
|
|
|
static inline struct property *of_find_property(const struct device_node *np,
|
|
|
|
const char *name,
|
|
|
|
int *lenp)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-02-16 02:47:42 +08:00
|
|
|
static inline struct device_node *of_find_compatible_node(
|
|
|
|
struct device_node *from,
|
|
|
|
const char *type,
|
|
|
|
const char *compat)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-02-12 08:00:34 +08:00
|
|
|
static inline int of_property_count_elems_of_size(const struct device_node *np,
|
|
|
|
const char *propname, int elem_size)
|
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
2017-11-06 21:26:10 +08:00
|
|
|
static inline int of_property_read_u32_index(const struct device_node *np,
|
|
|
|
const char *propname, u32 index, u32 *out_value)
|
2011-07-08 16:27:33 +08:00
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
2017-11-06 21:26:10 +08:00
|
|
|
static inline int of_property_read_u64_index(const struct device_node *np,
|
|
|
|
const char *propname, u32 index, u64 *out_value)
|
2011-09-27 23:45:43 +08:00
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
2011-08-06 06:50:30 +08:00
|
|
|
static inline const void *of_get_property(const struct device_node *node,
|
|
|
|
const char *name,
|
|
|
|
int *lenp)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-08-15 21:01:40 +08:00
|
|
|
static inline struct device_node *of_get_cpu_node(int cpu,
|
|
|
|
unsigned int *thread)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-08-23 04:04:40 +08:00
|
|
|
static inline struct device_node *of_get_next_cpu_node(struct device_node *prev)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
of: base: Add of_get_cpu_state_node() to get idle states for a CPU node
The CPU's idle state nodes are currently parsed at the common cpuidle DT
library, but also when initializing data for specific CPU idle operations,
as in the PSCI cpuidle driver case and qcom-spm cpuidle case.
To avoid open-coding, let's introduce of_get_cpu_state_node(), which takes
the device node for the CPU and the index to the requested idle state node,
as in-parameters. In case a corresponding idle state node is found, it
returns the node with the refcount incremented for it, else it returns
NULL.
Moreover, for PSCI there are two options to describe the CPU's idle states
[1], either via a flattened description or a hierarchical layout. Hence,
let's take both options into account.
[1] Documentation/devicetree/bindings/arm/psci.yaml
Suggested-by: Sudeep Holla <sudeep.holla@arm.com>
Co-developed-by: Lina Iyer <lina.iyer@linaro.org>
Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Reviewed-by: Rob Herring <robh@kernel.org>
Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
2019-10-10 18:01:48 +08:00
|
|
|
static inline struct device_node *of_get_cpu_state_node(struct device_node *cpu_node,
|
|
|
|
int index)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-10-14 06:57:40 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-11-06 21:26:10 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2011-09-15 03:49:59 +08:00
|
|
|
static inline int of_property_read_u64(const struct device_node *np,
|
|
|
|
const char *propname, u64 *out_value)
|
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
2017-11-06 21:26:10 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-03-03 05:35:51 +08:00
|
|
|
static inline int of_property_match_string(const struct device_node *np,
|
2012-04-13 22:18:34 +08:00
|
|
|
const char *propname,
|
|
|
|
const char *string)
|
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
2017-11-06 21:26:10 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-01-19 01:35:02 +08:00
|
|
|
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)
|
2012-04-13 22:19:21 +08:00
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
of: Support parsing phandle argument lists through a nexus node
Platforms like 96boards have a standardized connector/expansion
slot that exposes signals like GPIOs to expansion boards in an
SoC agnostic way. We'd like the DT overlays for the expansion
boards to be written once without knowledge of the SoC on the
other side of the connector. This avoids the unscalable
combinatorial explosion of a different DT overlay for each
expansion board and SoC pair.
We need a way to describe the GPIOs routed through the connector
in an SoC agnostic way. Let's introduce nexus property parsing
into the OF core to do this. This is largely based on the
interrupt nexus support we already have. This allows us to remap
a phandle list in a consumer node (e.g. reset-gpios) through a
connector in a generic way (e.g. via gpio-map). Do this in a
generic routine so that we can remap any sort of variable length
phandle list.
Taking GPIOs as an example, the connector would be a GPIO nexus,
supporting the remapping of a GPIO specifier space to multiple
GPIO providers on the SoC. DT would look as shown below, where
'soc_gpio1' and 'soc_gpio2' are inside the SoC, 'connector' is an
expansion port where boards can be plugged in, and
'expansion_device' is a device on the expansion board.
soc {
soc_gpio1: gpio-controller1 {
#gpio-cells = <2>;
};
soc_gpio2: gpio-controller2 {
#gpio-cells = <2>;
};
};
connector: connector {
#gpio-cells = <2>;
gpio-map = <0 0 &soc_gpio1 1 0>,
<1 0 &soc_gpio2 4 0>,
<2 0 &soc_gpio1 3 0>,
<3 0 &soc_gpio2 2 0>;
gpio-map-mask = <0xf 0x0>;
gpio-map-pass-thru = <0x0 0x1>
};
expansion_device {
reset-gpios = <&connector 2 GPIO_ACTIVE_LOW>;
};
The GPIO core would use of_parse_phandle_with_args_map() instead
of of_parse_phandle_with_args() and arrive at the same type of
result, a phandle and argument list. The difference is that the
phandle and arguments will be remapped through the nexus node to
the underlying SoC GPIO controller node. In the example above,
we would remap 'reset-gpios' from <&connector 2 GPIO_ACTIVE_LOW>
to <&soc_gpio1 3 GPIO_ACTIVE_LOW>.
Cc: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Mark Brown <broonie@kernel.org>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
Signed-off-by: Rob Herring <robh@kernel.org>
2018-01-31 10:36:16 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-07-28 22:42:27 +08:00
|
|
|
static inline int of_count_phandle_with_args(const struct device_node *np,
|
2013-02-11 06:57:21 +08:00
|
|
|
const char *list_name,
|
|
|
|
const char *cells_name)
|
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
2016-04-04 23:49:17 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-04-04 23:49:18 +08:00
|
|
|
static inline int of_phandle_iterator_next(struct of_phandle_iterator *it)
|
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
2016-04-04 23:49:21 +08:00
|
|
|
static inline int of_phandle_iterator_args(struct of_phandle_iterator *it,
|
|
|
|
uint32_t *args,
|
|
|
|
int size)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-10-27 17:07:28 +08:00
|
|
|
static inline int of_alias_get_id(struct device_node *np, const char *stem)
|
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
2015-03-13 00:17:58 +08:00
|
|
|
static inline int of_alias_get_highest_id(const char *stem)
|
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
2011-10-25 20:01:26 +08:00
|
|
|
static inline int of_machine_is_compatible(const char *compat)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-10 17:13:13 +08:00
|
|
|
static inline int of_add_property(struct device_node *np, struct property *prop)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-09-05 05:37:29 +08:00
|
|
|
static inline int of_remove_property(struct device_node *np, struct property *prop)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-03-28 08:18:55 +08:00
|
|
|
static inline bool of_console_check(const struct device_node *dn, const char *name, int index)
|
2013-08-05 20:40:44 +08:00
|
|
|
{
|
2014-03-28 08:18:55 +08:00
|
|
|
return false;
|
2013-08-05 20:40:44 +08:00
|
|
|
}
|
|
|
|
|
2013-06-17 22:48:13 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-01-22 01:05:57 +08:00
|
|
|
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(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)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-01-02 19:25:27 +08:00
|
|
|
static inline int of_cpu_node_to_id(struct device_node *np)
|
|
|
|
{
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
2020-06-19 16:20:07 +08:00
|
|
|
static inline int of_map_id(struct device_node *np, u32 id,
|
2018-09-10 21:49:16 +08:00
|
|
|
const char *map_name, const char *map_mask_name,
|
|
|
|
struct device_node **target, u32 *id_out)
|
|
|
|
{
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2020-11-20 01:53:55 +08:00
|
|
|
static inline phys_addr_t of_dma_get_max_cpu_address(struct device_node *np)
|
|
|
|
{
|
|
|
|
return PHYS_ADDR_MAX;
|
|
|
|
}
|
|
|
|
|
2011-08-03 17:11:42 +08:00
|
|
|
#define of_match_ptr(_ptr) NULL
|
2011-10-24 17:53:32 +08:00
|
|
|
#define of_match_node(_matches, _node) NULL
|
2010-02-14 22:13:43 +08:00
|
|
|
#endif /* CONFIG_OF */
|
2011-07-08 16:27:33 +08:00
|
|
|
|
2016-06-22 01:50:20 +08:00
|
|
|
/* 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
|
|
|
|
|
2018-10-05 11:32:04 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2013-09-17 23:42:50 +08:00
|
|
|
#if defined(CONFIG_OF) && defined(CONFIG_NUMA)
|
|
|
|
extern int of_node_to_nid(struct device_node *np);
|
|
|
|
#else
|
2015-04-09 00:59:20 +08:00
|
|
|
static inline int of_node_to_nid(struct device_node *device)
|
|
|
|
{
|
|
|
|
return NUMA_NO_NODE;
|
|
|
|
}
|
2012-06-04 13:04:34 +08:00
|
|
|
#endif
|
|
|
|
|
2016-04-09 06:50:25 +08:00
|
|
|
#ifdef CONFIG_OF_NUMA
|
|
|
|
extern int of_numa_init(void);
|
|
|
|
#else
|
|
|
|
static inline int of_numa_init(void)
|
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-02-03 22:53:44 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2018-08-29 04:10:48 +08:00
|
|
|
static inline const char *of_node_get_device_type(const struct device_node *np)
|
|
|
|
{
|
2018-10-01 23:54:51 +08:00
|
|
|
return of_get_property(np, "device_type", NULL);
|
2018-08-29 04:10:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2022-01-19 01:35:02 +08:00
|
|
|
/**
|
|
|
|
* 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);
|
|
|
|
}
|
|
|
|
|
2014-02-12 08:00:34 +08:00
|
|
|
/**
|
|
|
|
* 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
|
2021-03-26 00:47:12 +08:00
|
|
|
* in it.
|
|
|
|
*
|
|
|
|
* Return: The number of elements on sucess, -EINVAL if the property does
|
2014-02-12 08:00:34 +08:00
|
|
|
* 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
|
2021-03-26 00:47:12 +08:00
|
|
|
* in it.
|
|
|
|
*
|
|
|
|
* Return: The number of elements on sucess, -EINVAL if the property does
|
2014-02-12 08:00:34 +08:00
|
|
|
* 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
|
2021-03-26 00:47:12 +08:00
|
|
|
* in it.
|
|
|
|
*
|
|
|
|
* Return: The number of elements on sucess, -EINVAL if the property does
|
2014-02-12 08:00:34 +08:00
|
|
|
* 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
|
2021-03-26 00:47:12 +08:00
|
|
|
* in it.
|
|
|
|
*
|
|
|
|
* Return: The number of elements on sucess, -EINVAL if the property does
|
2014-02-12 08:00:34 +08:00
|
|
|
* 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));
|
|
|
|
}
|
|
|
|
|
2014-11-03 23:15:35 +08:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*
|
2021-03-26 00:47:12 +08:00
|
|
|
* Return: If @out_strs is NULL, the number of strings in the property is returned.
|
2014-11-03 23:15:35 +08:00
|
|
|
*/
|
2016-03-03 05:35:51 +08:00
|
|
|
static inline int of_property_read_string_array(const struct device_node *np,
|
2014-11-03 23:15:35 +08:00
|
|
|
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
|
2021-03-26 00:47:12 +08:00
|
|
|
* 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.
|
2014-11-03 23:15:35 +08:00
|
|
|
*/
|
2016-03-03 05:35:51 +08:00
|
|
|
static inline int of_property_count_strings(const struct device_node *np,
|
2014-11-03 23:15:35 +08:00
|
|
|
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
|
2021-04-17 14:12:44 +08:00
|
|
|
* @output: pointer to null terminated return string, modified only if
|
2014-11-03 23:15:35 +08:00
|
|
|
* 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.
|
2021-03-26 00:47:12 +08:00
|
|
|
*
|
|
|
|
* Return: 0 on success, -EINVAL if the property does not exist, -ENODATA if
|
2014-11-03 23:15:35 +08:00
|
|
|
* 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.
|
|
|
|
*/
|
2016-03-03 05:35:51 +08:00
|
|
|
static inline int of_property_read_string_index(const struct device_node *np,
|
2014-11-03 23:15:35 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-02-07 12:12:51 +08:00
|
|
|
/**
|
2019-07-26 18:17:44 +08:00
|
|
|
* of_property_read_bool - Find a property
|
2012-02-07 12:12:51 +08:00
|
|
|
* @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.
|
2021-03-26 00:47:12 +08:00
|
|
|
*
|
|
|
|
* Return: true if the property exists false otherwise.
|
2012-02-07 12:12:51 +08:00
|
|
|
*/
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-01-19 01:35:03 +08:00
|
|
|
/**
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
|
2012-11-20 12:45:19 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2011-07-08 16:27:33 +08:00
|
|
|
static inline int of_property_read_u32(const struct device_node *np,
|
2011-08-02 22:45:07 +08:00
|
|
|
const char *propname,
|
2011-07-08 16:27:33 +08:00
|
|
|
u32 *out_value)
|
|
|
|
{
|
|
|
|
return of_property_read_u32_array(np, propname, out_value, 1);
|
|
|
|
}
|
|
|
|
|
2014-04-06 18:52:11 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2016-04-04 23:49:20 +08:00
|
|
|
#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))
|
|
|
|
|
2013-06-17 22:48:13 +08:00
|
|
|
#define of_property_for_each_u32(np, propname, prop, p, u) \
|
|
|
|
for (prop = of_find_property(np, propname, NULL), \
|
|
|
|
p = of_prop_next_u32(prop, NULL, &u); \
|
|
|
|
p; \
|
|
|
|
p = of_prop_next_u32(prop, p, &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))
|
|
|
|
|
2014-02-03 22:53:44 +08:00
|
|
|
#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_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))
|
|
|
|
|
2018-08-23 04:04:40 +08:00
|
|
|
#define for_each_of_cpu_node(cpu) \
|
|
|
|
for (cpu = of_get_next_cpu_node(NULL); cpu != NULL; \
|
|
|
|
cpu = of_get_next_cpu_node(cpu))
|
|
|
|
|
2014-02-03 22:53:44 +08:00
|
|
|
#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;
|
|
|
|
}
|
|
|
|
|
2021-06-11 00:23:13 +08:00
|
|
|
#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 }
|
|
|
|
|
2016-01-22 00:33:51 +08:00
|
|
|
#if defined(CONFIG_OF) && !defined(MODULE)
|
2014-05-09 05:09:24 +08:00
|
|
|
#define _OF_DECLARE(table, name, compat, fn, fn_type) \
|
|
|
|
static const struct of_device_id __of_table_##name \
|
2020-10-22 10:36:07 +08:00
|
|
|
__used __section("__" #table "_of_table") \
|
2020-11-23 18:23:12 +08:00
|
|
|
__aligned(__alignof__(struct of_device_id)) \
|
2014-05-09 05:09:24 +08:00
|
|
|
= { .compatible = compat, \
|
|
|
|
.data = (fn == (fn_type)NULL) ? fn : fn }
|
|
|
|
#else
|
2014-10-02 22:01:10 +08:00
|
|
|
#define _OF_DECLARE(table, name, compat, fn, fn_type) \
|
2021-06-11 00:23:13 +08:00
|
|
|
_OF_DECLARE_STUB(table, name, compat, fn, fn_type)
|
2014-05-09 05:09:24 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
typedef int (*of_init_fn_2)(struct device_node *, struct device_node *);
|
2016-04-19 05:06:48 +08:00
|
|
|
typedef int (*of_init_fn_1_ret)(struct device_node *);
|
2014-05-09 05:09:24 +08:00
|
|
|
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)
|
2016-04-19 05:06:48 +08:00
|
|
|
#define OF_DECLARE_1_RET(table, name, compat, fn) \
|
|
|
|
_OF_DECLARE(table, name, compat, fn, of_init_fn_1_ret)
|
2014-05-09 05:09:24 +08:00
|
|
|
#define OF_DECLARE_2(table, name, compat, fn) \
|
|
|
|
_OF_DECLARE(table, name, compat, fn, of_init_fn_2)
|
|
|
|
|
2014-07-05 00:58:49 +08:00
|
|
|
/**
|
|
|
|
* 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;
|
|
|
|
};
|
|
|
|
|
2014-10-29 04:33:53 +08:00
|
|
|
enum of_reconfig_change {
|
|
|
|
OF_RECONFIG_NO_CHANGE = 0,
|
|
|
|
OF_RECONFIG_CHANGE_ADD,
|
|
|
|
OF_RECONFIG_CHANGE_REMOVE,
|
|
|
|
};
|
|
|
|
|
2014-07-05 00:58:49 +08:00
|
|
|
#ifdef CONFIG_OF_DYNAMIC
|
2014-11-21 23:14:58 +08:00
|
|
|
extern int of_reconfig_notifier_register(struct notifier_block *);
|
|
|
|
extern int of_reconfig_notifier_unregister(struct notifier_block *);
|
2014-11-25 01:58:01 +08:00
|
|
|
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);
|
2014-11-21 23:14:58 +08:00
|
|
|
|
2014-07-05 00:58:49 +08:00
|
|
|
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);
|
|
|
|
}
|
2014-11-21 23:14:58 +08:00
|
|
|
#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;
|
|
|
|
}
|
2014-11-25 01:58:01 +08:00
|
|
|
static inline int of_reconfig_notify(unsigned long action,
|
|
|
|
struct of_reconfig_data *arg)
|
2014-11-21 23:14:58 +08:00
|
|
|
{
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2014-11-25 01:58:01 +08:00
|
|
|
static inline int of_reconfig_get_state_change(unsigned long action,
|
|
|
|
struct of_reconfig_data *arg)
|
2014-11-21 23:14:58 +08:00
|
|
|
{
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_OF_DYNAMIC */
|
2014-07-05 00:58:49 +08:00
|
|
|
|
2014-10-14 14:31:09 +08:00
|
|
|
/**
|
2014-11-25 20:28:25 +08:00
|
|
|
* of_device_is_system_power_controller - Tells if system-power-controller is found for device_node
|
2014-10-14 14:31:09 +08:00
|
|
|
* @np: Pointer to the given device_node
|
|
|
|
*
|
2021-03-26 00:47:12 +08:00
|
|
|
* Return: true if present false otherwise
|
2014-10-14 14:31:09 +08:00
|
|
|
*/
|
2014-11-25 20:28:25 +08:00
|
|
|
static inline bool of_device_is_system_power_controller(const struct device_node *np)
|
2014-10-14 14:31:09 +08:00
|
|
|
{
|
2014-11-25 20:28:25 +08:00
|
|
|
return of_property_read_bool(np, "system-power-controller");
|
2014-10-14 14:31:09 +08:00
|
|
|
}
|
|
|
|
|
2021-04-17 14:12:44 +08:00
|
|
|
/*
|
2014-10-29 04:35:58 +08:00
|
|
|
* Overlay support
|
|
|
|
*/
|
|
|
|
|
2016-11-02 03:14:22 +08:00
|
|
|
enum of_overlay_notify_action {
|
2017-10-18 07:36:26 +08:00
|
|
|
OF_OVERLAY_PRE_APPLY = 0,
|
2016-11-02 03:14:22 +08:00
|
|
|
OF_OVERLAY_POST_APPLY,
|
|
|
|
OF_OVERLAY_PRE_REMOVE,
|
|
|
|
OF_OVERLAY_POST_REMOVE,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct of_overlay_notify_data {
|
|
|
|
struct device_node *overlay;
|
|
|
|
struct device_node *target;
|
|
|
|
};
|
|
|
|
|
2014-10-29 04:35:58 +08:00
|
|
|
#ifdef CONFIG_OF_OVERLAY
|
|
|
|
|
2018-02-12 16:19:42 +08:00
|
|
|
int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size,
|
|
|
|
int *ovcs_id);
|
2017-10-18 07:36:26 +08:00
|
|
|
int of_overlay_remove(int *ovcs_id);
|
2017-10-18 07:36:23 +08:00
|
|
|
int of_overlay_remove_all(void);
|
2014-10-29 04:35:58 +08:00
|
|
|
|
2016-11-02 03:14:22 +08:00
|
|
|
int of_overlay_notifier_register(struct notifier_block *nb);
|
|
|
|
int of_overlay_notifier_unregister(struct notifier_block *nb);
|
|
|
|
|
2014-10-29 04:35:58 +08:00
|
|
|
#else
|
|
|
|
|
2019-03-22 08:23:41 +08:00
|
|
|
static inline int of_overlay_fdt_apply(void *overlay_fdt, u32 overlay_fdt_size,
|
|
|
|
int *ovcs_id)
|
2014-10-29 04:35:58 +08:00
|
|
|
{
|
|
|
|
return -ENOTSUPP;
|
|
|
|
}
|
|
|
|
|
2017-10-18 07:36:26 +08:00
|
|
|
static inline int of_overlay_remove(int *ovcs_id)
|
2014-10-29 04:35:58 +08:00
|
|
|
{
|
|
|
|
return -ENOTSUPP;
|
|
|
|
}
|
|
|
|
|
2017-10-18 07:36:23 +08:00
|
|
|
static inline int of_overlay_remove_all(void)
|
2014-10-29 04:35:58 +08:00
|
|
|
{
|
|
|
|
return -ENOTSUPP;
|
|
|
|
}
|
|
|
|
|
2016-11-02 03:14:22 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-10-29 04:35:58 +08:00
|
|
|
#endif
|
|
|
|
|
2007-05-01 14:19:07 +08:00
|
|
|
#endif /* _LINUX_OF_H */
|