]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/drivers-frst/uart/src/uart_s3c2410.cc
Update
[l4.git] / l4 / pkg / drivers-frst / uart / src / uart_s3c2410.cc
1 /*
2  * (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
3  *     economic rights: Technische Universität Dresden (Germany)
4  *
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.
8  */
9 #include "uart_s3c2410.h"
10 #include "poll_timeout_counter.h"
11
12 namespace L4
13 {
14   enum
15   {
16     Type_24xx, Type_64xx, Type_s5pv210,
17   };
18
19   enum
20   {
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
32     UFRACVAL= 0x2c,
33     // 64xx++
34     UINTP   = 0x30, // interrupt pending register
35     UINTSP  = 0x34, // interrupt source pending register
36     UINTM   = 0x38, // interrupt mask register
37
38
39     ULCON_8N1_MODE = 0x3,
40
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,
50
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
54
55     UMCON_AFC = 1 << 4,
56
57     UTRSTAT_Rx_RDY = 1 << 0,
58     UTRSTAT_Tx_RDY = 1 << 1,
59
60     UINT_RXD   = 1 << 0,
61     UINT_ERROR = 1 << 1,
62     UINT_TXD   = 1 << 2,
63     UINT_MODEM = 1 << 3,
64
65     // 2410
66     UFSTAT_2410_Rx_COUNT_MASK = 0x00f,
67     UFSTAT_2410_Tx_COUNT_MASK = 0x0f0,
68     UFSTAT_2410_RxFULL        = 0x100,
69     UFSTAT_2410_TxFULL        = 0x200,
70
71     // 64xx
72     UFSTAT_64XX_Rx_COUNT_MASK = 0x003f,
73     UFSTAT_64XX_Tx_COUNT_MASK = 0x3f00,
74     UFSTAT_64XX_RxFULL        = 0x0040,
75     UFSTAT_64XX_TxFULL        = 0x4000,
76
77     // s5pv210
78     UFSTAT_S5PV210_Rx_COUNT_MASK = 0x000000ff,
79     UFSTAT_S5PV210_Tx_COUNT_MASK = 0x00ff0000,
80     UFSTAT_S5PV210_RxFULL        = 0x00000100,
81     UFSTAT_S5PV210_TxFULL        = 0x01000000,
82   };
83
84
85   void Uart_s3c::fifo_reset()
86   {
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)))
90       ;
91   }
92
93
94   bool Uart_s3c::startup(Io_register_block const *regs)
95   {
96     _regs = regs;
97
98     fifo_reset();
99 #if 0
100     _regs->write<unsigned int>(UMCON, 0);
101 #endif
102
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);
106
107     switch (type())
108       {
109       case Type_24xx:
110         break;
111       case Type_64xx:
112       case Type_s5pv210:
113         _regs->write<unsigned int>(UINTM, ~UINT_RXD); // mask all but receive irq
114         _regs->write<unsigned int>(UINTP, ~0); // clear all pending irqs
115         break;
116       }
117 #if 0
118     _regs->write<unsigned int>(UBRDIV, 0x23);
119 #endif
120
121     return true;
122   }
123
124   void Uart_s3c::shutdown()
125   {
126     // more
127   }
128
129   bool Uart_s3c::change_mode(Transfer_mode, Baud_rate r)
130   {
131     if (r != 115200)
132       return false;
133
134 #if 0
135     _regs->write<unsigned int>(ULCON, ULCON_8N1_MODE);
136     _regs->write<unsigned int>(UCON,  UCON_MODE);
137     _regs->write<unsigned int>(UFCON, 1);
138
139     _regs->write<unsigned int>(UBRDIV, 0x23);
140 #endif
141
142     return true;
143   }
144
145   int Uart_s3c::get_char(bool blocking) const
146   {
147     while (!char_avail())
148       if (!blocking)
149         return -1;
150
151     _regs->read<unsigned int>(UFCON);
152     int c = _regs->read<unsigned int>(URXH) & 0xff;
153     ack_rx_irq();
154     return c;
155   }
156
157   int Uart_s3c::char_avail() const
158   {
159     return is_rx_fifo_non_empty();
160   }
161
162   void Uart_s3c::out_char(char c) const
163   {
164     wait_for_non_full_tx_fifo();
165     _regs->write<unsigned int>(UTXH, c);
166   }
167
168   int Uart_s3c::write(char const *s, unsigned long count) const
169   {
170     unsigned long c = count;
171     while (c--)
172       out_char(*s++);
173     wait_for_empty_tx_fifo();
174
175     return count;
176   }
177
178   // -----------------------
179
180   void Uart_s3c2410::wait_for_empty_tx_fifo() const
181   {
182     Poll_timeout_counter i(3000000);
183     while (i.test(_regs->read<unsigned int>(UFSTAT) & (UFSTAT_2410_Tx_COUNT_MASK | UFSTAT_2410_TxFULL)))
184       ;
185   }
186
187   void Uart_s3c2410::wait_for_non_full_tx_fifo() const
188   {
189     Poll_timeout_counter i(3000000);
190     while (i.test(_regs->read<unsigned int>(UFSTAT) & UFSTAT_2410_TxFULL))
191       ;
192   }
193
194   unsigned Uart_s3c2410::is_rx_fifo_non_empty() const
195   {
196     return _regs->read<unsigned int>(UFSTAT) & (UFSTAT_2410_Rx_COUNT_MASK | UFSTAT_2410_RxFULL);
197   }
198
199   void Uart_s3c2410::auto_flow_control(bool on)
200   {
201     _regs->write<unsigned int>(UMCON, (_regs->read<unsigned int>(UMCON) & ~UMCON_AFC) | (on ? UMCON_AFC : 0));
202   }
203
204   // -----------------------
205
206   void Uart_s3c64xx::wait_for_empty_tx_fifo() const
207   {
208     Poll_timeout_counter i(3000000);
209     while (i.test(_regs->read<unsigned int>(UFSTAT) & (UFSTAT_64XX_Tx_COUNT_MASK | UFSTAT_64XX_TxFULL)))
210       ;
211   }
212
213   void Uart_s3c64xx::wait_for_non_full_tx_fifo() const
214   {
215     Poll_timeout_counter i(3000000);
216     while (i.test(_regs->read<unsigned int>(UFSTAT) & UFSTAT_64XX_TxFULL))
217       ;
218   }
219
220   unsigned Uart_s3c64xx::is_rx_fifo_non_empty() const
221   {
222     return _regs->read<unsigned int>(UFSTAT) & (UFSTAT_64XX_Rx_COUNT_MASK | UFSTAT_64XX_RxFULL);
223   }
224
225   void Uart_s3c64xx::ack_rx_irq() const
226   {
227     _regs->write<unsigned int>(UINTP, UINT_RXD);
228   }
229
230   // -----------------------
231
232   void Uart_s5pv210::wait_for_empty_tx_fifo() const
233   {
234     Poll_timeout_counter i(3000000);
235     while (i.test(_regs->read<unsigned int>(UFSTAT) & (UFSTAT_S5PV210_Tx_COUNT_MASK | UFSTAT_S5PV210_TxFULL)))
236       ;
237   }
238
239   void Uart_s5pv210::wait_for_non_full_tx_fifo() const
240   {
241     Poll_timeout_counter i(3000000);
242     while (i.test(_regs->read<unsigned int>(UFSTAT) & UFSTAT_S5PV210_TxFULL))
243       ;
244   }
245
246   unsigned Uart_s5pv210::is_rx_fifo_non_empty() const
247   {
248     return _regs->read<unsigned int>(UFSTAT) & (UFSTAT_S5PV210_Rx_COUNT_MASK | UFSTAT_S5PV210_RxFULL);
249   }
250
251   void Uart_s5pv210::ack_rx_irq() const
252   {
253     _regs->write<unsigned int>(UINTP, UINT_RXD);
254   }
255 };
256