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