/*
|
/*
|
* FILE: mon960_console.c
|
* FILE: mon960_console.c
|
* AUTHOR: kma
|
* AUTHOR: kma
|
* DESCR: serial console for TI's 16552 serial controller
|
* DESCR: serial console for TI's 16552 serial controller
|
*/
|
*/
|
|
|
#ident "$Id: mon960_console.c,v 1.1 2005-12-20 09:42:38 jcastillo Exp $"
|
#ident "$Id: mon960_console.c,v 1.1 2005-12-20 09:42:38 jcastillo Exp $"
|
|
|
#include <linux/tty.h>
|
#include <linux/tty.h>
|
#include <linux/tty_driver.h>
|
#include <linux/tty_driver.h>
|
#include <linux/major.h>
|
#include <linux/major.h>
|
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
#include <asm/system.h>
|
#include <asm/system.h>
|
#include <asm/delay.h>
|
#include <asm/delay.h>
|
|
|
#define SER16552_LSR ((volatile unsigned char*)0xe0000014) /* line status */
|
#define SER16552_LSR ((volatile unsigned char*)0xe0000014) /* line status */
|
#define SER16552_THR ((volatile unsigned char*)0xe0000000) /* send fifo */
|
#define SER16552_THR ((volatile unsigned char*)0xe0000000) /* send fifo */
|
#define SER16552_RBR ((volatile unsigned char*)0xe0000000) /* rcv fifo */
|
#define SER16552_RBR ((volatile unsigned char*)0xe0000000) /* rcv fifo */
|
#define SER16552_IER ((volatile unsigned char*)0xe0000004) /* int enable */
|
#define SER16552_IER ((volatile unsigned char*)0xe0000004) /* int enable */
|
|
|
#define LSR_READY 1
|
#define LSR_READY 1
|
#define LSR_SEND_READY 0x20
|
#define LSR_SEND_READY 0x20
|
#define LSR_RECEIVE_READY 0x1
|
#define LSR_RECEIVE_READY 0x1
|
#define LSR_BREAK (1 << 4)
|
#define LSR_BREAK (1 << 4)
|
|
|
#define IER_RCV_ENABLE 1
|
#define IER_RCV_ENABLE 1
|
#define IER_SEND_ENABLE 2
|
#define IER_SEND_ENABLE 2
|
|
|
static int console_refcount;
|
static int console_refcount;
|
static struct tty_struct *console_table[1];
|
static struct tty_struct *console_table[1];
|
static struct termios *console_termios[1];
|
static struct termios *console_termios[1];
|
static struct termios *console_termios_locked[1];
|
static struct termios *console_termios_locked[1];
|
static struct tty_driver console_driver;
|
static struct tty_driver console_driver;
|
|
|
/*
|
/*
|
* The interrupt for the 16552; should only happen for reads
|
* The interrupt for the 16552; should only happen for reads
|
*/
|
*/
|
void do_16552_intr(void)
|
void do_16552_intr(void)
|
{
|
{
|
unsigned char buf[16];
|
unsigned char buf[16];
|
int ii;
|
int ii;
|
struct tty_struct *tty = console_table[0];
|
struct tty_struct *tty = console_table[0];
|
unsigned long lsr;
|
unsigned long lsr;
|
|
|
/* Drain the fifo into the tty */
|
/* Drain the fifo into the tty */
|
for (ii=0; (lsr = *SER16552_LSR) & LSR_RECEIVE_READY; ii++) {
|
for (ii=0; (lsr = *SER16552_LSR) & LSR_RECEIVE_READY; ii++) {
|
/* If there was a break, enter the debugger */
|
/* If there was a break, enter the debugger */
|
#ifdef CONFIG_MON960
|
#ifdef CONFIG_MON960
|
char garbage;
|
char garbage;
|
if (lsr & LSR_BREAK) {
|
if (lsr & LSR_BREAK) {
|
extern void system_break(void);
|
extern void system_break(void);
|
system_break();
|
system_break();
|
garbage = *SER16552_RBR;
|
garbage = *SER16552_RBR;
|
ii--;
|
ii--;
|
}
|
}
|
else
|
else
|
#endif
|
#endif
|
buf[ii] = *SER16552_RBR;
|
buf[ii] = *SER16552_RBR;
|
}
|
}
|
|
|
|
|
if (ii)
|
if (ii)
|
tty->ldisc.receive_buf(tty, buf, 0, ii);
|
tty->ldisc.receive_buf(tty, buf, 0, ii);
|
}
|
}
|
|
|
#if 0
|
#if 0
|
static void do_16552_bh(void)
|
static void do_16552_bh(void)
|
{
|
{
|
printk("in 16552 bottom half!\n");
|
printk("in 16552 bottom half!\n");
|
printk("umm... yeah.\n");
|
printk("umm... yeah.\n");
|
}
|
}
|
#endif
|
#endif
|
|
|
static inline void putc_16552(char c, int blocking)
|
static inline void putc_16552(char c, int blocking)
|
{
|
{
|
unsigned long flags;
|
unsigned long flags;
|
|
|
save_flags(flags);
|
save_flags(flags);
|
cli();
|
cli();
|
top:
|
top:
|
while (!(*SER16552_LSR & LSR_SEND_READY)) {
|
while (!(*SER16552_LSR & LSR_SEND_READY)) {
|
udelay(1000);
|
udelay(1000);
|
}
|
}
|
|
|
*SER16552_THR = c;
|
*SER16552_THR = c;
|
|
|
if (c == '\n') {
|
if (c == '\n') {
|
c = '\r';
|
c = '\r';
|
goto top;
|
goto top;
|
}
|
}
|
restore_flags(flags);
|
restore_flags(flags);
|
}
|
}
|
|
|
void console_print_mon960(const char* msg)
|
void console_print_mon960(const char* msg)
|
{
|
{
|
long flags;
|
long flags;
|
char c;
|
char c;
|
|
|
save_flags(flags);
|
save_flags(flags);
|
cli();
|
cli();
|
while (c = *msg++)
|
while (c = *msg++)
|
putc_16552(c, 0);
|
putc_16552(c, 0);
|
|
|
restore_flags(flags);
|
restore_flags(flags);
|
}
|
}
|
|
|
/*
|
/*
|
* XXX: make this interrupt driven if it's coming from the user
|
* XXX: make this interrupt driven if it's coming from the user
|
*/
|
*/
|
static int con_write(struct tty_struct* tty, int from_user,
|
static int con_write(struct tty_struct* tty, int from_user,
|
const unsigned char* buf, int count)
|
const unsigned char* buf, int count)
|
{
|
{
|
int ii = count;
|
int ii = count;
|
|
|
while (ii--)
|
while (ii--)
|
putc_16552(*buf++, from_user);
|
putc_16552(*buf++, from_user);
|
return count;
|
return count;
|
}
|
}
|
|
|
static int con_chars_in_buffer(struct tty_struct *tty)
|
static int con_chars_in_buffer(struct tty_struct *tty)
|
{
|
{
|
return 0; /* we're not buffering */
|
return 0; /* we're not buffering */
|
}
|
}
|
|
|
static int con_writeroom(struct tty_struct *tty)
|
static int con_writeroom(struct tty_struct *tty)
|
{
|
{
|
return 8192; /* could return anything */
|
return 8192; /* could return anything */
|
}
|
}
|
|
|
static void con_putchar(struct tty_struct* tty, unsigned char c)
|
static void con_putchar(struct tty_struct* tty, unsigned char c)
|
{
|
{
|
putc_16552(c, 0);
|
putc_16552(c, 0);
|
}
|
}
|
|
|
static int con_open(struct tty_struct* tty, struct file* filp)
|
static int con_open(struct tty_struct* tty, struct file* filp)
|
{
|
{
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/*
|
/*
|
* register our tty driver
|
* register our tty driver
|
*/
|
*/
|
|
|
void mon960_console_init(void)
|
void mon960_console_init(void)
|
{
|
{
|
memset(&console_driver, 0, sizeof(console_driver));
|
memset(&console_driver, 0, sizeof(console_driver));
|
console_driver.magic = TTY_DRIVER_MAGIC;
|
console_driver.magic = TTY_DRIVER_MAGIC;
|
console_driver.name = "tty";
|
console_driver.name = "tty";
|
console_driver.name_base = 1;
|
console_driver.name_base = 1;
|
console_driver.major = TTY_MAJOR;
|
console_driver.major = TTY_MAJOR;
|
console_driver.minor_start = 1;
|
console_driver.minor_start = 1;
|
console_driver.num = 1;
|
console_driver.num = 1;
|
console_driver.type = TTY_DRIVER_TYPE_SERIAL;
|
console_driver.type = TTY_DRIVER_TYPE_SERIAL;
|
console_driver.init_termios = tty_std_termios;
|
console_driver.init_termios = tty_std_termios;
|
console_driver.init_termios.c_lflag |= ISIG | ICANON | ECHO
|
console_driver.init_termios.c_lflag |= ISIG | ICANON | ECHO
|
| ECHOE | ECHOK ;
|
| ECHOE | ECHOK ;
|
console_driver.init_termios.c_iflag |= ICRNL;
|
console_driver.init_termios.c_iflag |= ICRNL;
|
console_driver.init_termios.c_cflag = CS8 | CREAD | CLOCAL;
|
console_driver.init_termios.c_cflag = CS8 | CREAD | CLOCAL;
|
console_driver.flags = TTY_DRIVER_REAL_RAW;
|
console_driver.flags = TTY_DRIVER_REAL_RAW;
|
console_driver.refcount = &console_refcount;
|
console_driver.refcount = &console_refcount;
|
|
|
console_driver.table = console_table;
|
console_driver.table = console_table;
|
console_driver.termios = console_termios;
|
console_driver.termios = console_termios;
|
console_driver.termios_locked = console_termios_locked;
|
console_driver.termios_locked = console_termios_locked;
|
|
|
console_driver.open = con_open;
|
console_driver.open = con_open;
|
console_driver.write = con_write;
|
console_driver.write = con_write;
|
console_driver.put_char = con_putchar;
|
console_driver.put_char = con_putchar;
|
console_driver.write_room = con_writeroom;
|
console_driver.write_room = con_writeroom;
|
console_driver.chars_in_buffer = con_chars_in_buffer;
|
console_driver.chars_in_buffer = con_chars_in_buffer;
|
|
|
if (tty_register_driver(&console_driver)) {
|
if (tty_register_driver(&console_driver)) {
|
printk("Couldn't register console driver\n");
|
printk("Couldn't register console driver\n");
|
}
|
}
|
|
|
/*
|
/*
|
* Enable receive interrupts
|
* Enable receive interrupts
|
*/
|
*/
|
*SER16552_IER = IER_RCV_ENABLE;
|
*SER16552_IER = IER_RCV_ENABLE;
|
|
|
}
|
}
|
|
|