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 Devicetree files will be converted correctly. **ADJUSTED/GENERATED FILES
MUST BE MANUALLY REVIEWED**. MUST BE MANUALLY REVIEWED**.
Known limitations: All SPI nodes will be assumed to be a master device.
Usage:: Usage::
python3 pinctrl_nrf_migrate.py python3 pinctrl_nrf_migrate.py
@ -95,17 +97,24 @@ class PIN_CONFIG(enum.Enum):
PULL_UP = "bias-pull-up" PULL_UP = "bias-pull-up"
PULL_DOWN = "bias-pull-down" PULL_DOWN = "bias-pull-down"
LOW_POWER = "low-power-enable" LOW_POWER = "low-power-enable"
NORDIC_INVERT = "nordic,invert"
class Device(object): class Device(object):
"""Device configuration class""" """Device configuration class"""
def __init__( def __init__(
self, pattern: str, callback: Callable, signals: Dict[str, str] self,
pattern: str,
callback: Callable,
signals: Dict[str, str],
needs_sleep: bool,
) -> None: ) -> None:
self.pattern = pattern self.pattern = pattern
self.callback = callback self.callback = callback
self.signals = signals self.signals = signals
self.needs_sleep = needs_sleep
self.attrs = {}
class SignalMapping(object): class SignalMapping(object):
@ -272,7 +281,7 @@ def fmt_pinctrl_groups(groups: List[PinGroup]) -> str:
# write psels entries # write psels entries
for i, mapping in enumerate(group.pins): 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 "," suffix = ";" if i == len(group.pins) - 1 else ","
pin = mapping.pin pin = mapping.pin
port = 0 if pin < 32 else 1 port = 0 if pin < 32 else 1
@ -291,24 +300,33 @@ def fmt_pinctrl_groups(groups: List[PinGroup]) -> str:
return content 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. """Format state entries for the given device.
Args: Args:
device: Device name. device: Device name.
indent: Indentation. indent: Indentation.
needs_sleep: If sleep entry is needed.
Returns: Returns:
State entries to be appended to the device. State entries to be appended to the device.
""" """
return "\n".join( if needs_sleep:
( return "\n".join(
f"{indent}pinctrl-0 = <&{device}_default>;", (
f"{indent}pinctrl-1 = <&{device}_sleep>;", f"{indent}pinctrl-0 = <&{device}_default>;",
f'{indent}pinctrl-names = "default", "sleep";\n', f"{indent}pinctrl-1 = <&{device}_sleep>;",
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: 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] = [] configs: List[DeviceConfiguration] = []
level = 0 level = 0
in_device = False in_device = False
states_written = False
new_content = [] new_content = []
@ -384,10 +403,11 @@ def adjust_content(content: List[str], board: str) -> List[DeviceConfiguration]:
break break
# we are now inside a device node # we are now inside a device node
in_device = True
level = 1 level = 1
in_device = True
states_written = False
else: else:
# entering subnode # entering subnode (must come after all properties)
if re.match(r"[^\/\*]*{.*", line): if re.match(r"[^\/\*]*{.*", line):
level += 1 level += 1
# exiting subnode (or device node) # 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 # process each device line, append states at the end
if current_device: if current_device:
if in_device: if level == 1:
line = current_device.callback(config, current_device.signals, line) line = current_device.callback(config, current_device.signals, line)
else: if (level == 2 or not in_device) and not states_written:
line = fmt_states(config.name, indent) + line line = (
fmt_states(config.name, indent, current_device.needs_sleep)
+ line
)
states_written = True
current_device = None current_device = None
if line: if line:
@ -431,7 +455,7 @@ def adjust_content(content: List[str], board: str) -> List[DeviceConfiguration]:
def match_and_store_pin( def match_and_store_pin(
config: DeviceConfiguration, signals: Dict[str, str], line: str config: DeviceConfiguration, signals: Dict[str, str], line: str
) -> bool: ) -> Optional[str]:
"""Match and store a pin mapping. """Match and store a pin mapping.
Args: Args:
@ -440,15 +464,23 @@ def match_and_store_pin(
line: Line containing potential pin mapping. line: Line containing potential pin mapping.
Returns: 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: if m:
config.set_signal_pin(signals[m.group(1)], int(m.group(2))) 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.""" """Process UART/UARTE devices."""
# check if line specifies a pin # check if line specifies a pin
if match_and_store_pin(config, signals, line): if not match_and_store_pin(config, signals, line):
return None return
# check if pull-up is specified # check if pull-up is specified
m = re.match(r"\s*([a-z]+)-pull-up.*", line) m = re.match(r"\s*([a-z]+)-pull-up.*", line)
if m: if m:
config.add_signal_config(signals[m.group(1)], PIN_CONFIG.PULL_UP) 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 return line
@ -482,6 +552,81 @@ DEVICES = [
"rts": "UART_RTS", "rts": "UART_RTS",
"cts": "UART_CTS", "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""" """Supported devices and associated configuration"""
@ -533,10 +678,7 @@ if __name__ == "__main__":
help="Skip checking if board is nRF-based", help="Skip checking if board is nRF-based",
) )
parser.add_argument( parser.add_argument(
"--header", "--header", default="", type=str, help="Header to be prepended to pinctrl files"
default="",
type=str,
help="Header to be prepended to pinctrl files"
) )
args = parser.parse_args() args = parser.parse_args()