aboutsummaryrefslogtreecommitdiff
path: root/platform/ext/target/arm/musca_b1/sse_200/Native_Driver/uart_pl011_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'platform/ext/target/arm/musca_b1/sse_200/Native_Driver/uart_pl011_drv.c')
-rw-r--r--platform/ext/target/arm/musca_b1/sse_200/Native_Driver/uart_pl011_drv.c1019
1 files changed, 1019 insertions, 0 deletions
diff --git a/platform/ext/target/arm/musca_b1/sse_200/Native_Driver/uart_pl011_drv.c b/platform/ext/target/arm/musca_b1/sse_200/Native_Driver/uart_pl011_drv.c
new file mode 100644
index 0000000000..01feaa4fdd
--- /dev/null
+++ b/platform/ext/target/arm/musca_b1/sse_200/Native_Driver/uart_pl011_drv.c
@@ -0,0 +1,1019 @@
+/*
+ * Copyright (c) 2016-2018 Arm Limited
+ *
+ * Licensed 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.
+ */
+
+#include "uart_pl011_drv.h"
+
+#include <stddef.h>
+#include "cmsis_compiler.h"
+
+#define FREQ_IRLPBAUD16_MIN (1420000u) /* 1.42 MHz */
+#define FREQ_IRLPBAUD16_MAX (2120000u) /* 2.12 MHz */
+#define SAMPLING_FACTOR (16u)
+#define UART_PL011_FBRD_WIDTH (6u)
+
+/**
+ * \brief UART PL011 register map structure
+ */
+struct _uart_pl011_reg_map_t {
+ volatile uint32_t uartdr; /*!< Offset: 0x000 (R/W) Data register */
+ union {
+ volatile uint32_t uartrsr;
+ /*!< Offset: 0x004 (R/ ) Receive status register */
+ volatile uint32_t uartecr;
+ /*!< Offset: 0x004 ( /W) Error clear register */
+ };
+ volatile uint32_t reserved_0[4]; /*!< Offset: 0x008-0x014 Reserved */
+ volatile uint32_t uartfr; /*!< Offset: 0x018 (R/ ) Flag register */
+ volatile uint32_t reserved_1; /*!< Offset: 0x01C Reserved */
+ volatile uint32_t uartilpr;
+ /*!< Offset: 0x020 (R/W) IrDA low-power counter register */
+ volatile uint32_t uartibrd;
+ /*!< Offset: 0x024 (R/W) Integer baud rate register */
+ volatile uint32_t uartfbrd;
+ /*!< Offset: 0x028 (R/W) Fractional baud rate register */
+ volatile uint32_t uartlcr_h;
+ /*!< Offset: 0x02C (R/W) Line control register */
+ volatile uint32_t uartcr;
+ /*!< Offset: 0x030 (R/W) Control register */
+ volatile uint32_t uartifls;
+ /*!< Offset: 0x034 (R/W) Interrupt FIFO level select register */
+ volatile uint32_t uartimsc;
+ /*!< Offset: 0x038 (R/W) Interrupt mask set/clear register */
+ volatile uint32_t uartris;
+ /*!< Offset: 0x03C (R/ ) Raw interrupt status register */
+ volatile uint32_t uartmis;
+ /*!< Offset: 0x040 (R/ ) Masked interrupt status register */
+ volatile uint32_t uarticr;
+ /*!< Offset: 0x044 ( /W) Interrupt clear register */
+ volatile uint32_t uartdmacr;
+ /*!< Offset: 0x048 (R/W) DMA control register */
+ volatile uint32_t reserved_2[13]; /*!< Offset: 0x04C-0x07C Reserved */
+ volatile uint32_t reserved_3[4];
+ /*!< Offset: 0x080-0x08C Reserved for test purposes */
+ volatile uint32_t reserved_4[976]; /*!< Offset: 0x090-0xFCC Reserved */
+ volatile uint32_t reserved_5[4];
+ /*!< Offset: 0xFD0-0xFDC Reserved for future ID expansion */
+ volatile uint32_t uartperiphid0;
+ /*!< Offset: 0xFE0 (R/ ) UARTPeriphID0 register */
+ volatile uint32_t uartperiphid1;
+ /*!< Offset: 0xFE4 (R/ ) UARTPeriphID1 register */
+ volatile uint32_t uartperiphid2;
+ /*!< Offset: 0xFE8 (R/ ) UARTPeriphID2 register */
+ volatile uint32_t uartperiphid3;
+ /*!< Offset: 0xFEC (R/ ) UARTPeriphID3 register */
+ volatile uint32_t uartpcellid0;
+ /*!< Offset: 0xFF0 (R/ ) UARTPCellID0 register */
+ volatile uint32_t uartpcellid1;
+ /*!< Offset: 0xFF4 (R/ ) UARTPCellID1 register */
+ volatile uint32_t uartpcellid2;
+ /*!< Offset: 0xFF8 (R/ ) UARTPCellID2 register */
+ volatile uint32_t uartpcellid3;
+ /*!< Offset: 0xFFC (R/ ) UARTPCellID3 register */
+};
+
+#define UART_PL011_UARTFR_CTS_MASK ( \
+ 0x1u<<UART_PL011_UARTFR_CTS_OFF)
+#define UART_PL011_UARTFR_DSR_MASK ( \
+ 0x1u<<UART_PL011_UARTFR_DSR_OFF)
+#define UART_PL011_UARTFR_DCD_MASK ( \
+ 0x1u<<UART_PL011_UARTFR_DCD_OFF)
+#define UART_PL011_UARTFR_BUSYBIT ( \
+ 0x1u<<UART_PL011_UARTFR_BUSYBIT_OFF)
+#define UART_PL011_UARTFR_RX_FIFO_EMPTY ( \
+ 0x1u<<UART_PL011_UARTFR_RX_FIFO_EMPTY_OFF)
+#define UART_PL011_UARTFR_TX_FIFO_FULL ( \
+ 0x1u<<UART_PL011_UARTFR_TX_FIFO_FULL_OFF)
+#define UART_PL011_UARTFR_RI_MASK ( \
+ 0x1u<<UART_PL011_UARTFR_RI_OFF)
+
+#define UART_PL011_UARTLCR_H_BRK_MASK ( \
+ 0x1u<<UART_PL011_UARTLCR_H_BRK_OFF)
+#define UART_PL011_UARTLCR_H_PARITY_MASK ( \
+ 0x1u<<UART_PL011_UARTLCR_H_PEN_OFF \
+ | 0x1u<<UART_PL011_UARTLCR_H_EPS_OFF \
+ | 0x1u<<UART_PL011_UARTLCR_H_SPS_OFF)
+#define UART_PL011_UARTLCR_H_STOPBIT_MASK ( \
+ 0x1u<<UART_PL011_UARTLCR_H_STP2_OFF)
+#define UART_PL011_UARTLCR_H_FEN_MASK ( \
+ 0x1u<<UART_PL011_UARTLCR_H_FEN_OFF)
+#define UART_PL011_UARTLCR_H_WLEN_MASK ( \
+ 0x3u<<UART_PL011_UARTLCR_H_WLEN_OFF)
+#define UART_PL011_FORMAT_MASK ( \
+ UART_PL011_UARTLCR_H_PARITY_MASK \
+ | UART_PL011_UARTLCR_H_STOPBIT_MASK \
+ | UART_PL011_UARTLCR_H_WLEN_MASK)
+
+#define UART_PL011_UARTCR_EN_MASK ( \
+ 0x1u<<UART_PL011_UARTCR_UARTEN_OFF)
+#define UART_PL011_UARTCR_SIREN_MASK ( \
+ 0x1u<<UART_PL011_UARTCR_SIREN_OFF)
+#define UART_PL011_UARTCR_SIRLP_MASK ( \
+ 0x1u<<UART_PL011_UARTCR_SIRLP_OFF)
+#define UART_PL011_UARTCR_LBE_MASK ( \
+ 0x1u<<UART_PL011_UARTCR_LBE_OFF)
+#define UART_PL011_UARTCR_TX_EN_MASK ( \
+ 0x1u<<UART_PL011_UARTCR_TXE_OFF)
+#define UART_PL011_UARTCR_RX_EN_MASK ( \
+ 0x1u<<UART_PL011_UARTCR_RXE_OFF)
+#define UART_PL011_UARTCR_DTR_MASK ( \
+ 0x1u<<UART_PL011_UARTCR_DTR_OFF)
+#define UART_PL011_UARTCR_RTS_MASK ( \
+ 0x1u<<UART_PL011_UARTCR_RTS_OFF)
+#define UART_PL011_UARTCR_OUT1_MASK ( \
+ 0x1u<<UART_PL011_UARTCR_OUT1_OFF)
+#define UART_PL011_UARTCR_OUT2_MASK ( \
+ 0x1u<<UART_PL011_UARTCR_OUT2_OFF)
+#define UART_PL011_UARTCR_RTSE_MASK ( \
+ 0x1u<<UART_PL011_UARTCR_RTSE_OFF)
+#define UART_PL011_UARTCR_CTSE_MASK ( \
+ 0x1u<<UART_PL011_UARTCR_CTSE_OFF)
+
+#define UART_PL011_UARTIFLS_TX_FIFO_LVL_MASK ( \
+ 0x7u<<UART_PL011_UARTIFLS_TX_OFF)
+#define UART_PL011_UARTIFLS_RX_FIFO_LVL_MASK ( \
+ 0x7u<<UART_PL011_UARTIFLS_RX_OFF)
+
+#define UART_PL011_UARTDMACR_RX_MASK ( \
+ 0x1u<<UART_PL011_UARTDMACR_RXEN_OFF \
+ | 0x1u<<UART_PL011_UARTDMACR_ON_ERR_OFF)
+#define UART_PL011_UARTDMACR_TX_MASK ( \
+ 0x1u<<UART_PL011_UARTDMACR_TXEN_OFF)
+
+/* Default register values of UART PL011 */
+#define UART_PL011_DATA_REG_RESET_VALUE (0x0u)
+#define UART_PL011_ECR_REG_CLEAR_VALUE (0xFFu)
+#define UART_PL011_ILPR_REG_RESET_VALUE (0x0u)
+#define UART_PL011_IBRD_REG_RESET_VALUE (0x0u)
+#define UART_PL011_FBRD_REG_RESET_VALUE (0x0u)
+#define UART_PL011_LCR_H_REG_RESET_VALUE (0x0u)
+#define UART_PL011_CR_REG_RESET_VALUE (0x0300u)
+#define UART_PL011_IFLS_REG_RESET_VALUE (0x12u)
+#define UART_PL011_IMSC_REG_RESET_VALUE (0x0u)
+#define UART_PL011_ICR_REG_CLEAR_VALUE (0x7FFu)
+#define UART_PL011_DMACR_REG_RESET_VALUE (0x0u)
+
+static void _uart_pl011_enable(struct _uart_pl011_reg_map_t* p_uart)
+{
+ p_uart->uartcr |= UART_PL011_UARTCR_EN_MASK;
+}
+
+static void _uart_pl011_disable(struct _uart_pl011_reg_map_t* p_uart)
+{
+ p_uart->uartcr &= ~UART_PL011_UARTCR_EN_MASK;
+}
+
+static bool _uart_pl011_is_enabled(struct _uart_pl011_reg_map_t* p_uart)
+{
+ return (bool)(p_uart->uartcr & UART_PL011_UARTCR_EN_MASK);
+}
+
+static void _uart_pl011_enable_fifo(struct _uart_pl011_reg_map_t* p_uart)
+{
+ p_uart->uartlcr_h |= UART_PL011_UARTLCR_H_FEN_MASK;
+}
+
+static void _uart_pl011_disable_fifo(struct _uart_pl011_reg_map_t* p_uart)
+{
+ p_uart->uartlcr_h &= ~UART_PL011_UARTLCR_H_FEN_MASK;
+}
+
+static bool _uart_pl011_is_fifo_enabled(struct _uart_pl011_reg_map_t* p_uart)
+{
+ return (bool)(p_uart->uartlcr_h & UART_PL011_UARTLCR_H_FEN_MASK);
+}
+
+static bool _uart_pl011_is_busy(struct _uart_pl011_reg_map_t* p_uart)
+{
+ return (bool)(p_uart->uartfr & UART_PL011_UARTFR_BUSYBIT);
+}
+
+static enum uart_pl011_error_t _uart_pl011_set_baudrate(
+ struct _uart_pl011_reg_map_t* p_uart,
+ uint32_t clk, uint32_t baudrate)
+{
+ /* Avoiding float calculations, bauddiv is left shifted by 6 */
+ uint64_t bauddiv = (((uint64_t)clk)<<UART_PL011_FBRD_WIDTH)
+ /(SAMPLING_FACTOR*baudrate);
+
+ /* Valid bauddiv value
+ * uart_clk (min) >= 16 x baud_rate (max)
+ * uart_clk (max) <= 16 x 65535 x baud_rate (min)
+ */
+ if((bauddiv < (1u<<UART_PL011_FBRD_WIDTH))
+ || (bauddiv > (65535u<<UART_PL011_FBRD_WIDTH))) {
+ return UART_PL011_ERR_INVALID_BAUD;
+ }
+
+ p_uart->uartibrd = (uint32_t)(bauddiv >> UART_PL011_FBRD_WIDTH);
+ p_uart->uartfbrd = (uint32_t)(bauddiv &
+ ((1u << UART_PL011_FBRD_WIDTH) - 1u));
+
+ __DMB();
+
+ /* In order to internally update the contents of uartibrd or uartfbrd, a
+ * uartlcr_h write must always be performed at the end
+ * ARM DDI 0183F, Pg 3-13
+ */
+ p_uart->uartlcr_h = p_uart->uartlcr_h;
+
+ return UART_PL011_ERR_NONE;
+}
+
+static void _uart_pl011_set_format(struct _uart_pl011_reg_map_t* p_uart,
+ enum uart_pl011_wlen_t word_len,
+ enum uart_pl011_parity_t parity,
+ enum uart_pl011_stopbit_t stop_bits)
+{
+ uint32_t ctrl_reg = p_uart->uartlcr_h & ~(UART_PL011_FORMAT_MASK);
+
+ /* Making sure other bit are not changed */
+ word_len &= UART_PL011_UARTLCR_H_WLEN_MASK;
+ parity &= UART_PL011_UARTLCR_H_PARITY_MASK;
+ stop_bits &= UART_PL011_UARTLCR_H_STOPBIT_MASK;
+
+ p_uart->uartlcr_h = ctrl_reg | word_len | parity | stop_bits;
+
+}
+
+static void _uart_pl011_set_cr_bit(struct _uart_pl011_reg_map_t* p_uart,
+ uint32_t mask)
+{
+ bool uart_enabled = _uart_pl011_is_enabled(p_uart);
+ bool fifo_enabled = _uart_pl011_is_fifo_enabled(p_uart);
+
+ /* UART must be disabled before any Control Register or
+ * Line Control Register are reprogrammed */
+ _uart_pl011_disable(p_uart);
+
+ /* Flush the transmit FIFO by disabling bit 4 (FEN) in
+ * the line control register (UARTCLR_H) */
+ _uart_pl011_disable_fifo(p_uart);
+
+ p_uart->uartcr |= (mask);
+
+ /* Enabling the FIFOs if previously enabled */
+ if(fifo_enabled) {
+ _uart_pl011_enable_fifo(p_uart);
+ }
+
+ /* Enabling the UART if previously enabled */
+ if(uart_enabled) {
+ _uart_pl011_enable(p_uart);
+ }
+}
+
+static void _uart_pl011_clear_cr_bit(struct _uart_pl011_reg_map_t* p_uart,
+ uint32_t mask)
+{
+ bool uart_enabled = _uart_pl011_is_enabled(p_uart);
+ bool fifo_enabled = _uart_pl011_is_fifo_enabled(p_uart);
+
+ /* UART must be disabled before any Control Register or
+ * Line Control Register are reprogrammed */
+ _uart_pl011_disable(p_uart);
+
+ /* Flush the transmit FIFO by disabling bit 4 (FEN) in
+ * the line control register (UARTCLR_H) */
+ _uart_pl011_disable_fifo(p_uart);
+
+ p_uart->uartcr &= ~(mask);
+
+ /* Enabling the FIFOs if previously enabled */
+ if(fifo_enabled) {
+ _uart_pl011_enable_fifo(p_uart);
+ }
+
+ /* Enabling the UART if previously enabled */
+ if(uart_enabled) {
+ _uart_pl011_enable(p_uart);
+ }
+}
+
+static void _uart_pl011_set_lcr_h_bit(struct _uart_pl011_reg_map_t* p_uart,
+ uint32_t mask)
+{
+ bool uart_enabled = _uart_pl011_is_enabled(p_uart);
+
+ /* UART must be disabled before any Control Register or
+ * Line Control Register are reprogrammed */
+ _uart_pl011_disable(p_uart);
+
+ p_uart->uartlcr_h |= (mask);
+
+ /* Enabling the UART if previously enabled */
+ if(uart_enabled) {
+ _uart_pl011_enable(p_uart);
+ }
+}
+
+static void _uart_pl011_clear_lcr_h_bit(struct _uart_pl011_reg_map_t* p_uart,
+ uint32_t mask)
+{
+ bool uart_enabled = _uart_pl011_is_enabled(p_uart);
+
+ /* UART must be disabled before any Control Register or
+ * Line Control Register are reprogrammed */
+ _uart_pl011_disable(p_uart);
+
+ p_uart->uartlcr_h &= ~(mask);
+
+ /* Enabling the UART if previously enabled */
+ if(uart_enabled) {
+ _uart_pl011_enable(p_uart);
+ }
+}
+
+static void _uart_pl011_reset_regs(struct _uart_pl011_reg_map_t* p_uart)
+{
+ /* Restore the default value of UART registers, the registers which
+ * are not listed below are Read-Only */
+
+ /* Will disable the UART */
+ p_uart->uartcr = UART_PL011_CR_REG_RESET_VALUE;
+ p_uart->uartdr = UART_PL011_DATA_REG_RESET_VALUE;
+ /* Clear all the errors */
+ p_uart->uartecr = UART_PL011_ECR_REG_CLEAR_VALUE;
+ p_uart->uartilpr = UART_PL011_ILPR_REG_RESET_VALUE;
+ p_uart->uartibrd = UART_PL011_IBRD_REG_RESET_VALUE;
+ p_uart->uartfbrd = UART_PL011_FBRD_REG_RESET_VALUE;
+ p_uart->uartlcr_h = UART_PL011_LCR_H_REG_RESET_VALUE;
+ p_uart->uartifls = UART_PL011_IFLS_REG_RESET_VALUE;
+ p_uart->uartimsc = UART_PL011_IMSC_REG_RESET_VALUE;
+ /* Clear all the interrupts */
+ p_uart->uarticr = UART_PL011_ICR_REG_CLEAR_VALUE;
+ p_uart->uartdmacr = UART_PL011_DMACR_REG_RESET_VALUE;
+}
+
+enum uart_pl011_error_t uart_pl011_init(struct uart_pl011_dev_t* dev,
+ uint32_t uart_clk)
+{
+ enum uart_pl011_error_t err;
+
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ uint32_t def_baud = dev->cfg->def_baudrate;
+
+ if(uart_clk == 0) {
+ return UART_PL011_ERR_INVALID_ARG;
+ }
+
+ if(def_baud == 0) {
+ return UART_PL011_ERR_INVALID_BAUD;
+ }
+
+ /* Updating the system clock */
+ dev->data->uart_clk = uart_clk;
+
+ /* Setting the default baudrate */
+ err = _uart_pl011_set_baudrate(p_uart, uart_clk, def_baud);
+
+ if(err != UART_PL011_ERR_NONE) {
+ return err;
+ }
+
+ /* Setting the default character format */
+ _uart_pl011_set_format(p_uart, dev->cfg->def_wlen,
+ dev->cfg->def_parity,
+ dev->cfg->def_stopbit);
+
+ /* Enabling the FIFOs */
+ _uart_pl011_enable_fifo(p_uart);
+
+ dev->data->state = UART_PL011_INITIALIZED;
+
+ return UART_PL011_ERR_NONE;
+}
+
+void uart_pl011_uninit(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ while(_uart_pl011_is_busy(p_uart));
+
+ /* Disable and restore the default configuration of the peripheral */
+ _uart_pl011_reset_regs(p_uart);
+
+ dev->data->state = UART_PL011_UNINITIALIZED;
+
+ return;
+}
+
+enum uart_pl011_state_t uart_pl011_get_state(struct uart_pl011_dev_t* dev)
+{
+ return dev->data->state;
+}
+
+enum uart_pl011_error_t uart_pl011_set_baudrate(
+ struct uart_pl011_dev_t* dev, uint32_t baudrate)
+{
+ enum uart_pl011_error_t err = UART_PL011_ERR_NONE;
+
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ bool uart_enabled = _uart_pl011_is_enabled(p_uart);
+
+ if(uart_pl011_get_state(dev) != UART_PL011_INITIALIZED) {
+ return UART_PL011_ERR_NOT_INIT;
+ }
+
+ if(baudrate == 0) {
+ return UART_PL011_ERR_INVALID_BAUD;
+ }
+
+ /* UART must be disabled before any Control Register or
+ * Line Control Register are reprogrammed */
+ _uart_pl011_disable(p_uart);
+
+ /* If baudrate is not valid ie UART_PL011_ERR_NONE is not returned then
+ * the UART will continue to function at the old baudrate */
+ err = _uart_pl011_set_baudrate(p_uart, dev->data->uart_clk, baudrate);
+
+ if(err == UART_PL011_ERR_NONE) {
+ dev->data->baudrate = baudrate;
+ }
+
+ if(uart_enabled) {
+ _uart_pl011_enable(p_uart);
+ }
+
+ return err;
+}
+
+uint32_t uart_pl011_get_baudrate(struct uart_pl011_dev_t* dev)
+{
+ return dev->data->baudrate;
+}
+
+void uart_pl011_enable_intr(struct uart_pl011_dev_t* dev,
+ enum uart_pl011_intr_t mask)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ p_uart->uartimsc |= (uint32_t)(mask);
+
+ return;
+}
+
+void uart_pl011_disable_intr(struct uart_pl011_dev_t* dev,
+ enum uart_pl011_intr_t mask)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ p_uart->uartimsc &= (uint32_t)(~mask);
+
+ return;
+}
+
+void uart_pl011_clear_intr(struct uart_pl011_dev_t* dev,
+ enum uart_pl011_intr_t mask)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ p_uart->uarticr = (uint32_t)mask;
+
+ return;
+}
+
+
+enum uart_pl011_intr_t uart_pl011_get_masked_intr_status(
+ struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ return (enum uart_pl011_intr_t)(p_uart->uartmis);
+
+}
+
+enum uart_pl011_intr_t uart_pl011_get_raw_intr_status(
+ struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ return (enum uart_pl011_intr_t)(p_uart->uartris);
+}
+
+void uart_pl011_set_rx_fifo_lvl(struct uart_pl011_dev_t* dev,
+ enum uart_pl011_rx_fifo_lvl_t rx_lvl)
+{
+ uint32_t fifo_lvl;
+
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ /* Check if rx_lvl have valid values */
+ rx_lvl &= UART_PL011_UARTIFLS_RX_FIFO_LVL_MASK;
+
+ fifo_lvl = p_uart->uartifls
+ & ~(UART_PL011_UARTIFLS_RX_FIFO_LVL_MASK);
+ p_uart->uartifls = fifo_lvl | rx_lvl;
+
+ return;
+}
+
+void uart_pl011_set_tx_fifo_lvl(struct uart_pl011_dev_t* dev,
+ enum uart_pl011_tx_fifo_lvl_t tx_lvl)
+{
+ uint32_t fifo_lvl;
+
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+ /* Check if tx_lvl have valid values */
+ tx_lvl &= UART_PL011_UARTIFLS_TX_FIFO_LVL_MASK;
+
+ fifo_lvl = p_uart->uartifls
+ & ~(UART_PL011_UARTIFLS_TX_FIFO_LVL_MASK);
+ p_uart->uartifls = fifo_lvl | tx_lvl;
+
+ return;
+}
+
+void uart_pl011_set_tx_dma(struct uart_pl011_dev_t* dev,
+ enum uart_pl011_tx_dma_t enable)
+{
+ uint32_t dma_cr;
+
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ enable &= UART_PL011_UARTDMACR_TX_MASK;
+
+ dma_cr = p_uart->uartdmacr
+ & ~(UART_PL011_UARTDMACR_TX_MASK);
+
+ p_uart->uartdmacr = dma_cr | enable;
+
+ return;
+}
+
+void uart_pl011_set_rx_dma(struct uart_pl011_dev_t* dev,
+ enum uart_pl011_rx_dma_t enable)
+{
+ uint32_t dma_cr;
+
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ enable &= UART_PL011_UARTDMACR_RX_MASK;
+
+ dma_cr = p_uart->uartdmacr
+ & ~(UART_PL011_UARTDMACR_RX_MASK);
+
+ p_uart->uartdmacr = dma_cr | enable;
+
+ return;
+}
+
+bool uart_pl011_is_readable(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ if( (uart_pl011_get_state(dev) == UART_PL011_INITIALIZED) &&
+ /* UART is initialized */
+ (p_uart->uartcr & UART_PL011_UARTCR_EN_MASK) &&
+ /* UART is enabled */
+ (p_uart->uartcr & UART_PL011_UARTCR_RX_EN_MASK) &&
+ /* Receive is enabled */
+ ((p_uart->uartfr & UART_PL011_UARTFR_RX_FIFO_EMPTY) == 0)) {
+ /* Receive Fifo is not empty */
+ return true;
+ }
+
+ return false;
+
+}
+
+enum uart_pl011_error_t uart_pl011_read(
+ struct uart_pl011_dev_t* dev, uint8_t* byte)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ *byte = p_uart->uartdr;
+
+ return (enum uart_pl011_error_t)(p_uart->uartrsr
+ & UART_PL011_RX_ERR_MASK);
+}
+
+bool uart_pl011_is_writable(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ if( (uart_pl011_get_state(dev) == UART_PL011_INITIALIZED) &&
+ /* UART is initialized */
+ (p_uart->uartcr & UART_PL011_UARTCR_EN_MASK) &&
+ /* UART is enabled */
+ (p_uart->uartcr & UART_PL011_UARTCR_TX_EN_MASK) &&
+ /* Transmit is enabled */
+ ((p_uart->uartfr & UART_PL011_UARTFR_TX_FIFO_FULL) == 0)) {
+ /* Transmit Fifo is not full */
+ return true;
+ }
+ return false;
+
+}
+
+void uart_pl011_write(struct uart_pl011_dev_t* dev, uint8_t byte)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ p_uart->uartdr = byte;
+
+ return;
+}
+
+enum uart_pl011_error_t uart_pl011_set_format(struct uart_pl011_dev_t* dev,
+ enum uart_pl011_wlen_t word_len,
+ enum uart_pl011_parity_t parity,
+ enum uart_pl011_stopbit_t stop_bits)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ bool uart_enabled = _uart_pl011_is_enabled(p_uart);
+
+ if(uart_pl011_get_state(dev) != UART_PL011_INITIALIZED) {
+ return UART_PL011_ERR_NOT_INIT;
+ }
+
+ /* UART must be disabled before any Control Register or
+ * Line Control Register are reprogrammed */
+ _uart_pl011_disable(p_uart);
+
+ _uart_pl011_set_format(p_uart, word_len, parity, stop_bits);
+
+ /* Enabling the UART if previously enabled */
+ if(uart_enabled) {
+ _uart_pl011_enable(p_uart);
+ }
+
+ return UART_PL011_ERR_NONE;
+}
+
+void uart_pl011_enable_fifo(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_set_lcr_h_bit(p_uart, UART_PL011_UARTLCR_H_FEN_MASK);
+
+ return;
+}
+
+void uart_pl011_disable_fifo(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_clear_lcr_h_bit(p_uart, UART_PL011_UARTLCR_H_FEN_MASK);
+
+ return;
+}
+
+void uart_pl011_enable_break(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_set_lcr_h_bit(p_uart, UART_PL011_UARTLCR_H_BRK_MASK);
+
+ return;
+}
+
+void uart_pl011_disable_break(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_clear_lcr_h_bit(p_uart, UART_PL011_UARTLCR_H_BRK_MASK);
+
+ return;
+}
+
+void uart_pl011_enable_cts_flowcontrol(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_set_cr_bit(p_uart, UART_PL011_UARTCR_CTSE_MASK);
+
+ return;
+}
+
+void uart_pl011_disable_cts_flowcontrol(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_clear_cr_bit(p_uart, UART_PL011_UARTCR_CTSE_MASK);
+
+ return;
+}
+
+void uart_pl011_enable_rts_flowcontrol(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_set_cr_bit(p_uart, UART_PL011_UARTCR_RTSE_MASK);
+
+ return;
+}
+
+void uart_pl011_disable_rts_flowcontrol(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_clear_cr_bit(p_uart, UART_PL011_UARTCR_RTSE_MASK);
+
+ return;
+}
+
+void uart_pl011_enable_ri(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_set_cr_bit(p_uart, UART_PL011_UARTCR_OUT2_MASK);
+
+ return;
+}
+
+void uart_pl011_disable_ri(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_clear_cr_bit(p_uart, UART_PL011_UARTCR_OUT2_MASK);
+
+ return;
+}
+
+void uart_pl011_enable_dcd(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_set_cr_bit(p_uart, UART_PL011_UARTCR_OUT1_MASK);
+
+ return;
+}
+
+void uart_pl011_disable_dcd(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_clear_cr_bit(p_uart, UART_PL011_UARTCR_OUT1_MASK);
+
+ return;
+}
+
+void uart_pl011_set_rts(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_set_cr_bit(p_uart, UART_PL011_UARTCR_RTS_MASK);
+
+ return;
+}
+
+void uart_pl011_clear_rts(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_clear_cr_bit(p_uart, UART_PL011_UARTCR_RTS_MASK);
+
+ return;
+}
+
+void uart_pl011_set_dtr(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_set_cr_bit(p_uart, UART_PL011_UARTCR_DTR_MASK);
+
+ return;
+}
+
+void uart_pl011_clear_dtr(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_clear_cr_bit(p_uart, UART_PL011_UARTCR_DTR_MASK);
+
+ return;
+}
+
+void uart_pl011_enable_receive(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_set_cr_bit(p_uart, UART_PL011_UARTCR_RX_EN_MASK);
+
+ return;
+}
+
+void uart_pl011_disable_receive(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_clear_cr_bit(p_uart, UART_PL011_UARTCR_RX_EN_MASK);
+
+ return;
+}
+
+void uart_pl011_enable_transmit(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_set_cr_bit(p_uart, UART_PL011_UARTCR_TX_EN_MASK);
+
+ return;
+}
+
+void uart_pl011_disable_transmit(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_clear_cr_bit(p_uart, UART_PL011_UARTCR_TX_EN_MASK);
+
+ return;
+}
+
+void uart_pl011_set_loopback(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_set_cr_bit(p_uart, UART_PL011_UARTCR_LBE_MASK);
+
+ return;
+}
+
+void uart_pl011_clear_loopback(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_clear_cr_bit(p_uart, UART_PL011_UARTCR_LBE_MASK);
+
+ return;
+}
+
+void uart_pl011_enable_sirlp(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_set_cr_bit(p_uart,
+ UART_PL011_UARTCR_SIREN_MASK | UART_PL011_UARTCR_SIRLP_MASK);
+
+ return;
+}
+
+void uart_pl011_disable_sirlp(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_clear_cr_bit(p_uart,
+ UART_PL011_UARTCR_SIREN_MASK | UART_PL011_UARTCR_SIRLP_MASK);
+
+ return;
+}
+
+void uart_pl011_enable_sir(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_set_cr_bit(p_uart, UART_PL011_UARTCR_SIREN_MASK);
+
+ return;
+}
+
+void uart_pl011_disable_sir(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_clear_cr_bit(p_uart, UART_PL011_UARTCR_SIREN_MASK);
+
+ return;
+}
+
+void uart_pl011_enable(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_enable(p_uart);
+
+ return;
+}
+
+void uart_pl011_disable(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ _uart_pl011_disable(p_uart);
+
+ return;
+}
+
+bool uart_pl011_get_cts_status(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+ return (bool)(p_uart->uartfr & UART_PL011_UARTFR_CTS_MASK);
+
+}
+
+bool uart_pl011_get_dsr_status(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+ return (bool)(p_uart->uartfr & UART_PL011_UARTFR_DSR_MASK);
+
+}
+
+bool uart_pl011_get_dcd_status(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+ return (bool)(p_uart->uartfr & UART_PL011_UARTFR_DCD_MASK);
+
+}
+
+bool uart_pl011_get_ri_status(struct uart_pl011_dev_t* dev)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+ return (bool)(p_uart->uartfr & UART_PL011_UARTFR_RI_MASK);
+
+}
+
+enum uart_pl011_error_t uart_pl011_set_sirlp_divisor(
+ struct uart_pl011_dev_t* dev, uint32_t value)
+{
+ struct _uart_pl011_reg_map_t* p_uart =
+ (struct _uart_pl011_reg_map_t*)dev->cfg->base;
+
+ uint32_t irlp_baud16_clk;
+
+ if(uart_pl011_get_state(dev) != UART_PL011_INITIALIZED) {
+ return UART_PL011_ERR_NOT_INIT;
+ }
+
+ if(value == 0) {
+ return UART_PL011_ERR_INVALID_ARG;
+ }
+
+ irlp_baud16_clk = dev->data->uart_clk/value;
+
+ /* Chose the divisor so that 1.42MHz < FIrLPBaud16 < 2.12MHz, that
+ * results in a low-power pulse duration of 1.41–2.11μs (three times
+ * the period of IrLPBaud16). ARM DDI0183F Pg 3-9 */
+ if(irlp_baud16_clk < FREQ_IRLPBAUD16_MIN ||
+ irlp_baud16_clk > FREQ_IRLPBAUD16_MAX) {
+ return UART_PL011_ERR_INVALID_ARG;
+ }
+
+ p_uart->uartilpr = value;
+
+ return UART_PL011_ERR_NONE;
+}