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:
parent
c1ad91405d
commit
8b91cb0cd4
|
@ -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()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue