From e7dad390169931fb9422c5b0e2f88bd6f08a9b21 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Mon, 23 Feb 2015 12:40:19 +0100 Subject: [PATCH] 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 --- .../include/drivers/uart/exynos_uart_base.h | 276 ++++++++++-------- .../src/drivers/uart/exynos5/exynos5_uart.h | 42 ++- 2 files changed, 185 insertions(+), 133 deletions(-) diff --git a/repos/base/include/drivers/uart/exynos_uart_base.h b/repos/base/include/drivers/uart/exynos_uart_base.h index 49c049e36..40723e9b2 100644 --- a/repos/base/include/drivers/uart/exynos_uart_base.h +++ b/repos/base/include/drivers/uart/exynos_uart_base.h @@ -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 + struct Uintx : Register + { + struct Rxd : Register::template Bitfield<0, 1> { }; + struct Error : Register::template Bitfield<1, 1> { }; + struct Txd : Register::template Bitfield<2, 1> { }; + struct Modem : Register::template Bitfield<3, 1> { }; + }; + + using Uintp = Uintx<0x30>; + using Uintm = Uintx<0x38>; + + void _rx_enable() + { + write(1); + + /* mask all IRQs except receive IRQ */ + write(Uintm::Error::bits(1) | + Uintm::Txd::bits(1) | + Uintm::Modem::bits(1)); + + /* clear pending IRQs */ + write(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::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(); + char c = read(); - /** - * 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::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(1); + write(1); + while (read() || read()) ; + /* init control registers */ write(Ulcon::init_value()); write(Ucon::init_value()); - write(Ufcon::init_value()); write(Umcon::init_value()); /* apply baud rate */ diff --git a/repos/os/src/drivers/uart/exynos5/exynos5_uart.h b/repos/os/src/drivers/uart/exynos5/exynos5_uart.h index fb10d4a0c..e9ed429df 100644 --- a/repos/os/src/drivers/uart/exynos5/exynos5_uart.h +++ b/repos/os/src/drivers/uart/exynos5/exynos5_uart.h @@ -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(), - Genode::Board_base::UART_2_CLOCK, baud_rate) { } + : Exynos_uart_base((Genode::addr_t)uart_mmio->local_addr(), + 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) {} };