]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/lib/uart/uart_pl011.cc
update
[l4.git] / kernel / fiasco / src / lib / uart / uart_pl011.cc
1 #include "uart_pl011.h"
2 #include "poll_timeout_counter.h"
3
4 namespace L4
5 {
6   enum {
7     UART011_RXIM = 1 << 4,
8     UART011_TXIM = 1 << 5,
9     UART011_RTIM = 1 << 6,
10     UART011_FEIM = 1 << 7,
11     UART011_PEIM = 1 << 8,
12     UART011_BEIM = 1 << 9,
13     UART011_OEIM = 1 << 10,
14
15     UART011_RXIS = 1 << 4,
16     UART011_RTIS = 1 << 6,
17
18     UART011_RXIC = 1 << 4,
19     UART011_RTIC = 1 << 6,
20
21     UART01x_CR_UARTEN = 1, // UART enable
22     UART011_CR_LBE    = 0x080, // loopback enable
23     UART011_CR_TXE    = 0x100, // transmit enable
24     UART011_CR_RXE    = 0x200, // receive enable
25
26     UART01x_FR_BUSY   = 0x008,
27     UART01x_FR_RXFE   = 0x010,
28     UART01x_FR_TXFF   = 0x020,
29
30     UART01x_LCRH_PEN    = 0x02, // parity enable
31     UART01x_LCRH_FEN    = 0x10, // FIFO enable
32     UART01x_LCRH_WLEN_8 = 0x60,
33
34     UART01x_DR   = 0x00,
35     UART011_ECR  = 0x04,
36     UART01x_FR   = 0x18,
37     UART011_IBRD = 0x24,
38     UART011_FBRD = 0x28,
39     UART011_LCRH = 0x2c,
40     UART011_CR   = 0x30,
41     UART011_IMSC = 0x38,
42     UART011_MIS  = 0x40,
43     UART011_ICR  = 0x44,
44
45     Default_baud = 115200,
46   };
47
48   bool Uart_pl011::startup(Io_register_block const *regs)
49   {
50     _regs = regs;
51     _regs->write<unsigned int>(UART011_CR, UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE);
52     unsigned fi_val = _freq * 4 / Default_baud;
53     _regs->write<unsigned int>(UART011_FBRD, fi_val & 0x3f);
54     _regs->write<unsigned int>(UART011_IBRD, fi_val >> 6);
55     _regs->write<unsigned int>(UART011_LCRH, UART01x_LCRH_WLEN_8);
56     _regs->write<unsigned int>(UART011_IMSC, 0);
57     Poll_timeout_counter i(3000000);
58     while (i.test() && _regs->read<unsigned int>(UART01x_FR) & UART01x_FR_BUSY)
59       ;
60     return true;
61   }
62
63   void Uart_pl011::shutdown()
64   {
65     _regs->write<unsigned int>(UART011_IMSC, 0);
66     _regs->write<unsigned int>(UART011_ICR, 0xffff);
67     _regs->write<unsigned int>(UART011_CR, 0);
68   }
69
70   bool Uart_pl011::enable_rx_irq(bool enable)
71   {
72     unsigned long mask = UART011_RXIM | UART011_RTIM;
73
74     _regs->write<unsigned int>(UART011_ICR, 0xffff & ~mask);
75     _regs->write<unsigned int>(UART011_ECR, 0xff);
76     if (enable)
77       _regs->write<unsigned int>(UART011_IMSC, _regs->read<unsigned int>(UART011_IMSC) | mask);
78     else
79       _regs->write<unsigned int>(UART011_IMSC, _regs->read<unsigned int>(UART011_IMSC) & ~mask);
80     return true;
81   }
82
83   bool Uart_pl011::change_mode(Transfer_mode, Baud_rate r)
84   {
85     unsigned long old_cr = _regs->read<unsigned int>(UART011_CR);
86     _regs->write<unsigned int>(UART011_CR, 0);
87
88     unsigned fi_val = _freq * 4 / r;
89     _regs->write<unsigned int>(UART011_FBRD, fi_val & 0x3f);
90     _regs->write<unsigned int>(UART011_IBRD, fi_val >> 6);
91     _regs->write<unsigned int>(UART011_LCRH, UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN);
92
93     _regs->write<unsigned int>(UART011_CR, old_cr);
94
95     return true;
96   }
97
98   int Uart_pl011::get_char(bool blocking) const
99   {
100     while (!char_avail())
101       if (!blocking)
102         return -1;
103
104     //_regs->write(UART011_ICR, UART011_RXIC | UART011_RTIC);
105
106     int c = _regs->read<unsigned int>(UART01x_DR);
107     _regs->write<unsigned int>(UART011_ECR, 0xff);
108     return c;
109   }
110
111   int Uart_pl011::char_avail() const
112   {
113     return !(_regs->read<unsigned int>(UART01x_FR) & UART01x_FR_RXFE);
114   }
115
116   void Uart_pl011::out_char(char c) const
117   {
118     Poll_timeout_counter i(3000000);
119     while (i.test(_regs->read<unsigned int>(UART01x_FR) & UART01x_FR_TXFF))
120       ;
121     _regs->write<unsigned int>(UART01x_DR,c);
122   }
123
124   int Uart_pl011::write(char const *s, unsigned long count) const
125   {
126     unsigned long c = count;
127     while (c--)
128       out_char(*s++);
129
130     Poll_timeout_counter i(3000000);
131     while (i.test(_regs->read<unsigned int>(UART01x_FR) & UART01x_FR_BUSY))
132       ;
133
134     return count;
135   }
136 };