scripts: edtlib: Call nodes "nodes" instead of "devices"
edtlib.Device is just a devicetree node augmented with binding information and some interpretation of properties. Rename it to edtlib.Node to make that clearer. That also avoids calling things like flash partition nodes "devices", which is a bit confusing. I called it edtlib.Device instead of edtlib.Node originally to avoid confusion with dtlib.Node, but in retrospect it probably makes it more confusing on the whole. Something like edtlib.ENode might work too, but it's probably overkill. Clients of edtlib.py only interact with edtlib.Node, so the only potential for confusion is within edtlib.py itself, and it doesn't get too bad there either. Piggyback some documentation nits, and consistently write it "devicetree" instead of "device tree", to match the spec. Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
This commit is contained in:
parent
51f550cd07
commit
73ac1466fb
5 changed files with 418 additions and 415 deletions
|
@ -8,7 +8,7 @@
|
|||
# pylint: disable=undefined-variable
|
||||
|
||||
"""
|
||||
A library for extracting information from .dts (Device Tree) files. See the
|
||||
A library for extracting information from .dts (devicetree) files. See the
|
||||
documentation for the DT and Node classes for more information.
|
||||
|
||||
The top-level entry point of the library is the DT class. DT.__init__() takes a
|
||||
|
@ -23,14 +23,17 @@ import re
|
|||
import sys
|
||||
import textwrap
|
||||
|
||||
# NOTE: testdtlib.py is the test suite for this library. It can be run directly.
|
||||
# NOTE: testdtlib.py is the test suite for this library. It can be run directly
|
||||
# as a script:
|
||||
#
|
||||
# ./testdtlib.py
|
||||
|
||||
|
||||
class DT:
|
||||
"""
|
||||
Represents a device tree parsed from a .dts file (or from many files, if
|
||||
the .dts file /include/s other files). Creating many instances of this
|
||||
class is fine. The library has no global state.
|
||||
Represents a devicetree parsed from a .dts file (or from many files, if the
|
||||
.dts file /include/s other files). Creating many instances of this class is
|
||||
fine. The library has no global state.
|
||||
|
||||
These attributes are available on DT instances:
|
||||
|
||||
|
@ -160,7 +163,7 @@ class DT:
|
|||
|
||||
def node_iter(self):
|
||||
"""
|
||||
Returns a generator for iterating over all nodes in the device tree.
|
||||
Returns a generator for iterating over all nodes in the devicetree.
|
||||
|
||||
For example, this will print the name of each node that has a property
|
||||
called 'foo':
|
||||
|
@ -173,8 +176,8 @@ class DT:
|
|||
|
||||
def __str__(self):
|
||||
"""
|
||||
Returns a DTS representation of the device tree. Called automatically
|
||||
if the DT instance is print()ed.
|
||||
Returns a DTS representation of the devicetree. Called automatically if
|
||||
the DT instance is print()ed.
|
||||
"""
|
||||
s = "/dts-v1/;\n\n"
|
||||
|
||||
|
@ -1165,7 +1168,7 @@ class DT:
|
|||
|
||||
class Node:
|
||||
r"""
|
||||
Represents a node in the device tree ('node-name { ... };').
|
||||
Represents a node in the devicetree ('node-name { ... };').
|
||||
|
||||
These attributes are available on Node instances:
|
||||
|
||||
|
@ -1721,7 +1724,7 @@ class Property:
|
|||
def to_num(data, length=None, signed=False):
|
||||
"""
|
||||
Converts the 'bytes' array 'data' to a number. The value is expected to be
|
||||
in big-endian format, which is standard in Device Tree.
|
||||
in big-endian format, which is standard in devicetree.
|
||||
|
||||
length (default: None):
|
||||
The expected length of the value in bytes, as a simple type check. If
|
||||
|
@ -1743,7 +1746,7 @@ def to_num(data, length=None, signed=False):
|
|||
def to_nums(data, length=4, signed=False):
|
||||
"""
|
||||
Like Property.to_nums(), but takes an arbitrary 'bytes' array. The values
|
||||
are assumed to be in big-endian format, which is standard in Device Tree.
|
||||
are assumed to be in big-endian format, which is standard in devicetree.
|
||||
"""
|
||||
_check_is_bytes(data)
|
||||
_check_length_positive(length)
|
||||
|
@ -1844,7 +1847,7 @@ _escape_table = str.maketrans({
|
|||
|
||||
|
||||
class DTError(Exception):
|
||||
"Exception raised for Device Tree-related errors"
|
||||
"Exception raised for devicetree-related errors"
|
||||
|
||||
|
||||
_Token = collections.namedtuple("Token", "id val")
|
||||
|
|
|
@ -5,22 +5,21 @@
|
|||
# Tip: You can view just the documentation with 'pydoc3 edtlib'
|
||||
|
||||
"""
|
||||
Library for working with .dts files and bindings at a higher level compared to
|
||||
dtlib. Deals with things at the level of devices, registers, interrupts,
|
||||
compatibles, bindings, etc., as opposed to dtlib, which is just a low-level
|
||||
device tree parser.
|
||||
Library for working with devicetrees at a higher level compared to dtlib. Like
|
||||
dtlib, this library presents a tree of devicetree nodes, but the nodes are
|
||||
augmented with information from bindings and include some interpretation of
|
||||
properties.
|
||||
|
||||
Each device tree node (dtlib.Node) gets a Device instance, which has all the
|
||||
information related to the device, derived from both the device tree and from
|
||||
the binding for the device.
|
||||
Bindings are files that describe devicetree nodes. Devicetree nodes are usually
|
||||
mapped to bindings via their 'compatible = "..."' property, but a binding can
|
||||
also come from a 'child-binding:' key in the binding for the parent devicetree
|
||||
node.
|
||||
|
||||
Bindings are files that describe device tree nodes. Device tree nodes are
|
||||
usually mapped to bindings via their 'compatible = "..."' property, but a
|
||||
binding can also come from a 'child-binding:' key in the binding for the parent
|
||||
device tree node.
|
||||
Each devicetree node (dtlib.Node) gets a corresponding edtlib.Node instance,
|
||||
which has all the information related to the node.
|
||||
|
||||
The top-level entry point of the library is the EDT class. EDT.__init__() takes
|
||||
a .dts file to parse and the path of a directory containing bindings.
|
||||
a .dts file to parse and a list of paths to directories containing bindings.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
@ -33,7 +32,9 @@ from dtlib import DT, DTError, to_num, to_nums, TYPE_EMPTY, TYPE_NUMS, \
|
|||
TYPE_PHANDLE, TYPE_PHANDLES_AND_NUMS
|
||||
|
||||
# NOTE: testedtlib.py is the test suite for this library. It can be run
|
||||
# directly.
|
||||
# directly as a script:
|
||||
#
|
||||
# ./testedtlib.py
|
||||
|
||||
# Implementation notes
|
||||
# --------------------
|
||||
|
@ -80,13 +81,12 @@ from dtlib import DT, DTError, to_num, to_nums, TYPE_EMPTY, TYPE_NUMS, \
|
|||
|
||||
class EDT:
|
||||
"""
|
||||
Represents a "high-level" view of a device tree, with a list of devices
|
||||
that each have some number of registers, etc.
|
||||
Represents a devicetree augmented with information from bindings.
|
||||
|
||||
These attributes are available on EDT objects:
|
||||
|
||||
devices:
|
||||
A list of Device objects for the devices
|
||||
nodes:
|
||||
A list of Node objects for the nodes that appear in the devicetree
|
||||
|
||||
dts_path:
|
||||
The .dts path passed to __init__()
|
||||
|
@ -99,7 +99,7 @@ class EDT:
|
|||
EDT constructor. This is the top-level entry point to the library.
|
||||
|
||||
dts:
|
||||
Path to device tree .dts file
|
||||
Path to devicetree .dts file
|
||||
|
||||
bindings_dirs:
|
||||
List of paths to directories containing bindings, in YAML format.
|
||||
|
@ -112,22 +112,22 @@ class EDT:
|
|||
_check_dt(self._dt)
|
||||
|
||||
self._init_compat2binding(bindings_dirs)
|
||||
self._init_devices()
|
||||
self._init_nodes()
|
||||
|
||||
def get_dev(self, path):
|
||||
def get_node(self, path):
|
||||
"""
|
||||
Returns the Device at the DT path or alias 'path'. Raises EDTError if
|
||||
the path or alias doesn't exist.
|
||||
Returns the Node at the DT path or alias 'path'. Raises EDTError if the
|
||||
path or alias doesn't exist.
|
||||
"""
|
||||
try:
|
||||
return self._node2dev[self._dt.get_node(path)]
|
||||
return self._node2enode[self._dt.get_node(path)]
|
||||
except DTError as e:
|
||||
_err(e)
|
||||
|
||||
def chosen_dev(self, name):
|
||||
def chosen_node(self, name):
|
||||
"""
|
||||
Returns the Device pointed at by the property named 'name' in /chosen,
|
||||
or None if the property is missing
|
||||
Returns the Node pointed at by the property named 'name' in /chosen, or
|
||||
None if the property is missing
|
||||
"""
|
||||
try:
|
||||
chosen = self._dt.get_node("/chosen")
|
||||
|
@ -139,7 +139,7 @@ class EDT:
|
|||
return None
|
||||
|
||||
# to_path() checks that the node exists
|
||||
return self._node2dev[chosen.props[name].to_path()]
|
||||
return self._node2enode[chosen.props[name].to_path()]
|
||||
|
||||
def _init_compat2binding(self, bindings_dirs):
|
||||
# Creates self._compat2binding. This is a dictionary that maps
|
||||
|
@ -154,7 +154,7 @@ class EDT:
|
|||
# For bindings that don't specify a bus, <bus> is None, so that e.g.
|
||||
# self._compat2binding["company,notonbus", None] contains the binding.
|
||||
#
|
||||
# Only bindings for 'compatible' strings that appear in the device tree
|
||||
# Only bindings for 'compatible' strings that appear in the devicetree
|
||||
# are loaded.
|
||||
|
||||
# Add legacy '!include foo.yaml' handling. Do
|
||||
|
@ -296,63 +296,63 @@ class EDT:
|
|||
yaml.load(f, Loader=yaml.Loader),
|
||||
paths[0])
|
||||
|
||||
def _init_devices(self):
|
||||
# Creates a list of devices (Device objects) from the DT nodes, in
|
||||
# self.devices
|
||||
def _init_nodes(self):
|
||||
# Creates a list of edtlib.Node objects from the dtlib.Node objects, in
|
||||
# self.nodes
|
||||
|
||||
# Maps dtlib.Node's to their corresponding Devices
|
||||
self._node2dev = {}
|
||||
# Maps each dtlib.Node to its corresponding edtlib.Node
|
||||
self._node2enode = {}
|
||||
|
||||
self.devices = []
|
||||
self.nodes = []
|
||||
|
||||
for node in self._dt.node_iter():
|
||||
# Warning: We depend on parent Devices being created before their
|
||||
for dt_node in self._dt.node_iter():
|
||||
# Warning: We depend on parent Nodes being created before their
|
||||
# children. This is guaranteed by node_iter().
|
||||
dev = Device()
|
||||
dev.edt = self
|
||||
dev._node = node
|
||||
dev._init_binding()
|
||||
dev._init_regs()
|
||||
dev._set_instance_no()
|
||||
node = Node()
|
||||
node.edt = self
|
||||
node._node = dt_node
|
||||
node._init_binding()
|
||||
node._init_regs()
|
||||
node._set_instance_no()
|
||||
|
||||
self.devices.append(dev)
|
||||
self._node2dev[node] = dev
|
||||
self.nodes.append(node)
|
||||
self._node2enode[dt_node] = node
|
||||
|
||||
for dev in self.devices:
|
||||
# Device._init_props() depends on all Device objects having been
|
||||
for node in self.nodes:
|
||||
# Node._init_props() depends on all Node objects having been
|
||||
# created, due to 'type: phandle', so we run it separately.
|
||||
# Property.val is set to the pointed-to Device instance for
|
||||
# phandles, which must exist.
|
||||
dev._init_props()
|
||||
# Property.val is set to the pointed-to Node instance for phandles,
|
||||
# which must exist.
|
||||
node._init_props()
|
||||
|
||||
for dev in self.devices:
|
||||
# These also depend on all Device objects having been created, and
|
||||
# might also depend on all Device.props having been initialized
|
||||
for node in self.nodes:
|
||||
# These also depend on all Node objects having been created, and
|
||||
# might also depend on all Node.props having been initialized
|
||||
# (_init_clocks() does as of writing).
|
||||
dev._init_interrupts()
|
||||
dev._init_gpios()
|
||||
dev._init_pwms()
|
||||
dev._init_iochannels()
|
||||
dev._init_clocks()
|
||||
node._init_interrupts()
|
||||
node._init_gpios()
|
||||
node._init_pwms()
|
||||
node._init_iochannels()
|
||||
node._init_clocks()
|
||||
|
||||
def __repr__(self):
|
||||
return "<EDT for '{}', binding directories '{}'>".format(
|
||||
self.dts_path, self.bindings_dirs)
|
||||
|
||||
|
||||
class Device:
|
||||
class Node:
|
||||
"""
|
||||
Represents a device, which is a devicetree node augmented with information
|
||||
from bindings and some interpretation of devicetree properties. There's a
|
||||
one-to-one correspondence between device tree nodes and Devices.
|
||||
Represents a devicetree node, augmented with information from bindings, and
|
||||
with some interpretation of devicetree properties. There's a one-to-one
|
||||
correspondence between devicetree nodes and Nodes.
|
||||
|
||||
These attributes are available on Device objects:
|
||||
These attributes are available on Node objects:
|
||||
|
||||
edt:
|
||||
The EDT instance this device is from
|
||||
The EDT instance this node is from
|
||||
|
||||
name:
|
||||
The name of the device. This is fetched from the node name.
|
||||
The name of the node
|
||||
|
||||
unit_addr:
|
||||
An integer with the ...@<unit-address> portion of the node name,
|
||||
|
@ -360,67 +360,65 @@ class Device:
|
|||
the node name has no unit-address portion
|
||||
|
||||
path:
|
||||
The device tree path of the device
|
||||
The devicetree path of the node
|
||||
|
||||
label:
|
||||
The text from the 'label' property on the DT node of the Device, or None
|
||||
if the node has no 'label'
|
||||
The text from the 'label' property on the node, or None if the node has
|
||||
no 'label'
|
||||
|
||||
parent:
|
||||
The Device instance for the devicetree parent of the Device, or None if
|
||||
there is no parent
|
||||
The Node instance for the devicetree parent of the Node, or None if the
|
||||
node is the root node
|
||||
|
||||
children:
|
||||
A dictionary with the Device instances for the devicetree children of the
|
||||
Device, indexed by name
|
||||
A dictionary with the Node instances for the devicetree children of the
|
||||
node, indexed by name
|
||||
|
||||
enabled:
|
||||
True unless the device's node has 'status = "disabled"'
|
||||
True unless the node has 'status = "disabled"'
|
||||
|
||||
read_only:
|
||||
True if the DT node of the Device has a 'read-only' property, and False
|
||||
otherwise
|
||||
True if the node has a 'read-only' property, and False otherwise
|
||||
|
||||
instance_no:
|
||||
Dictionary that maps each 'compatible' string for the device to a unique
|
||||
index among all devices that have that 'compatible' string.
|
||||
Dictionary that maps each 'compatible' string for the node to a unique
|
||||
index among all nodes that have that 'compatible' string.
|
||||
|
||||
As an example, 'instance_no["foo,led"] == 3' can be read as "this is the
|
||||
fourth foo,led device".
|
||||
fourth foo,led node".
|
||||
|
||||
Only enabled devices (status != "disabled") are counted. 'instance_no' is
|
||||
meaningless for disabled devices.
|
||||
Only enabled nodes (status != "disabled") are counted. 'instance_no' is
|
||||
meaningless for disabled nodes.
|
||||
|
||||
matching_compat:
|
||||
The 'compatible' string for the binding that matched the device, or
|
||||
None if the device has no binding
|
||||
The 'compatible' string for the binding that matched the node, or None if
|
||||
the node has no binding
|
||||
|
||||
description:
|
||||
The description string from the binding file for the device, or None if
|
||||
the device has no binding. Trailing whitespace (including newlines) is
|
||||
removed.
|
||||
The description string from the binding file for the node, or None if the
|
||||
node has no binding. Trailing whitespace (including newlines) is removed.
|
||||
|
||||
binding_path:
|
||||
The path to the binding file for the device, or None if the device has no
|
||||
The path to the binding file for the node, or None if the node has no
|
||||
binding
|
||||
|
||||
compats:
|
||||
A list of 'compatible' strings for the device, in the same order that
|
||||
A list of 'compatible' strings for the node, in the same order that
|
||||
they're listed in the .dts file
|
||||
|
||||
regs:
|
||||
A list of Register objects for the device's registers
|
||||
A list of Register objects for the node's registers
|
||||
|
||||
props:
|
||||
A dictionary that maps property names to Property objects. Property
|
||||
objects are created for all DT properties on the device that are
|
||||
objects are created for all devicetree properties on the node that are
|
||||
mentioned in 'properties:' in the binding.
|
||||
|
||||
aliases:
|
||||
A list of aliases for the device. This is fetched from the /aliases node.
|
||||
A list of aliases for the node. This is fetched from the /aliases node.
|
||||
|
||||
interrupts:
|
||||
A list of Interrupt objects for the interrupts generated by the device
|
||||
A list of Interrupt objects for the interrupts generated by the node
|
||||
|
||||
gpios:
|
||||
A dictionary that maps the <prefix> part in '<prefix>-gpios' properties
|
||||
|
@ -431,24 +429,23 @@ class Device:
|
|||
|
||||
pwms:
|
||||
A list of PWM objects, derived from the 'pwms' property. The list is
|
||||
empty if the device has no 'pwms' property.
|
||||
empty if the node has no 'pwms' property.
|
||||
|
||||
iochannels:
|
||||
A list of IOChannel objects, derived from the 'io-channels'
|
||||
property. The list is empty if the device has no 'io-channels'
|
||||
property.
|
||||
A list of IOChannel objects, derived from the 'io-channels' property. The
|
||||
list is empty if the node has no 'io-channels' property.
|
||||
|
||||
clocks:
|
||||
A list of Clock objects, derived from the 'clocks' property. The list is
|
||||
empty if the device has no 'clocks' property.
|
||||
empty if the node has no 'clocks' property.
|
||||
|
||||
bus:
|
||||
The bus for the device as specified in its binding, e.g. "i2c" or "spi".
|
||||
The bus for the node as specified in its binding, e.g. "i2c" or "spi".
|
||||
None if the binding doesn't specify a bus.
|
||||
|
||||
flash_controller:
|
||||
The flash controller for the device. Only meaningful for devices
|
||||
representing flash partitions.
|
||||
The flash controller for the node. Only meaningful for nodes representing
|
||||
flash partitions.
|
||||
"""
|
||||
@property
|
||||
def name(self):
|
||||
|
@ -492,15 +489,15 @@ class Device:
|
|||
@property
|
||||
def parent(self):
|
||||
"See the class docstring"
|
||||
return self.edt._node2dev.get(self._node.parent)
|
||||
return self.edt._node2enode.get(self._node.parent)
|
||||
|
||||
@property
|
||||
def children(self):
|
||||
"See the class docstring"
|
||||
# Could be initialized statically too to preserve identity, but not
|
||||
# sure if needed. Parent Devices being initialized before their
|
||||
# children would need to be kept in mind.
|
||||
return {name: self.edt._node2dev[node]
|
||||
# sure if needed. Parent nodes being initialized before their children
|
||||
# would need to be kept in mind.
|
||||
return {name: self.edt._node2enode[node]
|
||||
for name, node in self._node.nodes.items()}
|
||||
|
||||
@property
|
||||
|
@ -546,20 +543,20 @@ class Device:
|
|||
return controller
|
||||
|
||||
def __repr__(self):
|
||||
return "<Device {} in '{}', {}>".format(
|
||||
return "<Node {} in '{}', {}>".format(
|
||||
self.path, self.edt.dts_path,
|
||||
"binding " + self.binding_path if self.binding_path
|
||||
else "no binding")
|
||||
|
||||
def _init_binding(self):
|
||||
# Initializes Device.matching_compat, Device._binding, and
|
||||
# Device.binding_path.
|
||||
# Initializes Node.matching_compat, Node._binding, and
|
||||
# Node.binding_path.
|
||||
#
|
||||
# Device._binding holds the data from the device's binding file, in the
|
||||
# Node._binding holds the data from the node's binding file, in the
|
||||
# format returned by PyYAML (plain Python lists, dicts, etc.), or None
|
||||
# if the device has no binding.
|
||||
# if the node has no binding.
|
||||
|
||||
# This relies on the parent of the Device having already been
|
||||
# This relies on the parent of the node having already been
|
||||
# initialized, which is guaranteed by going through the nodes in
|
||||
# node_iter() order.
|
||||
|
||||
|
@ -696,7 +693,7 @@ class Device:
|
|||
return
|
||||
|
||||
prop = Property()
|
||||
prop.dev = self
|
||||
prop.node = self
|
||||
prop.name = name
|
||||
prop.description = options.get("description")
|
||||
if prop.description:
|
||||
|
@ -768,10 +765,10 @@ class Device:
|
|||
return prop.to_strings()
|
||||
|
||||
if prop_type == "phandle":
|
||||
return self.edt._node2dev[prop.to_node()]
|
||||
return self.edt._node2enode[prop.to_node()]
|
||||
|
||||
if prop_type == "phandles":
|
||||
return [self.edt._node2dev[node] for node in prop.to_nodes()]
|
||||
return [self.edt._node2enode[node] for node in prop.to_nodes()]
|
||||
|
||||
if prop_type == "phandle-array":
|
||||
# This property type only does a type check. No Property object is
|
||||
|
@ -831,7 +828,7 @@ class Device:
|
|||
|
||||
for raw_reg in _slice(node, "reg", 4*(address_cells + size_cells)):
|
||||
reg = Register()
|
||||
reg.dev = self
|
||||
reg.node = self
|
||||
reg.addr = _translate(to_num(raw_reg[:4*address_cells]), node)
|
||||
reg.size = to_num(raw_reg[4*address_cells:])
|
||||
if size_cells != 0 and reg.size == 0:
|
||||
|
@ -852,8 +849,8 @@ class Device:
|
|||
|
||||
for controller_node, spec in _interrupts(node):
|
||||
interrupt = Interrupt()
|
||||
interrupt.dev = self
|
||||
interrupt.controller = self.edt._node2dev[controller_node]
|
||||
interrupt.node = self
|
||||
interrupt.controller = self.edt._node2enode[controller_node]
|
||||
interrupt.specifier = self._named_cells(interrupt.controller, spec,
|
||||
"interrupt")
|
||||
|
||||
|
@ -870,8 +867,8 @@ class Device:
|
|||
self.gpios[prefix] = []
|
||||
for controller_node, spec in gpios:
|
||||
gpio = GPIO()
|
||||
gpio.dev = self
|
||||
gpio.controller = self.edt._node2dev[controller_node]
|
||||
gpio.node = self
|
||||
gpio.controller = self.edt._node2enode[controller_node]
|
||||
gpio.specifier = self._named_cells(gpio.controller, spec,
|
||||
"GPIO")
|
||||
gpio.name = prefix
|
||||
|
@ -928,7 +925,7 @@ class Device:
|
|||
#
|
||||
# cls:
|
||||
# A class object. Instances of this class will be created and the
|
||||
# 'dev', 'controller', 'specifier', and 'name' fields initialized.
|
||||
# 'node', 'controller', 'specifier', and 'name' fields initialized.
|
||||
# See the documentation for e.g. the PWM class.
|
||||
#
|
||||
# Returns a list of 'cls' instances.
|
||||
|
@ -941,8 +938,8 @@ class Device:
|
|||
|
||||
for controller_node, spec in _phandle_val_list(prop, name):
|
||||
obj = cls()
|
||||
obj.dev = self
|
||||
obj.controller = self.edt._node2dev[controller_node]
|
||||
obj.node = self
|
||||
obj.controller = self.edt._node2enode[controller_node]
|
||||
obj.specifier = self._named_cells(obj.controller, spec, name)
|
||||
|
||||
res.append(obj)
|
||||
|
@ -987,19 +984,19 @@ class Device:
|
|||
|
||||
for compat in self.compats:
|
||||
self.instance_no[compat] = 0
|
||||
for other_dev in self.edt.devices:
|
||||
if compat in other_dev.compats and other_dev.enabled:
|
||||
for other_node in self.edt.nodes:
|
||||
if compat in other_node.compats and other_node.enabled:
|
||||
self.instance_no[compat] += 1
|
||||
|
||||
|
||||
class Register:
|
||||
"""
|
||||
Represents a register on a device.
|
||||
Represents a register on a node.
|
||||
|
||||
These attributes are available on Register objects:
|
||||
|
||||
dev:
|
||||
The Device instance this register is from
|
||||
node:
|
||||
The Node instance this register is from
|
||||
|
||||
name:
|
||||
The name of the register as given in the 'reg-names' property, or None if
|
||||
|
@ -1025,19 +1022,19 @@ class Register:
|
|||
|
||||
class Interrupt:
|
||||
"""
|
||||
Represents an interrupt generated by a device.
|
||||
Represents an interrupt generated by a node.
|
||||
|
||||
These attributes are available on Interrupt objects:
|
||||
|
||||
dev:
|
||||
The Device instance that generated the interrupt
|
||||
node:
|
||||
The Node instance that generated the interrupt
|
||||
|
||||
name:
|
||||
The name of the interrupt as given in the 'interrupt-names' property, or
|
||||
None if there is no 'interrupt-names' property
|
||||
|
||||
controller:
|
||||
The Device instance for the controller the interrupt gets sent to. Any
|
||||
The Node instance for the controller the interrupt gets sent to. Any
|
||||
'interrupt-map' is taken into account, so that this is the final
|
||||
controller node.
|
||||
|
||||
|
@ -1060,19 +1057,19 @@ class Interrupt:
|
|||
|
||||
class GPIO:
|
||||
"""
|
||||
Represents a GPIO used by a device.
|
||||
Represents a GPIO used by a node.
|
||||
|
||||
These attributes are available on GPIO objects:
|
||||
|
||||
dev:
|
||||
The Device instance that uses the GPIO
|
||||
node:
|
||||
The Node instance that uses the GPIO
|
||||
|
||||
name:
|
||||
The name of the gpio as extracted out of the "<NAME>-gpios" property. If
|
||||
the property is just "gpios" than there is no name.
|
||||
|
||||
controller:
|
||||
The Device instance for the controller of the GPIO
|
||||
The Node instance for the controller of the GPIO
|
||||
|
||||
specifier:
|
||||
A dictionary that maps names from the #cells portion of the binding to
|
||||
|
@ -1093,19 +1090,19 @@ class GPIO:
|
|||
|
||||
class Clock:
|
||||
"""
|
||||
Represents a clock used by a device.
|
||||
Represents a clock used by a node.
|
||||
|
||||
These attributes are available on Clock objects:
|
||||
|
||||
dev:
|
||||
The Device instance that uses the clock
|
||||
node:
|
||||
The Node instance that uses the clock
|
||||
|
||||
name:
|
||||
The name of the clock as given in the 'clock-names' property, or
|
||||
None if there is no 'clock-names' property
|
||||
|
||||
controller:
|
||||
The Device instance for the controller of the clock.
|
||||
The Node instance for the controller of the clock.
|
||||
|
||||
frequency:
|
||||
The frequency of the clock for fixed clocks ('fixed-clock' in
|
||||
|
@ -1133,19 +1130,19 @@ class Clock:
|
|||
|
||||
class PWM:
|
||||
"""
|
||||
Represents a PWM used by a device.
|
||||
Represents a PWM used by a node.
|
||||
|
||||
These attributes are available on PWM objects:
|
||||
|
||||
dev:
|
||||
The Device instance that uses the PWM
|
||||
node:
|
||||
The Node instance that uses the PWM
|
||||
|
||||
name:
|
||||
The name of the pwm as given in the 'pwm-names' property, or the
|
||||
node name if the 'pwm-names' property doesn't exist.
|
||||
|
||||
controller:
|
||||
The Device instance for the controller of the PWM
|
||||
The Node instance for the controller of the PWM
|
||||
|
||||
specifier:
|
||||
A dictionary that maps names from the #cells portion of the binding to
|
||||
|
@ -1166,21 +1163,21 @@ class PWM:
|
|||
|
||||
class IOChannel:
|
||||
"""
|
||||
Represents an IO channel used by a device, similar to the property used
|
||||
Represents an IO channel used by a node, similar to the property used
|
||||
by the Linux IIO bindings and described at:
|
||||
https://www.kernel.org/doc/Documentation/devicetree/bindings/iio/iio-bindings.txt
|
||||
|
||||
These attributes are available on IO channel objects:
|
||||
|
||||
dev:
|
||||
The Device instance that uses the IO channel
|
||||
node:
|
||||
The Node instance that uses the IO channel
|
||||
|
||||
name:
|
||||
The name of the IO channel as given in the 'io-channel-names' property,
|
||||
or the node name if the 'io-channel-names' property doesn't exist.
|
||||
|
||||
controller:
|
||||
The Device instance for the controller of the IO channel
|
||||
The Node instance for the controller of the IO channel
|
||||
|
||||
specifier:
|
||||
A dictionary that maps names from the #cells portion of the binding to
|
||||
|
@ -1201,7 +1198,7 @@ class IOChannel:
|
|||
|
||||
class Property:
|
||||
"""
|
||||
Represents a property on a Device, as set in its DT node and with
|
||||
Represents a property on a Node, as set in its DT node and with
|
||||
additional info from the 'properties:' section of the binding.
|
||||
|
||||
Only properties mentioned in 'properties:' get created. Properties with
|
||||
|
@ -1210,8 +1207,8 @@ class Property:
|
|||
|
||||
These attributes are available on Property objects:
|
||||
|
||||
dev:
|
||||
The Device instance the property is on
|
||||
node:
|
||||
The Node instance the property is on
|
||||
|
||||
name:
|
||||
The name of the property
|
||||
|
@ -1227,9 +1224,9 @@ class Property:
|
|||
The value of the property, with the format determined by the 'type:' key
|
||||
from the binding.
|
||||
|
||||
For 'type: phandle' properties, this is the pointed-to Device instance.
|
||||
For 'type: phandle' properties, this is the pointed-to Node instance.
|
||||
|
||||
For 'type: phandles' properties, this is a list of the pointed-to Device
|
||||
For 'type: phandles' properties, this is a list of the pointed-to Node
|
||||
instances.
|
||||
|
||||
enum_index:
|
||||
|
@ -1249,7 +1246,7 @@ class Property:
|
|||
|
||||
|
||||
class EDTError(Exception):
|
||||
"Exception raised for Extended Device Tree-related errors"
|
||||
"Exception raised for devicetree- and binding-related errors"
|
||||
|
||||
|
||||
#
|
||||
|
@ -1257,20 +1254,20 @@ class EDTError(Exception):
|
|||
#
|
||||
|
||||
|
||||
def spi_dev_cs_gpio(dev):
|
||||
def spi_dev_cs_gpio(node):
|
||||
# Returns an SPI device's GPIO chip select if it exists, as a GPIO
|
||||
# instance, and None otherwise. See
|
||||
# Documentation/devicetree/bindings/spi/spi-bus.txt in the Linux kernel.
|
||||
|
||||
if dev.bus == "spi" and dev.parent:
|
||||
parent_cs = dev.parent.gpios.get("cs")
|
||||
if node.bus == "spi" and node.parent:
|
||||
parent_cs = node.parent.gpios.get("cs")
|
||||
if parent_cs:
|
||||
# cs-gpios is indexed by the unit address
|
||||
cs_index = dev.regs[0].addr
|
||||
cs_index = node.regs[0].addr
|
||||
if cs_index >= len(parent_cs):
|
||||
_err("index from 'regs' in {!r} ({}) is >= number of cs-gpios "
|
||||
"in {!r} ({})".format(
|
||||
dev, cs_index, dev.parent, len(parent_cs)))
|
||||
node, cs_index, node.parent, len(parent_cs)))
|
||||
|
||||
return parent_cs[cs_index]
|
||||
|
||||
|
@ -1283,7 +1280,7 @@ def spi_dev_cs_gpio(dev):
|
|||
|
||||
|
||||
def _dt_compats(dt):
|
||||
# Returns a set() with all 'compatible' strings in the device tree
|
||||
# Returns a set() with all 'compatible' strings in the devicetree
|
||||
# represented by dt (a dtlib.DT instance)
|
||||
|
||||
return {compat
|
||||
|
@ -1647,6 +1644,9 @@ def _translate(addr, node):
|
|||
# Recursively translates 'addr' on 'node' to the address space(s) of its
|
||||
# parent(s), by looking at 'ranges' properties. Returns the translated
|
||||
# address.
|
||||
#
|
||||
# node:
|
||||
# dtlib.Node instance
|
||||
|
||||
if not node.parent or "ranges" not in node.parent.props:
|
||||
# No translation
|
||||
|
@ -1691,7 +1691,7 @@ def _add_names(node, names_ident, objs):
|
|||
# Helper for registering names from <foo>-names properties.
|
||||
#
|
||||
# node:
|
||||
# Device tree node
|
||||
# edtlib.Node instance
|
||||
#
|
||||
# names-ident:
|
||||
# The <foo> part of <foo>-names, e.g. "reg" for "reg-names"
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
# This script uses edtlib to generate a header file and a .conf file (both
|
||||
# containing the same values) from a device tree (.dts) file. Information from
|
||||
# containing the same values) from a devicetree (.dts) file. Information from
|
||||
# binding files in YAML format is used as well.
|
||||
#
|
||||
# Bindings are files that describe device tree nodes. Device tree nodes are
|
||||
# Bindings are files that describe devicetree nodes. Devicetree nodes are
|
||||
# usually mapped to bindings via their 'compatible = "..."' property.
|
||||
#
|
||||
# See the docstring/comments at the top of edtlib.py for more information.
|
||||
|
@ -33,7 +33,7 @@ def main():
|
|||
try:
|
||||
edt = edtlib.EDT(args.dts, args.bindings_dirs)
|
||||
except edtlib.EDTError as e:
|
||||
sys.exit("device tree error: " + str(e))
|
||||
sys.exit("devicetree error: " + str(e))
|
||||
|
||||
conf_file = open(args.conf_out, "w", encoding="utf-8")
|
||||
header_file = open(args.header_out, "w", encoding="utf-8")
|
||||
|
@ -45,33 +45,33 @@ def main():
|
|||
|
||||
active_compats = set()
|
||||
|
||||
for dev in edt.devices:
|
||||
if dev.enabled and dev.matching_compat:
|
||||
for node in edt.nodes:
|
||||
if node.enabled and node.matching_compat:
|
||||
# Skip 'fixed-partitions' devices since they are handled by
|
||||
# write_flash() and would generate extra spurious #defines
|
||||
if dev.matching_compat == "fixed-partitions":
|
||||
if node.matching_compat == "fixed-partitions":
|
||||
continue
|
||||
|
||||
out_comment("Device tree node: " + dev.path)
|
||||
out_comment("Devicetree node: " + node.path)
|
||||
out_comment("Binding (compatible = {}): {}".format(
|
||||
dev.matching_compat, dev.binding_path),
|
||||
node.matching_compat, node.binding_path),
|
||||
blank_before=False)
|
||||
out_comment("Binding description: " + dev.description,
|
||||
out_comment("Binding description: " + node.description,
|
||||
blank_before=False)
|
||||
|
||||
write_regs(dev)
|
||||
write_irqs(dev)
|
||||
for gpios in dev.gpios.values():
|
||||
write_phandle_val_list(dev, gpios, "GPIO")
|
||||
write_phandle_val_list(dev, dev.pwms, "PWM")
|
||||
write_phandle_val_list(dev, dev.iochannels, "IO_CHANNEL")
|
||||
write_clocks(dev)
|
||||
write_spi_dev(dev)
|
||||
write_props(dev)
|
||||
write_bus(dev)
|
||||
write_existence_flags(dev)
|
||||
write_regs(node)
|
||||
write_irqs(node)
|
||||
for gpios in node.gpios.values():
|
||||
write_phandle_val_list(node, gpios, "GPIO")
|
||||
write_phandle_val_list(node, node.pwms, "PWM")
|
||||
write_phandle_val_list(node, node.iochannels, "IO_CHANNEL")
|
||||
write_clocks(node)
|
||||
write_spi_dev(node)
|
||||
write_props(node)
|
||||
write_bus(node)
|
||||
write_existence_flags(node)
|
||||
|
||||
active_compats.update(dev.compats)
|
||||
active_compats.update(node.compats)
|
||||
|
||||
out_comment("Active compatibles (mentioned in DTS + binding found)")
|
||||
for compat in sorted(active_compats):
|
||||
|
@ -83,20 +83,20 @@ def main():
|
|||
write_addr_size(edt, "zephyr,ccm", "CCM")
|
||||
write_addr_size(edt, "zephyr,dtcm", "DTCM")
|
||||
|
||||
write_flash(edt.chosen_dev("zephyr,flash"))
|
||||
write_code_partition(edt.chosen_dev("zephyr,code-partition"))
|
||||
write_flash(edt.chosen_node("zephyr,flash"))
|
||||
write_code_partition(edt.chosen_node("zephyr,code-partition"))
|
||||
|
||||
flash_index = 0
|
||||
for dev in edt.devices:
|
||||
if dev.name.startswith("partition@"):
|
||||
write_flash_partition(dev, flash_index)
|
||||
for node in edt.nodes:
|
||||
if node.name.startswith("partition@"):
|
||||
write_flash_partition(node, flash_index)
|
||||
flash_index += 1
|
||||
|
||||
out_comment("Number of flash partitions")
|
||||
if flash_index != 0:
|
||||
out("FLASH_AREA_NUM", flash_index)
|
||||
|
||||
print("Device tree configuration written to " + args.conf_out)
|
||||
print("Devicetree configuration written to " + args.conf_out)
|
||||
|
||||
|
||||
def parse_args():
|
||||
|
@ -115,8 +115,8 @@ def parse_args():
|
|||
return parser.parse_args()
|
||||
|
||||
|
||||
def write_regs(dev):
|
||||
# Writes address/size output for the registers in dev's 'reg' property
|
||||
def write_regs(node):
|
||||
# Writes address/size output for the registers in the node's 'reg' property
|
||||
|
||||
def reg_addr_name_alias(reg):
|
||||
return str2ident(reg.name) + "_BASE_ADDRESS" if reg.name else None
|
||||
|
@ -124,20 +124,20 @@ def write_regs(dev):
|
|||
def reg_size_name_alias(reg):
|
||||
return str2ident(reg.name) + "_SIZE" if reg.name else None
|
||||
|
||||
for reg in dev.regs:
|
||||
out_dev(dev, reg_addr_ident(reg), hex(reg.addr),
|
||||
for reg in node.regs:
|
||||
out_dev(node, reg_addr_ident(reg), hex(reg.addr),
|
||||
name_alias=reg_addr_name_alias(reg))
|
||||
|
||||
if reg.size:
|
||||
out_dev(dev, reg_size_ident(reg), reg.size,
|
||||
out_dev(node, reg_size_ident(reg), reg.size,
|
||||
name_alias=reg_size_name_alias(reg))
|
||||
|
||||
|
||||
def write_props(dev):
|
||||
def write_props(node):
|
||||
# Writes any properties defined in the "properties" section of the binding
|
||||
# for the device
|
||||
# for the node
|
||||
|
||||
for prop in dev.props.values():
|
||||
for prop in node.props.values():
|
||||
# Skip #size-cell and other property starting with #. Also skip mapping
|
||||
# properties like 'gpio-map'.
|
||||
if prop.name[0] == "#" or prop.name.endswith("-map"):
|
||||
|
@ -160,64 +160,65 @@ def write_props(dev):
|
|||
ident = str2ident(prop.name)
|
||||
|
||||
if prop.type == "boolean":
|
||||
out_dev(dev, ident, 1 if prop.val else 0)
|
||||
out_dev(node, ident, 1 if prop.val else 0)
|
||||
elif prop.type == "string":
|
||||
out_dev_s(dev, ident, prop.val)
|
||||
out_dev_s(node, ident, prop.val)
|
||||
elif prop.type == "int":
|
||||
out_dev(dev, ident, prop.val)
|
||||
out_dev(node, ident, prop.val)
|
||||
elif prop.type == "array":
|
||||
for i, val in enumerate(prop.val):
|
||||
out_dev(dev, "{}_{}".format(ident, i), val)
|
||||
out_dev(node, "{}_{}".format(ident, i), val)
|
||||
elif prop.type == "string-array":
|
||||
for i, val in enumerate(prop.val):
|
||||
out_dev_s(dev, "{}_{}".format(ident, i), val)
|
||||
out_dev_s(node, "{}_{}".format(ident, i), val)
|
||||
elif prop.type == "uint8-array":
|
||||
out_dev(dev, ident,
|
||||
out_dev(node, ident,
|
||||
"{ " + ", ".join("0x{:02x}".format(b) for b in prop.val) + " }")
|
||||
|
||||
# Generate DT_..._ENUM if there's an 'enum:' key in the binding
|
||||
if prop.enum_index is not None:
|
||||
out_dev(dev, ident + "_ENUM", prop.enum_index)
|
||||
out_dev(node, ident + "_ENUM", prop.enum_index)
|
||||
|
||||
|
||||
def write_bus(dev):
|
||||
def write_bus(node):
|
||||
# Generate bus-related #defines
|
||||
|
||||
if not dev.bus:
|
||||
if not node.bus:
|
||||
return
|
||||
|
||||
if dev.parent.label is None:
|
||||
err("missing 'label' property on {!r}".format(dev.parent))
|
||||
if node.parent.label is None:
|
||||
err("missing 'label' property on {!r}".format(node.parent))
|
||||
|
||||
# #define DT_<DEV-IDENT>_BUS_NAME <BUS-LABEL>
|
||||
out_dev_s(dev, "BUS_NAME", str2ident(dev.parent.label))
|
||||
out_dev_s(node, "BUS_NAME", str2ident(node.parent.label))
|
||||
|
||||
for compat in dev.compats:
|
||||
for compat in node.compats:
|
||||
# #define DT_<COMPAT>_BUS_<BUS-TYPE> 1
|
||||
out("{}_BUS_{}".format(str2ident(compat), str2ident(dev.bus)), 1)
|
||||
out("{}_BUS_{}".format(str2ident(compat), str2ident(node.bus)), 1)
|
||||
|
||||
|
||||
def write_existence_flags(dev):
|
||||
def write_existence_flags(node):
|
||||
# Generate #defines of the form
|
||||
#
|
||||
# #define DT_INST_<INSTANCE>_<COMPAT> 1
|
||||
#
|
||||
# These are flags for which devices exist.
|
||||
|
||||
for compat in dev.compats:
|
||||
out("INST_{}_{}".format(dev.instance_no[compat], str2ident(compat)), 1)
|
||||
for compat in node.compats:
|
||||
out("INST_{}_{}".format(node.instance_no[compat],
|
||||
str2ident(compat)), 1)
|
||||
|
||||
|
||||
def reg_addr_ident(reg):
|
||||
# Returns the identifier (e.g., macro name) to be used for the address of
|
||||
# 'reg' in the output
|
||||
|
||||
dev = reg.dev
|
||||
node = reg.node
|
||||
|
||||
# NOTE: to maintain compat wit the old script we special case if there's
|
||||
# only a single register (we drop the '_0').
|
||||
if len(dev.regs) > 1:
|
||||
return "BASE_ADDRESS_{}".format(dev.regs.index(reg))
|
||||
if len(node.regs) > 1:
|
||||
return "BASE_ADDRESS_{}".format(node.regs.index(reg))
|
||||
else:
|
||||
return "BASE_ADDRESS"
|
||||
|
||||
|
@ -226,61 +227,61 @@ def reg_size_ident(reg):
|
|||
# Returns the identifier (e.g., macro name) to be used for the size of
|
||||
# 'reg' in the output
|
||||
|
||||
dev = reg.dev
|
||||
node = reg.node
|
||||
|
||||
# NOTE: to maintain compat wit the old script we special case if there's
|
||||
# only a single register (we drop the '_0').
|
||||
if len(dev.regs) > 1:
|
||||
return "SIZE_{}".format(dev.regs.index(reg))
|
||||
if len(node.regs) > 1:
|
||||
return "SIZE_{}".format(node.regs.index(reg))
|
||||
else:
|
||||
return "SIZE"
|
||||
|
||||
|
||||
def dev_ident(dev):
|
||||
# Returns an identifier for the Device 'dev'. Used when building e.g. macro
|
||||
# names.
|
||||
def dev_ident(node):
|
||||
# Returns an identifier for the device given by 'node'. Used when building
|
||||
# e.g. macro names.
|
||||
|
||||
# TODO: Handle PWM on STM
|
||||
# TODO: Better document the rules of how we generate things
|
||||
|
||||
ident = ""
|
||||
|
||||
if dev.bus:
|
||||
if node.bus:
|
||||
ident += "{}_{:X}_".format(
|
||||
str2ident(dev.parent.matching_compat), dev.parent.unit_addr)
|
||||
str2ident(node.parent.matching_compat), node.parent.unit_addr)
|
||||
|
||||
ident += "{}_".format(str2ident(dev.matching_compat))
|
||||
ident += "{}_".format(str2ident(node.matching_compat))
|
||||
|
||||
if dev.unit_addr is not None:
|
||||
ident += "{:X}".format(dev.unit_addr)
|
||||
elif dev.parent.unit_addr is not None:
|
||||
ident += "{:X}_{}".format(dev.parent.unit_addr, str2ident(dev.name))
|
||||
if node.unit_addr is not None:
|
||||
ident += "{:X}".format(node.unit_addr)
|
||||
elif node.parent.unit_addr is not None:
|
||||
ident += "{:X}_{}".format(node.parent.unit_addr, str2ident(node.name))
|
||||
else:
|
||||
# This is a bit of a hack
|
||||
ident += "{}".format(str2ident(dev.name))
|
||||
ident += "{}".format(str2ident(node.name))
|
||||
|
||||
return ident
|
||||
|
||||
|
||||
def dev_aliases(dev):
|
||||
# Returns a list of aliases for the Device 'dev', used e.g. when building
|
||||
# macro names
|
||||
def dev_aliases(node):
|
||||
# Returns a list of aliases for the device given by 'node', used e.g. when
|
||||
# building macro names
|
||||
|
||||
return dev_path_aliases(dev) + dev_instance_aliases(dev)
|
||||
return dev_path_aliases(node) + dev_instance_aliases(node)
|
||||
|
||||
|
||||
def dev_path_aliases(dev):
|
||||
# Returns a list of aliases for the Device 'dev', based on the aliases
|
||||
# registered for the device, in the /aliases node. Used when building e.g.
|
||||
def dev_path_aliases(node):
|
||||
# Returns a list of aliases for the device given by 'node', based on the
|
||||
# aliases registered for it, in the /aliases node. Used when building e.g.
|
||||
# macro names.
|
||||
|
||||
if dev.matching_compat is None:
|
||||
if node.matching_compat is None:
|
||||
return []
|
||||
|
||||
compat_s = str2ident(dev.matching_compat)
|
||||
compat_s = str2ident(node.matching_compat)
|
||||
|
||||
aliases = []
|
||||
for alias in dev.aliases:
|
||||
for alias in node.aliases:
|
||||
aliases.append("ALIAS_{}".format(str2ident(alias)))
|
||||
# TODO: See if we can remove or deprecate this form
|
||||
aliases.append("{}_{}".format(compat_s, str2ident(alias)))
|
||||
|
@ -288,112 +289,112 @@ def dev_path_aliases(dev):
|
|||
return aliases
|
||||
|
||||
|
||||
def dev_instance_aliases(dev):
|
||||
# Returns a list of aliases for the Device 'dev', based on the instance
|
||||
# number of the device (based on how many instances of that particular
|
||||
# device there are).
|
||||
def dev_instance_aliases(node):
|
||||
# Returns a list of aliases for the device given by 'node', based on the
|
||||
# instance number of the device (based on how many instances of that
|
||||
# particular device there are).
|
||||
#
|
||||
# This is a list since a device can have multiple 'compatible' strings,
|
||||
# each with their own instance number.
|
||||
|
||||
return ["INST_{}_{}".format(dev.instance_no[compat], str2ident(compat))
|
||||
for compat in dev.compats]
|
||||
return ["INST_{}_{}".format(node.instance_no[compat], str2ident(compat))
|
||||
for compat in node.compats]
|
||||
|
||||
|
||||
def write_addr_size(edt, prop_name, prefix):
|
||||
# Writes <prefix>_BASE_ADDRESS and <prefix>_SIZE for the device
|
||||
# pointed at by the /chosen property named 'prop_name', if it exists
|
||||
# Writes <prefix>_BASE_ADDRESS and <prefix>_SIZE for the node pointed at by
|
||||
# the /chosen property named 'prop_name', if it exists
|
||||
|
||||
dev = edt.chosen_dev(prop_name)
|
||||
if not dev:
|
||||
node = edt.chosen_node(prop_name)
|
||||
if not node:
|
||||
return
|
||||
|
||||
if not dev.regs:
|
||||
if not node.regs:
|
||||
err("missing 'reg' property in node pointed at by /chosen/{} ({!r})"
|
||||
.format(prop_name, dev))
|
||||
.format(prop_name, node))
|
||||
|
||||
out_comment("/chosen/{} ({})".format(prop_name, dev.path))
|
||||
out("{}_BASE_ADDRESS".format(prefix), hex(dev.regs[0].addr))
|
||||
out("{}_SIZE".format(prefix), dev.regs[0].size//1024)
|
||||
out_comment("/chosen/{} ({})".format(prop_name, node.path))
|
||||
out("{}_BASE_ADDRESS".format(prefix), hex(node.regs[0].addr))
|
||||
out("{}_SIZE".format(prefix), node.regs[0].size//1024)
|
||||
|
||||
|
||||
def write_flash(flash_dev):
|
||||
def write_flash(flash_node):
|
||||
# Writes output for the node pointed at by the zephyr,flash property in
|
||||
# /chosen
|
||||
|
||||
out_comment("/chosen/zephyr,flash ({})"
|
||||
.format(flash_dev.path if flash_dev else "missing"))
|
||||
.format(flash_node.path if flash_node else "missing"))
|
||||
|
||||
if not flash_dev:
|
||||
# No flash device. Write dummy values.
|
||||
if not flash_node:
|
||||
# No flash node. Write dummy values.
|
||||
out("FLASH_BASE_ADDRESS", 0)
|
||||
out("FLASH_SIZE", 0)
|
||||
return
|
||||
|
||||
if len(flash_dev.regs) != 1:
|
||||
if len(flash_node.regs) != 1:
|
||||
err("expected zephyr,flash to have a single register, has {}"
|
||||
.format(len(flash_dev.regs)))
|
||||
.format(len(flash_node.regs)))
|
||||
|
||||
if flash_dev.bus == "spi" and len(flash_dev.parent.regs) == 2:
|
||||
reg = flash_dev.parent.regs[1] # QSPI flash
|
||||
if flash_node.bus == "spi" and len(flash_node.parent.regs) == 2:
|
||||
reg = flash_node.parent.regs[1] # QSPI flash
|
||||
else:
|
||||
reg = flash_dev.regs[0]
|
||||
reg = flash_node.regs[0]
|
||||
|
||||
out("FLASH_BASE_ADDRESS", hex(reg.addr))
|
||||
if reg.size:
|
||||
out("FLASH_SIZE", reg.size//1024)
|
||||
|
||||
if "erase-block-size" in flash_dev.props:
|
||||
out("FLASH_ERASE_BLOCK_SIZE", flash_dev.props["erase-block-size"].val)
|
||||
if "erase-block-size" in flash_node.props:
|
||||
out("FLASH_ERASE_BLOCK_SIZE", flash_node.props["erase-block-size"].val)
|
||||
|
||||
if "write-block-size" in flash_dev.props:
|
||||
out("FLASH_WRITE_BLOCK_SIZE", flash_dev.props["write-block-size"].val)
|
||||
if "write-block-size" in flash_node.props:
|
||||
out("FLASH_WRITE_BLOCK_SIZE", flash_node.props["write-block-size"].val)
|
||||
|
||||
|
||||
def write_code_partition(code_dev):
|
||||
def write_code_partition(code_node):
|
||||
# Writes output for the node pointed at by the zephyr,code-partition
|
||||
# property in /chosen
|
||||
|
||||
out_comment("/chosen/zephyr,code-partition ({})"
|
||||
.format(code_dev.path if code_dev else "missing"))
|
||||
.format(code_node.path if code_node else "missing"))
|
||||
|
||||
if not code_dev:
|
||||
if not code_node:
|
||||
# No code partition. Write dummy values.
|
||||
out("CODE_PARTITION_OFFSET", 0)
|
||||
out("CODE_PARTITION_SIZE", 0)
|
||||
return
|
||||
|
||||
if not code_dev.regs:
|
||||
err("missing 'regs' property on {!r}".format(code_dev))
|
||||
if not code_node.regs:
|
||||
err("missing 'regs' property on {!r}".format(code_node))
|
||||
|
||||
out("CODE_PARTITION_OFFSET", code_dev.regs[0].addr)
|
||||
out("CODE_PARTITION_SIZE", code_dev.regs[0].size)
|
||||
out("CODE_PARTITION_OFFSET", code_node.regs[0].addr)
|
||||
out("CODE_PARTITION_SIZE", code_node.regs[0].size)
|
||||
|
||||
|
||||
def write_flash_partition(partition_dev, index):
|
||||
out_comment("Flash partition at " + partition_dev.path)
|
||||
def write_flash_partition(partition_node, index):
|
||||
out_comment("Flash partition at " + partition_node.path)
|
||||
|
||||
if partition_dev.label is None:
|
||||
err("missing 'label' property on {!r}".format(partition_dev))
|
||||
if partition_node.label is None:
|
||||
err("missing 'label' property on {!r}".format(partition_node))
|
||||
|
||||
# Generate label-based identifiers
|
||||
write_flash_partition_prefix(
|
||||
"FLASH_AREA_" + str2ident(partition_dev.label), partition_dev, index)
|
||||
"FLASH_AREA_" + str2ident(partition_node.label), partition_node, index)
|
||||
|
||||
# Generate index-based identifiers
|
||||
write_flash_partition_prefix(
|
||||
"FLASH_AREA_{}".format(index), partition_dev, index)
|
||||
"FLASH_AREA_{}".format(index), partition_node, index)
|
||||
|
||||
|
||||
def write_flash_partition_prefix(prefix, partition_dev, index):
|
||||
def write_flash_partition_prefix(prefix, partition_node, index):
|
||||
# write_flash_partition() helper. Generates identifiers starting with
|
||||
# 'prefix'.
|
||||
|
||||
out("{}_ID".format(prefix), index)
|
||||
|
||||
out("{}_READ_ONLY".format(prefix), 1 if partition_dev.read_only else 0)
|
||||
out("{}_READ_ONLY".format(prefix), 1 if partition_node.read_only else 0)
|
||||
|
||||
for i, reg in enumerate(partition_dev.regs):
|
||||
for i, reg in enumerate(partition_node.regs):
|
||||
# Also add aliases that point to the first sector (TODO: get rid of the
|
||||
# aliases?)
|
||||
out("{}_OFFSET_{}".format(prefix, i), reg.addr,
|
||||
|
@ -401,13 +402,14 @@ def write_flash_partition_prefix(prefix, partition_dev, index):
|
|||
out("{}_SIZE_{}".format(prefix, i), reg.size,
|
||||
aliases=["{}_SIZE".format(prefix)] if i == 0 else [])
|
||||
|
||||
controller = partition_dev.flash_controller
|
||||
controller = partition_node.flash_controller
|
||||
if controller.label is not None:
|
||||
out_s("{}_DEV".format(prefix), controller.label)
|
||||
|
||||
|
||||
def write_irqs(dev):
|
||||
# Writes IRQ num and data for the interrupts in dev's 'interrupt' property
|
||||
def write_irqs(node):
|
||||
# Writes IRQ num and data for the interrupts in the node's 'interrupt'
|
||||
# property
|
||||
|
||||
def irq_name_alias(irq, cell_name):
|
||||
if not irq.name:
|
||||
|
@ -433,7 +435,7 @@ def write_irqs(dev):
|
|||
irq_ctrl = irq_ctrl.interrupts[0].controller
|
||||
return irq_num
|
||||
|
||||
for irq_i, irq in enumerate(dev.interrupts):
|
||||
for irq_i, irq in enumerate(node.interrupts):
|
||||
for cell_name, cell_value in irq.specifier.items():
|
||||
ident = "IRQ_{}".format(irq_i)
|
||||
if cell_name == "irq":
|
||||
|
@ -441,25 +443,25 @@ def write_irqs(dev):
|
|||
else:
|
||||
ident += "_" + str2ident(cell_name)
|
||||
|
||||
out_dev(dev, ident, cell_value,
|
||||
out_dev(node, ident, cell_value,
|
||||
name_alias=irq_name_alias(irq, cell_name))
|
||||
|
||||
|
||||
def write_spi_dev(dev):
|
||||
def write_spi_dev(node):
|
||||
# Writes SPI device GPIO chip select data if there is any
|
||||
|
||||
cs_gpio = edtlib.spi_dev_cs_gpio(dev)
|
||||
cs_gpio = edtlib.spi_dev_cs_gpio(node)
|
||||
if cs_gpio is not None:
|
||||
write_phandle_val_list_entry(dev, cs_gpio, None, "GPIO")
|
||||
write_phandle_val_list_entry(node, cs_gpio, None, "GPIO")
|
||||
|
||||
|
||||
def write_phandle_val_list(dev, entries, ident):
|
||||
def write_phandle_val_list(node, entries, ident):
|
||||
# Writes output for a phandle/value list, e.g.
|
||||
#
|
||||
# pwms = <&pwm-ctrl-1 10 20
|
||||
# &pwm-ctrl-2 30 40>;
|
||||
#
|
||||
# dev:
|
||||
# node:
|
||||
# Device used to generate device prefixes (see 'ident' below)
|
||||
#
|
||||
# entries:
|
||||
|
@ -487,13 +489,13 @@ def write_phandle_val_list(dev, entries, ident):
|
|||
initializer_vals = []
|
||||
for i, entry in enumerate(entries):
|
||||
initializer_vals.append(write_phandle_val_list_entry(
|
||||
dev, entry, i if len(entries) > 1 else None, ident))
|
||||
node, entry, i if len(entries) > 1 else None, ident))
|
||||
if len(entries) > 1:
|
||||
out_dev(dev, ident + "S_COUNT", len(initializer_vals))
|
||||
out_dev(dev, ident + "S", "{" + ", ".join(initializer_vals) + "}")
|
||||
out_dev(node, ident + "S_COUNT", len(initializer_vals))
|
||||
out_dev(node, ident + "S", "{" + ", ".join(initializer_vals) + "}")
|
||||
|
||||
|
||||
def write_phandle_val_list_entry(dev, entry, i, ident):
|
||||
def write_phandle_val_list_entry(node, entry, i, ident):
|
||||
# write_phandle_val_list() helper. We could get rid of it if it wasn't for
|
||||
# write_spi_dev(). Adds 'i' as an index to identifiers unless it's None.
|
||||
#
|
||||
|
@ -510,7 +512,7 @@ def write_phandle_val_list_entry(dev, entry, i, ident):
|
|||
if i is not None:
|
||||
ctrl_ident += "_{}".format(i)
|
||||
initializer_vals.append(quote_str(entry.controller.label))
|
||||
out_dev_s(dev, ctrl_ident, entry.controller.label)
|
||||
out_dev_s(node, ctrl_ident, entry.controller.label)
|
||||
|
||||
for cell, val in entry.specifier.items():
|
||||
cell_ident = ident + "S_" + str2ident(cell) # e.g. PWMS_CHANNEL
|
||||
|
@ -520,7 +522,7 @@ def write_phandle_val_list_entry(dev, entry, i, ident):
|
|||
# Backwards compatibility (see above)
|
||||
if i is not None:
|
||||
cell_ident += "_{}".format(i)
|
||||
out_dev(dev, cell_ident, val)
|
||||
out_dev(node, cell_ident, val)
|
||||
|
||||
initializer_vals += entry.specifier.values()
|
||||
|
||||
|
@ -529,20 +531,20 @@ def write_phandle_val_list_entry(dev, entry, i, ident):
|
|||
initializer_ident += "_" + str2ident(entry.name)
|
||||
if i is not None:
|
||||
initializer_ident += "_{}".format(i)
|
||||
return out_dev(dev, initializer_ident,
|
||||
return out_dev(node, initializer_ident,
|
||||
"{" + ", ".join(map(str, initializer_vals)) + "}")
|
||||
|
||||
|
||||
def write_clocks(dev):
|
||||
# Writes clock controller and specifier info for the clock in dev's 'clock'
|
||||
# property
|
||||
def write_clocks(node):
|
||||
# Writes clock controller and specifier info for the clock in the node's
|
||||
# 'clock' property
|
||||
|
||||
for clock_i, clock in enumerate(dev.clocks):
|
||||
for clock_i, clock in enumerate(node.clocks):
|
||||
if clock.controller.label is not None:
|
||||
out_dev_s(dev, "CLOCK_CONTROLLER", clock.controller.label)
|
||||
out_dev_s(node, "CLOCK_CONTROLLER", clock.controller.label)
|
||||
|
||||
if clock.frequency is not None:
|
||||
out_dev(dev, "CLOCKS_CLOCK_FREQUENCY", clock.frequency)
|
||||
out_dev(node, "CLOCKS_CLOCK_FREQUENCY", clock.frequency)
|
||||
|
||||
for spec, val in clock.specifier.items():
|
||||
if clock_i == 0:
|
||||
|
@ -550,7 +552,7 @@ def write_clocks(dev):
|
|||
else:
|
||||
clk_name_alias = None
|
||||
|
||||
out_dev(dev, "CLOCK_{}_{}".format(str2ident(spec), clock_i), val,
|
||||
out_dev(node, "CLOCK_{}_{}".format(str2ident(spec), clock_i), val,
|
||||
name_alias=clk_name_alias)
|
||||
|
||||
|
||||
|
@ -566,7 +568,7 @@ def str2ident(s):
|
|||
.upper()
|
||||
|
||||
|
||||
def out_dev(dev, ident, val, name_alias=None):
|
||||
def out_dev(node, ident, val, name_alias=None):
|
||||
# Writes an
|
||||
#
|
||||
# <device prefix>_<ident> = <val>
|
||||
|
@ -584,24 +586,24 @@ def out_dev(dev, ident, val, name_alias=None):
|
|||
# 'name_alias' is used for reg-names and the like.
|
||||
#
|
||||
# Returns the identifier used for the macro that provides the value
|
||||
# for 'ident' within 'dev', e.g. DT_MFG_MODEL_CTL_GPIOS_PIN.
|
||||
# for 'ident' within 'node', e.g. DT_MFG_MODEL_CTL_GPIOS_PIN.
|
||||
|
||||
dev_prefix = dev_ident(dev)
|
||||
dev_prefix = dev_ident(node)
|
||||
|
||||
aliases = [alias + "_" + ident for alias in dev_aliases(dev)]
|
||||
aliases = [alias + "_" + ident for alias in dev_aliases(node)]
|
||||
if name_alias is not None:
|
||||
aliases.append(dev_prefix + "_" + name_alias)
|
||||
aliases += [alias + "_" + name_alias for alias in dev_aliases(dev)]
|
||||
aliases += [alias + "_" + name_alias for alias in dev_aliases(node)]
|
||||
|
||||
return out(dev_prefix + "_" + ident, val, aliases)
|
||||
|
||||
|
||||
def out_dev_s(dev, ident, s):
|
||||
def out_dev_s(node, ident, s):
|
||||
# Like out_dev(), but emits 's' as a string literal
|
||||
#
|
||||
# Returns the generated macro name for 'ident'.
|
||||
|
||||
return out_dev(dev, ident, quote_str(s))
|
||||
return out_dev(node, ident, quote_str(s))
|
||||
|
||||
|
||||
def out_s(ident, val):
|
||||
|
|
|
@ -40,109 +40,109 @@ def run():
|
|||
# Test interrupts
|
||||
#
|
||||
|
||||
verify_streq(edt.get_dev("/interrupt-parent-test/node").interrupts,
|
||||
"[<Interrupt, name: foo, target: <Device /interrupt-parent-test/controller in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 1, 'two': 2, 'three': 3}>, <Interrupt, name: bar, target: <Device /interrupt-parent-test/controller in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 4, 'two': 5, 'three': 6}>]")
|
||||
verify_streq(edt.get_node("/interrupt-parent-test/node").interrupts,
|
||||
"[<Interrupt, name: foo, target: <Node /interrupt-parent-test/controller in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 1, 'two': 2, 'three': 3}>, <Interrupt, name: bar, target: <Node /interrupt-parent-test/controller in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 4, 'two': 5, 'three': 6}>]")
|
||||
|
||||
verify_streq(edt.get_dev("/interrupts-extended-test/node").interrupts,
|
||||
"[<Interrupt, target: <Device /interrupts-extended-test/controller-0 in 'test.dts', binding test-bindings/interrupt-1-cell.yaml>, specifier: {'one': 1}>, <Interrupt, target: <Device /interrupts-extended-test/controller-1 in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, specifier: {'one': 2, 'two': 3}>, <Interrupt, target: <Device /interrupts-extended-test/controller-2 in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 4, 'two': 5, 'three': 6}>]")
|
||||
verify_streq(edt.get_node("/interrupts-extended-test/node").interrupts,
|
||||
"[<Interrupt, target: <Node /interrupts-extended-test/controller-0 in 'test.dts', binding test-bindings/interrupt-1-cell.yaml>, specifier: {'one': 1}>, <Interrupt, target: <Node /interrupts-extended-test/controller-1 in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, specifier: {'one': 2, 'two': 3}>, <Interrupt, target: <Node /interrupts-extended-test/controller-2 in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 4, 'two': 5, 'three': 6}>]")
|
||||
|
||||
verify_streq(edt.get_dev("/interrupt-map-test/node@0").interrupts,
|
||||
"[<Interrupt, target: <Device /interrupt-map-test/controller-0 in 'test.dts', binding test-bindings/interrupt-1-cell.yaml>, specifier: {'one': 0}>, <Interrupt, target: <Device /interrupt-map-test/controller-1 in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, specifier: {'one': 0, 'two': 1}>, <Interrupt, target: <Device /interrupt-map-test/controller-2 in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 0, 'two': 0, 'three': 2}>]")
|
||||
verify_streq(edt.get_node("/interrupt-map-test/node@0").interrupts,
|
||||
"[<Interrupt, target: <Node /interrupt-map-test/controller-0 in 'test.dts', binding test-bindings/interrupt-1-cell.yaml>, specifier: {'one': 0}>, <Interrupt, target: <Node /interrupt-map-test/controller-1 in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, specifier: {'one': 0, 'two': 1}>, <Interrupt, target: <Node /interrupt-map-test/controller-2 in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 0, 'two': 0, 'three': 2}>]")
|
||||
|
||||
verify_streq(edt.get_dev("/interrupt-map-test/node@1").interrupts,
|
||||
"[<Interrupt, target: <Device /interrupt-map-test/controller-0 in 'test.dts', binding test-bindings/interrupt-1-cell.yaml>, specifier: {'one': 3}>, <Interrupt, target: <Device /interrupt-map-test/controller-1 in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, specifier: {'one': 0, 'two': 4}>, <Interrupt, target: <Device /interrupt-map-test/controller-2 in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 0, 'two': 0, 'three': 5}>]")
|
||||
verify_streq(edt.get_node("/interrupt-map-test/node@1").interrupts,
|
||||
"[<Interrupt, target: <Node /interrupt-map-test/controller-0 in 'test.dts', binding test-bindings/interrupt-1-cell.yaml>, specifier: {'one': 3}>, <Interrupt, target: <Node /interrupt-map-test/controller-1 in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, specifier: {'one': 0, 'two': 4}>, <Interrupt, target: <Node /interrupt-map-test/controller-2 in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 0, 'two': 0, 'three': 5}>]")
|
||||
|
||||
verify_streq(edt.get_dev("/interrupt-map-bitops-test/node@70000000E").interrupts,
|
||||
"[<Interrupt, target: <Device /interrupt-map-bitops-test/controller in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, specifier: {'one': 3, 'two': 2}>]")
|
||||
verify_streq(edt.get_node("/interrupt-map-bitops-test/node@70000000E").interrupts,
|
||||
"[<Interrupt, target: <Node /interrupt-map-bitops-test/controller in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, specifier: {'one': 3, 'two': 2}>]")
|
||||
|
||||
#
|
||||
# Test GPIOs
|
||||
#
|
||||
|
||||
verify_streq(edt.get_dev("/gpio-test/node").gpios,
|
||||
"{'': [<GPIO, name: , target: <Device /gpio-test/controller-0 in 'test.dts', binding test-bindings/gpio-1-cell.yaml>, specifier: {'one': 1}>, <GPIO, name: , target: <Device /gpio-test/controller-1 in 'test.dts', binding test-bindings/gpio-2-cell.yaml>, specifier: {'one': 2, 'two': 3}>], 'foo': [<GPIO, name: foo, target: <Device /gpio-test/controller-1 in 'test.dts', binding test-bindings/gpio-2-cell.yaml>, specifier: {'one': 4, 'two': 5}>], 'bar': [<GPIO, name: bar, target: <Device /gpio-test/controller-1 in 'test.dts', binding test-bindings/gpio-2-cell.yaml>, specifier: {'one': 6, 'two': 7}>]}")
|
||||
verify_streq(edt.get_node("/gpio-test/node").gpios,
|
||||
"{'': [<GPIO, name: , target: <Node /gpio-test/controller-0 in 'test.dts', binding test-bindings/gpio-1-cell.yaml>, specifier: {'one': 1}>, <GPIO, name: , target: <Node /gpio-test/controller-1 in 'test.dts', binding test-bindings/gpio-2-cell.yaml>, specifier: {'one': 2, 'two': 3}>], 'foo': [<GPIO, name: foo, target: <Node /gpio-test/controller-1 in 'test.dts', binding test-bindings/gpio-2-cell.yaml>, specifier: {'one': 4, 'two': 5}>], 'bar': [<GPIO, name: bar, target: <Node /gpio-test/controller-1 in 'test.dts', binding test-bindings/gpio-2-cell.yaml>, specifier: {'one': 6, 'two': 7}>]}")
|
||||
|
||||
#
|
||||
# Test clocks
|
||||
#
|
||||
|
||||
verify_streq(edt.get_dev("/clock-test/node").clocks,
|
||||
"[<Clock, name: fixed, frequency: 123, target: <Device /clock-test/fixed-clock in 'test.dts', binding test-bindings/fixed-clock.yaml>, specifier: {}>, <Clock, name: one-cell, target: <Device /clock-test/clock-1 in 'test.dts', binding test-bindings/clock-1-cell.yaml>, specifier: {'one': 1}>, <Clock, name: two-cell, target: <Device /clock-test/clock-2 in 'test.dts', binding test-bindings/clock-2-cell.yaml>, specifier: {'one': 1, 'two': 2}>]")
|
||||
verify_streq(edt.get_node("/clock-test/node").clocks,
|
||||
"[<Clock, name: fixed, frequency: 123, target: <Node /clock-test/fixed-clock in 'test.dts', binding test-bindings/fixed-clock.yaml>, specifier: {}>, <Clock, name: one-cell, target: <Node /clock-test/clock-1 in 'test.dts', binding test-bindings/clock-1-cell.yaml>, specifier: {'one': 1}>, <Clock, name: two-cell, target: <Node /clock-test/clock-2 in 'test.dts', binding test-bindings/clock-2-cell.yaml>, specifier: {'one': 1, 'two': 2}>]")
|
||||
|
||||
#
|
||||
# Test PWMs
|
||||
#
|
||||
|
||||
verify_streq(edt.get_dev("/pwm-test/node").pwms,
|
||||
"[<PWM, name: zero-cell, target: <Device /pwm-test/pwm-0 in 'test.dts', binding test-bindings/pwm-0-cell.yaml>, specifier: {}>, <PWM, name: one-cell, target: <Device /pwm-test/pwm-1 in 'test.dts', binding test-bindings/pwm-1-cell.yaml>, specifier: {'one': 1}>]")
|
||||
verify_streq(edt.get_node("/pwm-test/node").pwms,
|
||||
"[<PWM, name: zero-cell, target: <Node /pwm-test/pwm-0 in 'test.dts', binding test-bindings/pwm-0-cell.yaml>, specifier: {}>, <PWM, name: one-cell, target: <Node /pwm-test/pwm-1 in 'test.dts', binding test-bindings/pwm-1-cell.yaml>, specifier: {'one': 1}>]")
|
||||
|
||||
#
|
||||
# Test IO channels
|
||||
#
|
||||
|
||||
verify_streq(edt.get_dev("/io-channel-test/node").iochannels,
|
||||
"[<IOChannel, name: io-channel, target: <Device /io-channel-test/io-channel in 'test.dts', binding test-bindings/io-channel.yaml>, specifier: {'one': 1}>]")
|
||||
verify_streq(edt.get_node("/io-channel-test/node").iochannels,
|
||||
"[<IOChannel, name: io-channel, target: <Node /io-channel-test/io-channel in 'test.dts', binding test-bindings/io-channel.yaml>, specifier: {'one': 1}>]")
|
||||
|
||||
#
|
||||
# Test 'reg'
|
||||
#
|
||||
|
||||
verify_streq(edt.get_dev("/reg-zero-address-cells/node").regs,
|
||||
verify_streq(edt.get_node("/reg-zero-address-cells/node").regs,
|
||||
"[<Register, addr: 0x0, size: 0x1>, <Register, addr: 0x0, size: 0x2>]")
|
||||
|
||||
verify_streq(edt.get_dev("/reg-zero-size-cells/node").regs,
|
||||
verify_streq(edt.get_node("/reg-zero-size-cells/node").regs,
|
||||
"[<Register, addr: 0x1, size: 0x0>, <Register, addr: 0x2, size: 0x0>]")
|
||||
|
||||
verify_streq(edt.get_dev("/reg-ranges/parent/node").regs,
|
||||
verify_streq(edt.get_node("/reg-ranges/parent/node").regs,
|
||||
"[<Register, addr: 0x5, size: 0x1>, <Register, addr: 0xe0000000f, size: 0x1>, <Register, addr: 0xc0000000e, size: 0x1>, <Register, addr: 0xc0000000d, size: 0x1>, <Register, addr: 0xa0000000b, size: 0x1>, <Register, addr: 0x0, size: 0x1>]")
|
||||
|
||||
verify_streq(edt.get_dev("/reg-nested-ranges/grandparent/parent/node").regs,
|
||||
verify_streq(edt.get_node("/reg-nested-ranges/grandparent/parent/node").regs,
|
||||
"[<Register, addr: 0x30000000200000001, size: 0x1>]")
|
||||
|
||||
#
|
||||
# Test Device.parent and Device.children
|
||||
#
|
||||
|
||||
verify_eq(edt.get_dev("/").parent, None)
|
||||
verify_eq(edt.get_node("/").parent, None)
|
||||
|
||||
verify_streq(edt.get_dev("/parent/child-1").parent,
|
||||
"<Device /parent in 'test.dts', no binding>")
|
||||
verify_streq(edt.get_node("/parent/child-1").parent,
|
||||
"<Node /parent in 'test.dts', no binding>")
|
||||
|
||||
verify_streq(edt.get_dev("/parent/child-2/grandchild").parent,
|
||||
"<Device /parent/child-2 in 'test.dts', no binding>")
|
||||
verify_streq(edt.get_node("/parent/child-2/grandchild").parent,
|
||||
"<Node /parent/child-2 in 'test.dts', no binding>")
|
||||
|
||||
verify_streq(edt.get_dev("/parent").children,
|
||||
"{'child-1': <Device /parent/child-1 in 'test.dts', no binding>, 'child-2': <Device /parent/child-2 in 'test.dts', no binding>}")
|
||||
verify_streq(edt.get_node("/parent").children,
|
||||
"{'child-1': <Node /parent/child-1 in 'test.dts', no binding>, 'child-2': <Node /parent/child-2 in 'test.dts', no binding>}")
|
||||
|
||||
verify_eq(edt.get_dev("/parent/child-1").children, {})
|
||||
verify_eq(edt.get_node("/parent/child-1").children, {})
|
||||
|
||||
#
|
||||
# Test 'include:' and the legacy 'inherits: !include ...'
|
||||
#
|
||||
|
||||
verify_streq(edt.get_dev("/binding-include").description,
|
||||
verify_streq(edt.get_node("/binding-include").description,
|
||||
"Parent binding")
|
||||
|
||||
verify_streq(edt.get_dev("/binding-include").props,
|
||||
verify_streq(edt.get_node("/binding-include").props,
|
||||
"{'foo': <Property, name: foo, type: int, value: 0>, 'bar': <Property, name: bar, type: int, value: 1>, 'baz': <Property, name: baz, type: int, value: 2>, 'qaz': <Property, name: qaz, type: int, value: 3>}")
|
||||
|
||||
#
|
||||
# Test 'child/parent-bus:'
|
||||
#
|
||||
|
||||
verify_streq(edt.get_dev("/buses/foo-bus/node").binding_path,
|
||||
verify_streq(edt.get_node("/buses/foo-bus/node").binding_path,
|
||||
"test-bindings/device-on-foo-bus.yaml")
|
||||
|
||||
verify_streq(edt.get_dev("/buses/bar-bus/node").binding_path,
|
||||
verify_streq(edt.get_node("/buses/bar-bus/node").binding_path,
|
||||
"test-bindings/device-on-bar-bus.yaml")
|
||||
|
||||
#
|
||||
# Test 'child-binding:'
|
||||
#
|
||||
|
||||
child1 = edt.get_dev("/child-binding/child-1")
|
||||
child2 = edt.get_dev("/child-binding/child-2")
|
||||
grandchild = edt.get_dev("/child-binding/child-1/grandchild")
|
||||
child1 = edt.get_node("/child-binding/child-1")
|
||||
child2 = edt.get_node("/child-binding/child-2")
|
||||
grandchild = edt.get_node("/child-binding/child-1/grandchild")
|
||||
|
||||
verify_streq(child1.binding_path, "test-bindings/child-binding.yaml")
|
||||
verify_streq(child1.description, "child node")
|
||||
|
@ -160,21 +160,21 @@ def run():
|
|||
# Test deprecated 'sub-node:' key (replaced with 'child-binding:')
|
||||
#
|
||||
|
||||
verify_streq(edt.get_dev("/deprecated/sub-node").props,
|
||||
verify_streq(edt.get_node("/deprecated/sub-node").props,
|
||||
"{'child-prop': <Property, name: child-prop, type: int, value: 3>}")
|
||||
|
||||
#
|
||||
# Test Device.property (derived from DT and 'properties:' in the binding)
|
||||
#
|
||||
|
||||
verify_streq(edt.get_dev("/props").props,
|
||||
r"{'nonexistent-boolean': <Property, name: nonexistent-boolean, type: boolean, value: False>, 'existent-boolean': <Property, name: existent-boolean, type: boolean, value: True>, 'int': <Property, name: int, type: int, value: 1>, 'array': <Property, name: array, type: array, value: [1, 2, 3]>, 'uint8-array': <Property, name: uint8-array, type: uint8-array, value: b'\x124'>, 'string': <Property, name: string, type: string, value: 'foo'>, 'string-array': <Property, name: string-array, type: string-array, value: ['foo', 'bar', 'baz']>, 'phandle-ref': <Property, name: phandle-ref, type: phandle, value: <Device /props/node in 'test.dts', no binding>>, 'phandle-refs': <Property, name: phandle-refs, type: phandles, value: [<Device /props/node in 'test.dts', no binding>, <Device /props/node2 in 'test.dts', no binding>]>}")
|
||||
verify_streq(edt.get_node("/props").props,
|
||||
r"{'nonexistent-boolean': <Property, name: nonexistent-boolean, type: boolean, value: False>, 'existent-boolean': <Property, name: existent-boolean, type: boolean, value: True>, 'int': <Property, name: int, type: int, value: 1>, 'array': <Property, name: array, type: array, value: [1, 2, 3]>, 'uint8-array': <Property, name: uint8-array, type: uint8-array, value: b'\x124'>, 'string': <Property, name: string, type: string, value: 'foo'>, 'string-array': <Property, name: string-array, type: string-array, value: ['foo', 'bar', 'baz']>, 'phandle-ref': <Property, name: phandle-ref, type: phandle, value: <Node /props/node in 'test.dts', no binding>>, 'phandle-refs': <Property, name: phandle-refs, type: phandles, value: [<Node /props/node in 'test.dts', no binding>, <Node /props/node2 in 'test.dts', no binding>]>}")
|
||||
|
||||
#
|
||||
# Test property default values given in bindings
|
||||
#
|
||||
|
||||
verify_streq(edt.get_dev("/defaults").props,
|
||||
verify_streq(edt.get_node("/defaults").props,
|
||||
r"{'int': <Property, name: int, type: int, value: 123>, 'array': <Property, name: array, type: array, value: [1, 2, 3]>, 'uint8-array': <Property, name: uint8-array, type: uint8-array, value: b'\x89\xab\xcd'>, 'string': <Property, name: string, type: string, value: 'hello'>, 'string-array': <Property, name: string-array, type: string-array, value: ['hello', 'there']>, 'default-not-used': <Property, name: default-not-used, type: int, value: 234>}")
|
||||
|
||||
#
|
||||
|
@ -183,10 +183,10 @@ def run():
|
|||
|
||||
edt = edtlib.EDT("test-multidir.dts", ["test-bindings", "test-bindings-2"])
|
||||
|
||||
verify_streq(edt.get_dev("/in-dir-1").binding_path,
|
||||
verify_streq(edt.get_node("/in-dir-1").binding_path,
|
||||
"test-bindings/multidir.yaml")
|
||||
|
||||
verify_streq(edt.get_dev("/in-dir-2").binding_path,
|
||||
verify_streq(edt.get_node("/in-dir-2").binding_path,
|
||||
"test-bindings-2/multidir.yaml")
|
||||
|
||||
|
||||
|
|
|
@ -121,54 +121,54 @@ def dt_str_val(kconf, _, name):
|
|||
def dt_chosen_label(kconf, _, chosen):
|
||||
"""
|
||||
This function takes a 'chosen' property and treats that property as a path
|
||||
to a EDT device. If it finds a EDT device, it will look to see if that
|
||||
device has a "label" property and return the value of that "label", if not
|
||||
we return an empty string.
|
||||
to an EDT node. If it finds an EDT node, it will look to see if that node
|
||||
has a "label" property and return the value of that "label", if not we
|
||||
return an empty string.
|
||||
"""
|
||||
if doc_mode or edt is None:
|
||||
return ""
|
||||
|
||||
dev = edt.chosen_dev(chosen)
|
||||
if not dev:
|
||||
node = edt.chosen_node(chosen)
|
||||
if not node:
|
||||
return ""
|
||||
|
||||
if "label" not in dev.props:
|
||||
if "label" not in node.props:
|
||||
return ""
|
||||
|
||||
return dev.props["label"].val
|
||||
return node.props["label"].val
|
||||
|
||||
|
||||
def _dev_reg_addr(dev, index, unit):
|
||||
if not dev:
|
||||
def _node_reg_addr(node, index, unit):
|
||||
if not node:
|
||||
return "0x0"
|
||||
|
||||
if not dev.regs:
|
||||
if not node.regs:
|
||||
return "0x0"
|
||||
|
||||
if int(index) >= len(dev.regs):
|
||||
if int(index) >= len(node.regs):
|
||||
return "0x0"
|
||||
|
||||
return hex(dev.regs[int(index)].addr >> _dt_units_to_scale(unit))
|
||||
return hex(node.regs[int(index)].addr >> _dt_units_to_scale(unit))
|
||||
|
||||
|
||||
def _dev_reg_size(dev, index, unit):
|
||||
if not dev:
|
||||
def _node_reg_size(node, index, unit):
|
||||
if not node:
|
||||
return "0"
|
||||
|
||||
if not dev.regs:
|
||||
if not node.regs:
|
||||
return "0"
|
||||
|
||||
if int(index) >= len(dev.regs):
|
||||
if int(index) >= len(node.regs):
|
||||
return "0"
|
||||
|
||||
return str(dev.regs[int(index)].size >> _dt_units_to_scale(unit))
|
||||
return str(node.regs[int(index)].size >> _dt_units_to_scale(unit))
|
||||
|
||||
|
||||
def dt_chosen_reg_addr(kconf, _, chosen, index=0, unit=None):
|
||||
"""
|
||||
This function takes a 'chosen' property and treats that property as a path
|
||||
to a EDT device. If it finds a EDT device, it will look to see if that
|
||||
device has a register at the give 'index' and return the address value of
|
||||
to an EDT node. If it finds an EDT node, it will look to see if that
|
||||
nodnode has a register at the given 'index' and return the address value of
|
||||
that reg, if not we return 0.
|
||||
|
||||
The function will divide the value based on 'unit':
|
||||
|
@ -180,17 +180,17 @@ def dt_chosen_reg_addr(kconf, _, chosen, index=0, unit=None):
|
|||
if doc_mode or edt is None:
|
||||
return "0x0"
|
||||
|
||||
dev = edt.chosen_dev(chosen)
|
||||
node = edt.chosen_node(chosen)
|
||||
|
||||
return _dev_reg_addr(dev, index, unit)
|
||||
return _node_reg_addr(node, index, unit)
|
||||
|
||||
|
||||
def dt_chosen_reg_size(kconf, _, chosen, index=0, unit=None):
|
||||
"""
|
||||
This function takes a 'chosen' property and treats that property as a path
|
||||
to a EDT device. If it finds a EDT device, it will look to see if that
|
||||
device has a register at the give 'index' and return the size value of
|
||||
that reg, if not we return 0.
|
||||
to an EDT node. If it finds an EDT node, it will look to see if that node
|
||||
has a register at the given 'index' and return the size value of that reg,
|
||||
if not we return 0.
|
||||
|
||||
The function will divide the value based on 'unit':
|
||||
None No division
|
||||
|
@ -201,17 +201,16 @@ def dt_chosen_reg_size(kconf, _, chosen, index=0, unit=None):
|
|||
if doc_mode or edt is None:
|
||||
return "0"
|
||||
|
||||
dev = edt.chosen_dev(chosen)
|
||||
node = edt.chosen_node(chosen)
|
||||
|
||||
return _dev_reg_size(dev, index, unit)
|
||||
return _node_reg_size(node, index, unit)
|
||||
|
||||
|
||||
def dt_node_reg_addr(kconf, _, path, index=0, unit=None):
|
||||
"""
|
||||
This function takes a 'path' and looks for a EDT device at that path.
|
||||
If it finds a EDT device, it will look to see if that device has a
|
||||
register at the give 'index' and return the address value of that reg, if
|
||||
not we return 0.
|
||||
This function takes a 'path' and looks for an EDT node at that path. If it
|
||||
finds an EDT node, it will look to see if that node has a register at the
|
||||
given 'index' and return the address value of that reg, if not we return 0.
|
||||
|
||||
The function will divide the value based on 'unit':
|
||||
None No division
|
||||
|
@ -223,19 +222,18 @@ def dt_node_reg_addr(kconf, _, path, index=0, unit=None):
|
|||
return "0"
|
||||
|
||||
try:
|
||||
dev = edt.get_dev(path)
|
||||
node = edt.get_node(path)
|
||||
except edtlib.EDTError:
|
||||
return "0"
|
||||
|
||||
return _dev_reg_addr(dev, index, unit)
|
||||
return _node_reg_addr(node, index, unit)
|
||||
|
||||
|
||||
def dt_node_reg_size(kconf, _, path, index=0, unit=None):
|
||||
"""
|
||||
This function takes a 'path' and looks for a EDT device at that path.
|
||||
If it finds a EDT device, it will look to see if that device has a
|
||||
register at the give 'index' and return the size value of that reg, if
|
||||
not we return 0.
|
||||
This function takes a 'path' and looks for an EDT node at that path. If it
|
||||
finds an EDT node, it will look to see if that node has a register at the
|
||||
given 'index' and return the size value of that reg, if not we return 0.
|
||||
|
||||
The function will divide the value based on 'unit':
|
||||
None No division
|
||||
|
@ -247,35 +245,35 @@ def dt_node_reg_size(kconf, _, path, index=0, unit=None):
|
|||
return "0"
|
||||
|
||||
try:
|
||||
dev = edt.get_dev(path)
|
||||
node = edt.get_node(path)
|
||||
except edtlib.EDTError:
|
||||
return "0"
|
||||
|
||||
return _dev_reg_size(dev, index, unit)
|
||||
return _node_reg_size(node, index, unit)
|
||||
|
||||
|
||||
def dt_node_has_bool_prop(kconf, _, path, prop):
|
||||
"""
|
||||
This function takes a 'path' and looks for a EDT device at that path.
|
||||
If it finds a EDT device, it will look to see if that device has a
|
||||
boolean property by the name of 'prop'. If the 'prop' exists it will
|
||||
return "y" otherwise we return "n".
|
||||
This function takes a 'path' and looks for an EDT node at that path. If it
|
||||
finds an EDT node, it will look to see if that node has a boolean property
|
||||
by the name of 'prop'. If the 'prop' exists it will return "y" otherwise
|
||||
we return "n".
|
||||
"""
|
||||
if doc_mode or edt is None:
|
||||
return "n"
|
||||
|
||||
try:
|
||||
dev = edt.get_dev(path)
|
||||
node = edt.get_node(path)
|
||||
except edtlib.EDTError:
|
||||
return "n"
|
||||
|
||||
if prop not in dev.props:
|
||||
if prop not in node.props:
|
||||
return "n"
|
||||
|
||||
if dev.props[prop].type != "boolean":
|
||||
if node.props[prop].type != "boolean":
|
||||
return "n"
|
||||
|
||||
if dev.props[prop].val:
|
||||
if node.props[prop].val:
|
||||
return "y"
|
||||
|
||||
return "n"
|
||||
|
@ -284,13 +282,13 @@ def dt_node_has_bool_prop(kconf, _, path, prop):
|
|||
def dt_compat_enabled(kconf, _, compat):
|
||||
"""
|
||||
This function takes a 'compat' and returns "y" if we find an "enabled"
|
||||
compatible device in the EDT otherwise we return "n"
|
||||
compatible node in the EDT otherwise we return "n"
|
||||
"""
|
||||
if doc_mode or edt is None:
|
||||
return "n"
|
||||
|
||||
for dev in edt.devices:
|
||||
if compat in dev.compats and dev.enabled:
|
||||
for node in edt.nodes:
|
||||
if compat in node.compats and node.enabled:
|
||||
return "y"
|
||||
|
||||
return "n"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue