
Pull ACPI and power management updates from Rafael Wysocki: "This time we have some more new material than we used to have during the last couple of development cycles. The most important part of it to me is the introduction of a unified interface for accessing device properties provided by platform firmware. It works with Device Trees and ACPI in a uniform way and drivers using it need not worry about where the properties come from as long as the platform firmware (either DT or ACPI) makes them available. It covers both devices and "bare" device node objects without struct device representation as that turns out to be necessary in some cases. This has been in the works for quite a few months (and development cycles) and has been approved by all of the relevant maintainers. On top of that, some drivers are switched over to the new interface (at25, leds-gpio, gpio_keys_polled) and some additional changes are made to the core GPIO subsystem to allow device drivers to manipulate GPIOs in the "canonical" way on platforms that provide GPIO information in their ACPI tables, but don't assign names to GPIO lines (in which case the driver needs to do that on the basis of what it knows about the device in question). That also has been approved by the GPIO core maintainers and the rfkill driver is now going to use it. Second is support for hardware P-states in the intel_pstate driver. It uses CPUID to detect whether or not the feature is supported by the processor in which case it will be enabled by default. However, it can be disabled entirely from the kernel command line if necessary. Next is support for a platform firmware interface based on ACPI operation regions used by the PMIC (Power Management Integrated Circuit) chips on the Intel Baytrail-T and Baytrail-T-CR platforms. That interface is used for manipulating power resources and for thermal management: sensor temperature reporting, trip point setting and so on. Also the ACPI core is now going to support the _DEP configuration information in a limited way. Basically, _DEP it supposed to reflect off-the-hierarchy dependencies between devices which may be very indirect, like when AML for one device accesses locations in an operation region handled by another device's driver (usually, the device depended on this way is a serial bus or GPIO controller). The support added this time is sufficient to make the ACPI battery driver work on Asus T100A, but it is general enough to be able to cover some other use cases in the future. Finally, we have a new cpufreq driver for the Loongson1B processor. In addition to the above, there are fixes and cleanups all over the place as usual and a traditional ACPICA update to a recent upstream release. As far as the fixes go, the ACPI LPSS (Low-power Subsystem) driver for Intel platforms should be able to handle power management of the DMA engine correctly, the cpufreq-dt driver should interact with the thermal subsystem in a better way and the ACPI backlight driver should handle some more corner cases, among other things. On top of the ACPICA update there are fixes for race conditions in the ACPICA's interrupt handling code which might lead to some random and strange looking failures on some systems. In the cleanups department the most visible part is the series of commits targeted at getting rid of the CONFIG_PM_RUNTIME configuration option. That was triggered by a discussion regarding the generic power domains code during which we realized that trying to support certain combinations of PM config options was painful and not really worth it, because nobody would use them in production anyway. For this reason, we decided to make CONFIG_PM_SLEEP select CONFIG_PM_RUNTIME and that lead to the conclusion that the latter became redundant and CONFIG_PM could be used instead of it. The material here makes that replacement in a major part of the tree, but there will be at least one more batch of that in the second part of the merge window. Specifics: - Support for retrieving device properties information from ACPI _DSD device configuration objects and a unified device properties interface for device drivers (and subsystems) on top of that. As stated above, this works with Device Trees and ACPI and allows device drivers to be written in a platform firmware (DT or ACPI) agnostic way. The at25, leds-gpio and gpio_keys_polled drivers are now going to use this new interface and the GPIO subsystem is additionally modified to allow device drivers to assign names to GPIO resources returned by ACPI _CRS objects (in case _DSD is not present or does not provide the expected data). The changes in this set are mostly from Mika Westerberg, Rafael J Wysocki, Aaron Lu, and Darren Hart with some fixes from others (Fabio Estevam, Geert Uytterhoeven). - Support for Hardware Managed Performance States (HWP) as described in Volume 3, section 14.4, of the Intel SDM in the intel_pstate driver. CPUID is used to detect whether or not the feature is supported by the processor. If supported, it will be enabled automatically unless the intel_pstate=no_hwp switch is present in the kernel command line. From Dirk Brandewie. - New Intel Broadwell-H ID for intel_pstate (Dirk Brandewie). - Support for firmware interface based on ACPI operation regions used by the PMIC chips on the Intel Baytrail-T and Baytrail-T-CR platforms for power resource control and thermal management (Aaron Lu). - Limited support for retrieving off-the-hierarchy dependencies between devices from ACPI _DEP device configuration objects and deferred probing support for the ACPI battery driver based on the _DEP information to make that driver work on Asus T100A (Lan Tianyu). - New cpufreq driver for the Loongson1B processor (Kelvin Cheung). - ACPICA update to upstream revision 20141107 which only affects tools (Bob Moore). - Fixes for race conditions in the ACPICA's interrupt handling code and in the ACPI code related to system suspend and resume (Lv Zheng and Rafael J Wysocki). - ACPI core fix for an RCU-related issue in the ioremap() regions management code that slowed down significantly after CPUs had been allowed to enter idle states even if they'd had RCU callbakcs queued and triggered some problems in certain proprietary graphics driver (and elsewhere). The fix replaces synchronize_rcu() in that code with synchronize_rcu_expedited() which makes the issue go away. From Konstantin Khlebnikov. - ACPI LPSS (Low-Power Subsystem) driver fix to handle power management of the DMA engine included into the LPSS correctly. The problem is that the DMA engine doesn't have ACPI PM support of its own and it simply is turned off when the last LPSS device having ACPI PM support goes into D3cold. To work around that, the PM domain used by the ACPI LPSS driver is redesigned so at least one device with ACPI PM support will be on as long as the DMA engine is in use. From Andy Shevchenko. - ACPI backlight driver fix to avoid using it on "Win8-compatible" systems where it doesn't work and where it was used by default by mistake (Aaron Lu). - Assorted minor ACPI core fixes and cleanups from Tomasz Nowicki, Sudeep Holla, Huang Rui, Hanjun Guo, Fabian Frederick, and Ashwin Chaugule (mostly related to the upcoming ARM64 support). - Intel RAPL (Running Average Power Limit) power capping driver fixes and improvements including new processor IDs (Jacob Pan). - Generic power domains modification to power up domains after attaching devices to them to meet the expectations of device drivers and bus types assuming devices to be accessible at probe time (Ulf Hansson). - Preliminary support for controlling device clocks from the generic power domains core code and modifications of the ARM/shmobile platform to use that feature (Ulf Hansson). - Assorted minor fixes and cleanups of the generic power domains core code (Ulf Hansson, Geert Uytterhoeven). - Assorted minor fixes and cleanups of the device clocks control code in the PM core (Geert Uytterhoeven, Grygorii Strashko). - Consolidation of device power management Kconfig options by making CONFIG_PM_SLEEP select CONFIG_PM_RUNTIME and removing the latter which is now redundant (Rafael J Wysocki and Kevin Hilman). That is the first batch of the changes needed for this purpose. - Core device runtime power management support code cleanup related to the execution of callbacks (Andrzej Hajda). - cpuidle ARM support improvements (Lorenzo Pieralisi). - cpuidle cleanup related to the CPUIDLE_FLAG_TIME_VALID flag and a new MAINTAINERS entry for ARM Exynos cpuidle (Daniel Lezcano and Bartlomiej Zolnierkiewicz). - New cpufreq driver callback (->ready) to be executed when the cpufreq core is ready to use a given policy object and cpufreq-dt driver modification to use that callback for cooling device registration (Viresh Kumar). - cpufreq core fixes and cleanups (Viresh Kumar, Vince Hsu, James Geboski, Tomeu Vizoso). - Assorted fixes and cleanups in the cpufreq-pcc, intel_pstate, cpufreq-dt, pxa2xx cpufreq drivers (Lenny Szubowicz, Ethan Zhao, Stefan Wahren, Petr Cvek). - OPP (Operating Performance Points) framework modification to allow OPPs to be removed too and update of a few cpufreq drivers (cpufreq-dt, exynos5440, imx6q, cpufreq) to remove OPPs (added during initialization) on driver removal (Viresh Kumar). - Hibernation core fixes and cleanups (Tina Ruchandani and Markus Elfring). - PM Kconfig fix related to CPU power management (Pankaj Dubey). - cpupower tool fix (Prarit Bhargava)" * tag 'pm+acpi-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (120 commits) i2c-omap / PM: Drop CONFIG_PM_RUNTIME from i2c-omap.c dmaengine / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM tools: cpupower: fix return checks for sysfs_get_idlestate_count() drivers: sh / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM e1000e / igb / PM: Eliminate CONFIG_PM_RUNTIME MMC / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM MFD / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM misc / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM media / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM input / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM leds: leds-gpio: Fix multiple instances registration without 'label' property iio / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM hsi / OMAP / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM i2c-hid / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM drm / exynos / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM gpio / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM hwrandom / exynos / PM: Use CONFIG_PM in #ifdef block / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM USB / PM: Drop CONFIG_PM_RUNTIME from the USB core PM: Merge the SET*_RUNTIME_PM_OPS() macros ...
971 lines
29 KiB
C
971 lines
29 KiB
C
#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.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version
|
|
* 2 of the License, or (at your option) any later version.
|
|
*/
|
|
#include <linux/types.h>
|
|
#include <linux/bitops.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/kobject.h>
|
|
#include <linux/mod_devicetable.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/topology.h>
|
|
#include <linux/notifier.h>
|
|
#include <linux/property.h>
|
|
|
|
#include <asm/byteorder.h>
|
|
#include <asm/errno.h>
|
|
|
|
typedef u32 phandle;
|
|
typedef u32 ihandle;
|
|
|
|
struct property {
|
|
char *name;
|
|
int length;
|
|
void *value;
|
|
struct property *next;
|
|
unsigned long _flags;
|
|
unsigned int unique_id;
|
|
struct bin_attribute attr;
|
|
};
|
|
|
|
#if defined(CONFIG_SPARC)
|
|
struct of_irq_controller;
|
|
#endif
|
|
|
|
struct device_node {
|
|
const char *name;
|
|
const char *type;
|
|
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;
|
|
struct device_node *next; /* next device of same type */
|
|
struct device_node *allnext; /* next in list of all nodes */
|
|
struct kobject kobj;
|
|
unsigned long _flags;
|
|
void *data;
|
|
#if defined(CONFIG_SPARC)
|
|
const char *path_component_name;
|
|
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];
|
|
};
|
|
|
|
/* initialize a node */
|
|
extern struct kobj_type of_node_ktype;
|
|
static inline void of_node_init(struct device_node *node)
|
|
{
|
|
kobject_init(&node->kobj, &of_node_ktype);
|
|
node->fwnode.type = FWNODE_OF;
|
|
}
|
|
|
|
/* true when node is initialized */
|
|
static inline int of_node_is_initialized(struct device_node *node)
|
|
{
|
|
return node && node->kobj.state_initialized;
|
|
}
|
|
|
|
/* true when node is attached (i.e. present on sysfs) */
|
|
static inline int of_node_is_attached(struct device_node *node)
|
|
{
|
|
return node && node->kobj.state_in_sysfs;
|
|
}
|
|
|
|
#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 */
|
|
|
|
#ifdef CONFIG_OF
|
|
|
|
/* Pointer for first entry in chain of all nodes. */
|
|
extern struct device_node *of_allnodes;
|
|
extern struct device_node *of_chosen;
|
|
extern struct device_node *of_aliases;
|
|
extern struct device_node *of_stdout;
|
|
extern raw_spinlock_t devtree_lock;
|
|
|
|
static inline bool is_of_node(struct fwnode_handle *fwnode)
|
|
{
|
|
return fwnode && fwnode->type == FWNODE_OF;
|
|
}
|
|
|
|
static inline struct device_node *of_node(struct fwnode_handle *fwnode)
|
|
{
|
|
return fwnode ? container_of(fwnode, struct device_node, fwnode) : NULL;
|
|
}
|
|
|
|
static inline bool of_have_populated_dt(void)
|
|
{
|
|
return of_allnodes != 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(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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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;
|
|
while (size--)
|
|
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
|
|
|
|
/* Default #address and #size cells. Allow arch asm/prom.h to override */
|
|
#if !defined(OF_ROOT_NODE_ADDR_CELLS_DEFAULT)
|
|
#define OF_ROOT_NODE_ADDR_CELLS_DEFAULT 1
|
|
#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1
|
|
#endif
|
|
|
|
/* 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
|
|
|
|
/* flag descriptions */
|
|
#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */
|
|
#define OF_DETACHED 2 /* node has been detached from the device tree */
|
|
#define OF_POPULATED 3 /* device already created for the node */
|
|
#define OF_POPULATED_BUS 4 /* of_platform_populate recursed to children of this node */
|
|
|
|
#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
|
|
#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
|
|
|
|
#define OF_BAD_ADDR ((u64)-1)
|
|
|
|
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(dn) \
|
|
for (dn = of_allnodes; dn; dn = dn->allnext)
|
|
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_by_path(const char *path);
|
|
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_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 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_u8_array(const struct device_node *np,
|
|
const char *propname, u8 *out_values, size_t sz);
|
|
extern int of_property_read_u16_array(const struct device_node *np,
|
|
const char *propname, u16 *out_values, size_t sz);
|
|
extern int of_property_read_u32_array(const struct device_node *np,
|
|
const char *propname,
|
|
u32 *out_values,
|
|
size_t sz);
|
|
extern int of_property_read_u64(const struct device_node *np,
|
|
const char *propname, u64 *out_value);
|
|
extern int of_property_read_u64_array(const struct device_node *np,
|
|
const char *propname,
|
|
u64 *out_values,
|
|
size_t sz);
|
|
|
|
extern int of_property_read_string(struct device_node *np,
|
|
const char *propname,
|
|
const char **out_string);
|
|
extern int of_property_match_string(struct device_node *np,
|
|
const char *propname,
|
|
const char *string);
|
|
extern int of_property_read_string_helper(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_is_available(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);
|
|
#define for_each_property_of_node(dn, pp) \
|
|
for (pp = dn->properties; pp != NULL; pp = pp->next)
|
|
|
|
extern int of_n_addr_cells(struct device_node *np);
|
|
extern int of_n_size_cells(struct device_node *np);
|
|
extern const struct of_device_id *of_match_node(
|
|
const struct of_device_id *matches, const struct device_node *node);
|
|
extern int of_modalias_node(struct device_node *node, char *modalias, int len);
|
|
extern void of_print_phandle_args(const char *msg, const struct of_phandle_args *args);
|
|
extern struct device_node *of_parse_phandle(const struct device_node *np,
|
|
const char *phandle_name,
|
|
int index);
|
|
extern int of_parse_phandle_with_args(const struct device_node *np,
|
|
const char *list_name, const char *cells_name, int index,
|
|
struct of_phandle_args *out_args);
|
|
extern int of_parse_phandle_with_fixed_args(const struct device_node *np,
|
|
const char *list_name, int cells_count, 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);
|
|
|
|
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_machine_is_compatible(const char *compat);
|
|
|
|
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
|
|
|
|
struct of_prop_reconfig {
|
|
struct device_node *dn;
|
|
struct property *prop;
|
|
struct property *old_prop;
|
|
};
|
|
|
|
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, void *);
|
|
|
|
extern int of_attach_node(struct device_node *);
|
|
extern int of_detach_node(struct device_node *);
|
|
|
|
#define of_match_ptr(_ptr) (_ptr)
|
|
|
|
/*
|
|
* 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);
|
|
|
|
bool of_console_check(struct device_node *dn, char *name, int index);
|
|
|
|
#else /* CONFIG_OF */
|
|
|
|
static inline bool is_of_node(struct fwnode_handle *fwnode)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static inline struct device_node *of_node(struct fwnode_handle *fwnode)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
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_get_parent(const 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_find_node_with_property(
|
|
struct device_node *from, const char *prop_name)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline bool of_have_populated_dt(void)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
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_is_available(const struct device_node *device)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
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_u8_array(const struct device_node *np,
|
|
const char *propname, u8 *out_values, size_t sz)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_property_read_u16_array(const struct device_node *np,
|
|
const char *propname, u16 *out_values, size_t sz)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_property_read_u32_array(const struct device_node *np,
|
|
const char *propname,
|
|
u32 *out_values, size_t sz)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_property_read_u64_array(const struct device_node *np,
|
|
const char *propname,
|
|
u64 *out_values, size_t sz)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_property_read_string(struct device_node *np,
|
|
const char *propname,
|
|
const char **out_string)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_property_read_string_helper(struct device_node *np,
|
|
const char *propname,
|
|
const char **out_strs, size_t sz, int index)
|
|
{
|
|
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 int of_property_read_u64(const struct device_node *np,
|
|
const char *propname, u64 *out_value)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_property_match_string(struct device_node *np,
|
|
const char *propname,
|
|
const char *string)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline struct device_node *of_parse_phandle(const struct device_node *np,
|
|
const char *phandle_name,
|
|
int index)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline int of_parse_phandle_with_args(struct device_node *np,
|
|
const char *list_name,
|
|
const char *cells_name,
|
|
int index,
|
|
struct of_phandle_args *out_args)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_parse_phandle_with_fixed_args(const struct device_node *np,
|
|
const char *list_name, int cells_count, int index,
|
|
struct of_phandle_args *out_args)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_count_phandle_with_args(struct device_node *np,
|
|
const char *list_name,
|
|
const char *cells_name)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_alias_get_id(struct device_node *np, const char *stem)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline int of_machine_is_compatible(const char *compat)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
#define of_match_ptr(_ptr) NULL
|
|
#define of_match_node(_matches, _node) NULL
|
|
#endif /* CONFIG_OF */
|
|
|
|
#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 0; }
|
|
#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);
|
|
}
|
|
|
|
/**
|
|
* 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. Returns 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. Returns 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. Returns 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. Returns 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.
|
|
*
|
|
* If @out_strs is NULL, the number of strings in the property is returned.
|
|
*/
|
|
static inline int of_property_read_string_array(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. Returns 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(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
|
|
* @out_string: 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.
|
|
* Returns 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(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 - Findfrom 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.
|
|
* Returns true if the property exist 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;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
#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))
|
|
|
|
#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))
|
|
|
|
#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;
|
|
}
|
|
|
|
#ifdef CONFIG_OF
|
|
#define _OF_DECLARE(table, name, compat, fn, fn_type) \
|
|
static const struct of_device_id __of_table_##name \
|
|
__used __section(__##table##_of_table) \
|
|
= { .compatible = compat, \
|
|
.data = (fn == (fn_type)NULL) ? fn : fn }
|
|
#else
|
|
#define _OF_DECLARE(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 }
|
|
#endif
|
|
|
|
typedef int (*of_init_fn_2)(struct device_node *, 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_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;
|
|
};
|
|
|
|
#ifdef CONFIG_OF_DYNAMIC
|
|
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);
|
|
}
|
|
#endif
|
|
|
|
/* CONFIG_OF_RESOLVE api */
|
|
extern int of_resolve_phandles(struct device_node *tree);
|
|
|
|
/**
|
|
* 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");
|
|
}
|
|
|
|
#endif /* _LINUX_OF_H */
|