1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49#include <common.h>
50#include <watchdog.h>
51#include <asm/io.h>
52#include <asm/ibmpc.h>
53
54#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
55#include <malloc.h>
56#endif
57
58DECLARE_GLOBAL_DATA_PTR;
59
60#define UART_RBR 0x00
61#define UART_THR 0x00
62#define UART_IER 0x01
63#define UART_IIR 0x02
64#define UART_FCR 0x02
65#define UART_LCR 0x03
66#define UART_MCR 0x04
67#define UART_LSR 0x05
68#define UART_MSR 0x06
69#define UART_SCR 0x07
70#define UART_DLL 0x00
71#define UART_DLM 0x01
72
73
74
75
76#define asyncLSRDataReady1 0x01
77#define asyncLSROverrunError1 0x02
78#define asyncLSRParityError1 0x04
79#define asyncLSRFramingError1 0x08
80#define asyncLSRBreakInterrupt1 0x10
81#define asyncLSRTxHoldEmpty1 0x20
82#define asyncLSRTxShiftEmpty1 0x40
83#define asyncLSRRxFifoError1 0x80
84
85
86#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
87
88
89
90typedef struct {
91 char *rx_buffer;
92 ulong rx_put;
93 ulong rx_get;
94 int cts;
95} serial_buffer_t;
96
97volatile serial_buffer_t buf_info;
98static int serial_buffer_active=0;
99#endif
100
101
102static int serial_div(int baudrate)
103{
104
105 switch (baudrate) {
106 case 1200:
107 return 96;
108 case 9600:
109 return 12;
110 case 19200:
111 return 6;
112 case 38400:
113 return 3;
114 case 57600:
115 return 2;
116 case 115200:
117 return 1;
118 }
119
120 return 12;
121}
122
123
124
125
126
127
128
129int serial_init(void)
130{
131 volatile char val;
132 int bdiv = serial_div(gd->baudrate);
133
134 outb(0x80, UART0_BASE + UART_LCR);
135 outb(bdiv, UART0_BASE + UART_DLL);
136 outb(bdiv >> 8, UART0_BASE + UART_DLM);
137 outb(0x03, UART0_BASE + UART_LCR);
138 outb(0x01, UART0_BASE + UART_FCR);
139 outb(0x0b, UART0_BASE + UART_MCR);
140 val = inb(UART0_BASE + UART_LSR);
141 val = inb(UART0_BASE + UART_RBR);
142 outb(0x00, UART0_BASE + UART_SCR);
143 outb(0x00, UART0_BASE + UART_IER);
144
145 return 0;
146}
147
148
149void serial_setbrg(void)
150{
151 unsigned short bdiv;
152
153 bdiv = serial_div(gd->baudrate);
154
155 outb(0x80, UART0_BASE + UART_LCR);
156 outb(bdiv&0xff, UART0_BASE + UART_DLL);
157 outb(bdiv >> 8, UART0_BASE + UART_DLM);
158 outb(0x03, UART0_BASE + UART_LCR);
159}
160
161
162void serial_putc(const char c)
163{
164 int i;
165
166 if (c == '\n')
167 serial_putc ('\r');
168
169
170 for (i = 1; i < 3500; i++) {
171 if ((inb (UART0_BASE + UART_LSR) & 0x20) == 0x20) {
172 break;
173 }
174 udelay(100);
175 }
176 outb(c, UART0_BASE + UART_THR);
177}
178
179
180void serial_puts(const char *s)
181{
182 while (*s) {
183 serial_putc(*s++);
184 }
185}
186
187
188int serial_getc(void)
189{
190 unsigned char status = 0;
191
192#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
193 if (serial_buffer_active) {
194 return serial_buffered_getc();
195 }
196#endif
197
198 while (1) {
199#if defined(CONFIG_HW_WATCHDOG)
200 WATCHDOG_RESET();
201#endif
202 status = inb(UART0_BASE + UART_LSR);
203 if ((status & asyncLSRDataReady1) != 0x0) {
204 break;
205 }
206 if ((status & ( asyncLSRFramingError1 |
207 asyncLSROverrunError1 |
208 asyncLSRParityError1 |
209 asyncLSRBreakInterrupt1 )) != 0) {
210 outb(asyncLSRFramingError1 |
211 asyncLSROverrunError1 |
212 asyncLSRParityError1 |
213 asyncLSRBreakInterrupt1, UART0_BASE + UART_LSR);
214 }
215 }
216 return (0x000000ff & (int) inb (UART0_BASE));
217}
218
219
220int serial_tstc(void)
221{
222 unsigned char status;
223
224#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
225 if (serial_buffer_active) {
226 return serial_buffered_tstc();
227 }
228#endif
229
230 status = inb(UART0_BASE + UART_LSR);
231 if ((status & asyncLSRDataReady1) != 0x0) {
232 return (1);
233 }
234 if ((status & ( asyncLSRFramingError1 |
235 asyncLSROverrunError1 |
236 asyncLSRParityError1 |
237 asyncLSRBreakInterrupt1 )) != 0) {
238 outb(asyncLSRFramingError1 |
239 asyncLSROverrunError1 |
240 asyncLSRParityError1 |
241 asyncLSRBreakInterrupt1, UART0_BASE + UART_LSR);
242 }
243 return 0;
244}
245
246
247#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
248
249void serial_isr(void *arg)
250{
251 int space;
252 int c;
253 int rx_put = buf_info.rx_put;
254
255 if (buf_info.rx_get <= rx_put) {
256 space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - buf_info.rx_get);
257 } else {
258 space = buf_info.rx_get - rx_put;
259 }
260
261 while (inb(UART0_BASE + UART_LSR) & 1) {
262 c = inb(UART0_BASE);
263 if (space) {
264 buf_info.rx_buffer[rx_put++] = c;
265 space--;
266
267 if (rx_put == buf_info.rx_get) {
268 buf_info.rx_get++;
269 if (rx_put == CONFIG_SERIAL_SOFTWARE_FIFO) {
270 buf_info.rx_get = 0;
271 }
272 }
273
274 if (rx_put == CONFIG_SERIAL_SOFTWARE_FIFO) {
275 rx_put = 0;
276 if (0 == buf_info.rx_get) {
277 buf_info.rx_get = 1;
278 }
279
280 }
281
282 }
283 if (space < CONFIG_SERIAL_SOFTWARE_FIFO / 4) {
284
285 outb(inb(UART0_BASE + UART_MCR) & (0xFF ^ 0x02),
286 UART0_BASE + UART_MCR);
287 }
288 }
289 buf_info.rx_put = rx_put;
290}
291
292void serial_buffered_init(void)
293{
294 serial_puts ("Switching to interrupt driven serial input mode.\n");
295 buf_info.rx_buffer = malloc (CONFIG_SERIAL_SOFTWARE_FIFO);
296 buf_info.rx_put = 0;
297 buf_info.rx_get = 0;
298
299 if (inb (UART0_BASE + UART_MSR) & 0x10) {
300 serial_puts ("Check CTS signal present on serial port: OK.\n");
301 buf_info.cts = 1;
302 } else {
303 serial_puts ("WARNING: CTS signal not present on serial port.\n");
304 buf_info.cts = 0;
305 }
306
307 irq_install_handler ( VECNUM_U0 ,
308 serial_isr ,
309 (void *) &buf_info );
310
311
312
313 outb(0x01, UART0_BASE + UART_IER);
314
315
316 outb(inb (UART0_BASE + UART_MCR) | 0x0b, UART0_BASE + UART_MCR);
317
318
319 outb( 1, UART0_BASE + UART_FCR);
320
321 serial_buffer_active = 1;
322}
323
324void serial_buffered_putc (const char c)
325{
326 int i;
327
328#if defined(CONFIG_HW_WATCHDOG)
329 while (!(inb (UART0_BASE + UART_MSR) & 0x10))
330 WATCHDOG_RESET ();
331#else
332 if (buf_info.cts) {
333 for (i=0;i<1000;i++) {
334 if ((inb (UART0_BASE + UART_MSR) & 0x10)) {
335 break;
336 }
337 }
338 if (i!=1000) {
339 buf_info.cts = 0;
340 }
341 } else {
342 if ((inb (UART0_BASE + UART_MSR) & 0x10)) {
343 buf_info.cts = 1;
344 }
345 }
346
347#endif
348 serial_putc (c);
349}
350
351void serial_buffered_puts(const char *s)
352{
353 serial_puts (s);
354}
355
356int serial_buffered_getc(void)
357{
358 int space;
359 int c;
360 int rx_get = buf_info.rx_get;
361 int rx_put;
362
363#if defined(CONFIG_HW_WATCHDOG)
364 while (rx_get == buf_info.rx_put)
365 WATCHDOG_RESET ();
366#else
367 while (rx_get == buf_info.rx_put);
368#endif
369 c = buf_info.rx_buffer[rx_get++];
370 if (rx_get == CONFIG_SERIAL_SOFTWARE_FIFO) {
371 rx_get = 0;
372 }
373 buf_info.rx_get = rx_get;
374
375 rx_put = buf_info.rx_put;
376 if (rx_get <= rx_put) {
377 space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - rx_get);
378 } else {
379 space = rx_get - rx_put;
380 }
381 if (space > CONFIG_SERIAL_SOFTWARE_FIFO / 2) {
382
383 outb(inb (UART0_BASE + UART_MCR) | 0x02, UART0_BASE + UART_MCR);
384 }
385
386 return c;
387}
388
389int serial_buffered_tstc(void)
390{
391 return (buf_info.rx_get != buf_info.rx_put) ? 1 : 0;
392}
393
394#endif
395
396
397#if defined(CONFIG_CMD_KGDB)
398
399
400
401
402
403
404
405
406#if (CONFIG_KGDB_SER_INDEX & 2)
407void kgdb_serial_init(void)
408{
409 volatile char val;
410 bdiv = serial_div (CONFIG_KGDB_BAUDRATE);
411
412
413
414
415 outb(0x80, UART1_BASE + UART_LCR);
416 outb((bdiv & 0xff), UART1_BASE + UART_DLL);
417 outb((bdiv >> 8 ), UART1_BASE + UART_DLM);
418 outb(0x03, UART1_BASE + UART_LCR);
419 outb(0x00, UART1_BASE + UART_FCR);
420 outb(0x00, UART1_BASE + UART_MCR);
421 val = inb(UART1_BASE + UART_LSR);
422 val = inb(UART1_BASE + UART_RBR);
423 outb(0x00, UART1_BASE + UART_SCR);
424 outb(0x00, UART1_BASE + UART_IER);
425}
426
427
428void putDebugChar(const char c)
429{
430 if (c == '\n')
431 serial_putc ('\r');
432
433 outb(c, UART1_BASE + UART_THR);
434
435
436 while ((inb(UART1_BASE + UART_LSR) & 0x20) != 0x20);
437}
438
439
440void putDebugStr(const char *s)
441{
442 while (*s) {
443 serial_putc(*s++);
444 }
445}
446
447
448int getDebugChar(void)
449{
450 unsigned char status = 0;
451
452 while (1) {
453 status = inb(UART1_BASE + UART_LSR);
454 if ((status & asyncLSRDataReady1) != 0x0) {
455 break;
456 }
457 if ((status & ( asyncLSRFramingError1 |
458 asyncLSROverrunError1 |
459 asyncLSRParityError1 |
460 asyncLSRBreakInterrupt1 )) != 0) {
461 outb(asyncLSRFramingError1 |
462 asyncLSROverrunError1 |
463 asyncLSRParityError1 |
464 asyncLSRBreakInterrupt1, UART1_BASE + UART_LSR);
465 }
466 }
467 return (0x000000ff & (int) inb(UART1_BASE));
468}
469
470
471void kgdb_interruptible(int yes)
472{
473 return;
474}
475
476#else
477
478void kgdb_serial_init(void)
479{
480 serial_printf ("[on serial] ");
481}
482
483void putDebugChar(int c)
484{
485 serial_putc (c);
486}
487
488void putDebugStr(const char *str)
489{
490 serial_puts (str);
491}
492
493int getDebugChar(void)
494{
495 return serial_getc ();
496}
497
498void kgdb_interruptible(int yes)
499{
500 return;
501}
502#endif
503#endif
504