diff --git a/base-hw/include/tl16c750/drivers/serial_log.h b/base-hw/include/tl16c750/drivers/serial_log.h index 12fc3607ab..902b0aac8e 100644 --- a/base-hw/include/tl16c750/drivers/serial_log.h +++ b/base-hw/include/tl16c750/drivers/serial_log.h @@ -33,8 +33,8 @@ namespace Genode * \param baud_rate targeted transfer baud-rate */ Serial_log(unsigned const baud_rate) : - Tl16c750_base(Board::TL16C750_3_MMIO_BASE, - Board::TL16C750_3_CLOCK, baud_rate) + Tl16c750_base(Board::TL16C750_MMIO_BASE, + Board::TL16C750_CLOCK, baud_rate) { } }; } diff --git a/base-hw/src/core/panda/platform_support.cc b/base-hw/src/core/panda/platform_support.cc index 53dfb6c56a..b99948753d 100644 --- a/base-hw/src/core/panda/platform_support.cc +++ b/base-hw/src/core/panda/platform_support.cc @@ -79,7 +79,7 @@ Native_region * Platform::_core_only_mmio_regions(unsigned const i) Board::CORTEX_A9_PRIVATE_MEM_SIZE }, /* core UART */ - { Board::TL16C750_3_MMIO_BASE, Board::TL16C750_3_MMIO_SIZE } + { Board::TL16C750_3_MMIO_BASE, Board::TL16C750_MMIO_SIZE } }; return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0; } diff --git a/base/include/drivers/uart/tl16c750_base.h b/base/include/drivers/uart/tl16c750_base.h index c96ac1eb18..d0ac058920 100644 --- a/base/include/drivers/uart/tl16c750_base.h +++ b/base/include/drivers/uart/tl16c750_base.h @@ -27,120 +27,137 @@ namespace Genode */ class Tl16c750_base : public Mmio { - /** - * Least significant divisor part - */ - struct Uart_dll : Register<0x0, 32> - { - struct Clock_lsb : Bitfield<0, 8> { }; - }; - - /** - * Transmit holding register - */ - struct Uart_thr : Register<0x0, 32> - { - struct Thr : Bitfield<0, 8> { }; - }; - - /** - * Most significant divisor part - */ - struct Uart_dlh : Register<0x4, 32> - { - struct Clock_msb : Bitfield<0, 6> { }; - }; - - /** - * Interrupt enable register - */ - struct Uart_ier : Register<0x4, 32> - { - struct Rhr_it : Bitfield<0, 1> { }; - struct Thr_it : Bitfield<1, 1> { }; - struct Line_sts_it : Bitfield<2, 1> { }; - struct Modem_sts_it : Bitfield<3, 1> { }; - struct Sleep_mode : Bitfield<4, 1> { }; - struct Xoff_it : Bitfield<5, 1> { }; - struct Rts_it : Bitfield<6, 1> { }; - struct Cts_it : Bitfield<7, 1> { }; - }; - - /** - * FIFO control register - */ - struct Uart_fcr : Register<0x8, 32> - { - struct Fifo_enable : Bitfield<0, 1> { }; - }; - - /** - * Line control register - */ - struct Uart_lcr : Register<0xc, 32> - { - struct Char_length : Bitfield<0, 2> + protected: + /** + * Least significant divisor part + */ + struct Uart_dll : Register<0x0, 32> { - enum { _8_BIT = 3 }; + struct Clock_lsb : Bitfield<0, 8> { }; }; - struct Nb_stop : Bitfield<2, 1> + + /** + * Transmit holding register + */ + struct Uart_thr : Register<0x0, 32> { - enum { _1_STOP_BIT = 0 }; + struct Thr : Bitfield<0, 8> { }; }; - struct Parity_en : Bitfield<3, 1> { }; - struct Break_en : Bitfield<6, 1> { }; - struct Div_en : Bitfield<7, 1> { }; - struct Reg_mode : Bitfield<0, 8> + + /** + * Receiver holding register + */ + struct Uart_rhr : Register<0x0, 32> { - enum { OPERATIONAL = 0, CONFIG_A = 0x80, CONFIG_B = 0xbf }; + struct Rhr : Bitfield<0, 8> { }; }; - }; - /** - * Modem control register - */ - struct Uart_mcr : Register<0x10, 32> - { - struct Tcr_tlr : Bitfield<6, 1> { }; - }; - - /** - * Line status register - */ - struct Uart_lsr : Register<0x14, 32> - { - struct Tx_fifo_empty : Bitfield<5, 1> { }; - }; - - /** - * Mode definition register 1 - */ - struct Uart_mdr1 : Register<0x20, 32> - { - struct Mode_select : Bitfield<0, 3> + /** + * Most significant divisor part + */ + struct Uart_dlh : Register<0x4, 32> { - enum { UART_16X = 0, DISABLED = 7 }; + struct Clock_msb : Bitfield<0, 6> { }; }; - }; - /** - * System control register - */ - struct Uart_sysc : Register<0x54, 32> - { - struct Softreset : Bitfield<1, 1> { }; - }; + /** + * Interrupt enable register + */ + struct Uart_ier : Register<0x4, 32> + { + struct Rhr_it : Bitfield<0, 1> { }; + struct Thr_it : Bitfield<1, 1> { }; + struct Line_sts_it : Bitfield<2, 1> { }; + struct Modem_sts_it : Bitfield<3, 1> { }; + struct Sleep_mode : Bitfield<4, 1> { }; + struct Xoff_it : Bitfield<5, 1> { }; + struct Rts_it : Bitfield<6, 1> { }; + struct Cts_it : Bitfield<7, 1> { }; + }; - /** - * System status register - */ - struct Uart_syss : Register<0x58, 32> - { - struct Resetdone : Bitfield<0, 1> { }; - }; + /** + * Interrupt identification register + */ + struct Uart_iir : Register<0x8, 32> + { + struct It_pending : Bitfield<0, 1> { }; + }; + + /** + * FIFO control register + */ + struct Uart_fcr : Register<0x8, 32> + { + struct Fifo_enable : Bitfield<0, 1> { }; + }; + + /** + * Line control register + */ + struct Uart_lcr : Register<0xc, 32> + { + struct Char_length : Bitfield<0, 2> + { + enum { _8_BIT = 3 }; + }; + struct Nb_stop : Bitfield<2, 1> + { + enum { _1_STOP_BIT = 0 }; + }; + struct Parity_en : Bitfield<3, 1> { }; + struct Break_en : Bitfield<6, 1> { }; + struct Div_en : Bitfield<7, 1> { }; + struct Reg_mode : Bitfield<0, 8> + { + enum { OPERATIONAL = 0, CONFIG_A = 0x80, CONFIG_B = 0xbf }; + }; + }; + + /** + * Modem control register + */ + struct Uart_mcr : Register<0x10, 32> + { + struct Tcr_tlr : Bitfield<6, 1> { }; + }; + + /** + * Line status register + */ + struct Uart_lsr : Register<0x14, 32> + { + struct Rx_fifo_empty : Bitfield<0, 1> { }; + struct Tx_fifo_empty : Bitfield<5, 1> { }; + }; + + /** + * Mode definition register 1 + */ + struct Uart_mdr1 : Register<0x20, 32> + { + struct Mode_select : Bitfield<0, 3> + { + enum { UART_16X = 0, DISABLED = 7 }; + }; + }; + + /** + * System control register + */ + struct Uart_sysc : Register<0x54, 32> + { + struct Softreset : Bitfield<1, 1> { }; + }; + + /** + * System status register + */ + struct Uart_syss : Register<0x58, 32> + { + struct Resetdone : Bitfield<0, 1> { }; + }; public: - /** * Constructor * diff --git a/base/include/platform/panda/drivers/board.h b/base/include/platform/panda/drivers/board.h index d535fa0a85..bc99f5e4dc 100644 --- a/base/include/platform/panda/drivers/board.h +++ b/base/include/platform/panda/drivers/board.h @@ -36,11 +36,19 @@ namespace Genode /* clocks */ MPU_DPLL_CLOCK = 200*1000*1000, - /* UART */ - TL16C750_3_MMIO_BASE = 0x48020000, - TL16C750_3_MMIO_SIZE = 0x00002000, - TL16C750_3_CLOCK = 48*1000*1000, + /* UARTs */ + TL16C750_1_MMIO_BASE = MMIO_0_BASE + 0x6a000, + TL16C750_2_MMIO_BASE = MMIO_0_BASE + 0x6c000, + TL16C750_3_MMIO_BASE = MMIO_0_BASE + 0x20000, + TL16C750_4_MMIO_BASE = MMIO_0_BASE + 0x6e000, + + TL16C750_MMIO_SIZE = 0x2000, + TL16C750_CLOCK = 48*1000*1000, + + TL16C750_1_IRQ = 72, + TL16C750_2_IRQ = 73, TL16C750_3_IRQ = 74, + TL16C750_4_IRQ = 70, /* CPU */ CORTEX_A9_PRIVATE_MEM_BASE = 0x48240000, diff --git a/os/include/platform/panda/uart_defs.h b/os/include/platform/panda/uart_defs.h new file mode 100644 index 0000000000..93aaae4745 --- /dev/null +++ b/os/include/platform/panda/uart_defs.h @@ -0,0 +1,39 @@ +/* + * \brief OMAP4 UART definitions + * \author Ivan Loskutov + * \date 2012-11-08 + */ + +/* + * Copyright (C) 2012 Ksys Labs LLC + * Copyright (C) 2011-2012 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__PLATFORM__PANDABOARD__UART_DEFS_H_ +#define _INCLUDE__PLATFORM__PANDABOARD__UART_DEFS_H_ + +#include + +enum { + /** Number of UARTs */ + UARTS_NUM = 4, + + BAUD_115200 = 26, +}; + + +static struct Omap_uart_cfg { + Genode::addr_t mmio_base; + Genode::size_t mmio_size; + int irq_number; +} omap_uart_cfg[UARTS_NUM] = { + { Genode::Board::TL16C750_1_MMIO_BASE, Genode::Board::TL16C750_MMIO_SIZE, Genode::Board::TL16C750_1_IRQ + 32 }, + { Genode::Board::TL16C750_2_MMIO_BASE, Genode::Board::TL16C750_MMIO_SIZE, Genode::Board::TL16C750_2_IRQ + 32 }, + { Genode::Board::TL16C750_3_MMIO_BASE, Genode::Board::TL16C750_MMIO_SIZE, Genode::Board::TL16C750_3_IRQ + 32 }, + { Genode::Board::TL16C750_4_MMIO_BASE, Genode::Board::TL16C750_MMIO_SIZE, Genode::Board::TL16C750_4_IRQ + 32 }, +}; + +#endif /* _INCLUDE__PLATFORM__PANDABOARD__UART_DEFS_H_ */ diff --git a/os/run/panda_uart4_echo.run b/os/run/panda_uart4_echo.run new file mode 100644 index 0000000000..4013261771 --- /dev/null +++ b/os/run/panda_uart4_echo.run @@ -0,0 +1,72 @@ +# +# Build +# +assert_spec foc +assert_spec platform_panda + +# generic components +set build_components { + core init + drivers/timer drivers/uart + test/terminal_echo +} + +build $build_components +create_boot_directory + + +# +# Config +# + +set config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +install_config $config + + +# +# Boot modules +# + +# generic modules +set boot_modules { + core init + timer uart_drv test-terminal_echo +} + +build_boot_image $boot_modules + diff --git a/os/src/drivers/uart/omap4/main.cc b/os/src/drivers/uart/omap4/main.cc new file mode 100644 index 0000000000..2be9b35774 --- /dev/null +++ b/os/src/drivers/uart/omap4/main.cc @@ -0,0 +1,88 @@ +/* + * \brief Driver for OMAP4 UARTs + * \author Ivan Loskutov + * \date 2012-11-08 + */ + +/* + * Copyright (C) 2012 Ksys Labs LLC + * Copyright (C) 2011-2012 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Genode includes */ +#include +#include +#include +#include +#include + +#include + +/* local includes */ +#include "omap_uart.h" +#include "uart_component.h" + + +int main(int argc, char **argv) +{ + using namespace Genode; + + PDBG("--- OMAP4 UART driver started ---\n"); + + /** + * Factory used by 'Terminal::Root' at session creation/destruction time + */ + struct Omap_uart_driver_factory : Uart::Driver_factory + { + Omap_uart *created[UARTS_NUM]; + + /** + * Constructor + */ + Omap_uart_driver_factory() + { + for (unsigned i = 0; i < UARTS_NUM; i++) + created[i] = 0; + } + + Uart::Driver *create(unsigned index, + Uart::Char_avail_callback &callback) + { + if (index > UARTS_NUM) + throw Uart::Driver_factory::Not_available(); + + Omap_uart_cfg *cfg = &omap_uart_cfg[index]; + Omap_uart *uart = created[index]; + + Genode::Attached_io_mem_dataspace *uart_mmio = new (env()->heap()) + Genode::Attached_io_mem_dataspace(cfg->mmio_base, cfg->mmio_size); + + if (!uart) { + uart = new (env()->heap()) + Omap_uart(uart_mmio, cfg->irq_number, BAUD_115200, callback); + + /* update 'created' table */ + created[index] = uart; + } + + return uart; + } + + void destroy(Uart::Driver *driver) { /* TODO */ } + + } driver_factory; + + enum { STACK_SIZE = 0x2000 }; + static Cap_connection cap; + + static Rpc_entrypoint ep(&cap, STACK_SIZE, "uart_ep"); + + static Uart::Root uart_root(&ep, env()->heap(), driver_factory); + env()->parent()->announce(ep.manage(&uart_root)); + + sleep_forever(); + return 0; +} diff --git a/os/src/drivers/uart/omap4/omap_uart.h b/os/src/drivers/uart/omap4/omap_uart.h new file mode 100644 index 0000000000..549422c122 --- /dev/null +++ b/os/src/drivers/uart/omap4/omap_uart.h @@ -0,0 +1,101 @@ +/* + * \brief Driver for OMAP4 UARTs + * \author Ivan Loskutov + * \date 2012-11-08 + */ + +/* + * Copyright (C) 2012 Ksys Labs LLC + * Copyright (C) 2011-2012 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _OMAP_UART_H_ +#define _OMAP_UART_H_ + +/* Genode includes */ +#include +#include +#include +#include + +#include + +/* local includes */ +#include "uart_driver.h" + +class Omap_uart : public Genode::Tl16c750_base, public Uart::Driver, public Genode::Irq_handler +{ + private: + Genode::Attached_io_mem_dataspace _uart_mmio; + + Uart::Char_avail_callback &_char_avail_callback; + + enum { IRQ_STACK_SIZE = 4096 }; + Genode::Irq_activation _irq_activation; + + void _enable_rx_interrupt() + { + /* enable access to 'Uart_fcr' and 'Uart_ier' */ + write(Uart_lcr::Reg_mode::OPERATIONAL); + + /* enable rx interrupt, disable other interrupts and sleep mode */ + write(Uart_ier::Rhr_it::bits(1) + | Uart_ier::Thr_it::bits(0) + | Uart_ier::Line_sts_it::bits(0) + | Uart_ier::Modem_sts_it::bits(0) + | Uart_ier::Sleep_mode::bits(0) + | Uart_ier::Xoff_it::bits(0) + | Uart_ier::Rts_it::bits(0) + | Uart_ier::Cts_it::bits(0)); + /* + * Configure protocol formatting and thereby return to + * operational mode. + */ + write(Uart_lcr::Char_length::bits(Uart_lcr::Char_length::_8_BIT) + | Uart_lcr::Nb_stop::bits(Uart_lcr::Nb_stop::_1_STOP_BIT) + | Uart_lcr::Parity_en::bits(0) + | Uart_lcr::Break_en::bits(0) + | Uart_lcr::Div_en::bits(0)); + } + + public: + + /** + * Constructor + */ + Omap_uart(Genode::Attached_io_mem_dataspace *uart_mmio, int irq_number, + unsigned baud_rate, Uart::Char_avail_callback &callback) + : + Tl16c750_base((Genode::addr_t)uart_mmio->local_addr(), Genode::Board::TL16C750_CLOCK, baud_rate), + _uart_mmio(*uart_mmio), + _char_avail_callback(callback), + _irq_activation(irq_number, *this, IRQ_STACK_SIZE) + { + _enable_rx_interrupt(); + } + + /** + * * IRQ handler interface ** + */ + void handle_irq(int irq_number) + { + /* inform client about the availability of data */ + unsigned int iir = read(); + if (iir) return; + _char_avail_callback(); + } + + /** + * * UART driver interface ** + */ + void put_char(char c) { Tl16c750_base::put_char(c); } + + bool char_avail() { return read(); } + + char get_char() { return read(); } +}; + +#endif /* _OMAP_UART_H_ */ diff --git a/os/src/drivers/uart/omap4/target.mk b/os/src/drivers/uart/omap4/target.mk new file mode 100644 index 0000000000..b9f19b1158 --- /dev/null +++ b/os/src/drivers/uart/omap4/target.mk @@ -0,0 +1,6 @@ +TARGET = uart_drv +REQUIRES = omap4 +SRC_CC = main.cc +LIBS = cxx env server signal + +INC_DIR += $(PRG_DIR) $(PRG_DIR)/..