scripts: utils: pinctrl_nrf_migrate: support more peripherals

Add support for more peripherals:

- I2C
- SPI (master mode assumed)
- PDM
- QDEC
- QSPI
- PWM
- I2S

Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
This commit is contained in:
Gerard Marull-Paretas 2022-03-16 16:04:49 +01:00 committed by Carles Cufí
parent c1ad91405d
commit 8b91cb0cd4

View file

@ -20,6 +20,8 @@ partially ported.
Devicetree files will be converted correctly. **ADJUSTED/GENERATED FILES
MUST BE MANUALLY REVIEWED**.
Known limitations: All SPI nodes will be assumed to be a master device.
Usage::
python3 pinctrl_nrf_migrate.py
@ -95,17 +97,24 @@ class PIN_CONFIG(enum.Enum):
PULL_UP = "bias-pull-up"
PULL_DOWN = "bias-pull-down"
LOW_POWER = "low-power-enable"
NORDIC_INVERT = "nordic,invert"
class Device(object):
"""Device configuration class"""
def __init__(
self, pattern: str, callback: Callable, signals: Dict[str, str]
self,
pattern: str,
callback: Callable,
signals: Dict[str, str],
needs_sleep: bool,
) -> None:
self.pattern = pattern
self.callback = callback
self.signals = signals
self.needs_sleep = needs_sleep
self.attrs = {}
class SignalMapping(object):
@ -272,7 +281,7 @@ def fmt_pinctrl_groups(groups: List[PinGroup]) -> str:
# write psels entries
for i, mapping in enumerate(group.pins):
prefix = "psels = " if i == 0 else " "
prefix = "psels = " if i == 0 else "\t"
suffix = ";" if i == len(group.pins) - 1 else ","
pin = mapping.pin
port = 0 if pin < 32 else 1
@ -291,17 +300,19 @@ def fmt_pinctrl_groups(groups: List[PinGroup]) -> str:
return content
def fmt_states(device: str, indent: str) -> str:
def fmt_states(device: str, indent: str, needs_sleep: bool) -> str:
"""Format state entries for the given device.
Args:
device: Device name.
indent: Indentation.
needs_sleep: If sleep entry is needed.
Returns:
State entries to be appended to the device.
"""
if needs_sleep:
return "\n".join(
(
f"{indent}pinctrl-0 = <&{device}_default>;",
@ -309,6 +320,13 @@ def fmt_states(device: str, indent: str) -> str:
f'{indent}pinctrl-names = "default", "sleep";\n',
)
)
else:
return "\n".join(
(
f"{indent}pinctrl-0 = <&{device}_default>;",
f'{indent}pinctrl-names = "default";\n',
)
)
def insert_pinctrl_include(content: List[str], board: str) -> None:
@ -365,6 +383,7 @@ def adjust_content(content: List[str], board: str) -> List[DeviceConfiguration]:
configs: List[DeviceConfiguration] = []
level = 0
in_device = False
states_written = False
new_content = []
@ -384,10 +403,11 @@ def adjust_content(content: List[str], board: str) -> List[DeviceConfiguration]:
break
# we are now inside a device node
in_device = True
level = 1
in_device = True
states_written = False
else:
# entering subnode
# entering subnode (must come after all properties)
if re.match(r"[^\/\*]*{.*", line):
level += 1
# exiting subnode (or device node)
@ -407,10 +427,14 @@ def adjust_content(content: List[str], board: str) -> List[DeviceConfiguration]:
# process each device line, append states at the end
if current_device:
if in_device:
if level == 1:
line = current_device.callback(config, current_device.signals, line)
else:
line = fmt_states(config.name, indent) + line
if (level == 2 or not in_device) and not states_written:
line = (
fmt_states(config.name, indent, current_device.needs_sleep)
+ line
)
states_written = True
current_device = None
if line:
@ -431,7 +455,7 @@ def adjust_content(content: List[str], board: str) -> List[DeviceConfiguration]:
def match_and_store_pin(
config: DeviceConfiguration, signals: Dict[str, str], line: str
) -> bool:
) -> Optional[str]:
"""Match and store a pin mapping.
Args:
@ -440,15 +464,23 @@ def match_and_store_pin(
line: Line containing potential pin mapping.
Returns:
True if line contains a pin mapping, False otherwise.
Line if found a pin mapping, None otherwise.
"""
m = re.match(r"\s*([a-z]+)-pin\s*=\s*<(\d+)>.*", line)
# handle qspi special case for io-pins (array case)
m = re.match(r"\s*io-pins\s*=\s*([\s<>,0-9]+).*", line)
if m:
pins = re.sub(r"[<>,]", "", m.group(1)).split()
for i, pin in enumerate(pins):
config.set_signal_pin(signals[f"io{i}"], int(pin))
return
m = re.match(r"\s*([a-z]+\d?)-pins?\s*=\s*<(\d+)>.*", line)
if m:
config.set_signal_pin(signals[m.group(1)], int(m.group(2)))
return True
return
return False
return line
#
@ -460,14 +492,52 @@ def process_uart(config: DeviceConfiguration, signals, line: str) -> Optional[st
"""Process UART/UARTE devices."""
# check if line specifies a pin
if match_and_store_pin(config, signals, line):
return None
if not match_and_store_pin(config, signals, line):
return
# check if pull-up is specified
m = re.match(r"\s*([a-z]+)-pull-up.*", line)
if m:
config.add_signal_config(signals[m.group(1)], PIN_CONFIG.PULL_UP)
return None
return
return line
def process_spi(config: DeviceConfiguration, signals, line: str) -> Optional[str]:
"""Process SPI devices."""
# check if line specifies a pin
if not match_and_store_pin(config, signals, line):
return
# check if pull-up is specified
m = re.match(r"\s*miso-pull-up.*", line)
if m:
config.add_signal_config(signals["miso"], PIN_CONFIG.PULL_UP)
return
# check if pull-down is specified
m = re.match(r"\s*miso-pull-down.*", line)
if m:
config.add_signal_config(signals["miso"], PIN_CONFIG.PULL_DOWN)
return
return line
def process_pwm(config: DeviceConfiguration, signals, line: str) -> Optional[str]:
"""Process PWM devices."""
# check if line specifies a pin
if not match_and_store_pin(config, signals, line):
return
# check if channel inversion is specified
m = re.match(r"\s*([a-z0-9]+)-inverted.*", line)
if m:
config.add_signal_config(signals[m.group(1)], PIN_CONFIG.NORDIC_INVERT)
return
return line
@ -482,6 +552,81 @@ DEVICES = [
"rts": "UART_RTS",
"cts": "UART_CTS",
},
needs_sleep=True,
),
Device(
r"i2c\d",
match_and_store_pin,
{
"sda": "TWIM_SDA",
"scl": "TWIM_SCL",
},
needs_sleep=True,
),
Device(
r"spi\d",
process_spi,
{
"sck": "SPIM_SCK",
"miso": "SPIM_MISO",
"mosi": "SPIM_MOSI",
},
needs_sleep=True,
),
Device(
r"pdm\d",
match_and_store_pin,
{
"clk": "PDM_CLK",
"din": "PDM_DIN",
},
needs_sleep=False,
),
Device(
r"qdec",
match_and_store_pin,
{
"a": "QDEC_A",
"b": "QDEC_B",
"led": "QDEC_LED",
},
needs_sleep=True,
),
Device(
r"qspi",
match_and_store_pin,
{
"sck": "QSPI_SCK",
"io0": "QSPI_IO0",
"io1": "QSPI_IO1",
"io2": "QSPI_IO2",
"io3": "QSPI_IO3",
"csn": "QSPI_CSN",
},
needs_sleep=True,
),
Device(
r"pwm\d",
process_pwm,
{
"ch0": "PWM_OUT0",
"ch1": "PWM_OUT1",
"ch2": "PWM_OUT2",
"ch3": "PWM_OUT3",
},
needs_sleep=True,
),
Device(
r"i2s\d",
match_and_store_pin,
{
"sck": "I2S_SCK_M",
"lrck": "I2S_LRCK_M",
"sdout": "I2S_SDOUT",
"sdin": "I2S_SDIN",
"mck": "I2S_MCK",
},
needs_sleep=False,
),
]
"""Supported devices and associated configuration"""
@ -533,10 +678,7 @@ if __name__ == "__main__":
help="Skip checking if board is nRF-based",
)
parser.add_argument(
"--header",
default="",
type=str,
help="Header to be prepended to pinctrl files"
"--header", default="", type=str, help="Header to be prepended to pinctrl files"
)
args = parser.parse_args()