1#!/usr/bin/env python3
2
3import argparse
4import tempfile
5import re
6import os
7
8HELPSTR = """
9Fix generated pinctrl defintions
10Generated RT11xx pinctrl definitions will be incorrect, because the signal
11configuration XML file itself is not correct. Fix them using fsl_iomuxc
12definitions.
13"""
14
15
16parser = argparse.ArgumentParser(description=HELPSTR,
17        formatter_class=argparse.RawDescriptionHelpFormatter)
18parser.add_argument('iomuxc_file', metavar = 'IOMUXC',
19                    type=str,
20                    help='iomuxc file to use as ground truth')
21parser.add_argument('pinctrl_file', metavar = 'pinctrl',
22                    type=str,
23                    help='pinctrl file to check against iomuxc file')
24parser.add_argument('--check', action='store_true',
25                    help='do not edit pinctrl file, just check for errors')
26
27args = parser.parse_args()
28
29try:
30    iomux_file = open(args.iomuxc_file, 'r', encoding='utf8')
31except IOError:
32    print(f"Could not open {args.iomuxc_file}")
33try:
34    pinctrl_file = open(args.pinctrl_file, 'r+', encoding='utf8')
35except IOError:
36    print(f"Could not open {args.pinctrl_file}")
37
38iomuxc_re = re.compile(r'#define (IOMUXC_[\w_]+)\s+([0x]*[\dA-F]+)[U]*, ([0x]*[\dA-F]+)[U]*,'
39    r' ([0x]*[\dA-F]+)[U]*, ([0x]*[\dA-F]+)[U]*, ([0x]*[\dA-F]+)[U]*\n')
40
41pinctrl_line1_re = re.compile(r'\t/omit-if-no-ref/ [\w_]+: ([\w_]+) {\n')
42pinctrl_line2_re = re.compile(r'\t\tpinmux = <(0x[\da-f]+) '
43    r'(\d+) (0x[\da-f]+) (\d+) (0x[\da-f]+)>;')
44
45ground_truth = {}
46while True:
47    line = iomux_file.readline()
48    if line == '':
49        break
50    match = iomuxc_re.match(line)
51    if match:
52        mux_reg = int(match.group(2), 0)
53        mux = int(match.group(3), 0)
54        daisy_reg = int(match.group(4), 0)
55        daisy = int(match.group(5), 0)
56        cfg_reg = int(match.group(6), 0)
57        if (mux_reg, mux, cfg_reg) in ground_truth:
58            raise RuntimeError("Duplicate mux_reg and mux value pairings")
59        ground_truth[(mux_reg, mux)] = (match.group(1), daisy_reg, daisy, cfg_reg)
60
61if not args.check:
62    tmp = tempfile.TemporaryFile(mode='r+')
63while True:
64    line = pinctrl_file.readline()
65    if line == '':
66        break
67    if not args.check:
68        if line == '&iomuxc {\n':
69            # Write a comment before dts defintions
70            tmp.write('/*\n'
71                f' * NOTE: file fixup performed by {os.path.basename(__file__)}\n'
72                " * to correct missing daisy register values\n"
73                ' */\n\n')
74        # Write back untouched line
75        tmp.write(line)
76    match = pinctrl_line1_re.match(line)
77    if match:
78        line = pinctrl_file.readline()
79        match2 = pinctrl_line2_re.match(line)
80        if match2:
81            mux_reg = int(match2.group(1), 0)
82            mux = int(match2.group(2), 0)
83            daisy_reg = int(match2.group(3), 0)
84            daisy = int(match2.group(4), 0)
85            cfg_reg = int(match2.group(5), 0)
86            name = match.group(1)
87            errors = False
88            if (mux_reg, mux) in ground_truth:
89                mux_truth = ground_truth[(mux_reg, mux)]
90                # Get the MUX daisy values
91                if mux_truth[1] != daisy_reg:
92                    print(f"Bad daisy reg on {name}")
93                    errors = True
94                if mux_truth[2] != daisy:
95                    print(f"Bad daisy value on {name}")
96                    errors = True
97                if mux_truth[3] != cfg_reg:
98                    print(f"Bad cfg value on {name}")
99                    errors = True
100                if (not args.check) and (errors):
101                    # Fix up file
102                    new_line = (f"\t\tpinmux = <0x{mux_reg:x} {mux} "
103                        f"0x{mux_truth[1]:x} {mux_truth[2]} 0x{mux_truth[3]:x}>;\n")
104                    tmp.write(new_line)
105                elif not args.check:
106                    # Write back untouched line
107                    tmp.write(line)
108            else:
109                print("WARNING: Mux name %s not preset in ground truth" % (name))
110                if not args.check:
111                    # Write back untouched line
112                    tmp.write(line)
113if not args.check:
114    # Commit operation by writing temp file to real file
115    tmp.seek(0)
116    pinctrl_file.seek(0)
117    while True:
118        tmpline = tmp.readline()
119        if tmpline == '':
120            break
121        pinctrl_file.write(tmpline)
122
123iomux_file.close()
124pinctrl_file.close()
125if not args.check:
126    tmp.close()
127