zephyr/ext/hal/qmsi/drivers/include/qm_ss_spi.h

440 lines
15 KiB
C

/*
* Copyright (c) 2016, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL CORPORATION OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __QM_SS_SPI_H__
#define __QM_SS_SPI_H__
#include "qm_common.h"
#include "qm_sensor_regs.h"
#if HAS_SS_DMA
#include "qm_ss_dma.h"
#endif
/**
* SPI peripheral driver for Sensor Subsystem.
*
* @defgroup groupSSSPI SS SPI
* @{
*/
/**
* QM Sensor SPI frame size type
*/
typedef enum {
QM_SS_SPI_FRAME_SIZE_4_BIT = 3, /**< 4 bit frame. */
QM_SS_SPI_FRAME_SIZE_5_BIT, /**< 5 bit frame. */
QM_SS_SPI_FRAME_SIZE_6_BIT, /**< 6 bit frame. */
QM_SS_SPI_FRAME_SIZE_7_BIT, /**< 7 bit frame. */
QM_SS_SPI_FRAME_SIZE_8_BIT, /**< 8 bit frame. */
QM_SS_SPI_FRAME_SIZE_9_BIT, /**< 9 bit frame. */
QM_SS_SPI_FRAME_SIZE_10_BIT, /**< 10 bit frame. */
QM_SS_SPI_FRAME_SIZE_11_BIT, /**< 11 bit frame. */
QM_SS_SPI_FRAME_SIZE_12_BIT, /**< 12 bit frame. */
QM_SS_SPI_FRAME_SIZE_13_BIT, /**< 13 bit frame. */
QM_SS_SPI_FRAME_SIZE_14_BIT, /**< 14 bit frame. */
QM_SS_SPI_FRAME_SIZE_15_BIT, /**< 15 bit frame. */
QM_SS_SPI_FRAME_SIZE_16_BIT, /**< 16 bit frame. */
#if HAS_SS_SPI_32BIT
QM_SS_SPI_FRAME_SIZE_17_BIT, /**< 17 bit frame. */
QM_SS_SPI_FRAME_SIZE_18_BIT, /**< 18 bit frame. */
QM_SS_SPI_FRAME_SIZE_19_BIT, /**< 19 bit frame. */
QM_SS_SPI_FRAME_SIZE_20_BIT, /**< 20 bit frame. */
QM_SS_SPI_FRAME_SIZE_21_BIT, /**< 21 bit frame. */
QM_SS_SPI_FRAME_SIZE_22_BIT, /**< 22 bit frame. */
QM_SS_SPI_FRAME_SIZE_23_BIT, /**< 23 bit frame. */
QM_SS_SPI_FRAME_SIZE_24_BIT, /**< 24 bit frame. */
QM_SS_SPI_FRAME_SIZE_25_BIT, /**< 25 bit frame. */
QM_SS_SPI_FRAME_SIZE_26_BIT, /**< 26 bit frame. */
QM_SS_SPI_FRAME_SIZE_27_BIT, /**< 27 bit frame. */
QM_SS_SPI_FRAME_SIZE_28_BIT, /**< 28 bit frame. */
QM_SS_SPI_FRAME_SIZE_29_BIT, /**< 29 bit frame. */
QM_SS_SPI_FRAME_SIZE_30_BIT, /**< 30 bit frame. */
QM_SS_SPI_FRAME_SIZE_31_BIT, /**< 31 bit frame. */
QM_SS_SPI_FRAME_SIZE_32_BIT /**< 32 bit frame. */
#endif /* HAS_SS_SPI_32BIT */
} qm_ss_spi_frame_size_t;
/**
* SPI transfer mode type.
*/
typedef enum {
/**
* Transmit & Receive mode.
*
* This mode synchronously receives and transmits data during the
* transfer. rx_len and tx_len buffer need to be the same length.
*/
QM_SS_SPI_TMOD_TX_RX,
/**
* Transmit-Only mode.
*
* This mode only transmits data. The rx buffer is not accessed and
* rx_len need to be set to 0.
*/
QM_SS_SPI_TMOD_TX,
/**
* Receive-Only mode.
*
* This mode only receives data. The tx buffer is not accessed and
* tx_len need to be set to 0.
*/
QM_SS_SPI_TMOD_RX,
/**
* EEPROM-Read Mode.
*
* This mode transmits the data stored in the tx buffer (EEPROM
* address). After the transmit is completed it populates the rx buffer
* (EEPROM data) with received data.
*/
QM_SS_SPI_TMOD_EEPROM_READ
} qm_ss_spi_tmode_t;
/**
* SPI Bus Mode Type
*/
typedef enum {
QM_SS_SPI_BMODE_0 = 0, /**< Clock Polarity = 0, Clock Phase = 0. */
QM_SS_SPI_BMODE_1, /**< Clock Polarity = 0, Clock Phase = 1. */
QM_SS_SPI_BMODE_2, /**< Clock Polarity = 1, Clock Phase = 0. */
QM_SS_SPI_BMODE_3 /**< Clock Polarity = 1, Clock Phase = 1. */
} qm_ss_spi_bmode_t;
/**
* SPI Slave select type.
*
* Slave selects can be combined by logical OR.
*/
typedef enum {
QM_SS_SPI_SS_DISABLED = 0, /**< Slave select disable. */
QM_SS_SPI_SS_0 = BIT(0), /**< Slave select 0. */
QM_SS_SPI_SS_1 = BIT(1), /**< Slave select 1. */
QM_SS_SPI_SS_2 = BIT(2), /**< Slave select 2. */
QM_SS_SPI_SS_3 = BIT(3) /**< Slave select 3. */
} qm_ss_spi_slave_select_t;
/**
* SPI status
*/
typedef enum {
QM_SS_SPI_IDLE, /**< SPI device is not in use. */
QM_SS_SPI_BUSY, /**< SPI device is busy. */
QM_SS_SPI_RX_OVERFLOW, /**< RX transfer has overflown. */
#if HAS_SS_SPI_VERBOSE_ERROR
QM_SS_SPI_TX_OVERFLOW, /**< TX transfer has overflown. */
QM_SS_SPI_RX_UNDERFLOW /**< RX transfer has underflown. */
#endif /* HAS_SS_SPI_VERBOSE_ERROR */
} qm_ss_spi_status_t;
/**
* SPI configuration type.
*/
typedef struct {
qm_ss_spi_frame_size_t frame_size; /**< Frame Size */
qm_ss_spi_tmode_t transfer_mode; /**< Transfer mode (enum) */
qm_ss_spi_bmode_t bus_mode; /**< Bus mode (enum) */
/**
* SCK = SPI_clock/clk_divider.
* A value of 0 will disable SCK. The LSB of this value is ignored.
*/
uint16_t clk_divider;
} qm_ss_spi_config_t;
/**
* SPI asynchronous transfer type.
*
* If the frame size is 8 bits or less, 1 byte is needed per data frame. If the
* frame size is 9-16 bits, 2 bytes are needed per data frame and frames of more
* than 16 bits require 4 bytes. In each case, the least significant bits are
* sent while the extra bits are discarded. The most significant bits of the
* frame are sent first.
*/
typedef struct {
void *tx; /**< Write data. */
void *rx; /**< Read data. */
uint16_t tx_len; /**< Number of data frames to write. */
uint16_t rx_len; /**< Number of data frames to read. */
/**
* Transfer callback.
*
* Called after all data is transmitted/received or if the driver
* detects an error during the SPI transfer.
*
* @param[in] data The callback user data.
* @param[in] error 0 on success.
* Negative @ref errno for possible error codes.
* @param[in] status The SPI module status.
* @param[in] len The amount of frames transmitted.
*/
void (*callback)(void *data, int error, qm_ss_spi_status_t status,
uint16_t len);
void *callback_data; /**< Callback user data */
} qm_ss_spi_async_transfer_t;
/**
* SPI synchronous transfer type.
*
* If the frame size is 8 bits or less, 1 byte is needed per data frame. If the
* frame size is 9-16 bits, 2 bytes are needed per data frame and frames of more
* than 16 bits require 4 bytes. In each case, the least significant bits are
* sent while the extra bits are discarded. The most significant bits of the
* frame are sent first.
*/
typedef struct {
void *tx; /**< Write data. */
void *rx; /**< Read data. */
uint16_t tx_len; /**< Number of data frames to write. */
uint16_t rx_len; /**< Number of data frames to read. */
} qm_ss_spi_transfer_t;
/**
* Set SPI configuration.
*
* Change the configuration of a SPI module.
* This includes transfer mode, bus mode, clock divider and data frame size.
*
* This operation is permitted only when the SPI module is disabled.
*
* @param [in] spi SPI module identifier.
* @param [in] cfg New configuration for SPI. This must not be NULL.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
int qm_ss_spi_set_config(const qm_ss_spi_t spi,
const qm_ss_spi_config_t *const cfg);
/**
* Set Slave Select lines.
*
* Select which slaves to perform SPI transmissions on. Select lines can be
* combined using the | operator. It is only suggested to use this functionality
* in TX only mode. This operation is permitted only when a SPI transfer is not
* already in progress; the caller should check that by retrieving the device
* status.
*
* @param[in] spi SPI module identifier.
* @param[in] ss Select lines to enable when performing transfers.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
int qm_ss_spi_slave_select(const qm_ss_spi_t spi,
const qm_ss_spi_slave_select_t ss);
/**
* Get SPI bus status.
*
* @param[in] spi SPI module identifier.
* @param[out] status Reference to the variable where to store the current SPI
* bus status (QM_SS_SPI_BUSY if a transfer is in progress
* or QM_SS_SPI_IDLE if SPI device is IDLE).
* This must not be NULL.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
int qm_ss_spi_get_status(const qm_ss_spi_t spi,
qm_ss_spi_status_t *const status);
/**
* Perform a blocking SPI transfer.
*
* This is a blocking synchronous call. If transfer mode is full duplex
* (QM_SS_SPI_TMOD_TX_RX) tx_len and rx_len must be equal. Similarly, for
* transmit-only transfers (QM_SS_SPI_TMOD_TX) rx_len must be 0, while for
* receive-only transfers (QM_SS_SPI_TMOD_RX) tx_len must be 0.
*
* @param[in] spi SPI module identifier.
* @param[in] xfer Structure containing transfer information.
* This must not be NULL.
* @param[out] status Reference to the variable where to store the SPI status
* at the end of the transfer.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
int qm_ss_spi_transfer(const qm_ss_spi_t spi,
const qm_ss_spi_transfer_t *const xfer,
qm_ss_spi_status_t *const status);
/**
* Initiate an interrupt based SPI transfer.
*
* Perform an interrupt based SPI transfer. If transfer mode is full duplex
* (QM_SS_SPI_TMOD_TX_RX), then tx_len and rx_len must be equal. Similarly, for
* transmit-only transfers (QM_SS_SPI_TMOD_TX) rx_len must be 0, while for
* receive-only transfers (QM_SS_SPI_TMOD_RX) tx_len must be 0. This function is
* non blocking.
*
* @param[in] spi SPI module identifier.
* @param[in] xfer Structure containing transfer information.
* The structure must not be NULL and must be kept valid until
* the transfer is complete.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
int qm_ss_spi_irq_transfer(const qm_ss_spi_t spi,
const qm_ss_spi_async_transfer_t *const xfer);
#if HAS_SS_DMA
/**
* Configure a DMA channel with a specific transfer direction.
*
* The user is responsible for managing the allocation of the pool of DMA
* channels provided by each DMA core to the different peripheral drivers
* that require them.
*
* Note that a SPI controller cannot use different DMA cores to manage
* transfers in different directions.
*
* This function configures DMA channel parameters that are unlikely to change
* between transfers, like transaction width, burst size, and handshake
* interface parameters. The user will likely only call this function once for
* the lifetime of an application unless the channel needs to be repurposed.
*
* Note that qm_dma_init() must first be called before configuring a channel.
*
* @param[in] spi SPI controller identifier.
* @param[in] dma_channel_direction DMA channel direction, either
* QM_DMA_MEMORY_TO_PERIPHERAL (TX transfer) or QM_DMA_PERIPHERAL_TO_MEMORY
* (RX transfer).
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
/* TODO - DR AP[2756] Revisit when DMA is added the sensor SPI QMSI 1.1 */
int qm_ss_spi_dma_channel_config(
const qm_ss_spi_t spi,
const qm_ss_dma_destination_target_type_t dma_channel_direction);
/**
* Perform a DMA based transfer on the SPI bus. The function will
* replenish/empty TX/RX FIFOs on DMA empty/full interrupts.
*
* @brief DMA based transfer on SPI.
*
* @param [in] spi SPI controller id
* @param [in] xfer Transfer structure includes write / read data
* and length; write, read and error callback
* functions and a callback identifier.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes
*/
/* TODO - DR AP[2756] Revisit when DMA is added the sensor SPI QMSI 1.1 */
int qm_ss_spi_dma_transfer(const qm_ss_spi_t spi,
const qm_ss_spi_async_transfer_t *const xfer);
#endif /* HAS_SS_QMSI_DMA */
/**
* Terminate SPI IRQ transfer.
*
* Terminate the current IRQ SPI transfer.
* This function will trigger complete callbacks even
* if the transfer is not completed.
*
* @param[in] spi SPI module identifier.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
int qm_ss_spi_transfer_terminate(const qm_ss_spi_t spi);
#if HAS_SS_QMSI_DMA
/**
* Terminate SPI DMA transfer.
*
* Terminate the current DMA SPI transfer.
* This function will trigger complete callbacks even
* if the transfer is not completed.
*
* @param[in] spi SPI module identifier.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
/* TODO - DR AP[2756] Revisit when DMA is added the sensor SPI QMSI 1.1 */
int qm_ss_spi_dma_transfer_terminate(const qm_ss_spi_t spi);
#endif /* HAS_SS_QMSI_DMA */
#if (ENABLE_RESTORE_CONTEXT)
/**
* Save SS SPI context.
*
* Saves the configuration of the specified SS SPI peripheral
* before entering sleep.
*
* @param[in] spi SPI controller identifier.
* @param[out] ctx SPI context structure. This must not be NULL.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
int qm_ss_spi_save_context(const qm_ss_spi_t spi,
qm_ss_spi_context_t *const ctx);
/**
* Restore SS SPI context.
*
* Restore the configuration of the specified SS SPI peripheral
* after exiting sleep.
*
* @param[in] spi SPI controller identifier.
* @param[in] ctx SPI context structure. This must not be NULL.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
int qm_ss_spi_restore_context(const qm_ss_spi_t spi,
const qm_ss_spi_context_t *const ctx);
#endif /* ENABLE_RESTORE_CONTEXT */
/**
* @}
*/
#endif /* __QM_SS_SPI_H__ */