blob: 998d033f7ac5f64872c4f5b3f5d8747ef2d09d18 [file] [log] [blame] [edit]
/*
* 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 <linux/config.h>
#if defined(CONFIG_IBM405GP) || defined(CONFIG_IBM405CR)
#ifdef CONFIG_KGDB
#include <asm/kgdb.h>
#include <linux/init.h>
#endif
#ifdef CONFIG_DEBUG_BRINGUP
#include <linux/console.h>
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) */