genode/repos/os/src/server/vmm/spec/arm_v8/pl011.h

146 lines
4.0 KiB
C++

/*
* \brief VMM PL011 serial device model
* \author Stefan Kalkowski
* \date 2019-07-18
*/
/*
* Copyright (C) 2019 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _SRC__SERVER__VMM__PL011_H_
#define _SRC__SERVER__VMM__PL011_H_
#include <os/ring_buffer.h>
#include <terminal_session/connection.h>
#include <gic.h>
namespace Vmm {
class Cpu;
class Pl011;
}
class Vmm::Pl011 : public Vmm::Mmio_device
{
private:
using Ring_buffer =
Genode::Ring_buffer<char, 1024,
Genode::Ring_buffer_unsynchronized>;
enum Mask : Genode::uint16_t {
RX_MASK = 1 << 4,
TX_MASK = 1 << 5
};
Terminal::Connection _terminal;
Cpu::Signal_handler<Pl011> _handler;
Gic::Irq & _irq;
Ring_buffer _rx_buf;
Mmio_register _uart_ris { "UARTRIS", Mmio_register::RO,
0x3c, 2 };
/**
* Dummy container for holding array of noncopyable objects
* Workaround for gcc bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70395
*/
struct Dummy {
Mmio_register regs[13];
} _reg_container { .regs = {
{ "UARTIBRD", Mmio_register::RW, 0x24, 2, 0 },
{ "UARTFBRD", Mmio_register::RW, 0x28, 2, 0 },
{ "UARTLCR_H", Mmio_register::RW, 0x2c, 2, 0 },
{ "UARTCR", Mmio_register::RW, 0x30, 2, 0x300 },
{ "UARTIFLS", Mmio_register::RW, 0x34, 2, 0x12 },
{ "UARTPERIPHID0", Mmio_register::RO, 0xfe0, 4, 0x11 },
{ "UARTPERIPHID1", Mmio_register::RO, 0xfe4, 4, 0x10 },
{ "UARTPERIPHID2", Mmio_register::RO, 0xfe8, 4, 0x14 },
{ "UARTPERIPHID3", Mmio_register::RO, 0xfec, 4, 0x0 },
{ "UARTPCELLID0", Mmio_register::RO, 0xff0, 4, 0xd },
{ "UARTPCELLID1", Mmio_register::RO, 0xff4, 4, 0xf0 },
{ "UARTPCELLID2", Mmio_register::RO, 0xff8, 4, 0x5 },
{ "UARTPCELLID3", Mmio_register::RO, 0xffc, 4, 0xb1 }
}};
struct Uartdr : Mmio_register
{
Terminal::Connection & terminal;
Ring_buffer & rx;
Mmio_register & ris;
Register read(Address_range&, Cpu&) override;
void write(Address_range&, Cpu&, Register) override;
Uartdr(Terminal::Connection & terminal,
Ring_buffer & rx,
Mmio_register & ris)
: Mmio_register("UARTDR", Mmio_register::RW, 0x0, 2),
terminal(terminal), rx(rx), ris(ris) {}
} _uart_dr { _terminal, _rx_buf, _uart_ris };
struct Uartfr : Mmio_register, Genode::Register<32>
{
struct Rx_empty : Bitfield<4, 1> {};
struct Rx_full : Bitfield<6, 1> {};
Ring_buffer & rx;
Mmio_register::Register read(Address_range&, Cpu&) override;
Uartfr(Ring_buffer & rx)
: Mmio_register("UARTFR", Mmio_register::RO, 0x18, 4), rx(rx) {}
} _uart_fr { _rx_buf };
struct Uartimsc : Mmio_register
{
Gic::Irq & irq;
Mmio_register & ris;
void write(Address_range&, Cpu&, Register) override;
Uartimsc(Gic::Irq & irq, Mmio_register & ris)
: Mmio_register("UARTIMSC", Mmio_register::RW, 0x38, 2, 0xf),
irq(irq), ris(ris) {}
} _uart_imsc { _irq, _uart_ris };
struct Uartmis : Mmio_register
{
Mmio_register & ris;
Uartimsc & imsc;
Register read(Address_range&, Cpu&) override;
Uartmis(Mmio_register & ris, Uartimsc & imsc)
: Mmio_register("UARTMIS", Mmio_register::RO, 0x40, 2),
ris(ris), imsc(imsc) {}
} _uart_mis { _uart_ris, _uart_imsc };
struct Uarticr : Mmio_register
{
Mmio_register & ris;
void write(Address_range&, Cpu&, Register) override;
Uarticr(Mmio_register & ris)
: Mmio_register("UARTICR", Mmio_register::WO, 0x44, 2), ris(ris) {}
} _uart_icr { _uart_ris };
void _read();
public:
Pl011(const char * const name,
const Genode::uint64_t addr,
const Genode::uint64_t size,
unsigned irq,
Cpu & cpu,
Mmio_bus & bus,
Genode::Env & env);
};
#endif /* _SRC__SERVER__VMM__PL011_H_ */