diff --git a/src/drivers/imx_uart/imx_uart.c b/src/drivers/imx_uart/imx_uart.c new file mode 100644 index 0000000..355f75f --- /dev/null +++ b/src/drivers/imx_uart/imx_uart.c @@ -0,0 +1,119 @@ +/** + * Bao, a Lightweight Static Partitioning Hypervisor + * + * Copyright (c) Bao Project (www.bao-project.org), 2019- + * + * Authors: + * David Cerdeira + * + * Bao is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License version 2 as published by the Free + * Software Foundation, with a special exception exempting guest code from such + * license. See the COPYING file in the top-level directory for details. + * + */ + +#include +#include + +#define IMX_UART_STAT2_TXFULL (1 << 4) + +#define IMX_UART_UTS_SOFTRST (1UL << 0) +#define IMX_UART_UTS_RXEMPTY (1UL << 5) + +#define IMX_UART_CR1_RRDYEN (1 << 9) +#define IMX_UART_CR1_UARTEN (1 << 0) + +#define IMX_UART_CR2_IRTS (1 << 14) +#define IMX_UART_CR2_WS (1 << 5) +#define IMX_UART_CR2_TXEN (1 << 2) +#define IMX_UART_CR2_RXEN (1 << 1) +#define IMX_UART_CR2_SRST (0 << 1) + +#define IMX_UART_CR3_DSR (1 << 10) +#define IMX_UART_CR3_DCD (1 << 9) +#define IMX_UART_CR3_RI (1 << 8) +#define IMX_UART_CR3_ADNIMP (1 << 7) +#define IMX_UART_CR3_RXDMUXSEL (1 << 2) + +#define IMX_UART_FCR_TXTL(x) ((x) << 10) + +#define IMX_UART_FCR_RFDIV2 (1 << 9) +#define IMX_UART_FCR_RXTL(x) (x) + +void imx_uart_init(volatile struct imx_uart *uart){ + /* Baudrate 115200 8N1 */ + + /* reset UART */ + uart->ucr2 = 0; + while(uart->uts & IMX_UART_UTS_SOFTRST); + + uart->ucr1 = IMX_UART_CR1_UARTEN; + + /* Ignore RTS, 8N1 */ + uart->ucr2 = IMX_UART_CR2_IRTS | IMX_UART_CR2_WS | IMX_UART_CR2_SRST | + IMX_UART_CR2_TXEN | IMX_UART_CR2_RXEN; + + /* No parity, autobaud detect-old, rxdmuxsel=1 */ + uart->ucr3 = IMX_UART_CR3_DSR | IMX_UART_CR3_DCD | IMX_UART_CR3_RI | + IMX_UART_CR3_ADNIMP | IMX_UART_CR3_RXDMUXSEL; + + /* Set CTS FIFO trigger to 32 bytes bits 15:10 */ + uart->ucr4 = 0x8000; + + /* TX/RX-thresh = 2 bytes, DTE (bit6 = 0), refclk @24MHz / 4 */ + uart->ufcr = IMX_UART_FCR_TXTL(2) | IMX_UART_FCR_RXTL(1) | IMX_UART_FCR_RFDIV2; + + uart->uesc = 0x2B; + + /* + * The equation for BAUD rate calculation is + * RefClk = Supplied clock / FCR_DIVx + * + * BAUD = Refclk + * ------------ + * 16 x (UBMR + 1/ UBIR + 1) + * + * We write 0x0f into UBIR to remove the 16 mult + * BAUD = 6000000 + * ------------ + * 16 x (UBMR + 1/ 15 + 1) + */ + fence_sync(); + uart->ubir = 0x0fUL; + + uart->ubmr = ((24000000 / 2) / 115200); + + uart->utim = 0; + uart->uts = 0; + uart->umcr = 0; +} + +void imx_uart_putc(volatile struct imx_uart *uart, char c){ + /* TX FULL */ + while((uart->uts & IMX_UART_STAT2_TXFULL)); + uart->utxd = c; +} + +void uimx_art_puts(volatile struct imx_uart *uart, char const* str){ + while (*str) { + imx_uart_putc(uart, *str++); + } +} + +char imx_uart_getchar(volatile struct imx_uart *uart){ + if((uart->uts & IMX_UART_UTS_RXEMPTY)) + return -1; + /* Only read the UART character */ + return uart->urxd & 0x000000FF; +} + + +void imx_uart_enable_rxirq(volatile struct imx_uart *uart){ + uart->ucr1 |= IMX_UART_CR1_RRDYEN; + (void)uart->stat1; +} + +void imx_uart_clear_rxirq(volatile struct imx_uart *uart){ + (void) imx_uart_getchar(uart); +} diff --git a/src/drivers/imx_uart/inc/imx_uart.h b/src/drivers/imx_uart/inc/imx_uart.h new file mode 100644 index 0000000..2ecc239 --- /dev/null +++ b/src/drivers/imx_uart/inc/imx_uart.h @@ -0,0 +1,36 @@ +#ifndef IMX_UART_H +#define IMX_UART_H + +#include +#include + +struct imx_uart { + uint32_t urxd; /* 0x0 */ + uint32_t reserved1[0xf]; /* (0x40 - 0x4) / 4 */ + uint32_t utxd; /* 0x40*/ + uint32_t reserved2[0xf]; /* (0x80 - 0x44) / 4 */ + uint32_t ucr1; /* 0x80 */ + uint32_t ucr2; /* 0x84 */ + uint32_t ucr3; /* 0x88 */ + uint32_t ucr4; /* 0x8c */ + uint32_t ufcr; /* 0x90 */ + uint32_t stat1; /* 0x94 */ + uint32_t stat2; /* 0x98 */ + uint32_t uesc; /* 0x9c */ + uint32_t utim; /* 0xa0 */ + uint32_t ubir; /* 0xa4 */ + uint32_t ubmr; /* 0xa8 */ + uint32_t ubrc; /* 0xac */ + uint32_t onems; /* 0xb0 */ + uint32_t uts; /* 0xb4 */ + uint32_t umcr; /* 0xb8 */ +}; + +void imx_uart_init(volatile struct imx_uart *uart); +void imx_uart_puts(volatile struct imx_uart * uart, const char* str); +void imx_uart_putc(volatile struct imx_uart * uart, char str); +char imx_uart_getchar(volatile struct imx_uart * uart); +void imx_uart_clear_rxirq(volatile struct imx_uart * uart); +void imx_uart_enable_rxirq(volatile struct imx_uart * uart); + +#endif /* IMX_UART_H */ diff --git a/src/drivers/imx_uart/sources.mk b/src/drivers/imx_uart/sources.mk new file mode 100644 index 0000000..2ef67f6 --- /dev/null +++ b/src/drivers/imx_uart/sources.mk @@ -0,0 +1,2 @@ +driver_c_srcs+=imx_uart/imx_uart.c +driver_s_srcs+= diff --git a/src/platform/imx8mp-verdin/imx8m.c b/src/platform/imx8mp-verdin/imx8m.c new file mode 100644 index 0000000..ae09166 --- /dev/null +++ b/src/platform/imx8mp-verdin/imx8m.c @@ -0,0 +1,24 @@ +#include +#include + +volatile struct imx_uart * const uart = UART_ADDR; + +void uart_init(){ + imx_uart_init(uart); +} + +void uart_putc(char c){ + imx_uart_putc(uart, c); +} + +char uart_getchar(){ + return imx_uart_getchar(uart); +} + +void uart_enable_rxirq(){ + imx_uart_enable_rxirq(uart); +} + +void uart_clear_rxirq(){ + imx_uart_clear_rxirq(uart); +} diff --git a/src/platform/imx8mp-verdin/inc/plat.h b/src/platform/imx8mp-verdin/inc/plat.h new file mode 100644 index 0000000..1d2bd22 --- /dev/null +++ b/src/platform/imx8mp-verdin/inc/plat.h @@ -0,0 +1,13 @@ +#ifndef PLAT_H +#define PLAT_H + +#define PLAT_MEM_BASE 0x80200000 +#define PLAT_MEM_SIZE 0x8000000 + +#define PLAT_GICD_BASE_ADDR (0x38800000) +#define PLAT_GICR_BASE_ADDR (0x38880000) + +#define PLAT_UART_ADDR (0x30880000UL) +#define UART_IRQ_ID (60) + +#endif diff --git a/src/platform/imx8mp-verdin/plat.mk b/src/platform/imx8mp-verdin/plat.mk new file mode 100644 index 0000000..0abe0b9 --- /dev/null +++ b/src/platform/imx8mp-verdin/plat.mk @@ -0,0 +1,3 @@ +ARCH:=armv8 +GIC_VERSION:=GICV3 +drivers:=imx_uart diff --git a/src/platform/imx8mp-verdin/sources.mk b/src/platform/imx8mp-verdin/sources.mk new file mode 100644 index 0000000..7cc3739 --- /dev/null +++ b/src/platform/imx8mp-verdin/sources.mk @@ -0,0 +1,2 @@ +plat_c_srcs:=imx8m.c +plat_s_srcs:=