kernel: add SiFive UART driver for riscv64
Change-Id: I37a909b5bcdb18b3fa062961eca9ff2f5187867c Reviewed-on: https://review.haiku-os.org/c/haiku/+/4305 Reviewed-by: Alex von Gluck IV <[email protected]>
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2021, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef _ARCH_UART_SIFIVE_H_
|
||||
#define _ARCH_UART_SIFIVE_H_
|
||||
|
||||
|
||||
#include <arch/generic/debug_uart.h>
|
||||
|
||||
|
||||
// UARTSifiveRegs.ie, ip
|
||||
enum {
|
||||
kUartSifiveTxwm = 1 << 0,
|
||||
kUartSifiveRxwm = 1 << 1,
|
||||
};
|
||||
|
||||
|
||||
struct UARTSifiveRegs {
|
||||
union Txdata {
|
||||
struct {
|
||||
uint32 data: 8;
|
||||
uint32 reserved: 23;
|
||||
uint32 isFull: 1;
|
||||
};
|
||||
uint32 val;
|
||||
} txdata;
|
||||
|
||||
union Rxdata {
|
||||
struct {
|
||||
uint32 data: 8;
|
||||
uint32 reserved: 23;
|
||||
uint32 isEmpty: 1;
|
||||
};
|
||||
uint32 val;
|
||||
} rxdata;
|
||||
|
||||
union Txctrl {
|
||||
struct {
|
||||
uint32 enable: 1;
|
||||
uint32 nstop: 1;
|
||||
uint32 reserved1: 14;
|
||||
uint32 cnt: 3;
|
||||
uint32 reserved2: 13;
|
||||
};
|
||||
uint32 val;
|
||||
} txctrl;
|
||||
|
||||
union Rxctrl {
|
||||
struct {
|
||||
uint32 enable: 1;
|
||||
uint32 reserved1: 15;
|
||||
uint32 cnt: 3;
|
||||
uint32 reserved2: 13;
|
||||
};
|
||||
uint32 val;
|
||||
} rxctrl;
|
||||
|
||||
uint32 ie; // interrupt enable
|
||||
uint32 ip; // interrupt pending
|
||||
uint32 div;
|
||||
uint32 unused;
|
||||
};
|
||||
|
||||
|
||||
class ArchUARTSifive : public DebugUART {
|
||||
public:
|
||||
ArchUARTSifive(addr_t base, int64 clock);
|
||||
~ArchUARTSifive();
|
||||
|
||||
virtual void InitEarly();
|
||||
virtual void Init();
|
||||
virtual void InitPort(uint32 baud);
|
||||
|
||||
virtual void Enable();
|
||||
virtual void Disable();
|
||||
|
||||
virtual int PutChar(char ch);
|
||||
virtual int GetChar(bool wait);
|
||||
|
||||
virtual void FlushTx();
|
||||
virtual void FlushRx();
|
||||
|
||||
protected:
|
||||
virtual void Barrier();
|
||||
|
||||
inline volatile UARTSifiveRegs*
|
||||
Regs();
|
||||
};
|
||||
|
||||
|
||||
volatile UARTSifiveRegs*
|
||||
ArchUARTSifive::Regs()
|
||||
{
|
||||
return (volatile UARTSifiveRegs*)Base();
|
||||
}
|
||||
|
||||
|
||||
#endif // _ARCH_UART_SIFIVE_H_
|
||||
@@ -3,6 +3,8 @@ SubDir HAIKU_TOP src system kernel arch riscv64 ;
|
||||
SubDirHdrs $(SUBDIR) $(DOTDOT) generic ;
|
||||
UsePrivateKernelHeaders ;
|
||||
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) generic ] ;
|
||||
|
||||
KernelMergeObject kernel_arch_riscv64.o :
|
||||
arch_asm.S
|
||||
arch_commpage.cpp
|
||||
@@ -23,6 +25,9 @@ KernelMergeObject kernel_arch_riscv64.o :
|
||||
RISCV64VMTranslationMap.cpp
|
||||
Htif.cpp
|
||||
sbi_syscalls.S
|
||||
|
||||
debug_uart_8250.cpp
|
||||
arch_uart_sifive.cpp
|
||||
:
|
||||
$(TARGET_KERNEL_PIC_CCFLAGS) -Wno-unused
|
||||
:
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright 2021, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <arch/riscv64/arch_uart_sifive.h>
|
||||
|
||||
|
||||
ArchUARTSifive::ArchUARTSifive(addr_t base, int64 clock)
|
||||
:
|
||||
DebugUART(base, clock)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ArchUARTSifive::~ArchUARTSifive()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ArchUARTSifive::InitEarly()
|
||||
{
|
||||
//Regs()->ie = 0;
|
||||
//Enable();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ArchUARTSifive::Init()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ArchUARTSifive::InitPort(uint32 baud)
|
||||
{
|
||||
uint64 quotient = (Clock() + baud - 1) / baud;
|
||||
|
||||
if (quotient == 0)
|
||||
Regs()->div = 0;
|
||||
else
|
||||
Regs()->div = (uint32)(quotient - 1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ArchUARTSifive::Enable()
|
||||
{
|
||||
//Regs()->txctrl.enable = 1;
|
||||
//Regs()->rxctrl.enable = 1;
|
||||
DebugUART::Enable();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ArchUARTSifive::Disable()
|
||||
{
|
||||
//Regs()->txctrl.enable = 0;
|
||||
//Regs()->rxctrl.enable = 0;
|
||||
DebugUART::Disable();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ArchUARTSifive::PutChar(char ch)
|
||||
{
|
||||
// TODO: Needs to be more atomic?
|
||||
// Character drop will happen if there is one space left
|
||||
// in the FIFO and two harts race. atomic_fetch_or of
|
||||
// register, retrying if isFull.
|
||||
while (Regs()->txdata.isFull) {}
|
||||
Regs()->txdata.val = ch;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ArchUARTSifive::GetChar(bool wait)
|
||||
{
|
||||
UARTSifiveRegs::Rxdata data;
|
||||
do {
|
||||
data = { .val = Regs()->rxdata.val };
|
||||
} while (!wait || data.isEmpty);
|
||||
|
||||
return data.isEmpty ? -1 : data.data;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ArchUARTSifive::FlushTx()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ArchUARTSifive::FlushRx()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ArchUARTSifive::Barrier()
|
||||
{
|
||||
asm volatile ("" : : : "memory");
|
||||
}
|
||||
Reference in New Issue
Block a user