pinctrl: Add pinctrl script
Add initial version of pinctrl script. It creates pinctrl definitions from a well defined pinconfig yaml file. This file is filled with all I/O multiplexing and considerations for all Atmel SAM SoCs. The auto generated files produced by this script should be used inside a <board>-pinctrl.dtsi file to define the pinctrl groups. Signed-off-by: Gerson Fernando Budke <nandojve@gmail.com>
This commit is contained in:
parent
45cb8f898f
commit
9597144ca1
|
@ -1 +1,2 @@
|
|||
zephyr_include_directories(include)
|
||||
add_subdirectory(asf)
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Gerson Fernando Budke
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef DT_BINDINGS_PINCTRL_ATMEL_SAM_H_
|
||||
#define DT_BINDINGS_PINCTRL_ATMEL_SAM_H_
|
||||
|
||||
/*
|
||||
* @name Atmel SAM gpio port list.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define SAM_PINMUX_PORT_a 0U
|
||||
#define SAM_PINMUX_PORT_b 1U
|
||||
#define SAM_PINMUX_PORT_c 2U
|
||||
#define SAM_PINMUX_PORT_d 3U
|
||||
#define SAM_PINMUX_PORT_e 4U
|
||||
#define SAM_PINMUX_PORT_f 5U
|
||||
#define SAM_PINMUX_PORT_g 6U
|
||||
#define SAM_PINMUX_PORT_h 7U
|
||||
#define SAM_PINMUX_PORT_i 8U
|
||||
#define SAM_PINMUX_PORT_j 9U
|
||||
#define SAM_PINMUX_PORT_k 10U
|
||||
#define SAM_PINMUX_PORT_l 11U
|
||||
#define SAM_PINMUX_PORT_m 12U
|
||||
#define SAM_PINMUX_PORT_n 13U
|
||||
#define SAM_PINMUX_PORT_o 14U
|
||||
#define SAM_PINMUX_PORT_p 15U
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Atmel SAM peripheral list.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** GPIO */
|
||||
#define SAM_PINMUX_PERIPH_gpio 0U
|
||||
/** Peripherals */
|
||||
#define SAM_PINMUX_PERIPH_a 0U
|
||||
#define SAM_PINMUX_PERIPH_b 1U
|
||||
#define SAM_PINMUX_PERIPH_c 2U
|
||||
#define SAM_PINMUX_PERIPH_d 3U
|
||||
#define SAM_PINMUX_PERIPH_e 4U
|
||||
#define SAM_PINMUX_PERIPH_f 5U
|
||||
#define SAM_PINMUX_PERIPH_g 6U
|
||||
#define SAM_PINMUX_PERIPH_h 7U
|
||||
#define SAM_PINMUX_PERIPH_i 8U
|
||||
#define SAM_PINMUX_PERIPH_j 9U
|
||||
#define SAM_PINMUX_PERIPH_k 10U
|
||||
#define SAM_PINMUX_PERIPH_l 11U
|
||||
#define SAM_PINMUX_PERIPH_m 12U
|
||||
#define SAM_PINMUX_PERIPH_n 13U
|
||||
/** Extra */
|
||||
#define SAM_PINMUX_PERIPH_x 0U
|
||||
/** System */
|
||||
#define SAM_PINMUX_PERIPH_s 0U
|
||||
/** LPM */
|
||||
#define SAM_PINMUX_PERIPH_lpm 0U
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Atmel SAM pin function list.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Selects pin to be used as GPIO */
|
||||
#define SAM_PINMUX_FUNC_gpio 0U
|
||||
/** Selects pin to be used as by some peripheral */
|
||||
#define SAM_PINMUX_FUNC_periph 1U
|
||||
/** Selects pin to be used as extra function */
|
||||
#define SAM_PINMUX_FUNC_extra 2U
|
||||
/** Selects pin to be used as system function */
|
||||
#define SAM_PINMUX_FUNC_system 3U
|
||||
/** Selects and configure pin to be used in Low Power Mode */
|
||||
#define SAM_PINMUX_FUNC_lpm 4U
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Atmel SAM pinmux bit field mask and positions.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Pinmux bit field position. */
|
||||
#define SAM_PINCTRL_PINMUX_POS (16U)
|
||||
/** Pinmux bit field mask. */
|
||||
#define SAM_PINCTRL_PINMUX_MASK (0xFFFF)
|
||||
|
||||
/** Port field mask. */
|
||||
#define SAM_PINMUX_PORT_MSK (0xFU)
|
||||
/** Port field position. */
|
||||
#define SAM_PINMUX_PORT_POS (0U)
|
||||
/** Pin field mask. */
|
||||
#define SAM_PINMUX_PIN_MSK (0x1FU)
|
||||
/** Pin field position. */
|
||||
#define SAM_PINMUX_PIN_POS (SAM_PINMUX_PORT_POS + 4U)
|
||||
/** Function field mask. */
|
||||
#define SAM_PINMUX_FUNC_MSK (0x7U)
|
||||
/** Function field position. */
|
||||
#define SAM_PINMUX_FUNC_POS (SAM_PINMUX_PIN_POS + 5U)
|
||||
/** Peripheral field mask. */
|
||||
#define SAM_PINMUX_PERIPH_MSK (0xFU)
|
||||
/** Peripheral field position. */
|
||||
#define SAM_PINMUX_PERIPH_POS (SAM_PINMUX_FUNC_POS + 3U)
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Atmel SAM pinmux bit field.
|
||||
* @anchor SAM_PINMUX
|
||||
*
|
||||
* Fields:
|
||||
*
|
||||
* - 0..3: port
|
||||
* - 4..8: pin_num
|
||||
* - 9..11: func
|
||||
* - 12..15: pin_mux
|
||||
*
|
||||
* @param port Port ('A'..'P')
|
||||
* @param pin Pin (0..31)
|
||||
* @param func Function (GPIO, Peripheral, System, Extra, LPM - 0..4)
|
||||
* @param pin_mux Peripheral based on the Function selected (0..15)
|
||||
*/
|
||||
#define SAM_PINMUX(port, pin_num, pin_mux, func) \
|
||||
((((SAM_PINMUX_PORT_##port) & SAM_PINMUX_PORT_MSK) \
|
||||
<< SAM_PINMUX_PORT_POS) | \
|
||||
(((pin_num) & SAM_PINMUX_PIN_MSK) \
|
||||
<< SAM_PINMUX_PIN_POS) | \
|
||||
(((SAM_PINMUX_FUNC_##func) & SAM_PINMUX_FUNC_MSK) \
|
||||
<< SAM_PINMUX_FUNC_POS) | \
|
||||
(((SAM_PINMUX_PERIPH_##pin_mux) & SAM_PINMUX_PERIPH_MSK) \
|
||||
<< SAM_PINMUX_PERIPH_POS))
|
||||
|
||||
/**
|
||||
* Obtain Pinmux value from pinctrl_soc_pin_t configuration.
|
||||
*
|
||||
* @param pincfg pinctrl_soc_pin_t bit field value.
|
||||
*/
|
||||
#define SAM_PINMUX_GET(pincfg) \
|
||||
(((pincfg) >> SAM_PINCTRL_PINMUX_POS) & SAM_PINCTRL_PINMUX_MASK)
|
||||
|
||||
#define SAM_PINMUX_PORT_GET(pincfg) \
|
||||
((SAM_PINMUX_GET(pincfg) >> SAM_PINMUX_PORT_POS) \
|
||||
& SAM_PINMUX_PORT_MSK)
|
||||
|
||||
#define SAM_PINMUX_PIN_GET(pincfg) \
|
||||
((SAM_PINMUX_GET(pincfg) >> SAM_PINMUX_PIN_POS) \
|
||||
& SAM_PINMUX_PIN_MSK)
|
||||
|
||||
#define SAM_PINMUX_FUNC_GET(pincfg) \
|
||||
((SAM_PINMUX_GET(pincfg) >> SAM_PINMUX_FUNC_POS) \
|
||||
& SAM_PINMUX_FUNC_MSK)
|
||||
|
||||
#define SAM_PINMUX_PERIPH_GET(pincfg) \
|
||||
((SAM_PINMUX_GET(pincfg) >> SAM_PINMUX_PERIPH_POS) \
|
||||
& SAM_PINMUX_PERIPH_MSK)
|
||||
|
||||
#endif /* DT_BINDINGS_PINCTRL_ATMEL_SAM_H_ */
|
|
@ -0,0 +1,22 @@
|
|||
# hal_atmel scripts
|
||||
|
||||
This folder contains `hal_atmel` scripts.
|
||||
|
||||
# Dependencies
|
||||
|
||||
Scripts require Python 3.6+ and the Python dependencies listed in
|
||||
`requirements.txt`. They can be installed by running:
|
||||
|
||||
```
|
||||
pip install -r scripts/requirements.txt
|
||||
```
|
||||
|
||||
# Lint
|
||||
|
||||
Scripts should be formatted using `black` and linted using `flake8`.
|
||||
|
||||
Such development tools can be installed using:
|
||||
|
||||
```
|
||||
pip install -r scripts/requirements-dev.txt
|
||||
```
|
|
@ -0,0 +1,2 @@
|
|||
flake8
|
||||
black
|
|
@ -0,0 +1,2 @@
|
|||
pyyaml
|
||||
natsort
|
|
@ -0,0 +1,264 @@
|
|||
# Copyright (c) 2021 Teslabs Engineering S.L.
|
||||
# Copyright (c) 2022 Gerson Fernando Budke
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
Utility to autogenerate pinctrl definitions.
|
||||
|
||||
Usage::
|
||||
python3 sampinctrl.py [-i /path/to/configs] [-o /path/to/include]
|
||||
"""
|
||||
|
||||
import argparse
|
||||
from collections import OrderedDict
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
from natsort import natsorted
|
||||
import yaml
|
||||
|
||||
|
||||
REPO_ROOT = Path(__file__).absolute().parents[1]
|
||||
"""Repository root."""
|
||||
|
||||
HEADER = """/*
|
||||
* Autogenerated file
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
"""
|
||||
"""Header for the generated files."""
|
||||
|
||||
EXCEPTION = """
|
||||
/*
|
||||
* WARNING: this variant has package exception.
|
||||
*
|
||||
* Read datasheet topics related to I/O Multiplexing and Considerations or
|
||||
* Peripheral Signal Multiplexing on I/O Lines for more information.
|
||||
*/
|
||||
"""
|
||||
|
||||
|
||||
def get_header_fname(serie, variant, revision):
|
||||
"""Get header file name.
|
||||
|
||||
Args:
|
||||
family: Atmel SAM family.
|
||||
serie: Series.
|
||||
variant: Variant information.
|
||||
|
||||
Returns:
|
||||
Header file name.
|
||||
"""
|
||||
|
||||
sufix = ""
|
||||
if revision:
|
||||
sufix = f"X{revision}"
|
||||
|
||||
return f"sam{serie}{variant}{sufix}-pinctrl.h"
|
||||
|
||||
|
||||
def get_port_pin(pin_name):
|
||||
"""Obtain port and pin number from a pin name
|
||||
|
||||
Args:
|
||||
pin_name: Pin name, e.g. PA0
|
||||
|
||||
Returns:
|
||||
Port and pin, e.g. A, 0.
|
||||
"""
|
||||
|
||||
m = re.match(r"P([A-Z])(\d+)", pin_name.upper())
|
||||
if not m:
|
||||
raise ValueError(f"Unexpected pin name: {pin_name}")
|
||||
|
||||
return m.group(1), str(int(m.group(2)))
|
||||
|
||||
|
||||
def write_gpio_function(f, port, pin_num, fmap, function):
|
||||
f.write(f"\n/* p{port.lower()}{pin_num}_{function.lower()} */\n")
|
||||
define = f"#define P{port.upper()}{pin_num.upper()}_{function.upper()}"
|
||||
define_val = f"{fmap}({port.lower()}, {pin_num}, {function.lower()}, " \
|
||||
f"{function.lower()})"
|
||||
f.write(f"{define} \\\n\t{define_val}\n")
|
||||
|
||||
|
||||
def write_periph_function(f, port, pin_num, pinmux, periph,
|
||||
signal, fmap, function):
|
||||
f.write(f"\n/* p{port.lower()}{pin_num}{pinmux}_{periph}_{signal} "
|
||||
f"*/\n")
|
||||
define = f"#define P{port.upper()}{pin_num.upper()}" \
|
||||
f"{pinmux.upper()}_{periph.upper()}_{signal.upper()}"
|
||||
define_val = f"{fmap}({port.lower()}, {pin_num}, " \
|
||||
f"{pinmux.lower()}, {function.lower()})"
|
||||
f.write(f"{define} \\\n\t{define_val}\n")
|
||||
|
||||
|
||||
def generate_atmel_sam_header(outdir, family, fmap, serie,
|
||||
variant, pin_cfgs, revision):
|
||||
"""Generate Atmel SAM header with pin configurations.
|
||||
|
||||
Args:
|
||||
outdir: Output base directory.
|
||||
family: Atmel SAM family.
|
||||
fmap: Function to map pinctrl.
|
||||
series: MCU Series.
|
||||
variant: Variant information.
|
||||
pin_cfgs: Pin configurations.
|
||||
"""
|
||||
|
||||
ofname = outdir / get_header_fname(serie, variant["pincode"], revision)
|
||||
with open(ofname, "w") as f:
|
||||
f.write(HEADER)
|
||||
f.write(f'\n{"#include <dt-bindings/pinctrl/atmel_sam_pinctrl.h>"}\n')
|
||||
|
||||
if len(variant) > 2:
|
||||
if variant["exception"]:
|
||||
f.write(EXCEPTION)
|
||||
|
||||
for port, pin_num, pinmux, periph, signal, function in pin_cfgs:
|
||||
if function in ["gpio", "lpm"]:
|
||||
write_gpio_function(f, port, pin_num, fmap, function)
|
||||
else:
|
||||
write_periph_function(f, port, pin_num, pinmux, periph,
|
||||
signal, fmap, function)
|
||||
|
||||
|
||||
def build_atmel_sam_gpio_sets(pin_cfgs, pin):
|
||||
"""Build Atmel SAM pin configurations sets.
|
||||
|
||||
Args:
|
||||
pins: Pins description.
|
||||
|
||||
Returns:
|
||||
Dictionary with pins configuration.
|
||||
"""
|
||||
|
||||
port, pin_num = get_port_pin(pin)
|
||||
new_item = (port, pin_num, "a", "gpio", "gpio", "gpio")
|
||||
|
||||
if new_item not in pin_cfgs:
|
||||
pin_cfgs.append(new_item)
|
||||
|
||||
|
||||
def build_atmel_sam_sets(pin_cfgs, pin, pin_lst, serie, variant, function):
|
||||
"""Build Atmel SAM pin configurations sets.
|
||||
|
||||
Args:
|
||||
serie: MCU Serie.
|
||||
variant: Variant information.
|
||||
pins: Pins description.
|
||||
|
||||
Returns:
|
||||
Dictionary with pins configuration.
|
||||
"""
|
||||
|
||||
if len(pin_lst[0]) > 0:
|
||||
for pinmux, periph, signal, *excludes in pin_lst:
|
||||
if len(excludes) > 0:
|
||||
if serie in excludes[0]:
|
||||
continue
|
||||
if variant["pincode"] in excludes[0]:
|
||||
continue
|
||||
|
||||
port, pin_num = get_port_pin(pin)
|
||||
|
||||
pin_cfgs.append((port, pin_num, pinmux, periph, signal, function))
|
||||
|
||||
|
||||
def build_atmel_sam_pin_cfgs(serie, variant, pins):
|
||||
"""Build Atmel SAM pin configurations.
|
||||
|
||||
Args:
|
||||
serie: MCU Serie.
|
||||
variant: Variant information.
|
||||
pins: Pins description.
|
||||
|
||||
Returns:
|
||||
Dictionary with pins configuration.
|
||||
"""
|
||||
|
||||
pin_cfgs = []
|
||||
|
||||
pins = OrderedDict(natsorted(pins.items(), key=lambda kv: kv[0]))
|
||||
|
||||
for pin, pin_cfg in pins.items():
|
||||
if variant["pincode"] not in pin_cfg["pincodes"]:
|
||||
continue
|
||||
|
||||
build_atmel_sam_gpio_sets(pin_cfgs, pin)
|
||||
|
||||
if "periph" in pin_cfg.keys():
|
||||
build_atmel_sam_sets(pin_cfgs, pin, pin_cfg["periph"],
|
||||
serie, variant, "periph")
|
||||
if "extra" in pin_cfg.keys():
|
||||
build_atmel_sam_sets(pin_cfgs, pin, pin_cfg["extra"],
|
||||
serie, variant, "extra")
|
||||
if "system" in pin_cfg.keys():
|
||||
build_atmel_sam_sets(pin_cfgs, pin, pin_cfg["system"],
|
||||
serie, variant, "system")
|
||||
if "lpm" in pin_cfg.keys():
|
||||
build_atmel_sam_sets(pin_cfgs, pin, pin_cfg["lpm"],
|
||||
serie, variant, "lpm")
|
||||
|
||||
return pin_cfgs
|
||||
|
||||
|
||||
def main(indir, outdir) -> None:
|
||||
"""Entry point.
|
||||
|
||||
Args:
|
||||
indir: Directory with pin configuration files.
|
||||
outdir: Output directory
|
||||
"""
|
||||
|
||||
if outdir.exists():
|
||||
for entry in outdir.glob("sam*-pinctrl.h"):
|
||||
entry.unlink()
|
||||
else:
|
||||
outdir.mkdir()
|
||||
|
||||
for entry in indir.iterdir():
|
||||
if not entry.is_file() or entry.suffix not in (".yml", ".yaml"):
|
||||
continue
|
||||
|
||||
config = yaml.load(open(entry), Loader=yaml.Loader)
|
||||
|
||||
model = config["model"]
|
||||
family = config["family"]
|
||||
fmap = config["map"]
|
||||
series = config["series"]
|
||||
variants = config["variants"]
|
||||
has_rev = "revisions" in config.keys()
|
||||
pins = config["pins"]
|
||||
|
||||
if model == "atmel,sam":
|
||||
for serie in series:
|
||||
for variant in [v for v in variants if serie in v["series"]]:
|
||||
pin_cfgs = build_atmel_sam_pin_cfgs(serie, variant, pins)
|
||||
rev = config["revisions"].get(serie) if has_rev else None
|
||||
generate_atmel_sam_header(outdir, family, fmap, serie,
|
||||
variant, pin_cfgs, rev)
|
||||
else:
|
||||
raise ValueError(f"Unexpected model: {model}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"-i",
|
||||
"--indir",
|
||||
type=Path,
|
||||
default=REPO_ROOT / "pinconfigs",
|
||||
help="Directory with pin configuration files",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-o",
|
||||
"--outdir",
|
||||
type=Path,
|
||||
default=REPO_ROOT / "include" / "dt-bindings" / "pinctrl",
|
||||
help="Output directory",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
main(args.indir, args.outdir)
|
|
@ -1,2 +1,4 @@
|
|||
build:
|
||||
cmake: .
|
||||
settings:
|
||||
dts_root: .
|
||||
|
|
Loading…
Reference in New Issue