* Copyright 2022 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Oliver Ruiz Dorantes, oliver.ruiz.dorantes@gmail.com
*/
#include <debug.h>
#include <arch/arm/reg.h>
#include <arch/generic/debug_uart.h>
#include <arch/arm64/arch_uart_linflex.h>
#include <new>
using namespace LINFlexRegisters;
ArchUARTlinflex::ArchUARTlinflex(addr_t base, int64 clock)
:
DebugUART(base, clock)
{
Barrier();
if (LinflexCell()->LINCR1.B.SLEEP == 0) {
if ((LinflexCell()->UARTCR.B.TXEN == 1)
&& (LinflexCell()->UARTCR.B.RXEN == 1)
&& (LinflexCell()->UARTCR.B.UART == 1)) {
} else {
}
}
}
ArchUARTlinflex::~ArchUARTlinflex()
{
}
void
ArchUARTlinflex::Barrier()
{
asm volatile ("" : : : "memory");
}
void
ArchUARTlinflex::InitPort(uint32 baud)
{
uint32 baudDivisor = Clock() / (16 * baud);
uint32 remainder = Clock() % (16 * baud);
uint32 baudFractional = ((8 * remainder) / baud >> 1)
+ ((8 * remainder) / baud & 1);
Disable();
Enable();
}
void
ArchUARTlinflex::InitEarly()
{
}
void
ArchUARTlinflex::Enable()
{
DebugUART::Enable();
}
void
ArchUARTlinflex::Disable()
{
DebugUART::Disable();
}
int
ArchUARTlinflex::PutChar(char c)
{
if (Enabled() == true) {
bool fifo = LinflexCell()->UARTCR.B.TFBM == 1;
if (fifo) {
while (LinflexCell()->UARTSR.B.DTF == 1) {
Barrier();
}
}
Out<uint8, vuint32>(&LinflexCell()->BDRL.R, c);
if (!fifo) {
while (LinflexCell()->UARTSR.B.DTF == 0) {
Barrier();
}
auto uartsr = BitfieldRegister<UARTSR_register>();
uartsr.B.DTF = 1;
LinflexCell()->UARTSR.R = uartsr.R;
}
return 0;
}
return -1;
}
int
ArchUARTlinflex::GetChar(bool wait)
{
int character;
if (Enabled() == true) {
bool fifo = LinflexCell()->UARTCR.B.RFBM == 1;
if (fifo) {
if (wait) {
while (LinflexCell()->UARTSR.B.DRF == 1) {
Barrier();
}
} else {
if (LinflexCell()->UARTSR.B.DRF == 1)
return -1;
}
} else {
if (wait) {
while (LinflexCell()->UARTSR.B.DRF == 0) {
Barrier();
}
} else {
if (LinflexCell()->UARTSR.B.DRF == 0)
return -1;
}
}
character = In<uint8, vuint32>(&LinflexCell()->BDRM.R);
auto uartsr = BitfieldRegister<UARTSR_register>();
uartsr.B.RMB = 1;
uartsr.B.DRF = 1;
LinflexCell()->UARTSR.R = uartsr.R;
return character;
}
return -1;
}
void
ArchUARTlinflex::FlushTx()
{
}
void
ArchUARTlinflex::FlushRx()
{
}
ArchUARTlinflex*
arch_get_uart_linflex(addr_t base, int64 clock)
{
static char buffer[sizeof(ArchUARTlinflex)];
ArchUARTlinflex *uart = new(buffer) ArchUARTlinflex(base, clock);
return uart;
}