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