diff --git a/boards/renesas/rzn2l_rsk/rzn2l_rsk-pinctrl.dtsi b/boards/renesas/rzn2l_rsk/rzn2l_rsk-pinctrl.dtsi index 2b338491a4bb3..0540300bdac45 100644 --- a/boards/renesas/rzn2l_rsk/rzn2l_rsk-pinctrl.dtsi +++ b/boards/renesas/rzn2l_rsk/rzn2l_rsk-pinctrl.dtsi @@ -48,4 +48,13 @@ ; /* SDA */ }; }; + + /omit-if-no-ref/ spi2_pins: spi2 { + spi2-pinmux { + pinmux = , /* CK2 */ + , /* MOSI2 */ + , /* MISO2 */ + ; /* SSL20 */ + }; + }; }; diff --git a/boards/renesas/rzn2l_rsk/rzn2l_rsk.dts b/boards/renesas/rzn2l_rsk/rzn2l_rsk.dts index bc733ef5c4558..27b92452ebae1 100644 --- a/boards/renesas/rzn2l_rsk/rzn2l_rsk.dts +++ b/boards/renesas/rzn2l_rsk/rzn2l_rsk.dts @@ -123,3 +123,9 @@ pinctrl-names = "default"; status = "okay"; }; + +&spi2 { + pinctrl-0 = <&spi2_pins>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/boards/renesas/rzn2l_rsk/rzn2l_rsk.yaml b/boards/renesas/rzn2l_rsk/rzn2l_rsk.yaml index 79b273a75e30f..572fceb457e95 100644 --- a/boards/renesas/rzn2l_rsk/rzn2l_rsk.yaml +++ b/boards/renesas/rzn2l_rsk/rzn2l_rsk.yaml @@ -11,4 +11,5 @@ supported: - adc - i2c - counter + - spi vendor: renesas diff --git a/boards/renesas/rzt2m_rsk/rzt2m_rsk-pinctrl.dtsi b/boards/renesas/rzt2m_rsk/rzt2m_rsk-pinctrl.dtsi index 9b48e978a3cce..fb8766cea199f 100644 --- a/boards/renesas/rzt2m_rsk/rzt2m_rsk-pinctrl.dtsi +++ b/boards/renesas/rzt2m_rsk/rzt2m_rsk-pinctrl.dtsi @@ -40,4 +40,13 @@ ; /* SDA */ }; }; + + /omit-if-no-ref/ spi2_pins: spi2 { + spi2-pinmux { + pinmux = , /* CK2 */ + , /* MOSI2 */ + , /* MISO2 */ + ; /* SSL20 */ + }; + }; }; diff --git a/boards/renesas/rzt2m_rsk/rzt2m_rsk_r9a07g075m24gbg_cr520.dts b/boards/renesas/rzt2m_rsk/rzt2m_rsk_r9a07g075m24gbg_cr520.dts index 97ef74bbbe670..248b6ce7fd728 100644 --- a/boards/renesas/rzt2m_rsk/rzt2m_rsk_r9a07g075m24gbg_cr520.dts +++ b/boards/renesas/rzt2m_rsk/rzt2m_rsk_r9a07g075m24gbg_cr520.dts @@ -120,3 +120,9 @@ &adc1 { status = "okay"; }; + +&spi2 { + pinctrl-0 = <&spi2_pins>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/boards/renesas/rzt2m_rsk/rzt2m_rsk_r9a07g075m24gbg_cr520.yaml b/boards/renesas/rzt2m_rsk/rzt2m_rsk_r9a07g075m24gbg_cr520.yaml index a8eaf76442a24..c2e092c7f210e 100644 --- a/boards/renesas/rzt2m_rsk/rzt2m_rsk_r9a07g075m24gbg_cr520.yaml +++ b/boards/renesas/rzt2m_rsk/rzt2m_rsk_r9a07g075m24gbg_cr520.yaml @@ -16,4 +16,5 @@ supported: - adc - i2c - counter + - spi vendor: renesas diff --git a/drivers/spi/CMakeLists.txt b/drivers/spi/CMakeLists.txt index 6ceda851b1e17..7171b93726f01 100644 --- a/drivers/spi/CMakeLists.txt +++ b/drivers/spi/CMakeLists.txt @@ -54,6 +54,7 @@ zephyr_library_sources_ifdef(CONFIG_SPI_PW spi_pw.c) zephyr_library_sources_ifdef(CONFIG_SPI_RENESAS_RA spi_renesas_ra.c) zephyr_library_sources_ifdef(CONFIG_SPI_RENESAS_RA8 spi_b_renesas_ra8.c) zephyr_library_sources_ifdef(CONFIG_SPI_RENESAS_RX spi_renesas_rx.c) +zephyr_library_sources_ifdef(CONFIG_SPI_RENESAS_RZ spi_renesas_rz.c) zephyr_library_sources_ifdef(CONFIG_SPI_RENESAS_RZ_RSPI spi_renesas_rz_rspi.c) zephyr_library_sources_ifdef(CONFIG_SPI_RPI_PICO_PIO spi_rpi_pico_pio.c) zephyr_library_sources_ifdef(CONFIG_SPI_RV32M1_LPSPI spi_rv32m1_lpspi.c) diff --git a/drivers/spi/Kconfig.renesas_rz b/drivers/spi/Kconfig.renesas_rz index d379e691767da..fc52532a13672 100644 --- a/drivers/spi/Kconfig.renesas_rz +++ b/drivers/spi/Kconfig.renesas_rz @@ -23,6 +23,32 @@ config SPI_RENESAS_RZ_RSPI_DMAC help Enable the SPI DMA mode for SPI instances +endif # SPI_RENESAS_RZ_RSPI + +config SPI_RENESAS_RZ + bool "Renesas RZ SPI" + default y + depends on DT_HAS_RENESAS_RZ_SPI_ENABLED + select USE_RZ_FSP_SPI + select PINCTRL + help + Enable Renesas RZ SPI Driver. + +if SPI_RENESAS_RZ + +config SPI_RENESAS_RZ_INTERRUPT + bool "RZ SPI Interrupt Support" + help + Enable Interrupt support for the SPI. + +config SPI_USE_HW_SS + bool "RZ SPI Hardware Peripheral Select support" + default y + help + Use Hardware Peripheral Select instead of Software Peripheral Select. + +endif # SPI_RENESAS_RZ + if SPI_RTIO config SPI_RTIO_SQ_SIZE int "Number of available submission queue entries" @@ -40,5 +66,3 @@ config SPI_RTIO_CQ_SIZE default 8 # Sensible default that covers most common spi transactions endif # SPI_RTIO - -endif # SPI_RENESAS_RZ_RSPI diff --git a/drivers/spi/spi_renesas_rz.c b/drivers/spi/spi_renesas_rz.c new file mode 100644 index 0000000000000..34dc519db6b1e --- /dev/null +++ b/drivers/spi/spi_renesas_rz.c @@ -0,0 +1,779 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_rz_spi + +#include +#include +#include +#include +#include +#include "r_spi.h" +#ifdef CONFIG_SPI_RTIO +#include +#include +#endif +#include + +LOG_MODULE_REGISTER(rz_spi); + +#define LOG_DEV_ERR(dev, format, ...) LOG_ERR("%s:" #format, (dev)->name, ##__VA_ARGS__) + +#include "spi_context.h" + +#define SPI_RZ_SPSRC_CLR 0xFD80 +#define SPI_RZ_TRANSMIT_RECEIVE 0x0 +#define SPI_RZ_TX_ONLY 0x1 + +struct spi_rz_config { + const struct pinctrl_dev_config *pinctrl_dev; + const spi_api_t *fsp_api; + spi_clock_source_t clock_source; +}; + +struct spi_rz_data { + struct spi_context ctx; + uint8_t dfs; + uint32_t data_len; + spi_cfg_t *fsp_config; + spi_instance_ctrl_t *fsp_ctrl; +#ifdef CONFIG_SPI_RTIO + struct spi_rtio *rtio_ctx; +#endif /* CONFIG_SPI_RTIO */ +}; + +#if defined(CONFIG_SPI_RENESAS_RZ_INTERRUPT) +void spi_rxi_isr(void); +void spi_txi_isr(void); +void spi_tei_isr(void); +void spi_eri_isr(void); +#endif /* CONFIG_SPI_RENESAS_RZ_INTERRUPT */ + +#ifdef CONFIG_SPI_RTIO +static void spi_rz_iodev_complete(const struct device *dev, int status); +#else +static bool spi_rz_transfer_ongoing(struct spi_rz_data *data) +{ +#if defined(CONFIG_SPI_RENESAS_RZ_INTERRUPT) + return (spi_context_tx_on(&data->ctx) || spi_context_rx_on(&data->ctx)); +#else + if (spi_context_total_tx_len(&data->ctx) == spi_context_total_rx_len(&data->ctx)) { + return (spi_context_tx_on(&data->ctx) && spi_context_rx_on(&data->ctx)); + } else { + return (spi_context_tx_on(&data->ctx) || spi_context_rx_on(&data->ctx)); + } +#endif +} +#endif /* CONFIG_SPI_RTIO */ + +static void spi_callback(spi_callback_args_t *p_args) +{ + struct device *dev = (struct device *)p_args->p_context; + struct spi_rz_data *data = dev->data; + + switch (p_args->event) { + case SPI_EVENT_TRANSFER_COMPLETE: + spi_context_cs_control(&data->ctx, false); +#ifdef CONFIG_SPI_RTIO + struct spi_rtio *rtio_ctx = data->rtio_ctx; + + if (rtio_ctx->txn_head != NULL) { + spi_rz_iodev_complete(dev, 0); + } +#endif + spi_context_complete(&data->ctx, dev, 0); + break; + case SPI_EVENT_ERR_MODE_FAULT: /* Mode fault error */ + case SPI_EVENT_ERR_READ_OVERFLOW: /* Read overflow error */ + case SPI_EVENT_ERR_PARITY: /* Parity error */ + case SPI_EVENT_ERR_OVERRUN: /* Overrun error */ + case SPI_EVENT_ERR_FRAMING: /* Framing error */ + case SPI_EVENT_ERR_MODE_UNDERRUN: /* Underrun error */ + spi_context_cs_control(&data->ctx, false); + spi_context_complete(&data->ctx, dev, -EIO); + break; + default: + break; + } +} + +static int spi_rz_configure(const struct device *dev, const struct spi_config *spi_cfg) +{ + struct spi_rz_data *data = dev->data; + const struct spi_rz_config *config = dev->config; + spi_extended_cfg_t *spi_extend = (spi_extended_cfg_t *)data->fsp_config->p_extend; + fsp_err_t err; + + if (spi_context_configured(&data->ctx, spi_cfg)) { + /* This configuration is already in use */ + return 0; + } + + if (data->fsp_ctrl->open != 0) { + config->fsp_api->close(data->fsp_ctrl); + } + + if (spi_cfg->operation & SPI_FRAME_FORMAT_TI) { + LOG_ERR("TI frame not supported"); + return -ENOTSUP; + } + + if (IS_ENABLED(CONFIG_SPI_EXTENDED_MODES) && + (spi_cfg->operation & SPI_LINES_MASK) != SPI_LINES_SINGLE) { + LOG_DEV_ERR(dev, "Only single line mode is supported"); + return -ENOTSUP; + } + + /* SPI mode */ + if (spi_cfg->operation & SPI_OP_MODE_SLAVE) { + data->fsp_config->operating_mode = SPI_MODE_SLAVE; + } else { + data->fsp_config->operating_mode = SPI_MODE_MASTER; + } + + /* SPI POLARITY */ + if (SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPOL) { + data->fsp_config->clk_polarity = SPI_CLK_POLARITY_HIGH; + } else { + data->fsp_config->clk_polarity = SPI_CLK_POLARITY_LOW; + } + + /* SPI PHASE */ + if (SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPHA) { + data->fsp_config->clk_phase = SPI_CLK_PHASE_EDGE_EVEN; + } else { + data->fsp_config->clk_phase = SPI_CLK_PHASE_EDGE_ODD; + } + + /* SPI bit order */ + if (spi_cfg->operation & SPI_TRANSFER_LSB) { + data->fsp_config->bit_order = SPI_BIT_ORDER_LSB_FIRST; + } else { + data->fsp_config->bit_order = SPI_BIT_ORDER_MSB_FIRST; + } + + data->dfs = ((SPI_WORD_SIZE_GET(spi_cfg->operation) - 1) / 8) + 1; + data->fsp_ctrl->bit_width = (spi_bit_width_t)(SPI_WORD_SIZE_GET(spi_cfg->operation) - 1); + if ((data->fsp_ctrl->bit_width > SPI_BIT_WIDTH_32_BITS) || + (data->fsp_ctrl->bit_width < SPI_BIT_WIDTH_4_BITS)) { + LOG_ERR("Unsupported SPI word size: %u", SPI_WORD_SIZE_GET(spi_cfg->operation)); + return -ENOTSUP; + } + + /* SPI slave select polarity */ + if (spi_cfg->operation & SPI_CS_ACTIVE_HIGH) { + spi_extend->ssl_polarity = SPI_SSLP_HIGH; + } else { + spi_extend->ssl_polarity = SPI_SSLP_LOW; + } + + /* Calculate bitrate */ + if ((spi_cfg->frequency > 0) && (!(spi_cfg->operation & SPI_OP_MODE_SLAVE))) { + err = R_SPI_CalculateBitrate(spi_cfg->frequency, config->clock_source, + &spi_extend->spck_div); + + if (err != FSP_SUCCESS) { + LOG_DEV_ERR(dev, "spi: bitrate calculate error: %d", err); + return -ENOSYS; + } + } + + spi_extend->spi_comm = SPI_COMMUNICATION_FULL_DUPLEX; + + if (spi_cs_is_gpio(spi_cfg) || !IS_ENABLED(CONFIG_SPI_USE_HW_SS)) { + if ((spi_cfg->operation & SPI_OP_MODE_SLAVE) && + (data->fsp_config->clk_phase == SPI_CLK_PHASE_EDGE_ODD)) { + LOG_DEV_ERR(dev, "The CPHA bit must be set to 1 slave mode"); + return -EIO; + } + spi_extend->spi_clksyn = SPI_SSL_MODE_CLK_SYN; + } else { + spi_extend->spi_clksyn = SPI_SSL_MODE_SPI; + switch (spi_cfg->slave) { + case 0: + spi_extend->ssl_select = SPI_SSL_SELECT_SSL0; + break; + case 1: + spi_extend->ssl_select = SPI_SSL_SELECT_SSL1; + break; + case 2: + spi_extend->ssl_select = SPI_SSL_SELECT_SSL2; + break; + case 3: + spi_extend->ssl_select = SPI_SSL_SELECT_SSL3; + break; + default: + LOG_ERR("Invalid SSL"); + return -EINVAL; + } + } + + spi_extend->receive_fifo_threshold = 0; + spi_extend->transmit_fifo_threshold = 0; + + /* Open module r_spi. */ + err = config->fsp_api->open(data->fsp_ctrl, data->fsp_config); + if (err != FSP_SUCCESS) { + LOG_ERR("R_SPI_Open error: %d", err); + return -EIO; + } + + data->ctx.config = spi_cfg; + + return 0; +} + +#if !defined(CONFIG_SPI_RENESAS_RZ_INTERRUPT) +static int spi_rz_spi_transceive_data(struct spi_rz_data *data) +{ + uint32_t tx; + uint32_t rx; + + if (spi_context_tx_buf_on(&data->ctx)) { + if (data->fsp_ctrl->bit_width > SPI_BIT_WIDTH_16_BITS) { + tx = *(uint32_t *)(data->ctx.tx_buf); + } else if (data->fsp_ctrl->bit_width > SPI_BIT_WIDTH_8_BITS) { + tx = *(uint16_t *)(data->ctx.tx_buf); + } else { + tx = *(uint8_t *)(data->ctx.tx_buf); + } + } else { + tx = 0U; + } + + while (!data->fsp_ctrl->p_regs->SPSR_b.SPTEF) { + } + + /* TX transfer */ + if (data->fsp_ctrl->bit_width > SPI_BIT_WIDTH_16_BITS) { + data->fsp_ctrl->p_regs->SPDR = (uint32_t)tx; + } else if (data->fsp_ctrl->bit_width > SPI_BIT_WIDTH_8_BITS) { + data->fsp_ctrl->p_regs->SPDR = (uint16_t)tx; + } else { + data->fsp_ctrl->p_regs->SPDR = (uint8_t)tx; + } + + data->fsp_ctrl->p_regs->SPSRC_b.SPTEFC = 1; /* Clear SPTEF flag */ + spi_context_update_tx(&data->ctx, data->dfs, 1); + + if (data->fsp_ctrl->p_regs->SPCR_b.TXMD == 0x0) { + while (!data->fsp_ctrl->p_regs->SPSR_b.SPRF) { + } + + if (SPI_BIT_WIDTH_16_BITS < data->fsp_ctrl->bit_width) { + rx = (uint32_t)data->fsp_ctrl->p_regs->SPDR; + } else if (SPI_BIT_WIDTH_8_BITS >= data->fsp_ctrl->bit_width) { + rx = (uint8_t)data->fsp_ctrl->p_regs->SPDR; + } else { + rx = (uint16_t)data->fsp_ctrl->p_regs->SPDR; + } + + /* RX transfer */ + if (spi_context_rx_buf_on(&data->ctx)) { + + /* Read data from Data Register */ + if (data->fsp_ctrl->bit_width > SPI_BIT_WIDTH_16_BITS) { + UNALIGNED_PUT(rx, (uint32_t *)data->ctx.rx_buf); + } else if (data->fsp_ctrl->bit_width > SPI_BIT_WIDTH_8_BITS) { + UNALIGNED_PUT(rx, (uint16_t *)data->ctx.rx_buf); + } else { + UNALIGNED_PUT(rx, (uint8_t *)data->ctx.rx_buf); + } + } + spi_context_update_rx(&data->ctx, data->dfs, 1); + data->fsp_ctrl->p_regs->SPSRC_b.SPRFC = 1; /* Clear SPRF flag */ + } + return 0; +} +#endif /* CONFIG_SPI_RENESAS_RZ_INTERRUPT */ + +static int transceive(const struct device *dev, const struct spi_config *spi_cfg, + const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs, + bool asynchronous, spi_callback_t cb, void *userdata) +{ + struct spi_rz_data *data = dev->data; + struct spi_context *spi_ctx = &data->ctx; + int ret = 0; + + if (!tx_bufs && !rx_bufs) { + return 0; + } + +#ifndef CONFIG_SPI_RENESAS_RZ_INTERRUPT + if (asynchronous) { + return -ENOTSUP; + } +#endif + spi_context_lock(spi_ctx, asynchronous, cb, userdata, spi_cfg); + /* Configure module SPI. */ + ret = spi_rz_configure(dev, spi_cfg); + if (ret) { + spi_context_release(spi_ctx, ret); + return -EIO; + } +#ifndef CONFIG_SPI_RTIO + /* Setup tx buffer and rx buffer info. */ + spi_context_buffers_setup(spi_ctx, tx_bufs, rx_bufs, data->dfs); + spi_context_cs_control(spi_ctx, true); +#if defined(CONFIG_SPI_RENESAS_RZ_INTERRUPT) + const struct spi_rz_config *config = dev->config; + + if (!spi_context_total_tx_len(&data->ctx) && !spi_context_total_rx_len(&data->ctx)) { + goto end_transceive; + } + if (data->ctx.rx_len == 0) { + data->data_len = spi_context_is_slave(&data->ctx) + ? spi_context_total_tx_len(&data->ctx) + : data->ctx.tx_len; + } else if (data->ctx.tx_len == 0) { + data->data_len = spi_context_is_slave(&data->ctx) + ? spi_context_total_rx_len(&data->ctx) + : data->ctx.rx_len; + } else { + data->data_len = spi_context_is_slave(&data->ctx) + ? MAX(spi_context_total_tx_len(&data->ctx), + spi_context_total_rx_len(&data->ctx)) + : MIN(data->ctx.tx_len, data->ctx.rx_len); + } + + if (data->ctx.tx_buf == NULL) { /* If there is only the rx buffer */ + ret = config->fsp_api->read(data->fsp_ctrl, data->ctx.rx_buf, data->data_len, + data->fsp_ctrl->bit_width); + } else if (data->ctx.rx_buf == NULL) { /* If there is only the tx buffer */ + ret = config->fsp_api->write(data->fsp_ctrl, data->ctx.tx_buf, data->data_len, + data->fsp_ctrl->bit_width); + } else { + ret = config->fsp_api->writeRead(data->fsp_ctrl, data->ctx.tx_buf, data->ctx.rx_buf, + data->data_len, data->fsp_ctrl->bit_width); + } + if (ret) { + LOG_ERR("Async transmit fail: %d", ret); + spi_context_cs_control(spi_ctx, false); + spi_context_release(spi_ctx, ret); + return -EIO; + } + ret = spi_context_wait_for_completion(spi_ctx); +end_transceive: +#else + /* Enable the SPI transfer */ + data->fsp_ctrl->p_regs->SPCR_b.TXMD = SPI_RZ_TRANSMIT_RECEIVE; + if (!spi_context_rx_on(&data->ctx)) { + data->fsp_ctrl->p_regs->SPCR_b.TXMD = SPI_RZ_TX_ONLY; /* tx only */ + } + + /* Configure data length based on the selected bit width . */ + uint32_t spcmd0 = data->fsp_ctrl->p_regs->SPCMD[0]; + + spcmd0 &= (uint32_t)~R_SPI0_SPCMD_SPB_Msk; + spcmd0 |= (uint32_t)(data->fsp_ctrl->bit_width) << R_SPI0_SPCMD_SPB_Pos; + data->fsp_ctrl->p_regs->SPCMD[0] = spcmd0; + + /* FIFO clear */ + data->fsp_ctrl->p_regs->SPFCR_b.SPFRST = 1; + /* Enable the SPI Transfer */ + data->fsp_ctrl->p_regs->SPCR_b.SPE = 1; + + do { + spi_rz_spi_transceive_data(data); + } while (spi_rz_transfer_ongoing(data)); + + /* Wait for transmit complete */ + while (data->fsp_ctrl->p_regs->SPSR_b.IDLNF) { + } + + /* Disable the SPI Transfer */ + data->fsp_ctrl->p_regs->SPCR_b.SPE = 0x0; + +#endif /* CONFIG_SPI_RENESAS_RZ_INTERRUPT */ + +#ifdef CONFIG_SPI_SLAVE + if (spi_context_is_slave(spi_ctx) && !ret) { + ret = spi_ctx->recv_frames; + } +#endif /* CONFIG_SPI_SLAVE */ + + spi_context_cs_control(spi_ctx, false); + +#else + struct spi_rtio *rtio_ctx = data->rtio_ctx; + + ret = spi_rtio_transceive(rtio_ctx, spi_cfg, tx_bufs, rx_bufs); + +#endif + spi_context_release(spi_ctx, ret); + + return ret; +} + +static int spi_rz_transceive_sync(const struct device *dev, const struct spi_config *spi_cfg, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs) +{ + return transceive(dev, spi_cfg, tx_bufs, rx_bufs, false, NULL, NULL); +} + +static int spi_rz_release(const struct device *dev, const struct spi_config *config) +{ + struct spi_rz_data *data = dev->data; + + spi_context_unlock_unconditionally(&data->ctx); + + return 0; +} + +#ifdef CONFIG_SPI_ASYNC +static int spi_rz_transceive_async(const struct device *dev, const struct spi_config *spi_cfg, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, spi_callback_t cb, + void *userdata) +{ + return transceive(dev, spi_cfg, tx_bufs, rx_bufs, true, cb, userdata); +} +#endif /* CONFIG_SPI_ASYNC */ + +#ifdef CONFIG_SPI_RTIO + +static inline void spi_rz_iodev_prepare_start(const struct device *dev) +{ + struct spi_rz_data *data = dev->data; + struct spi_rtio *rtio_ctx = data->rtio_ctx; + struct spi_dt_spec *spi_dt_spec = rtio_ctx->txn_curr->sqe.iodev->data; + struct spi_config *spi_config = &spi_dt_spec->config; + int err; + + err = spi_rz_configure(dev, spi_config); + if (err != 0) { + LOG_ERR("RTIO config spi error: %d", err); + spi_rz_iodev_complete(dev, err); + return; + } + spi_context_cs_control(&data->ctx, true); +} + +static void spi_rz_iodev_start(const struct device *dev) +{ + struct spi_rz_data *data = dev->data; + const struct spi_rz_config *config = dev->config; + struct spi_rtio *rtio_ctx = data->rtio_ctx; + struct rtio_sqe *sqe = &rtio_ctx->txn_curr->sqe; + int ret = 0; + + switch (sqe->op) { + case RTIO_OP_RX: + data->data_len = sqe->rx.buf_len / data->dfs; + ret = config->fsp_api->read(data->fsp_ctrl, sqe->rx.buf, data->data_len, + data->fsp_ctrl->bit_width); + break; + case RTIO_OP_TX: + data->data_len = sqe->tx.buf_len / data->dfs; + ret = config->fsp_api->write(data->fsp_ctrl, sqe->tx.buf, data->data_len, + data->fsp_ctrl->bit_width); + break; + case RTIO_OP_TINY_TX: + data->data_len = sqe->tiny_tx.buf_len / data->dfs; + ret = config->fsp_api->write(data->fsp_ctrl, sqe->tiny_tx.buf, data->data_len, + data->fsp_ctrl->bit_width); + break; + case RTIO_OP_TXRX: + data->data_len = sqe->txrx.buf_len / data->dfs; + ret = config->fsp_api->writeRead(data->fsp_ctrl, sqe->txrx.tx_buf, sqe->txrx.rx_buf, + data->data_len, data->fsp_ctrl->bit_width); + break; + default: + spi_rz_iodev_complete(dev, -EINVAL); + break; + } + + if (ret != 0) { + spi_rz_iodev_complete(dev, ret); + } +} + +static void spi_rz_iodev_complete(const struct device *dev, int status) +{ + struct spi_rz_data *data = dev->data; + struct spi_rtio *rtio_ctx = data->rtio_ctx; + + if (!status && rtio_ctx->txn_curr->sqe.flags & RTIO_SQE_TRANSACTION) { + rtio_ctx->txn_curr = rtio_txn_next(rtio_ctx->txn_curr); + spi_rz_iodev_start(dev); + } else { + spi_context_cs_control(&data->ctx, false); + + /* + * Submit the result of the operation to the completion queue + * This may start the next asynchronous request if one is available + */ + if (spi_rtio_complete(rtio_ctx, status)) { + spi_rz_iodev_prepare_start(dev); + spi_rz_iodev_start(dev); + } + } +} + +static void spi_rz_iodev_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +{ + struct spi_rz_data *data = dev->data; + struct spi_rtio *rtio_ctx = data->rtio_ctx; + + /* Submit sqe to the queue */ + if (spi_rtio_submit(rtio_ctx, iodev_sqe)) { + spi_rz_iodev_prepare_start(dev); + spi_rz_iodev_start(dev); + } +} + +#endif /* CONFIG_SPI_RTIO */ + +static DEVICE_API(spi, spi_rz_driver_api) = { + .transceive = spi_rz_transceive_sync, + .release = spi_rz_release, +#ifdef CONFIG_SPI_ASYNC + .transceive_async = spi_rz_transceive_async, +#endif /* CONFIG_SPI_ASYNC */ +#ifdef CONFIG_SPI_RTIO + .iodev_submit = spi_rz_iodev_submit, +#endif /* CONFIG_SPI_RTIO */ +}; + +#if defined(CONFIG_SPI_RENESAS_RZ_INTERRUPT) +#if !defined(CONFIG_SPI_RTIO) +static void spi_rz_retransmit(struct spi_rz_data *data) +{ + spi_bit_width_t spi_width = + (spi_bit_width_t)(SPI_WORD_SIZE_GET(data->ctx.config->operation) - 1); + + if (data->ctx.rx_len == 0) { + data->data_len = data->ctx.tx_len; + data->fsp_ctrl->p_tx_data = data->ctx.tx_buf; + data->fsp_ctrl->p_rx_data = NULL; + } else if (data->ctx.tx_len == 0) { + data->data_len = data->ctx.rx_len; + data->fsp_ctrl->p_tx_data = NULL; + data->fsp_ctrl->p_rx_data = data->ctx.rx_buf; + } else { + data->data_len = MIN(data->ctx.tx_len, data->ctx.rx_len); + data->fsp_ctrl->p_tx_data = data->ctx.tx_buf; + data->fsp_ctrl->p_rx_data = data->ctx.rx_buf; + } + + data->fsp_ctrl->bit_width = spi_width; + data->fsp_ctrl->rx_count = 0; + data->fsp_ctrl->tx_count = 0; + data->fsp_ctrl->count = data->data_len; +} +#endif /* !CONFIG_SPI_RTIO */ + +static void spi_rz_rxi_isr(const struct device *dev) +{ +#ifndef CONFIG_SPI_SLAVE + ARG_UNUSED(dev); + spi_rxi_isr(); +#else + struct spi_rz_data *data = dev->data; + + spi_rxi_isr(); + + if (spi_context_is_slave(&data->ctx) && data->fsp_ctrl->rx_count == data->fsp_ctrl->count) { + if (data->ctx.rx_buf != NULL && data->ctx.tx_buf != NULL) { + data->ctx.recv_frames = MIN(spi_context_total_tx_len(&data->ctx), + spi_context_total_rx_len(&data->ctx)); + } else if (data->ctx.tx_buf == NULL) { + data->ctx.recv_frames = data->data_len; + } + R_BSP_IrqDisable(data->fsp_config->tei_irq); + + /* Writing 0 to SPE generatates a TXI IRQ. Disable the TXI IRQ. + * (See Section 38.2.1 SPI Control Register in the RA6T2 manual R01UH0886EJ0100). + */ + R_BSP_IrqDisable(data->fsp_config->txi_irq); + + /* Disable the SPI Transfer. */ + data->fsp_ctrl->p_regs->SPCR_b.SPE = 0; + + /* Re-enable the TXI IRQ and clear the pending IRQ. */ + R_BSP_IrqEnable(data->fsp_config->txi_irq); + + spi_context_cs_control(&data->ctx, false); + spi_context_complete(&data->ctx, dev, 0); + } + +#endif +} + +static void spi_rz_txi_isr(const struct device *dev) +{ + ARG_UNUSED(dev); + spi_txi_isr(); +} + +static void spi_rz_tei_isr(const struct device *dev) +{ +#ifndef CONFIG_SPI_RTIO + struct spi_rz_data *data = dev->data; + + if (data->fsp_ctrl->rx_count == data->fsp_ctrl->count) { + spi_context_update_rx(&data->ctx, data->dfs, data->data_len); + } + if (data->fsp_ctrl->tx_count == data->fsp_ctrl->count) { + spi_context_update_tx(&data->ctx, data->dfs, data->data_len); + } + + if (spi_rz_transfer_ongoing(data)) { + R_BSP_IrqDisable(data->fsp_ctrl->p_cfg->txi_irq); + /* Disable the SPI Transfer. */ + data->fsp_ctrl->p_regs->SPCR_b.SPE = 0U; + data->fsp_ctrl->p_regs->SPSRC = SPI_RZ_SPSRC_CLR; + R_BSP_IrqEnable(data->fsp_ctrl->p_cfg->txi_irq); + data->fsp_ctrl->p_regs->SPCR_b.SPE = 1U; + spi_rz_retransmit(data); + } else { + spi_tei_isr(); + } +#else + spi_tei_isr(); +#endif /* CONFIG_SPI_RTIO */ +} + +static void spi_rz_eri_isr(const struct device *dev) +{ + ARG_UNUSED(dev); + spi_eri_isr(); +} +#endif /* CONFIG_SPI_RENESAS_RZ_INTERRUPT || CONFIG_SPI_RTIO */ + +static int spi_rz_init(const struct device *dev) +{ + const struct spi_rz_config *config = dev->config; + struct spi_rz_data *data = dev->data; + int ret; + + ret = pinctrl_apply_state(config->pinctrl_dev, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + LOG_ERR("pinctrl_apply_state fail: %d", ret); + return ret; + } + + ret = spi_context_cs_configure_all(&data->ctx); + if (ret < 0) { + LOG_ERR("spi_context_cs_configure_all fail: %d", ret); + return ret; + } +#ifdef CONFIG_SPI_RTIO + spi_rtio_init(data->rtio_ctx, dev); +#endif /* CONFIG_SPI_RTIO */ + spi_context_unlock_unconditionally(&data->ctx); + + return 0; +} + +#if defined(CONFIG_SPI_RTIO) +#define SPI_RZ_RTIO_DEFINE(n) \ + SPI_RTIO_DEFINE(spi_rz_rtio_##n, CONFIG_SPI_RTIO_SQ_SIZE, CONFIG_SPI_RTIO_CQ_SIZE) +#else +#define SPI_RZ_RTIO_DEFINE(n) +#endif + +#if defined(CONFIG_SPI_RENESAS_RZ_INTERRUPT) +#define RZ_SPI_IRQ_INIT(n) \ + do { \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, rxi, irq), \ + DT_INST_IRQ_BY_NAME(n, rxi, priority), spi_rz_rxi_isr, \ + DEVICE_DT_INST_GET(n), DT_INST_IRQ_BY_NAME(n, rxi, flags)); \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, txi, irq), \ + DT_INST_IRQ_BY_NAME(n, txi, priority), spi_rz_txi_isr, \ + DEVICE_DT_INST_GET(n), DT_INST_IRQ_BY_NAME(n, txi, flags)); \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, eri, irq), \ + DT_INST_IRQ_BY_NAME(n, eri, priority), spi_rz_eri_isr, \ + DEVICE_DT_INST_GET(n), DT_INST_IRQ_BY_NAME(n, eri, flags)); \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, tei, irq), \ + DT_INST_IRQ_BY_NAME(n, tei, priority), spi_rz_tei_isr, \ + DEVICE_DT_INST_GET(n), DT_INST_IRQ_BY_NAME(n, tei, flags)); \ + irq_enable(DT_INST_IRQ_BY_NAME(n, rxi, irq)); \ + irq_enable(DT_INST_IRQ_BY_NAME(n, txi, irq)); \ + irq_enable(DT_INST_IRQ_BY_NAME(n, eri, irq)); \ + irq_enable(DT_INST_IRQ_BY_NAME(n, tei, irq)); \ + } while (0) + +#else +#define RZ_SPI_IRQ_INIT(n) +#endif /* CONFIG_SPI_RENESAS_RZ_INTERRUPT */ + +#define SPI_RZ_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + SPI_RZ_RTIO_DEFINE(n); \ + static spi_instance_ctrl_t g_spi##n##_ctrl; \ + static spi_extended_cfg_t g_spi_##n##_cfg_extend = { \ + .spi_clksyn = SPI_SSL_MODE_SPI, \ + .spi_comm = SPI_COMMUNICATION_FULL_DUPLEX, \ + .ssl_polarity = SPI_SSLP_LOW, \ + .ssl_select = SPI_SSL_SELECT_SSL0, \ + .mosi_idle = SPI_MOSI_IDLE_VALUE_FIXING_DISABLE, \ + .parity = SPI_PARITY_MODE_DISABLE, \ + .byte_swap = SPI_BYTE_SWAP_DISABLE, \ + .clock_source = SPI_CLOCK_SOURCE_SPI0ASYNCCLK, \ + .spck_div = \ + { \ + .spbr = 4, \ + .brdv = 0, \ + }, \ + .spck_delay = SPI_DELAY_COUNT_1, \ + .ssl_negation_delay = SPI_DELAY_COUNT_1, \ + .next_access_delay = SPI_DELAY_COUNT_1, \ + .transmit_fifo_threshold = 0, \ + .receive_fifo_threshold = 0, \ + .receive_data_ready_detect_adjustment = 0, \ + .master_receive_clock = SPI_MASTER_RECEIVE_CLOCK_MRIOCLK, \ + .mrioclk_analog_delay = SPI_MRIOCLK_ANALOG_DELAY_NODELAY, \ + .mrclk_digital_delay = SPI_MRCLK_DIGITAL_DELAY_CLOCK_0, \ + }; \ + static spi_cfg_t g_spi_##n##_config = { \ + .channel = DT_INST_PROP(n, channel), \ + .eri_irq = DT_INST_IRQ_BY_NAME(n, eri, irq), \ + .rxi_ipl = DT_INST_IRQ_BY_NAME(n, rxi, priority), \ + .txi_ipl = DT_INST_IRQ_BY_NAME(n, txi, priority), \ + .eri_ipl = DT_INST_IRQ_BY_NAME(n, eri, priority), \ + .operating_mode = SPI_MODE_MASTER, \ + .clk_phase = SPI_CLK_PHASE_EDGE_ODD, \ + .clk_polarity = SPI_CLK_POLARITY_LOW, \ + .mode_fault = SPI_MODE_FAULT_ERROR_ENABLE, \ + .bit_order = SPI_BIT_ORDER_MSB_FIRST, \ + .p_callback = spi_callback, \ + .p_context = DEVICE_DT_INST_GET(n), \ + .p_extend = &g_spi_##n##_cfg_extend, \ + .rxi_irq = DT_INST_IRQ_BY_NAME(n, rxi, irq), \ + .txi_irq = DT_INST_IRQ_BY_NAME(n, txi, irq), \ + .tei_irq = DT_INST_IRQ_BY_NAME(n, tei, irq), \ + .p_transfer_tx = NULL, \ + .p_transfer_rx = NULL, \ + }; \ + static const struct spi_rz_config spi_rz_config_##n = { \ + .pinctrl_dev = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .fsp_api = &g_spi_on_spi, \ + .clock_source = (spi_clock_source_t)DT_INST_PROP(n, clk_src), \ + }; \ + \ + static struct spi_rz_data spi_rz_data_##n = { \ + SPI_CONTEXT_INIT_LOCK(spi_rz_data_##n, ctx), \ + SPI_CONTEXT_INIT_SYNC(spi_rz_data_##n, ctx), \ + SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(n), ctx).fsp_ctrl = &g_spi##n##_ctrl, \ + .fsp_config = &g_spi_##n##_config, \ + IF_ENABLED(CONFIG_SPI_RTIO, \ + (.rtio_ctx = &spi_rz_rtio_##n,)) }; \ + \ + static int spi_rz_init_##n(const struct device *dev) \ + { \ + int err = spi_rz_init(dev); \ + if (err != 0) { \ + return err; \ + } \ + RZ_SPI_IRQ_INIT(n); \ + return 0; \ + } \ + DEVICE_DT_INST_DEFINE(n, &spi_rz_init_##n, NULL, &spi_rz_data_##n, &spi_rz_config_##n, \ + POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, &spi_rz_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(SPI_RZ_INIT) diff --git a/dts/arm/renesas/rz/rzn/r9a07g084.dtsi b/dts/arm/renesas/rz/rzn/r9a07g084.dtsi index ac36e255387b0..b8c7b447b45da 100644 --- a/dts/arm/renesas/rz/rzn/r9a07g084.dtsi +++ b/dts/arm/renesas/rz/rzn/r9a07g084.dtsi @@ -1257,5 +1257,69 @@ status = "disabled"; }; }; + + spi0: spi@80003000 { + compatible = "renesas,rz-spi"; + reg = <0x80003000 0x74>; + interrupts = , + , + , + , + ; + interrupt-names = "rxi", "txi", "idle", "eri", "tei"; + channel = <0>; + clk-src = <0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi1: spi@80003400 { + compatible = "renesas,rz-spi"; + reg = <0x80003400 0x74>; + interrupts = , + , + , + , + ; + interrupt-names = "rxi", "txi", "idle", "eri", "tei"; + channel = <1>; + clk-src = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi2: spi@80003800 { + compatible = "renesas,rz-spi"; + reg = <0x80003800 0x74>; + interrupts = , + , + , + , + ; + interrupt-names = "rxi", "txi", "idle", "eri", "tei"; + channel = <2>; + clk-src = <2>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi3: spi@81002000 { + compatible = "renesas,rz-spi"; + reg = <0x81002000 0x74>; + interrupts = , + , + , + , + ; + interrupt-names = "rxi", "txi", "idle", "eri", "tei"; + channel = <3>; + clk-src = <3>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; }; }; diff --git a/dts/arm/renesas/rz/rzt/r9a07g075.dtsi b/dts/arm/renesas/rz/rzt/r9a07g075.dtsi index 5133bc4ea997a..8930d123e0059 100644 --- a/dts/arm/renesas/rz/rzt/r9a07g075.dtsi +++ b/dts/arm/renesas/rz/rzt/r9a07g075.dtsi @@ -1261,5 +1261,69 @@ status = "disabled"; }; }; + + spi0: spi@80003000 { + compatible = "renesas,rz-spi"; + reg = <0x80003000 0x74>; + interrupts = , + , + , + , + ; + interrupt-names = "rxi", "txi", "idle", "eri", "tei"; + channel = <0>; + clk-src = <0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi1: spi@80003400 { + compatible = "renesas,rz-spi"; + reg = <0x80003400 0x74>; + interrupts = , + , + , + , + ; + interrupt-names = "rxi", "txi", "idle", "eri", "tei"; + channel = <1>; + clk-src = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi2: spi@80003800 { + compatible = "renesas,rz-spi"; + reg = <0x80003800 0x74>; + interrupts = , + , + , + , + ; + interrupt-names = "rxi", "txi", "idle", "eri", "tei"; + channel = <2>; + clk-src = <2>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi3: spi@81002000 { + compatible = "renesas,rz-spi"; + reg = <0x81002000 0x74>; + interrupts = , + , + , + , + ; + interrupt-names = "rxi", "txi", "idle", "eri", "tei"; + channel = <3>; + clk-src = <3>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; }; }; diff --git a/dts/bindings/spi/renesas,rz-spi.yaml b/dts/bindings/spi/renesas,rz-spi.yaml new file mode 100644 index 0000000000000..ebf23d8b265d3 --- /dev/null +++ b/dts/bindings/spi/renesas,rz-spi.yaml @@ -0,0 +1,39 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: RENESAS RZ SPI + +compatible: "renesas,rz-spi" + +include: [spi-controller.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + interrupt-names: + required: true + + channel: + type: int + required: true + + clk-src: + type: int + required: true + enum: + - 0 + - 1 + - 2 + - 3 + - 4 + description: | + Select clock source supplied to calculate bitrate + - 0: SPI0ASYNCCLK + - 1: SPI1ASYNCCLK + - 2: SPI2ASYNCCLK + - 3: SPI3ASYNCCLK + - 4: PCLKM diff --git a/modules/Kconfig.renesas b/modules/Kconfig.renesas index 67d944695cf29..3c0f05a2a0348 100644 --- a/modules/Kconfig.renesas +++ b/modules/Kconfig.renesas @@ -332,6 +332,11 @@ config USE_RZ_FSP_CMTW help Enable RZ FSP CMTW driver +config USE_RZ_FSP_SPI + bool + help + Enable RZ FSP SPI driver + endif config HAS_RENESAS_RX_RDP diff --git a/samples/drivers/spi_bitbang/boards/rzt2m_rsk_r9a07g075m24gbg_cr520.conf b/samples/drivers/spi_bitbang/boards/rzt2m_rsk_r9a07g075m24gbg_cr520.conf new file mode 100644 index 0000000000000..bec1bd2a12d91 --- /dev/null +++ b/samples/drivers/spi_bitbang/boards/rzt2m_rsk_r9a07g075m24gbg_cr520.conf @@ -0,0 +1,2 @@ +CONFIG_GPIO=y +CONFIG_NO_OPTIMIZATIONS=y diff --git a/samples/drivers/spi_bitbang/boards/rzt2m_rsk_r9a07g075m24gbg_cr520.overlay b/samples/drivers/spi_bitbang/boards/rzt2m_rsk_r9a07g075m24gbg_cr520.overlay new file mode 100644 index 0000000000000..b48068b7596a5 --- /dev/null +++ b/samples/drivers/spi_bitbang/boards/rzt2m_rsk_r9a07g075m24gbg_cr520.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +spibb0: &spi2 { + cs-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/rzn2l_rsk.conf b/tests/drivers/spi/spi_controller_peripheral/boards/rzn2l_rsk.conf new file mode 100644 index 0000000000000..a491c30deaf54 --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/rzn2l_rsk.conf @@ -0,0 +1,2 @@ +CONFIG_SPI_RENESAS_RZ_INTERRUPT=y +CONFIG_TESTED_SPI_MODE=1 diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/rzn2l_rsk.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/rzn2l_rsk.overlay new file mode 100644 index 0000000000000..2ebcc12027a4b --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/rzn2l_rsk.overlay @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + /omit-if-no-ref/ spi2_pins: spi2 { + spi2-pinmux { + pinmux = , /* CK2 */ + , /* MOSI2 */ + ; /* MISO2 */ + drive-strength = "high"; + slew-rate = "fast"; + }; + }; + + /omit-if-no-ref/ spi3_pins: spi3 { + spi3-pinmux { + pinmux = , /* CK3 */ + , /* MOSI3 */ + , /* MISO3 */ + ; /* SSL3_0 */ + drive-strength = "high"; + slew-rate = "fast"; + }; + }; +}; + +&gpio3 { + status = "okay"; +}; + +&spi2 { + status = "okay"; + pinctrl-0 = <&spi2_pins>; + pinctrl-names = "default"; + cs-gpios = <&gpio3 0 GPIO_ACTIVE_LOW>; + + dut_spi_dt: test-spi-dev@0 { + compatible = "vnd,spi-device"; + reg = <0>; + spi-max-frequency = <1000000>; + spi-cs-setup-delay-ns = <180000>; + spi-cs-hold-delay-ns = <180000>; + }; +}; + +dut_spis: &spi3 { + status = "okay"; + pinctrl-0 = <&spi3_pins>; + pinctrl-names = "default"; +}; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/rzt2m_rsk_r9a07g075m24gbg_cr520.conf b/tests/drivers/spi/spi_controller_peripheral/boards/rzt2m_rsk_r9a07g075m24gbg_cr520.conf new file mode 100644 index 0000000000000..a491c30deaf54 --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/rzt2m_rsk_r9a07g075m24gbg_cr520.conf @@ -0,0 +1,2 @@ +CONFIG_SPI_RENESAS_RZ_INTERRUPT=y +CONFIG_TESTED_SPI_MODE=1 diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/rzt2m_rsk_r9a07g075m24gbg_cr520.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/rzt2m_rsk_r9a07g075m24gbg_cr520.overlay new file mode 100644 index 0000000000000..e20522dc95e00 --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/rzt2m_rsk_r9a07g075m24gbg_cr520.overlay @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + + /omit-if-no-ref/ spi2_pins: spi2 { + spi2-pinmux { + pinmux = , /* CK2 */ + , /* MOSI2 */ + ; /* MISO2 */ + drive-strength = "high"; + slew-rate = "fast"; + }; + }; + + /omit-if-no-ref/ spi3_pins: spi3 { + spi3-pinmux { + pinmux = , /* CK3 */ + , /* MOSI3 */ + , /* MISO3 */ + ; /* SSL3 */ + drive-strength = "high"; + slew-rate = "fast"; + }; + }; +}; + +&gpio1 { + status = "okay"; +}; + +&spi2 { + status = "okay"; + pinctrl-0 = <&spi2_pins>; + pinctrl-names = "default"; + cs-gpios = <&gpio1 6 GPIO_ACTIVE_LOW>; + + dut_spi_dt: test-spi-dev@0 { + compatible = "vnd,spi-device"; + reg = <0>; + spi-max-frequency = <1000000>; + spi-cs-setup-delay-ns = <180000>; + spi-cs-hold-delay-ns = <180000>; + }; +}; + +dut_spis: &spi3 { + status = "okay"; + pinctrl-0 = <&spi3_pins>; + pinctrl-names = "default"; +}; diff --git a/tests/drivers/spi/spi_loopback/boards/rzn2l_rsk.conf b/tests/drivers/spi/spi_loopback/boards/rzn2l_rsk.conf new file mode 100644 index 0000000000000..3de8446aac514 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/rzn2l_rsk.conf @@ -0,0 +1,5 @@ +CONFIG_SPI_ASYNC=y +CONFIG_SPI_RENESAS_RZ_INTERRUPT=y +CONFIG_SPI_RTIO=n +CONFIG_SPI_LOOPBACK_MODE_LOOP=n +CONFIG_SPI_LARGE_BUFFER_SIZE=2048 diff --git a/tests/drivers/spi/spi_loopback/boards/rzn2l_rsk.overlay b/tests/drivers/spi/spi_loopback/boards/rzn2l_rsk.overlay new file mode 100644 index 0000000000000..7cee6555a3cdf --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/rzn2l_rsk.overlay @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&spi2 { + slow@2 { + compatible = "test-spi-loopback-slow"; + reg = <2>; + spi-max-frequency = <500000>; + }; + + fast@2 { + compatible = "test-spi-loopback-fast"; + reg = <2>; + spi-max-frequency = <2500000>; + }; +}; diff --git a/tests/drivers/spi/spi_loopback/boards/rzt2m_rsk_r9a07g075m24gbg_cr520.conf b/tests/drivers/spi/spi_loopback/boards/rzt2m_rsk_r9a07g075m24gbg_cr520.conf new file mode 100644 index 0000000000000..3de8446aac514 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/rzt2m_rsk_r9a07g075m24gbg_cr520.conf @@ -0,0 +1,5 @@ +CONFIG_SPI_ASYNC=y +CONFIG_SPI_RENESAS_RZ_INTERRUPT=y +CONFIG_SPI_RTIO=n +CONFIG_SPI_LOOPBACK_MODE_LOOP=n +CONFIG_SPI_LARGE_BUFFER_SIZE=2048 diff --git a/tests/drivers/spi/spi_loopback/boards/rzt2m_rsk_r9a07g075m24gbg_cr520.overlay b/tests/drivers/spi/spi_loopback/boards/rzt2m_rsk_r9a07g075m24gbg_cr520.overlay new file mode 100644 index 0000000000000..7cee6555a3cdf --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/rzt2m_rsk_r9a07g075m24gbg_cr520.overlay @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&spi2 { + slow@2 { + compatible = "test-spi-loopback-slow"; + reg = <2>; + spi-max-frequency = <500000>; + }; + + fast@2 { + compatible = "test-spi-loopback-fast"; + reg = <2>; + spi-max-frequency = <2500000>; + }; +}; diff --git a/west.yml b/west.yml index 8ddf3001a042d..c2b4c7bbaba0c 100644 --- a/west.yml +++ b/west.yml @@ -226,7 +226,7 @@ manifest: - hal - name: hal_renesas path: modules/hal/renesas - revision: 53738694cc40f7a7a53c4940209889f1eee556ea + revision: pull/153/head groups: - hal - name: hal_rpi_pico