xref: /OK3568_Linux_fs/u-boot/tools/rkmux.py (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#!/usr/bin/env python2
2*4882a593Smuzhiyun
3*4882a593Smuzhiyun# Script to create enums from datasheet register tables
4*4882a593Smuzhiyun#
5*4882a593Smuzhiyun# Usage:
6*4882a593Smuzhiyun#
7*4882a593Smuzhiyun# First, create a text file from the datasheet:
8*4882a593Smuzhiyun#    pdftotext -layout /path/to/rockchip-3288-trm.pdf /tmp/asc
9*4882a593Smuzhiyun#
10*4882a593Smuzhiyun# Then use this script to output the #defines for a particular register:
11*4882a593Smuzhiyun#    ./tools/rkmux.py GRF_GPIO4C_IOMUX
12*4882a593Smuzhiyun#
13*4882a593Smuzhiyun# It will create output suitable for putting in a header file, with SHIFT and
14*4882a593Smuzhiyun# MASK values for each bitfield in the register.
15*4882a593Smuzhiyun#
16*4882a593Smuzhiyun# Note: this tool is not perfect and you may need to edit the resulting code.
17*4882a593Smuzhiyun# But it should speed up the process.
18*4882a593Smuzhiyun
19*4882a593Smuzhiyunimport csv
20*4882a593Smuzhiyunimport re
21*4882a593Smuzhiyunimport sys
22*4882a593Smuzhiyun
23*4882a593Smuzhiyuntab_to_col = 3
24*4882a593Smuzhiyun
25*4882a593Smuzhiyunclass RegField:
26*4882a593Smuzhiyun    def __init__(self, cols=None):
27*4882a593Smuzhiyun        if cols:
28*4882a593Smuzhiyun            self.bits, self.attr, self.reset_val, self.desc = (
29*4882a593Smuzhiyun                [x.strip() for x in cols])
30*4882a593Smuzhiyun            self.desc = [self.desc]
31*4882a593Smuzhiyun        else:
32*4882a593Smuzhiyun            self.bits = ''
33*4882a593Smuzhiyun            self.attr = ''
34*4882a593Smuzhiyun            self.reset_val = ''
35*4882a593Smuzhiyun            self.desc = []
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun    def Setup(self, cols):
38*4882a593Smuzhiyun        self.bits, self.attr, self.reset_val = cols[0:3]
39*4882a593Smuzhiyun        if len(cols) > 3:
40*4882a593Smuzhiyun            self.desc.append(cols[3])
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun    def AddDesc(self, desc):
43*4882a593Smuzhiyun        self.desc.append(desc)
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun    def Show(self):
46*4882a593Smuzhiyun        print self
47*4882a593Smuzhiyun        print
48*4882a593Smuzhiyun        self.__init__()
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun    def __str__(self):
51*4882a593Smuzhiyun        return '%s,%s,%s,%s' % (self.bits, self.attr, self.reset_val,
52*4882a593Smuzhiyun                                '\n'.join(self.desc))
53*4882a593Smuzhiyun
54*4882a593Smuzhiyunclass Printer:
55*4882a593Smuzhiyun    def __init__(self, name):
56*4882a593Smuzhiyun        self.first = True
57*4882a593Smuzhiyun        self.name = name
58*4882a593Smuzhiyun        self.re_sel = re.compile("[1-9]'b([01]+): (.*)")
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun    def __enter__(self):
61*4882a593Smuzhiyun        return self
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun    def __exit__(self, type, value, traceback):
64*4882a593Smuzhiyun        if not self.first:
65*4882a593Smuzhiyun            self.output_footer()
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun    def output_header(self):
68*4882a593Smuzhiyun        print '/* %s */' % self.name
69*4882a593Smuzhiyun        print 'enum {'
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun    def output_footer(self):
72*4882a593Smuzhiyun        print '};';
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun    def output_regfield(self, regfield):
75*4882a593Smuzhiyun        lines = regfield.desc
76*4882a593Smuzhiyun        field = lines[0]
77*4882a593Smuzhiyun        #print 'field:', field
78*4882a593Smuzhiyun        if field in ['reserved', 'reserve', 'write_enable', 'write_mask']:
79*4882a593Smuzhiyun            return
80*4882a593Smuzhiyun        if field.endswith('_sel') or field.endswith('_con'):
81*4882a593Smuzhiyun            field = field[:-4]
82*4882a593Smuzhiyun        elif field.endswith(' iomux'):
83*4882a593Smuzhiyun            field = field[:-6]
84*4882a593Smuzhiyun        elif field.endswith('_mode') or field.endswith('_mask'):
85*4882a593Smuzhiyun            field = field[:-5]
86*4882a593Smuzhiyun        #else:
87*4882a593Smuzhiyun            #print 'bad field %s' % field
88*4882a593Smuzhiyun            #return
89*4882a593Smuzhiyun        field = field.upper()
90*4882a593Smuzhiyun        if ':' in regfield.bits:
91*4882a593Smuzhiyun            bit_high, bit_low = [int(x) for x in regfield.bits.split(':')]
92*4882a593Smuzhiyun        else:
93*4882a593Smuzhiyun            bit_high = bit_low = int(regfield.bits)
94*4882a593Smuzhiyun        bit_width = bit_high - bit_low + 1
95*4882a593Smuzhiyun        mask = (1 << bit_width) - 1
96*4882a593Smuzhiyun        if self.first:
97*4882a593Smuzhiyun            self.first = False
98*4882a593Smuzhiyun            self.output_header()
99*4882a593Smuzhiyun        else:
100*4882a593Smuzhiyun            print
101*4882a593Smuzhiyun        out_enum(field, 'shift', bit_low)
102*4882a593Smuzhiyun        out_enum(field, 'mask', mask)
103*4882a593Smuzhiyun        next_val = -1
104*4882a593Smuzhiyun        #print 'lines: %s', lines
105*4882a593Smuzhiyun        for line in lines:
106*4882a593Smuzhiyun            m = self.re_sel.match(line)
107*4882a593Smuzhiyun            if m:
108*4882a593Smuzhiyun                val, enum = int(m.group(1), 2), m.group(2)
109*4882a593Smuzhiyun                if enum not in ['reserved', 'reserve']:
110*4882a593Smuzhiyun                    out_enum(field, enum, val, val == next_val)
111*4882a593Smuzhiyun                    next_val = val + 1
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun
114*4882a593Smuzhiyundef process_file(name, fd):
115*4882a593Smuzhiyun    field = RegField()
116*4882a593Smuzhiyun    reg = ''
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun    fields = []
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun    def add_it(field):
121*4882a593Smuzhiyun        if field.bits:
122*4882a593Smuzhiyun            if reg == name:
123*4882a593Smuzhiyun                fields.append(field)
124*4882a593Smuzhiyun            field = RegField()
125*4882a593Smuzhiyun        return field
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun    def is_field_start(line):
128*4882a593Smuzhiyun       if '=' in line or '+' in line:
129*4882a593Smuzhiyun           return False
130*4882a593Smuzhiyun       if (line.startswith('gpio') or line.startswith('peri_') or
131*4882a593Smuzhiyun                line.endswith('_sel') or line.endswith('_con')):
132*4882a593Smuzhiyun           return True
133*4882a593Smuzhiyun       if not ' ' in line: # and '_' in line:
134*4882a593Smuzhiyun           return True
135*4882a593Smuzhiyun       return False
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun    for line in fd:
138*4882a593Smuzhiyun        line = line.rstrip()
139*4882a593Smuzhiyun        if line[:4] in ['GRF_', 'PMU_', 'CRU_']:
140*4882a593Smuzhiyun            field = add_it(field)
141*4882a593Smuzhiyun            reg = line
142*4882a593Smuzhiyun            do_this = name == reg
143*4882a593Smuzhiyun        elif not line or not line.startswith(' '):
144*4882a593Smuzhiyun            continue
145*4882a593Smuzhiyun        line = line.replace('\xe2\x80\x99', "'")
146*4882a593Smuzhiyun        leading = len(line) - len(line.lstrip())
147*4882a593Smuzhiyun        line = line.lstrip()
148*4882a593Smuzhiyun        cols = re.split(' *', line, 3)
149*4882a593Smuzhiyun        if leading > 15 or (len(cols) > 3 and is_field_start(cols[3])):
150*4882a593Smuzhiyun            if is_field_start(line):
151*4882a593Smuzhiyun                field = add_it(field)
152*4882a593Smuzhiyun            field.AddDesc(line)
153*4882a593Smuzhiyun        else:
154*4882a593Smuzhiyun            if cols[0] == 'Bit' or len(cols) < 3:
155*4882a593Smuzhiyun                continue
156*4882a593Smuzhiyun            #print
157*4882a593Smuzhiyun            #print field
158*4882a593Smuzhiyun            field = add_it(field)
159*4882a593Smuzhiyun            field.Setup(cols)
160*4882a593Smuzhiyun    field = add_it(field)
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun    with Printer(name) as printer:
163*4882a593Smuzhiyun        for field in fields:
164*4882a593Smuzhiyun            #print field
165*4882a593Smuzhiyun            printer.output_regfield(field)
166*4882a593Smuzhiyun            #print
167*4882a593Smuzhiyun
168*4882a593Smuzhiyundef out_enum(field, suffix, value, skip_val=False):
169*4882a593Smuzhiyun    str = '%s_%s' % (field.upper(), suffix.upper())
170*4882a593Smuzhiyun    if not skip_val:
171*4882a593Smuzhiyun        tabs = tab_to_col - len(str) / 8
172*4882a593Smuzhiyun        if value > 9:
173*4882a593Smuzhiyun            val_str = '%#x' % value
174*4882a593Smuzhiyun        else:
175*4882a593Smuzhiyun            val_str = '%d' % value
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun        str += '%s= %s' % ('\t' * tabs, val_str)
178*4882a593Smuzhiyun    print '\t%s,' % str
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun# Process a CSV file, e.g. from tabula
181*4882a593Smuzhiyundef process_csv(name, fd):
182*4882a593Smuzhiyun    reader = csv.reader(fd)
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun    rows = []
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun    field = RegField()
187*4882a593Smuzhiyun    for row in reader:
188*4882a593Smuzhiyun        #print field.desc
189*4882a593Smuzhiyun        if not row[0]:
190*4882a593Smuzhiyun            field.desc.append(row[3])
191*4882a593Smuzhiyun            continue
192*4882a593Smuzhiyun        if field.bits:
193*4882a593Smuzhiyun            if field.bits != 'Bit':
194*4882a593Smuzhiyun                rows.append(field)
195*4882a593Smuzhiyun        #print row
196*4882a593Smuzhiyun        field = RegField(row)
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun    with Printer(name) as printer:
199*4882a593Smuzhiyun        for row in rows:
200*4882a593Smuzhiyun            #print field
201*4882a593Smuzhiyun            printer.output_regfield(row)
202*4882a593Smuzhiyun            #print
203*4882a593Smuzhiyun
204*4882a593Smuzhiyunfname = sys.argv[1]
205*4882a593Smuzhiyunname = sys.argv[2]
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun# Read output from pdftotext -layout
208*4882a593Smuzhiyunif 1:
209*4882a593Smuzhiyun    with open(fname, 'r') as fd:
210*4882a593Smuzhiyun        process_file(name, fd)
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun# Use tabula
213*4882a593Smuzhiyun# It seems to be better at outputting text for an entire cell in one cell.
214*4882a593Smuzhiyun# But it does not always work. E.g. GRF_GPIO7CH_IOMUX.
215*4882a593Smuzhiyun# So there is no point in using it.
216*4882a593Smuzhiyunif 0:
217*4882a593Smuzhiyun    with open(fname, 'r') as fd:
218*4882a593Smuzhiyun        process_csv(name, fd)
219