summaryrefslogtreecommitdiff
path: root/soc-to-kernel-pinctrl-driver.py
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2014-03-06 13:06:31 -0700
committerStephen Warren <swarren@nvidia.com>2014-04-22 16:18:35 -0600
commit2577ab08c5a84229580c83a0cd00a03328eba89b (patch)
treead04beb34ad4e3f65564316b6a9d8ac585298095 /soc-to-kernel-pinctrl-driver.py
parent16495973b3f18b575ed20773c788be642ffceb63 (diff)
downloadtegra-pinmux-scripts-2577ab08c5a84229580c83a0cd00a03328eba89b.tar.gz
Initial set of scripts
A set of scripts to generate Linux kernel and U-Boot pinmux drivers and board pinmux configuration tables. Also included are scripts to convert existing Linux kernel pinmux drivers and NV-internal spreadsheets to the internal data representation. SoC configuration files are included for Tegra30, Tegra114, and Tegra124. Board configuration files are included for Jetson TK1 and Venice2. configs/tegra30.soc configs/tegra114.soc configs/tegra124.soc SoC pin definitions configs/jetson-tk1.board configs/venice2.board Board configurations soc-to-kernel-pinctrl-driver.py soc-to-uboot-driver.py Generate Linux kernel and U-Boot pinmux drivers board-to-kernel-dt.py board-to-uboot.py Generate board configuration tables for the Linux kernel (DT) and U-Boot. kernel-pinctrl-driver-to-soc.py Convert an existing Linux kernel pinmux driver to the internal representation of an SoC used by this project. csv-to-board-tegra124-xlsx.py Convert an NV-internal board configuration spreadsheet to the internal representation of a board configuration used by this project. tegra_pmx_board_parser.py tegra_pmx_parser_utils.py tegra_pmx_soc_parser.py tegra_pmx_utils.py Internal Python modules used to parse the internal data representations, and various other utilities. Signed-off-by: Stephen Warren <swarren@nvidia.com>
Diffstat (limited to 'soc-to-kernel-pinctrl-driver.py')
-rwxr-xr-xsoc-to-kernel-pinctrl-driver.py408
1 files changed, 408 insertions, 0 deletions
diff --git a/soc-to-kernel-pinctrl-driver.py b/soc-to-kernel-pinctrl-driver.py
new file mode 100755
index 0000000..fd1930d
--- /dev/null
+++ b/soc-to-kernel-pinctrl-driver.py
@@ -0,0 +1,408 @@
+#!/usr/bin/env 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.
+
+import argparse
+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 kernel pinctrl ' +
+ 'driver from an SoC config file')
+parser.add_argument('--debug', action='store_true', help='Turn on debugging prints')
+parser.add_argument('soc', help='SoC to process')
+args = parser.parse_args()
+if args.debug:
+ dbg = True
+if dbg: print(args)
+
+soc = tegra_pmx_soc_parser.load_soc(args.soc)
+
+print('''\
+/*
+ * Pinctrl data for the NVIDIA %s pinmux
+ *
+ * Copyright (c) %s, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "pinctrl-tegra.h"
+
+/*
+ * Most pins affected by the pinmux can also be GPIOs. Define these first.
+ * These must match how the GPIO driver names/numbers its pins.
+ */
+''' % (soc.titlename, soc.kernel_copyright_years), end='')
+
+# Do not add any more exceptions here; new SoCs should be formatted correctly
+if soc.name == 'tegra30':
+ define_column = 41
+else:
+ define_column = 49
+
+emit_define('_GPIO(offset)', '(offset)', define_column)
+print()
+
+last_gpio_define = None
+for gpio in soc.gpios_by_num():
+ emit_define(gpio.define, '_GPIO(%d)' % gpio.num, define_column)
+ last_gpio_define = gpio.define
+
+print()
+print('/* All non-GPIO pins follow */')
+emit_define('NUM_GPIOS', '(%s + 1)' % last_gpio_define, define_column)
+emit_define('_PIN(offset)', '(NUM_GPIOS + (offset))', define_column)
+print()
+print('/* Non-GPIO pins */')
+
+for pin in soc.pins_by_num():
+ emit_define(pin.define, '_PIN(%d)' % pin.num, define_column)
+
+print()
+print('static const struct pinctrl_pin_desc %s_pins[] = {' % soc.name)
+for pin in soc.gpios_pins_by_num():
+ print('\tPINCTRL_PIN(%s, "%s"),' % (pin.define, pin.desc))
+print('};')
+
+for pin in soc.gpios_pins_by_num():
+ if not pin.reg:
+ continue
+ print('''\
+
+static const unsigned %s_pins[] = {
+ %s,
+};
+''' % (pin.fullname, pin.define), end='')
+
+# Do not add any more exceptions here; new SoCs should be formatted correctly
+if soc.name == 'tegra30':
+ f = soc.drive_groups_by_alpha
+else:
+ f = soc.drive_groups_by_reg
+for group in f():
+ print('''\
+
+static const unsigned %s_pins[] = {
+''' % group.fullname, end='')
+ for pin in group.gpios_pins:
+ print('\t%s,' % pin.define)
+ print('};');
+
+print('''\
+
+enum tegra_mux {
+''', end='')
+
+for func in soc.functions_by_alpha():
+ print('\tTEGRA_MUX_%s,' % func.name.upper())
+
+print('''\
+};
+
+#define FUNCTION(fname) \\
+ { \\
+ .name = #fname, \\
+ }
+
+static struct tegra_function %s_functions[] = {
+''' % soc.name, end='')
+
+for func in soc.functions_by_alpha():
+ print('\tFUNCTION(%s),' % func.name)
+
+print('''\
+};
+
+#define DRV_PINGROUP_REG_A 0x868 /* bank 0 */
+#define PINGROUP_REG_A 0x3000 /* bank 1 */
+
+#define PINGROUP_REG(r) ((r) - PINGROUP_REG_A)
+
+#define PINGROUP_BIT_Y(b) (b)
+#define PINGROUP_BIT_N(b) (-1)
+
+''', end='')
+
+if soc.has_rcv_sel:
+ print('#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel) \\')
+ tab = '\t'
+else:
+ print('#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior) \\')
+ tab = ''
+
+print('''\
+ { %(tab)s\\
+ .name = #pg_name, %(tab)s\\
+ .pins = pg_name##_pins, %(tab)s\\
+ .npins = ARRAY_SIZE(pg_name##_pins), %(tab)s\\
+ .funcs = { %(tab)s\\
+ TEGRA_MUX_##f0, %(tab)s\\
+ TEGRA_MUX_##f1, %(tab)s\\
+ TEGRA_MUX_##f2, %(tab)s\\
+ TEGRA_MUX_##f3, %(tab)s\\
+ }, %(tab)s\\
+ .mux_reg = PINGROUP_REG(r), %(tab)s\\
+ .mux_bank = 1, %(tab)s\\
+ .mux_bit = 0, %(tab)s\\
+ .pupd_reg = PINGROUP_REG(r), %(tab)s\\
+ .pupd_bank = 1, %(tab)s\\
+ .pupd_bit = 2, %(tab)s\\
+ .tri_reg = PINGROUP_REG(r), %(tab)s\\
+ .tri_bank = 1, %(tab)s\\
+ .tri_bit = 4, %(tab)s\\
+ .einput_bit = PINGROUP_BIT_Y(5), %(tab)s\\
+ .odrain_bit = PINGROUP_BIT_##od(6), %(tab)s\\
+ .lock_bit = PINGROUP_BIT_Y(7), %(tab)s\\
+ .ioreset_bit = PINGROUP_BIT_##ior(8), %(tab)s\\
+''' % {'tab': tab}, end='')
+
+if soc.has_rcv_sel:
+ print('''\
+ .rcv_sel_bit = PINGROUP_BIT_##rcv_sel(9), %(tab)s\\
+''' % {'tab': tab}, end='')
+else:
+ print('''\
+ .rcv_sel_bit = -1, %(tab)s\\
+''' % {'tab': tab}, end='')
+
+print('''\
+ .drv_reg = -1, %(tab)s\\
+ }
+
+#define DRV_PINGROUP_REG(r) ((r) - DRV_PINGROUP_REG_A)
+
+''' % {'tab': tab}, end='')
+
+if soc.has_drvtype:
+ print('''\
+#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, \\
+ drvdn_b, drvdn_w, drvup_b, drvup_w, \\
+ slwr_b, slwr_w, slwf_b, slwf_w, \\
+ drvtype) \\
+''', end='')
+else:
+ print('''\
+#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, \\
+ drvdn_b, drvdn_w, drvup_b, drvup_w, \\
+ slwr_b, slwr_w, slwf_b, slwf_w) \\
+''', end='')
+
+print('''\
+ { %(tab)s\\
+ .name = "drive_" #pg_name, %(tab)s\\
+ .pins = drive_##pg_name##_pins, %(tab)s\\
+ .npins = ARRAY_SIZE(drive_##pg_name##_pins), %(tab)s\\
+ .mux_reg = -1, %(tab)s\\
+ .pupd_reg = -1, %(tab)s\\
+ .tri_reg = -1, %(tab)s\\
+ .einput_bit = -1, %(tab)s\\
+ .odrain_bit = -1, %(tab)s\\
+ .lock_bit = -1, %(tab)s\\
+ .ioreset_bit = -1, %(tab)s\\
+ .rcv_sel_bit = -1, %(tab)s\\
+ .drv_reg = DRV_PINGROUP_REG(r), %(tab)s\\
+ .drv_bank = 0, %(tab)s\\
+ .hsm_bit = hsm_b, %(tab)s\\
+ .schmitt_bit = schmitt_b, %(tab)s\\
+ .lpmd_bit = lpmd_b, %(tab)s\\
+ .drvdn_bit = drvdn_b, %(tab)s\\
+ .drvdn_width = drvdn_w, %(tab)s\\
+ .drvup_bit = drvup_b, %(tab)s\\
+ .drvup_width = drvup_w, %(tab)s\\
+ .slwr_bit = slwr_b, %(tab)s\\
+ .slwr_width = slwr_w, %(tab)s\\
+ .slwf_bit = slwf_b, %(tab)s\\
+ .slwf_width = slwf_w, %(tab)s\\
+''' % {'tab': tab}, end='')
+
+if soc.has_drvtype:
+ print('''\
+ .drvtype_bit = PINGROUP_BIT_##drvtype(6), %(tab)s\\
+''' % {'tab': tab}, end='')
+else:
+ print('''\
+ .drvtype_bit = -1, %(tab)s\\
+''' % {'tab': tab}, end='')
+
+print('''\
+ }
+
+static const struct tegra_pingroup %s_groups[] = {
+''' % soc.name, end='')
+
+# Do not add any more exceptions here; new SoCs should be formatted correctly
+if soc.name == 'tegra30':
+ max_gpio_pin_len = max([len(pin.fullname) for pin in soc.gpios_pins_by_reg()])
+ max_f0_len = 12
+ max_f1_len = 12
+ max_f2_len = 12
+ max_f3_len = 12
+ yn_width = 1
+ col_widths = (max_gpio_pin_len, max_f0_len, max_f1_len, max_f2_len, max_f3_len, 6, yn_width, yn_width)
+ if soc.has_rcv_sel:
+ col_widths += (yn_width,)
+ right_justifies = None
+elif soc.name in ('tegra114', 'tegra124'):
+ max_gpio_pin_len = max([len(pin.fullname) for pin in soc.gpios_pins_by_reg()])
+ max_f0_len = 10
+ max_f1_len = 10
+ max_f2_len = 12
+ max_f3_len = 11
+ yn_width = 2
+ col_widths = (max_gpio_pin_len, max_f0_len, max_f1_len, max_f2_len, max_f3_len, 6, yn_width, yn_width)
+ if soc.has_rcv_sel:
+ col_widths += (yn_width,)
+ right_justifies = (False, False, False, False, False, False, False, True, True, True)
+else:
+ col_widths = None
+ right_justifies = None
+
+headings = ('pg_name', 'f0', 'f1', 'f2', 'f3', 'r', 'od', 'ior',)
+if soc.has_rcv_sel:
+ headings += ('rcv_sel',)
+
+rows = []
+# Do not add any more exceptions here; new SoCs should be formatted correctly
+if soc.name == 'tegra30':
+ f = soc.gpios_pins_by_num
+else:
+ f = soc.gpios_pins_by_reg
+for pin in f():
+ if not pin.reg:
+ continue
+ row = (
+ pin.fullname,
+ pin.f0.upper(),
+ pin.f1.upper(),
+ pin.f2.upper(),
+ pin.f3.upper(),
+ '0x%x' % pin.reg,
+ boolean_to_yn(pin.od),
+ boolean_to_yn(pin.ior),
+ )
+ if soc.has_rcv_sel:
+ row += (boolean_to_yn(pin.rcv_sel),)
+ rows.append(row)
+dump_c_table(headings, 'PINGROUP', rows, col_widths=col_widths, right_justifies=right_justifies)
+
+# Do not add any more exceptions here; new SoCs should be formatted correctly
+if soc.name != 'tegra30':
+ print()
+
+max_drvgrp_len = max([len(drvgroup.name) for drvgroup in soc.drive_groups_by_reg()])
+
+print('\t/* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w', end='')
+if soc.has_drvtype:
+ print(', drvtype', end='')
+print(' */')
+
+rows = []
+# Do not add any more exceptions here; new SoCs should be formatted correctly
+if soc.name == 'tegra30':
+ f = soc.drive_groups_by_alpha
+else:
+ f = soc.drive_groups_by_reg
+col_widths = (0, 0, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2)
+right_justifies = (False, False, True, True, True, True, True, True, True, True, True, True, True, True)
+for drvgroup in f():
+ row = (
+ drvgroup.name,
+ '0x%x' % drvgroup.reg,
+ repr(drvgroup.hsm_b),
+ repr(drvgroup.schmitt_b),
+ repr(drvgroup.lpmd_b),
+ repr(drvgroup.drvdn_b),
+ repr(drvgroup.drvdn_w),
+ repr(drvgroup.drvup_b),
+ repr(drvgroup.drvup_w),
+ repr(drvgroup.slwr_b),
+ repr(drvgroup.slwr_w),
+ repr(drvgroup.slwf_b),
+ repr(drvgroup.slwf_w),
+ )
+ if soc.has_drvtype:
+ row += (boolean_to_yn(drvgroup.drvtype),)
+ rows.append(row)
+dump_c_table(None, 'DRV_PINGROUP', rows, col_widths=col_widths, right_justifies=right_justifies)
+
+socvars = {
+ 'author': soc.kernel_author,
+ 'soc': soc.name,
+ 'usoc': soc.titlename,
+}
+
+print('''\
+};
+
+static const struct tegra_pinctrl_soc_data %(soc)s_pinctrl = {
+ .ngpios = NUM_GPIOS,
+ .pins = %(soc)s_pins,
+ .npins = ARRAY_SIZE(%(soc)s_pins),
+ .functions = %(soc)s_functions,
+ .nfunctions = ARRAY_SIZE(%(soc)s_functions),
+ .groups = %(soc)s_groups,
+ .ngroups = ARRAY_SIZE(%(soc)s_groups),
+};
+
+static int %(soc)s_pinctrl_probe(struct platform_device *pdev)
+{
+ return tegra_pinctrl_probe(pdev, &%(soc)s_pinctrl);
+}
+
+static struct of_device_id %(soc)s_pinctrl_of_match[] = {
+ { .compatible = "nvidia,%(soc)s-pinmux", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, %(soc)s_pinctrl_of_match);
+
+static struct platform_driver %(soc)s_pinctrl_driver = {
+ .driver = {
+ .name = "%(soc)s-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = %(soc)s_pinctrl_of_match,
+ },
+ .probe = %(soc)s_pinctrl_probe,
+ .remove = tegra_pinctrl_remove,
+};
+module_platform_driver(%(soc)s_pinctrl_driver);
+
+MODULE_AUTHOR("%(author)s");
+MODULE_DESCRIPTION("NVIDIA %(usoc)s pinctrl driver");
+MODULE_LICENSE("GPL v2");
+''' % socvars, end='')