xref: /openbmc/u-boot/tools/rkmux.py (revision 94b13bbae90bfb94204b8fe9c531bc163e746a9f)
1*94b13bbaSMasahiro Yamada#!/usr/bin/env python2
2002c634cSSimon Glass
3002c634cSSimon Glass# Script to create enums from datasheet register tables
4002c634cSSimon Glass#
5002c634cSSimon Glass# Usage:
6002c634cSSimon Glass#
7002c634cSSimon Glass# First, create a text file from the datasheet:
8002c634cSSimon Glass#    pdftotext -layout /path/to/rockchip-3288-trm.pdf /tmp/asc
9002c634cSSimon Glass#
10002c634cSSimon Glass# Then use this script to output the #defines for a particular register:
11002c634cSSimon Glass#    ./tools/rkmux.py GRF_GPIO4C_IOMUX
12002c634cSSimon Glass#
13002c634cSSimon Glass# It will create output suitable for putting in a header file, with SHIFT and
14002c634cSSimon Glass# MASK values for each bitfield in the register.
15002c634cSSimon Glass#
16002c634cSSimon Glass# Note: this tool is not perfect and you may need to edit the resulting code.
17002c634cSSimon Glass# But it should speed up the process.
18002c634cSSimon Glass
19002c634cSSimon Glassimport csv
20002c634cSSimon Glassimport re
21002c634cSSimon Glassimport sys
22002c634cSSimon Glass
23002c634cSSimon Glasstab_to_col = 3
24002c634cSSimon Glass
25002c634cSSimon Glassclass RegField:
26002c634cSSimon Glass    def __init__(self, cols=None):
27002c634cSSimon Glass        if cols:
28002c634cSSimon Glass            self.bits, self.attr, self.reset_val, self.desc = (
29002c634cSSimon Glass                [x.strip() for x in cols])
30002c634cSSimon Glass            self.desc = [self.desc]
31002c634cSSimon Glass        else:
32002c634cSSimon Glass            self.bits = ''
33002c634cSSimon Glass            self.attr = ''
34002c634cSSimon Glass            self.reset_val = ''
35002c634cSSimon Glass            self.desc = []
36002c634cSSimon Glass
37002c634cSSimon Glass    def Setup(self, cols):
38002c634cSSimon Glass        self.bits, self.attr, self.reset_val = cols[0:3]
39002c634cSSimon Glass        if len(cols) > 3:
40002c634cSSimon Glass            self.desc.append(cols[3])
41002c634cSSimon Glass
42002c634cSSimon Glass    def AddDesc(self, desc):
43002c634cSSimon Glass        self.desc.append(desc)
44002c634cSSimon Glass
45002c634cSSimon Glass    def Show(self):
46002c634cSSimon Glass        print self
47002c634cSSimon Glass        print
48002c634cSSimon Glass        self.__init__()
49002c634cSSimon Glass
50002c634cSSimon Glass    def __str__(self):
51002c634cSSimon Glass        return '%s,%s,%s,%s' % (self.bits, self.attr, self.reset_val,
52002c634cSSimon Glass                                '\n'.join(self.desc))
53002c634cSSimon Glass
54002c634cSSimon Glassclass Printer:
55002c634cSSimon Glass    def __init__(self, name):
56002c634cSSimon Glass        self.first = True
57002c634cSSimon Glass        self.name = name
58002c634cSSimon Glass        self.re_sel = re.compile("[1-9]'b([01]+): (.*)")
59002c634cSSimon Glass
60002c634cSSimon Glass    def __enter__(self):
61002c634cSSimon Glass        return self
62002c634cSSimon Glass
63002c634cSSimon Glass    def __exit__(self, type, value, traceback):
64002c634cSSimon Glass        if not self.first:
65002c634cSSimon Glass            self.output_footer()
66002c634cSSimon Glass
67002c634cSSimon Glass    def output_header(self):
68002c634cSSimon Glass        print '/* %s */' % self.name
69002c634cSSimon Glass        print 'enum {'
70002c634cSSimon Glass
71002c634cSSimon Glass    def output_footer(self):
72002c634cSSimon Glass        print '};';
73002c634cSSimon Glass
74002c634cSSimon Glass    def output_regfield(self, regfield):
75002c634cSSimon Glass        lines = regfield.desc
76002c634cSSimon Glass        field = lines[0]
77002c634cSSimon Glass        #print 'field:', field
78002c634cSSimon Glass        if field in ['reserved', 'reserve', 'write_enable', 'write_mask']:
79002c634cSSimon Glass            return
80002c634cSSimon Glass        if field.endswith('_sel') or field.endswith('_con'):
81002c634cSSimon Glass            field = field[:-4]
82002c634cSSimon Glass        elif field.endswith(' iomux'):
83002c634cSSimon Glass            field = field[:-6]
84002c634cSSimon Glass        elif field.endswith('_mode') or field.endswith('_mask'):
85002c634cSSimon Glass            field = field[:-5]
86002c634cSSimon Glass        #else:
87002c634cSSimon Glass            #print 'bad field %s' % field
88002c634cSSimon Glass            #return
89002c634cSSimon Glass        field = field.upper()
90002c634cSSimon Glass        if ':' in regfield.bits:
91002c634cSSimon Glass            bit_high, bit_low = [int(x) for x in regfield.bits.split(':')]
92002c634cSSimon Glass        else:
93002c634cSSimon Glass            bit_high = bit_low = int(regfield.bits)
94002c634cSSimon Glass        bit_width = bit_high - bit_low + 1
95002c634cSSimon Glass        mask = (1 << bit_width) - 1
96002c634cSSimon Glass        if self.first:
97002c634cSSimon Glass            self.first = False
98002c634cSSimon Glass            self.output_header()
99002c634cSSimon Glass        else:
100002c634cSSimon Glass            print
101002c634cSSimon Glass        out_enum(field, 'shift', bit_low)
102002c634cSSimon Glass        out_enum(field, 'mask', mask)
103002c634cSSimon Glass        next_val = -1
104002c634cSSimon Glass        #print 'lines: %s', lines
105002c634cSSimon Glass        for line in lines:
106002c634cSSimon Glass            m = self.re_sel.match(line)
107002c634cSSimon Glass            if m:
108002c634cSSimon Glass                val, enum = int(m.group(1), 2), m.group(2)
109002c634cSSimon Glass                if enum not in ['reserved', 'reserve']:
110002c634cSSimon Glass                    out_enum(field, enum, val, val == next_val)
111002c634cSSimon Glass                    next_val = val + 1
112002c634cSSimon Glass
113002c634cSSimon Glass
114002c634cSSimon Glassdef process_file(name, fd):
115002c634cSSimon Glass    field = RegField()
116002c634cSSimon Glass    reg = ''
117002c634cSSimon Glass
118002c634cSSimon Glass    fields = []
119002c634cSSimon Glass
120002c634cSSimon Glass    def add_it(field):
121002c634cSSimon Glass        if field.bits:
122002c634cSSimon Glass            if reg == name:
123002c634cSSimon Glass                fields.append(field)
124002c634cSSimon Glass            field = RegField()
125002c634cSSimon Glass        return field
126002c634cSSimon Glass
127002c634cSSimon Glass    def is_field_start(line):
128002c634cSSimon Glass       if '=' in line or '+' in line:
129002c634cSSimon Glass           return False
130002c634cSSimon Glass       if (line.startswith('gpio') or line.startswith('peri_') or
131002c634cSSimon Glass                line.endswith('_sel') or line.endswith('_con')):
132002c634cSSimon Glass           return True
133002c634cSSimon Glass       if not ' ' in line: # and '_' in line:
134002c634cSSimon Glass           return True
135002c634cSSimon Glass       return False
136002c634cSSimon Glass
137002c634cSSimon Glass    for line in fd:
138002c634cSSimon Glass        line = line.rstrip()
139002c634cSSimon Glass        if line[:4] in ['GRF_', 'PMU_', 'CRU_']:
140002c634cSSimon Glass            field = add_it(field)
141002c634cSSimon Glass            reg = line
142002c634cSSimon Glass            do_this = name == reg
143002c634cSSimon Glass        elif not line or not line.startswith(' '):
144002c634cSSimon Glass            continue
145002c634cSSimon Glass        line = line.replace('\xe2\x80\x99', "'")
146002c634cSSimon Glass        leading = len(line) - len(line.lstrip())
147002c634cSSimon Glass        line = line.lstrip()
148002c634cSSimon Glass        cols = re.split(' *', line, 3)
149002c634cSSimon Glass        if leading > 15 or (len(cols) > 3 and is_field_start(cols[3])):
150002c634cSSimon Glass            if is_field_start(line):
151002c634cSSimon Glass                field = add_it(field)
152002c634cSSimon Glass            field.AddDesc(line)
153002c634cSSimon Glass        else:
154002c634cSSimon Glass            if cols[0] == 'Bit' or len(cols) < 3:
155002c634cSSimon Glass                continue
156002c634cSSimon Glass            #print
157002c634cSSimon Glass            #print field
158002c634cSSimon Glass            field = add_it(field)
159002c634cSSimon Glass            field.Setup(cols)
160002c634cSSimon Glass    field = add_it(field)
161002c634cSSimon Glass
162002c634cSSimon Glass    with Printer(name) as printer:
163002c634cSSimon Glass        for field in fields:
164002c634cSSimon Glass            #print field
165002c634cSSimon Glass            printer.output_regfield(field)
166002c634cSSimon Glass            #print
167002c634cSSimon Glass
168002c634cSSimon Glassdef out_enum(field, suffix, value, skip_val=False):
169002c634cSSimon Glass    str = '%s_%s' % (field.upper(), suffix.upper())
170002c634cSSimon Glass    if not skip_val:
171002c634cSSimon Glass        tabs = tab_to_col - len(str) / 8
172002c634cSSimon Glass        if value > 9:
173002c634cSSimon Glass            val_str = '%#x' % value
174002c634cSSimon Glass        else:
175002c634cSSimon Glass            val_str = '%d' % value
176002c634cSSimon Glass
177002c634cSSimon Glass        str += '%s= %s' % ('\t' * tabs, val_str)
178002c634cSSimon Glass    print '\t%s,' % str
179002c634cSSimon Glass
180002c634cSSimon Glass# Process a CSV file, e.g. from tabula
181002c634cSSimon Glassdef process_csv(name, fd):
182002c634cSSimon Glass    reader = csv.reader(fd)
183002c634cSSimon Glass
184002c634cSSimon Glass    rows = []
185002c634cSSimon Glass
186002c634cSSimon Glass    field = RegField()
187002c634cSSimon Glass    for row in reader:
188002c634cSSimon Glass        #print field.desc
189002c634cSSimon Glass        if not row[0]:
190002c634cSSimon Glass            field.desc.append(row[3])
191002c634cSSimon Glass            continue
192002c634cSSimon Glass        if field.bits:
193002c634cSSimon Glass            if field.bits != 'Bit':
194002c634cSSimon Glass                rows.append(field)
195002c634cSSimon Glass        #print row
196002c634cSSimon Glass        field = RegField(row)
197002c634cSSimon Glass
198002c634cSSimon Glass    with Printer(name) as printer:
199002c634cSSimon Glass        for row in rows:
200002c634cSSimon Glass            #print field
201002c634cSSimon Glass            printer.output_regfield(row)
202002c634cSSimon Glass            #print
203002c634cSSimon Glass
204002c634cSSimon Glassfname = sys.argv[1]
205002c634cSSimon Glassname = sys.argv[2]
206002c634cSSimon Glass
207002c634cSSimon Glass# Read output from pdftotext -layout
208002c634cSSimon Glassif 1:
209002c634cSSimon Glass    with open(fname, 'r') as fd:
210002c634cSSimon Glass        process_file(name, fd)
211002c634cSSimon Glass
212002c634cSSimon Glass# Use tabula
213002c634cSSimon Glass# It seems to be better at outputting text for an entire cell in one cell.
214002c634cSSimon Glass# But it does not always work. E.g. GRF_GPIO7CH_IOMUX.
215002c634cSSimon Glass# So there is no point in using it.
216002c634cSSimon Glassif 0:
217002c634cSSimon Glass    with open(fname, 'r') as fd:
218002c634cSSimon Glass        process_csv(name, fd)
219