diff --git a/drivers/debug/CMakeLists.txt b/drivers/debug/CMakeLists.txt index 8ab94991678..54ca9f71694 100644 --- a/drivers/debug/CMakeLists.txt +++ b/drivers/debug/CMakeLists.txt @@ -4,4 +4,5 @@ zephyr_library() # zephyr-keep-sorted-start +zephyr_library_sources_ifdef(CONFIG_DEBUG_SILABS_PTI debug_silabs_pti.c) # zephyr-keep-sorted-stop diff --git a/drivers/debug/Kconfig b/drivers/debug/Kconfig index 1b1b09daa08..68c23fdf124 100644 --- a/drivers/debug/Kconfig +++ b/drivers/debug/Kconfig @@ -15,6 +15,7 @@ config DEBUG_DRIVER_INIT_PRIORITY Debug drivers initialization priority. # zephyr-keep-sorted-start +source "drivers/debug/Kconfig.silabs" # zephyr-keep-sorted-stop module = DEBUG_DRIVER diff --git a/drivers/debug/Kconfig.silabs b/drivers/debug/Kconfig.silabs new file mode 100644 index 00000000000..bf3239f5b28 --- /dev/null +++ b/drivers/debug/Kconfig.silabs @@ -0,0 +1,12 @@ +# Copyright (c) 2025 Silicon Laboratories Inc. +# SPDX-License-Identifier: Apache-2.0 + +config DEBUG_SILABS_PTI + bool "Silicon Labs Packet Trace Interface" + default y + depends on DT_HAS_SILABS_PTI_ENABLED + depends on PINCTRL + depends on SOC_GECKO_USE_RAIL + help + Enable the Packet Trace Interface, providing a mechanism for viewing + transmitted and received radio packets for network sniffing or debugging. diff --git a/drivers/debug/debug_silabs_pti.c b/drivers/debug/debug_silabs_pti.c new file mode 100644 index 00000000000..3dbfab66932 --- /dev/null +++ b/drivers/debug/debug_silabs_pti.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2025 Silicon Laboratories Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include + +#define DT_DRV_COMPAT silabs_pti + +struct silabs_pti_config { + const struct pinctrl_dev_config *pcfg; + RAIL_PtiMode_t mode; + uint32_t baud; +}; + +int silabs_pti_init(const struct device *dev) +{ + const struct silabs_pti_config *config = dev->config; + const struct pinctrl_state *state; + RAIL_PtiConfig_t pti_config = { + .mode = config->mode, + .baud = config->baud, + }; + RAIL_Status_t status; + int err; + + /* The RAIL API to configure PTI requires GPIO port and pin as part of its configuration + * struct, and does the pin configuration itself internally. Create the configuration + * struct from the pinctrl node instead of using pinctrl_apply_state(). + */ + err = pinctrl_lookup_state(config->pcfg, PINCTRL_STATE_DEFAULT, &state); + if (err < 0) { + return err; + } + for (int i = 0; i < state->pin_cnt; i++) { + switch (state->pins[i].en_bit) { + case _GPIO_FRC_ROUTEEN_DCLKPEN_SHIFT: + pti_config.dclkPort = state->pins[i].port; + pti_config.dclkPin = state->pins[i].pin; + break; + case _GPIO_FRC_ROUTEEN_DFRAMEPEN_SHIFT: + pti_config.dframePort = state->pins[i].port; + pti_config.dframePin = state->pins[i].pin; + break; + case _GPIO_FRC_ROUTEEN_DOUTPEN_SHIFT: + pti_config.doutPort = state->pins[i].port; + pti_config.doutPin = state->pins[i].pin; + break; + default: + return -EINVAL; + } + } + status = RAIL_ConfigPti(RAIL_EFR32_HANDLE, &pti_config); + if (status != RAIL_STATUS_NO_ERROR) { + return -EIO; + } + + return 0; +} + +#define SILABS_PTI_INIT(idx) \ + PINCTRL_DT_INST_DEFINE(idx); \ + \ + static const struct silabs_pti_config silabs_pti_config_##idx = { \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx), \ + .mode = DT_INST_ENUM_IDX(idx, mode), \ + .baud = DT_INST_PROP(idx, clock_frequency), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(idx, &silabs_pti_init, NULL, NULL, &silabs_pti_config_##idx, \ + POST_KERNEL, CONFIG_DEBUG_DRIVER_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(SILABS_PTI_INIT)