blob: 938488a26aea433ff2044272867c16804220eb0a [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#ifndef _SW_DEVICE_LIB_DIF_UART_H_
#define _SW_DEVICE_LIB_DIF_UART_H_
#include <stdbool.h>
#include <stdint.h>
#include "sw/device/lib/base/mmio.h"
/**
* UART interrupt configuration
*
* Enumeration used to enable, disable, test and query the UART interrupts.
* Please see the comportability specification for more information:
* https://docs.opentitan.org/doc/rm/comportability_specification/
*/
typedef enum dif_uart_interrupt {
kDifUartInterruptTxWatermark = 0, /**< TX FIFO dipped below watermark */
kDifUartInterruptRxWatermark, /**< RX FIFO reached high watermark */
kDifUartInterruptTxEmpty, /**< TX FIFO empty */
kDifUartInterruptRxOverflow, /**< RX FIFO overflow */
kDifUartInterruptRxFrameErr, /**< RX framing error */
kDifUartInterruptRxBreakErr, /**< RX break condition */
kDifUartInterruptRxTimeout, /**< RX FIFO timeout (not empty in a set time) */
kDifUartInterruptRxParityErr, /**< RX parity error detection */
kDifUartInterruptLast =
kDifUartInterruptRxParityErr, /**< \internal Final UART interrupt */
} dif_uart_interrupt_t;
/**
* TX and RX FIFO depth configuration
*
* Enumeration used to set the upper limit of bytes to queue.
*/
typedef enum dif_uart_watermark {
kDifUartWatermarkByte1 = 0, /**< 1 byte */
kDifUartWatermarkByte4, /**< 4 bytes */
kDifUartWatermarkByte8, /**< 8 bytes */
kDifUartWatermarkByte16, /**< 16 bytes */
kDifUartWatermarkByte30, /**< 30 bytes */
kDifUartWatermarkLast =
kDifUartWatermarkByte30, /**< \internal Final UART watermark */
} dif_uart_watermark_t;
/**
* Generic enable/disable enumeration
*
* Enumeration used to enable/disable bits, flags, ...
*/
typedef enum dif_uart_enable {
kDifUartEnable = 0, /**< enable */
kDifUartDisable, /**< disable */
} dif_uart_enable_t;
/**
* UART parity enumeration
*
* Enumeration used to convey parity information
*/
typedef enum dif_uart_parity {
kDifUartParityOdd = 0, /**< odd */
kDifUartParityEven, /**< even */
} dif_uart_parity_t;
/**
* UART configuration data
*
* The fundamental data used to configure an UART instance
*/
typedef struct dif_uart_config {
uint32_t baudrate; /**< Requested baudrate */
uint32_t clk_freq_hz; /**< Input clock frequency */
dif_uart_enable_t parity_enable; /**< Enable parity check */
dif_uart_parity_t parity; /**< Set parity (even by default) */
} dif_uart_config_t;
/**
* UART instance state
*
* UART persistent data that is required by all UART API. |base_address| must
* be initialised by the caller, before passing into the UART DIF init routine.
*/
typedef struct dif_uart {
mmio_region_t base_addr; /**< UART base address */
} dif_uart_t;
/**
* Initialise an instance of UART
*
* Initialise UART instance using the configuration data in @p config.
* Information that must be retained, and is required to program UART must be
* stored in @p uart.
* @param base_addr Base address of an instance of UART IP block
* @param config UART configuration data
* @param uart UART state data
* @return true if the function was successful, false otherwise
*/
bool dif_uart_init(mmio_region_t base_addr, const dif_uart_config_t *config,
dif_uart_t *uart);
/**
* Configure an instance of UART
*
* Configure UART using the configuration data in @p config. This operation
* performs fundamental configuration.
*
* @param uart UART state data
* @param config UART configuration data
* @return true if the function was successful, false otherwise
*/
bool dif_uart_configure(const dif_uart_t *uart,
const dif_uart_config_t *config);
/**
* Set the RX FIFO watermark
*
* Set the RX FIFO watermark, is only useful when the corresponding interrupt
* is enabled. When the queued RX FIFO number of bytes rises to or above this
* level, the RX watermark interrupt is raised.
*
* @param uart UART state data
* @param watermark RX FIFO watermark
* @return true if the function was successful, false otherwise
*/
bool dif_uart_watermark_rx_set(const dif_uart_t *uart,
dif_uart_watermark_t watermark);
/**
* Set the TX FIFO watermark
*
* Set the TX FIFO watermark, is only useful when the corresponding interrupt
* is enabled. When the queued TX FIFO number of bytes falls to or below this
* level, the TX watermark interrupt is raised.
*
* @param uart UART state data
* @param watermark TX FIFO watermark
* @return true if the function was successful, false otherwise
*/
bool dif_uart_watermark_tx_set(const dif_uart_t *uart,
dif_uart_watermark_t watermark);
/**
* UART send bytes
*
* Non-blocking UART send bytes routine. Can be used from inside an UART ISR.
* This function attempts to write @p bytes_requested number of bytes to the
* UART TX FIFO from @p bytes_requested, and passes @p bytes_written back to
* the caller. @p bytes_written is optional, NULL should be passed in if the
* value is not needed.
*
* @param uart UART state data
* @param data Data to be written
* @param bytes_requested Number of bytes requested to be written by the caller
* @param bytes_written Number of bytes written (optional)
* @return true if the function was successful, false otherwise
*/
bool dif_uart_bytes_send(const dif_uart_t *uart, const uint8_t *data,
size_t bytes_requested, size_t *bytes_written);
/**
* UART receive bytes
*
* Non-blocking UART receive bytes routine. Can be used from inside an UART ISR.
* This function attempts to read @p bytes_requested number of bytes from the
* UART RX FIFO into @p data, and passes @p bytes_read back to the caller.
* @p bytes_read is optional, NULL should be passed in if the value is not
* needed.
*
* @param uart UART state data
* @param bytes_requested Number of bytes requested to be read by the caller
* @param data Data to be read
* @param bytes_read Number of bytes read (optional)
* @return true if the function was successful, false otherwise
*/
bool dif_uart_bytes_receive(const dif_uart_t *uart, size_t bytes_requested,
uint8_t *data, size_t *bytes_read);
/**
* Transmit a single UART byte (polled)
*
* Transmit a single UART byte @p byte. This operation is polled, and will busy
* wait until a byte has been sent. Must not be used inside an ISR.
*
* @param uart UART state data
* @param byte Byte to be transmitted
* @return true if the function was successful, false otherwise
*/
bool dif_uart_byte_send_polled(const dif_uart_t *uart, uint8_t byte);
/**
* Receive a single UART byte (polled)
*
* Receive a single UART byte and store it in @p byte. This operation is polled,
* and will busy wait until a byte has been read. Must not be used inside an
* ISR.
*
* @param uart UART state data
* @param byte Received byte
* @return true if the function was successful, false otherwise
*/
bool dif_uart_byte_receive_polled(const dif_uart_t *uart, uint8_t *byte);
/**
* UART get requested IRQ state
*
* Get the state of the requested IRQ in @p irq_type.
*
* @param uart UART state data
* @param irq_type IRQ to get the state of
* @param state IRQ state passed back to the caller
* @return true if the function was successful, false otherwise
*/
bool dif_uart_irq_state_get(const dif_uart_t *uart,
dif_uart_interrupt_t irq_type,
dif_uart_enable_t *state);
/**
* UART clear requested IRQ state
*
* Clear the state of the requested IRQ in @p irq_type. Primary use of this
* function is to de-assert the interrupt after it has been serviced.
*
* @param uart UART state data
* @param irq_type IRQ to be de-asserted
* @return true if the function was successful, false otherwise
*/
bool dif_uart_irq_state_clear(const dif_uart_t *uart,
dif_uart_interrupt_t irq_type);
/**
* UART disable interrupts
*
* Disable generation of all UART interrupts, and pass previous interrupt state
* in @p state back to the caller. Parameter @p state is ignored if NULL.
*
* @param uart UART state data
* @param state IRQ state passed back to the caller
* @return true if the function was successful, false otherwise
*/
bool dif_uart_irqs_disable(const dif_uart_t *uart, uint32_t *state);
/**
* UART restore IRQ state
*
* Restore previous UART IRQ state. This function is used to restore the
* UART interrupt state prior to dif_uart_irqs_disable function call.
*
* @param uart UART state data
* @param state IRQ state to restore
* @return true if the function was successful, false otherwise
*/
bool dif_uart_irqs_restore(const dif_uart_t *uart, uint32_t state);
/**
* UART interrupt control
*
* Enable/disable an UART interrupt specified in @p enable.
*
* @param uart UART state data
* @param irq_type UART interrupt type
* @param enable enable or disable the interrupt
* @return true if the function was successful, false otherwise
*/
bool dif_uart_irq_enable(const dif_uart_t *uart, dif_uart_interrupt_t irq_type,
dif_uart_enable_t enable);
/**
* UART interrupt force
*
* Force interrupt specified in @p irq_type.
*
* @param uart UART state data
* @param irq_type UART interrupt type to be forced
* @return true if the function was successful, false otherwise
*/
bool dif_uart_irq_force(const dif_uart_t *uart, dif_uart_interrupt_t irq_type);
/**
* UART RX bytes available
*
* Get the number of bytes available to be read from the UART RX FIFO. This
* function can be used to check FIFO full and empty conditions.
*
* @param uart UART state data
* @param num_bytes Number of bytes available to be read
* @return true if the function was successful, false otherwise
*/
bool dif_uart_rx_bytes_available(const dif_uart_t *uart, size_t *num_bytes);
/**
* UART TX bytes available
*
* Get the number of bytes available to be written to the UART TX FIFO. This
* function can be used to check FIFO full and empty conditions.
*
* @param uart UART state data
* @param num_bytes Number of bytes available to be written
* @return true if the function was successful, false otherwise
*/
bool dif_uart_tx_bytes_available(const dif_uart_t *uart, size_t *num_bytes);
#endif