pkarashchenko commented on code in PR #6492:
URL: https://github.com/apache/incubator-nuttx/pull/6492#discussion_r907082047


##########
arch/arm/src/stm32wl5/hardware/stm32wl5_spi.h:
##########
@@ -0,0 +1,277 @@
+/****************************************************************************
+ * arch/arm/src/stm32wl5/hardware/stm32wl5_spi.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_SPI_H
+#define __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_SPI_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include "chip.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* SPI version **************************************************************/
+
+/* SPI IP v1 is default unless v2 or greater is specified for this chip */
+
+#undef HAVE_SPI_I2S               /* No I2S mode in the SPI peripheral */
+#undef HAVE_SPI_I2S_ASTRT         /* No I2S asynchronous start capability */
+#undef HAVE_SPI_TI_MODE           /* Motorola frame mode only; no TI mode */
+#undef HAVE_SPI_ARB_DATA_SIZE     /* Data size 8 or 16 bit; not arbitrary 4-16 
bit */
+#undef HAVE_SPI_FIFOS             /* No Tx/Rx FIFOs */
+#undef HAVE_SPI_NSSP              /* No NSS Pulse Management in master mode */
+
+#if defined(STM32WL5_HAVE_IP_SPI_V2)
+#  define HAVE_SPI_I2S            /* Some SPI peripherals have I2S mode */
+#  undef HAVE_SPI_I2S_ASTRT       /* No I2S asynchronous start capability */
+#  define HAVE_SPI_TI_MODE        /* Have Motorola and TI frame modes */
+#  undef HAVE_SPI_ARB_DATA_SIZE   /* Data size 8 or 16 bit; not arbitrary 4-16 
bit */
+#  undef HAVE_SPI_FIFOS           /* No Tx/Rx FIFOs */
+#  undef HAVE_SPI_NSSP            /* No NSS Pulse Management in master mode */
+#endif
+
+#if defined(STM32WL5_HAVE_IP_SPI_V3)
+#  define HAVE_SPI_I2S            /* Some SPI peripherals have I2S mode */
+#  undef HAVE_SPI_I2S_ASTRT       /* No I2S asynchronous start capability */
+#  define HAVE_SPI_TI_MODE        /* Have Motorola and TI frame modes */
+#  define HAVE_SPI_ARB_DATA_SIZE  /* Supports arbitrary data size from 4-16 
bits */
+#  define HAVE_SPI_FIFOS          /* Have Tx/Rx FIFOs */
+#  undef HAVE_SPI_NSSP            /* No NSS Pulse Management in master mode */
+#endif
+
+#if defined(STM32WL5_HAVE_IP_SPI_V4)
+#  define HAVE_SPI_I2S            /* Some SPI peripherals have I2S mode */
+#  define HAVE_SPI_I2S_ASTRT      /* Supports I2S asynchronous start 
capability */
+#  define HAVE_SPI_TI_MODE        /* Have Motorola and TI frame modes */
+#  define HAVE_SPI_ARB_DATA_SIZE  /* Supports arbitrary data size from 4-16 
bits */
+#  define HAVE_SPI_FIFOS          /* Have Tx/Rx FIFOs */
+#  define HAVE_SPI_NSSP           /* Have NSS Pulse Management in master mode 
*/
+#endif
+
+/* Maximum allowed speed as per specifications for all SPIs */
+
+#if defined(CONFIG_STM32WL5_STM32F4XXX)
+#  define STM32WL5_SPI_CLK_MAX     37500000UL
+#else
+#  define STM32WL5_SPI_CLK_MAX     18000000UL
+#endif
+
+/* Register Offsets *********************************************************/
+
+#define STM32WL5_SPI_CR1_OFFSET       0x0000  /* SPI Control Register 1 
(16-bit) */
+#define STM32WL5_SPI_CR2_OFFSET       0x0004  /* SPI control register 2 
(16-bit) */
+#define STM32WL5_SPI_SR_OFFSET        0x0008  /* SPI status register (16-bit) 
*/
+#define STM32WL5_SPI_DR_OFFSET        0x000c  /* SPI data register (16-bit) */
+#define STM32WL5_SPI_CRCPR_OFFSET     0x0010  /* SPI CRC polynomial register 
(16-bit) */
+#define STM32WL5_SPI_RXCRCR_OFFSET    0x0014  /* SPI Rx CRC register (16-bit) 
*/
+#define STM32WL5_SPI_TXCRCR_OFFSET    0x0018  /* SPI Tx CRC register (16-bit) 
*/
+
+#if defined(HAVE_SPI_I2S)
+#  define STM32WL5_SPI_I2SCFGR_OFFSET 0x001c  /* I2S configuration register */
+#  define STM32WL5_SPI_I2SPR_OFFSET   0x0020  /* I2S prescaler register */
+#endif
+
+/* Register Addresses *******************************************************/
+
+#if STM32WL5_NSPI > 0
+#  define STM32WL5_SPI1_CR1          \
+  (STM32WL5_SPI1_BASE + STM32WL5_SPI_CR1_OFFSET)
+#  define STM32WL5_SPI1_CR2          \
+  (STM32WL5_SPI1_BASE + STM32WL5_SPI_CR2_OFFSET)
+#  define STM32WL5_SPI1_SR           \
+  (STM32WL5_SPI1_BASE + STM32WL5_SPI_SR_OFFSET)
+#  define STM32WL5_SPI1_DR           \
+  (STM32WL5_SPI1_BASE + STM32WL5_SPI_DR_OFFSET)
+#  define STM32WL5_SPI1_CRCPR        \
+  (STM32WL5_SPI1_BASE + STM32WL5_SPI_CRCPR_OFFSET)
+#  define STM32WL5_SPI1_RXCRCR       \
+  (STM32WL5_SPI1_BASE + STM32WL5_SPI_RXCRCR_OFFSET)
+#  define STM32WL5_SPI1_TXCRCR       \
+  (STM32WL5_SPI1_BASE + STM32WL5_SPI_TXCRCR_OFFSET)
+#endif
+
+#if STM32WL5_NSPI > 1
+#  define STM32WL5_SPI2S2_CR1        \
+  (STM32WL5_SPI2S2_BASE + STM32WL5_SPI_CR1_OFFSET)
+#  define STM32WL5_SPI2S2_CR2        \
+  (STM32WL5_SPI2S2_BASE + STM32WL5_SPI_CR2_OFFSET)
+#  define STM32WL5_SPI2S2_SR         \
+  (STM32WL5_SPI2S2_BASE + STM32WL5_SPI_SR_OFFSET)
+#  define STM32WL5_SPI2S2_DR         \
+  (STM32WL5_SPI2S2_BASE + STM32WL5_SPI_DR_OFFSET)
+#  define STM32WL5_SPI2S2_CRCPR      \
+  (STM32WL5_SPI2S2_BASE + STM32WL5_SPI_CRCPR_OFFSET)
+#  define STM32WL5_SPI2S2_RXCRCR     \
+  (STM32WL5_SPI2S2_BASE + STM32WL5_SPI_RXCRCR_OFFSET)
+#  define STM32WL5_SPI2S2_TXCRCR     \
+  (STM32WL5_SPI2S2_BASE + STM32WL5_SPI_TXCRCR_OFFSET)
+#  if defined(HAVE_SPI_I2S)
+#    define STM32WL5_SPI2S2_I2SCFGR  \
+  (STM32WL5_SPI2S2_BASE + STM32WL5_SPI_I2SCFGR_OFFSET)
+#    define STM32WL5_SPI2S2_I2SPR    \
+  (STM32WL5_SPI2S2_BASE + STM32WL5_SPI_I2SPR_OFFSET)
+#  endif
+#endif
+
+/* Register Bitfield Definitions ********************************************/
+
+/* SPI Control Register 1 */
+
+#define SPI_CR1_CPHA              (1 << 0)                /* Bit 0: Clock 
Phase */
+#define SPI_CR1_CPOL              (1 << 1)                /* Bit 1: Clock 
Polarity */
+#define SPI_CR1_MSTR              (1 << 2)                /* Bit 2: Master 
Selection */
+#define SPI_CR1_BR_SHIFT          (3)                     /* Bits 5:3 Baud 
Rate Control */
+#define SPI_CR1_BR_MASK           (7 << SPI_CR1_BR_SHIFT)
+#  define SPI_CR1_FPCLCKd2        (0 << SPI_CR1_BR_SHIFT) /* 000: fPCLK/2 */
+#  define SPI_CR1_FPCLCKd4        (1 << SPI_CR1_BR_SHIFT) /* 001: fPCLK/4 */
+#  define SPI_CR1_FPCLCKd8        (2 << SPI_CR1_BR_SHIFT) /* 010: fPCLK/8 */
+#  define SPI_CR1_FPCLCKd16       (3 << SPI_CR1_BR_SHIFT) /* 011: fPCLK/16 */
+#  define SPI_CR1_FPCLCKd32       (4 << SPI_CR1_BR_SHIFT) /* 100: fPCLK/32 */
+#  define SPI_CR1_FPCLCKd64       (5 << SPI_CR1_BR_SHIFT) /* 101: fPCLK/64 */
+#  define SPI_CR1_FPCLCKd128      (6 << SPI_CR1_BR_SHIFT) /* 110: fPCLK/128 */
+#  define SPI_CR1_FPCLCKd256      (7 << SPI_CR1_BR_SHIFT) /* 111: fPCLK/256 */
+#define SPI_CR1_SPE               (1 << 6)                /* Bit 6: SPI Enable 
*/
+#define SPI_CR1_LSBFIRST          (1 << 7)                /* Bit 7: Frame 
Format */
+#define SPI_CR1_SSI               (1 << 8)                /* Bit 8: Internal 
slave select */
+#define SPI_CR1_SSM               (1 << 9)                /* Bit 9: Software 
slave management */
+#define SPI_CR1_RXONLY            (1 << 10)               /* Bit 10: Receive 
only */
+#define SPI_CR1_CRCL              (1 << 11)               /* Bit 11: CRC 
length */
+#define SPI_CR1_CRCNEXT           (1 << 12)               /* Bit 12: Transmit 
CRC next */
+#define SPI_CR1_CRCEN             (1 << 13)               /* Bit 13: Hardware 
CRC calculation enable */
+#define SPI_CR1_BIDIOE            (1 << 14)               /* Bit 14: Output 
enable in bidirectional mode */
+#define SPI_CR1_BIDIMODE          (1 << 15)               /* Bit 15: 
Bidirectional data mode enable */
+
+/* SPI Control Register 2 */
+
+#define SPI_CR2_RXDMAEN           (1 << 0)  /* Bit 0: Rx Buffer DMA Enable */
+#define SPI_CR2_TXDMAEN           (1 << 1)  /* Bit 1: Tx Buffer DMA Enable */
+#define SPI_CR2_SSOE              (1 << 2)  /* Bit 2: SS Output Enable */
+
+#if defined(HAVE_SPI_NSSP)
+#  define SPI_CR2_NSSP            (1 << 3)  /* Bit 3: NSS Pulse Management 
(Master mode only) */
+#endif
+
+#if defined(HAVE_SPI_TI_MODE)
+#  define SPI_CR2_FRF             (1 << 4)  /* Bit 4: Frame format: 
0=Motorola, 1=TI */
+#endif
+
+#define SPI_CR2_ERRIE             (1 << 5)  /* Bit 5: Error interrupt enable */
+#define SPI_CR2_RXNEIE            (1 << 6)  /* Bit 6: RX buffer not empty 
interrupt enable */
+#define SPI_CR2_TXEIE             (1 << 7)  /* Bit 7: Tx buffer empty 
interrupt enable */
+
+#define SPI_CR2_DS_SHIFT          (8)       /* Bits 8-11:  Data size */
+#define SPI_CR2_DS_MASK           (15 << SPI_CR2_DS_SHIFT)
+#    define SPI_CR2_DS(n)         ((uint32_t)((n) - 1) << SPI_CR2_DS_SHIFT)
+#    define SPI_CR2_DS_4BIT       (3 << SPI_CR2_DS_SHIFT)
+#    define SPI_CR2_DS_5BIT       (4 << SPI_CR2_DS_SHIFT)
+#    define SPI_CR2_DS_6BIT       (5 << SPI_CR2_DS_SHIFT)
+#    define SPI_CR2_DS_7BIT       (6 << SPI_CR2_DS_SHIFT)
+#    define SPI_CR2_DS_8BIT       (7 << SPI_CR2_DS_SHIFT)
+#    define SPI_CR2_DS_9BIT       (8 << SPI_CR2_DS_SHIFT)
+#    define SPI_CR2_DS_10BIT      (9 << SPI_CR2_DS_SHIFT)
+#    define SPI_CR2_DS_11BIT      (10 << SPI_CR2_DS_SHIFT)
+#    define SPI_CR2_DS_12BIT      (11 << SPI_CR2_DS_SHIFT)
+#    define SPI_CR2_DS_13BIT      (12 << SPI_CR2_DS_SHIFT)
+#    define SPI_CR2_DS_14BIT      (13 << SPI_CR2_DS_SHIFT)
+#    define SPI_CR2_DS_15BIT      (14 << SPI_CR2_DS_SHIFT)
+#    define SPI_CR2_DS_16BIT      (15 << SPI_CR2_DS_SHIFT)

Review Comment:
   remove 2 leading spaces before `define`



##########
arch/arm/src/stm32wl5/stm32wl5_spi.c:
##########
@@ -0,0 +1,1859 @@
+/****************************************************************************
+ * arch/arm/src/stm32wl5/stm32wl5_spi.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * The external functions, stm32wl5_spi1/2select and stm32wl5_spi1/2status
+ * must be provided by board-specific logic.  They are implementations of the
+ * select and status methods of the SPI interface defined by struct spi_ops_s
+ * (see include/nuttx/spi/spi.h).
+ * All other methods (including stm32wl5_spibus_initialize())  are provided
+ * by common STM32 logic.  To use this common SPI logic on your board:
+ *
+ *   1. Provide logic in stm32wl5_boardinitialize() to configure SPI chip
+ *      select pins.
+ *   2. Provide stm32wl5_spi1/2select() and stm32wl5_spi1/2() functions
+ *      in your board-specific logic.  These functions will perform chip
+ *      selection and status operations using GPIOs in the way your board is
+ *      configured.
+ *   3. Add a calls to stm32wl5_spibus_initialize() in your low level
+ *      application initialization logic
+ *   4. The handle returned by stm32wl5_spibus_initialize() may then be used
+ *      to bind the SPI driver to higher level logic (e.g., calling
+ *      mmcsd_spislotinitialize(), for example, will bind the SPI driver to
+ *      the SPI MMC/SD driver).
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <nuttx/semaphore.h>
+#include <nuttx/spi/spi.h>
+
+#include <arch/board/board.h>
+
+#include "arm_internal.h"
+#include "chip.h"
+#include "stm32wl5.h"
+#include "stm32wl5_gpio.h"
+#ifdef CONFIG_STM32WL5_SPI_DMA
+#include "stm32wl5_dma.h"
+#endif
+#include "stm32wl5_spi.h"
+
+#if defined(CONFIG_STM32WL5_SPI1) || defined(CONFIG_STM32WL5_SPI2S2)
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+
+/* SPI interrupts */
+
+#ifdef CONFIG_STM32WL5_SPI_INTERRUPTS
+#  error "Interrupt driven SPI not yet supported"
+#endif
+
+#ifdef CONFIG_STM32WL5_SPI_DMA
+#  error "DMA driven SPI not yet supported"
+#endif
+
+/* Can't have both interrupt driven SPI and SPI DMA */
+
+#if defined(CONFIG_STM32WL5_SPI_INTERRUPTS) && defined(CONFIG_STM32WL5_SPI_DMA)
+#  error "Cannot enable both interrupt mode and DMA mode for SPI"
+#endif
+
+/* SPI DMA priority */
+
+#ifdef CONFIG_STM32WL5_SPI_DMA
+
+#  if defined(CONFIG_SPI_DMAPRIO)
+#    define SPI_DMA_PRIO  CONFIG_SPI_DMAPRIO
+#  elif defined(CONFIG_STM32WL5_STM32WL5XXX_CPU1
+#warning "Verify, read doc and Implement"
+#    define SPI_DMA_PRIO  DMA_CCR_PRIMED
+#  else
+#    error "Unknown STM32WL5 DMA"
+#  endif
+
+#  if defined(CONFIG_STM32WL5_STM32WL5XXX_CPU1)
+#    if (SPI_DMA_PRIO & ~DMA_CCR_PL_MASK) != 0
+#      error "Illegal value for CONFIG_SPI_DMAPRIO"
+#    endif
+#  else
+#    error "Unknown STM32 DMA"
+#  endif
+
+/* DMA channel configuration */
+
+#if defined(CONFIG_STM32WL5_STM32WL5XXX_CPU1)
+#  define SPI_RXDMA16_CONFIG        
(SPI_DMA_PRIO|DMA_CCR_MSIZE_16BITS|DMA_CCR_PSIZE_16BITS|DMA_CCR_MINC            
)
+#  define SPI_RXDMA8_CONFIG         (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS 
|DMA_CCR_PSIZE_8BITS |DMA_CCR_MINC            )
+#  define SPI_RXDMA16NULL_CONFIG    (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS 
|DMA_CCR_PSIZE_16BITS                         )
+#  define SPI_RXDMA8NULL_CONFIG     (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS 
|DMA_CCR_PSIZE_8BITS                          )
+#  define SPI_TXDMA16_CONFIG        
(SPI_DMA_PRIO|DMA_CCR_MSIZE_16BITS|DMA_CCR_PSIZE_16BITS|DMA_CCR_MINC|DMA_CCR_DIR)
+#  define SPI_TXDMA8_CONFIG         (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS 
|DMA_CCR_PSIZE_8BITS |DMA_CCR_MINC|DMA_CCR_DIR)
+#  define SPI_TXDMA16NULL_CONFIG    (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS 
|DMA_CCR_PSIZE_16BITS             |DMA_CCR_DIR)
+#  define SPI_TXDMA8NULL_CONFIG     (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS 
|DMA_CCR_PSIZE_8BITS              |DMA_CCR_DIR)
+#else
+#  error "Unknown STM32WL5 DMA"
+#endif
+
+#  define SPIDMA_BUFFER_MASK   (0x03)
+#  define SPIDMA_SIZE(b) (((b) + SPIDMA_BUFFER_MASK) & ~SPIDMA_BUFFER_MASK)
+#  define SPIDMA_BUF_ALIGN   aligned_data(4)
+
+#  if defined(CONFIG_STM32WL5_SPI1_DMA_BUFFER) && \
+            CONFIG_STM32WL5_SPI1_DMA_BUFFER > 0
+#    define SPI1_DMABUFSIZE_ADJUSTED 
SPIDMA_SIZE(CONFIG_STM32WL5_SPI1_DMA_BUFFER)
+#    define SPI1_DMABUFSIZE_ALGN SPIDMA_BUF_ALIGN
+#  endif
+
+#  if defined(CONFIG_STM32WL5_SPI2S2_DMA_BUFFER) && \
+            CONFIG_STM32WL5_SPI2S2_DMA_BUFFER > 0
+#    define SPI2S2_DMABUFSIZE_ADJUSTED 
SPIDMA_SIZE(CONFIG_STM32WL5_SPI2S2_DMA_BUFFER)
+#    define SPI2S2_DMABUFSIZE_ALGN SPIDMA_BUF_ALIGN
+#  endif
+
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct stm32wl5_spidev_s
+{
+  struct spi_dev_s spidev;       /* Externally visible part of the SPI 
interface */
+  uint32_t         spibase;      /* SPIn base address */
+  uint32_t         spiclock;     /* Clocking for the SPI module */
+#ifdef CONFIG_STM32WL5_SPI_INTERRUPTS
+  uint8_t          spiirq;       /* SPI IRQ number */
+#endif
+#ifdef CONFIG_STM32WL5_SPI_DMA
+  volatile uint8_t rxresult;     /* Result of the RX DMA */
+  volatile uint8_t txresult;     /* Result of the RX DMA */
+#ifdef CONFIG_SPI_TRIGGER
+  bool             defertrig;    /* Flag indicating that trigger should be 
deferred */
+  bool             trigarmed;    /* Flag indicating that the trigger is armed 
*/
+#endif
+  uint8_t          rxch;         /* The RX DMA channel number */
+  uint8_t          txch;         /* The TX DMA channel number */
+  uint8_t          *rxbuf;       /* The RX DMA buffer */
+  uint8_t          *txbuf;       /* The TX DMA buffer */
+  size_t           buflen;       /* The DMA buffer length */
+  DMA_HANDLE       rxdma;        /* DMA channel handle for RX transfers */
+  DMA_HANDLE       txdma;        /* DMA channel handle for TX transfers */
+  sem_t            rxsem;        /* Wait for RX DMA to complete */
+  sem_t            txsem;        /* Wait for TX DMA to complete */
+  uint32_t         txccr;        /* DMA control register for TX transfers */
+  uint32_t         rxccr;        /* DMA control register for RX transfers */
+#endif
+  bool             initialized;  /* Has SPI interface been initialized */
+  sem_t            exclsem;      /* Held while chip is selected for mutual 
exclusion */
+  uint32_t         frequency;    /* Requested clock frequency */
+  uint32_t         actual;       /* Actual clock frequency */
+  uint8_t          nbits;        /* Width of word in bits (4 through 16) */
+  uint8_t          mode;         /* Mode 0,1,2,3 */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Helpers */
+
+static inline uint16_t spi_getreg(struct stm32wl5_spidev_s *priv,
+                                  uint8_t offset);
+
+static inline uint8_t spi_getreg8(struct stm32wl5_spidev_s *priv,
+                                  uint8_t offset);
+
+static inline void spi_putreg(struct stm32wl5_spidev_s *priv,
+                              uint8_t offset,
+                              uint16_t value);
+
+static inline void spi_putreg8(struct stm32wl5_spidev_s *priv,
+                               uint8_t offset,
+                               uint8_t value);
+
+static inline uint16_t spi_readword(struct stm32wl5_spidev_s *priv);
+static inline void spi_writeword(struct stm32wl5_spidev_s *priv,
+                                 uint16_t byte);
+
+/* DMA support */
+
+#ifdef CONFIG_STM32WL5_SPI_DMA
+static int         spi_dmarxwait(struct stm32wl5_spidev_s *priv);
+static int         spi_dmatxwait(struct stm32wl5_spidev_s *priv);
+static inline void spi_dmarxwakeup(struct stm32wl5_spidev_s *priv);
+static inline void spi_dmatxwakeup(struct stm32wl5_spidev_s *priv);
+static void        spi_dmarxcallback(DMA_HANDLE handle, uint8_t isr,
+                                     void *arg);
+static void        spi_dmatxcallback(DMA_HANDLE handle, uint8_t isr,
+                                     void *arg);
+static void        spi_dmarxsetup(struct stm32wl5_spidev_s *priv,
+                                  void *rxbuffer,
+                                  void *rxdummy,
+                                  size_t nwords);
+static void        spi_dmatxsetup(struct stm32wl5_spidev_s *priv,
+                                  const void *txbuffer,
+                                  const void *txdummy,
+                                  size_t nwords);
+static inline void spi_dmarxstart(struct stm32wl5_spidev_s *priv);
+static inline void spi_dmatxstart(struct stm32wl5_spidev_s *priv);
+#endif
+
+/* SPI methods */
+
+static int         spi_lock(struct spi_dev_s *dev, bool lock);
+static uint32_t    spi_setfrequency(struct spi_dev_s *dev,
+                                    uint32_t frequency);
+static void        spi_setmode(struct spi_dev_s *dev,
+                               enum spi_mode_e mode);
+static void        spi_setbits(struct spi_dev_s *dev, int nbits);
+#ifdef CONFIG_SPI_HWFEATURES
+static int         spi_hwfeatures(struct spi_dev_s *dev,
+                                  spi_hwfeatures_t features);
+#endif
+static uint32_t    spi_send(struct spi_dev_s *dev, uint32_t wd);
+static void        spi_exchange(struct spi_dev_s *dev,
+                                const void *txbuffer,
+                                void *rxbuffer, size_t nwords);
+#ifdef CONFIG_SPI_TRIGGER
+static int         spi_trigger(struct spi_dev_s *dev);
+#endif
+#ifndef CONFIG_SPI_EXCHANGE
+static void        spi_sndblock(struct spi_dev_s *dev,
+                                const void *txbuffer,
+                                size_t nwords);
+static void        spi_recvblock(struct spi_dev_s *dev,
+                                 void *rxbuffer,
+                                 size_t nwords);
+#endif
+
+/* Initialization */
+
+static void        spi_bus_initialize(struct stm32wl5_spidev_s *priv);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32WL5_SPI1
+static const struct spi_ops_s g_sp1iops =
+{
+  .lock              = spi_lock,
+  .select            = stm32wl5_spi1select,
+  .setfrequency      = spi_setfrequency,
+  .setmode           = spi_setmode,
+  .setbits           = spi_setbits,
+#ifdef CONFIG_SPI_HWFEATURES
+  .hwfeatures        = spi_hwfeatures,
+#endif
+  .status            = stm32wl5_spi1status,
+#ifdef CONFIG_SPI_CMDDATA
+  .cmddata           = stm32wl5_spi1cmddata,
+#endif
+  .send              = spi_send,
+#ifdef CONFIG_SPI_EXCHANGE
+  .exchange          = spi_exchange,
+#else
+  .sndblock          = spi_sndblock,
+  .recvblock         = spi_recvblock,
+#endif
+#ifdef CONFIG_SPI_TRIGGER
+  .trigger           = spi_trigger,
+#endif
+#ifdef CONFIG_SPI_CALLBACK
+  .registercallback  = stm32wl5_spi1register,  /* Provided externally */
+#else
+  .registercallback  = 0,                   /* Not implemented */
+#endif
+};
+
+#if defined(SPI1_DMABUFSIZE_ADJUSTED)
+static uint8_t g_spi1_txbuf[SPI1_DMABUFSIZE_ADJUSTED] SPI1_DMABUFSIZE_ALGN;
+static uint8_t g_spi1_rxbuf[SPI1_DMABUFSIZE_ADJUSTED] SPI1_DMABUFSIZE_ALGN;
+#endif
+
+static struct stm32wl5_spidev_s g_spi1dev =
+{
+  .spidev   =
+    {
+      &g_sp1iops
+    },
+  .spibase  = STM32WL5_SPI1_BASE,
+  .spiclock = STM32WL5_PCLK2_FREQUENCY,
+#ifdef CONFIG_STM32WL5_SPI_INTERRUPTS
+  .spiirq   = STM32WL5_IRQ_SPI1,
+#endif
+#ifdef CONFIG_STM32WL5_SPI_DMA
+#  ifdef CONFIG_STM32WL5_SPI1_DMA
+  .rxch     = DMACHAN_SPI1_RX,
+  .txch     = DMACHAN_SPI1_TX,
+#if defined(SPI1_DMABUFSIZE_ADJUSTED)
+  .rxbuf    = g_spi1_rxbuf,
+  .txbuf    = g_spi1_txbuf,
+  .buflen   = SPI1_DMABUFSIZE_ADJUSTED,
+#    endif
+#  else
+  .rxch     = 0,
+  .txch     = 0,
+#  endif
+#endif
+};
+#endif
+
+#ifdef CONFIG_STM32WL5_SPI2S2
+static const struct spi_ops_s g_sp2iops =
+{
+  .lock              = spi_lock,
+  .select            = stm32wl5_spi2s2select,
+  .setfrequency      = spi_setfrequency,
+  .setmode           = spi_setmode,
+  .setbits           = spi_setbits,
+#ifdef CONFIG_SPI_HWFEATURES
+  .hwfeatures        = spi_hwfeatures,
+#endif
+  .status            = stm32wl5_spi2s2status,
+#ifdef CONFIG_SPI_CMDDATA
+  .cmddata           = stm32wl5_spi2s2cmddata,
+#endif
+  .send              = spi_send,
+#ifdef CONFIG_SPI_EXCHANGE
+  .exchange          = spi_exchange,
+#else
+  .sndblock          = spi_sndblock,
+  .recvblock         = spi_recvblock,
+#endif
+#ifdef CONFIG_SPI_TRIGGER
+  .trigger           = spi_trigger,
+#endif
+#ifdef CONFIG_SPI_CALLBACK
+  .registercallback  = stm32wl5_s2register,  /* provided externally */
+#else
+  .registercallback  = 0,                   /* not implemented */
+#endif
+};
+
+#if defined(SPI2S2_DMABUFSIZE_ADJUSTED)
+static uint8_t g_spi2s2_txbuf[SPI2S2_DMABUFSIZE_ADJUSTED]
+  SPI2S2_DMABUFSIZE_ALGN;
+static uint8_t g_spi2s2_rxbuf[SPI2S2_DMABUFSIZE_ADJUSTED]
+  SPI2S2_DMABUFSIZE_ALGN;
+#endif
+
+static struct stm32wl5_spidev_s g_spi2s2dev =
+{
+  .spidev   =
+    {
+      &g_sp2iops
+    },
+  .spibase  = STM32WL5_SPI2S2_BASE,
+  .spiclock = STM32WL5_PCLK1_FREQUENCY,
+#ifdef CONFIG_STM32WL5_SPI_INTERRUPTS
+  .spiirq   = STM32WL5_IRQ_SPI2S2,
+#endif
+#ifdef CONFIG_STM32WL5_SPI_DMA
+#  ifdef CONFIG_STM32WL5_SPI2S2_DMA
+  .rxch     = DMACHAN_SPI2S2_RX,
+  .txch     = DMACHAN_SPI2S2_TX,
+#if defined(SPI2S2_DMABUFSIZE_ADJUSTED)
+  .rxbuf    = g_spi2s2_rxbuf,
+  .txbuf    = g_spi2s2_txbuf,
+  .buflen   = SPI2S2_DMABUFSIZE_ADJUSTED,
+#    endif
+#  else
+  .rxch     = 0,
+  .txch     = 0,
+#  endif
+#endif
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: spi_getreg8
+ *
+ * Description:
+ *   Get the contents of the SPI register at offset
+ *
+ * Input Parameters:
+ *   priv   - private SPI device structure
+ *   offset - offset to the register of interest
+ *
+ * Returned Value:
+ *   The contents of the 16-bit register
+ *
+ ****************************************************************************/
+
+static inline uint8_t spi_getreg8(struct stm32wl5_spidev_s *priv,
+                                  uint8_t offset)
+{
+  return getreg8(priv->spibase + offset);
+}
+
+/****************************************************************************
+ * Name: spi_getreg
+ *
+ * Description:
+ *   Get the contents of the SPI register at offset
+ *
+ * Input Parameters:
+ *   priv   - private SPI device structure
+ *   offset - offset to the register of interest
+ *
+ * Returned Value:
+ *   The contents of the 16-bit register
+ *
+ ****************************************************************************/
+
+static inline uint16_t spi_getreg(struct stm32wl5_spidev_s *priv,
+                                  uint8_t offset)
+{
+  return getreg16(priv->spibase + offset);
+}
+
+/****************************************************************************
+ * Name: spi_putreg
+ *
+ * Description:
+ *   Write a 16-bit value to the SPI register at offset
+ *
+ * Input Parameters:
+ *   priv   - private SPI device structure
+ *   offset - offset to the register of interest
+ *   value  - the 16-bit value to be written
+ *
+ * Returned Value:
+ *   The contents of the 16-bit register
+ *
+ ****************************************************************************/
+
+static inline void spi_putreg(struct stm32wl5_spidev_s *priv,
+                              uint8_t offset,
+                              uint16_t value)
+{
+  putreg16(value, priv->spibase + offset);
+}
+
+/****************************************************************************
+ * Name: spi_putreg8
+ *
+ * Description:
+ *   Write an 8-bit value to the SPI register at offset
+ *
+ * Input Parameters:
+ *   priv   - private SPI device structure
+ *   offset - offset to the register of interest
+ *   value  - the 16-bit value to be written
+ *
+ * Returned Value:
+ *   The contents of the 16-bit register
+ *
+ ****************************************************************************/
+
+static inline void spi_putreg8(struct stm32wl5_spidev_s *priv,
+                               uint8_t offset,
+                               uint8_t value)
+{
+  putreg8(value, priv->spibase + offset);
+}
+
+/****************************************************************************
+ * Name: spi_readword
+ *
+ * Description:
+ *   Read one byte from SPI
+ *
+ * Input Parameters:
+ *   priv - Device-specific state data
+ *
+ * Returned Value:
+ *   Byte as read
+ *
+ ****************************************************************************/
+
+static inline uint16_t spi_readword(struct stm32wl5_spidev_s *priv)
+{
+  /* Wait until the receive buffer is not empty */
+
+  while ((spi_getreg(priv, STM32WL5_SPI_SR_OFFSET) & SPI_SR_RXNE) == 0)
+    {
+    }
+
+  /* Then return the received byte */
+
+  /* "When the data frame size fits into one byte
+   * (less than or equal to 8 bits),
+   *  data packing is used automatically when any read or write 16-bit access
+   *  is performed on the SPIx_DR register. The double data frame pattern is
+   *  handled in parallel in this case. At first, the SPI operates using the
+   *  pattern stored in the LSB of the accessed word, then with the other
+   *  half stored in the MSB.... The receiver then has to access both data
+   *  frames by a single 16-bit read of SPIx_DR as a response to this single
+   *  RXNE event. The RxFIFO threshold setting and the following read access
+   *  must be always kept aligned at the receiver side, as data can be lost
+   *  if it is not in line."
+   */
+
+  if (priv->nbits < 9)
+    {
+      return (uint16_t)spi_getreg8(priv, STM32WL5_SPI_DR_OFFSET);
+    }
+  else
+    {
+      return spi_getreg(priv, STM32WL5_SPI_DR_OFFSET);
+    }
+}
+
+/****************************************************************************
+ * Name: spi_writeword
+ *
+ * Description:
+ *   Write one word or byte to SPI. If the frame size is 8 bit or lower
+ *   a byte is written. In other case a word is written.
+ *
+ * Input Parameters:
+ *   priv - Device-specific state data
+ *   word - word to send
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static inline void spi_writeword(struct stm32wl5_spidev_s *priv,
+                                 uint16_t word)
+{
+  /* Wait until the transmit buffer is empty */
+
+  while ((spi_getreg(priv, STM32WL5_SPI_SR_OFFSET) & SPI_SR_TXE) == 0)
+    {
+    }
+
+  /* Then send the word */
+
+  if (priv->nbits < 9)
+    {
+      spi_putreg8(priv, STM32WL5_SPI_DR_OFFSET, (uint8_t)word);
+    }
+  else
+    {
+      spi_putreg(priv, STM32WL5_SPI_DR_OFFSET, word);
+    }
+}
+
+/****************************************************************************
+ * Name: spi_dmarxwait
+ *
+ * Description:
+ *   Wait for DMA to complete.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32WL5_SPI_DMA
+static int spi_dmarxwait(struct stm32wl5_spidev_s *priv)
+{
+  int ret;
+
+  /* Take the semaphore (perhaps waiting).  If the result is zero, then the
+   * DMA must not really have completed???
+   */
+
+  do
+    {
+      ret = nxsem_wait_uninterruptible(&priv->rxsem);
+
+      /* The only expected error is ECANCELED which would occur if the
+       * calling thread were canceled.
+       */
+
+      DEBUGASSERT(ret == OK || ret == -ECANCELED);
+    }
+  while (priv->rxresult == 0 && ret != OK);
+
+  return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: spi_dmatxwait
+ *
+ * Description:
+ *   Wait for DMA to complete.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32WL5_SPI_DMA
+static int spi_dmatxwait(struct stm32wl5_spidev_s *priv)
+{
+  int ret;
+
+  /* Take the semaphore (perhaps waiting).  If the result is zero, then the
+   * DMA must not really have completed???
+   */
+
+  do
+    {
+      ret = nxsem_wait_uninterruptible(&priv->txsem);
+
+      /* The only expected error is ECANCELED which would occur if the
+       * calling thread were canceled.
+       */
+
+      DEBUGASSERT(ret == OK || ret == -ECANCELED);
+    }
+  while (priv->txresult == 0 && ret != OK);
+
+  return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: spi_dmarxwakeup
+ *
+ * Description:
+ *   Signal that DMA is complete
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32WL5_SPI_DMA
+static inline void spi_dmarxwakeup(struct stm32wl5_spidev_s *priv)
+{
+  nxsem_post(&priv->rxsem);
+}
+#endif
+
+/****************************************************************************
+ * Name: spi_dmatxwakeup
+ *
+ * Description:
+ *   Signal that DMA is complete
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32WL5_SPI_DMA
+static inline void spi_dmatxwakeup(struct stm32wl5_spidev_s *priv)
+{
+  nxsem_post(&priv->txsem);
+}
+#endif
+
+/****************************************************************************
+ * Name: spi_dmarxcallback
+ *
+ * Description:
+ *   Called when the RX DMA completes
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32WL5_SPI_DMA
+static void spi_dmarxcallback(DMA_HANDLE handle, uint8_t isr, void *arg)
+{
+  struct stm32wl5_spidev_s *priv = (struct stm32wl5_spidev_s *)arg;
+
+  /* Wake-up the SPI driver */
+
+  priv->rxresult = isr | 0x80;  /* OR'ed with 0x80 to assure non-zero */
+  spi_dmarxwakeup(priv);
+}
+#endif
+
+/****************************************************************************
+ * Name: spi_dmatxcallback
+ *
+ * Description:
+ *   Called when the RX DMA completes
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32WL5_SPI_DMA
+static void spi_dmatxcallback(DMA_HANDLE handle, uint8_t isr, void *arg)
+{
+  struct stm32wl5_spidev_s *priv = (struct stm32wl5_spidev_s *)arg;
+
+  /* Wake-up the SPI driver */
+
+  priv->txresult = isr | 0x80;  /* OR'ed with 0x80 to assure non-zero */
+  spi_dmatxwakeup(priv);
+}
+#endif
+
+/****************************************************************************
+ * Name: spi_dmarxsetup
+ *
+ * Description:
+ *   Setup to perform RX DMA
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32WL5_SPI_DMA
+static void spi_dmarxsetup(struct stm32wl5_spidev_s *priv,
+                           void *rxbuffer,
+                           void *rxdummy, size_t nwords)
+{
+  /* 8- or 16-bit mode? */
+
+  if (priv->nbits > 8)
+    {
+      /* 16-bit mode -- is there a buffer to receive data in? */
+
+      if (rxbuffer)
+        {
+          priv->rxccr = SPI_RXDMA16_CONFIG;
+        }
+      else
+        {
+          rxbuffer    = rxdummy;
+          priv->rxccr = SPI_RXDMA16NULL_CONFIG;
+        }
+    }
+  else
+    {
+      /* 8-bit mode -- is there a buffer to receive data in? */
+
+      if (rxbuffer)
+        {
+          priv->rxccr = SPI_RXDMA8_CONFIG;
+        }
+      else
+        {
+          rxbuffer    = rxdummy;
+          priv->rxccr = SPI_RXDMA8NULL_CONFIG;
+        }
+    }
+
+  /* Configure the RX DMA */
+
+  stm32wl5_dmasetup(priv->rxdma, priv->spibase + STM32WL5_SPI_DR_OFFSET,
+                    (uint32_t)rxbuffer, nwords, priv->rxccr);
+}
+#endif
+
+/****************************************************************************
+ * Name: spi_dmatxsetup
+ *
+ * Description:
+ *   Setup to perform TX DMA
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32WL5_SPI_DMA
+static void spi_dmatxsetup(struct stm32wl5_spidev_s *priv,
+                           const void *txbuffer,
+                           const void *txdummy, size_t nwords)
+{
+  /* 8- or 16-bit mode? */
+
+  if (priv->nbits > 8)
+    {
+      /* 16-bit mode -- is there a buffer to transfer data from? */
+
+      if (txbuffer)
+        {
+          priv->txccr = SPI_TXDMA16_CONFIG;
+        }
+      else
+        {
+          txbuffer    = txdummy;
+          priv->txccr = SPI_TXDMA16NULL_CONFIG;
+        }
+    }
+  else
+    {
+      /* 8-bit mode -- is there a buffer to transfer data from? */
+
+      if (txbuffer)
+        {
+          priv->txccr = SPI_TXDMA8_CONFIG;
+        }
+      else
+        {
+          txbuffer    = txdummy;
+          priv->txccr = SPI_TXDMA8NULL_CONFIG;
+        }
+    }
+
+  /* Setup the TX DMA */
+
+  stm32wl5_dmasetup(priv->txdma, priv->spibase + STM32WL5_SPI_DR_OFFSET,
+                    (uint32_t)txbuffer, nwords, priv->txccr);
+}
+#endif
+
+/****************************************************************************
+ * Name: spi_dmarxstart
+ *
+ * Description:
+ *   Start RX DMA
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32WL5_SPI_DMA
+static inline void spi_dmarxstart(struct stm32wl5_spidev_s *priv)
+{
+  priv->rxresult = 0;
+  stm32wl5_dmastart(priv->rxdma, spi_dmarxcallback, priv, false);
+}
+#endif
+
+/****************************************************************************
+ * Name: spi_dmatxstart
+ *
+ * Description:
+ *   Start TX DMA
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32WL5_SPI_DMA
+static inline void spi_dmatxstart(struct stm32wl5_spidev_s *priv)
+{
+  priv->txresult = 0;
+  stm32wl5_dmastart(priv->txdma, spi_dmatxcallback, priv, false);
+}
+#endif
+
+/****************************************************************************
+ * Name: spi_modifycr1
+ *
+ * Description:
+ *   Clear and set bits in the CR1 register
+ *
+ * Input Parameters:
+ *   priv    - Device-specific state data
+ *   clrbits - The bits to clear
+ *   setbits - The bits to set
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void spi_modifycr1(struct stm32wl5_spidev_s *priv,
+                          uint16_t setbits,
+                          uint16_t clrbits)
+{
+  uint16_t cr1;
+  cr1 = spi_getreg(priv, STM32WL5_SPI_CR1_OFFSET);
+  cr1 &= ~clrbits;
+  cr1 |= setbits;
+  spi_putreg(priv, STM32WL5_SPI_CR1_OFFSET, cr1);
+
+  spiinfo("CR1 (0x%lx) = 0x%04x\n", priv->spibase + STM32WL5_SPI_CR1_OFFSET,
+          cr1);
+}
+
+/****************************************************************************
+ * Name: spi_modifycr2
+ *
+ * Description:
+ *   Clear and set bits in the CR2 register
+ *
+ * Input Parameters:
+ *   priv    - Device-specific state data
+ *   clrbits - The bits to clear
+ *   setbits - The bits to set
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void spi_modifycr2(struct stm32wl5_spidev_s *priv, uint16_t setbits,
+                          uint16_t clrbits)
+{
+  uint16_t cr2;
+  cr2  = spi_getreg(priv, STM32WL5_SPI_CR2_OFFSET);
+  cr2 &= ~clrbits;
+  cr2 |= setbits;
+  spi_putreg(priv, STM32WL5_SPI_CR2_OFFSET, cr2);
+  spiinfo("CR2 (0x%lx) = 0x%04x\n", priv->spibase + STM32WL5_SPI_CR2_OFFSET,
+          cr2);
+}
+
+/****************************************************************************
+ * Name: spi_lock
+ *
+ * Description:
+ *   On SPI buses where there are multiple devices, it will be necessary to
+ *   lock SPI to have exclusive access to the buses for a sequence of
+ *   transfers.  The bus should be locked before the chip is selected. After
+ *   locking the SPI bus, the caller should then also call the setfrequency,
+ *   setbits, and setmode methods to make sure that the SPI is properly
+ *   configured for the device.  If the SPI bus is being shared, then it
+ *   may have been left in an incompatible state.
+ *
+ * Input Parameters:
+ *   dev  - Device-specific state data
+ *   lock - true: Lock spi bus, false: unlock SPI bus
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static int spi_lock(struct spi_dev_s *dev, bool lock)
+{
+  struct stm32wl5_spidev_s *priv = (struct stm32wl5_spidev_s *)dev;
+  int ret;
+
+  if (lock)
+    {
+      ret = nxsem_wait_uninterruptible(&priv->exclsem);
+    }
+  else
+    {
+      ret = nxsem_post(&priv->exclsem);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: spi_setfrequency
+ *
+ * Description:
+ *   Set the SPI frequency.
+ *
+ * Input Parameters:
+ *   dev -       Device-specific state data
+ *   frequency - The SPI frequency requested
+ *
+ * Returned Value:
+ *   Returns the actual frequency selected
+ *
+ ****************************************************************************/
+
+static uint32_t spi_setfrequency(struct spi_dev_s *dev,
+                                 uint32_t frequency)
+{
+  struct stm32wl5_spidev_s *priv = (struct stm32wl5_spidev_s *)dev;
+  uint16_t setbits;
+  uint32_t actual;
+
+  /* Has the frequency changed? */
+
+  if (frequency != priv->frequency)
+    {
+      /* Choices are limited by PCLK frequency with a set of divisors */
+
+      if (frequency >= priv->spiclock >> 1)
+        {
+          /* More than fPCLK/2.  This is as fast as we can go */
+
+          setbits = SPI_CR1_FPCLCKd2; /* 000: fPCLK/2 */
+          actual = priv->spiclock >> 1;
+        }
+      else if (frequency >= priv->spiclock >> 2)
+        {
+          /* Between fPCLCK/2 and fPCLCK/4, pick the slower */
+
+          setbits = SPI_CR1_FPCLCKd4; /* 001: fPCLK/4 */
+          actual = priv->spiclock >> 2;
+        }
+      else if (frequency >= priv->spiclock >> 3)
+        {
+          /* Between fPCLCK/4 and fPCLCK/8, pick the slower */
+
+          setbits = SPI_CR1_FPCLCKd8; /* 010: fPCLK/8 */
+          actual = priv->spiclock >> 3;
+        }
+      else if (frequency >= priv->spiclock >> 4)
+        {
+          /* Between fPCLCK/8 and fPCLCK/16, pick the slower */
+
+          setbits = SPI_CR1_FPCLCKd16; /* 011: fPCLK/16 */
+          actual = priv->spiclock >> 4;
+        }
+      else if (frequency >= priv->spiclock >> 5)
+        {
+          /* Between fPCLCK/16 and fPCLCK/32, pick the slower */
+
+          setbits = SPI_CR1_FPCLCKd32; /* 100: fPCLK/32 */
+          actual = priv->spiclock >> 5;
+        }
+      else if (frequency >= priv->spiclock >> 6)
+        {
+          /* Between fPCLCK/32 and fPCLCK/64, pick the slower */
+
+          setbits = SPI_CR1_FPCLCKd64; /*  101: fPCLK/64 */
+          actual = priv->spiclock >> 6;
+        }
+      else if (frequency >= priv->spiclock >> 7)
+        {
+          /* Between fPCLCK/64 and fPCLCK/128, pick the slower */
+
+          setbits = SPI_CR1_FPCLCKd128; /* 110: fPCLK/128 */
+          actual = priv->spiclock >> 7;
+        }
+      else
+        {
+          /* Less than fPCLK/128.  This is as slow as we can go */
+
+          setbits = SPI_CR1_FPCLCKd256; /* 111: fPCLK/256 */
+          actual = priv->spiclock >> 8;
+        }
+
+      spi_modifycr1(priv, 0, SPI_CR1_SPE);
+      spi_modifycr1(priv, setbits, SPI_CR1_BR_MASK);
+      spi_modifycr1(priv, SPI_CR1_SPE, 0);
+
+      /* Save the frequency selection so that subsequent reconfigurations
+       * will be faster.
+       */
+
+      spiinfo("Frequency %" PRIu32 "->%" PRIu32 "\n", frequency, actual);
+
+      priv->frequency = frequency;
+      priv->actual    = actual;
+    }
+
+  return priv->actual;
+}
+
+/****************************************************************************
+ * Name: spi_setmode
+ *
+ * Description:
+ *   Set the SPI mode.  see enum spi_mode_e for mode definitions
+ *
+ * Input Parameters:
+ *   dev  - Device-specific state data
+ *   mode - The SPI mode requested
+ *
+ * Returned Value:
+ *   Returns the actual frequency selected
+ *
+ ****************************************************************************/
+
+static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode)
+{
+  struct stm32wl5_spidev_s *priv = (struct stm32wl5_spidev_s *)dev;
+  uint16_t setbits;
+  uint16_t clrbits;
+
+  spiinfo("mode=%d\n", mode);
+
+  /* Has the mode changed? */
+
+  if (mode != priv->mode)
+    {
+      /* Yes... Set CR1 appropriately */
+
+      switch (mode)
+        {
+        case SPIDEV_MODE0: /* CPOL=0; CPHA=0 */
+          setbits = 0;
+          clrbits = SPI_CR1_CPOL | SPI_CR1_CPHA;
+          break;
+
+        case SPIDEV_MODE1: /* CPOL=0; CPHA=1 */
+          setbits = SPI_CR1_CPHA;
+          clrbits = SPI_CR1_CPOL;
+          break;
+
+        case SPIDEV_MODE2: /* CPOL=1; CPHA=0 */
+          setbits = SPI_CR1_CPOL;
+          clrbits = SPI_CR1_CPHA;
+          break;
+
+        case SPIDEV_MODE3: /* CPOL=1; CPHA=1 */
+          setbits = SPI_CR1_CPOL | SPI_CR1_CPHA;
+          clrbits = 0;
+          break;
+
+#ifdef SPI_CR2_FRF    /* If MCU supports TI Synchronous Serial Frame Format */
+        case SPIDEV_MODETI:
+          setbits = 0;
+          clrbits = SPI_CR1_CPOL | SPI_CR1_CPHA;
+          break;
+#endif
+
+        default:
+          return;
+        }
+
+        spi_modifycr1(priv, 0, SPI_CR1_SPE);
+        spi_modifycr1(priv, setbits, clrbits);
+        spi_modifycr1(priv, SPI_CR1_SPE, 0);
+
+#ifdef SPI_CR2_FRF    /* If MCU supports TI Synchronous Serial Frame Format */
+      switch (mode)
+        {
+          case SPIDEV_MODE0:
+          case SPIDEV_MODE1:
+          case SPIDEV_MODE2:
+          case SPIDEV_MODE3:
+            setbits = 0;
+            clrbits = SPI_CR2_FRF;
+            break;
+
+          case SPIDEV_MODETI:
+            setbits = SPI_CR2_FRF;
+            clrbits = 0;
+            break;
+
+          default:
+            return;
+        }
+
+      spi_modifycr1(priv, 0, SPI_CR1_SPE);
+      spi_modifycr2(priv, setbits, clrbits);
+      spi_modifycr1(priv, SPI_CR1_SPE, 0);
+#endif
+
+        /* Save the mode so that subsequent re-configurations will be
+         * faster
+         */
+
+        priv->mode = mode;

Review Comment:
   remove 2 leading spaces



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to