Skip to content

Commit b9d8f2b

Browse files
galakdanieldegrasse
authored andcommitted
mcux: Add script that will convert MCUX signal xml to devicetree
Signed-off-by: Kumar Gala <[email protected]>
1 parent da6c141 commit b9d8f2b

File tree

1 file changed

+183
-0
lines changed

1 file changed

+183
-0
lines changed

mcux/scripts/kinetis_signal2dts.py

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Copyright (c) 2021, Linaro Limited.
4+
#
5+
# SPDX-License-Identifier: Apache-2.0
6+
7+
import xml.etree.ElementTree as ET
8+
import re
9+
import os
10+
import sys
11+
import collections
12+
import logging
13+
14+
# layout/index of pins tuple
15+
PIN = collections.namedtuple('PIN', ['PERIPH', 'NAME_PART', 'SIGNAL', 'PORT',
16+
'PIN', 'CH', 'MUX_FUNC'])
17+
18+
19+
def parse_signal_xml(signal_fn):
20+
signal_tree = ET.parse(signal_fn)
21+
signal_root = signal_tree.getroot()
22+
23+
pins = []
24+
25+
partNum = signal_root.find("./part_information/part_number").get('id')
26+
27+
print(f"################## {partNum} ###########")
28+
29+
periphs_node = signal_root.find("peripherals")
30+
periphs = []
31+
for p in periphs_node:
32+
id = p.attrib.get("id")
33+
name = p.attrib.get("name")
34+
35+
if id != name:
36+
logging.warn("id and name don't match")
37+
38+
periphs.append(id)
39+
40+
pins_node = signal_root.find("pins")
41+
for p in pins_node:
42+
name = p.attrib.get("name")
43+
44+
# Kinetis family uses PT[A-Z][0-31]
45+
if "PT" in name:
46+
logging.debug(name)
47+
48+
num_conns = 0
49+
50+
for conns in p.findall("connections"):
51+
num_conns += 1
52+
logging.debug(f"\t{num_conns} - {conns.tag} {conns.attrib}")
53+
name_part = conns.attrib.get("name_part")
54+
# func = conns.attrib.get("package_function")
55+
56+
conns_tree = ET.ElementTree(conns)
57+
periph = None
58+
59+
num_periph_sig = 0
60+
61+
for c in conns_tree.iter('peripheral_signal_ref'):
62+
num_periph_sig += 1
63+
logging.debug(f"\t\t{num_periph_sig} - {c.tag} {c.attrib}")
64+
signal = c.attrib.get("signal")
65+
periph = c.attrib.get("peripheral")
66+
ch = c.attrib.get("channel")
67+
68+
if num_periph_sig > 1:
69+
logging.error(num_periph_sig)
70+
71+
# handle unrouted_pin_function_ref case (disabled pin)
72+
if periph is None:
73+
continue
74+
75+
pin = None
76+
77+
for c in conns_tree.iter('assign'):
78+
logging.debug(f"\t\t\t[ASSIGN] {c.tag} {c.attrib}")
79+
reg = c.attrib.get("register")
80+
reg_match = re.search(r"PORT([A-Z])_PCR(\d+)", reg)
81+
82+
# Only process PCR registers
83+
if reg_match:
84+
port = reg_match.group(1).lower()
85+
if len(reg_match.groups()) == 2:
86+
pin = reg_match.group(2).lower()
87+
else:
88+
pin = None
89+
else:
90+
continue
91+
92+
logging.debug(c.attrib)
93+
94+
val = c.attrib.get("bit_field_value")
95+
96+
pin_data = PIN(PERIPH=periph,
97+
NAME_PART=name_part,
98+
SIGNAL=signal,
99+
PORT=port,
100+
PIN=int(pin),
101+
CH=ch,
102+
MUX_FUNC=int(val, 16))
103+
logging.debug(pin_data)
104+
pins.append(pin_data)
105+
106+
return (partNum, pins)
107+
108+
109+
def write_pins(whichPort, pins, f):
110+
port_pins = list(filter(lambda p: (p.PORT.lower() == whichPort), pins))
111+
112+
if (len(port_pins)) == 0:
113+
return
114+
115+
port_pins.sort(key=lambda p: (p.PIN, p.MUX_FUNC))
116+
117+
seen_nodes = []
118+
119+
f.write(f"&port{whichPort} {{\n")
120+
for pin_data in port_pins:
121+
port_name = f"PT{pin_data.PORT.upper()}{pin_data.PIN}"
122+
# Special case handle GPIO so that it will be of the form:
123+
# PT[A-E][0-31]: GPIO[A-E]_PT[A-E][0-31]: ...
124+
#
125+
# eg:
126+
# PTA3: GPIOA_PTA3: gpioa_pta3 { .... };
127+
if pin_data.PERIPH.startswith("GPIO"):
128+
node = f"{pin_data.PERIPH.lower()}_{port_name.lower()}"
129+
label = f"{port_name}: {node.upper()}"
130+
else:
131+
label = f"{pin_data.NAME_PART}_{port_name}"
132+
node = label.lower()
133+
k_port_pins_prop = f"< {pin_data.PIN} {pin_data.MUX_FUNC} >"
134+
135+
if node in seen_nodes:
136+
continue
137+
else:
138+
seen_nodes.append(node)
139+
140+
f.write(f"\t{label}: {node} {{\n")
141+
f.write("\t\t/* < PIN PCR[MUX] > */\n")
142+
f.write(f"\t\tnxp,kinetis-port-pins = {k_port_pins_prop};\n")
143+
f.write("\t};\n")
144+
145+
f.write("};\n")
146+
f.write("\n")
147+
148+
149+
def process_signal_xml(filename):
150+
(partNum, pins) = parse_signal_xml(filename)
151+
152+
pcr_pins = list(filter(lambda p: (p.PERIPH not in ["FB", "EZPORT"]), pins))
153+
154+
with open(partNum + "-pinctrl.dtsi", "w", encoding="utf-8") as f:
155+
f.write("/*\n")
156+
f.write(" * NOTE: Autogenerated file by kinetis_signal2dts.py\n")
157+
f.write(f" * for {partNum}/signal_configuration.xml\n")
158+
f.write(" *\n")
159+
f.write(" * SPDX-License-Identifier: Apache-2.0\n")
160+
f.write(" */\n")
161+
f.write("\n")
162+
163+
write_pins('a', pcr_pins, f)
164+
write_pins('b', pcr_pins, f)
165+
write_pins('c', pcr_pins, f)
166+
write_pins('d', pcr_pins, f)
167+
write_pins('e', pcr_pins, f)
168+
169+
170+
logger = logging.getLogger('')
171+
172+
processor = None
173+
if len(sys.argv) > 1:
174+
processor = sys.argv[1]
175+
176+
signal_xml_fn = "signal_configuration.xml"
177+
178+
for root, dirs, files in os.walk("."):
179+
if signal_xml_fn in files:
180+
if processor and processor not in root:
181+
continue
182+
print(os.path.join(root, signal_xml_fn))
183+
process_signal_xml(os.path.join(root, signal_xml_fn))

0 commit comments

Comments
 (0)