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 ;
|
SubDirHdrs $(SUBDIR) $(DOTDOT) generic ;
|
||||||
UsePrivateKernelHeaders ;
|
UsePrivateKernelHeaders ;
|
||||||
|
|
||||||
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) generic ] ;
|
||||||
|
|
||||||
KernelMergeObject kernel_arch_riscv64.o :
|
KernelMergeObject kernel_arch_riscv64.o :
|
||||||
arch_asm.S
|
arch_asm.S
|
||||||
arch_commpage.cpp
|
arch_commpage.cpp
|
||||||
@@ -23,6 +25,9 @@ KernelMergeObject kernel_arch_riscv64.o :
|
|||||||
RISCV64VMTranslationMap.cpp
|
RISCV64VMTranslationMap.cpp
|
||||||
Htif.cpp
|
Htif.cpp
|
||||||
sbi_syscalls.S
|
sbi_syscalls.S
|
||||||
|
|
||||||
|
debug_uart_8250.cpp
|
||||||
|
arch_uart_sifive.cpp
|
||||||
:
|
:
|
||||||
$(TARGET_KERNEL_PIC_CCFLAGS) -Wno-unused
|
$(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