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