]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/drivers-frst/uart/src/uart_pl011.cc
update
[l4.git] / l4 / pkg / drivers-frst / uart / src / uart_pl011.cc
1 /*
2  * (c) 2009-2012 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_pl011.h"
10 #include "poll_timeout_counter.h"
11
12 namespace L4
13 {
14   enum {
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,
22
23     UART011_RXIS = 1 << 4,
24     UART011_RTIS = 1 << 6,
25
26     UART011_RXIC = 1 << 4,
27     UART011_RTIC = 1 << 6,
28
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
33
34     UART01x_FR_BUSY   = 0x008,
35     UART01x_FR_RXFE   = 0x010,
36     UART01x_FR_TXFF   = 0x020,
37
38     UART01x_LCRH_PEN    = 0x02, // parity enable
39     UART01x_LCRH_FEN    = 0x10, // FIFO enable
40     UART01x_LCRH_WLEN_8 = 0x60,
41
42     UART01x_DR   = 0x00,
43     UART011_ECR  = 0x04,
44     UART01x_FR   = 0x18,
45     UART011_IBRD = 0x24,
46     UART011_FBRD = 0x28,
47     UART011_LCRH = 0x2c,
48     UART011_CR   = 0x30,
49     UART011_IMSC = 0x38,
50     UART011_MIS  = 0x40,
51     UART011_ICR  = 0x44,
52
53     Default_baud = 115200,
54   };
55
56   bool Uart_pl011::startup(Io_register_block const *regs)
57   {
58     _regs = 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)
67       ;
68     return true;
69   }
70
71   void Uart_pl011::shutdown()
72   {
73     _regs->write<unsigned int>(UART011_IMSC, 0);
74     _regs->write<unsigned int>(UART011_ICR, 0xffff);
75     _regs->write<unsigned int>(UART011_CR, 0);
76   }
77
78   bool Uart_pl011::enable_rx_irq(bool enable)
79   {
80     unsigned long mask = UART011_RXIM | UART011_RTIM;
81
82     _regs->write<unsigned int>(UART011_ICR, 0xffff & ~mask);
83     _regs->write<unsigned int>(UART011_ECR, 0xff);
84     if (enable)
85       _regs->write<unsigned int>(UART011_IMSC, _regs->read<unsigned int>(UART011_IMSC) | mask);
86     else
87       _regs->write<unsigned int>(UART011_IMSC, _regs->read<unsigned int>(UART011_IMSC) & ~mask);
88     return true;
89   }
90
91   bool Uart_pl011::change_mode(Transfer_mode, Baud_rate r)
92   {
93     unsigned long old_cr = _regs->read<unsigned int>(UART011_CR);
94     _regs->write<unsigned int>(UART011_CR, 0);
95
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);
100
101     _regs->write<unsigned int>(UART011_CR, old_cr);
102
103     return true;
104   }
105
106   int Uart_pl011::get_char(bool blocking) const
107   {
108     while (!char_avail())
109       if (!blocking)
110         return -1;
111
112     //_regs->write(UART011_ICR, UART011_RXIC | UART011_RTIC);
113
114     int c = _regs->read<unsigned int>(UART01x_DR);
115     _regs->write<unsigned int>(UART011_ECR, 0xff);
116     return c;
117   }
118
119   int Uart_pl011::char_avail() const
120   {
121     return !(_regs->read<unsigned int>(UART01x_FR) & UART01x_FR_RXFE);
122   }
123
124   void Uart_pl011::out_char(char c) const
125   {
126     Poll_timeout_counter i(3000000);
127     while (i.test(_regs->read<unsigned int>(UART01x_FR) & UART01x_FR_TXFF))
128       ;
129     _regs->write<unsigned int>(UART01x_DR,c);
130   }
131
132   int Uart_pl011::write(char const *s, unsigned long count) const
133   {
134     unsigned long c = count;
135     while (c--)
136       out_char(*s++);
137
138     Poll_timeout_counter i(3000000);
139     while (i.test(_regs->read<unsigned int>(UART01x_FR) & UART01x_FR_BUSY))
140       ;
141
142     return count;
143   }
144 };