/* * arch/ppc/syslib/ppc405_serial.c * * Author: MontaVista Software, Inc. * frank_rowand@mvista.com or source@mvista.com * debbie_chu@mvista.com * * This is a fairly standard 165xx type device that will eventually * be merged with other similar processor/boards. -- Dan * * 2000 (c) MontaVista, Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. * * Console I/O support for Early kernel bringup. */ #include #if defined(CONFIG_IBM405GP) || defined(CONFIG_IBM405CR) #ifdef CONFIG_KGDB #include #include #endif #ifdef CONFIG_DEBUG_BRINGUP #include extern void ftr_reset_preferred_console(void); static int ppc405_sercons_setup(struct console *co, char *options) { #ifdef CONFIG_UART0_DEBUG_CONSOLE volatile unsigned char *uart_dll = (char *)0xef600300; volatile unsigned char *uart_fcr = (char *)0xef600302; volatile unsigned char *uart_lcr = (char *)0xef600303; #endif #ifdef CONFIG_UART1_DEBUG_CONSOLE volatile unsigned char *uart_dll = (char *)0xef600400; volatile unsigned char *uart_fcr = (char *)0xef600402; volatile unsigned char *uart_lcr = (char *)0xef600403; #endif *uart_lcr = *uart_lcr | 0x80; /* DLAB on */ /* ftr revisit - there is no config option for this ** also see include/asm-ppc/ppc405_serial.h ** ** #define CONFIG_IBM405GP_INTERNAL_CLOCK */ #ifdef CONFIG_IBM405GP_INTERNAL_CLOCK /* ftr revisit ** why is bit 19 of chcr0 (0x1000) being set? */ /* 0x2a results in data corruption, kgdb works with 0x28 */ *uart_dll = 0x28; /* 9600 baud */ _put_CHCR0((_get_CHCR0() & 0xffffe000) | 0x103e); #else *uart_dll = 0x48; /* 9600 baud */ #endif *uart_lcr = *uart_lcr & 0x7f; /* DLAB off */ return 0; } /* * This is a bringup hack, writing directly to uart0 or uart1 */ static void ppc405_sercons_write(struct console *co, const char *ptr, unsigned nb) { int i; #ifdef CONFIG_UART0_DEBUG_CONSOLE volatile unsigned char *uart_xmit = (char *)0xef600300; volatile unsigned char *uart_lsr = (char *)0xef600305; #endif #ifdef CONFIG_UART1_DEBUG_CONSOLE volatile unsigned char *uart_xmit = (char *)0xef600400; volatile unsigned char *uart_lsr = (char *)0xef600405; #endif for (i = 0; i < nb; ++i) { /* wait for transmit reg (possibly fifo) to empty */ while ((*uart_lsr & 0x40) == 0) ; *uart_xmit = (ptr[i] & 0xff); if (ptr[i] == '\n') { /* add a carriage return */ /* wait for transmit reg (possibly fifo) to empty */ while ((*uart_lsr & 0x40) == 0) ; *uart_xmit = '\r'; } } return; } static int ppc405_sercons_read(struct console *co, char *ptr, unsigned nb) { #ifdef CONFIG_UART0_DEBUG_CONSOLE volatile unsigned char *uart_rcv = (char *)0xef600300; volatile unsigned char *uart_lsr = (char *)0xef600305; #endif #ifdef CONFIG_UART1_DEBUG_CONSOLE volatile unsigned char *uart_rcv = (char *)0xef600400; volatile unsigned char *uart_lsr = (char *)0xef600405; #endif /* ftr revisit: not tested */ if (nb == 0) return(0); if (!ptr) return(-1); /* wait for receive reg (possibly fifo) to contain data */ while ((*uart_lsr & 0x01) == 0) ; *ptr = *uart_rcv; return(1); } static struct console ppc405_sercons = { .name = "dbg_cons", .write = ppc405_console_write, .setup = ppc405_console_setup, .flags = CON_PRINTBUFFER, .index = -1, }; void register_debug_console(void) { register_console(&ppc405_sercons); } void unregister_debug_console(void) { unregister_console(&ppc405_sercons); } #endif /* CONFIG_DEBUG_BRINGUP */ #endif /* #if defined(CONFIG_IBM405GP) || defined(CONFIG_IBM405CR) */