#!/usr/bin/env python3 # Copyright (C) 2018 RDA Technologies Limited and/or its affiliates("RDA"). # All rights reserved. # # This software is supplied "AS IS" without any warranties. # RDA assumes no responsibility or liability for the use of the software, # conveys no license or title under any patent, copyright, or mask work # right to the product. RDA reserves the right to make changes in the # software without notification. RDA also make no representation or # warranty that such application will be suitable for the specified use # without further testing or modification. import argparse import sys import csv import re import json import os """ JSON configuration file format: csv: the chip pinmux csv, related to json file directory init_fun: a list of functions to be initialized fun_prop: key is function, values: pull: default (can be omit), pull_none, pull_down, pull_up (8955/8909), pull_up_3, pull_up_2, pull_up_1 inout: default (can be omit), input, output_hi, output_lo driving: string, 0~3 or 0~15, default is 2 fun_def_pad: key is function, value is pad """ DESCRIPTION = """ Generate iomux source files from csv and json """ COPYRIGHT = '''/* Copyright (C) 2018 RDA Technologies Limited and/or its affiliates("RDA"). * All rights reserved. * * This software is supplied "AS IS" without any warranties. * RDA assumes no responsibility or liability for the use of the software, * conveys no license or title under any patent, copyright, or mask work * right to the product. RDA reserves the right to make changes in the * software without notification. RDA also make no representation or * warranty that such application will be suitable for the specified use * without further testing or modification. */ ''' INOUT_VAL = {'default': 'HAL_IOMUX_INOUT_DEFAULT', 'input': 'HAL_IOMUX_FORCE_INPUT', 'output': 'HAL_IOMUX_FORCE_OUTPUT', 'output_hi': 'HAL_IOMUX_FORCE_OUTPUT_HI', 'output_lo': 'HAL_IOMUX_FORCE_OUTPUT_LO'} PULL_VAL = {'default': 'HAL_IOMUX_PULL_DEFAULT', 'pull_none': 'HAL_IOMUX_FORCE_PULL_NONE', 'pull_down': 'HAL_IOMUX_FORCE_PULL_DOWN', 'pull_up_3': 'HAL_IOMUX_FORCE_PULL_UP_3', 'pull_up_2': 'HAL_IOMUX_FORCE_PULL_UP_2', 'pull_up_1': 'HAL_IOMUX_FORCE_PULL_UP_1'} def sort_nice(l): def convert(text): return int(text) if text.isdigit() else text def alphanum_key(key): return [convert(c) for c in re.split('([0-9]+)', key)] l.sort(key=alphanum_key) def output_defpad(fun_def_pad, fname): cfg = {} cfg['fun_def_pad'] = {} for fun, pad in fun_def_pad.items(): lfun = fun.lower() lpad = pad.lower() cfg['fun_def_pad'][lfun] = lpad with open(fname, 'w') as fh: json.dump(cfg, fh, indent=4, sort_keys=True) def main(argv): parser = argparse.ArgumentParser(description=DESCRIPTION) parser.add_argument('--chip', dest='chip', required=True, help='chip, list for all') parser.add_argument('--def-pad', dest='defpad', help='output non-unique default pad') parser.add_argument('json', help='project fun mux configuration') parser.add_argument("pincfgin", help="template of hal_iomux_pincfg.c") parser.add_argument("pincfg", help="output hal_iomux_pincfg.c") parser.add_argument("pindef", nargs='?', help="output hal_iomux_pindef.h") args = parser.parse_args() if args.chip == 'list': print('supported chip: ', ['8910', '8811', '8955', '8909','8850']) return 0 with open(args.pincfgin, 'r') as fh: pincfgin = fh.read() pads = [] # all pads funs = [] # all functions pad_idx = {} # pad -> index fun_idx = {} # fun -> index pad_reg = {} # pad -> reg fun_pads = {} # fun -> [pads] pad_funs = {} # pad -> [funs] fun_pad_sel = {} # fun,pad -> reg,sel fun_def_pad = {} # fun -> default pad init_fun = [] # init funs fun_prop = {} # fun -> {props} with open(args.json, 'r') as fh: pcfg = json.load(fh) for fun in pcfg.get('init_fun', []): init_fun.append(fun.upper()) for fun in pcfg.get('fun_prop', {}): fun_prop[fun.upper()] = dict(pcfg['fun_prop'][fun]) # cvs is related to directory of json file with open(os.path.join(os.path.dirname(args.json), pcfg['csv']), 'r') as fh: pinmux = csv.reader(fh) for row in pinmux: if not row[0]: # title row continue reg = row[0] pad = row[1].upper() pad_reg[pad] = reg if pad not in pads: pads.append(pad) if pad not in pad_funs: pad_funs[pad] = [] n = -1 for fun in row[2:]: n += 1 if not fun: continue if fun.startswith('x--'): continue fun = fun.upper() #functions from csv if fun not in funs: funs.append(fun) if fun not in fun_pads: fun_pads[fun] = [] if fun not in fun_prop: fun_prop[fun] = {} if fun in pad_funs[pad]: continue fun_pads[fun].append(pad) pad_funs[pad].append(fun) fun_pad_sel[(fun, pad)] = (reg, n) sort_nice(funs) sort_nice(pads) n = 1 for fun in funs: fun_idx[fun] = n n += 1 n = 1 for pad in pads: pad_idx[pad] = n n += 1 # sort for fun in funs: fun_pads[fun].sort(key=lambda el: pad_idx[el]) for pad in pads: pad_funs[pad].sort(key=lambda el: fun_idx[el]) # default pad from json for lfun in pcfg.get('fun_def_pad', {}): lpad = pcfg['fun_def_pad'][lfun] fun_def_pad[lfun.upper()] = lpad.upper() # when there is only one pad for fun, it is the default pad for fun in funs: if len(fun_pads[fun]) == 1: fun_def_pad[fun] = fun_pads[fun][0] # output default pads if needed if args.defpad: out_def_pad = dict(filter(lambda el: fun_pads[el[0]] != 1, fun_def_pad.items())) output_defpad(out_def_pad, args.defpad) return 0 # output pindef if needed if args.pindef: with open(args.pindef, 'w') as fh: fh.write(COPYRIGHT) fh.write('#ifndef _HAL_IOMUX_PIN_H_\n') fh.write('#define _HAL_IOMUX_PIN_H_\n') fh.write('\n// Auto generated. Don\'t edit it manually!\n') fh.write('\n// all functions\n') for fun in funs: fh.write('#define HAL_IOMUX_FUN_{fun} {n} // 0x{n:x}\n'. format(fun=fun, n=fun_idx[fun])) fh.write('#define HAL_IOMUX_FUN_COUNT {}\n'.format(len(funs))) fh.write('\n// all pads\n') for pad in pads: fh.write('#define HAL_IOMUX_PAD_{pad} ({n} << 12) // 0x{n:x}\n'. format(pad=pad, n=pad_idx[pad])) fh.write('#define HAL_IOMUX_PAD_COUNT {}\n'.format(len(pads))) fh.write('\n// function with specified pad\n') for fun in funs: for pad in fun_pads[fun]: _, sel = fun_pad_sel[(fun, pad)] val = (sel << 24) | pad_idx[pad] << 12 | fun_idx[fun] fh.write('#define HAL_IOMUX_FUN_{fun}_PAD_{pad} 0x{n:x}\n'. format(fun=fun, pad=pad, n=val)) fh.write('\n#endif\n') fun_prop_configs = [] pad_prop_configs = [] init_pad_configs = [] fun_pad_sel_configs = [] fun_name_configs = [] pad_name_configs = [] def gen_fun_prop(prop): inout = fun_prop[fun].get('inout', 'default') pull = fun_prop[fun].get('pull', 'default') driving = fun_prop[fun].get('driving', '2') return INOUT_VAL[inout], PULL_VAL[pull], driving def gen_pad_prop_8910(pad, reg): if reg == 'NULL': return '{{/*{pad}*/ NULL, NULL, 0, 0}}'.format(pad=pad) iomux, ana, offset, pull, _ = reg.split(':') iomux_reg = 'hwp_iomux->{}'.format(iomux) ana_reg = 'hwp_analogReg->{}'.format(ana) pad_type = 'PAD_TYPE_SPU' if pull == 'spu' else 'PAD_TYPE_WPUS' tmpl = '{{/*{pad}*/ &{iomux_reg}, &{ana_reg}, {offset}, {pad_type}}}' return tmpl.format(pad=pad, iomux_reg=iomux_reg, ana_reg=ana_reg, offset=offset, pad_type=pad_type) def gen_pad_prop_8850(pad, reg): if reg == 'NULL': return '{{/*{pad}*/ NULL, NULL}}'.format(pad=pad) iomux, ana, _ = reg.split(':') iomux_reg = 'hwp_iomux->{}'.format(iomux) ana_reg = 'hwp_iomux->{}'.format(ana) tmpl = '{{/*{pad}*/ &{iomux_reg}, &{ana_reg}}}' return tmpl.format(pad=pad, iomux_reg=iomux_reg, ana_reg=ana_reg) def gen_pad_prop_reg(pad, reg): if reg == 'NULL': return '{{/*{pad}*/ NULL}}'.format(pad=pad) tmpl = '{{/*{pad}*/ &{reg}}}' return tmpl.format(pad=pad, reg=reg) def gen_pad_prop(pad, reg): if args.chip == '8910': return gen_pad_prop_8910(pad, reg) elif args.chip == '8850': return gen_pad_prop_8850(pad, reg) return gen_pad_prop_reg(pad, reg) # pad propperties, must be complete list for pad in pads: reg = pad_reg[pad] pad_prop_configs.append(gen_pad_prop(pad, reg)) # fun properties, must be complete list for fun in funs: inout, pull, driving = gen_fun_prop(fun_prop[fun]) if fun in fun_def_pad: def_pad = fun_def_pad[fun] _, sel = fun_pad_sel[(fun, def_pad)] fun_prop_configs.append('{{/*{fun}*/ PAD_INDEX(HAL_IOMUX_PAD_{def_pad}), {sel}, {inout}, {pull}, {driving}}}' .format(fun=fun, def_pad=def_pad, sel=sel, inout=inout, pull=pull, driving=driving)) else: fun_prop_configs.append('{{/*{fun}*/ 0, 0, {inout}, {pull}, {driving}}}' .format(fun=fun, inout=inout, pull=pull, driving=driving)) # init fun for generation for fun in init_fun: if fun not in fun_def_pad: raise Exception('{} without default pad'.format(fun)) pad = fun_def_pad[fun] reg, sel = fun_pad_sel[(fun, pad)] inout, pull, driving = gen_fun_prop(fun_prop[fun]) init_pad_configs.append('{{PAD_INDEX(HAL_IOMUX_PAD_{pad}), {sel} /*{fun}*/, {inout}, {pull}, {driving}}}' .format(fun=fun, pad=pad, sel=sel, inout=inout, pull=pull, driving=driving)) # all fun/pad combination for fun in funs: for pad in fun_pads[fun]: fun_pad_sel_configs.append('HAL_IOMUX_FUN_{fun}_PAD_{pad}' .format(fun=fun, pad=pad)) # fun string name for fun in funs: fun_name_configs.append('"{fun}"'.format(fun=fun)) # pad string name for pad in pads: pad_name_configs.append('"{pad}"'.format(pad=pad)) with open(args.pincfg, 'w') as fh: fh.write(pincfgin.format( fun_pad_sel_config=',\n '.join(fun_pad_sel_configs), fun_name_config=',\n '.join(fun_name_configs), pad_name_config=',\n '.join(pad_name_configs), fun_prop_config=',\n '.join(fun_prop_configs), pad_prop_config=',\n '.join(pad_prop_configs), init_pad_config=',\n '.join(init_pad_configs))) return 0 if __name__ == "__main__": sys.exit(main(sys.argv[1:]))