diff --git a/drivers/watchdog/Kconfig.nxp_fs26 b/drivers/watchdog/Kconfig.nxp_fs26 index 933cd96530f..231f692f710 100644 --- a/drivers/watchdog/Kconfig.nxp_fs26 +++ b/drivers/watchdog/Kconfig.nxp_fs26 @@ -73,4 +73,19 @@ config WDT_NXP_FS26_INT_THREAD_PRIO Priority level for internal cooperative thread which is ran for interrupt processing. +config WDT_NXP_FS26_SPI_8BIT_TRANSFER + bool "Use 8-bit SPI transfer mode for FS26" + default y if SPI_RTIO + help + Enable this to force the FS26 driver to use 8-bit SPI transfers + instead of the default 32-bit transfers. + + This is required when using SPI controllers that do not support + 32-bit word sizes (e.g. SPI_RTIO), or when an application requires + strictly byte-sized transfers. + + When disabled, the FS26 driver will continue to use 32-bit SPI + transfers as defined by the original implementation. + + endif # WDT_NXP_FS26 diff --git a/drivers/watchdog/wdt_nxp_fs26.c b/drivers/watchdog/wdt_nxp_fs26.c index 26ffca172e7..ff2dda49828 100644 --- a/drivers/watchdog/wdt_nxp_fs26.c +++ b/drivers/watchdog/wdt_nxp_fs26.c @@ -1,5 +1,5 @@ /* - * Copyright 2023 NXP + * Copyright 2023, 2026 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,10 +17,16 @@ LOG_MODULE_REGISTER(wdt_nxp_fs26); #include "wdt_nxp_fs26.h" -#if defined(CONFIG_BIG_ENDIAN) +#if defined(CONFIG_BIG_ENDIAN) || defined(CONFIG_WDT_NXP_FS26_SPI_8BIT_TRANSFER) #define SWAP_ENDIANNESS #endif +#ifdef CONFIG_WDT_NXP_FS26_SPI_8BIT_TRANSFER +#define FS26_SPI_TRANSFER_WIDTH 8 +#else +#define FS26_SPI_TRANSFER_WIDTH 32 +#endif + #define FS26_CRC_TABLE_SIZE 256U #define FS26_CRC_INIT 0xff #define FS26_FS_WD_TOKEN_DEFAULT 0x5ab2 @@ -279,7 +285,6 @@ static int fs26_wd_refresh(const struct device *dev) const struct wdt_nxp_fs26_config *config = dev->config; struct wdt_nxp_fs26_data *data = dev->data; int retval = 0; - int key; uint16_t answer; struct fs26_spi_rx_frame rx_frame; @@ -289,8 +294,6 @@ static int fs26_wd_refresh(const struct device *dev) retval = -EIO; } } else if (config->wd_type == FS26_WD_CHALLENGER) { - key = irq_lock(); - /* Read challenge token generated by the device */ if (fs26_getreg(&config->spi, FS26_FS_WD_TOKEN, &rx_frame)) { LOG_ERR("Failed to obtain watchdog token"); @@ -305,8 +308,6 @@ static int fs26_wd_refresh(const struct device *dev) retval = -EIO; } } - - irq_unlock(key); } else { retval = -EINVAL; } @@ -632,44 +633,13 @@ static int wdt_nxp_fs26_init(const struct device *dev) struct wdt_nxp_fs26_data *data = dev->data; struct fs26_spi_rx_frame rx_frame; uint32_t regval; + int ret; /* Validate bus is ready */ if (!spi_is_ready_dt(&config->spi)) { return -ENODEV; } - k_sem_init(&data->int_sem, 0, 1); - - /* Configure GPIO used for INTB signal */ - if (!gpio_is_ready_dt(&config->int_gpio)) { - LOG_ERR("GPIO port %s not ready", config->int_gpio.port->name); - return -ENODEV; - } - - if (gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT)) { - LOG_ERR("Unable to configure GPIO pin %u", config->int_gpio.pin); - return -EIO; - } - - gpio_init_callback(&(data->int_gpio_cb), wdt_nxp_fs26_int_callback, - BIT(config->int_gpio.pin)); - - if (gpio_add_callback(config->int_gpio.port, &(data->int_gpio_cb))) { - return -EINVAL; - } - - if (gpio_pin_interrupt_configure_dt(&config->int_gpio, - GPIO_INT_EDGE_FALLING)) { - return -EINVAL; - } - - k_thread_create(&data->int_thread, data->int_thread_stack, - CONFIG_WDT_NXP_FS26_INT_THREAD_STACK_SIZE, - wdt_nxp_fs26_int_thread, - (void *)dev, NULL, NULL, - K_PRIO_COOP(CONFIG_WDT_NXP_FS26_INT_THREAD_PRIO), - 0, K_NO_WAIT); - /* Verify FS BIST before proceeding */ if (fs26_getreg(&config->spi, FS26_FS_DIAG_SAFETY1, &rx_frame)) { return -EIO; @@ -801,6 +771,43 @@ static int wdt_nxp_fs26_init(const struct device *dev) } } + k_sem_init(&data->int_sem, 0, 1); + + /* Configure GPIO used for INTB signal */ + if (!gpio_is_ready_dt(&config->int_gpio)) { + LOG_ERR("GPIO port %s not ready", config->int_gpio.port->name); + return -ENODEV; + } + + if (gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT)) { + LOG_ERR("Unable to configure GPIO pin %u", config->int_gpio.pin); + return -EIO; + } + + gpio_init_callback(&(data->int_gpio_cb), wdt_nxp_fs26_int_callback, + BIT(config->int_gpio.pin)); + + ret = gpio_add_callback(config->int_gpio.port, &(data->int_gpio_cb)); + + if (ret) { + LOG_ERR("Failed to add GPIO callback: %d\n", ret); + return ret; + } + + ret = gpio_pin_interrupt_configure_dt(&config->int_gpio, GPIO_INT_EDGE_FALLING); + + if (ret) { + LOG_ERR("Failed to configure GPIO interrupt: %d", ret); + return ret; + } + + k_tid_t tid = k_thread_create( + &data->int_thread, data->int_thread_stack, + CONFIG_WDT_NXP_FS26_INT_THREAD_STACK_SIZE, wdt_nxp_fs26_int_thread, (void *)dev, + NULL, NULL, K_PRIO_COOP(CONFIG_WDT_NXP_FS26_INT_THREAD_PRIO), 0, K_NO_WAIT); + + k_thread_name_set(tid, "wdt_nxp_fs26"); + return 0; } @@ -824,8 +831,8 @@ static DEVICE_API(wdt, wdt_nxp_fs26_api) = { }; \ \ static const struct wdt_nxp_fs26_config wdt_nxp_fs26_config_##n = { \ - .spi = SPI_DT_SPEC_INST_GET(n, \ - SPI_OP_MODE_MASTER | SPI_MODE_CPHA | SPI_WORD_SET(32)), \ + .spi = SPI_DT_SPEC_INST_GET(n, SPI_OP_MODE_MASTER | SPI_MODE_CPHA | \ + SPI_WORD_SET(FS26_SPI_TRANSFER_WIDTH)), \ .wd_type = _CONCAT(FS26_WD_, DT_INST_STRING_UPPER_TOKEN(n, type)), \ .int_gpio = GPIO_DT_SPEC_INST_GET(n, int_gpios), \ }; \