mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-07 19:34:56 +00:00
uart_drv: enable RX channel for exynos5 driver
This is useful for automated tests on this platform, where the run script wants to interact with some component via terminal Ref #1405
This commit is contained in:
parent
1e3c80ff5b
commit
e7dad39016
@ -24,145 +24,181 @@ namespace Genode
|
||||
*/
|
||||
class Exynos_uart_base : Mmio
|
||||
{
|
||||
/**
|
||||
* Line control
|
||||
*/
|
||||
struct Ulcon : Register<0x0, 32>
|
||||
{
|
||||
struct Word_length : Bitfield<0, 2> { enum { _8_BIT = 3 }; };
|
||||
struct Stop_bits : Bitfield<2, 1> { enum { _1_BIT = 0 }; };
|
||||
struct Parity_mode : Bitfield<3, 3> { enum { NONE = 0 }; };
|
||||
struct Infrared_mode : Bitfield<6, 1> { };
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Initialization value
|
||||
* Line control
|
||||
*/
|
||||
static access_t init_value()
|
||||
struct Ulcon : Register<0x0, 32>
|
||||
{
|
||||
return Word_length::bits(Word_length::_8_BIT) |
|
||||
Stop_bits::bits(Stop_bits::_1_BIT) |
|
||||
Parity_mode::bits(Parity_mode::NONE) |
|
||||
Infrared_mode::bits(0);
|
||||
}
|
||||
};
|
||||
struct Word_length : Bitfield<0, 2> { enum { _8_BIT = 3 }; };
|
||||
struct Stop_bits : Bitfield<2, 1> { enum { _1_BIT = 0 }; };
|
||||
struct Parity_mode : Bitfield<3, 3> { enum { NONE = 0 }; };
|
||||
struct Infrared_mode : Bitfield<6, 1> { };
|
||||
|
||||
/**
|
||||
* Control
|
||||
*/
|
||||
struct Ucon : Register<0x4, 32>
|
||||
{
|
||||
struct Receive_mode : Bitfield<0, 2> { enum { IRQ_POLL = 1 }; };
|
||||
struct Transmit_mode : Bitfield<2, 2> { enum { IRQ_POLL = 1 }; };
|
||||
struct Send_brk_signal : Bitfield<4, 1> { };
|
||||
struct Loop_back_mode : Bitfield<5, 1> { };
|
||||
struct Rx_err_irq : Bitfield<6, 1> { };
|
||||
struct Rx_timeout : Bitfield<7, 1> { };
|
||||
struct Rx_irq_type : Bitfield<8, 1> { enum { LEVEL = 1 }; };
|
||||
struct Tx_irq_type : Bitfield<9, 1> { enum { LEVEL = 1 }; };
|
||||
struct Rx_to_dma_susp : Bitfield<10, 1> { };
|
||||
struct Rx_to_empty_rx : Bitfield<11, 1> { };
|
||||
struct Rx_to_interval : Bitfield<12, 4> { };
|
||||
struct Rx_dma_bst_size : Bitfield<16, 3> { };
|
||||
struct Tx_dma_bst_size : Bitfield<20, 3> { };
|
||||
/**
|
||||
* Initialization value
|
||||
*/
|
||||
static access_t init_value()
|
||||
{
|
||||
return Word_length::bits(Word_length::_8_BIT) |
|
||||
Stop_bits::bits(Stop_bits::_1_BIT) |
|
||||
Parity_mode::bits(Parity_mode::NONE) |
|
||||
Infrared_mode::bits(0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialization value
|
||||
* Control
|
||||
*/
|
||||
static access_t init_value()
|
||||
struct Ucon : Register<0x4, 32>
|
||||
{
|
||||
return Receive_mode::bits(Receive_mode::IRQ_POLL) |
|
||||
Transmit_mode::bits(Transmit_mode::IRQ_POLL) |
|
||||
Send_brk_signal::bits(0) |
|
||||
Loop_back_mode::bits(0) |
|
||||
Rx_err_irq::bits(1) |
|
||||
Rx_timeout::bits(0) |
|
||||
Rx_irq_type::bits(Rx_irq_type::LEVEL) |
|
||||
Tx_irq_type::bits(Tx_irq_type::LEVEL) |
|
||||
Rx_to_dma_susp::bits(0) |
|
||||
Rx_to_empty_rx::bits(0) |
|
||||
Rx_to_interval::bits(3) |
|
||||
Rx_dma_bst_size::bits(0) |
|
||||
Tx_dma_bst_size::bits(0);
|
||||
}
|
||||
};
|
||||
struct Receive_mode : Bitfield<0, 2> { enum { IRQ_POLL = 1 }; };
|
||||
struct Transmit_mode : Bitfield<2, 2> { enum { IRQ_POLL = 1 }; };
|
||||
struct Send_brk_signal : Bitfield<4, 1> { };
|
||||
struct Loop_back_mode : Bitfield<5, 1> { };
|
||||
struct Rx_err_irq : Bitfield<6, 1> { };
|
||||
struct Rx_timeout : Bitfield<7, 1> { };
|
||||
struct Rx_irq_type : Bitfield<8, 1> { enum { LEVEL = 1 }; };
|
||||
struct Tx_irq_type : Bitfield<9, 1> { enum { LEVEL = 1 }; };
|
||||
struct Rx_to_dma_susp : Bitfield<10, 1> { };
|
||||
struct Rx_to_empty_rx : Bitfield<11, 1> { };
|
||||
struct Rx_to_interval : Bitfield<12, 4> { };
|
||||
struct Rx_dma_bst_size : Bitfield<16, 3> { };
|
||||
struct Tx_dma_bst_size : Bitfield<20, 3> { };
|
||||
|
||||
/**
|
||||
* FIFO control
|
||||
*/
|
||||
struct Ufcon : Register<0x8, 32>
|
||||
{
|
||||
struct Fifo_en : Bitfield<0, 1> { };
|
||||
struct Rx_fifo_rst : Bitfield<1, 1> { };
|
||||
struct Tx_fifo_rst : Bitfield<2, 1> { };
|
||||
struct Rx_fifo_trigger : Bitfield<4, 3> { };
|
||||
struct Tx_fifo_trigger : Bitfield<8, 3> { };
|
||||
/**
|
||||
* Initialization value
|
||||
*/
|
||||
static access_t init_value()
|
||||
{
|
||||
return Receive_mode::bits(Receive_mode::IRQ_POLL) |
|
||||
Transmit_mode::bits(Transmit_mode::IRQ_POLL) |
|
||||
Rx_timeout::bits(1);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialization value
|
||||
* FIFO control
|
||||
*/
|
||||
static access_t init_value()
|
||||
struct Ufcon : Register<0x8, 32>
|
||||
{
|
||||
return Fifo_en::bits(1) |
|
||||
Rx_fifo_rst::bits(0) |
|
||||
Tx_fifo_rst::bits(0) |
|
||||
Rx_fifo_trigger::bits(0) |
|
||||
Tx_fifo_trigger::bits(0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Modem control
|
||||
*/
|
||||
struct Umcon : Register<0xc, 32>
|
||||
{
|
||||
struct Send_request : Bitfield<0, 1> { };
|
||||
struct Modem_irq : Bitfield<3, 1> { };
|
||||
struct Auto_flow_ctl : Bitfield<4, 1> { };
|
||||
struct Rts_trigger : Bitfield<5, 3> { };
|
||||
struct Fifo_en : Bitfield<0, 1> { };
|
||||
struct Rx_fifo_rst : Bitfield<1, 1> { };
|
||||
struct Tx_fifo_rst : Bitfield<2, 1> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialization value
|
||||
* Modem control
|
||||
*/
|
||||
static access_t init_value()
|
||||
struct Umcon : Register<0xc, 32>
|
||||
{
|
||||
return Send_request::bits(0) |
|
||||
Modem_irq::bits(0) |
|
||||
Auto_flow_ctl::bits(0) |
|
||||
Rts_trigger::bits(0);
|
||||
struct Send_request : Bitfield<0, 1> { };
|
||||
struct Modem_irq : Bitfield<3, 1> { };
|
||||
struct Auto_flow_ctl : Bitfield<4, 1> { };
|
||||
struct Rts_trigger : Bitfield<5, 3> { };
|
||||
|
||||
/**
|
||||
* Initialization value
|
||||
*/
|
||||
static access_t init_value()
|
||||
{
|
||||
return Send_request::bits(0) |
|
||||
Modem_irq::bits(0) |
|
||||
Auto_flow_ctl::bits(0) |
|
||||
Rts_trigger::bits(0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* FIFO status
|
||||
*/
|
||||
struct Ufstat : Register<0x18, 32>
|
||||
{
|
||||
struct Rx_fifo_count : Bitfield<0, 8> { };
|
||||
struct Rx_fifo_full : Bitfield<8, 1> { };
|
||||
struct Tx_fifo_full : Bitfield<24, 1> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Transmit buffer
|
||||
*/
|
||||
struct Utxh : Register<0x20, 32>
|
||||
{
|
||||
struct Transmit_data : Bitfield<0, 8> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Receive buffer
|
||||
*/
|
||||
struct Urxh : Register<0x24, 32>
|
||||
{
|
||||
struct Receive_data : Bitfield<0, 8> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Baud Rate Divisor
|
||||
*/
|
||||
struct Ubrdiv : Register<0x28, 32>
|
||||
{
|
||||
struct Baud_rate_div : Bitfield<0, 16> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Fractional part of Baud Rate Divisor
|
||||
*/
|
||||
struct Ufracval : Register<0x2c, 32>
|
||||
{
|
||||
struct Baud_rate_frac : Bitfield<0, 4> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Interrupt mask register
|
||||
*/
|
||||
template <unsigned OFF>
|
||||
struct Uintx : Register<OFF, 32>
|
||||
{
|
||||
struct Rxd : Register<OFF, 32>::template Bitfield<0, 1> { };
|
||||
struct Error : Register<OFF, 32>::template Bitfield<1, 1> { };
|
||||
struct Txd : Register<OFF, 32>::template Bitfield<2, 1> { };
|
||||
struct Modem : Register<OFF, 32>::template Bitfield<3, 1> { };
|
||||
};
|
||||
|
||||
using Uintp = Uintx<0x30>;
|
||||
using Uintm = Uintx<0x38>;
|
||||
|
||||
void _rx_enable()
|
||||
{
|
||||
write<Ufcon::Fifo_en>(1);
|
||||
|
||||
/* mask all IRQs except receive IRQ */
|
||||
write<Uintm>(Uintm::Error::bits(1) |
|
||||
Uintm::Txd::bits(1) |
|
||||
Uintm::Modem::bits(1));
|
||||
|
||||
/* clear pending IRQs */
|
||||
write<Uintp>(Uintp::Rxd::bits(1) |
|
||||
Uintp::Error::bits(1) |
|
||||
Uintp::Txd::bits(1) |
|
||||
Uintp::Modem::bits(1));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* FIFO status
|
||||
*/
|
||||
struct Ufstat : Register<0x18, 32>
|
||||
{
|
||||
struct Tx_fifo_full : Bitfield<24, 1> { };
|
||||
};
|
||||
bool _rx_avail() {
|
||||
return (read<Ufstat>() & (Ufstat::Rx_fifo_count::bits(0xff)
|
||||
| Ufstat::Rx_fifo_full::bits(1))); }
|
||||
|
||||
/**
|
||||
* Transmit buffer
|
||||
*/
|
||||
struct Utxh : Register<0x20, 32>
|
||||
{
|
||||
struct Transmit_data : Bitfield<0, 8> { };
|
||||
};
|
||||
/**
|
||||
* Return character received via UART
|
||||
*/
|
||||
char _rx_char()
|
||||
{
|
||||
read<Ufcon>();
|
||||
char c = read<Urxh::Receive_data>();
|
||||
|
||||
/**
|
||||
* Baud Rate Divisor
|
||||
*/
|
||||
struct Ubrdiv : Register<0x28, 32>
|
||||
{
|
||||
struct Baud_rate_div : Bitfield<0, 16> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Fractional part of Baud Rate Divisor
|
||||
*/
|
||||
struct Ufracval : Register<0x2c, 32>
|
||||
{
|
||||
struct Baud_rate_frac : Bitfield<0, 4> { };
|
||||
};
|
||||
/* clear pending RX IRQ */
|
||||
write<Uintp>(Uintp::Rxd::bits(1));
|
||||
return c;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
@ -176,10 +212,14 @@ namespace Genode
|
||||
Exynos_uart_base(addr_t const base, unsigned const clock,
|
||||
unsigned const baud_rate) : Mmio(base)
|
||||
{
|
||||
/* RX and TX FIFO reset */
|
||||
write<Ufcon::Rx_fifo_rst>(1);
|
||||
write<Ufcon::Tx_fifo_rst>(1);
|
||||
while (read<Ufcon::Rx_fifo_rst>() || read<Ufcon::Tx_fifo_rst>()) ;
|
||||
|
||||
/* init control registers */
|
||||
write<Ulcon>(Ulcon::init_value());
|
||||
write<Ucon>(Ucon::init_value());
|
||||
write<Ufcon>(Ufcon::init_value());
|
||||
write<Umcon>(Umcon::init_value());
|
||||
|
||||
/* apply baud rate */
|
||||
|
@ -30,6 +30,11 @@ class Exynos_uart : public Genode::Exynos_uart_base,
|
||||
public Uart::Driver,
|
||||
public Genode::Irq_handler
|
||||
{
|
||||
private:
|
||||
|
||||
Uart::Char_avail_callback &_char_avail_callback;
|
||||
Genode::Irq_activation _irq_activation;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -37,24 +42,31 @@ class Exynos_uart : public Genode::Exynos_uart_base,
|
||||
*/
|
||||
Exynos_uart(Genode::Attached_io_mem_dataspace *uart_mmio, int irq_number,
|
||||
unsigned baud_rate, Uart::Char_avail_callback &callback)
|
||||
:
|
||||
Exynos_uart_base((Genode::addr_t)uart_mmio->local_addr<void>(),
|
||||
Genode::Board_base::UART_2_CLOCK, baud_rate) { }
|
||||
: Exynos_uart_base((Genode::addr_t)uart_mmio->local_addr<void>(),
|
||||
Genode::Board_base::UART_2_CLOCK, baud_rate),
|
||||
_char_avail_callback(callback),
|
||||
_irq_activation(irq_number, *this, sizeof(Genode::addr_t) * 1024) {
|
||||
_rx_enable(); }
|
||||
|
||||
/**
|
||||
* * IRQ handler interface **
|
||||
*/
|
||||
void handle_irq(int irq_number) { }
|
||||
|
||||
/**
|
||||
* * UART driver interface **
|
||||
*/
|
||||
/***************************
|
||||
** IRQ handler interface **
|
||||
***************************/
|
||||
|
||||
void handle_irq(int irq_number)
|
||||
{
|
||||
/* inform client about the availability of data */
|
||||
_char_avail_callback();
|
||||
}
|
||||
|
||||
|
||||
/***************************
|
||||
** UART driver interface **
|
||||
***************************/
|
||||
|
||||
void put_char(char c) { Exynos_uart_base::put_char(c); }
|
||||
|
||||
bool char_avail() { return false; }
|
||||
|
||||
char get_char() { return 0; }
|
||||
|
||||
bool char_avail() { return _rx_avail(); }
|
||||
char get_char() { return _rx_char(); }
|
||||
void baud_rate(int bits_per_second) {}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user