blob: d6f562d74cf5842ac9af03d061dc1ec85e17696b [file] [log] [blame]
/*
* Copyright (c) 2017, 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_UART_H__
#define __QM_UART_H__
#include "qm_common.h"
#include "qm_soc_regs.h"
#include "qm_dma.h"
/**
* UART peripheral driver.
*
* @defgroup groupUART UART
* @{
*/
/**
* UART Line control.
*/
typedef enum {
QM_UART_LC_5N1 = 0x00, /**< 5 data bits, no parity, 1 stop bit. */
QM_UART_LC_5N1_5 = 0x04, /**< 5 data bits, no parity, 1.5 stop bits. */
QM_UART_LC_5E1 = 0x18, /**< 5 data bits, even parity, 1 stop bit. */
QM_UART_LC_5E1_5 = 0x1c, /**< 5 data bits, even par., 1.5 stop bits. */
QM_UART_LC_5O1 = 0x08, /**< 5 data bits, odd parity, 1 stop bit. */
QM_UART_LC_5O1_5 = 0x0c, /**< 5 data bits, odd parity, 1.5 stop bits. */
QM_UART_LC_6N1 = 0x01, /**< 6 data bits, no parity, 1 stop bit. */
QM_UART_LC_6N2 = 0x05, /**< 6 data bits, no parity, 2 stop bits. */
QM_UART_LC_6E1 = 0x19, /**< 6 data bits, even parity, 1 stop bit. */
QM_UART_LC_6E2 = 0x1d, /**< 6 data bits, even parity, 2 stop bits. */
QM_UART_LC_6O1 = 0x09, /**< 6 data bits, odd parity, 1 stop bit. */
QM_UART_LC_6O2 = 0x0d, /**< 6 data bits, odd parity, 2 stop bits. */
QM_UART_LC_7N1 = 0x02, /**< 7 data bits, no parity, 1 stop bit. */
QM_UART_LC_7N2 = 0x06, /**< 7 data bits, no parity, 2 stop bits. */
QM_UART_LC_7E1 = 0x1a, /**< 7 data bits, even parity, 1 stop bit. */
QM_UART_LC_7E2 = 0x1e, /**< 7 data bits, even parity, 2 stop bits. */
QM_UART_LC_7O1 = 0x0a, /**< 7 data bits, odd parity, 1 stop bit. */
QM_UART_LC_7O2 = 0x0e, /**< 7 data bits, odd parity, 2 stop bits. */
QM_UART_LC_8N1 = 0x03, /**< 8 data bits, no parity, 1 stop bit. */
QM_UART_LC_8N2 = 0x07, /**< 8 data bits, no parity, 2 stop bits. */
QM_UART_LC_8E1 = 0x1b, /**< 8 data bits, even parity, 1 stop bit. */
QM_UART_LC_8E2 = 0x1f, /**< 8 data bits, even parity, 2 stop bits. */
QM_UART_LC_8O1 = 0x0b, /**< 8 data bits, odd parity, 1 stop bit. */
QM_UART_LC_8O2 = 0x0f /**< 8 data bits, odd parity, 2 stop bits. */
} qm_uart_lc_t;
/**
* UART Status type.
*/
typedef enum {
QM_UART_IDLE = 0, /**< IDLE. */
QM_UART_RX_OE = BIT(1), /**< Receiver overrun. */
QM_UART_RX_PE = BIT(2), /**< Parity error. */
QM_UART_RX_FE = BIT(3), /**< Framing error. */
QM_UART_RX_BI = BIT(4), /**< Break interrupt. */
QM_UART_TX_BUSY = BIT(5), /**< TX Busy flag. */
QM_UART_RX_BUSY = BIT(6), /**< RX Busy flag. */
QM_UART_TX_NFULL = BIT(7), /**< TX FIFO not full. */
QM_UART_RX_NEMPTY = BIT(8), /**< RX FIFO not empty. */
} qm_uart_status_t;
/**
* UART configuration structure type
*/
typedef struct {
qm_uart_lc_t line_control; /**< Line control (enum). */
uint32_t baud_divisor; /**< Baud Divisor. */
bool hw_fc; /**< Hardware Automatic Flow Control. */
} qm_uart_config_t;
/**
* UART asynchronous transfer structure.
*/
typedef struct {
uint8_t *data; /**< Pre-allocated write or read buffer. */
uint32_t data_len; /**< Number of bytes to transfer. */
/** Transfer callback
*
* @param[in] data Callback user data.
* @param[in] error 0 on success.
* Negative @ref errno for possible error codes.
* @param[in] status UART module status
* @param[in] len Length of the UART transfer if successful, 0
* otherwise.
*/
void (*callback)(void *data, int error, qm_uart_status_t status,
uint32_t len);
void *callback_data; /**< Callback identifier. */
} qm_uart_transfer_t;
/**
* Set UART configuration.
*
* Change the configuration of a UART module. This includes line control,
* baud rate and hardware flow control.
*
* @param[in] uart Which UART module to configure.
* @param[in] cfg New configuration for UART. 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_uart_set_config(const qm_uart_t uart, const qm_uart_config_t *const cfg);
/**
* Get UART bus status.
*
* Retrieve UART interface status. Return QM_UART_BUSY if transmitting
* data; QM_UART_IDLE if available for transfer; QM_UART_TX_ERROR if an
* error has occurred in transmission.
*
* The user may call this function before performing an UART transfer in order
* to guarantee that the UART interface is available.
* @param[in] uart Which UART to read the status of.
* @param[out] status Current UART status. 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_uart_get_status(const qm_uart_t uart, qm_uart_status_t *const status);
/**
* UART character data write.
*
* Perform a single character write on the UART interface.
* This is a blocking synchronous call.
*
* @param[in] uart UART identifer.
* @param[in] data Data to write to UART.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
int qm_uart_write(const qm_uart_t uart, const uint8_t data);
/**
* UART character data read.
*
* Perform a single character read from the UART interface.
* This is a blocking synchronous call.
*
* @param[in] uart UART identifer.
* @param[out] data Data to read from UART. This must not be NULL.
* @param[out] status UART specific status.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
int qm_uart_read(const qm_uart_t uart, uint8_t *const data,
qm_uart_status_t *const status);
/**
* UART character data write.
*
* Perform a single character write on the UART interface.
* This is a non-blocking synchronous call.
*
* @param[in] uart UART identifier.
* @param[in] data Data to write to UART.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
int qm_uart_write_non_block(const qm_uart_t uart, const uint8_t data);
/**
* UART character data read.
*
* Perform a single character read from the UART interface.
* This is a non-blocking synchronous call.
*
* @param[in] uart UART identifer.
* @param[out] data Character read. 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_uart_read_non_block(const qm_uart_t uart, uint8_t *const data);
/**
* UART multi-byte data write.
*
* Perform a write on the UART interface. This is a blocking
* synchronous call. The function will block until all data has
* been transferred.
*
* @param[in] uart UART controller identifier
* @param[in] data Data to write to UART. This must not be NULL.
* @param[in] len Length of data to write to UART.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
int qm_uart_write_buffer(const qm_uart_t uart, const uint8_t *const data,
const uint32_t len);
/**
* Interrupt based TX on UART.
*
* Perform an interrupt based TX transfer on the UART bus. The function
* will replenish the TX FIFOs on UART empty interrupts.
*
* @param[in] uart UART identifier.
* @param[in] xfer Structure containing pre-allocated
* write buffer and callback functions.
* 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_uart_irq_write(const qm_uart_t uart,
const qm_uart_transfer_t *const xfer);
/**
* Interrupt based RX on UART.
*
* Perform an interrupt based RX transfer on the UART bus. The function
* will read back the RX FIFOs on UART empty interrupts.
*
* @param[in] uart UART identifier.
* @param[in] xfer Structure containing pre-allocated read
* buffer and callback functions.
* 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_uart_irq_read(const qm_uart_t uart,
const qm_uart_transfer_t *const xfer);
/**
* Terminate UART IRQ TX transfer.
*
* Terminate the current IRQ TX transfer on the UART bus.
* This will cause the relevant callbacks to be called.
*
* @param[in] uart UART identifier.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
int qm_uart_irq_write_terminate(const qm_uart_t uart);
/**
* Terminate UART IRQ RX transfer.
*
* Terminate the current IRQ RX transfer on the UART bus.
* This will cause the relevant callbacks to be called.
*
* @param[in] uart UART identifier.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
int qm_uart_irq_read_terminate(const qm_uart_t uart);
/**
* 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.
*
* 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] uart UART identifier.
* @param[in] dma_ctrl_id DMA controller identifier.
* @param[in] dma_channel_id DMA channel identifier.
* @param[in] dma_channel_direction DMA channel direction, either
* QM_DMA_MEMORY_TO_PERIPHERAL (write transfer) or QM_DMA_PERIPHERAL_TO_MEMORY
* (read transfer).
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
int qm_uart_dma_channel_config(
const qm_uart_t uart, const qm_dma_t dma_ctrl_id,
const qm_dma_channel_id_t dma_channel_id,
const qm_dma_channel_direction_t dma_channel_direction);
/**
* Perform a DMA-based TX transfer on the UART bus.
*
* In order for this call to succeed, previously the user
* must have configured a DMA channel with direction
* QM_DMA_MEMORY_TO_PERIPHERAL to be used on this UART, calling
* qm_uart_dma_channel_config(). The transfer length is limited to 4KB.
*
* Note that this function uses the UART TX FIFO empty interrupt and therefore,
* in addition to the DMA interrupts, the ISR of the corresponding UART must be
* registered before using this function.
*
* @param[in] uart UART identifer.
* @param[in] xfer Structure containing a pre-allocated write buffer
* and callback functions.
* 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_uart_dma_write(const qm_uart_t uart,
const qm_uart_transfer_t *const xfer);
/**
* Perform a DMA-based RX transfer on the UART bus.
*
* In order for this call to succeed, previously the user
* must have configured a DMA channel with direction
* QM_DMA_PERIPHERAL_TO_MEMORY to be used on this UART, calling
* qm_uart_dma_channel_config(). The transfer length is limited to 4KB.
*
* @param[in] uart UART identifer.
* @param[in] xfer Structure containing a pre-allocated read buffer
* and callback functions.
* 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_uart_dma_read(const qm_uart_t uart,
const qm_uart_transfer_t *const xfer);
/**
* Terminate the current DMA TX transfer on the UART bus.
*
* This will cause the relevant callbacks to be called.
*
* @param[in] uart UART identifer.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
int qm_uart_dma_write_terminate(const qm_uart_t uart);
/**
* Terminate the current DMA RX transfer on the UART bus.
*
* This will cause the relevant callbacks to be called.
*
* @param[in] uart UART identifer.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
int qm_uart_dma_read_terminate(const qm_uart_t uart);
/**
* Save UART context.
*
* Saves the configuration of the specified UART peripheral
* before entering sleep.
*
* @param[in] uart UART port index.
* @param[out] ctx UART 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_uart_save_context(const qm_uart_t uart, qm_uart_context_t *const ctx);
/**
* Restore UART context.
*
* Restore the configuration of the specified UART peripheral
* after exiting sleep.
*
* FIFO control register cannot be read back,
* the default configuration is applied for this register.
* Application will need to restore its own parameters.
*
* @param[in] uart UART port index.
* @param[in] ctx UART 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_uart_restore_context(const qm_uart_t uart,
const qm_uart_context_t *const ctx);
/**
* @}
*/
#endif /* __QM_UART_H__ */