mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-23 04:41:12 +00:00
thermosphere: refactor tegra uart code, etc.
This commit is contained in:
parent
a552c254e0
commit
26bda4f32d
10 changed files with 261 additions and 149 deletions
|
@ -129,9 +129,6 @@ void initIrq(void)
|
|||
|
||||
configureInterrupt(GIC_IRQID_MAINTENANCE, IRQ_PRIORITY_HOST, true);
|
||||
|
||||
for(u32 i=32; i < 256+32; i++) {
|
||||
configureInterrupt(i, IRQ_PRIORITY_HOST, true);
|
||||
}
|
||||
recursiveSpinlockUnlockRestoreIrq(&g_irqManager.lock, flags);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,8 +45,9 @@ void thermosphereMain(ExceptionStackFrame *frame)
|
|||
initIrq();
|
||||
|
||||
if (currentCoreCtx->isBootCore) {
|
||||
uartInit(DEFAULT_UART, 115200, 0);
|
||||
uartSetInterruptStatus(DEFAULT_UART, false, false);
|
||||
uartInit(DEFAULT_UART, BAUD_115200, 0);
|
||||
uartSetInterruptStatus(DEFAULT_UART, DIRECTION_READ, true);
|
||||
|
||||
DEBUG("EL2: core %u reached main first!\n", currentCoreCtx->coreId);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,21 +21,21 @@
|
|||
// For both guest and host
|
||||
#define MAX_NUM_REGISTERED_INTERRUPTS 512
|
||||
|
||||
#define GIC_IRQID_PMU 23
|
||||
#define GIC_IRQID_MAINTENANCE 25
|
||||
#define GIC_IRQID_NS_PHYS_HYP_TIMER 26
|
||||
#define GIC_IRQID_NS_VIRT_TIMER 27
|
||||
//#define GIC_IRQID_LEGACY_NFIQ 28 not defined?
|
||||
#define GIC_IRQID_SEC_PHYS_TIMER 29
|
||||
#define GIC_IRQID_NS_PHYS_TIMER 30
|
||||
//#define GIC_IRQID_LEGACY_NIRQ 31 not defined?
|
||||
#define GIC_IRQID_PMU 23
|
||||
#define GIC_IRQID_MAINTENANCE 25
|
||||
#define GIC_IRQID_NS_PHYS_HYP_TIMER 26
|
||||
#define GIC_IRQID_NS_VIRT_TIMER 27
|
||||
//#define GIC_IRQID_LEGACY_NFIQ 28 not defined?
|
||||
#define GIC_IRQID_SEC_PHYS_TIMER 29
|
||||
#define GIC_IRQID_NS_PHYS_TIMER 30
|
||||
//#define GIC_IRQID_LEGACY_NIRQ 31 not defined?
|
||||
|
||||
|
||||
#define GIC_IRQID_NS_VIRT_HYP_TIMER GIC_IRQID_SPURIOUS // SBSA: 28. Unimplemented
|
||||
#define GIC_IRQID_SEC_PHYS_HYP_TIMER GIC_IRQID_SPURIOUS // SBSA: 20. Unimplemented
|
||||
#define GIC_IRQID_SEC_VIRT_HYP_TIMER GIC_IRQID_SPURIOUS // SBSA: 19. Unimplemented
|
||||
|
||||
#define GIC_IRQID_UART 33
|
||||
#define GIC_IRQID_UART (32 + 1)
|
||||
|
||||
static inline void initGicV2Pointers(ArmGicV2 *gic)
|
||||
{
|
||||
|
|
|
@ -83,12 +83,11 @@ void uartInit(UartDevice dev, u32 baudRate, u32 flags)
|
|||
uart->icr = PL011_ALL_INTERRUPTS;
|
||||
|
||||
// Register the interrupt ID
|
||||
//configureInterrupt(uartGetIrqId(dev), IRQ_PRIORITY_HOST, true);
|
||||
configureInterrupt(uartGetIrqId(dev), IRQ_PRIORITY_HOST, true);
|
||||
|
||||
// Enable tx, rx, and uart overall
|
||||
uart->cr = PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN;
|
||||
uart->imsc = PL011_RTI | PL011_RXI | PL011_RXI;
|
||||
|
||||
//uart->imsc = PL011_RTI | PL011_RXI | PL011_RXI;
|
||||
}
|
||||
|
||||
void uartWriteData(UartDevice dev, const void *buffer, size_t size)
|
||||
|
@ -120,24 +119,48 @@ size_t uartReadDataMax(UartDevice dev, void *buffer, size_t maxSize)
|
|||
volatile PL011UartRegisters *uart = uartGetRegisters(dev);
|
||||
|
||||
u8 *buf8 = (u8 *)buffer;
|
||||
size_t i;
|
||||
size_t count = 0;
|
||||
|
||||
for (i = 0; i < maxSize && !(uart->fr & PL011_UARTFR_RXFE); i++) {
|
||||
for (size_t i = 0; i < maxSize && !(uart->fr & PL011_UARTFR_RXFE); i++) {
|
||||
buf8[i] = uart->dr;
|
||||
++count;
|
||||
}
|
||||
|
||||
return 1 + i;
|
||||
return count;
|
||||
}
|
||||
|
||||
void uartSetInterruptStatus(UartDevice dev, bool read, bool enable)
|
||||
ReadWriteDirection uartGetInterruptDirection(UartDevice dev)
|
||||
{
|
||||
volatile PL011UartRegisters *uart = uartGetRegisters(dev);
|
||||
u32 ret = 0;
|
||||
|
||||
u32 istatus = uart->mis;
|
||||
if (istatus & (PL011_RTI | PL011_RXI)) {
|
||||
ret |= DIRECTION_READ;
|
||||
}
|
||||
if (istatus & PL011_TXI) {
|
||||
ret |= DIRECTION_WRITE;
|
||||
}
|
||||
|
||||
return (ReadWriteDirection)ret;
|
||||
}
|
||||
|
||||
void uartSetInterruptStatus(UartDevice dev, ReadWriteDirection direction, bool enable)
|
||||
{
|
||||
volatile PL011UartRegisters *uart = uartGetRegisters(dev);
|
||||
|
||||
u32 mask = read ? PL011_RTI | PL011_RXI : PL011_RTI;
|
||||
u32 mask = 0;
|
||||
if (direction & DIRECTION_READ) {
|
||||
mask |= PL011_RTI | PL011_RXI;
|
||||
}
|
||||
if (direction & DIRECTION_WRITE) {
|
||||
mask |= PL011_TXI;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
uart->imsc |= mask;
|
||||
} else {
|
||||
uart->icr = mask;
|
||||
uart->imsc &= ~mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,7 +132,8 @@ void uartInit(UartDevice dev, u32 baudRate, u32 flags);
|
|||
void uartWriteData(UartDevice dev, const void *buffer, size_t size);
|
||||
void uartReadData(UartDevice dev, void *buffer, size_t size);
|
||||
size_t uartReadDataMax(UartDevice dev, void *buffer, size_t maxSize);
|
||||
void uartSetInterruptStatus(UartDevice dev, bool read, bool enable);
|
||||
ReadWriteDirection uartGetInterruptDirection(UartDevice dev);
|
||||
void uartSetInterruptStatus(UartDevice dev, ReadWriteDirection direction, bool enable);
|
||||
|
||||
static inline u16 uartGetIrqId(UartDevice dev)
|
||||
{
|
||||
|
@ -142,4 +143,4 @@ static inline u16 uartGetIrqId(UartDevice dev)
|
|||
default:
|
||||
return GIC_IRQID_SPURIOUS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,11 @@
|
|||
#define GIC_IRQID_SEC_PHYS_HYP_TIMER GIC_IRQID_SPURIOUS // SBSA: 20. Unimplemented
|
||||
#define GIC_IRQID_SEC_VIRT_HYP_TIMER GIC_IRQID_SPURIOUS // SBSA: 19. Unimplemented
|
||||
|
||||
#define GIC_IRQID_UARTA (32 + 36)
|
||||
#define GIC_IRQID_UARTB (32 + 37)
|
||||
#define GIC_IRQID_UARTC (32 + 46)
|
||||
#define GIC_IRQID_UARTD (32 + 90)
|
||||
|
||||
static inline void initGicV2Pointers(ArmGicV2 *gic)
|
||||
{
|
||||
gic->gicd = (volatile ArmGicV2Distributor *)0x50041000ull;
|
||||
|
|
|
@ -20,18 +20,27 @@
|
|||
#include "pinmux.h"
|
||||
#include "gpio.h"
|
||||
#include "car.h"
|
||||
#include "../../irq.h"
|
||||
|
||||
static inline void uart_wait_cycles(uint32_t baud, uint32_t num)
|
||||
#define UART_BASE 0x70006000
|
||||
|
||||
static inline volatile tegra_uart_t *uartGetRegisters(UartDevice dev)
|
||||
{
|
||||
static const size_t offsets[] = { 0, 0x40, 0x200, 0x300, 0x400 };
|
||||
return (volatile tegra_uart_t *)(UART_BASE + offsets[dev]);
|
||||
}
|
||||
|
||||
static inline void uartWaitCycles(u32 baud, u32 num)
|
||||
{
|
||||
udelay((num * 1000000 + 16 * baud - 1) / (16 * baud));
|
||||
}
|
||||
|
||||
static inline void uart_wait_syms(uint32_t baud, uint32_t num)
|
||||
static inline void uartWaitSyms(u32 baud, u32 num)
|
||||
{
|
||||
udelay((num * 1000000 + baud - 1) / baud);
|
||||
}
|
||||
|
||||
void uart_config(UartDevice dev) {
|
||||
static void uartSetPinmuxConfig(UartDevice dev) {
|
||||
volatile tegra_pinmux_t *pinmux = pinmux_get_regs();
|
||||
|
||||
switch (dev) {
|
||||
|
@ -60,15 +69,15 @@ void uart_config(UartDevice dev) {
|
|||
pinmux->uart4_cts = (PINMUX_INPUT | PINMUX_PULL_DOWN);
|
||||
break;
|
||||
case UART_E:
|
||||
/* Unused. */
|
||||
// Unused.
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void uart_reset(UartDevice dev)
|
||||
static void uartReset(UartDevice dev)
|
||||
{
|
||||
CarDevice uartCarDevs[] = { CARDEVICE_UARTA, CARDEVICE_UARTB, CARDEVICE_UARTC, CARDEVICE_UARTD };
|
||||
static const CarDevice uartCarDevs[] = { CARDEVICE_UARTA, CARDEVICE_UARTB, CARDEVICE_UARTC, CARDEVICE_UARTD };
|
||||
if (dev == UART_B) {
|
||||
gpio_configure_mode(TEGRA_GPIO(G, 0), GPIO_MODE_SFIO);
|
||||
} else {
|
||||
|
@ -81,88 +90,143 @@ void uart_reset(UartDevice dev)
|
|||
gpio_configure_mode(TEGRA_GPIO(D, 1), GPIO_MODE_GPIO);
|
||||
}
|
||||
|
||||
uart_config(dev);
|
||||
uartSetPinmuxConfig(dev);
|
||||
clkrst_reboot(uartCarDevs[dev]);
|
||||
}
|
||||
|
||||
void uart_init(UartDevice dev, uint32_t baud, bool inverted) {
|
||||
volatile tegra_uart_t *uart = uart_get_regs(dev);
|
||||
|
||||
/* Wait for idle state. */
|
||||
uart_wait_idle(dev, UART_VENDOR_STATE_TX_IDLE);
|
||||
// This function blocks until the UART device is in the desired state.
|
||||
void uartWaitIdle(UartDevice dev, UartVendorStatus status)
|
||||
{
|
||||
volatile tegra_uart_t *uart = uartGetRegisters(dev);
|
||||
|
||||
/* Calculate baud rate, round to nearest. */
|
||||
uint32_t rate = (8 * baud + 408000000) / (16 * baud);
|
||||
|
||||
/* Setup UART in FIFO mode. */
|
||||
uart->UART_IER_DLAB = 0;
|
||||
uart->UART_MCR = 0;
|
||||
uart->UART_LCR = (UART_LCR_DLAB | UART_LCR_WD_LENGTH_8); /* Enable DLAB and set word length 8. */
|
||||
uart->UART_THR_DLAB = (uint8_t)rate; /* Divisor latch LSB. */
|
||||
uart->UART_IER_DLAB = (uint8_t)(rate >> 8); /* Divisor latch MSB. */
|
||||
uart->UART_LCR &= ~(UART_LCR_DLAB); /* Disable DLAB. */
|
||||
uart->UART_SPR; /* Dummy read. */
|
||||
uart_wait_syms(baud, 3); /* Wait for 3 symbols at the new baudrate. */
|
||||
|
||||
/* Enable FIFO with default settings. */
|
||||
uart->UART_IIR_FCR = UART_FCR_FCR_EN_FIFO;
|
||||
uart->UART_IRDA_CSR = inverted ? 2 : 0; /* Invert TX if needed */
|
||||
uart->UART_SPR; /* Dummy read as mandated by TRM. */
|
||||
uart_wait_cycles(baud, 3); /* Wait for 3 baud cycles, as mandated by TRM (erratum). */
|
||||
|
||||
/* Flush FIFO. */
|
||||
uart_wait_idle(dev, UART_VENDOR_STATE_TX_IDLE); /* Make sure there's no data being written in TX FIFO (TRM). */
|
||||
uart->UART_IIR_FCR |= UART_FCR_RX_CLR | UART_FCR_TX_CLR; /* Clear TX and RX FIFOs. */
|
||||
uart_wait_cycles(baud, 32); /* Wait for 32 baud cycles (TRM, erratum). */
|
||||
/* Wait for idle state (TRM). */
|
||||
uart_wait_idle(dev, UART_VENDOR_STATE_TX_IDLE | UART_VENDOR_STATE_RX_IDLE);
|
||||
}
|
||||
|
||||
/* This function blocks until the UART device is in the desired state. */
|
||||
void uart_wait_idle(UartDevice dev, UartVendorStatus status) {
|
||||
volatile tegra_uart_t *uart = uart_get_regs(dev);
|
||||
|
||||
if (status & UART_VENDOR_STATE_TX_IDLE) {
|
||||
while (!(uart->UART_LSR & UART_LSR_TMTY)) {
|
||||
/* Wait */
|
||||
}
|
||||
while (!(uart->lsr & UART_LSR_TMTY));
|
||||
}
|
||||
|
||||
if (status & UART_VENDOR_STATE_RX_IDLE) {
|
||||
while (uart->UART_LSR & UART_LSR_RDR) {
|
||||
/* Wait */
|
||||
}
|
||||
while (uart->lsr & UART_LSR_RDR);
|
||||
}
|
||||
}
|
||||
|
||||
void uart_send(UartDevice dev, const void *buf, size_t len) {
|
||||
volatile tegra_uart_t *uart = uart_get_regs(dev);
|
||||
void uartInit(UartDevice dev, u32 baud, u32 flags)
|
||||
{
|
||||
volatile tegra_uart_t *uart = uartGetRegisters(dev);
|
||||
bool inverted = (flags & BIT(0)) != 0;
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
while (!(uart->UART_LSR & UART_LSR_THRE)) {
|
||||
/* Wait until it's possible to send data. */
|
||||
}
|
||||
uart->UART_THR_DLAB = *((const uint8_t *)buf + i);
|
||||
// Set pinmux, gpio, clock
|
||||
uartReset(dev);
|
||||
|
||||
// Wait for idle state.
|
||||
uartWaitIdle(dev, UART_VENDOR_STATE_TX_IDLE);
|
||||
|
||||
// Calculate baud rate, round to nearest.
|
||||
u32 rate = (8 * baud + 408000000) / (16 * baud);
|
||||
|
||||
uart->lcr &= ~UART_LCR_DLAB; // Disable DLAB.
|
||||
uart->ier = 0; // Disable all interrupts.
|
||||
uart->mcr = 0;
|
||||
|
||||
// Setup UART in FIFO mode
|
||||
uart->lcr = UART_LCR_DLAB | UART_LCR_WD_LENGTH_8; // Enable DLAB and set word length 8.
|
||||
uart->dll = (u8)rate; // Divisor latch LSB.
|
||||
uart->dlh = (u8)(rate >> 8); // Divisor latch MSB.
|
||||
uart->lcr &= ~UART_LCR_DLAB; // Disable DLAB.
|
||||
uart->spr; // Dummy read.
|
||||
uartWaitSyms(baud, 3); // Wait for 3 symbols at the new baudrate.
|
||||
|
||||
// Enable FIFO with default settings.
|
||||
uart->fcr = UART_FCR_FCR_EN_FIFO;
|
||||
uart->irda_csr = inverted ? UART_IRDA_CSR_INVERT_TXD : 0; // Invert TX if needed
|
||||
uart->spr; // Dummy read as mandated by TRM.
|
||||
uartWaitCycles(baud, 3); // Wait for 3 baud cycles, as mandated by TRM (erratum).
|
||||
|
||||
// Flush FIFO.
|
||||
uartWaitIdle(dev, UART_VENDOR_STATE_TX_IDLE); // Make sure there's no data being written in TX FIFO (TRM).
|
||||
uart->fcr |= UART_FCR_RX_CLR | UART_FCR_TX_CLR; // Clear TX and RX FIFOs.
|
||||
uartWaitCycles(baud, 32); // Wait for 32 baud cycles (TRM, erratum).
|
||||
|
||||
// Wait for idle state (TRM).
|
||||
uartWaitIdle(dev, UART_VENDOR_STATE_TX_IDLE | UART_VENDOR_STATE_RX_IDLE);
|
||||
|
||||
// Set scratch register to 0. We'll use it to backup write-only IER later
|
||||
uart->spr = 0;
|
||||
|
||||
// Register the interrupt ID
|
||||
configureInterrupt(uartGetIrqId(dev), IRQ_PRIORITY_HOST, true);
|
||||
}
|
||||
|
||||
void uartWriteData(UartDevice dev, const void *buffer, size_t size)
|
||||
{
|
||||
volatile tegra_uart_t *uart = uartGetRegisters(dev);
|
||||
const u8 *buf8 = (const u8 *)buffer;
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
while (!(uart->lsr & UART_LSR_THRE)); // Wait until it's possible to send data.
|
||||
uart->thr = buf8[i];
|
||||
}
|
||||
}
|
||||
|
||||
void uart_recv(UartDevice dev, void *buf, size_t len) {
|
||||
volatile tegra_uart_t *uart = uart_get_regs(dev);
|
||||
void uartReadData(UartDevice dev, void *buffer, size_t size)
|
||||
{
|
||||
volatile tegra_uart_t *uart = uartGetRegisters(dev);
|
||||
u8 *buf8 = (u8 *)buffer;
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
while (!(uart->UART_LSR & UART_LSR_RDR)) {
|
||||
/* Wait until it's possible to receive data. */
|
||||
}
|
||||
*((uint8_t *)buf + i) = uart->UART_THR_DLAB;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
while (!(uart->lsr & UART_LSR_RDR)) // Wait until it's possible to receive data.
|
||||
buf8[i] = uart->rbr;
|
||||
}
|
||||
}
|
||||
|
||||
size_t uart_recv_max(UartDevice dev, void *buf, size_t max_len) {
|
||||
volatile tegra_uart_t *uart = uart_get_regs(dev);
|
||||
size_t i;
|
||||
size_t uartReadDataMax(UartDevice dev, void *buffer, size_t maxSize)
|
||||
{
|
||||
volatile tegra_uart_t *uart = uartGetRegisters(dev);
|
||||
u8 *buf8 = (u8 *)buffer;
|
||||
size_t count = 0;
|
||||
|
||||
for (i = 0; i < max_len && (uart->UART_LSR & UART_LSR_RDR); i++) {
|
||||
*((uint8_t *)buf + i) = uart->UART_THR_DLAB;
|
||||
for (size_t i = 0; i < maxSize && (uart->lsr & UART_LSR_RDR); i++) {
|
||||
buf8[i] = uart->rbr;
|
||||
++count;
|
||||
}
|
||||
|
||||
return 1 + i;
|
||||
return count;
|
||||
}
|
||||
|
||||
ReadWriteDirection uartGetInterruptDirection(UartDevice dev)
|
||||
{
|
||||
volatile tegra_uart_t *uart = uartGetRegisters(dev);
|
||||
u32 ret = 0;
|
||||
|
||||
u32 iir = uart->iir & 0xF;
|
||||
|
||||
if (iir == 8 || iir == 12) {
|
||||
// Data ready or data timeout
|
||||
ret |= DIRECTION_READ;
|
||||
} else if (iir == 2) {
|
||||
// TX FIFO empty
|
||||
ret |= DIRECTION_WRITE;
|
||||
}
|
||||
|
||||
return (ReadWriteDirection)ret;
|
||||
}
|
||||
|
||||
void uartSetInterruptStatus(UartDevice dev, ReadWriteDirection direction, bool enable)
|
||||
{
|
||||
volatile tegra_uart_t *uart = uartGetRegisters(dev);
|
||||
|
||||
u32 mask = 0;
|
||||
if (direction & DIRECTION_READ) {
|
||||
mask |= UART_IER_IE_RX_TIMEOUT | UART_IER_IE_RHR;
|
||||
}
|
||||
if (direction & DIRECTION_WRITE) {
|
||||
mask |= UART_IER_IE_THR;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
uart->spr |= mask;
|
||||
uart->ier = uart->spr;
|
||||
} else {
|
||||
uart->spr &= ~mask;
|
||||
uart->ier = uart->spr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,18 +18,17 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../utils.h"
|
||||
|
||||
#define UART_BASE 0x70006000
|
||||
|
||||
#define BAUD_115200 115200
|
||||
#include "interrupt_config.h"
|
||||
|
||||
/* UART devices */
|
||||
typedef enum {
|
||||
typedef enum UartDevice {
|
||||
UART_A = 0,
|
||||
UART_B = 1,
|
||||
UART_C = 2,
|
||||
UART_D = 3,
|
||||
UART_E = 4,
|
||||
|
||||
UART_MAX = UART_E, // Treat UART_E as if it didn't exist
|
||||
} UartDevice;
|
||||
|
||||
/* 36.3.12 UART_VENDOR_STATUS_0_0 */
|
||||
|
@ -123,6 +122,17 @@ typedef enum {
|
|||
UART_FCR_RX_TRIG_FIFO_COUNT_GREATER_16 = 3 << 6,
|
||||
} UartFifoControl;
|
||||
|
||||
/* 36.3.2 UART_IER_DLAB_0_0 */
|
||||
typedef enum {
|
||||
UART_IER_IE_RHR = 1 << 0, /* Interrupt enable for Received Data Interrupt */
|
||||
UART_IER_IE_THR = 1 << 1, /* Interrupt enable for Transmitter Holding Register Empty interrupt */
|
||||
UART_IER_IE_RXS = 1 << 2, /* Interrupt enable for Receiver Line Status Interrupt */
|
||||
UART_IER_IE_MSI = 1 << 3, /* Interrupt enable for Modem Status Interrupt */
|
||||
UART_IER_IE_RX_TIMEOUT = 1 << 4, /* Interrupt enable for RX FIFO timeout */
|
||||
UART_IER_IE_EORD = 1 << 5, /* Interrupt enable for Interrupt Enable for End of Received Data */
|
||||
|
||||
} UartInterruptEnable;
|
||||
|
||||
/* 36.3.3 UART_IIR_FCR_0 */
|
||||
typedef enum {
|
||||
UART_IIR_IS_STA = 1 << 0, /* Interrupt Pending if ZERO */
|
||||
|
@ -139,32 +149,57 @@ typedef enum {
|
|||
UART_IIR_MODE_16550 = 1 << 6,
|
||||
} UartInterruptIdentification;
|
||||
|
||||
/* 36.3.9 UART_IRDA_CSR_0 */
|
||||
typedef enum {
|
||||
UART_IRDA_CSR_INVERT_RXD = 1 << 0,
|
||||
UART_IRDA_CSR_INVERT_TXD = 1 << 1,
|
||||
UART_IRDA_CSR_INVERT_CTS = 1 << 2,
|
||||
UART_IRDA_CSR_INVERT_RTS = 1 << 3,
|
||||
|
||||
UART_IRDA_CSR_PWT_A_BAUD_PULSE_3_14 = 0 << 6,
|
||||
UART_IRDA_CSR_PWT_A_BAUD_PULSE_4_14 = 1 << 6,
|
||||
UART_IRDA_CSR_SIR_A = 1 << 7,
|
||||
} UartIrDAPulseCodingCSR;
|
||||
|
||||
typedef struct {
|
||||
uint32_t UART_THR_DLAB;
|
||||
uint32_t UART_IER_DLAB;
|
||||
uint32_t UART_IIR_FCR;
|
||||
uint32_t UART_LCR;
|
||||
uint32_t UART_MCR;
|
||||
uint32_t UART_LSR;
|
||||
uint32_t UART_MSR;
|
||||
uint32_t UART_SPR;
|
||||
uint32_t UART_IRDA_CSR;
|
||||
uint32_t UART_RX_FIFO_CFG;
|
||||
uint32_t UART_MIE;
|
||||
uint32_t UART_VENDOR_STATUS;
|
||||
uint8_t _0x30[0x0C];
|
||||
uint32_t UART_ASR;
|
||||
union {
|
||||
// UART_THR_DLAB_0
|
||||
u32 thr;
|
||||
u32 rbr;
|
||||
u32 dll;
|
||||
};
|
||||
union {
|
||||
// UART_IER_DLAB_0
|
||||
u32 ier;
|
||||
u32 dlh;
|
||||
};
|
||||
union {
|
||||
// UART_IIR_FCR_0
|
||||
u32 iir;
|
||||
u32 fcr;
|
||||
};
|
||||
u32 lcr;
|
||||
u32 mcr;
|
||||
u32 lsr;
|
||||
u32 msr;
|
||||
u32 spr;
|
||||
u32 irda_csr;
|
||||
u32 rx_fifo_cfg;
|
||||
u32 mie;
|
||||
u32 vendor_status;
|
||||
u8 _0x30[0x0C];
|
||||
u32 asr;
|
||||
} tegra_uart_t;
|
||||
|
||||
void uart_config(UartDevice dev);
|
||||
void uart_reset(UartDevice dev);
|
||||
void uart_init(UartDevice dev, uint32_t baud, bool inverted);
|
||||
void uart_wait_idle(UartDevice dev, UartVendorStatus status);
|
||||
void uart_send(UartDevice dev, const void *buf, size_t len);
|
||||
void uart_recv(UartDevice dev, void *buf, size_t len);
|
||||
size_t uart_recv_max(UartDevice dev, void *buf, size_t max_len);
|
||||
void uartInit(UartDevice dev, u32 baud, u32 flags);
|
||||
void uartWriteData(UartDevice dev, const void *buffer, size_t size);
|
||||
void uartReadData(UartDevice dev, void *buffer, size_t size);
|
||||
size_t uartReadDataMax(UartDevice dev, void *buffer, size_t maxSize);
|
||||
ReadWriteDirection uartGetInterruptDirection(UartDevice dev);
|
||||
void uartSetInterruptStatus(UartDevice dev, ReadWriteDirection direction, bool enable);
|
||||
|
||||
static inline volatile tegra_uart_t *uart_get_regs(UartDevice dev) {
|
||||
static const size_t offsets[] = {0, 0x40, 0x200, 0x300, 0x400};
|
||||
return (volatile tegra_uart_t *)(UART_BASE + offsets[dev]);
|
||||
static inline u16 uartGetIrqId(UartDevice dev)
|
||||
{
|
||||
static const u16 irqIds[] = { GIC_IRQID_UARTA, GIC_IRQID_UARTB, GIC_IRQID_UARTC, GIC_IRQID_UARTD };
|
||||
return dev < UART_MAX ? irqIds[dev] : GIC_IRQID_SPURIOUS;
|
||||
}
|
||||
|
|
|
@ -16,39 +16,19 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#if PLATFORM_TEGRA
|
||||
// TODO
|
||||
#define BAUD_115200 115200
|
||||
|
||||
/*#include "tegra/uart.h"
|
||||
#if PLATFORM_TEGRA
|
||||
|
||||
#include "tegra/uart.h"
|
||||
|
||||
#define DEFAULT_UART UART_C
|
||||
#define DEFAULT_UARTINV_STATUS true
|
||||
|
||||
static inline void uartInit(u32 baudRate)
|
||||
{
|
||||
uart_reset(DEFAULT_UART);
|
||||
uart_init(DEFAULT_UART, baudRate, DEFAULT_UARTINV_STATUS);
|
||||
}
|
||||
|
||||
static inline void uartWriteData(const void *buffer, size_t size)
|
||||
{
|
||||
uart_send(DEFAULT_UART, buffer, size);
|
||||
}
|
||||
|
||||
static inline void uartReadData(void *buffer, size_t size)
|
||||
{
|
||||
uart_recv(DEFAULT_UART, buffer, size);
|
||||
}
|
||||
|
||||
static inline size_t uartReadDataMax(void *buffer, size_t maxSize)
|
||||
{
|
||||
return uart_recv_max(DEFAULT_UART, buffer, maxSize);
|
||||
}
|
||||
*/
|
||||
#define DEFAULT_UART_FLAGS 1
|
||||
|
||||
#elif defined(PLATFORM_QEMU)
|
||||
|
||||
#define DEFAULT_UART UART_A
|
||||
#define DEFAULT_UART_FLAGS 0
|
||||
|
||||
#include "qemu/uart.h"
|
||||
|
||||
|
@ -56,4 +36,4 @@ static inline size_t uartReadDataMax(void *buffer, size_t maxSize)
|
|||
|
||||
#error "Error: platform not defined"
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -56,6 +56,12 @@ static inline u##sz __##op##sz(u##sz n)\
|
|||
_DECLARE_ASM_ARITHMETIC_UNARY_HELPER64(rbit)
|
||||
_DECLARE_ASM_ARITHMETIC_UNARY_HELPER32(rbit)
|
||||
|
||||
typedef enum ReadWriteDirection {
|
||||
DIRECTION_READ = BIT(0),
|
||||
DIRECTION_WRITE = BIT(1),
|
||||
DIRECTION_READWRITE = DIRECTION_READ | DIRECTION_WRITE,
|
||||
} ReadWriteDirection;
|
||||
|
||||
static inline void __dmb_sy(void)
|
||||
{
|
||||
__asm__ __volatile__ ("dmb sy" ::: "memory");
|
||||
|
|
Loading…
Reference in a new issue