genode/repos/os/src/drivers/uart/spec/panda/uart_driver.h

136 lines
3.8 KiB
C++

/*
* \brief Driver for OMAP4 UARTs
* \author Ivan Loskutov
* \author Stefan Kalkowski
* \date 2012-11-08
*/
/*
* Copyright (C) 2012 Ksys Labs LLC
* Copyright (C) 2011-2017 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 _UART_DRIVER_H_
#define _UART_DRIVER_H_
/* Genode includes */
#include <base/attached_io_mem_dataspace.h>
#include <base/env.h>
#include <drivers/defs/panda.h>
#include <drivers/uart/tl16c750.h>
enum { UARTS_NUM = 4 }; /* needed by base class definitions */
/* local includes */
#include <uart_driver_base.h>
class Uart::Driver : private Genode::Attached_io_mem_dataspace,
private Genode::Tl16c750_uart,
public Uart::Driver_base
{
private:
void _enable_rx_interrupt()
{
/* enable access to 'Uart_fcr' and 'Uart_ier' */
write<Uart_lcr::Reg_mode>(Uart_lcr::Reg_mode::OPERATIONAL);
/* enable rx interrupt, disable other interrupts and sleep mode */
write<Uart_ier>(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>(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));
}
enum { BAUD_115200 = 115200 };
struct Uart {
Genode::addr_t mmio_base;
Genode::size_t mmio_size;
int irq_number;
};
Uart & _config(unsigned index)
{
using namespace Genode;
static Uart cfg[UARTS_NUM] = {
{ Panda::TL16C750_1_MMIO_BASE, Panda::TL16C750_MMIO_SIZE,
Panda::TL16C750_1_IRQ },
{ Panda::TL16C750_2_MMIO_BASE, Panda::TL16C750_MMIO_SIZE,
Panda::TL16C750_2_IRQ },
{ Panda::TL16C750_3_MMIO_BASE, Panda::TL16C750_MMIO_SIZE,
Panda::TL16C750_3_IRQ },
{ Panda::TL16C750_4_MMIO_BASE, Panda::TL16C750_MMIO_SIZE,
Panda::TL16C750_4_IRQ },
};
return cfg[index];
}
unsigned _baud_rate(unsigned baud_rate)
{
if (baud_rate != 0) return baud_rate;
Genode::warning("baud_rate ", baud_rate,
" not supported, set to default");
return BAUD_115200;
}
public:
Driver(Genode::Env &env, unsigned index,
unsigned baud_rate, Char_avail_functor &func)
: Genode::Attached_io_mem_dataspace(env, _config(index).mmio_base,
_config(index).mmio_size),
Tl16c750_uart((Genode::addr_t)local_addr<void>(),
Panda::TL16C750_CLOCK,
_baud_rate(baud_rate)),
Driver_base(env, _config(index).irq_number, func) {
_enable_rx_interrupt(); }
/***************************
** UART driver interface **
***************************/
void handle_irq() override
{
/* check for interrupt */
unsigned int iir = read<Uart_iir::It_pending>();
if (iir) return;
/* inform client about the availability of data */
Driver_base::handle_irq();
}
void put_char(char c) override { Tl16c750_uart::put_char(c); }
bool char_avail() override { return read<Uart_lsr::Rx_fifo_empty>(); }
char get_char() override { return read<Uart_rhr::Rhr>(); }
void baud_rate(int bits_per_second) override
{
_init(Panda::TL16C750_CLOCK, bits_per_second);
_enable_rx_interrupt();
}
};
#endif /* _UART_DRIVER_H_ */