2 * (c) 2009 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_s3c2410.h"
10 #include "poll_timeout_counter.h"
16 Type_24xx, Type_64xx, Type_s5pv210,
21 ULCON = 0x0, // line control register
22 UCON = 0x4, // control register
23 UFCON = 0x8, // FIFO control register
24 UMCON = 0xc, // modem control register
25 UTRSTAT = 0x10, // Tx/Rx status register
26 UERSTAT = 0x14, // Rx error status register
27 UFSTAT = 0x18, // FIFO status register
28 UMSTAT = 0x1c, // modem status register
29 UTXH = 0x20, // transmit buffer register (little endian, 0x23 for BE)
30 URXH = 0x24, // receive buffer register (little endian, 0x27 for BE)
31 UBRDIV = 0x28, // baud rate divisor register
34 UINTP = 0x30, // interrupt pending register
35 UINTSP = 0x34, // interrupt source pending register
36 UINTM = 0x38, // interrupt mask register
41 UCON_MODE_RECEIVE_IRQ_POLL = 1 << 0,
42 UCON_MODE_TRANSMIT_IRQ_POLL = 1 << 2,
43 UCON_SEND_BREAK_SIGNAL = 1 << 4,
44 UCON_LOOPBACK_MODE = 1 << 5,
45 UCON_RX_ERROR_STATUS_IRQ_EN = 1 << 6,
46 UCON_RX_TIME_OUT_EN = 1 << 7,
47 UCON_MODE = UCON_MODE_RECEIVE_IRQ_POLL
48 | UCON_MODE_TRANSMIT_IRQ_POLL
49 | UCON_RX_TIME_OUT_EN,
51 UFCON_ENABLE = 1 << 0, // enable fifo
52 UFCON_RX_FIFO_RESET = 1 << 1, // Rx Fifo reset
53 UFCON_TX_FIFO_RESET = 1 << 2, // Tx Fifo reset
57 UTRSTAT_Rx_RDY = 1 << 0,
58 UTRSTAT_Tx_RDY = 1 << 1,
66 UFSTAT_2410_Rx_COUNT_MASK = 0x00f,
67 UFSTAT_2410_Tx_COUNT_MASK = 0x0f0,
68 UFSTAT_2410_RxFULL = 0x100,
69 UFSTAT_2410_TxFULL = 0x200,
72 UFSTAT_64XX_Rx_COUNT_MASK = 0x003f,
73 UFSTAT_64XX_Tx_COUNT_MASK = 0x3f00,
74 UFSTAT_64XX_RxFULL = 0x0040,
75 UFSTAT_64XX_TxFULL = 0x4000,
78 UFSTAT_S5PV210_Rx_COUNT_MASK = 0x000000ff,
79 UFSTAT_S5PV210_Tx_COUNT_MASK = 0x00ff0000,
80 UFSTAT_S5PV210_RxFULL = 0x00000100,
81 UFSTAT_S5PV210_TxFULL = 0x01000000,
85 void Uart_s3c::fifo_reset()
87 _regs->write<unsigned int>(UFCON, UFCON_RX_FIFO_RESET | UFCON_TX_FIFO_RESET);
88 Poll_timeout_counter i(3000000);
89 while (i.test(_regs->read<unsigned int>(UFCON) & (UFCON_RX_FIFO_RESET | UFCON_TX_FIFO_RESET)))
94 bool Uart_s3c::startup(Io_register_block const *regs)
100 _regs->write<unsigned int>(UMCON, 0);
103 _regs->write<unsigned int>(ULCON, ULCON_8N1_MODE);
104 _regs->write<unsigned int>(UCON, UCON_MODE);
105 _regs->write<unsigned int>(UFCON, UFCON_ENABLE);
113 _regs->write<unsigned int>(UINTM, ~UINT_RXD); // mask all but receive irq
114 _regs->write<unsigned int>(UINTP, ~0); // clear all pending irqs
118 _regs->write<unsigned int>(UBRDIV, 0x23);
124 void Uart_s3c::shutdown()
129 bool Uart_s3c::change_mode(Transfer_mode, Baud_rate r)
135 _regs->write<unsigned int>(ULCON, ULCON_8N1_MODE);
136 _regs->write<unsigned int>(UCON, UCON_MODE);
137 _regs->write<unsigned int>(UFCON, 1);
139 _regs->write<unsigned int>(UBRDIV, 0x23);
145 int Uart_s3c::get_char(bool blocking) const
147 while (!char_avail())
151 _regs->read<unsigned int>(UFCON);
152 int c = _regs->read<unsigned int>(URXH) & 0xff;
157 int Uart_s3c::char_avail() const
159 return is_rx_fifo_non_empty();
162 void Uart_s3c::out_char(char c) const
164 wait_for_non_full_tx_fifo();
165 _regs->write<unsigned int>(UTXH, c);
168 int Uart_s3c::write(char const *s, unsigned long count) const
170 unsigned long c = count;
173 wait_for_empty_tx_fifo();
178 // -----------------------
180 void Uart_s3c2410::wait_for_empty_tx_fifo() const
182 Poll_timeout_counter i(3000000);
183 while (i.test(_regs->read<unsigned int>(UFSTAT) & (UFSTAT_2410_Tx_COUNT_MASK | UFSTAT_2410_TxFULL)))
187 void Uart_s3c2410::wait_for_non_full_tx_fifo() const
189 Poll_timeout_counter i(3000000);
190 while (i.test(_regs->read<unsigned int>(UFSTAT) & UFSTAT_2410_TxFULL))
194 unsigned Uart_s3c2410::is_rx_fifo_non_empty() const
196 return _regs->read<unsigned int>(UFSTAT) & (UFSTAT_2410_Rx_COUNT_MASK | UFSTAT_2410_RxFULL);
199 void Uart_s3c2410::auto_flow_control(bool on)
201 _regs->write<unsigned int>(UMCON, (_regs->read<unsigned int>(UMCON) & ~UMCON_AFC) | (on ? UMCON_AFC : 0));
204 // -----------------------
206 void Uart_s3c64xx::wait_for_empty_tx_fifo() const
208 Poll_timeout_counter i(3000000);
209 while (i.test(_regs->read<unsigned int>(UFSTAT) & (UFSTAT_64XX_Tx_COUNT_MASK | UFSTAT_64XX_TxFULL)))
213 void Uart_s3c64xx::wait_for_non_full_tx_fifo() const
215 Poll_timeout_counter i(3000000);
216 while (i.test(_regs->read<unsigned int>(UFSTAT) & UFSTAT_64XX_TxFULL))
220 unsigned Uart_s3c64xx::is_rx_fifo_non_empty() const
222 return _regs->read<unsigned int>(UFSTAT) & (UFSTAT_64XX_Rx_COUNT_MASK | UFSTAT_64XX_RxFULL);
225 void Uart_s3c64xx::ack_rx_irq() const
227 _regs->write<unsigned int>(UINTP, UINT_RXD);
230 // -----------------------
232 void Uart_s5pv210::wait_for_empty_tx_fifo() const
234 Poll_timeout_counter i(3000000);
235 while (i.test(_regs->read<unsigned int>(UFSTAT) & (UFSTAT_S5PV210_Tx_COUNT_MASK | UFSTAT_S5PV210_TxFULL)))
239 void Uart_s5pv210::wait_for_non_full_tx_fifo() const
241 Poll_timeout_counter i(3000000);
242 while (i.test(_regs->read<unsigned int>(UFSTAT) & UFSTAT_S5PV210_TxFULL))
246 unsigned Uart_s5pv210::is_rx_fifo_non_empty() const
248 return _regs->read<unsigned int>(UFSTAT) & (UFSTAT_S5PV210_Rx_COUNT_MASK | UFSTAT_S5PV210_RxFULL);
251 void Uart_s5pv210::ack_rx_irq() const
253 _regs->write<unsigned int>(UINTP, UINT_RXD);