3 * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
6 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
8 * See file CREDITS for list of people who contributed to this
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
26 /*------------------------------------------------------------------------------+ */
28 * This source code has been made available to you by IBM on an AS-IS
29 * basis. Anyone receiving this source is licensed under IBM
30 * copyrights to use it in any way he or she deems fit, including
31 * copying it, modifying it, compiling it, and redistributing it either
32 * with or without modifications. No license under IBM patents or
33 * patent applications is to be implied by the copyright license.
35 * Any user of this software should understand that IBM cannot provide
36 * technical support for this software and will not be responsible for
37 * any consequences resulting from the use of this software.
39 * Any person who transfers this source code or any derivative work
40 * must include the IBM copyright notice, this paragraph, and the
41 * preceding two paragraphs in the transferred software.
43 * COPYRIGHT I B M CORPORATION 1995
44 * LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
46 /*------------------------------------------------------------------------------- */
51 #include <asm/ibmpc.h>
53 #if CONFIG_SERIAL_SOFTWARE_FIFO
70 /*-----------------------------------------------------------------------------+
71 | Line Status Register.
72 +-----------------------------------------------------------------------------*/
73 #define asyncLSRDataReady1 0x01
74 #define asyncLSROverrunError1 0x02
75 #define asyncLSRParityError1 0x04
76 #define asyncLSRFramingError1 0x08
77 #define asyncLSRBreakInterrupt1 0x10
78 #define asyncLSRTxHoldEmpty1 0x20
79 #define asyncLSRTxShiftEmpty1 0x40
80 #define asyncLSRRxFifoError1 0x80
84 #if CONFIG_SERIAL_SOFTWARE_FIFO
85 /*-----------------------------------------------------------------------------+
87 +-----------------------------------------------------------------------------*/
94 volatile static serial_buffer_t buf_info;
98 static int serial_div (int baudrate )
120 * Minimal serial functions needed to use one of the SMC ports
121 * as serial console interface.
124 int serial_init (void)
126 DECLARE_GLOBAL_DATA_PTR;
130 int bdiv = serial_div(gd->baudrate);
133 outb(0x80, UART0_BASE + UART_LCR); /* set DLAB bit */
134 outb(bdiv, UART0_BASE + UART_DLL); /* set baudrate divisor */
135 outb(bdiv >> 8, UART0_BASE + UART_DLM);/* set baudrate divisor */
136 outb(0x03, UART0_BASE + UART_LCR); /* clear DLAB; set 8 bits, no parity */
137 outb(0x00, UART0_BASE + UART_FCR); /* disable FIFO */
138 outb(0x00, UART0_BASE + UART_MCR); /* no modem control DTR RTS */
139 val = inb(UART0_BASE + UART_LSR); /* clear line status */
140 val = inb(UART0_BASE + UART_RBR); /* read receive buffer */
141 outb(0x00, UART0_BASE + UART_SCR); /* set scratchpad */
142 outb(0x00, UART0_BASE + UART_IER); /* set interrupt enable reg */
148 void serial_setbrg (void)
150 DECLARE_GLOBAL_DATA_PTR;
154 bdiv = serial_div (gd->baudrate);
156 outb(0x80, UART0_BASE + UART_LCR); /* set DLAB bit */
157 outb(bdiv&0xff, UART0_BASE + UART_DLL); /* set baudrate divisor */
158 outb(bdiv >> 8, UART0_BASE + UART_DLM);/* set baudrate divisor */
159 outb(0x03, UART0_BASE + UART_LCR); /* clear DLAB; set 8 bits, no parity */
163 void serial_putc (const char c)
170 /* check THRE bit, wait for transmiter available */
171 for (i = 1; i < 3500; i++) {
172 if ((inb (UART0_BASE + UART_LSR) & 0x20) == 0x20)
176 outb(c, UART0_BASE + UART_THR); /* put character out */
180 void serial_puts (const char *s)
190 unsigned char status = 0;
193 #if defined(CONFIG_HW_WATCHDOG)
194 WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */
195 #endif /* CONFIG_HW_WATCHDOG */
196 status = inb (UART0_BASE + UART_LSR);
197 if ((status & asyncLSRDataReady1) != 0x0) {
200 if ((status & ( asyncLSRFramingError1 |
201 asyncLSROverrunError1 |
202 asyncLSRParityError1 |
203 asyncLSRBreakInterrupt1 )) != 0) {
204 outb(asyncLSRFramingError1 |
205 asyncLSROverrunError1 |
206 asyncLSRParityError1 |
207 asyncLSRBreakInterrupt1, UART0_BASE + UART_LSR);
210 return (0x000000ff & (int) inb (UART0_BASE));
216 unsigned char status;
218 status = inb (UART0_BASE + UART_LSR);
219 if ((status & asyncLSRDataReady1) != 0x0) {
222 if ((status & ( asyncLSRFramingError1 |
223 asyncLSROverrunError1 |
224 asyncLSRParityError1 |
225 asyncLSRBreakInterrupt1 )) != 0) {
226 outb(asyncLSRFramingError1 |
227 asyncLSROverrunError1 |
228 asyncLSRParityError1 |
229 asyncLSRBreakInterrupt1, UART0_BASE + UART_LSR);
235 #if CONFIG_SERIAL_SOFTWARE_FIFO
237 void serial_isr (void *arg)
241 const int rx_get = buf_info.rx_get;
242 int rx_put = buf_info.rx_put;
244 if (rx_get <= rx_put) {
245 space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - rx_get);
247 space = rx_get - rx_put;
249 while (serial_tstc ()) {
252 buf_info.rx_buffer[rx_put++] = c;
255 if (rx_put == CONFIG_SERIAL_SOFTWARE_FIFO)
257 if (space < CONFIG_SERIAL_SOFTWARE_FIFO / 4) {
258 /* Stop flow by setting RTS inactive */
259 outb(inb (UART0_BASE + UART_MCR) & (0xFF ^ 0x02),
260 UART0_BASE + UART_MCR);
263 buf_info.rx_put = rx_put;
266 void serial_buffered_init (void)
268 serial_puts ("Switching to interrupt driven serial input mode.\n");
269 buf_info.rx_buffer = malloc (CONFIG_SERIAL_SOFTWARE_FIFO);
273 if (inb (UART0_BASE + UART_MSR) & 0x10) {
274 serial_puts ("Check CTS signal present on serial port: OK.\n");
276 serial_puts ("WARNING: CTS signal not present on serial port.\n");
279 irq_install_handler ( VECNUM_U0 /*UART0 *//*int vec */ ,
280 serial_isr /*interrupt_handler_t *handler */ ,
281 (void *) &buf_info /*void *arg */ );
283 /* Enable "RX Data Available" Interrupt on UART */
284 /* outb(inb(UART0_BASE + UART_IER) |0x01, UART0_BASE + UART_IER); */
285 outb(0x01, UART0_BASE + UART_IER);
287 outb(inb (UART0_BASE + UART_MCR) | 0x01, UART0_BASE + UART_MCR);
288 /* Start flow by setting RTS active */
289 outb(inb (UART0_BASE + UART_MCR) | 0x02, UART0_BASE + UART_MCR);
290 /* Setup UART FIFO: RX trigger level: 4 byte, Enable FIFO */
291 outb((1 << 6) | 1, UART0_BASE + UART_FCR);
294 void serial_buffered_putc (const char c)
297 #if defined(CONFIG_HW_WATCHDOG)
298 while (!(inb (UART0_BASE + UART_MSR) & 0x10))
301 while (!(inb (UART0_BASE + UART_MSR) & 0x10));
306 void serial_buffered_puts (const char *s)
311 int serial_buffered_getc (void)
315 int rx_get = buf_info.rx_get;
318 #if defined(CONFIG_HW_WATCHDOG)
319 while (rx_get == buf_info.rx_put)
322 while (rx_get == buf_info.rx_put);
324 c = buf_info.rx_buffer[rx_get++];
325 if (rx_get == CONFIG_SERIAL_SOFTWARE_FIFO)
327 buf_info.rx_get = rx_get;
329 rx_put = buf_info.rx_put;
330 if (rx_get <= rx_put) {
331 space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - rx_get);
333 space = rx_get - rx_put;
335 if (space > CONFIG_SERIAL_SOFTWARE_FIFO / 2) {
336 /* Start flow by setting RTS active */
337 outb(inb (UART0_BASE + UART_MCR) | 0x02, UART0_BASE + UART_MCR);
343 int serial_buffered_tstc (void)
345 return (buf_info.rx_get != buf_info.rx_put) ? 1 : 0;
348 #endif /* CONFIG_SERIAL_SOFTWARE_FIFO */
351 #if (CONFIG_COMMANDS & CFG_CMD_KGDB)
353 AS HARNOIS : according to CONFIG_KGDB_SER_INDEX kgdb uses serial port
355 - if CONFIG_KGDB_SER_INDEX = 1 => serial port number 0 :
356 configuration has been already done
357 - if CONFIG_KGDB_SER_INDEX = 2 => serial port number 1 :
358 configure port 1 for serial I/O with rate = CONFIG_KGDB_BAUDRATE
360 #if (CONFIG_KGDB_SER_INDEX & 2)
361 void kgdb_serial_init (void)
363 DECLARE_GLOBAL_DATA_PTR;
366 bdiv = serial_div (CONFIG_KGDB_BAUDRATE);
369 * Init onboard 16550 UART
371 outb(0x80, UART1_BASE + UART_LCR); /* set DLAB bit */
372 outb(bdiv & 0xff), UART1_BASE + UART_DLL); /* set divisor for 9600 baud */
373 outb(bdiv >> 8), UART1_BASE + UART_DLM); /* set divisor for 9600 baud */
374 outb(0x03, UART1_BASE + UART_LCR); /* line control 8 bits no parity */
375 outb(0x00, UART1_BASE + UART_FCR); /* disable FIFO */
376 outb(0x00, UART1_BASE + UART_MCR); /* no modem control DTR RTS */
377 val = inb(UART1_BASE + UART_LSR); /* clear line status */
378 val = inb(UART1_BASE + UART_RBR); /* read receive buffer */
379 outb(0x00, UART1_BASE + UART_SCR); /* set scratchpad */
380 outb(0x00, UART1_BASE + UART_IER); /* set interrupt enable reg */
384 void putDebugChar (const char c)
389 outb(c, UART1_BASE + UART_THR); /* put character out */
391 /* check THRE bit, wait for transfer done */
392 while ((inb(UART1_BASE + UART_LSR) & 0x20) != 0x20);
396 void putDebugStr (const char *s)
404 int getDebugChar (void)
406 unsigned char status = 0;
409 status = inb(UART1_BASE + UART_LSR);
410 if ((status & asyncLSRDataReady1) != 0x0) {
413 if ((status & ( asyncLSRFramingError1 |
414 asyncLSROverrunError1 |
415 asyncLSRParityError1 |
416 asyncLSRBreakInterrupt1 )) != 0) {
417 outb(asyncLSRFramingError1 |
418 asyncLSROverrunError1 |
419 asyncLSRParityError1 |
420 asyncLSRBreakInterrupt1, UART1_BASE + UART_LSR);
423 return (0x000000ff & (int) inb(UART1_BASE));
427 void kgdb_interruptible (int yes)
432 #else /* ! (CONFIG_KGDB_SER_INDEX & 2) */
434 void kgdb_serial_init (void)
436 serial_printf ("[on serial] ");
439 void putDebugChar (int c)
444 void putDebugStr (const char *str)
449 int getDebugChar (void)
451 return serial_getc ();
454 void kgdb_interruptible (int yes)
458 #endif /* (CONFIG_KGDB_SER_INDEX & 2) */
459 #endif /* CFG_CMD_KGDB */