#!/usr/bin/python3 # Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # This parses a CSV version of Logan_customer_pinmux_release.xlsm import argparse import csv import os import os.path import sys import tegra_pmx_soc_parser from tegra_pmx_utils import * dbg = False parser = argparse.ArgumentParser(description='Create a board config' + 'from a CSV version of the Venice2 pinmux spreadsheet') parser.add_argument('--debug', action='store_true', help='Turn on debugging prints') parser.add_argument('--csv', default=argparse.SUPPRESS, help='CSV file to parse') parser.add_argument('--csv-rsvd-0based', action='store_true', dest='csv_rsvd_0based', default=argparse.SUPPRESS, help='Assume 0-based RSVD numbering') parser.add_argument('--csv-rsvd-1based', action='store_false', dest='csv_rsvd_0based', default=argparse.SUPPRESS, help='Assume 1-based RSVD numbering') parser.add_argument('board', help='Board name') args = parser.parse_args() if args.debug: dbg = True if dbg: print(args) # Boards in alphabetical order in this dictionary: supported_boards = { 'cei-tk1-som': { # tk1-som_pinmux_V2.4.xlsm Colorado TK1-SOM Configuration (1-based rsvd) # updated to version 11 by Peter Chubb 'filename': 'csv/cei-tk1-som.csv', 'rsvd_base': 1, 'soc': 'tegra124', }, 'e2220-1170': { # T210_customer_pinmux.xlsm worksheet [elided] (0-based rsvd) 'filename': 'csv/e2220-1170.csv', 'rsvd_base': 0, 'soc': 'tegra210', }, 'jetson-tk1': { # Jetson_TK1_customer_pinmux.xlsm worksheet Jetson TK1 Configuration (1-based rsvd) from: # https://developer.nvidia.com/hardware-design-and-development 'filename': 'csv/jetson-tk1.csv', 'rsvd_base': 1, 'soc': 'tegra124', }, 'norrin': { # PM370_T124_customer_pinmux_1.1.xlsm worksheet Customer_Configuration (0-based rsvd) 'filename': 'nv-internal-data/PM370_T124_customer_pinmux_1.1.csv', 'rsvd_base': 0, 'soc': 'tegra124', }, 'p2371-0000': { # T210_customer_pinmux.xlsm worksheet [elided] Configuration (0-based rsvd) 'filename': 'csv/p2371-0000.csv', 'rsvd_base': 0, 'soc': 'tegra210', }, 'p2371-2180': { # T210_customer_pinmux.xlsm worksheet [elided] Configuration (0-based rsvd) 'filename': 'csv/p2371-2180.csv', 'rsvd_base': 0, 'soc': 'tegra210', }, 'p3450-porg': { # Jetson_Nano_DeveloperKit_Users_Pinmux_Configuration.xlsm (0-based rsvd) 'filename': 'csv/p3450-porg.csv', 'rsvd_base': 0, 'soc': 'tegra210', }, 'p2571': { # T210_customer_pinmux.xlsm worksheet [elided] Configuration (0-based rsvd) 'filename': 'csv/p2571.csv', 'rsvd_base': 0, 'soc': 'tegra210', }, 'tegra210-smaug': { # erista_customer_pinmux_v04_0420.xlsm 'filename': 'csv/tegra210-smaug-v04_0420.csv', 'rsvd_base': 0, 'soc': 'tegra210', }, 'venice2': { # Venice2_T124_customer_pinmux_based_on_P4_rev47_2013-07-12.xlsm worksheet Customer_Configuration (0-based rsvd) 'filename': 'nv-internal-data/Venice2_T124_customer_pinmux_based_on_P4_rev47_2013-07-12.csv', 'rsvd_base': 0, 'soc': 'tegra124', }, } if not args.board in supported_boards: print('ERROR: Unsupported board %s' % args.board, file=sys.stderr) sys.exit(1) board_conf = supported_boards[args.board] if 'csv' in args: board_conf['filename'] = args.csv if 'csv_rsvd_0based' in args: board_conf['rsvd_base'] = {True: 0, False: 1}[args.csv_rsvd_0based] if dbg: print(board_conf) soc = tegra_pmx_soc_parser.load_soc(board_conf['soc']) COL_BALL_NAME = 0 COL_BALL_MID = 1 COL_BALL_DSC = 2 COL_GPIO = 3 COL_F0 = 4 COL_F1 = 5 COL_F2 = 6 COL_F3 = 7 COL_FS = 8 COL_MUX = 9 COL_PUPD = 10 COL_TRI = 11 COL_E_INPUT = 12 COL_GPIO_INIT_VAL = 13 COL_DIRECTION = 14 COL_RCV_SEL = 15 col_names = { COL_BALL_NAME: 'Ball Name', COL_BALL_MID: 'MID', COL_BALL_DSC: 'DSC', COL_GPIO: 'GPIO', COL_F0: 'F0', COL_F1: 'F1', COL_F2: 'F2', COL_F3: 'F3', COL_FS: 'FS', COL_MUX: 'Pin Group', COL_PUPD: 'PUPD', COL_TRI: 'Tristate', COL_E_INPUT: 'E_Input', COL_GPIO_INIT_VAL: 'GPIO Init Value', COL_DIRECTION: 'Pin Direction', } if soc.soc_pins_have_rcv_sel: col_names[COL_RCV_SEL] = 'High or Normal VIL/VIH' if soc.soc_pins_have_e_io_hv: col_names[COL_RCV_SEL] = '3.3V Tolerance Enable' cols = {} def func_munge(f): if board_conf['soc'] == 'tegra124': if f in ('sdmmc2a', 'sdmmc2b'): return 'sdmmc2' if f in ('ir3_rxd', 'ir3_txd'): return 'irda' if soc.soc_rsvd_base != board_conf['rsvd_base']: if soc.soc_rsvd_base: return rsvd_0base_to_1base(f) else: raise Exception('CSV 1-based to SoC 0-based not supported') return f def pupd_munge(d): return { 'NORMAL': 'none', 'PULL_UP': 'up', 'PULL_DOWN': 'down', }[d] def tri_munge(d): return { 'NORMAL': False, 'TRISTATE': True, }[d] def e_input_munge(d): return { 'DISABLE': False, 'ENABLE': True, }[d] warn_empty_gpio_init_val = False def gpio_init_val_munge(d): global warn_empty_gpio_init_val if d == '': warn_empty_gpio_init_val = True return { '': 'out?', '0': 'out0', '1': 'out1', }[d] def od_from_direction(d): return d == 'Open-Drain' def rcv_sel_munge(d): return { '': False, 'NORMAL': False, 'HIGH': True, 'Disable': False, 'Enable': True, }[d] found_header = False pin_table = [] mipi_table = [] with open(board_conf['filename'], newline='') as fh: csv = csv.reader(fh) lnum = 0 for row in csv: lnum += 1 # Header rows if not found_header: if 'Ball Name' not in row: if lnum > 25: print('ERROR: Header row not found', file=sys.stderr) sys.exit(1) continue for colid, coltext in col_names.items(): try: cols[colid] = row.index(coltext) except: if colid in (COL_BALL_MID, COL_BALL_DSC): pass else: if board_conf['soc'] != 'tegra124': raise if colid != COL_RCV_SEL: print('ERROR: Header column "%s" not found' % coltext, file=sys.stderr) sys.exit(1) cols[colid] = None found_header = True continue ball_name = row[cols[COL_BALL_NAME]].lower() if ball_name.startswith('mipi_pad_ctrl_'): ball_name = ball_name[14:] mipi = soc.mipi_pad_ctrl_group_by_name(ball_name) else: mipi = None if cols[COL_BALL_MID]: ball_mid = row[cols[COL_BALL_MID]] else: ball_mid = None if cols[COL_BALL_DSC]: ball_dsc = row[cols[COL_BALL_DSC]] else: ball_dsc = None # Section title row if not ball_mid and not ball_dsc and not mipi: continue mux = func_munge(row[cols[COL_MUX]].lower()) if mipi: mipi_table.append((repr(mipi.name), repr(mux))) continue # Pin not affected by pinmux if mux in ('', '0', '#n/a'): continue if dbg: print(ball_name) gpio = row[cols[COL_GPIO]].lower() f0 = func_munge(row[cols[COL_F0]].lower()) f1 = func_munge(row[cols[COL_F1]].lower()) f2 = func_munge(row[cols[COL_F2]].lower()) f3 = func_munge(row[cols[COL_F3]].lower()) fs = func_munge(row[cols[COL_FS]].lower()) pupd = pupd_munge(row[cols[COL_PUPD]]) tri = tri_munge(row[cols[COL_TRI]]) e_input = e_input_munge(row[cols[COL_E_INPUT]]) od = od_from_direction(row[cols[COL_DIRECTION]]) if cols[COL_RCV_SEL]: rcv_sel = rcv_sel_munge(row[cols[COL_RCV_SEL]]) else: rcv_sel = False mux_gpio = mux.startswith('gpio_p') or (mux == gpio) if mux_gpio: mux = None if e_input: gpio_init = 'in' else: gpio_init = gpio_init_val_munge(row[cols[COL_GPIO_INIT_VAL]]) else: gpio_init = None gpio_pin = soc.gpio_or_pin_by_name(ball_name) for i, func in enumerate((f0, f1, f2, f3)): alt_rsvd = 'rsvd' + str(soc.soc_rsvd_base + i) if func != gpio_pin.funcs[i] and func != alt_rsvd: print('WARNING: %s: F%d mismatch CSV %s vs SOC %s' % (ball_name, i, repr(func), repr(gpio_pin.funcs[i])), file=sys.stderr) for i, func in enumerate((f0, f1, f2, f3)): alt_rsvd = 'rsvd' + str(soc.soc_rsvd_base + i) if func not in gpio_pin.funcs and func != alt_rsvd: print('ERROR: %s: F%d CSV %s not in SOC list %s' % (ball_name, i, repr(func), repr(gpio_pin.funcs)), file=sys.stderr) sys.exit(1) if fs not in (f0, f1, f2, f3): print('ERROR: %s: FSAFE CSV %s not in CSV F0..3 %s' % (ball_name, fs, repr((f0, f1, f2, f3))), file=sys.stderr) sys.exit(1) if mux and mux not in (f0, f1, f2, f3): print('ERROR: %s: MUX CSV %s not in CSV F0..3 %s' % (ball_name, mux, repr((f0, f1, f2, f3))), file=sys.stderr) sys.exit(1) if mux and mux not in gpio_pin.funcs: print('ERROR: %s: MUX CSV %s not in SOC F0..3 %s' % (ball_name, mux, repr(gpio_pin.funcs)), file=sys.stderr) sys.exit(1) if (board_conf['soc'] == 'tegra124') and (ball_name in ('reset_out_n', 'owr', 'hdmi_int', 'ddc_scl', 'ddc_sda')): # These balls' pad type is always OD, so we don't need to set it # FIXME: The SoC data structure should tell us the pad type instead of hard-coding it od = False if od and not gpio_pin.od: print('WARNING: %s: OD in board file, but pin has no OD' % ball_name, file=sys.stderr) od = False pin_has_rcv_sel = False if soc.soc_pins_have_rcv_sel: pin_has_rcv_sel = gpio_pin.rcv_sel if soc.soc_pins_have_e_io_hv: pin_has_rcv_sel = gpio_pin.e_io_hv if rcv_sel and not pin_has_rcv_sel: print('WARNING: %s: RCV_SEL/E_IO_HV in board file, but pin does not support it' % ball_name, file=sys.stderr) rcv_sel = False pin_table.append((repr(gpio_pin.fullname), repr(mux), repr(gpio_init), repr(pupd), repr(tri), repr(e_input), repr(od), repr(rcv_sel))) pin_headings = ('pin', 'mux', 'gpio_init', 'pull', 'tri', 'e_inp', 'od') if soc.soc_pins_have_e_io_hv: pin_headings += ('e_io_hv',) if soc.soc_pins_have_rcv_sel: pin_headings += ('rcv_sel',) mipi_headings = ('pin', 'mux') cfgfile = os.path.join('configs', args.board + '.board') with open(cfgfile, 'wt') as fh: print('soc = \'%s\'' % board_conf['soc'], file=fh) print(file=fh) print('pins = (', file=fh) dump_py_table(pin_headings, pin_table, file=fh) print(')', file=fh) print('', file=fh) print('drive_groups = (', file=fh) print(')', file=fh) print('', file=fh) print('mipi_pad_ctrl_groups = (', file=fh) dump_py_table(mipi_headings, mipi_table, file=fh) print(')', file=fh) if warn_empty_gpio_init_val: print('WARNING: Missing gpio_init_vals detected. Manual fixup required', file=sys.stderr)