2017-12-30 12:06:27 +01:00
|
|
|
#
|
|
|
|
# Copyright (c) 2017 Linaro
|
|
|
|
# Copyright (c) 2017 Bobby Noelte
|
|
|
|
#
|
|
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
#
|
|
|
|
|
2019-02-27 20:31:56 +01:00
|
|
|
import sys
|
|
|
|
|
2018-03-29 17:25:13 +02:00
|
|
|
from collections import defaultdict
|
|
|
|
|
2017-12-30 12:06:27 +01:00
|
|
|
# globals
|
|
|
|
phandles = {}
|
2018-03-29 17:25:13 +02:00
|
|
|
aliases = defaultdict(list)
|
2017-12-30 12:06:27 +01:00
|
|
|
chosen = {}
|
|
|
|
reduced = {}
|
2018-07-04 11:24:07 +02:00
|
|
|
defs = {}
|
2018-12-04 13:30:20 -06:00
|
|
|
bindings = {}
|
2018-12-05 08:58:20 -06:00
|
|
|
bus_bindings = {}
|
2019-02-21 21:34:45 +01:00
|
|
|
binding_compats = []
|
2019-06-07 15:36:57 -05:00
|
|
|
deprecated = []
|
2018-10-31 19:19:54 +01:00
|
|
|
old_alias_names = False
|
2017-12-30 12:06:27 +01:00
|
|
|
|
|
|
|
regs_config = {
|
2018-12-07 10:35:04 -06:00
|
|
|
'zephyr,sram' : 'DT_SRAM',
|
2019-02-08 08:09:47 -06:00
|
|
|
'zephyr,ccm' : 'DT_CCM'
|
2017-12-30 12:06:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
name_config = {
|
2019-02-08 08:32:46 -06:00
|
|
|
'zephyr,console' : 'DT_UART_CONSOLE_ON_DEV_NAME',
|
|
|
|
'zephyr,shell-uart' : 'DT_UART_SHELL_ON_DEV_NAME',
|
|
|
|
'zephyr,bt-uart' : 'DT_BT_UART_ON_DEV_NAME',
|
|
|
|
'zephyr,uart-pipe' : 'DT_UART_PIPE_ON_DEV_NAME',
|
|
|
|
'zephyr,bt-mon-uart' : 'DT_BT_MONITOR_ON_DEV_NAME',
|
|
|
|
'zephyr,uart-mcumgr' : 'DT_UART_MCUMGR_ON_DEV_NAME'
|
2017-12-30 12:06:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-02-07 00:03:00 +01:00
|
|
|
def str_to_label(s):
|
|
|
|
# Change ,-@/ to _ and uppercase
|
|
|
|
return s.replace('-', '_') \
|
|
|
|
.replace(',', '_') \
|
|
|
|
.replace('@', '_') \
|
|
|
|
.replace('/', '_') \
|
|
|
|
.upper()
|
2017-12-30 12:06:27 +01:00
|
|
|
|
|
|
|
|
2019-02-08 23:19:45 +01:00
|
|
|
def all_compats(node):
|
|
|
|
# Returns a set() of all 'compatible' strings that appear at or below
|
|
|
|
# 'node', skipping disabled nodes
|
|
|
|
|
2019-02-08 21:48:18 +01:00
|
|
|
if node['props'].get('status') == 'disabled':
|
2019-02-08 23:19:45 +01:00
|
|
|
return set()
|
2017-12-30 12:06:27 +01:00
|
|
|
|
2019-02-08 23:19:45 +01:00
|
|
|
compats = set()
|
2019-02-08 21:48:18 +01:00
|
|
|
|
|
|
|
if 'compatible' in node['props']:
|
2019-02-08 23:19:45 +01:00
|
|
|
val = node['props']['compatible']
|
|
|
|
if isinstance(val, list):
|
|
|
|
compats.update(val)
|
|
|
|
else:
|
|
|
|
compats.add(val)
|
2017-12-30 12:06:27 +01:00
|
|
|
|
2019-02-08 23:19:45 +01:00
|
|
|
for child_node in node['children'].values():
|
|
|
|
compats.update(all_compats(child_node))
|
2017-12-30 12:06:27 +01:00
|
|
|
|
2019-02-08 23:19:45 +01:00
|
|
|
return compats
|
2017-12-30 12:06:27 +01:00
|
|
|
|
|
|
|
|
2019-02-08 20:25:12 +01:00
|
|
|
def create_aliases(root):
|
2019-02-21 17:57:49 +01:00
|
|
|
if 'aliases' in root['children']:
|
|
|
|
for name, node_path in root['children']['aliases']['props'].items():
|
|
|
|
aliases[node_path].append(name)
|
2017-12-30 12:06:27 +01:00
|
|
|
|
2019-02-20 19:32:15 +01:00
|
|
|
def get_compat(node_path):
|
2019-02-21 19:13:10 +01:00
|
|
|
# Returns the value of the 'compatible' property for the node at
|
|
|
|
# 'node_path'. Also checks the node's parent.
|
|
|
|
#
|
|
|
|
# Returns None if neither the node nor its parent has a 'compatible'
|
|
|
|
# property.
|
2017-12-30 12:06:27 +01:00
|
|
|
|
2019-02-21 19:13:10 +01:00
|
|
|
compat = reduced[node_path]['props'].get('compatible') or \
|
|
|
|
reduced[get_parent_path(node_path)]['props'].get('compatible')
|
2017-12-30 12:06:27 +01:00
|
|
|
|
2019-02-21 19:13:10 +01:00
|
|
|
if isinstance(compat, list):
|
|
|
|
return compat[0]
|
2017-12-30 12:06:27 +01:00
|
|
|
|
|
|
|
return compat
|
|
|
|
|
|
|
|
|
2019-02-08 20:27:24 +01:00
|
|
|
def create_chosen(root):
|
2019-02-21 19:19:35 +01:00
|
|
|
if 'chosen' in root['children']:
|
|
|
|
chosen.update(root['children']['chosen']['props'])
|
2017-12-30 12:06:27 +01:00
|
|
|
|
|
|
|
|
2019-02-08 22:26:51 +01:00
|
|
|
def create_phandles(root, name):
|
2019-02-06 20:26:11 +01:00
|
|
|
if root['props'].get('status') == 'disabled':
|
2017-12-30 12:06:27 +01:00
|
|
|
return
|
|
|
|
|
2019-02-06 20:26:11 +01:00
|
|
|
if 'phandle' in root['props']:
|
|
|
|
phandles[root['props']['phandle']] = name
|
2017-12-30 12:06:27 +01:00
|
|
|
|
|
|
|
if name != '/':
|
|
|
|
name += '/'
|
|
|
|
|
2019-02-08 22:29:33 +01:00
|
|
|
for child_name, child_node in root['children'].items():
|
|
|
|
create_phandles(child_node, name + child_name)
|
2017-12-30 12:06:27 +01:00
|
|
|
|
|
|
|
|
2019-02-20 19:32:15 +01:00
|
|
|
def insert_defs(node_path, new_defs, new_aliases):
|
2019-02-06 18:12:09 +01:00
|
|
|
for key in new_defs:
|
2018-10-23 22:55:49 -05:00
|
|
|
if key.startswith('DT_COMPAT_'):
|
2019-02-20 19:32:15 +01:00
|
|
|
node_path = 'compatibles'
|
2018-09-14 13:33:38 +02:00
|
|
|
|
2019-02-06 18:12:09 +01:00
|
|
|
remove = [k for k in new_aliases if k in new_defs]
|
2019-01-10 14:50:02 -06:00
|
|
|
for k in remove: del new_aliases[k]
|
|
|
|
|
2019-02-20 19:32:15 +01:00
|
|
|
if node_path in defs:
|
|
|
|
remove = [k for k in new_aliases if k in defs[node_path]]
|
2019-01-10 14:50:02 -06:00
|
|
|
for k in remove: del new_aliases[k]
|
2019-02-22 00:38:31 +01:00
|
|
|
defs[node_path]['aliases'].update(new_aliases)
|
2019-02-20 19:32:15 +01:00
|
|
|
defs[node_path].update(new_defs)
|
2017-12-30 12:06:27 +01:00
|
|
|
else:
|
|
|
|
new_defs['aliases'] = new_aliases
|
2019-02-20 19:32:15 +01:00
|
|
|
defs[node_path] = new_defs
|
2017-12-30 12:06:27 +01:00
|
|
|
|
|
|
|
|
2019-02-18 14:03:11 +01:00
|
|
|
# Dictionary where all keys default to 0. Used by create_reduced().
|
|
|
|
last_used_id = defaultdict(int)
|
|
|
|
|
|
|
|
|
|
|
|
def create_reduced(node, path):
|
|
|
|
# Compress nodes list to nodes w/ paths, add interrupt parent
|
|
|
|
|
|
|
|
if node['props'].get('status') == 'disabled':
|
|
|
|
return
|
|
|
|
|
|
|
|
reduced[path] = node.copy()
|
|
|
|
reduced[path].pop('children', None)
|
|
|
|
|
|
|
|
# Assign an instance ID for each compat
|
|
|
|
compat = node['props'].get('compatible')
|
|
|
|
if compat:
|
|
|
|
if type(compat) is not list:
|
|
|
|
compat = [compat]
|
|
|
|
|
|
|
|
reduced[path]['instance_id'] = {}
|
|
|
|
for comp in compat:
|
|
|
|
reduced[path]['instance_id'][comp] = last_used_id[comp]
|
|
|
|
last_used_id[comp] += 1
|
|
|
|
|
|
|
|
# Flatten 'prop = <1 2>, <3 4>' (which turns into nested lists) to
|
|
|
|
# 'prop = <1 2 3 4>'
|
|
|
|
for val in node['props'].values():
|
|
|
|
if isinstance(val, list) and isinstance(val[0], list):
|
|
|
|
# In-place modification
|
|
|
|
val[:] = [item for sublist in val for item in sublist]
|
|
|
|
|
|
|
|
if node['children']:
|
2017-12-30 12:06:27 +01:00
|
|
|
if path != '/':
|
|
|
|
path += '/'
|
2019-02-18 14:03:11 +01:00
|
|
|
|
|
|
|
for child_name, child_node in sorted(node['children'].items()):
|
|
|
|
create_reduced(child_node, path + child_name)
|
2017-12-30 12:06:27 +01:00
|
|
|
|
|
|
|
|
2019-02-27 19:32:08 +01:00
|
|
|
def node_label(node_path):
|
2019-02-20 19:32:15 +01:00
|
|
|
node_compat = get_compat(node_path)
|
2019-02-07 00:03:00 +01:00
|
|
|
def_label = str_to_label(node_compat)
|
2019-02-20 19:32:15 +01:00
|
|
|
if '@' in node_path:
|
2018-09-19 11:12:58 -05:00
|
|
|
# See if we have number we can convert
|
|
|
|
try:
|
2019-02-20 19:32:15 +01:00
|
|
|
unit_addr = int(node_path.split('@')[-1], 16)
|
|
|
|
(nr_addr_cells, nr_size_cells) = get_addr_size_cells(node_path)
|
|
|
|
unit_addr += translate_addr(unit_addr, node_path,
|
2018-09-19 11:12:58 -05:00
|
|
|
nr_addr_cells, nr_size_cells)
|
|
|
|
unit_addr = "%x" % unit_addr
|
|
|
|
except:
|
2019-02-20 19:32:15 +01:00
|
|
|
unit_addr = node_path.split('@')[-1]
|
2019-02-07 00:03:00 +01:00
|
|
|
def_label += '_' + str_to_label(unit_addr)
|
2017-12-30 12:06:27 +01:00
|
|
|
else:
|
2019-02-20 19:32:15 +01:00
|
|
|
def_label += '_' + str_to_label(node_path.split('/')[-1])
|
2017-12-30 12:06:27 +01:00
|
|
|
return def_label
|
2017-12-18 13:54:48 +01:00
|
|
|
|
|
|
|
|
2019-02-20 19:32:15 +01:00
|
|
|
def get_parent_path(node_path):
|
2019-02-27 20:31:56 +01:00
|
|
|
# Turns /foo/bar into /foo. Returns None for /.
|
|
|
|
|
|
|
|
if node_path == '/':
|
|
|
|
return None
|
2019-02-21 19:03:53 +01:00
|
|
|
|
|
|
|
return '/'.join(node_path.split('/')[:-1]) or '/'
|
2018-10-03 18:41:29 -05:00
|
|
|
|
|
|
|
|
2019-02-20 19:32:15 +01:00
|
|
|
def find_parent_prop(node_path, prop):
|
|
|
|
parent_path = get_parent_path(node_path)
|
2018-10-03 18:41:29 -05:00
|
|
|
|
2019-02-20 19:32:15 +01:00
|
|
|
if prop not in reduced[parent_path]['props']:
|
|
|
|
raise Exception("Parent of node " + node_path +
|
2017-12-18 13:54:48 +01:00
|
|
|
" has no " + prop + " property")
|
|
|
|
|
2019-02-20 19:32:15 +01:00
|
|
|
return reduced[parent_path]['props'][prop]
|
2019-02-07 18:02:12 +01:00
|
|
|
|
2018-10-03 16:25:24 -05:00
|
|
|
|
|
|
|
# Get the #{address,size}-cells for a given node
|
2019-02-20 19:32:15 +01:00
|
|
|
def get_addr_size_cells(node_path):
|
|
|
|
parent_addr = get_parent_path(node_path)
|
2018-10-03 16:25:24 -05:00
|
|
|
|
2018-10-03 18:42:30 -05:00
|
|
|
# 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)
|
2018-10-03 16:25:24 -05:00
|
|
|
|
|
|
|
return (nr_addr, nr_size)
|
2018-09-19 11:12:58 -05:00
|
|
|
|
2019-02-20 19:32:15 +01:00
|
|
|
def translate_addr(addr, node_path, nr_addr_cells, nr_size_cells):
|
2019-02-21 20:44:57 +01:00
|
|
|
parent_path = get_parent_path(node_path)
|
2018-09-19 11:12:58 -05:00
|
|
|
|
2019-02-21 20:44:57 +01:00
|
|
|
ranges = reduced[parent_path]['props'].get('ranges')
|
|
|
|
if not ranges:
|
2018-09-19 11:12:58 -05:00
|
|
|
return 0
|
|
|
|
|
2019-02-21 20:44:57 +01:00
|
|
|
if isinstance(ranges, list):
|
|
|
|
ranges = ranges.copy() # Modified in-place below
|
|
|
|
else:
|
|
|
|
# Empty value ('ranges;'), meaning the parent and child address spaces
|
|
|
|
# are the same
|
|
|
|
ranges = []
|
2018-09-19 11:12:58 -05:00
|
|
|
|
2019-02-21 20:44:57 +01:00
|
|
|
nr_p_addr_cells, nr_p_size_cells = get_addr_size_cells(parent_path)
|
2018-09-19 11:12:58 -05:00
|
|
|
|
|
|
|
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,
|
2019-02-20 19:32:15 +01:00
|
|
|
parent_path, nr_p_addr_cells, nr_p_size_cells)
|
2018-09-19 11:12:58 -05:00
|
|
|
range_offset += parent_range_offset
|
|
|
|
|
|
|
|
return range_offset
|
2018-10-31 19:19:54 +01:00
|
|
|
|
|
|
|
def enable_old_alias_names(enable):
|
|
|
|
global old_alias_names
|
|
|
|
old_alias_names = enable
|
|
|
|
|
2019-06-19 12:42:21 -05:00
|
|
|
def add_compat_alias(node_path, label_postfix, label, prop_aliases, deprecate=False):
|
2019-02-20 19:32:15 +01:00
|
|
|
if 'instance_id' in reduced[node_path]:
|
|
|
|
instance = reduced[node_path]['instance_id']
|
2019-01-10 13:31:39 -06:00
|
|
|
for k in instance:
|
|
|
|
i = instance[k]
|
2019-02-07 00:03:00 +01:00
|
|
|
b = 'DT_' + str_to_label(k) + '_' + str(i) + '_' + label_postfix
|
2019-06-07 15:36:57 -05:00
|
|
|
deprecated.append(b)
|
|
|
|
prop_aliases[b] = label
|
|
|
|
b = "DT_INST_{}_{}_{}".format(str(i), str_to_label(k), label_postfix)
|
2019-01-10 13:31:39 -06:00
|
|
|
prop_aliases[b] = label
|
2019-06-19 12:42:21 -05:00
|
|
|
if deprecate:
|
|
|
|
deprecated.append(b)
|
2019-01-10 13:31:39 -06:00
|
|
|
|
2019-02-20 19:32:15 +01:00
|
|
|
def add_prop_aliases(node_path,
|
2019-06-19 12:42:21 -05:00
|
|
|
alias_label_function, prop_label, prop_aliases, deprecate=False):
|
2019-02-20 19:32:15 +01:00
|
|
|
node_compat = get_compat(node_path)
|
2019-06-06 15:10:21 +02:00
|
|
|
new_alias_prefix = 'DT_'
|
2018-10-31 19:19:54 +01:00
|
|
|
|
2019-02-20 19:32:15 +01:00
|
|
|
for alias in aliases[node_path]:
|
2018-10-31 19:19:54 +01:00
|
|
|
old_alias_label = alias_label_function(alias)
|
2019-06-06 15:10:21 +02:00
|
|
|
new_alias_label = new_alias_prefix + 'ALIAS_' + old_alias_label
|
|
|
|
new_alias_compat_label = new_alias_prefix + str_to_label(node_compat) + '_' + old_alias_label
|
2018-10-31 19:19:54 +01:00
|
|
|
|
2019-02-06 21:14:34 +01:00
|
|
|
if new_alias_label != prop_label:
|
2018-10-31 19:19:54 +01:00
|
|
|
prop_aliases[new_alias_label] = prop_label
|
2019-06-19 12:42:21 -05:00
|
|
|
if deprecate:
|
|
|
|
deprecated.append(new_alias_label)
|
2019-06-06 15:10:21 +02:00
|
|
|
if new_alias_compat_label != prop_label:
|
|
|
|
prop_aliases[new_alias_compat_label] = prop_label
|
2019-06-19 12:42:21 -05:00
|
|
|
if deprecate:
|
|
|
|
deprecated.append(new_alias_compat_label)
|
2019-02-06 21:14:34 +01:00
|
|
|
if old_alias_names and old_alias_label != prop_label:
|
2018-10-31 19:19:54 +01:00
|
|
|
prop_aliases[old_alias_label] = prop_label
|
2018-12-04 13:30:20 -06:00
|
|
|
|
2019-02-20 19:32:15 +01:00
|
|
|
def get_binding(node_path):
|
2019-06-21 01:29:57 -05:00
|
|
|
compat = reduced[node_path]['props'].get('compatible')
|
|
|
|
if isinstance(compat, list):
|
|
|
|
compat = compat[0]
|
2018-12-11 09:48:55 -06:00
|
|
|
|
2019-02-20 19:32:15 +01:00
|
|
|
parent_path = get_parent_path(node_path)
|
|
|
|
parent_compat = get_compat(parent_path)
|
2019-06-21 01:29:57 -05:00
|
|
|
|
2019-03-24 20:32:42 +01:00
|
|
|
if parent_compat in bindings:
|
|
|
|
parent_binding = bindings[parent_compat]
|
2019-06-21 01:29:57 -05:00
|
|
|
# see if we're a sub-node
|
|
|
|
if compat is None and 'sub-node' in parent_binding:
|
|
|
|
return parent_binding['sub-node']
|
|
|
|
|
|
|
|
# look for a bus-specific binding
|
2019-03-24 20:32:42 +01:00
|
|
|
if 'child' in parent_binding and 'bus' in parent_binding['child']:
|
|
|
|
bus = parent_binding['child']['bus']
|
|
|
|
return bus_bindings[bus][compat]
|
|
|
|
|
|
|
|
# No bus-specific binding found, look in the main dict.
|
2019-06-21 01:29:57 -05:00
|
|
|
if compat:
|
|
|
|
return bindings[compat]
|
|
|
|
return None
|
2018-12-04 13:30:20 -06:00
|
|
|
|
|
|
|
def get_binding_compats():
|
2019-02-21 21:34:45 +01:00
|
|
|
return binding_compats
|
2019-01-22 14:36:50 -06:00
|
|
|
|
2019-01-25 03:57:28 -06:00
|
|
|
def build_cell_array(prop_array):
|
|
|
|
index = 0
|
|
|
|
ret_array = []
|
|
|
|
|
|
|
|
while index < len(prop_array):
|
|
|
|
handle = prop_array[index]
|
|
|
|
|
|
|
|
if handle in {0, -1}:
|
|
|
|
ret_array.append([])
|
|
|
|
index += 1
|
|
|
|
else:
|
|
|
|
# get controller node (referenced via phandle)
|
|
|
|
cell_parent = phandles[handle]
|
|
|
|
|
|
|
|
for prop in reduced[cell_parent]['props']:
|
|
|
|
if prop[0] == '#' and '-cells' in prop:
|
|
|
|
num_cells = reduced[cell_parent]['props'][prop]
|
|
|
|
break
|
|
|
|
|
|
|
|
ret_array.append(prop_array[index:index+num_cells+1])
|
|
|
|
|
|
|
|
index += num_cells + 1
|
|
|
|
|
|
|
|
return ret_array
|
|
|
|
|
2019-05-07 16:07:58 +02:00
|
|
|
def child_to_parent_unmap(cell_parent, gpio_index):
|
|
|
|
# This function returns a (gpio-controller, pin number) tuple from
|
|
|
|
# cell_parent (identified as a 'nexus node', ie: has a 'gpio-map'
|
|
|
|
# property) and gpio_index.
|
|
|
|
# Note: Nexus nodes and gpio-map property are described in the
|
|
|
|
# upcoming (presumably v0.3) Device Tree specification, chapter
|
|
|
|
# 'Nexus nodes and Specifier Mapping'.
|
|
|
|
|
|
|
|
# First, retrieve gpio-map as a list
|
|
|
|
gpio_map = reduced[cell_parent]['props']['gpio-map']
|
|
|
|
|
|
|
|
# Before parsing, we need to know 'gpio-map' row size
|
|
|
|
# gpio-map raws are encoded as follows:
|
|
|
|
# [child specifier][gpio controller phandle][parent specifier]
|
|
|
|
|
|
|
|
# child specifier field length is connector property #gpio-cells
|
|
|
|
child_specifier_size = reduced[cell_parent]['props']['#gpio-cells']
|
|
|
|
|
|
|
|
# parent specifier field length is parent property #gpio-cells
|
|
|
|
# Assumption 1: We assume parent #gpio-cells is constant across
|
|
|
|
# the map, so we take the value of the first occurrence and apply
|
|
|
|
# to the whole map.
|
|
|
|
parent = phandles[gpio_map[child_specifier_size]]
|
|
|
|
parent_specifier_size = reduced[parent]['props']['#gpio-cells']
|
|
|
|
|
|
|
|
array_cell_size = child_specifier_size + 1 + parent_specifier_size
|
|
|
|
|
|
|
|
# Now that the length of each entry in 'gpio-map' is known,
|
|
|
|
# look for a match with gpio_index
|
|
|
|
for i in range(0, len(gpio_map), array_cell_size):
|
|
|
|
entry = gpio_map[i:i+array_cell_size]
|
|
|
|
|
|
|
|
if entry[0] == gpio_index:
|
|
|
|
parent_controller_phandle = entry[child_specifier_size]
|
|
|
|
# Assumption 2: We assume optional properties 'gpio-map-mask'
|
|
|
|
# and 'gpio-map-pass-thru' are not specified.
|
|
|
|
# So, for now, only the pin number (first value of the parent
|
|
|
|
# specifier field) should be returned.
|
|
|
|
parent_pin_number = entry[child_specifier_size+1]
|
|
|
|
|
|
|
|
# Return gpio_controller and specifier pin
|
|
|
|
return phandles[parent_controller_phandle], parent_pin_number
|
|
|
|
|
|
|
|
# gpio_index did not match any entry in the gpio-map
|
|
|
|
return None, None
|
|
|
|
|
2019-01-25 03:57:28 -06:00
|
|
|
|
2019-02-20 19:32:15 +01:00
|
|
|
def extract_controller(node_path, prop, prop_values, index,
|
2019-01-23 07:22:01 -06:00
|
|
|
def_label, generic, handle_single=False):
|
2019-01-22 14:36:50 -06:00
|
|
|
|
|
|
|
prop_def = {}
|
|
|
|
prop_alias = {}
|
|
|
|
|
2019-01-25 03:57:28 -06:00
|
|
|
prop_array = build_cell_array(prop_values)
|
|
|
|
if handle_single:
|
|
|
|
prop_array = [prop_array[index]]
|
2019-01-22 14:36:50 -06:00
|
|
|
|
2019-01-25 03:57:28 -06:00
|
|
|
for i, elem in enumerate(prop_array):
|
|
|
|
num_cells = len(elem)
|
2019-01-22 14:36:50 -06:00
|
|
|
|
2019-01-25 03:57:28 -06:00
|
|
|
# if the entry is empty, skip
|
|
|
|
if num_cells == 0:
|
|
|
|
continue
|
2019-01-22 14:36:50 -06:00
|
|
|
|
2019-01-25 03:57:28 -06:00
|
|
|
cell_parent = phandles[elem[0]]
|
2019-05-07 16:07:58 +02:00
|
|
|
|
|
|
|
if 'gpio-map' in reduced[cell_parent]['props']:
|
|
|
|
# Parent is a gpio 'nexus node' (ie has gpio-map).
|
|
|
|
# Controller should be found in the map, using elem[1] as index.
|
|
|
|
# Pin attribues (number, flag) will not be used in this function
|
|
|
|
cell_parent, _ = child_to_parent_unmap(cell_parent, elem[1])
|
|
|
|
if cell_parent is None:
|
|
|
|
raise Exception("No parent matching child specifier")
|
|
|
|
|
2019-01-25 03:57:28 -06:00
|
|
|
l_cell = reduced[cell_parent]['props'].get('label')
|
2019-01-22 14:36:50 -06:00
|
|
|
|
2019-01-25 03:57:28 -06:00
|
|
|
if l_cell is None:
|
|
|
|
continue
|
2019-01-22 14:36:50 -06:00
|
|
|
|
2019-02-27 23:54:06 +01:00
|
|
|
l_base = [def_label]
|
2019-01-22 14:36:50 -06:00
|
|
|
|
|
|
|
# Check is defined should be indexed (_0, _1)
|
2019-01-25 03:57:28 -06:00
|
|
|
if handle_single or i == 0 and len(prop_array) == 1:
|
2019-01-22 14:36:50 -06:00
|
|
|
# 0 or 1 element in prop_values
|
|
|
|
l_idx = []
|
|
|
|
else:
|
2019-01-25 03:57:28 -06:00
|
|
|
l_idx = [str(i)]
|
2019-01-22 14:36:50 -06:00
|
|
|
|
|
|
|
# Check node generation requirements
|
|
|
|
try:
|
2019-02-20 19:32:15 +01:00
|
|
|
generation = get_binding(node_path)['properties'
|
2019-01-22 14:36:50 -06:00
|
|
|
][prop]['generation']
|
|
|
|
except:
|
|
|
|
generation = ''
|
|
|
|
|
|
|
|
if 'use-prop-name' in generation:
|
2019-02-07 00:03:00 +01:00
|
|
|
l_cellname = str_to_label(prop + '_' + 'controller')
|
2019-01-22 14:36:50 -06:00
|
|
|
else:
|
2019-02-07 00:03:00 +01:00
|
|
|
l_cellname = str_to_label(generic + '_' + 'controller')
|
2019-01-22 14:36:50 -06:00
|
|
|
|
|
|
|
label = l_base + [l_cellname] + l_idx
|
|
|
|
|
2019-02-20 19:32:15 +01:00
|
|
|
add_compat_alias(node_path, '_'.join(label[1:]), '_'.join(label), prop_alias)
|
2019-01-22 14:36:50 -06:00
|
|
|
prop_def['_'.join(label)] = "\"" + l_cell + "\""
|
|
|
|
|
|
|
|
#generate defs also if node is referenced as an alias in dts
|
2019-02-20 19:32:15 +01:00
|
|
|
if node_path in aliases:
|
2019-01-22 14:36:50 -06:00
|
|
|
add_prop_aliases(
|
2019-02-20 19:32:15 +01:00
|
|
|
node_path,
|
2019-02-07 00:03:00 +01:00
|
|
|
lambda alias: '_'.join([str_to_label(alias)] + label[1:]),
|
2019-01-22 14:36:50 -06:00
|
|
|
'_'.join(label),
|
|
|
|
prop_alias)
|
|
|
|
|
2019-02-20 19:32:15 +01:00
|
|
|
insert_defs(node_path, prop_def, prop_alias)
|
2019-01-22 14:36:50 -06:00
|
|
|
|
|
|
|
|
2019-02-20 19:32:15 +01:00
|
|
|
def extract_cells(node_path, prop, prop_values, names, index,
|
2019-01-23 07:22:01 -06:00
|
|
|
def_label, generic, handle_single=False):
|
2019-01-22 14:36:50 -06:00
|
|
|
|
2019-01-25 03:57:28 -06:00
|
|
|
prop_array = build_cell_array(prop_values)
|
|
|
|
if handle_single:
|
|
|
|
prop_array = [prop_array[index]]
|
2019-01-22 14:36:50 -06:00
|
|
|
|
2019-01-25 03:57:28 -06:00
|
|
|
for i, elem in enumerate(prop_array):
|
|
|
|
num_cells = len(elem)
|
2019-01-22 14:36:50 -06:00
|
|
|
|
2019-01-25 03:57:28 -06:00
|
|
|
# if the entry is empty, skip
|
|
|
|
if num_cells == 0:
|
|
|
|
continue
|
2019-01-22 14:36:50 -06:00
|
|
|
|
2019-01-25 03:57:28 -06:00
|
|
|
cell_parent = phandles[elem[0]]
|
2019-01-22 14:36:50 -06:00
|
|
|
|
2019-05-07 16:07:58 +02:00
|
|
|
if 'gpio-map' in reduced[cell_parent]['props']:
|
|
|
|
# Parent is a gpio connector ie 'nexus node', ie has gpio-map).
|
|
|
|
# Controller and pin number should be found in the connector map,
|
|
|
|
# using elem[1] as index.
|
|
|
|
# Parent pin flag is not used, so child flag(s) value (elem[2:])
|
|
|
|
# is kept as is.
|
|
|
|
cell_parent, elem[1] = child_to_parent_unmap(cell_parent, elem[1])
|
|
|
|
if cell_parent is None:
|
|
|
|
raise Exception("No parent matching child specifier")
|
|
|
|
|
2019-01-25 03:57:28 -06:00
|
|
|
try:
|
|
|
|
cell_yaml = get_binding(cell_parent)
|
|
|
|
except:
|
|
|
|
raise Exception(
|
|
|
|
"Could not find yaml description for " +
|
|
|
|
reduced[cell_parent]['name'])
|
2019-01-22 14:36:50 -06:00
|
|
|
|
2019-01-25 03:57:28 -06:00
|
|
|
try:
|
|
|
|
name = names.pop(0).upper()
|
|
|
|
except:
|
|
|
|
name = ''
|
2019-01-22 14:36:50 -06:00
|
|
|
|
2019-01-25 03:57:28 -06:00
|
|
|
# Get number of cells per element of current property
|
|
|
|
for props in reduced[cell_parent]['props']:
|
|
|
|
if props[0] == '#' and '-cells' in props:
|
2019-02-06 18:12:09 +01:00
|
|
|
if props in cell_yaml:
|
2019-01-25 03:57:28 -06:00
|
|
|
cell_yaml_names = props
|
|
|
|
else:
|
|
|
|
cell_yaml_names = '#cells'
|
|
|
|
try:
|
2019-02-20 19:32:15 +01:00
|
|
|
generation = get_binding(node_path)['properties'][prop
|
2019-01-25 03:57:28 -06:00
|
|
|
]['generation']
|
|
|
|
except:
|
|
|
|
generation = ''
|
2019-01-22 14:36:50 -06:00
|
|
|
|
2019-01-25 03:57:28 -06:00
|
|
|
if 'use-prop-name' in generation:
|
2019-02-07 00:03:00 +01:00
|
|
|
l_cell = [str_to_label(str(prop))]
|
2019-01-25 03:57:28 -06:00
|
|
|
else:
|
2019-02-07 00:03:00 +01:00
|
|
|
l_cell = [str_to_label(str(generic))]
|
2019-01-22 14:36:50 -06:00
|
|
|
|
2019-02-27 23:54:06 +01:00
|
|
|
l_base = [def_label]
|
2019-01-25 03:57:28 -06:00
|
|
|
# Check if #define should be indexed (_0, _1, ...)
|
|
|
|
if handle_single or i == 0 and len(prop_array) == 1:
|
|
|
|
# Less than 2 elements in prop_values
|
|
|
|
# Indexing is not needed
|
|
|
|
l_idx = []
|
|
|
|
else:
|
|
|
|
l_idx = [str(i)]
|
2019-01-22 14:36:50 -06:00
|
|
|
|
2019-01-25 03:57:28 -06:00
|
|
|
prop_def = {}
|
|
|
|
prop_alias = {}
|
2019-01-22 14:36:50 -06:00
|
|
|
|
2019-01-25 03:57:28 -06:00
|
|
|
# Generate label for each field of the property element
|
|
|
|
for j in range(num_cells-1):
|
|
|
|
l_cellname = [str(cell_yaml[cell_yaml_names][j]).upper()]
|
|
|
|
if l_cell == l_cellname:
|
|
|
|
label = l_base + l_cell + l_idx
|
|
|
|
else:
|
|
|
|
label = l_base + l_cell + l_cellname + l_idx
|
|
|
|
label_name = l_base + [name] + l_cellname
|
2019-02-20 19:32:15 +01:00
|
|
|
add_compat_alias(node_path, '_'.join(label[1:]), '_'.join(label), prop_alias)
|
2019-01-25 03:57:28 -06:00
|
|
|
prop_def['_'.join(label)] = elem[j+1]
|
|
|
|
if name:
|
|
|
|
prop_alias['_'.join(label_name)] = '_'.join(label)
|
|
|
|
|
|
|
|
# generate defs for node aliases
|
2019-02-20 19:32:15 +01:00
|
|
|
if node_path in aliases:
|
2019-01-25 03:57:28 -06:00
|
|
|
add_prop_aliases(
|
2019-02-20 19:32:15 +01:00
|
|
|
node_path,
|
2019-02-07 00:03:00 +01:00
|
|
|
lambda alias: '_'.join([str_to_label(alias)] + label[1:]),
|
2019-01-25 03:57:28 -06:00
|
|
|
'_'.join(label),
|
|
|
|
prop_alias)
|
|
|
|
|
2019-02-20 19:32:15 +01:00
|
|
|
insert_defs(node_path, prop_def, prop_alias)
|
2019-02-27 20:31:56 +01:00
|
|
|
|
|
|
|
|
|
|
|
def err(msg):
|
|
|
|
# General error reporting helper. Prints a message to stderr and exits with
|
|
|
|
# status 1.
|
|
|
|
|
|
|
|
sys.exit("error: " + msg)
|