]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/drivers-frst/uart/src/uart_cadence.cc
update
[l4.git] / l4 / pkg / drivers-frst / uart / src / uart_cadence.cc
1 /*
2  * (c) 2013 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_cadence.h"
10 #include "poll_timeout_counter.h"
11
12 namespace L4
13 {
14   enum
15   {
16     CR                       = 0x00,
17     MR                       = 0x04,
18     IER                      = 0x08,
19     IDR                      = 0x0C,
20     IMR                      = 0x10,
21     ISR                      = 0x14,
22     BAUDGEN                  = 0x18,
23     RXTOUT                   = 0x1C,
24     RXWM                     = 0x20,
25     MODEMCR                  = 0x24,
26     MODEMSR                  = 0x28,
27     SR                       = 0x2C,
28     FIFO                     = 0x30,
29     Baud_rate_divider_reg0   = 0x34,
30     Flow_delay_reg0          = 0x38,
31     Tx_FIFO_trigger_level0   = 0x44,
32   };
33
34   namespace Ctrl
35   {
36     enum {
37       Rxres = 1 << 0,
38       Txres = 1 << 1,
39       Rxen  = 1 << 2,
40       Rxdis = 1 << 3,
41       Txen  = 1 << 4,
42       Txdis = 1 << 5,
43       Rstto = 1 << 6,
44     };
45   };
46
47   enum
48   {
49     IXR_TXFULL  = 1 << 4,
50     IXR_TXEMPTY = 1 << 3,
51     IXR_RXFULL  = 1 << 2,
52     IXR_RXEMPTY = 1 << 1,
53     IXR_RXOVR   = 1 << 0,
54   };
55
56   bool Uart_cadence::startup(Io_register_block const *regs)
57   {
58     _regs = regs;
59     _regs->write<unsigned>(CR, Ctrl::Txres | Ctrl::Rxres);
60     change_mode(0, 115200);
61     _regs->write<unsigned>(CR, Ctrl::Rxen | Ctrl::Txen);
62     return true;
63   }
64
65   bool Uart_cadence::enable_rx_irq(bool enable)
66   {
67     _regs->write<unsigned>(RXWM, 1);
68     _regs->write<unsigned>(ISR, ~0U);
69     _regs->write<unsigned>(IER, enable ? IXR_RXOVR : 0);
70     return true;
71   }
72
73   void Uart_cadence::shutdown()
74   {
75     _regs->write<unsigned>(CR, Ctrl::Rxdis | Ctrl::Txdis);
76   }
77
78   bool Uart_cadence::change_mode(Transfer_mode, Baud_rate r)
79   {
80     unsigned div = 4;
81     _regs->write<unsigned>(Baud_rate_divider_reg0, div);
82     _regs->write<unsigned>(BAUDGEN, 50000000 / r / (div + 1));
83     _regs->write<unsigned>(MR, 0x20); // 8N1
84     return true;
85   }
86
87   int Uart_cadence::get_char(bool blocking) const
88   {
89     while (!char_avail())
90       if (!blocking)
91         return -1;
92
93     _regs->write<unsigned>(ISR, IXR_RXOVR);
94     return _regs->read<unsigned>(FIFO);
95   }
96
97   int Uart_cadence::char_avail() const
98   {
99     return !(_regs->read<unsigned>(SR) & IXR_RXEMPTY);
100   }
101
102   void Uart_cadence::out_char(char c) const
103   {
104     // check for some free fifo space
105     Poll_timeout_counter i(3000000);
106     while (i.test(_regs->read<unsigned>(SR) & IXR_TXFULL))
107       ;
108
109     _regs->write<unsigned>(FIFO, c);
110   }
111
112   int Uart_cadence::write(char const *s, unsigned long count) const
113   {
114     unsigned long c = count;
115     while (c--)
116       out_char(*s++);
117
118     return count;
119   }
120 };