2 * (c) 2009-2012 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
3 * economic rights: Technische Universität Dresden (Germany)
5 * This file is part of TUD:OS and distributed under the terms of the
6 * GNU General Public License 2.
7 * Please see the COPYING-GPL-2 file for details.
9 #include "uart_pl011.h"
10 #include "poll_timeout_counter.h"
15 UART011_RXIM = 1 << 4,
16 UART011_TXIM = 1 << 5,
17 UART011_RTIM = 1 << 6,
18 UART011_FEIM = 1 << 7,
19 UART011_PEIM = 1 << 8,
20 UART011_BEIM = 1 << 9,
21 UART011_OEIM = 1 << 10,
23 UART011_RXIS = 1 << 4,
24 UART011_RTIS = 1 << 6,
26 UART011_RXIC = 1 << 4,
27 UART011_RTIC = 1 << 6,
29 UART01x_CR_UARTEN = 1, // UART enable
30 UART011_CR_LBE = 0x080, // loopback enable
31 UART011_CR_TXE = 0x100, // transmit enable
32 UART011_CR_RXE = 0x200, // receive enable
34 UART01x_FR_BUSY = 0x008,
35 UART01x_FR_RXFE = 0x010,
36 UART01x_FR_TXFF = 0x020,
38 UART01x_LCRH_PEN = 0x02, // parity enable
39 UART01x_LCRH_FEN = 0x10, // FIFO enable
40 UART01x_LCRH_WLEN_8 = 0x60,
53 Default_baud = 115200,
56 bool Uart_pl011::startup(Io_register_block const *regs)
59 _regs->write<unsigned int>(UART011_CR, UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE);
60 unsigned fi_val = _freq * 4 / Default_baud;
61 _regs->write<unsigned int>(UART011_FBRD, fi_val & 0x3f);
62 _regs->write<unsigned int>(UART011_IBRD, fi_val >> 6);
63 _regs->write<unsigned int>(UART011_LCRH, UART01x_LCRH_WLEN_8);
64 _regs->write<unsigned int>(UART011_IMSC, 0);
65 Poll_timeout_counter i(3000000);
66 while (i.test() && _regs->read<unsigned int>(UART01x_FR) & UART01x_FR_BUSY)
71 void Uart_pl011::shutdown()
73 _regs->write<unsigned int>(UART011_IMSC, 0);
74 _regs->write<unsigned int>(UART011_ICR, 0xffff);
75 _regs->write<unsigned int>(UART011_CR, 0);
78 bool Uart_pl011::enable_rx_irq(bool enable)
80 unsigned long mask = UART011_RXIM | UART011_RTIM;
82 _regs->write<unsigned int>(UART011_ICR, 0xffff & ~mask);
83 _regs->write<unsigned int>(UART011_ECR, 0xff);
85 _regs->write<unsigned int>(UART011_IMSC, _regs->read<unsigned int>(UART011_IMSC) | mask);
87 _regs->write<unsigned int>(UART011_IMSC, _regs->read<unsigned int>(UART011_IMSC) & ~mask);
91 bool Uart_pl011::change_mode(Transfer_mode, Baud_rate r)
93 unsigned long old_cr = _regs->read<unsigned int>(UART011_CR);
94 _regs->write<unsigned int>(UART011_CR, 0);
96 unsigned fi_val = _freq * 4 / r;
97 _regs->write<unsigned int>(UART011_FBRD, fi_val & 0x3f);
98 _regs->write<unsigned int>(UART011_IBRD, fi_val >> 6);
99 _regs->write<unsigned int>(UART011_LCRH, UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN);
101 _regs->write<unsigned int>(UART011_CR, old_cr);
106 int Uart_pl011::get_char(bool blocking) const
108 while (!char_avail())
112 //_regs->write(UART011_ICR, UART011_RXIC | UART011_RTIC);
114 int c = _regs->read<unsigned int>(UART01x_DR);
115 _regs->write<unsigned int>(UART011_ECR, 0xff);
119 int Uart_pl011::char_avail() const
121 return !(_regs->read<unsigned int>(UART01x_FR) & UART01x_FR_RXFE);
124 void Uart_pl011::out_char(char c) const
126 Poll_timeout_counter i(3000000);
127 while (i.test(_regs->read<unsigned int>(UART01x_FR) & UART01x_FR_TXFF))
129 _regs->write<unsigned int>(UART01x_DR,c);
132 int Uart_pl011::write(char const *s, unsigned long count) const
134 unsigned long c = count;
138 Poll_timeout_counter i(3000000);
139 while (i.test(_regs->read<unsigned int>(UART01x_FR) & UART01x_FR_BUSY))