iomuxgen.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. #!/usr/bin/env python3
  2. # Copyright (C) 2018 RDA Technologies Limited and/or its affiliates("RDA").
  3. # All rights reserved.
  4. #
  5. # This software is supplied "AS IS" without any warranties.
  6. # RDA assumes no responsibility or liability for the use of the software,
  7. # conveys no license or title under any patent, copyright, or mask work
  8. # right to the product. RDA reserves the right to make changes in the
  9. # software without notification. RDA also make no representation or
  10. # warranty that such application will be suitable for the specified use
  11. # without further testing or modification.
  12. import argparse
  13. import sys
  14. import csv
  15. import re
  16. import json
  17. import os
  18. """
  19. JSON configuration file format:
  20. csv: the chip pinmux csv, related to json file directory
  21. init_fun: a list of functions to be initialized
  22. fun_prop: key is function, values:
  23. pull: default (can be omit), pull_none, pull_down,
  24. pull_up (8955/8909), pull_up_3, pull_up_2, pull_up_1
  25. inout: default (can be omit), input, output_hi, output_lo
  26. driving: string, 0~3 or 0~15, default is 2
  27. fun_def_pad: key is function, value is pad
  28. """
  29. DESCRIPTION = """
  30. Generate iomux source files from csv and json
  31. """
  32. COPYRIGHT = '''/* Copyright (C) 2018 RDA Technologies Limited and/or its affiliates("RDA").
  33. * All rights reserved.
  34. *
  35. * This software is supplied "AS IS" without any warranties.
  36. * RDA assumes no responsibility or liability for the use of the software,
  37. * conveys no license or title under any patent, copyright, or mask work
  38. * right to the product. RDA reserves the right to make changes in the
  39. * software without notification. RDA also make no representation or
  40. * warranty that such application will be suitable for the specified use
  41. * without further testing or modification.
  42. */
  43. '''
  44. INOUT_VAL = {'default': 'HAL_IOMUX_INOUT_DEFAULT',
  45. 'input': 'HAL_IOMUX_FORCE_INPUT',
  46. 'output': 'HAL_IOMUX_FORCE_OUTPUT',
  47. 'output_hi': 'HAL_IOMUX_FORCE_OUTPUT_HI',
  48. 'output_lo': 'HAL_IOMUX_FORCE_OUTPUT_LO'}
  49. PULL_VAL = {'default': 'HAL_IOMUX_PULL_DEFAULT',
  50. 'pull_none': 'HAL_IOMUX_FORCE_PULL_NONE',
  51. 'pull_down': 'HAL_IOMUX_FORCE_PULL_DOWN',
  52. 'pull_up_3': 'HAL_IOMUX_FORCE_PULL_UP_3',
  53. 'pull_up_2': 'HAL_IOMUX_FORCE_PULL_UP_2',
  54. 'pull_up_1': 'HAL_IOMUX_FORCE_PULL_UP_1'}
  55. def sort_nice(l):
  56. def convert(text):
  57. return int(text) if text.isdigit() else text
  58. def alphanum_key(key):
  59. return [convert(c) for c in re.split('([0-9]+)', key)]
  60. l.sort(key=alphanum_key)
  61. def output_defpad(fun_def_pad, fname):
  62. cfg = {}
  63. cfg['fun_def_pad'] = {}
  64. for fun, pad in fun_def_pad.items():
  65. lfun = fun.lower()
  66. lpad = pad.lower()
  67. cfg['fun_def_pad'][lfun] = lpad
  68. with open(fname, 'w') as fh:
  69. json.dump(cfg, fh, indent=4, sort_keys=True)
  70. def main(argv):
  71. parser = argparse.ArgumentParser(description=DESCRIPTION)
  72. parser.add_argument('--chip', dest='chip', required=True,
  73. help='chip, list for all')
  74. parser.add_argument('--def-pad', dest='defpad',
  75. help='output non-unique default pad')
  76. parser.add_argument('json', help='project fun mux configuration')
  77. parser.add_argument("pincfgin", help="template of hal_iomux_pincfg.c")
  78. parser.add_argument("pincfg", help="output hal_iomux_pincfg.c")
  79. parser.add_argument("pindef", nargs='?',
  80. help="output hal_iomux_pindef.h")
  81. args = parser.parse_args()
  82. if args.chip == 'list':
  83. print('supported chip: ', ['8910', '8811', '8955', '8909','8850'])
  84. return 0
  85. with open(args.pincfgin, 'r') as fh:
  86. pincfgin = fh.read()
  87. pads = [] # all pads
  88. funs = [] # all functions
  89. pad_idx = {} # pad -> index
  90. fun_idx = {} # fun -> index
  91. pad_reg = {} # pad -> reg
  92. fun_pads = {} # fun -> [pads]
  93. pad_funs = {} # pad -> [funs]
  94. fun_pad_sel = {} # fun,pad -> reg,sel
  95. fun_def_pad = {} # fun -> default pad
  96. init_fun = [] # init funs
  97. fun_prop = {} # fun -> {props}
  98. with open(args.json, 'r') as fh:
  99. pcfg = json.load(fh)
  100. for fun in pcfg.get('init_fun', []):
  101. init_fun.append(fun.upper())
  102. for fun in pcfg.get('fun_prop', {}):
  103. fun_prop[fun.upper()] = dict(pcfg['fun_prop'][fun])
  104. # cvs is related to directory of json file
  105. with open(os.path.join(os.path.dirname(args.json), pcfg['csv']), 'r') as fh:
  106. pinmux = csv.reader(fh)
  107. for row in pinmux:
  108. if not row[0]: # title row
  109. continue
  110. reg = row[0]
  111. pad = row[1].upper()
  112. pad_reg[pad] = reg
  113. if pad not in pads:
  114. pads.append(pad)
  115. if pad not in pad_funs:
  116. pad_funs[pad] = []
  117. n = -1
  118. for fun in row[2:]:
  119. n += 1
  120. if not fun:
  121. continue
  122. if fun.startswith('x--'):
  123. continue
  124. fun = fun.upper() #functions from csv
  125. if fun not in funs:
  126. funs.append(fun)
  127. if fun not in fun_pads:
  128. fun_pads[fun] = []
  129. if fun not in fun_prop:
  130. fun_prop[fun] = {}
  131. if fun in pad_funs[pad]:
  132. continue
  133. fun_pads[fun].append(pad)
  134. pad_funs[pad].append(fun)
  135. fun_pad_sel[(fun, pad)] = (reg, n)
  136. sort_nice(funs)
  137. sort_nice(pads)
  138. n = 1
  139. for fun in funs:
  140. fun_idx[fun] = n
  141. n += 1
  142. n = 1
  143. for pad in pads:
  144. pad_idx[pad] = n
  145. n += 1
  146. # sort
  147. for fun in funs:
  148. fun_pads[fun].sort(key=lambda el: pad_idx[el])
  149. for pad in pads:
  150. pad_funs[pad].sort(key=lambda el: fun_idx[el])
  151. # default pad from json
  152. for lfun in pcfg.get('fun_def_pad', {}):
  153. lpad = pcfg['fun_def_pad'][lfun]
  154. fun_def_pad[lfun.upper()] = lpad.upper()
  155. # when there is only one pad for fun, it is the default pad
  156. for fun in funs:
  157. if len(fun_pads[fun]) == 1:
  158. fun_def_pad[fun] = fun_pads[fun][0]
  159. # output default pads if needed
  160. if args.defpad:
  161. out_def_pad = dict(filter(lambda el: fun_pads[el[0]] != 1,
  162. fun_def_pad.items()))
  163. output_defpad(out_def_pad, args.defpad)
  164. return 0
  165. # output pindef if needed
  166. if args.pindef:
  167. with open(args.pindef, 'w') as fh:
  168. fh.write(COPYRIGHT)
  169. fh.write('#ifndef _HAL_IOMUX_PIN_H_\n')
  170. fh.write('#define _HAL_IOMUX_PIN_H_\n')
  171. fh.write('\n// Auto generated. Don\'t edit it manually!\n')
  172. fh.write('\n// all functions\n')
  173. for fun in funs:
  174. fh.write('#define HAL_IOMUX_FUN_{fun} {n} // 0x{n:x}\n'.
  175. format(fun=fun, n=fun_idx[fun]))
  176. fh.write('#define HAL_IOMUX_FUN_COUNT {}\n'.format(len(funs)))
  177. fh.write('\n// all pads\n')
  178. for pad in pads:
  179. fh.write('#define HAL_IOMUX_PAD_{pad} ({n} << 12) // 0x{n:x}\n'.
  180. format(pad=pad, n=pad_idx[pad]))
  181. fh.write('#define HAL_IOMUX_PAD_COUNT {}\n'.format(len(pads)))
  182. fh.write('\n// function with specified pad\n')
  183. for fun in funs:
  184. for pad in fun_pads[fun]:
  185. _, sel = fun_pad_sel[(fun, pad)]
  186. val = (sel << 24) | pad_idx[pad] << 12 | fun_idx[fun]
  187. fh.write('#define HAL_IOMUX_FUN_{fun}_PAD_{pad} 0x{n:x}\n'.
  188. format(fun=fun, pad=pad, n=val))
  189. fh.write('\n#endif\n')
  190. fun_prop_configs = []
  191. pad_prop_configs = []
  192. init_pad_configs = []
  193. fun_pad_sel_configs = []
  194. fun_name_configs = []
  195. pad_name_configs = []
  196. def gen_fun_prop(prop):
  197. inout = fun_prop[fun].get('inout', 'default')
  198. pull = fun_prop[fun].get('pull', 'default')
  199. driving = fun_prop[fun].get('driving', '2')
  200. return INOUT_VAL[inout], PULL_VAL[pull], driving
  201. def gen_pad_prop_8910(pad, reg):
  202. if reg == 'NULL':
  203. return '{{/*{pad}*/ NULL, NULL, 0, 0}}'.format(pad=pad)
  204. iomux, ana, offset, pull, _ = reg.split(':')
  205. iomux_reg = 'hwp_iomux->{}'.format(iomux)
  206. ana_reg = 'hwp_analogReg->{}'.format(ana)
  207. pad_type = 'PAD_TYPE_SPU' if pull == 'spu' else 'PAD_TYPE_WPUS'
  208. tmpl = '{{/*{pad}*/ &{iomux_reg}, &{ana_reg}, {offset}, {pad_type}}}'
  209. return tmpl.format(pad=pad, iomux_reg=iomux_reg, ana_reg=ana_reg,
  210. offset=offset, pad_type=pad_type)
  211. def gen_pad_prop_8850(pad, reg):
  212. if reg == 'NULL':
  213. return '{{/*{pad}*/ NULL, NULL}}'.format(pad=pad)
  214. iomux, ana, _ = reg.split(':')
  215. iomux_reg = 'hwp_iomux->{}'.format(iomux)
  216. ana_reg = 'hwp_iomux->{}'.format(ana)
  217. tmpl = '{{/*{pad}*/ &{iomux_reg}, &{ana_reg}}}'
  218. return tmpl.format(pad=pad, iomux_reg=iomux_reg, ana_reg=ana_reg)
  219. def gen_pad_prop_reg(pad, reg):
  220. if reg == 'NULL':
  221. return '{{/*{pad}*/ NULL}}'.format(pad=pad)
  222. tmpl = '{{/*{pad}*/ &{reg}}}'
  223. return tmpl.format(pad=pad, reg=reg)
  224. def gen_pad_prop(pad, reg):
  225. if args.chip == '8910':
  226. return gen_pad_prop_8910(pad, reg)
  227. elif args.chip == '8850':
  228. return gen_pad_prop_8850(pad, reg)
  229. return gen_pad_prop_reg(pad, reg)
  230. # pad propperties, must be complete list
  231. for pad in pads:
  232. reg = pad_reg[pad]
  233. pad_prop_configs.append(gen_pad_prop(pad, reg))
  234. # fun properties, must be complete list
  235. for fun in funs:
  236. inout, pull, driving = gen_fun_prop(fun_prop[fun])
  237. if fun in fun_def_pad:
  238. def_pad = fun_def_pad[fun]
  239. _, sel = fun_pad_sel[(fun, def_pad)]
  240. fun_prop_configs.append('{{/*{fun}*/ PAD_INDEX(HAL_IOMUX_PAD_{def_pad}), {sel}, {inout}, {pull}, {driving}}}'
  241. .format(fun=fun, def_pad=def_pad, sel=sel, inout=inout,
  242. pull=pull, driving=driving))
  243. else:
  244. fun_prop_configs.append('{{/*{fun}*/ 0, 0, {inout}, {pull}, {driving}}}'
  245. .format(fun=fun, inout=inout,
  246. pull=pull, driving=driving))
  247. # init fun for generation
  248. for fun in init_fun:
  249. if fun not in fun_def_pad:
  250. raise Exception('{} without default pad'.format(fun))
  251. pad = fun_def_pad[fun]
  252. reg, sel = fun_pad_sel[(fun, pad)]
  253. inout, pull, driving = gen_fun_prop(fun_prop[fun])
  254. init_pad_configs.append('{{PAD_INDEX(HAL_IOMUX_PAD_{pad}), {sel} /*{fun}*/, {inout}, {pull}, {driving}}}'
  255. .format(fun=fun, pad=pad, sel=sel, inout=inout,
  256. pull=pull, driving=driving))
  257. # all fun/pad combination
  258. for fun in funs:
  259. for pad in fun_pads[fun]:
  260. fun_pad_sel_configs.append('HAL_IOMUX_FUN_{fun}_PAD_{pad}'
  261. .format(fun=fun, pad=pad))
  262. # fun string name
  263. for fun in funs:
  264. fun_name_configs.append('"{fun}"'.format(fun=fun))
  265. # pad string name
  266. for pad in pads:
  267. pad_name_configs.append('"{pad}"'.format(pad=pad))
  268. with open(args.pincfg, 'w') as fh:
  269. fh.write(pincfgin.format(
  270. fun_pad_sel_config=',\n '.join(fun_pad_sel_configs),
  271. fun_name_config=',\n '.join(fun_name_configs),
  272. pad_name_config=',\n '.join(pad_name_configs),
  273. fun_prop_config=',\n '.join(fun_prop_configs),
  274. pad_prop_config=',\n '.join(pad_prop_configs),
  275. init_pad_config=',\n '.join(init_pad_configs)))
  276. return 0
  277. if __name__ == "__main__":
  278. sys.exit(main(sys.argv[1:]))