]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/drivers/arm/uart-sa1100.cpp
Some minor fixes.
[l4.git] / kernel / fiasco / src / drivers / arm / uart-sa1100.cpp
1 INTERFACE [sa1100]:
2
3 #include "types.h"
4
5 EXTENSION class Uart
6 {
7 public:
8
9   bool startup(Address address, unsigned irq);
10
11   enum {
12     PAR_NONE = 0x00,
13     PAR_EVEN = 0x03,
14     PAR_ODD  = 0x01,
15     DAT_5    = (unsigned)-1,
16     DAT_6    = (unsigned)-1,
17     DAT_7    = 0x00,
18     DAT_8    = 0x08,
19     STOP_1   = 0x00,
20     STOP_2   = 0x04,
21
22     MODE_8N1 = PAR_NONE | DAT_8 | STOP_1,
23     MODE_7E1 = PAR_EVEN | DAT_7 | STOP_1,
24
25   // these two values are to leave either mode
26   // or baud rate unchanged on a call to change_mode
27     MODE_NC  = 0x1000000,
28     BAUD_NC  = 0x1000000,
29
30   };
31
32 private:
33   Address address;
34   unsigned _irq;
35   enum {
36     UTCR0_PE  = 0x01,
37     UTCR0_OES = 0x02,
38     UTCR0_SBS = 0x04,
39     UTCR0_DSS = 0x08,
40     UTCR0_SCE = 0x10,
41     UTCR0_RCE = 0x20,
42     UTCR0_TCE = 0x40,
43
44     UTCR3_RXE = 0x01,
45     UTCR3_TXE = 0x02,
46     UTCR3_BRK = 0x04,
47     UTCR3_RIE = 0x08,
48     UTCR3_TIE = 0x10,
49     UTCR3_LBM = 0x20,
50
51
52     UTSR0_TFS = 0x01,
53     UTSR0_RFS = 0x02,
54     UTSR0_RID = 0x04,
55     UTSR0_RBB = 0x08,
56     UTSR0_REB = 0x10,
57     UTSR0_EIF = 0x20,
58
59     UTSR1_TBY = 0x01,
60     UTSR1_RNE = 0x02,
61     UTSR1_TNF = 0x04,
62     UTSR1_PRE = 0x08,
63     UTSR1_FRE = 0x10,
64     UTSR1_ROR = 0x20,
65
66     UARTCLK = 3686400,
67   };
68
69 };
70
71 //---------------------------------------------------------------------------
72 IMPLEMENTATION [sa1100]:
73
74 #include <cassert>
75 #include "processor.h"
76
77 PRIVATE INLINE static Address Uart::_utcr0(Address a)
78 { return a; }
79
80 PRIVATE INLINE static Address Uart::_utcr1(Address a)
81 { return (a+0x04); }
82
83 PRIVATE INLINE static Address Uart::_utcr2(Address a)
84 { return (a+0x08); }
85
86 PRIVATE INLINE static Address Uart::_utcr3(Address a)
87 { return (a+0x0c); }
88
89 PRIVATE INLINE static Address Uart::_utcr4(Address a)
90 { return (a+0x10); }
91
92 PRIVATE INLINE static Address Uart::_utdr(Address a)
93 { return (a+0x14); }
94
95 PRIVATE INLINE static Address Uart::_utsr0(Address a)
96 { return (a+0x1c); }
97
98 PRIVATE INLINE static Address Uart::_utsr1(Address a)
99 { return (a+0x20); }
100
101
102 PRIVATE INLINE NEEDS[Uart::_utcr0]
103 unsigned Uart::utcr0()  const
104 { return *((volatile unsigned*)(_utcr0(address))); }
105
106 PRIVATE INLINE NEEDS[Uart::_utcr1]
107 unsigned Uart::utcr1()  const
108 { return *((volatile unsigned*)(_utcr1(address))); }
109
110 PRIVATE INLINE NEEDS[Uart::_utcr2]
111 unsigned Uart::utcr2()  const
112 { return *((volatile unsigned*)(_utcr2(address))); }
113
114 PRIVATE INLINE NEEDS[Uart::_utcr3]
115 unsigned Uart::utcr3()  const
116 { return *((volatile unsigned*)(_utcr3(address))); }
117
118 PRIVATE INLINE NEEDS[Uart::_utcr4]
119 unsigned Uart::utcr4()  const
120 { return *((volatile unsigned*)(_utcr4(address))); }
121
122 PRIVATE INLINE NEEDS[Uart::_utdr]
123 unsigned Uart::utdr()  const
124 { return *((volatile unsigned*)(_utdr(address))); }
125
126 PRIVATE INLINE NEEDS[Uart::_utsr0]
127 unsigned Uart::utsr0()  const
128 { return *((volatile unsigned*)(_utsr0(address))); }
129
130 PRIVATE INLINE NEEDS[Uart::_utsr1]
131 unsigned Uart::utsr1()  const
132 { return *((volatile unsigned*)(_utsr1(address))); }
133
134
135 PRIVATE INLINE NEEDS[Uart::_utcr0]
136 void Uart::utcr0(unsigned v)
137 { *((volatile unsigned*)(_utcr0(address)))= v; }
138
139 PRIVATE INLINE NEEDS[Uart::_utcr1]
140 void Uart::utcr1(unsigned v)
141 { *((volatile unsigned*)(_utcr1(address)))= v; }
142
143 PRIVATE INLINE NEEDS[Uart::_utcr2]
144 void Uart::utcr2(unsigned v)
145 { *((volatile unsigned*)(_utcr2(address)))= v; }
146
147 PRIVATE INLINE NEEDS[Uart::_utcr3]
148 void Uart::utcr3(unsigned v)
149 { *((volatile unsigned*)(_utcr3(address)))= v; }
150
151 PRIVATE INLINE NEEDS[Uart::_utcr4]
152 void Uart::utcr4(unsigned v)
153 { *((volatile unsigned*)(_utcr4(address)))= v; }
154
155 PRIVATE INLINE NEEDS[Uart::_utdr]
156 void Uart::utdr(unsigned v)
157 { *((volatile unsigned*)(_utdr(address)))= v; }
158
159 PRIVATE INLINE NEEDS[Uart::_utsr0]
160 void Uart::utsr0(unsigned v)
161 { *((volatile unsigned*)(_utsr0(address)))= v; }
162
163 PRIVATE INLINE NEEDS[Uart::_utsr1]
164 void Uart::utsr1(unsigned v)
165 { *((volatile unsigned*)(_utsr1(address)))= v; }
166
167
168 IMPLEMENT Uart::Uart() : Console(DISABLED)
169 {
170   address = (unsigned)-1;
171   _irq = (unsigned)-1;
172 }
173
174 IMPLEMENT Uart::~Uart()
175 {
176   utcr3(0);
177 }
178
179
180 IMPLEMENT bool Uart::startup(Address _address, unsigned irq)
181 {
182   address =_address;
183   _irq = irq;
184   utsr0((unsigned)-1); //clear pending status bits
185   utcr3(UTCR3_RXE | UTCR3_TXE); //enable transmitter and receiver
186   add_state(ENABLED);
187   return true;
188 }
189
190 IMPLEMENT void Uart::shutdown()
191 {
192   utcr3(0);
193 }
194
195
196 IMPLEMENT bool Uart::change_mode(TransferMode m, BaudRate baud)
197 {
198   unsigned old_utcr3, quot;
199   Proc::Status st;
200   if(baud == (BaudRate)-1)
201     return false;
202   if(baud != BAUD_NC && (baud>115200 || baud<96))
203     return false;
204   if(m == (TransferMode)-1)
205     return false;
206
207   st = Proc::cli_save();
208   old_utcr3 = utcr3();
209   utcr3(old_utcr3 & ~(UTCR3_RIE|UTCR3_TIE));
210   Proc::sti_restore(st);
211
212   while(utsr1() & UTSR1_TBY);
213
214   /* disable all */
215   utcr3(0);
216
217   /* set parity, data size, and stop bits */
218   if(m!=MODE_NC)
219     utcr0(m & 0x0ff); 
220
221   /* set baud rate */
222   if(baud!=BAUD_NC) 
223     {
224       quot = (UARTCLK / (16*baud)) -1;
225       utcr1((quot & 0xf00) >> 8);
226       utcr2(quot & 0x0ff);
227     }
228
229   utsr0((unsigned)-1);
230
231   utcr3(old_utcr3);
232   return true;
233 }
234
235 PUBLIC bool Uart::tx_empty()
236 {
237   return !(utsr1() & UTSR1_TBY);
238 }
239
240
241 IMPLEMENT
242 int Uart::write(const char *s, size_t count)
243 {
244   unsigned old_utcr3;
245   Proc::Status st;
246   st = Proc::cli_save();
247   old_utcr3 = utcr3();
248   utcr3((old_utcr3 & ~(UTCR3_RIE|UTCR3_TIE)) | UTCR3_TXE);
249
250   /* transmission */
251   for(unsigned i =0; i<count; i++)
252     {
253       while(!(utsr1() & UTSR1_TNF))
254         ;
255       utdr(s[i]);
256       if( s[i]=='\n' )
257         {
258           while(!(utsr1() & UTSR1_TNF))
259             ;
260           utdr('\r');
261         }
262     }
263
264   /* wait till everything is transmitted */
265   while(utsr1() & UTSR1_TBY)
266     ;
267
268   utcr3(old_utcr3);
269   Proc::sti_restore(st);
270   return 1;
271 }
272
273 IMPLEMENT
274 int Uart::getchar(bool blocking)
275 {
276   unsigned old_utcr3, ch;
277
278   old_utcr3 = utcr3();
279   utcr3(old_utcr3 & ~(UTCR3_RIE|UTCR3_TIE));
280   while(!(utsr1() & UTSR1_RNE))
281     if(!blocking)
282       return -1;
283
284   ch = utdr();
285   utsr0(0x04); // clear RID
286   utcr3(old_utcr3);
287   return ch;
288 }
289
290
291 IMPLEMENT
292 int Uart::char_avail() const
293 {
294   if((utsr1() & UTSR1_RNE))
295     {
296       return 1;
297     }
298   else
299     return 0;
300 }
301
302
303 IMPLEMENT inline
304 int Uart::irq() const
305 {
306   return (int)_irq;
307 }
308
309 IMPLEMENT inline NEEDS[Uart::utcr3]
310 void Uart::enable_rcv_irq()
311 {
312   utcr3(utcr3() | UTCR3_RIE);
313 }
314
315 IMPLEMENT inline NEEDS[Uart::utcr3]
316 void Uart::disable_rcv_irq()
317 {
318   utcr3(utcr3() & ~UTCR3_RIE);
319 }
320