mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-15 09:36:35 +00:00
thermosphere: pl011 uart refactor
This commit is contained in:
parent
018260645a
commit
8dc9be9f8e
10 changed files with 224 additions and 135 deletions
|
@ -145,7 +145,8 @@ ifeq ($(PLATFORM), qemu)
|
||||||
export QEMU := qemu-system-aarch64
|
export QEMU := qemu-system-aarch64
|
||||||
|
|
||||||
QEMUFLAGS := -nographic -machine virt,virtualization=on,accel=tcg,gic-version=2 -cpu cortex-a57 -smp 4 -m 1024\
|
QEMUFLAGS := -nographic -machine virt,virtualization=on,accel=tcg,gic-version=2 -cpu cortex-a57 -smp 4 -m 1024\
|
||||||
-kernel thermosphere.elf -d unimp,guest_errors -semihosting-config enable,target=native -serial mon:stdio
|
-kernel thermosphere.elf -d unimp,guest_errors -semihosting-config enable,target=native\
|
||||||
|
-chardev stdio,id=uart -serial chardev:uart -monitor none
|
||||||
|
|
||||||
qemu: all
|
qemu: all
|
||||||
@$(QEMU) $(QEMUFLAGS)
|
@$(QEMU) $(QEMUFLAGS)
|
||||||
|
|
|
@ -37,7 +37,7 @@ int debugLog(const char *fmt, ...)
|
||||||
if (DLOG_USE_SEMIHOSTING_WRITE0 && semihosting_connection_supported()) {
|
if (DLOG_USE_SEMIHOSTING_WRITE0 && semihosting_connection_supported()) {
|
||||||
semihosting_write_string(buf);
|
semihosting_write_string(buf);
|
||||||
} else {
|
} else {
|
||||||
uartWriteData(buf, (size_t)res);
|
uartWriteData(DEFAULT_UART, buf, (size_t)res);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -98,7 +98,7 @@ static void initGic(void)
|
||||||
currentCoreCtx->gicInterfaceMask = gicd->itargetsr[0];
|
currentCoreCtx->gicInterfaceMask = gicd->itargetsr[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void configureInterrupt(u16 id, u8 prio, bool isLevelSensitive)
|
void configureInterrupt(u16 id, u8 prio, bool isLevelSensitive)
|
||||||
{
|
{
|
||||||
volatile ArmGicV2Distributor *gicd = g_irqManager.gic.gicd;
|
volatile ArmGicV2Distributor *gicd = g_irqManager.gic.gicd;
|
||||||
gicd->icenabler[id / 32] = BIT(id % 32);
|
gicd->icenabler[id / 32] = BIT(id % 32);
|
||||||
|
@ -129,6 +129,9 @@ void initIrq(void)
|
||||||
|
|
||||||
configureInterrupt(GIC_IRQID_MAINTENANCE, IRQ_PRIORITY_HOST, true);
|
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);
|
recursiveSpinlockUnlockRestoreIrq(&g_irqManager.lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +162,7 @@ void handleIrqException(ExceptionStackFrame *frame, bool isLowerEl, bool isA32)
|
||||||
u32 irqId = iar & 0x3FF;
|
u32 irqId = iar & 0x3FF;
|
||||||
u32 srcCore = (iar >> 10) & 7;
|
u32 srcCore = (iar >> 10) & 7;
|
||||||
|
|
||||||
//DEBUG("EL2 [core %d]: Received irq %x\n", (int)currentCoreCtx->coreId, irqId);
|
DEBUG("EL2 [core %d]: Received irq %x\n", (int)currentCoreCtx->coreId, irqId);
|
||||||
|
|
||||||
if (irqId == GIC_IRQID_SPURIOUS) {
|
if (irqId == GIC_IRQID_SPURIOUS) {
|
||||||
// Spurious interrupt received
|
// Spurious interrupt received
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "platform/interrupt_config.h"
|
#include "platform/interrupt_config.h"
|
||||||
|
#include "platform/uart.h"
|
||||||
|
|
||||||
#define IRQ_PRIORITY_HOST 0
|
#define IRQ_PRIORITY_HOST 0
|
||||||
#define IRQ_PRIORITY_GUEST 1
|
#define IRQ_PRIORITY_GUEST 1
|
||||||
|
@ -49,6 +50,7 @@ extern IrqManager g_irqManager;
|
||||||
|
|
||||||
void initIrq(void);
|
void initIrq(void);
|
||||||
void handleIrqException(ExceptionStackFrame *frame, bool isLowerEl, bool isA32);
|
void handleIrqException(ExceptionStackFrame *frame, bool isLowerEl, bool isA32);
|
||||||
|
void configureInterrupt(u16 id, u8 prio, bool isLevelSensitive);
|
||||||
|
|
||||||
static inline void generateSgiForAllOthers(ThermosphereSgi id)
|
static inline void generateSgiForAllOthers(ThermosphereSgi id)
|
||||||
{
|
{
|
||||||
|
@ -78,6 +80,7 @@ static inline bool irqIsGuest(u16 id)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ret = id != GIC_IRQID_MAINTENANCE && id != GIC_IRQID_NS_PHYS_HYP_TIMER;
|
bool ret = id != GIC_IRQID_MAINTENANCE && id != GIC_IRQID_NS_PHYS_HYP_TIMER;
|
||||||
|
ret = ret && id != uartGetIrqId(DEFAULT_UART); // FIXME
|
||||||
#if GIC_IRQID_NS_VIRT_HYP_TIMER != GIC_IRQID_SPURIOUS
|
#if GIC_IRQID_NS_VIRT_HYP_TIMER != GIC_IRQID_SPURIOUS
|
||||||
ret = ret && id != GIC_IRQID_NS_VIRT_HYP_TIMER;
|
ret = ret && id != GIC_IRQID_NS_VIRT_HYP_TIMER;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -45,7 +45,8 @@ void thermosphereMain(ExceptionStackFrame *frame)
|
||||||
initIrq();
|
initIrq();
|
||||||
|
|
||||||
if (currentCoreCtx->isBootCore) {
|
if (currentCoreCtx->isBootCore) {
|
||||||
uartInit(115200);
|
uartInit(DEFAULT_UART, 115200, 0);
|
||||||
|
uartSetInterruptStatus(DEFAULT_UART, false, false);
|
||||||
DEBUG("EL2: core %u reached main first!\n", currentCoreCtx->coreId);
|
DEBUG("EL2: core %u reached main first!\n", currentCoreCtx->coreId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
#define GIC_IRQID_SEC_PHYS_HYP_TIMER GIC_IRQID_SPURIOUS // SBSA: 20. 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_SEC_VIRT_HYP_TIMER GIC_IRQID_SPURIOUS // SBSA: 19. Unimplemented
|
||||||
|
|
||||||
|
#define GIC_IRQID_UART 33
|
||||||
|
|
||||||
static inline void initGicV2Pointers(ArmGicV2 *gic)
|
static inline void initGicV2Pointers(ArmGicV2 *gic)
|
||||||
{
|
{
|
||||||
gic->gicd = (volatile ArmGicV2Distributor *)0x08000000ull;
|
gic->gicd = (volatile ArmGicV2Distributor *)0x08000000ull;
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
#include "../../utils.h"
|
#include "../../irq.h"
|
||||||
|
|
||||||
// Adapted from ARM TF asm code
|
// Adapted from TF asm code
|
||||||
// AMBA PL101 driver
|
// AMBA PL101 driver
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -28,52 +28,116 @@
|
||||||
|
|
||||||
//115200
|
//115200
|
||||||
|
|
||||||
void uartInit(u32 baudRate)
|
static inline volatile PL011UartRegisters *uartGetRegisters(UartDevice dev)
|
||||||
{
|
{
|
||||||
// First, disable UART
|
switch (dev) {
|
||||||
g_uartRegs->CR &= ~PL011_UARTCR_UARTEN;
|
case UART_A:
|
||||||
|
return (volatile PL011UartRegisters *)0x09000000;
|
||||||
// Set baudrate, Divisor = (Uart clock * 4) / baudrate; stored in IBRD|FBRD
|
default:
|
||||||
u32 divisor = (4 * UART0_CLK_IN_HZ) / baudRate;
|
return NULL;
|
||||||
g_uartRegs->IBRD = divisor >> 6;
|
|
||||||
g_uartRegs->FBRD = divisor & 0x3F;
|
|
||||||
g_uartRegs->LCR_H = PL011_LINE_CONTROL;
|
|
||||||
|
|
||||||
// Clear any pending errors
|
|
||||||
g_uartRegs->ECR = 0;
|
|
||||||
|
|
||||||
// Enable tx, rx, and uart overall
|
|
||||||
g_uartRegs->CR = PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
void uartWriteData(const void *buffer, size_t size)
|
|
||||||
{
|
|
||||||
const u8 *buf8 = (const u8 *)buffer;
|
|
||||||
for (size_t i = 0; i < size; i++) {
|
|
||||||
while (g_uartRegs->FR & PL011_UARTFR_TXFF); // while TX FIFO full
|
|
||||||
g_uartRegs->DR = buf8[i];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void uartReadData(void *buffer, size_t size)
|
void uartInit(UartDevice dev, u32 baudRate, u32 flags)
|
||||||
{
|
{
|
||||||
|
/* The TRM (DDI0183) reads:
|
||||||
|
Program the control registers as follows:
|
||||||
|
1. Disable the UART.
|
||||||
|
2. Wait for the end of transmission or reception of the current character.
|
||||||
|
3. Flush the transmit FIFO by disabling bit 4 (FEN) in the line control register
|
||||||
|
(UARTCLR_H).
|
||||||
|
4. Reprogram the control register.
|
||||||
|
5. Enable the UART.
|
||||||
|
*/
|
||||||
|
(void)flags;
|
||||||
|
volatile PL011UartRegisters *uart = uartGetRegisters(dev);
|
||||||
|
|
||||||
|
// First, disable the UART. Flush the receive FIFO, wait for tx to complete, and disable both FIFOs.
|
||||||
|
uart->cr &= ~PL011_UARTCR_UARTEN;
|
||||||
|
while (!(uart->fr & PL011_UARTFR_RXFE)) {
|
||||||
|
uart->dr;
|
||||||
|
}
|
||||||
|
while (uart->fr & PL011_UARTFR_BUSY);
|
||||||
|
// This flushes the transmit FIFO:
|
||||||
|
uart->lcr_h &= ~PL011_UARTLCR_H_FEN;
|
||||||
|
|
||||||
|
// Set baudrate, Divisor = (Uart clock * 4) / baudrate; stored in IBRD|FBRD
|
||||||
|
u32 divisor = (4 * UART_CLK_IN_HZ) / baudRate;
|
||||||
|
uart->ibrd = divisor >> 6;
|
||||||
|
uart->fbrd = divisor & 0x3F;
|
||||||
|
|
||||||
|
// Select FIFO fill levels for interrupts
|
||||||
|
uart->ifls = PL011_IFLS_RX4_8 | PL011_IFLS_TX4_8;
|
||||||
|
|
||||||
|
// FIFO Enabled / No Parity / 8 Data bit / One Stop Bit
|
||||||
|
uart->lcr_h = PL011_UARTLCR_H_FEN | PL011_UARTLCR_H_WLEN_8;
|
||||||
|
|
||||||
|
// Select the interrupts we want to have
|
||||||
|
// RX timeout and TX/RX fill interrupts
|
||||||
|
uart->imsc = PL011_RTI | PL011_RXI | PL011_RXI;
|
||||||
|
|
||||||
|
// Clear any pending errors
|
||||||
|
uart->ecr = 0;
|
||||||
|
|
||||||
|
// Clear all interrupts
|
||||||
|
uart->icr = PL011_ALL_INTERRUPTS;
|
||||||
|
|
||||||
|
// Register the interrupt ID
|
||||||
|
//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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void uartWriteData(UartDevice dev, const void *buffer, size_t size)
|
||||||
|
{
|
||||||
|
volatile PL011UartRegisters *uart = uartGetRegisters(dev);
|
||||||
|
|
||||||
|
const u8 *buf8 = (const u8 *)buffer;
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
while (uart->fr & PL011_UARTFR_TXFF); // while TX FIFO full
|
||||||
|
uart->dr = buf8[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void uartReadData(UartDevice dev, void *buffer, size_t size)
|
||||||
|
{
|
||||||
|
volatile PL011UartRegisters *uart = uartGetRegisters(dev);
|
||||||
|
|
||||||
u8 *buf8 = (u8 *)buffer;
|
u8 *buf8 = (u8 *)buffer;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < size; i++) {
|
for (i = 0; i < size; i++) {
|
||||||
while (g_uartRegs->FR & PL011_UARTFR_RXFE);
|
while (uart->fr & PL011_UARTFR_RXFE);
|
||||||
buf8[i] = g_uartRegs->DR;
|
buf8[i] = uart->dr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t uartReadDataMax(void *buffer, size_t maxSize)
|
size_t uartReadDataMax(UartDevice dev, void *buffer, size_t maxSize)
|
||||||
{
|
{
|
||||||
|
volatile PL011UartRegisters *uart = uartGetRegisters(dev);
|
||||||
|
|
||||||
u8 *buf8 = (u8 *)buffer;
|
u8 *buf8 = (u8 *)buffer;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < maxSize && !(g_uartRegs->FR & PL011_UARTFR_RXFE); i++) {
|
for (i = 0; i < maxSize && !(uart->fr & PL011_UARTFR_RXFE); i++) {
|
||||||
buf8[i] = g_uartRegs->DR;
|
buf8[i] = uart->dr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1 + i;
|
return 1 + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void uartSetInterruptStatus(UartDevice dev, bool read, bool enable)
|
||||||
|
{
|
||||||
|
volatile PL011UartRegisters *uart = uartGetRegisters(dev);
|
||||||
|
|
||||||
|
u32 mask = read ? PL011_RTI | PL011_RXI : PL011_RTI;
|
||||||
|
if (enable) {
|
||||||
|
uart->imsc |= mask;
|
||||||
|
} else {
|
||||||
|
uart->icr = mask;
|
||||||
|
uart->imsc &= ~mask;
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,120 +16,130 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../../types.h"
|
#include "../../utils.h"
|
||||||
|
#include "interrupt_config.h"
|
||||||
|
|
||||||
// AMBA PL011 driver
|
// AMBA PL011 driver
|
||||||
|
// Originally from
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
* Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if 0
|
typedef enum UartDevice {
|
||||||
/* PL011 Registers */
|
UART_A = 0,
|
||||||
#define UARTDR 0x000
|
|
||||||
#define UARTRSR 0x004
|
|
||||||
#define UARTECR 0x004
|
|
||||||
#define UARTFR 0x018
|
|
||||||
#define UARTIMSC 0x038
|
|
||||||
#define UARTRIS 0x03C
|
|
||||||
#define UARTICR 0x044
|
|
||||||
|
|
||||||
/* PL011 registers (out of the SBSA specification) */
|
UART_MAX,
|
||||||
#if !PL011_GENERIC_UART
|
} UartDevice;
|
||||||
#define UARTILPR 0x020
|
|
||||||
#define UARTIBRD 0x024
|
|
||||||
#define UARTFBRD 0x028
|
|
||||||
#define UARTLCR_H 0x02C
|
|
||||||
#define UARTCR 0x030
|
|
||||||
#define UARTIFLS 0x034
|
|
||||||
#define UARTMIS 0x040
|
|
||||||
#define UARTDMACR 0x048
|
|
||||||
#endif /* !PL011_GENERIC_UART */
|
|
||||||
|
|
||||||
#endif
|
|
||||||
typedef struct PL011UartRegisters {
|
typedef struct PL011UartRegisters {
|
||||||
u32 DR;
|
u32 dr;
|
||||||
union {
|
union {
|
||||||
u32 SR;
|
u32 sr;
|
||||||
u32 ECR;
|
u32 ecr;
|
||||||
};
|
};
|
||||||
u32 _0x08, _0x0C, _0x10, _0x14;
|
u32 _0x08, _0x0C, _0x10, _0x14;
|
||||||
u32 FR;
|
u32 fr;
|
||||||
u32 _0x1C;
|
u32 _0x1C;
|
||||||
u32 ILPR;
|
u32 ilpr;
|
||||||
u32 IBRD;
|
u32 ibrd;
|
||||||
u32 FBRD;
|
u32 fbrd;
|
||||||
u32 LCR_H;
|
u32 lcr_h;
|
||||||
u32 CR;
|
u32 cr;
|
||||||
u32 IFLS;
|
u32 ifls;
|
||||||
u32 IMSC;
|
u32 imsc;
|
||||||
u32 TRIS;
|
u32 ris;
|
||||||
u32 TMIS;
|
u32 mis;
|
||||||
u32 TICR;
|
u32 icr;
|
||||||
u32 TDMACR;
|
u32 dmacr;
|
||||||
} PL011UartRegisters;
|
} PL011UartRegisters;
|
||||||
|
|
||||||
/* Data status bits */
|
// Data status bits
|
||||||
#define UART_DATA_ERROR_MASK 0x0F00
|
#define UART_DATA_ERROR_MASK 0x0F00
|
||||||
|
|
||||||
/* Status reg bits */
|
// Status reg bits
|
||||||
#define UART_STATUS_ERROR_MASK 0x0F
|
#define UART_STATUS_ERROR_MASK 0x0F
|
||||||
|
|
||||||
/* Flag reg bits */
|
// Errors
|
||||||
#define PL011_UARTFR_RI (1 << 8) /* Ring indicator */
|
#define PL011_OE BIT(3) // Overrun error
|
||||||
#define PL011_UARTFR_TXFE (1 << 7) /* Transmit FIFO empty */
|
#define PL011_BE BIT(2) // Break error
|
||||||
#define PL011_UARTFR_RXFF (1 << 6) /* Receive FIFO full */
|
#define PL011_PE BIT(1) // Parity error
|
||||||
#define PL011_UARTFR_TXFF (1 << 5) /* Transmit FIFO full */
|
#define PL011_FE BIT(0) // Framing error
|
||||||
#define PL011_UARTFR_RXFE (1 << 4) /* Receive FIFO empty */
|
|
||||||
#define PL011_UARTFR_BUSY (1 << 3) /* UART busy */
|
|
||||||
#define PL011_UARTFR_DCD (1 << 2) /* Data carrier detect */
|
|
||||||
#define PL011_UARTFR_DSR (1 << 1) /* Data set ready */
|
|
||||||
#define PL011_UARTFR_CTS (1 << 0) /* Clear to send */
|
|
||||||
|
|
||||||
#define PL011_UARTFR_TXFF_BIT 5 /* Transmit FIFO full bit in UARTFR register */
|
// Interrupts
|
||||||
#define PL011_UARTFR_RXFE_BIT 4 /* Receive FIFO empty bit in UARTFR register */
|
#define PL011_OEI BIT(10) // Overrun error interrupt
|
||||||
#define PL011_UARTFR_BUSY_BIT 3 /* UART busy bit in UARTFR register */
|
#define PL011_BEI BIT(9) // Break error interrupt
|
||||||
|
#define PL011_PEI BIT(8) // Parity error interrupt
|
||||||
|
#define PL011_FEI BIT(7) // Framing error interrupt
|
||||||
|
#define PL011_RTI BIT(6) // Receive timeout interrupt
|
||||||
|
#define PL011_TXI BIT(5) // Transmit interrupt
|
||||||
|
#define PL011_RXI BIT(4) // Receive interrupt
|
||||||
|
#define PL011_DSRMI BIT(3) // DSR modem interrupt
|
||||||
|
#define PL011_DCDMI BIT(2) // DCD modem interrupt
|
||||||
|
#define PL011_CTSMI BIT(1) // CTS modem interrupt
|
||||||
|
#define PL011_RIMI BIT(0) // RI modem interrupt
|
||||||
|
#define PL011_ALL_INTERRUPTS MASK(11)
|
||||||
|
|
||||||
/* Control reg bits */
|
// Flag reg bits
|
||||||
#if !PL011_GENERIC_UART
|
#define PL011_UARTFR_RI BIT(8) // Ring indicator
|
||||||
#define PL011_UARTCR_CTSEN (1 << 15) /* CTS hardware flow control enable */
|
#define PL011_UARTFR_TXFE BIT(7) // Transmit FIFO empty
|
||||||
#define PL011_UARTCR_RTSEN (1 << 14) /* RTS hardware flow control enable */
|
#define PL011_UARTFR_RXFF BIT(6) // Receive FIFO full
|
||||||
#define PL011_UARTCR_RTS (1 << 11) /* Request to send */
|
#define PL011_UARTFR_TXFF BIT(5) // Transmit FIFO full
|
||||||
#define PL011_UARTCR_DTR (1 << 10) /* Data transmit ready. */
|
#define PL011_UARTFR_RXFE BIT(4) // Receive FIFO empty
|
||||||
#define PL011_UARTCR_RXE (1 << 9) /* Receive enable */
|
#define PL011_UARTFR_BUSY BIT(3) // UART busy
|
||||||
#define PL011_UARTCR_TXE (1 << 8) /* Transmit enable */
|
#define PL011_UARTFR_DCD BIT(2) // Data carrier detect
|
||||||
#define PL011_UARTCR_LBE (1 << 7) /* Loopback enable */
|
#define PL011_UARTFR_DSR BIT(1) // Data set ready
|
||||||
#define PL011_UARTCR_UARTEN (1 << 0) /* UART Enable */
|
#define PL011_UARTFR_CTS BIT(0) // Clear to send
|
||||||
|
|
||||||
#if !defined(PL011_LINE_CONTROL)
|
// Control reg bits
|
||||||
/* FIFO Enabled / No Parity / 8 Data bit / One Stop Bit */
|
#define PL011_UARTCR_CTSEN BIT(15) // CTS hardware flow control enable
|
||||||
#define PL011_LINE_CONTROL (PL011_UARTLCR_H_FEN | PL011_UARTLCR_H_WLEN_8)
|
#define PL011_UARTCR_RTSEN BIT(14) // RTS hardware flow control enable
|
||||||
#endif
|
#define PL011_UARTCR_RTS BIT(11) // Request to send
|
||||||
|
#define PL011_UARTCR_DTR BIT(10) // Data transmit ready.
|
||||||
|
#define PL011_UARTCR_RXE BIT(9) // Receive enable
|
||||||
|
#define PL011_UARTCR_TXE BIT(8) // Transmit enable
|
||||||
|
#define PL011_UARTCR_LBE BIT(7) // Loopback enable
|
||||||
|
#define PL011_UARTCR_UARTEN BIT(0) // UART Enable
|
||||||
|
|
||||||
/* Line Control Register Bits */
|
// Line Control Register Bits
|
||||||
#define PL011_UARTLCR_H_SPS (1 << 7) /* Stick parity select */
|
#define PL011_UARTLCR_H_SPS BIT(7) // Stick parity select
|
||||||
#define PL011_UARTLCR_H_WLEN_8 (3 << 5)
|
#define PL011_UARTLCR_H_WLEN_8 (3 << 5)
|
||||||
#define PL011_UARTLCR_H_WLEN_7 (2 << 5)
|
#define PL011_UARTLCR_H_WLEN_7 (2 << 5)
|
||||||
#define PL011_UARTLCR_H_WLEN_6 (1 << 5)
|
#define PL011_UARTLCR_H_WLEN_6 BIT(5)
|
||||||
#define PL011_UARTLCR_H_WLEN_5 (0 << 5)
|
#define PL011_UARTLCR_H_WLEN_5 (0 << 5)
|
||||||
#define PL011_UARTLCR_H_FEN (1 << 4) /* FIFOs Enable */
|
#define PL011_UARTLCR_H_FEN BIT(4) // FIFOs Enable
|
||||||
#define PL011_UARTLCR_H_STP2 (1 << 3) /* Two stop bits select */
|
#define PL011_UARTLCR_H_STP2 BIT(3) // Two stop bits select
|
||||||
#define PL011_UARTLCR_H_EPS (1 << 2) /* Even parity select */
|
#define PL011_UARTLCR_H_EPS BIT(2) // Even parity select
|
||||||
#define PL011_UARTLCR_H_PEN (1 << 1) /* Parity Enable */
|
#define PL011_UARTLCR_H_PEN BIT(1) // Parity Enable
|
||||||
#define PL011_UARTLCR_H_BRK (1 << 0) /* Send break */
|
#define PL011_UARTLCR_H_BRK BIT(0) // Send break
|
||||||
|
|
||||||
#endif /* !PL011_GENERIC_UART */
|
// FIFO level select register
|
||||||
|
#define PL011_IFLS_RX1_8 (0 << 3)
|
||||||
|
#define PL011_IFLS_RX2_8 (1 << 3)
|
||||||
|
#define PL011_IFLS_RX4_8 (2 << 3)
|
||||||
|
#define PL011_IFLS_RX6_8 (3 << 3)
|
||||||
|
#define PL011_IFLS_RX7_8 (4 << 3)
|
||||||
|
#define PL011_IFLS_TX1_8 (0 << 0)
|
||||||
|
#define PL011_IFLS_TX2_8 (1 << 0)
|
||||||
|
#define PL011_IFLS_TX4_8 (2 << 0)
|
||||||
|
#define PL011_IFLS_TX6_8 (3 << 0)
|
||||||
|
#define PL011_IFLS_TX7_8 (4 << 0)
|
||||||
|
|
||||||
#define UART0_BASE 0x09000000
|
#define UART_CLK_IN_HZ 1
|
||||||
#define UART1_BASE 0x09040000
|
|
||||||
#define UART0_CLK_IN_HZ 1
|
|
||||||
#define UART1_CLK_IN_HZ 1
|
|
||||||
|
|
||||||
static volatile PL011UartRegisters *const g_uartRegs = (volatile PL011UartRegisters *)UART0_BASE;
|
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);
|
||||||
|
|
||||||
void uartInit(u32 baudRate);
|
static inline u16 uartGetIrqId(UartDevice dev)
|
||||||
void uartWriteData(const void *buffer, size_t size);
|
{
|
||||||
void uartReadData(void *buffer, size_t size);
|
switch (dev) {
|
||||||
size_t uartReadDataMax(void *buffer, size_t maxSize);
|
case UART_A:
|
||||||
|
return GIC_IRQID_UART;
|
||||||
|
default:
|
||||||
|
return GIC_IRQID_SPURIOUS;
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,8 +16,10 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef PLATFORM_TEGRA
|
#if PLATFORM_TEGRA
|
||||||
#include "tegra/uart.h"
|
// TODO
|
||||||
|
|
||||||
|
/*#include "tegra/uart.h"
|
||||||
|
|
||||||
#define DEFAULT_UART UART_C
|
#define DEFAULT_UART UART_C
|
||||||
#define DEFAULT_UARTINV_STATUS true
|
#define DEFAULT_UARTINV_STATUS true
|
||||||
|
@ -42,9 +44,12 @@ static inline size_t uartReadDataMax(void *buffer, size_t maxSize)
|
||||||
{
|
{
|
||||||
return uart_recv_max(DEFAULT_UART, buffer, maxSize);
|
return uart_recv_max(DEFAULT_UART, buffer, maxSize);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
#elif defined(PLATFORM_QEMU)
|
#elif defined(PLATFORM_QEMU)
|
||||||
|
|
||||||
|
#define DEFAULT_UART UART_A
|
||||||
|
|
||||||
#include "qemu/uart.h"
|
#include "qemu/uart.h"
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -25,13 +25,13 @@
|
||||||
|
|
||||||
// All generic timers possibly defined in the Arm architecture:
|
// All generic timers possibly defined in the Arm architecture:
|
||||||
// (suffix, time source suffix, level, irqid)
|
// (suffix, time source suffix, level, irqid)
|
||||||
#define NS_PHYS_TIMER (p, p, 0, GIC_IRQID_NS_PHYS_TIMER)
|
#define NS_PHYS_TIMER (p, p, 0, GIC_IRQID_NS_PHYS_TIMER)
|
||||||
#define NS_VIRT_TIMER (v, v, 0, GIC_IRQID_NS_VIRT_TIMER)
|
#define NS_VIRT_TIMER (v, v, 0, GIC_IRQID_NS_VIRT_TIMER)
|
||||||
#define NS_PHYS_HYP_TIMER (hp, p, 2, GIC_IRQID_NS_PHYS_HYP_TIMER)
|
#define NS_PHYS_HYP_TIMER (hp, p, 2, GIC_IRQID_NS_PHYS_HYP_TIMER)
|
||||||
#define NS_VIRT_HYP_TIMER (hv, v, 2, GIC_IRQID_NS_VIRT_HYP_TIMER)
|
#define NS_VIRT_HYP_TIMER (hv, v, 2, GIC_IRQID_NS_VIRT_HYP_TIMER)
|
||||||
#define SEC_PHYS_TIMER (ps, p, 1, GIC_IRQID_SEC_PHYS_TIMER)
|
#define SEC_PHYS_TIMER (ps, p, 1, GIC_IRQID_SEC_PHYS_TIMER)
|
||||||
#define SEC_PHYS_HYP_TIMER (hps, p, 2, GIC_IRQID_SEC_PHYS_HYP_TIMER)
|
#define SEC_PHYS_HYP_TIMER (hps, p, 2, GIC_IRQID_SEC_PHYS_HYP_TIMER)
|
||||||
#define SEC_VIRT_HYP_TIMER (hvs, v, 2, GIC_IRQID_SEC_VIRT_HYP_TIMER)
|
#define SEC_VIRT_HYP_TIMER (hvs, v, 2, GIC_IRQID_SEC_VIRT_HYP_TIMER)
|
||||||
|
|
||||||
#define TIMER_IRQID_FIELDS(ign, ign2, ign3, id) id
|
#define TIMER_IRQID_FIELDS(ign, ign2, ign3, id) id
|
||||||
#define TIMER_COUNTER_REG_FIELDS(ign, ts, ign2, ign3) cnt##ts##ct_el0
|
#define TIMER_COUNTER_REG_FIELDS(ign, ts, ign2, ign3) cnt##ts##ct_el0
|
||||||
|
|
Loading…
Reference in a new issue