From 540983c6b799478fc77af42946a83be7c8b755ba Mon Sep 17 00:00:00 2001 From: Sai Santhosh Malae Date: Sat, 22 Nov 2025 22:02:55 +0530 Subject: [PATCH 01/13] drivers: clock_control: siwx91x: Set INTF_PLL_FREQUENCY to 160 MHz The GSPI and QSPI peripherals run on the interface PLL clock. To ensure correct operation, the interface PLL frequency should be set to 160 MHz. This provides a base clock of 80 MHz to the QSPI peripheral, which matches its required operating frequency. The GSPI peripheral can continue to operate at higher frequencies as it receives the full interface PLL clock. Signed-off-by: Sai Santhosh Malae (cherry picked from commit cbb2fda8d204224b00ce49183a7bc82221e7f3c3) Upstream-status: available --- drivers/clock_control/clock_control_silabs_siwx91x.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/clock_control/clock_control_silabs_siwx91x.c b/drivers/clock_control/clock_control_silabs_siwx91x.c index 12e641a33a398..76ab36e922b4f 100644 --- a/drivers/clock_control/clock_control_silabs_siwx91x.c +++ b/drivers/clock_control/clock_control_silabs_siwx91x.c @@ -21,6 +21,7 @@ #define DT_DRV_COMPAT silabs_siwx91x_clock #define LF_FSM_CLOCK_FREQUENCY 32768 #define XTAL_FREQUENCY 40000000 +#define INTF_PLL_FREQUENCY 160000000 LOG_MODULE_REGISTER(siwx91x_clock, CONFIG_CLOCK_CONTROL_LOG_LEVEL); @@ -184,7 +185,7 @@ static int siwx91x_clock_get_rate(const struct device *dev, clock_control_subsys *rate = LF_FSM_CLOCK_FREQUENCY; return 0; case SIWX91X_CLK_GSPI: - *rate = RSI_CLK_GetBaseClock(M4_GSPI); + *rate = INTF_PLL_FREQUENCY; return 0; default: /* For now, no other driver need clock rate */ @@ -249,9 +250,7 @@ static int siwx91x_clock_init(const struct device *dev) DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency)); /* Use interface PLL at configured frequency as peripheral clock */ - sl_si91x_clock_manager_set_pll_freq(INFT_PLL, - DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency), - PLL_REF_CLK_VAL_XTAL); + sl_si91x_clock_manager_set_pll_freq(INFT_PLL, INTF_PLL_FREQUENCY, PLL_REF_CLK_VAL_XTAL); /* FIXME: Currently the clock consumer use clocks without power on them. * This should be fixed in drivers. Meanwhile, get the list of required From 660e8ed5b2f58b6de7bae9c3eded854cbb4076d8 Mon Sep 17 00:00:00 2001 From: Sai Santhosh Malae Date: Sat, 22 Nov 2025 22:20:15 +0530 Subject: [PATCH 02/13] drivers: spi: siwx91x: Add helper to round GSPI freq to valid range Add gspi_siwx91x_pick_lower_freq() to select the nearest lower supported GSPI clock frequency based on the requested value. The GSPI clock can operate only at discrete frequencies such as 80 MHz, 40 MHz, 26.6 MHz, 20 MHz, and so on (80 MHz divided by integer factors). If the requested frequency does not match one of these valid steps, it is rounded down to the nearest lower supported frequency. The driver now logs both the requested and the actual programmed frequency along with the divider value, helping users verify the effective SPI clock configuration. Signed-off-by: Sai Santhosh Malae (cherry picked from commit 23c8db4f8c3e967f63320605e861b59ace0e17f3) Upstream-status: available --- drivers/spi/spi_silabs_siwx91x_gspi.c | 32 ++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi_silabs_siwx91x_gspi.c b/drivers/spi/spi_silabs_siwx91x_gspi.c index 8d0984fe55d0d..8572baf9b2b6a 100644 --- a/drivers/spi/spi_silabs_siwx91x_gspi.c +++ b/drivers/spi/spi_silabs_siwx91x_gspi.c @@ -76,6 +76,29 @@ static bool spi_siwx91x_is_dma_enabled_instance(const struct device *dev) #endif } +void gspi_siwx91x_pick_lower_freq(uint32_t clock_hz, uint32_t requested_hz, uint32_t *actual_hz_out, + uint32_t *div_out) +{ + /* Calculate divider that ensures freq <= requested */ + uint32_t divider = DIV_ROUND_UP(clock_hz, 2 * requested_hz); + uint32_t actual_hz; + + if (divider == 0U) { + divider = 1U; + } + + /* Compute the actual achievable frequency */ + actual_hz = clock_hz / (2U * divider); + + if (actual_hz_out) { + *actual_hz_out = actual_hz; + } + + if (div_out) { + *div_out = divider; + } +} + static int gspi_siwx91x_config(const struct device *dev, const struct spi_config *spi_cfg, spi_callback_t cb, void *userdata) { @@ -83,6 +106,7 @@ static int gspi_siwx91x_config(const struct device *dev, const struct spi_config const struct gspi_siwx91x_config *cfg = dev->config; uint32_t bit_rate = spi_cfg->frequency; uint32_t clk_div_factor; + uint32_t actual_freq; uint32_t clock_rate; int ret; __maybe_unused int channel_filter; @@ -119,7 +143,13 @@ static int gspi_siwx91x_config(const struct device *dev, const struct spi_config if (ret) { return ret; } - clk_div_factor = ((clock_rate / spi_cfg->frequency) / 2); + + gspi_siwx91x_pick_lower_freq(clock_rate, spi_cfg->frequency, &actual_freq, + &clk_div_factor); + if (spi_cfg->frequency != actual_freq) { + LOG_INF("Requested %u Hz, programmed %u Hz (divider=%u)", + spi_cfg->frequency, actual_freq, clk_div_factor); + } } if (clk_div_factor < 1) { From 5f24a8a1dd814c5666904baaa8e19f91fd5c5cb4 Mon Sep 17 00:00:00 2001 From: Sai Santhosh Malae Date: Sun, 23 Nov 2025 16:57:49 +0530 Subject: [PATCH 03/13] drivers: spi: siwx91x: Add support for higher burst rates using GPDMA Enable higher SPI burst sizes when using GPDMA to improve throughput. Bursts are only enabled when both TX and RX channels use GPDMA and the SPI clock frequency is at least 10 MHz, as DMA flow control is unreliable at lower SPI rates. Signed-off-by: Sai Santhosh Malae (cherry picked from commit 9ebba6821b42734a935fa9f57c9d3dd3ebf6ac57) Upstream-status: available --- drivers/spi/spi_silabs_siwx91x_gspi.c | 76 +++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 9 deletions(-) diff --git a/drivers/spi/spi_silabs_siwx91x_gspi.c b/drivers/spi/spi_silabs_siwx91x_gspi.c index 8572baf9b2b6a..0da4393f071b8 100644 --- a/drivers/spi/spi_silabs_siwx91x_gspi.c +++ b/drivers/spi/spi_silabs_siwx91x_gspi.c @@ -27,6 +27,7 @@ LOG_MODULE_REGISTER(spi_siwx91x_gspi, CONFIG_SPI_LOG_LEVEL); #define GSPI_MAX_BAUDRATE_FOR_DYNAMIC_CLOCK 110000000 #define GSPI_MAX_BAUDRATE_FOR_POS_EDGE_SAMPLE 40000000 #define GSPI_DMA_MAX_DESCRIPTOR_TRANSFER_SIZE 4096 +#define SPI_HIGH_BURST_FREQ_THRESHOLD_HZ 10000000 /* Warning for unsupported configurations */ #if defined(CONFIG_SPI_ASYNC) && !defined(CONFIG_SPI_SILABS_SIWX91X_GSPI_DMA) @@ -247,7 +248,7 @@ static void gspi_siwx91x_dma_tx_callback(const struct device *dev, void *user_da static int gspi_siwx91x_dma_config(const struct device *dev, struct gspi_siwx91x_dma_channel *channel, uint32_t block_count, - bool is_tx, uint8_t dfs) + bool is_tx, uint8_t dfs, uint8_t burst_size) { struct dma_config cfg = { .channel_direction = is_tx ? MEMORY_TO_PERIPHERAL : PERIPHERAL_TO_MEMORY, @@ -255,8 +256,8 @@ static int gspi_siwx91x_dma_config(const struct device *dev, .complete_callback_en = 0, .source_data_size = dfs, .dest_data_size = dfs, - .source_burst_length = 1, - .dest_burst_length = 1, + .source_burst_length = burst_size, + .dest_burst_length = burst_size, .block_count = block_count, .head_block = channel->dma_descriptors, .dma_slot = channel->dma_slot, @@ -374,7 +375,8 @@ static void gspi_siwx91x_reset_desc(struct gspi_siwx91x_dma_channel *channel) static int gspi_siwx91x_prepare_dma_channel(const struct device *spi_dev, const struct spi_buf *buffer, size_t buffer_count, struct gspi_siwx91x_dma_channel *channel, - size_t padded_transaction_size, bool is_tx) + size_t padded_transaction_size, bool is_tx, + uint8_t burst_size) { const struct gspi_siwx91x_config *cfg = spi_dev->config; struct gspi_siwx91x_data *data = spi_dev->data; @@ -391,12 +393,13 @@ static int gspi_siwx91x_prepare_dma_channel(const struct device *spi_dev, } ret = gspi_siwx91x_dma_config(spi_dev, channel, - ARRAY_INDEX(channel->dma_descriptors, desc) + 1, is_tx, dfs); + ARRAY_INDEX(channel->dma_descriptors, desc) + 1, is_tx, dfs, + burst_size); return ret; } static int gspi_siwx91x_prepare_dma_transaction(const struct device *dev, - size_t padded_transaction_size) + size_t padded_transaction_size, uint8_t burst_size) { int ret; struct gspi_siwx91x_data *data = dev->data; @@ -406,13 +409,15 @@ static int gspi_siwx91x_prepare_dma_transaction(const struct device *dev, } ret = gspi_siwx91x_prepare_dma_channel(dev, data->ctx.current_tx, data->ctx.tx_count, - &data->dma_tx, padded_transaction_size, true); + &data->dma_tx, padded_transaction_size, true, + burst_size); if (ret) { return ret; } ret = gspi_siwx91x_prepare_dma_channel(dev, data->ctx.current_rx, data->ctx.rx_count, - &data->dma_rx, padded_transaction_size, false); + &data->dma_rx, padded_transaction_size, false, + burst_size); return ret; } @@ -425,6 +430,34 @@ static size_t gspi_siwx91x_longest_transfer_size(struct spi_context *instance_ct return MAX(tx_transfer_size, rx_transfer_size); } +static int gspi_siwx91x_burst_size_buf(const struct spi_buf *dma_spi_buf) +{ + int burst_len = 4; + + if (!dma_spi_buf->buf || !dma_spi_buf->len) { + return burst_len; + } + + burst_len = MIN(burst_len, BIT(find_lsb_set((uint32_t)dma_spi_buf->buf) - 1)); + burst_len = MIN(burst_len, BIT(find_lsb_set(dma_spi_buf->len) - 1)); + + return burst_len; +} + +static int gspi_siwx91x_burst_size(struct spi_context *ctx) +{ + int burst_len = 4; + + for (int i = 0; i < ctx->tx_count; i++) { + burst_len = MIN(burst_len, gspi_siwx91x_burst_size_buf(ctx->current_tx + i)); + } + + for (int i = 0; i < ctx->rx_count; i++) { + burst_len = MIN(burst_len, gspi_siwx91x_burst_size_buf(ctx->current_rx + i)); + } + + return burst_len; +} #endif /* CONFIG_SPI_SILABS_SIWX91X_GSPI_DMA */ static int gspi_siwx91x_transceive_dma(const struct device *dev, const struct spi_config *config) @@ -435,17 +468,42 @@ static int gspi_siwx91x_transceive_dma(const struct device *dev, const struct sp const struct device *dma_dev = data->dma_rx.dma_dev; struct spi_context *ctx = &data->ctx; size_t padded_transaction_size = gspi_siwx91x_longest_transfer_size(ctx); + uint8_t burst_size = 1; int ret = 0; if (padded_transaction_size == 0) { return -EINVAL; } + if (config->frequency >= SPI_HIGH_BURST_FREQ_THRESHOLD_HZ && + data->dma_rx.dma_slot != 0xFF && data->dma_tx.dma_slot != 0xFF) { + /* NOTE: This condition ensures that high burst rates are only used with GPDMA. + * + * GPDMA (General-Purpose DMA) supports higher burst rates and operates at higher + * frequencies, unlike UDMA, which does not handle such speeds reliably. + * Therefore, the DMA slots are validated to ensure that the active DMA channels + * belong to GPDMA before enabling higher burst rates. + * + * Currently, DMA flow control (DMA_FLOW_CTRL) is not functioning correctly for + * memory-to-peripheral and peripheral-to-memory transfers. As a result, at lower + * SPI clock frequencies, GPDMA may read/write FIFOs at a much higher rate than the + * SPI peripheral, causing synchronization issues. However, at higher SPI clock + * frequencies (≥ 10 MHz), this timing mismatch is negligible, and higher burst + * rates operate as expected. + * + * In summary, high burst rates are safely enabled only for SPI transfers running + * at or above 10 MHz when using GPDMA. + */ + burst_size = gspi_siwx91x_burst_size(ctx); + } + cfg->reg->GSPI_FIFO_THRLD_b.RFIFO_RESET = 1; cfg->reg->GSPI_FIFO_THRLD_b.WFIFO_RESET = 1; cfg->reg->GSPI_FIFO_THRLD = 0; + cfg->reg->GSPI_FIFO_THRLD_b.FIFO_AEMPTY_THRLD = burst_size - 1; + cfg->reg->GSPI_FIFO_THRLD_b.FIFO_AFULL_THRLD = burst_size - 1; - ret = gspi_siwx91x_prepare_dma_transaction(dev, padded_transaction_size); + ret = gspi_siwx91x_prepare_dma_transaction(dev, padded_transaction_size, burst_size); if (ret) { return ret; } From 953859c89b522f4ad5905f1d071952aaeea9784c Mon Sep 17 00:00:00 2001 From: Sai Santhosh Malae Date: Sat, 29 Nov 2025 18:17:26 +0530 Subject: [PATCH 04/13] drivers: spi: siwx91x: Align mosi_overrun to 32 bytes Updated mosi_overrun alignment from 4 bytes to 32 bytes to ensure compatibility with the GPDMA driver. This prevents alignment-related errors during DMA transfers. Signed-off-by: Sai Santhosh Malae (cherry picked from commit b6cef6fbf6091f394359d885bca9f90c4025bfc6) Upstream-status: available --- drivers/spi/spi_silabs_siwx91x_gspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi_silabs_siwx91x_gspi.c b/drivers/spi/spi_silabs_siwx91x_gspi.c index 0da4393f071b8..a530656e14e4c 100644 --- a/drivers/spi/spi_silabs_siwx91x_gspi.c +++ b/drivers/spi/spi_silabs_siwx91x_gspi.c @@ -49,7 +49,7 @@ struct gspi_siwx91x_config { const struct device *clock_dev; clock_control_subsys_t clock_subsys; const struct pinctrl_dev_config *pcfg; - uint8_t mosi_overrun __aligned(4); + uint8_t mosi_overrun __aligned(32); }; struct gspi_siwx91x_data { From 8f1c8f8df31044916102dbfff81eaffc78536a43 Mon Sep 17 00:00:00 2001 From: Sai Santhosh Malae Date: Sun, 23 Nov 2025 17:04:47 +0530 Subject: [PATCH 05/13] drivers: spi: siwx91x: Swap write and read data inside GSPI controller Swap the write and read data paths within the GSPI controller to ensure correct data is seen on the SPI lines during 16-bit transfers. Signed-off-by: Sai Santhosh Malae (cherry picked from commit d4b551b3fbd10aab99feeb8fba4667cee6e5c4d1) Upstream-status: available --- drivers/spi/spi_silabs_siwx91x_gspi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi_silabs_siwx91x_gspi.c b/drivers/spi/spi_silabs_siwx91x_gspi.c index a530656e14e4c..96a3c316aa61b 100644 --- a/drivers/spi/spi_silabs_siwx91x_gspi.c +++ b/drivers/spi/spi_silabs_siwx91x_gspi.c @@ -176,8 +176,9 @@ static int gspi_siwx91x_config(const struct device *dev, const struct spi_config /* Update the number of Data Bits */ cfg->reg->GSPI_WRITE_DATA2 = SPI_WORD_SIZE_GET(spi_cfg->operation); - /* Swap the read data inside the GSPI controller it-self */ - cfg->reg->GSPI_CONFIG2_b.GSPI_RD_DATA_SWAP_MNL_CSN0 = 0; + /* Swap the write and read data inside the GSPI controller it-self */ + cfg->reg->GSPI_CONFIG2_b.GSPI_RD_DATA_SWAP_MNL_CSN0 = 1; + cfg->reg->GSPI_CONFIG2_b.GSPI_WR_DATA_SWAP_MNL_CSN0 = 1; /* Enable full-duplex mode and manual read/write */ cfg->reg->GSPI_CONFIG1_b.SPI_FULL_DUPLEX_EN = 1; From eb20c2963ac598ff85424a233354ecd4e8cc62f3 Mon Sep 17 00:00:00 2001 From: Sai Santhosh Malae Date: Sun, 23 Nov 2025 17:08:34 +0530 Subject: [PATCH 06/13] drivers: spi: siwx91x: Guard callback registration Guard callback registration with CONFIG_SPI_ASYNC to avoid build error for blocking SPI transfers using DMA Signed-off-by: Sai Santhosh Malae (cherry picked from commit f8b5b77348651a9c20b439e53b0dbecc9a0c55f3) Upstream-status: available --- drivers/spi/spi_silabs_siwx91x_gspi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/spi/spi_silabs_siwx91x_gspi.c b/drivers/spi/spi_silabs_siwx91x_gspi.c index 96a3c316aa61b..1ff4723c44b43 100644 --- a/drivers/spi/spi_silabs_siwx91x_gspi.c +++ b/drivers/spi/spi_silabs_siwx91x_gspi.c @@ -215,8 +215,10 @@ static int gspi_siwx91x_config(const struct device *dev, const struct spi_config } } +#ifdef CONFIG_SPI_ASYNC data->ctx.callback = cb; data->ctx.callback_data = userdata; +#endif #endif data->ctx.config = spi_cfg; From 8256982f2d5ab7edda73aee145640835e9812759 Mon Sep 17 00:00:00 2001 From: Sai Santhosh Malae Date: Sun, 23 Nov 2025 17:12:29 +0530 Subject: [PATCH 07/13] tests: drivers: spi: siwx91x: Adjust transfer scaling factor Increase CONFIG_SPI_IDEAL_TRANSFER_DURATION_SCALING to compensate for the additional burst size calculation in the SPI driver, which slightly increases transfer time. Signed-off-by: Sai Santhosh Malae (cherry picked from commit 649e1f6d64b927ec8c13068e1e4e5ba00fd14c70) Upstream-status: available --- tests/drivers/spi/spi_loopback/boards/siwx917_rb4338a.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/drivers/spi/spi_loopback/boards/siwx917_rb4338a.conf b/tests/drivers/spi/spi_loopback/boards/siwx917_rb4338a.conf index 940add570e6fe..ccbb9b32c0ab3 100644 --- a/tests/drivers/spi/spi_loopback/boards/siwx917_rb4338a.conf +++ b/tests/drivers/spi/spi_loopback/boards/siwx917_rb4338a.conf @@ -1,2 +1,2 @@ CONFIG_SPI_SILABS_SIWX91X_GSPI_DMA=y -CONFIG_SPI_IDEAL_TRANSFER_DURATION_SCALING=24 +CONFIG_SPI_IDEAL_TRANSFER_DURATION_SCALING=26 From 4b517fd6245c7e847a07a2e5587c02d39636f3bf Mon Sep 17 00:00:00 2001 From: Sai Santhosh Malae Date: Sat, 29 Nov 2025 18:26:23 +0530 Subject: [PATCH 08/13] tests: drivers: spi: siwx91x: Enable spi_loopback test for PSRAM board Add overlay and config files for siwx917_rb4342a to enable the spi_loopback test. Signed-off-by: Sai Santhosh Malae (cherry picked from commit b82944ef8399a8a12c2a9f54eef3d2227b229a4e) Upstream-status: available --- .../spi_loopback/boards/siwx917_rb4342a.conf | 2 + .../boards/siwx917_rb4342a.overlay | 43 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 tests/drivers/spi/spi_loopback/boards/siwx917_rb4342a.conf create mode 100644 tests/drivers/spi/spi_loopback/boards/siwx917_rb4342a.overlay diff --git a/tests/drivers/spi/spi_loopback/boards/siwx917_rb4342a.conf b/tests/drivers/spi/spi_loopback/boards/siwx917_rb4342a.conf new file mode 100644 index 0000000000000..ccbb9b32c0ab3 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/siwx917_rb4342a.conf @@ -0,0 +1,2 @@ +CONFIG_SPI_SILABS_SIWX91X_GSPI_DMA=y +CONFIG_SPI_IDEAL_TRANSFER_DURATION_SCALING=26 diff --git a/tests/drivers/spi/spi_loopback/boards/siwx917_rb4342a.overlay b/tests/drivers/spi/spi_loopback/boards/siwx917_rb4342a.overlay new file mode 100644 index 0000000000000..5a4ad002f2f9b --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/siwx917_rb4342a.overlay @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Silicon Laboratories Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl0 { + spi0_default: spi0_default { + out { + pinmux = , ; + }; + + in { + pinmux = ; + }; + }; +}; + +&spi0 { + status = "okay"; + cs-gpios = <&gpiob 12 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&spi0_default>; + pinctrl-names = "default"; + + dmas = <&gpdma 0 11>, <&gpdma 1 10>; + dma-names = "tx", "rx"; + + slow@0 { + compatible = "test-spi-loopback-slow"; + reg = <0>; + spi-max-frequency = <500000>; + }; + + fast@1 { + compatible = "test-spi-loopback-fast"; + reg = <0>; + spi-max-frequency = <10000000>; + }; +}; + +&gpdma { + status = "okay"; +}; From b66deb6c7f63ef3a420034e9be0a6d78895ca9bd Mon Sep 17 00:00:00 2001 From: Swamidas Nampalli Date: Mon, 1 Dec 2025 09:27:37 +0530 Subject: [PATCH 09/13] drivers: wifi: siwx91x: Drop the loop back packets Added a MAC-layer filter to discard frames whose source MAC address matches the devices own MAC address. These packets are looped-back frames that do not need to be processed again by the network stack. Dropping such frames early improves correctness, avoids redundant RX processing, and reduces load on the IPv4/IPv6 protocol handlers. This patch is a workaround for a bug in the NWP Signed-off-by: Swamidas Nampalli (cherry picked from commit c2f8f9813de90618814b1eee314a0f0753de55f5) Upstream-status: available --- drivers/wifi/siwx91x/siwx91x_wifi.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/wifi/siwx91x/siwx91x_wifi.c b/drivers/wifi/siwx91x/siwx91x_wifi.c index 5252070fb17f6..5f8e978866c0a 100644 --- a/drivers/wifi/siwx91x/siwx91x_wifi.c +++ b/drivers/wifi/siwx91x/siwx91x_wifi.c @@ -267,10 +267,18 @@ sl_status_t sl_si91x_host_process_data_frame(sl_wifi_interface_t interface, sl_wifi_buffer_t *buffer) { sl_si91x_packet_t *si_pkt = sl_si91x_host_get_buffer_data(buffer, 0, NULL); + const struct net_eth_hdr *eth = (const struct net_eth_hdr *)si_pkt->data; struct net_if *iface = net_if_get_first_wifi(); + const struct net_linkaddr *ll = net_if_get_link_addr(iface); struct net_pkt *pkt; int ret; + /* NWP sometime echoes the Tx frames */ + if (memcmp(eth->src.addr, ll->addr, sizeof(eth->src.addr)) == 0) { + LOG_DBG("Dropped packet (source MAC matches our MAC)"); + return SL_STATUS_OK; + } + pkt = net_pkt_rx_alloc_with_buffer(iface, buffer->length, AF_UNSPEC, 0, K_NO_WAIT); if (!pkt) { LOG_ERR("net_pkt_rx_alloc_with_buffer() failed"); From 38fcb7ff26747e4543d6c66997402b69d3a9ba8d Mon Sep 17 00:00:00 2001 From: Sai Santhosh Malae Date: Tue, 2 Dec 2025 23:25:24 +0530 Subject: [PATCH 10/13] drivers: gpio: siwx91x: Implement device runtime PM for GPIO ports The existing device runtime PM model requires applications to call pm_device_runtime_get()/put() on the GPIO controller device directly, which is not ideal when GPIO ports are exposed as child nodes. This update enables runtime PM at the GPIO port (child node) level, allowing applications to manage power through the port devices instead of the top-level controller. Signed-off-by: Sai Santhosh Malae (cherry picked from commit 76b1a07c549f715be272426c3c3bdb20296b191e) Upstream-status: available --- drivers/gpio/gpio_silabs_siwx91x.c | 33 +++++++++++++++++++++++++----- dts/arm/silabs/siwg917.dtsi | 5 +++++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpio_silabs_siwx91x.c b/drivers/gpio/gpio_silabs_siwx91x.c index e13fc6e0cd070..94b2269821d48 100644 --- a/drivers/gpio/gpio_silabs_siwx91x.c +++ b/drivers/gpio/gpio_silabs_siwx91x.c @@ -207,6 +207,29 @@ static int gpio_siwx91x_pm_action(const struct device *dev, enum pm_device_actio return 0; } + +static int gpio_siwx91x_port_pm_action(const struct device *dev, enum pm_device_action action) +{ + const struct gpio_siwx91x_port_config *port_cfg = dev->config; + const struct device *parent = port_cfg->parent; + + switch (action) { + case PM_DEVICE_ACTION_TURN_ON: + break; + case PM_DEVICE_ACTION_TURN_OFF: + break; + case PM_DEVICE_ACTION_RESUME: + pm_device_runtime_get(parent); + break; + case PM_DEVICE_ACTION_SUSPEND: + pm_device_runtime_put(parent); + break; + default: + return -ENOTSUP; + } + return 0; +} + static int gpio_siwx91x_port_get(const struct device *port, gpio_port_value_t *value) { const struct gpio_siwx91x_port_config *port_cfg = port->config; @@ -378,7 +401,7 @@ static inline int gpio_siwx91x_init_port(const struct device *port) __ASSERT(port_cfg->port < cfg->port_count, "Too many ports"); data->ports[port_cfg->port] = port; - return 0; + return pm_device_driver_init(port, gpio_siwx91x_port_pm_action); } static void gpio_siwx91x_isr(const struct device *parent) @@ -449,10 +472,10 @@ static DEVICE_API(gpio, gpio_siwx91x_api) = { .pin_config_info = pin_config_info_##n, \ .total_pin_cnt = __builtin_popcount(GPIO_PORT_PIN_MASK_FROM_DT_NODE(n)), \ }; \ - \ - DEVICE_DT_DEFINE(n, gpio_siwx91x_init_port, NULL, &gpio_siwx91x_port_data##n, \ - &gpio_siwx91x_port_config##n, PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, \ - &gpio_siwx91x_api); + PM_DEVICE_DT_DEFINE(n, gpio_siwx91x_port_pm_action); \ + DEVICE_DT_DEFINE(n, gpio_siwx91x_init_port, PM_DEVICE_DT_GET(n), \ + &gpio_siwx91x_port_data##n, &gpio_siwx91x_port_config##n, PRE_KERNEL_1, \ + CONFIG_GPIO_INIT_PRIORITY, &gpio_siwx91x_api); #define CONFIGURE_SHARED_INTERRUPT(node_id, prop, idx) \ IRQ_CONNECT(DT_IRQ_BY_IDX(node_id, idx, irq), DT_IRQ_BY_IDX(node_id, idx, priority), \ diff --git a/dts/arm/silabs/siwg917.dtsi b/dts/arm/silabs/siwg917.dtsi index 23e653da7ec21..c94abd5b486f4 100644 --- a/dts/arm/silabs/siwg917.dtsi +++ b/dts/arm/silabs/siwg917.dtsi @@ -206,6 +206,7 @@ ngpios = <16>; gpio-reserved-ranges = <0 6>; silabs,pads = [ff ff ff ff ff ff 01 02 03 04 05 06 07 ff ff 08]; + zephyr,pm-device-runtime-auto; status = "okay"; }; @@ -216,6 +217,7 @@ #gpio-cells = <2>; ngpios = <16>; silabs,pads = [ff ff ff ff ff ff ff ff ff 00 00 00 00 00 00 09]; + zephyr,pm-device-runtime-auto; status = "okay"; }; @@ -226,6 +228,7 @@ #gpio-cells = <2>; ngpios = <16>; silabs,pads = [09 09 09 ff ff ff ff ff ff ff ff ff ff ff 0a 0b]; + zephyr,pm-device-runtime-auto; status = "okay"; }; @@ -236,6 +239,7 @@ #gpio-cells = <2>; ngpios = <10>; silabs,pads = [0c 0d 0e 0f 10 11 12 13 14 15 ff ff ff ff ff ff]; + zephyr,pm-device-runtime-auto; status = "okay"; }; }; @@ -260,6 +264,7 @@ ngpios = <12>; gpio-reserved-ranges = <3 1>; silabs,pads = [16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 ff ff ff ff]; + zephyr,pm-device-runtime-auto; status = "okay"; }; }; From 34095cd85d5c306165187fa65d81312a4145d72e Mon Sep 17 00:00:00 2001 From: Sai Santhosh Malae Date: Wed, 3 Dec 2025 22:39:00 +0530 Subject: [PATCH 11/13] tests: drivers: gpio: Add device runtime PM compatibility Update the gpio_basic_api test to support device runtime power management. This ensures the test runs correctly when runtime PM is enabled on GPIO devices. Signed-off-by: Sai Santhosh Malae (cherry picked from commit 0ceef4fb972296197f08232dbb8d367bce83f3b5) Upstream-status: available --- tests/drivers/gpio/gpio_basic_api/src/main.c | 23 +++++++++++++++---- .../drivers/gpio/gpio_basic_api/testcase.yaml | 7 ++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/tests/drivers/gpio/gpio_basic_api/src/main.c b/tests/drivers/gpio/gpio_basic_api/src/main.c index e82e9918652d4..25e9fad4c5ce7 100644 --- a/tests/drivers/gpio/gpio_basic_api/src/main.c +++ b/tests/drivers/gpio/gpio_basic_api/src/main.c @@ -5,6 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include "test_gpio.h" /* Grotesque hack for pinmux boards */ @@ -77,21 +78,33 @@ static void board_setup(void) static void *gpio_basic_setup(void) { board_setup(); - + (void)pm_device_runtime_get(DEVICE_DT_GET(DEV)); +#ifdef CONFIG_UART_CONSOLE + (void)pm_device_runtime_get(DEVICE_DT_GET(DT_CHOSEN(zephyr_console))); +#endif return NULL; } +void gpio_basic_teardown(void *args) +{ + (void)args; + (void)pm_device_runtime_put(DEVICE_DT_GET(DEV)); +#ifdef CONFIG_UART_CONSOLE + (void)pm_device_runtime_put(DEVICE_DT_GET(DT_CHOSEN(zephyr_console))); +#endif +} + /* Test GPIO port configuration */ -ZTEST_SUITE(gpio_port, NULL, gpio_basic_setup, NULL, NULL, NULL); +ZTEST_SUITE(gpio_port, NULL, gpio_basic_setup, NULL, NULL, gpio_basic_teardown); /* Test GPIO callback management */ -ZTEST_SUITE(gpio_port_cb_mgmt, NULL, gpio_basic_setup, NULL, NULL, NULL); +ZTEST_SUITE(gpio_port_cb_mgmt, NULL, gpio_basic_setup, NULL, NULL, gpio_basic_teardown); /* Test GPIO callbacks */ -ZTEST_SUITE(gpio_port_cb_vari, NULL, gpio_basic_setup, NULL, NULL, NULL); +ZTEST_SUITE(gpio_port_cb_vari, NULL, gpio_basic_setup, NULL, NULL, gpio_basic_teardown); /* Test GPIO port configuration influence on callbacks. Want to run just * after flash, hence the name starting in 'a' */ ZTEST_SUITE(after_flash_gpio_config_trigger, NULL, gpio_basic_setup, NULL, NULL, - NULL); + gpio_basic_teardown); diff --git a/tests/drivers/gpio/gpio_basic_api/testcase.yaml b/tests/drivers/gpio/gpio_basic_api/testcase.yaml index 3c927e71213ac..7bb8b6176db92 100644 --- a/tests/drivers/gpio/gpio_basic_api/testcase.yaml +++ b/tests/drivers/gpio/gpio_basic_api/testcase.yaml @@ -141,3 +141,10 @@ tests: extra_args: "DTC_OVERLAY_FILE=boards/frdm_rw612_hsgpio.overlay" harness_config: fixture: hsgpio_loopback + drivers.gpio.device_runtime_pm: + platform_allow: + - siwx917_rb4338a + extra_configs: + - CONFIG_PM=y + - CONFIG_PM_DEVICE=y + - CONFIG_ZTEST_NO_YIELD=n From 626408d322f3c29032a9da9fdbe7f62f422f7032 Mon Sep 17 00:00:00 2001 From: Martin Hoff Date: Wed, 3 Dec 2025 16:44:13 +0100 Subject: [PATCH 12/13] dts: arm: silabs: add missing clock on acmp node in xg21 dtsi Without this clock definition, you will get compilation error when using acmp device on board that use xg21 SoC. Signed-off-by: Martin Hoff (cherry picked from commit 62e97eb5a7929367e5c826611452d8ad6cf544a0) Upstream-status: available --- dts/arm/silabs/xg21/xg21.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dts/arm/silabs/xg21/xg21.dtsi b/dts/arm/silabs/xg21/xg21.dtsi index 5bdfed4857cf0..4b888849a07ec 100644 --- a/dts/arm/silabs/xg21/xg21.dtsi +++ b/dts/arm/silabs/xg21/xg21.dtsi @@ -488,6 +488,7 @@ acmp0: acmp@5a008000 { compatible = "silabs,acmp"; reg = <0x5a008000 0x4000>; + clocks = <&cmu CLOCK_AUTO CLOCK_BRANCH_INVALID>; interrupt-names = "acmp0"; interrupts = <41 2>; status = "disabled"; @@ -496,6 +497,7 @@ acmp1: acmp@5a00c000 { compatible = "silabs,acmp"; reg = <0x5a00c000 0x4000>; + clocks = <&cmu CLOCK_AUTO CLOCK_BRANCH_INVALID>; interrupt-names = "acmp1"; interrupts = <42 2>; status = "disabled"; From edd7efd4d29024ec933c441152e57aee409b6e5f Mon Sep 17 00:00:00 2001 From: Martin Hoff Date: Tue, 2 Dec 2025 17:46:18 +0100 Subject: [PATCH 13/13] tests: drivers: comparator: add silabs boards overlays This patch introduce multiple silabs boards overlay that are needed to test different ip version of the peripheral. Signed-off-by: Martin Hoff (cherry picked from commit 25362f72286737ee389a35e665860f2fc0438581) Upstream-status: available --- .../gpio_loopback/boards/slwrb4180a.overlay | 40 +++++++++++++++++++ .../gpio_loopback/boards/xg23_rb4210a.overlay | 40 +++++++++++++++++++ .../gpio_loopback/boards/xg28_rb4401c.overlay | 40 +++++++++++++++++++ .../comparator/gpio_loopback/testcase.yaml | 3 ++ 4 files changed, 123 insertions(+) create mode 100644 tests/drivers/comparator/gpio_loopback/boards/slwrb4180a.overlay create mode 100644 tests/drivers/comparator/gpio_loopback/boards/xg23_rb4210a.overlay create mode 100644 tests/drivers/comparator/gpio_loopback/boards/xg28_rb4401c.overlay diff --git a/tests/drivers/comparator/gpio_loopback/boards/slwrb4180a.overlay b/tests/drivers/comparator/gpio_loopback/boards/slwrb4180a.overlay new file mode 100644 index 0000000000000..34bcc3bdb749c --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/boards/slwrb4180a.overlay @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025 Silicon Laboratories Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +/ { + aliases { + test-comp = &acmp0; + }; + + zephyr,user { + test-gpios = <&gpioc 3 GPIO_ACTIVE_HIGH>; + }; +}; + +&pinctrl { + acmp0_default: acmp0_default { + group0 { + silabs,analog-bus = ; + }; + }; +}; + +&acmp0 { + pinctrl-0 = <&acmp0_default>; + pinctrl-names = "default"; + status = "okay"; + + hysteresis-mode = "disabled"; + accuracy-mode = "high"; + input-range = "full"; + input-positive = ; + input-negative = ; + vref-divider = <63>; +}; diff --git a/tests/drivers/comparator/gpio_loopback/boards/xg23_rb4210a.overlay b/tests/drivers/comparator/gpio_loopback/boards/xg23_rb4210a.overlay new file mode 100644 index 0000000000000..cf9864bdc8943 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/boards/xg23_rb4210a.overlay @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025 Silicon Laboratories Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +/ { + aliases { + test-comp = &acmp0; + }; + + zephyr,user { + test-gpios = <&gpioc 1 GPIO_ACTIVE_HIGH>; + }; +}; + +&pinctrl { + acmp0_default: acmp0_default { + group0 { + silabs,analog-bus = ; + }; + }; +}; + +&acmp0 { + pinctrl-0 = <&acmp0_default>; + pinctrl-names = "default"; + status = "okay"; + + hysteresis-mode = "disabled"; + accuracy-mode = "high"; + input-range = "full"; + input-positive = ; + input-negative = ; + vref-divider = <63>; +}; diff --git a/tests/drivers/comparator/gpio_loopback/boards/xg28_rb4401c.overlay b/tests/drivers/comparator/gpio_loopback/boards/xg28_rb4401c.overlay new file mode 100644 index 0000000000000..8f5f77fe24d8b --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/boards/xg28_rb4401c.overlay @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025 Silicon Laboratories Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +/ { + aliases { + test-comp = &acmp0; + }; + + zephyr,user { + test-gpios = <&gpiod 7 GPIO_ACTIVE_HIGH>; + }; +}; + +&pinctrl { + acmp0_default: acmp0_default { + group0 { + silabs,analog-bus = ; + }; + }; +}; + +&acmp0 { + pinctrl-0 = <&acmp0_default>; + pinctrl-names = "default"; + status = "okay"; + + hysteresis-mode = "disabled"; + accuracy-mode = "high"; + input-range = "full"; + input-positive = ; + input-negative = ; + vref-divider = <63>; +}; diff --git a/tests/drivers/comparator/gpio_loopback/testcase.yaml b/tests/drivers/comparator/gpio_loopback/testcase.yaml index 7aed8ca5118c3..02b49035cd057 100644 --- a/tests/drivers/comparator/gpio_loopback/testcase.yaml +++ b/tests/drivers/comparator/gpio_loopback/testcase.yaml @@ -10,8 +10,11 @@ common: tests: drivers.comparator.gpio_loopback.silabs_acmp: platform_allow: + - slwrb4180a + - xg23_rb4210a - xg24_dk2601b - xg24_rb4187c + - xg28_rb4401c - xg29_rb4412a - bg29_rb4420a drivers.comparator.gpio_loopback.mcux_acmp: