Almost all labels generated by the extracting script are now prefixed with DT_. The only exceptions are: - stuff with 'base_label' specified in yaml bindings - items specified by 'regs_config' and 'name_config' dictionaries in globals.py module - FLASH related labels generated by flash.extract() called separately from generate_node_definitions(), e.g. FLASH_WRITE_BLOCK_SIZE - these are used directly, not through fixups, from existing code so I didn't want to touch them now Labels generated for aliases are additionally prefixed with information from the 'compatible' property, e.g. DT_GPIO_LEDS_LED0_* is generated instead of LED0_*. To provide backward compatibility for code that uses LEDx_* and SWx_* labels in their previous forms, a command line option named 'old-alias-names' is added to the extraction script. This option causes that the labels for aliases are generated in both old and new forms. Currently this option is always enabled in dts.cmake. Signed-off-by: Andrzej Głąbek <andrzej.glabek@nordicsemi.no>
288 lines
7.9 KiB
Python
288 lines
7.9 KiB
Python
#
|
|
# Copyright (c) 2017 Linaro
|
|
# Copyright (c) 2017 Bobby Noelte
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
|
|
from collections import defaultdict
|
|
from copy import deepcopy
|
|
|
|
# globals
|
|
phandles = {}
|
|
aliases = defaultdict(list)
|
|
chosen = {}
|
|
reduced = {}
|
|
defs = {}
|
|
structs = {}
|
|
old_alias_names = False
|
|
|
|
regs_config = {
|
|
'zephyr,flash' : 'CONFIG_FLASH',
|
|
'zephyr,sram' : 'CONFIG_SRAM',
|
|
'zephyr,ccm' : 'CONFIG_CCM'
|
|
}
|
|
|
|
name_config = {
|
|
'zephyr,console' : 'CONFIG_UART_CONSOLE_ON_DEV_NAME',
|
|
'zephyr,bt-uart' : 'CONFIG_BT_UART_ON_DEV_NAME',
|
|
'zephyr,uart-pipe' : 'CONFIG_UART_PIPE_ON_DEV_NAME',
|
|
'zephyr,bt-mon-uart' : 'CONFIG_BT_MONITOR_ON_DEV_NAME',
|
|
'zephyr,uart-mcumgr' : 'CONFIG_UART_MCUMGR_ON_DEV_NAME'
|
|
}
|
|
|
|
|
|
def convert_string_to_label(s):
|
|
# Transmute ,-@/ to _
|
|
s = s.replace("-", "_")
|
|
s = s.replace(",", "_")
|
|
s = s.replace("@", "_")
|
|
s = s.replace("/", "_")
|
|
# Uppercase the string
|
|
s = s.upper()
|
|
return s
|
|
|
|
|
|
def get_all_compatibles(d, name, comp_dict):
|
|
if 'props' in d:
|
|
compat = d['props'].get('compatible')
|
|
enabled = d['props'].get('status')
|
|
|
|
if enabled == "disabled":
|
|
return comp_dict
|
|
|
|
if compat is not None:
|
|
comp_dict[name] = compat
|
|
|
|
if name != '/':
|
|
name += '/'
|
|
|
|
if isinstance(d, dict):
|
|
if d['children']:
|
|
for k, v in d['children'].items():
|
|
get_all_compatibles(v, name + k, comp_dict)
|
|
|
|
return comp_dict
|
|
|
|
|
|
def get_aliases(root):
|
|
if 'children' in root:
|
|
if 'aliases' in root['children']:
|
|
for k, v in root['children']['aliases']['props'].items():
|
|
aliases[v].append(k)
|
|
|
|
# Treat alternate names as aliases
|
|
for k in reduced.keys():
|
|
if reduced[k].get('alt_name', None) is not None:
|
|
aliases[k].append(reduced[k]['alt_name'])
|
|
|
|
def get_node_compats(node_address):
|
|
compat = None
|
|
|
|
try:
|
|
if 'props' in reduced[node_address].keys():
|
|
compat = reduced[node_address]['props'].get('compatible')
|
|
|
|
if not isinstance(compat, list):
|
|
compat = [compat, ]
|
|
|
|
except:
|
|
pass
|
|
|
|
return compat
|
|
|
|
def get_compat(node_address):
|
|
compat = None
|
|
|
|
try:
|
|
if 'props' in reduced[node_address].keys():
|
|
compat = reduced[node_address]['props'].get('compatible')
|
|
|
|
if compat == None:
|
|
compat = find_parent_prop(node_address, 'compatible')
|
|
|
|
if isinstance(compat, list):
|
|
compat = compat[0]
|
|
|
|
except:
|
|
pass
|
|
|
|
return compat
|
|
|
|
|
|
def get_chosen(root):
|
|
if 'children' in root:
|
|
if 'chosen' in root['children']:
|
|
for k, v in root['children']['chosen']['props'].items():
|
|
chosen[k] = v
|
|
|
|
|
|
def get_phandles(root, name, handles):
|
|
if 'props' in root:
|
|
handle = root['props'].get('phandle')
|
|
enabled = root['props'].get('status')
|
|
|
|
if enabled == "disabled":
|
|
return
|
|
|
|
if handle is not None:
|
|
phandles[handle] = name
|
|
|
|
if name != '/':
|
|
name += '/'
|
|
|
|
if isinstance(root, dict):
|
|
if root['children']:
|
|
for k, v in root['children'].items():
|
|
get_phandles(v, name + k, handles)
|
|
|
|
|
|
def insert_defs(node_address, new_defs, new_aliases):
|
|
|
|
for key in new_defs.keys():
|
|
if key.startswith('DT_COMPAT_'):
|
|
node_address = 'compatibles'
|
|
|
|
if node_address in defs:
|
|
if 'aliases' in defs[node_address]:
|
|
defs[node_address]['aliases'].update(new_aliases)
|
|
else:
|
|
defs[node_address]['aliases'] = new_aliases
|
|
|
|
defs[node_address].update(new_defs)
|
|
else:
|
|
new_defs['aliases'] = new_aliases
|
|
defs[node_address] = new_defs
|
|
|
|
|
|
def find_node_by_path(nodes, path):
|
|
d = nodes
|
|
for k in path[1:].split('/'):
|
|
d = d['children'][k]
|
|
|
|
return d
|
|
|
|
|
|
def get_reduced(nodes, path):
|
|
# compress nodes list to nodes w/ paths, add interrupt parent
|
|
if 'props' in nodes:
|
|
status = nodes['props'].get('status')
|
|
|
|
if status == "disabled":
|
|
return
|
|
|
|
if isinstance(nodes, dict):
|
|
reduced[path] = dict(nodes)
|
|
reduced[path].pop('children', None)
|
|
if path != '/':
|
|
path += '/'
|
|
if nodes['children']:
|
|
for k, v in nodes['children'].items():
|
|
get_reduced(v, path + k)
|
|
|
|
|
|
def get_node_label(node_address):
|
|
node_compat = get_compat(node_address)
|
|
def_label = convert_string_to_label(node_compat)
|
|
if '@' in node_address:
|
|
# See if we have number we can convert
|
|
try:
|
|
unit_addr = int(node_address.split('@')[-1], 16)
|
|
(nr_addr_cells, nr_size_cells) = get_addr_size_cells(node_address)
|
|
unit_addr += translate_addr(unit_addr, node_address,
|
|
nr_addr_cells, nr_size_cells)
|
|
unit_addr = "%x" % unit_addr
|
|
except:
|
|
unit_addr = node_address.split('@')[-1]
|
|
def_label += '_' + convert_string_to_label(unit_addr)
|
|
else:
|
|
def_label += '_' + \
|
|
convert_string_to_label(node_address.split('/')[-1])
|
|
return def_label
|
|
|
|
def get_parent_address(node_address):
|
|
parent_address = ''
|
|
|
|
for comp in node_address.split('/')[1:-1]:
|
|
parent_address += '/' + comp
|
|
|
|
return parent_address
|
|
|
|
|
|
def find_parent_prop(node_address, prop):
|
|
parent_address = get_parent_address(node_address)
|
|
|
|
if prop in reduced[parent_address]['props']:
|
|
parent_prop = reduced[parent_address]['props'].get(prop)
|
|
else:
|
|
raise Exception("Parent of node " + node_address +
|
|
" has no " + prop + " property")
|
|
|
|
return parent_prop
|
|
|
|
# Get the #{address,size}-cells for a given node
|
|
def get_addr_size_cells(node_address):
|
|
parent_addr = get_parent_address(node_address)
|
|
if parent_addr == '':
|
|
parent_addr = '/'
|
|
|
|
# The DT spec says that if #address-cells is missing default to 2
|
|
# if #size-cells is missing default to 1
|
|
nr_addr = reduced[parent_addr]['props'].get('#address-cells', 2)
|
|
nr_size = reduced[parent_addr]['props'].get('#size-cells', 1)
|
|
|
|
return (nr_addr, nr_size)
|
|
|
|
def translate_addr(addr, node_address, nr_addr_cells, nr_size_cells):
|
|
|
|
try:
|
|
ranges = deepcopy(find_parent_prop(node_address, 'ranges'))
|
|
if type(ranges) is not list: ranges = [ ]
|
|
except:
|
|
return 0
|
|
|
|
parent_address = get_parent_address(node_address)
|
|
|
|
(nr_p_addr_cells, nr_p_size_cells) = get_addr_size_cells(parent_address)
|
|
|
|
range_offset = 0
|
|
while ranges:
|
|
child_bus_addr = 0
|
|
parent_bus_addr = 0
|
|
range_len = 0
|
|
for x in range(nr_addr_cells):
|
|
val = ranges.pop(0) << (32 * (nr_addr_cells - x - 1))
|
|
child_bus_addr += val
|
|
for x in range(nr_p_addr_cells):
|
|
val = ranges.pop(0) << (32 * (nr_p_addr_cells - x - 1))
|
|
parent_bus_addr += val
|
|
for x in range(nr_size_cells):
|
|
range_len += ranges.pop(0) << (32 * (nr_size_cells - x - 1))
|
|
# if we are outside of the range we don't need to translate
|
|
if child_bus_addr <= addr <= (child_bus_addr + range_len):
|
|
range_offset = parent_bus_addr - child_bus_addr
|
|
break
|
|
|
|
parent_range_offset = translate_addr(addr + range_offset,
|
|
parent_address, nr_p_addr_cells, nr_p_size_cells)
|
|
range_offset += parent_range_offset
|
|
|
|
return range_offset
|
|
|
|
def enable_old_alias_names(enable):
|
|
global old_alias_names
|
|
old_alias_names = enable
|
|
|
|
def add_prop_aliases(node_address, yaml,
|
|
alias_label_function, prop_label, prop_aliases):
|
|
node_compat = get_compat(node_address)
|
|
new_alias_prefix = 'DT_' + convert_string_to_label(node_compat)
|
|
|
|
for alias in aliases[node_address]:
|
|
old_alias_label = alias_label_function(alias)
|
|
new_alias_label = new_alias_prefix + '_' + old_alias_label
|
|
|
|
if (new_alias_label != prop_label):
|
|
prop_aliases[new_alias_label] = prop_label
|
|
if (old_alias_names and old_alias_label != prop_label):
|
|
prop_aliases[old_alias_label] = prop_label
|