diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2001-04-01 03:32:51 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2001-04-01 03:32:51 +0000 |
commit | e11f564413d1d8feac7a60fb3aa440bf66a4e25a (patch) | |
tree | 9fc9db586b30cbdf4b414273201eab7c5598cb71 /arch | |
parent | 3c73e78526f87333ed70059e41c7e6a5ccda7ced (diff) |
Rest of Nino updates.
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/philips/drivers/.cvsignore | 2 | ||||
-rw-r--r-- | arch/mips/philips/drivers/generic_serial.c | 1078 | ||||
-rw-r--r-- | arch/mips/philips/drivers/uart-pr31700.c | 1313 | ||||
-rw-r--r-- | arch/mips/philips/drivers/uart-pr31700.h | 126 | ||||
-rw-r--r-- | arch/mips/philips/nino/Makefile | 11 | ||||
-rw-r--r-- | arch/mips/philips/nino/int-handler.S | 9 | ||||
-rw-r--r-- | arch/mips/philips/nino/irq.c | 42 | ||||
-rw-r--r-- | arch/mips/philips/nino/kgdb.c | 6 | ||||
-rw-r--r-- | arch/mips/philips/nino/power.c | 6 | ||||
-rw-r--r-- | arch/mips/philips/nino/prom.c | 73 | ||||
-rw-r--r-- | arch/mips/philips/nino/ramdisk/Makefile (renamed from arch/mips/philips/drivers/Makefile) | 14 | ||||
-rw-r--r-- | arch/mips/philips/nino/ramdisk/ld.script | 11 | ||||
-rw-r--r-- | arch/mips/philips/nino/reset.c | 4 | ||||
-rw-r--r-- | arch/mips/philips/nino/rtc.c | 7 | ||||
-rw-r--r-- | arch/mips/philips/nino/setup.c | 17 | ||||
-rw-r--r-- | arch/mips/philips/nino/time.c | 8 | ||||
-rw-r--r-- | arch/mips/philips/nino/wbflush.c | 4 |
17 files changed, 117 insertions, 2614 deletions
diff --git a/arch/mips/philips/drivers/.cvsignore b/arch/mips/philips/drivers/.cvsignore deleted file mode 100644 index 857dd22e9..000000000 --- a/arch/mips/philips/drivers/.cvsignore +++ /dev/null @@ -1,2 +0,0 @@ -.depend -.*.flags diff --git a/arch/mips/philips/drivers/generic_serial.c b/arch/mips/philips/drivers/generic_serial.c deleted file mode 100644 index acd3402f8..000000000 --- a/arch/mips/philips/drivers/generic_serial.c +++ /dev/null @@ -1,1078 +0,0 @@ -/* - * generic_serial.c - * - * Copyright (C) 1998/1999 R.E.Wolff@BitWizard.nl - * - * written for the SX serial driver. - * Contains the code that should be shared over all the serial drivers. - * - * Credit for the idea to do it this way might go to Alan Cox. - * - * - * Version 0.1 -- December, 1998. Initial version. - * Version 0.2 -- March, 1999. Some more routines. Bugfixes. Etc. - * Version 0.5 -- August, 1999. Some more fixes. Reformat for Linus. - * - * BitWizard is actively maintaining this file. We sometimes find - * that someone submitted changes to this file. We really appreciate - * your help, but please submit changes through us. We're doing our - * best to be responsive. -- REW - * */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/tty.h> -#include <linux/serial.h> -#include <linux/mm.h> -#include <linux/generic_serial.h> -#include <asm/semaphore.h> -#include <asm/uaccess.h> - -#define DEBUG - -static char * tmp_buf; -static DECLARE_MUTEX(tmp_buf_sem); - -static int gs_debug; - -#ifdef DEBUG -#define gs_dprintk(f, str...) if (gs_debug & f) printk (str) -#else -#define gs_dprintk(f, str...) /* nothing */ -#endif - -#define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter " __FUNCTION__ "\n") -#define func_exit() gs_dprintk (GS_DEBUG_FLOW, "gs: exit " __FUNCTION__ "\n") - -#if NEW_WRITE_LOCKING -#define DECL /* Nothing */ -#define LOCKIT down (& port->port_write_sem); -#define RELEASEIT up (&port->port_write_sem); -#else -#define DECL unsigned long flags; -#define LOCKIT save_flags (flags);cli () -#define RELEASEIT restore_flags (flags) -#endif - -#define RS_EVENT_WRITE_WAKEUP 1 - -MODULE_PARM(gs_debug, "i"); - - -void gs_put_char(struct tty_struct * tty, unsigned char ch) -{ - struct gs_port *port; - DECL - - func_enter (); - - if (!tty) return; - - port = tty->driver_data; - - if (!port) return; - - if (! (port->flags & ASYNC_INITIALIZED)) return; - - /* Take a lock on the serial tranmit buffer! */ - LOCKIT; - - if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { - /* Sorry, buffer is full, drop character. Update statistics???? -- REW */ - RELEASEIT; - return; - } - - port->xmit_buf[port->xmit_head++] = ch; - port->xmit_head &= SERIAL_XMIT_SIZE - 1; - port->xmit_cnt++; /* Characters in buffer */ - - RELEASEIT; - func_exit (); -} - - -#ifdef NEW_WRITE_LOCKING - -/* -> Problems to take into account are: -> -1- Interrupts that empty part of the buffer. -> -2- page faults on the access to userspace. -> -3- Other processes that are also trying to do a "write". -*/ - -int gs_write(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count) -{ - struct gs_port *port; - int c, total = 0; - int t; - - func_enter (); - - if (!tty) return 0; - - port = tty->driver; - - if (!port) return 0; - - if (! (port->flags & ASYNC_INITIALIZED)) - return 0; - - /* get exclusive "write" access to this port (problem 3) */ - /* This is not a spinlock because we can have a disk access (page - fault) in copy_from_user */ - down (& port->port_write_sem); - - while (1) { - - c = count; - - /* This is safe because we "OWN" the "head". Noone else can - change the "head": we own the port_write_sem. */ - /* Don't overrun the end of the buffer */ - t = SERIAL_XMIT_SIZE - port->xmit_head; - if (t < c) c = t; - - /* This is safe because the xmit_cnt can only decrease. This - would increase "t", so we might copy too little chars. */ - /* Don't copy past the "head" of the buffer */ - t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt; - if (t < c) c = t; - - /* Can't copy more? break out! */ - if (c <= 0) break; - if (from_user) - copy_from_user (port->xmit_buf + port->xmit_head, buf, c); - else - memcpy (port->xmit_buf + port->xmit_head, buf, c); - - port -> xmit_cnt += c; - port -> xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE -1); - buf += c; - count -= c; - total += c; - } - up (& port->port_write_sem); - - gs_dprintk (GS_DEBUG_WRITE, "write: interrupts are %s\n", - (port->flags & GS_TX_INTEN)?"enabled": "disabled"); - - if (port->xmit_cnt && - !tty->stopped && - !tty->hw_stopped && - !(port->flags & GS_TX_INTEN)) { - port->flags |= GS_TX_INTEN; - port->rd->enable_tx_interrupts (port); - } - func_exit (); - return total; -} -#else -/* -> Problems to take into account are: -> -1- Interrupts that empty part of the buffer. -> -2- page faults on the access to userspace. -> -3- Other processes that are also trying to do a "write". -*/ - -int gs_write(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count) -{ - struct gs_port *port; - int c, total = 0; - int t; - unsigned long flags; - - func_enter (); - - /* The standard serial driver returns 0 in this case. - That sounds to me as "No error, I just didn't get to writing any - bytes. Feel free to try again." - The "official" way to write n bytes from buf is: - - for (nwritten = 0;nwritten < n;nwritten += rv) { - rv = write (fd, buf+nwritten, n-nwritten); - if (rv < 0) break; // Error: bail out. // - } - - which will loop endlessly in this case. The manual page for write - agrees with me. In practise almost everybody writes - "write (fd, buf,n);" but some people might have had to deal with - incomplete writes in the past and correctly implemented it by now... - */ - - if (!tty) return -EIO; - - port = tty->driver_data; - if (!port || !port->xmit_buf || !tmp_buf) - return -EIO; - - save_flags(flags); - if (from_user) { - down(&tmp_buf_sem); - while (1) { - c = count; - - /* This is safe because we "OWN" the "head". Noone else can - change the "head": we own the port_write_sem. */ - /* Don't overrun the end of the buffer */ - t = SERIAL_XMIT_SIZE - port->xmit_head; - if (t < c) c = t; - - /* This is safe because the xmit_cnt can only decrease. This - would increase "t", so we might copy too little chars. */ - /* Don't copy past the "head" of the buffer */ - t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt; - if (t < c) c = t; - - /* Can't copy more? break out! */ - if (c <= 0) break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!total) - total = -EFAULT; - break; - } - cli(); - t = SERIAL_XMIT_SIZE - port->xmit_head; - if (t < c) c = t; - t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt; - if (t < c) c = t; - - memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c); - port->xmit_head = ((port->xmit_head + c) & - (SERIAL_XMIT_SIZE-1)); - port->xmit_cnt += c; - restore_flags(flags); - buf += c; - count -= c; - total += c; - } - up(&tmp_buf_sem); - } else { - while (1) { - cli(); - c = count; - - /* This is safe because we "OWN" the "head". Noone else can - change the "head": we own the port_write_sem. */ - /* Don't overrun the end of the buffer */ - t = SERIAL_XMIT_SIZE - port->xmit_head; - if (t < c) c = t; - - /* This is safe because the xmit_cnt can only decrease. This - would increase "t", so we might copy too little chars. */ - /* Don't copy past the "head" of the buffer */ - t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt; - if (t < c) c = t; - - /* Can't copy more? break out! */ - if (c <= 0) { - restore_flags(flags); - break; - } - memcpy(port->xmit_buf + port->xmit_head, buf, c); - port->xmit_head = ((port->xmit_head + c) & - (SERIAL_XMIT_SIZE-1)); - port->xmit_cnt += c; - restore_flags(flags); - buf += c; - count -= c; - total += c; - } - } - - if (port->xmit_cnt && - !tty->stopped && - !tty->hw_stopped && - !(port->flags & GS_TX_INTEN)) { - port->flags |= GS_TX_INTEN; - port->rd->enable_tx_interrupts (port); - } - func_exit (); - return total; -} - -#endif - - - -int gs_write_room(struct tty_struct * tty) -{ - struct gs_port *port = tty->driver_data; - int ret; - - func_enter (); - ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1; - if (ret < 0) - ret = 0; - func_exit (); - return ret; -} - - -int gs_chars_in_buffer(struct tty_struct *tty) -{ - struct gs_port *port = tty->driver_data; - func_enter (); - - func_exit (); - return port->xmit_cnt; -} - - -int gs_real_chars_in_buffer(struct tty_struct *tty) -{ - struct gs_port *port; - func_enter (); - - if (!tty) return 0; - port = tty->driver_data; - - if (!port->rd) return 0; - if (!port->rd->chars_in_buffer) return 0; - - func_exit (); - return port->xmit_cnt + port->rd->chars_in_buffer (port); -} - - -static int gs_wait_tx_flushed (void * ptr, int timeout) -{ - struct gs_port *port = ptr; - long end_jiffies; - int jiffies_to_transmit, charsleft = 0, rv = 0; - int to, rcib; - - func_enter(); - - gs_dprintk (GS_DEBUG_FLUSH, "port=%p.\n", port); - if (port) { - gs_dprintk (GS_DEBUG_FLUSH, "xmit_cnt=%x, xmit_buf=%p, tty=%p.\n", - port->xmit_cnt, port->xmit_buf, port->tty); - } - - if (!port || port->xmit_cnt < 0 || !port->xmit_buf) { - gs_dprintk (GS_DEBUG_FLUSH, "ERROR: !port, !port->xmit_buf or prot->xmit_cnt < 0.\n"); - func_exit(); - return -EINVAL; /* This is an error which we don't know how to handle. */ - } - - rcib = gs_real_chars_in_buffer(port->tty); - - if(rcib <= 0) { - gs_dprintk (GS_DEBUG_FLUSH, "nothing to wait for.\n"); - func_exit(); - return rv; - } - /* stop trying: now + twice the time it would normally take + seconds */ - end_jiffies = jiffies; - if (timeout != MAX_SCHEDULE_TIMEOUT) - end_jiffies += port->baud?(2 * rcib * 10 * HZ / port->baud):0; - end_jiffies += timeout; - - gs_dprintk (GS_DEBUG_FLUSH, "now=%lx, end=%lx (%ld).\n", - jiffies, end_jiffies, end_jiffies-jiffies); - - to = 100; - /* the expression is actually jiffies < end_jiffies, but that won't - work around the wraparound. Tricky eh? */ - while (to-- && - (charsleft = gs_real_chars_in_buffer (port->tty)) && - time_after (end_jiffies, jiffies)) { - /* Units check: - chars * (bits/char) * (jiffies /sec) / (bits/sec) = jiffies! - check! */ - - charsleft += 16; /* Allow 16 chars more to be transmitted ... */ - jiffies_to_transmit = port->baud?(1 + charsleft * 10 * HZ / port->baud):0; - /* ^^^ Round up.... */ - if (jiffies_to_transmit <= 0) jiffies_to_transmit = 1; - - gs_dprintk (GS_DEBUG_FLUSH, "Expect to finish in %d jiffies " - "(%d chars).\n", jiffies_to_transmit, charsleft); - - set_current_state (TASK_INTERRUPTIBLE); - schedule_timeout(jiffies_to_transmit); - if (signal_pending (current)) { - gs_dprintk (GS_DEBUG_FLUSH, "Signal pending. Bombing out: "); - rv = -EINTR; - break; - } - } - - gs_dprintk (GS_DEBUG_FLUSH, "charsleft = %d.\n", charsleft); - set_current_state (TASK_RUNNING); - - func_exit(); - return rv; -} - - - -void gs_flush_buffer(struct tty_struct *tty) -{ - struct gs_port *port; - unsigned long flags; - - func_enter (); - - if (!tty) return; - - port = tty->driver_data; - - if (!port) return; - - /* XXX Would the write semaphore do? */ - save_flags(flags); cli(); - port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; - restore_flags(flags); - - wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - func_exit (); -} - - -void gs_flush_chars(struct tty_struct * tty) -{ - struct gs_port *port; - - func_enter (); - - if (!tty) return; - - port = tty->driver_data; - - if (!port) return; - - if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || - !port->xmit_buf) { - func_exit (); - return; - } - - /* Beats me -- REW */ - port->flags |= GS_TX_INTEN; - port->rd->enable_tx_interrupts (port); - func_exit (); -} - - -void gs_stop(struct tty_struct * tty) -{ - struct gs_port *port; - - func_enter (); - - if (!tty) return; - - port = tty->driver_data; - - if (!port) return; - - if (port->xmit_cnt && - port->xmit_buf && - (port->flags & GS_TX_INTEN) ) { - port->flags &= ~GS_TX_INTEN; - port->rd->disable_tx_interrupts (port); - } - func_exit (); -} - - -void gs_start(struct tty_struct * tty) -{ - struct gs_port *port; - - if (!tty) return; - - port = tty->driver_data; - - if (!port) return; - - if (port->xmit_cnt && - port->xmit_buf && - !(port->flags & GS_TX_INTEN) ) { - port->flags |= GS_TX_INTEN; - port->rd->enable_tx_interrupts (port); - } - func_exit (); -} - - -void gs_shutdown_port (struct gs_port *port) -{ - long flags; - - func_enter(); - - if (!port) return; - - if (!(port->flags & ASYNC_INITIALIZED)) - return; - - save_flags (flags); - cli (); - - if (port->xmit_buf) { - free_page((unsigned long) port->xmit_buf); - port->xmit_buf = 0; - } - - if (port->tty) - set_bit(TTY_IO_ERROR, &port->tty->flags); - - port->rd->shutdown_port (port); - - port->flags &= ~ASYNC_INITIALIZED; - restore_flags (flags); - - func_exit(); -} - - -void gs_hangup(struct tty_struct *tty) -{ - struct gs_port *port; - - func_enter (); - - if (!tty) return; - - port = tty->driver_data; - tty = port->tty; - if (!tty) - return; - - gs_shutdown_port (port); - port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE |GS_ACTIVE); - port->tty = NULL; - port->count = 0; - - wake_up_interruptible(&port->open_wait); - func_exit (); -} - - -void gs_do_softint(void *private_) -{ - struct gs_port *port = private_; - struct tty_struct *tty; - - func_enter (); - - if (!port) return; - - tty = port->tty; - - if (!tty) return; - - if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - wake_up_interruptible(&tty->write_wait); - } - func_exit (); -} - - -int gs_block_til_ready(void *port_, struct file * filp) -{ - struct gs_port *port = port_; - DECLARE_WAITQUEUE(wait, current); - int retval; - int do_clocal = 0; - int CD; - struct tty_struct *tty; - - func_enter (); - - if (!port) return 0; - - tty = port->tty; - - if (!tty) return 0; - - gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n"); - /* - * If the device is in the middle of being closed, then block - * until it's done, and then try again. - */ - if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { - interruptible_sleep_on(&port->close_wait); - if (port->flags & ASYNC_HUP_NOTIFY) - return -EAGAIN; - else - return -ERESTARTSYS; - } - - gs_dprintk (GS_DEBUG_BTR, "after hung up\n"); - - /* - * If this is a callout device, then just make sure the normal - * device isn't being used. - */ - if (tty->driver.subtype == GS_TYPE_CALLOUT) { - if (port->flags & ASYNC_NORMAL_ACTIVE) - return -EBUSY; - if ((port->flags & ASYNC_CALLOUT_ACTIVE) && - (port->flags & ASYNC_SESSION_LOCKOUT) && - (port->session != current->session)) - return -EBUSY; - if ((port->flags & ASYNC_CALLOUT_ACTIVE) && - (port->flags & ASYNC_PGRP_LOCKOUT) && - (port->pgrp != current->pgrp)) - return -EBUSY; - port->flags |= ASYNC_CALLOUT_ACTIVE; - return 0; - } - - gs_dprintk (GS_DEBUG_BTR, "after subtype\n"); - - /* - * If non-blocking mode is set, or the port is not enabled, - * then make the check up front and then exit. - */ - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { - if (port->flags & ASYNC_CALLOUT_ACTIVE) - return -EBUSY; - port->flags |= ASYNC_NORMAL_ACTIVE; - return 0; - } - - gs_dprintk (GS_DEBUG_BTR, "after nonblock\n"); - - if (port->flags & ASYNC_CALLOUT_ACTIVE) { - if (port->normal_termios.c_cflag & CLOCAL) - do_clocal = 1; - } else { - if (C_CLOCAL(tty)) - do_clocal = 1; - } - - /* - * Block waiting for the carrier detect and the line to become - * free (i.e., not in use by the callout). While we are in - * this loop, port->count is dropped by one, so that - * rs_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - retval = 0; - - add_wait_queue(&port->open_wait, &wait); - - gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); - cli(); - if (!tty_hung_up_p(filp)) - port->count--; - sti(); - port->blocked_open++; - while (1) { - CD = port->rd->get_CD (port); - gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD); - set_current_state (TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) || - !(port->flags & ASYNC_INITIALIZED)) { - if (port->flags & ASYNC_HUP_NOTIFY) - retval = -EAGAIN; - else - retval = -ERESTARTSYS; - break; - } - if (!(port->flags & ASYNC_CALLOUT_ACTIVE) && - !(port->flags & ASYNC_CLOSING) && - (do_clocal || CD)) - break; - gs_dprintk (GS_DEBUG_BTR, "signal_pending is now: %d (%lx)\n", - (int)signal_pending (current), *(long*)(¤t->blocked)); - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - schedule(); - } - gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n", - port->blocked_open); - set_current_state (TASK_RUNNING); - remove_wait_queue(&port->open_wait, &wait); - if (!tty_hung_up_p(filp)) - port->count++; - port->blocked_open--; - if (retval) - return retval; - - port->flags |= ASYNC_NORMAL_ACTIVE; - func_exit (); - return 0; -} - - -void gs_close(struct tty_struct * tty, struct file * filp) -{ - unsigned long flags; - struct gs_port *port; - - func_enter (); - - if (!tty) return; - - port = (struct gs_port *) tty->driver_data; - - if (!port) return; - - if (!port->tty) { - /* This seems to happen when this is called from vhangup. */ - gs_dprintk (GS_DEBUG_CLOSE, "gs: Odd: port->tty is NULL\n"); - port->tty = tty; - } - - save_flags(flags); cli(); - - if (tty_hung_up_p(filp)) { - restore_flags(flags); - port->rd->hungup (port); - func_exit (); - return; - } - - if ((tty->count == 1) && (port->count != 1)) { - printk(KERN_ERR "gs: gs_close: bad port count;" - " tty->count is 1, port count is %d\n", port->count); - port->count = 1; - } - if (--port->count < 0) { - printk(KERN_ERR "gs: gs_close: bad port count: %d\n", port->count); - port->count = 0; - } - if (port->count) { - gs_dprintk(GS_DEBUG_CLOSE, "gs_close: count: %d\n", port->count); - restore_flags(flags); - func_exit (); - return; - } - port->flags |= ASYNC_CLOSING; - - /* - * Save the termios structure, since this port may have - * separate termios for callout and dialin. - */ - if (port->flags & ASYNC_NORMAL_ACTIVE) - port->normal_termios = *tty->termios; - if (port->flags & ASYNC_CALLOUT_ACTIVE) - port->callout_termios = *tty->termios; - /* - * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. - */ - tty->closing = 1; - /* if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, port->closing_wait); */ - - /* - * At this point we stop accepting input. To do this, we - * disable the receive line status interrupts, and tell the - * interrupt driver to stop checking the data ready bit in the - * line status register. - */ - - port->rd->disable_rx_interrupts (port); - - /* close has no way of returning "EINTR", so discard return value */ - if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) - gs_wait_tx_flushed (port, port->closing_wait); - - port->flags &= ~GS_ACTIVE; - - if (tty->driver.flush_buffer) - tty->driver.flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); - tty->closing = 0; - - port->event = 0; - port->rd->close (port); - port->rd->shutdown_port (port); - port->tty = 0; - - if (port->blocked_open) { - if (port->close_delay) { - set_current_state (TASK_INTERRUPTIBLE); - schedule_timeout(port->close_delay); - } - wake_up_interruptible(&port->open_wait); - } - port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE| - ASYNC_CLOSING | ASYNC_INITIALIZED); - wake_up_interruptible(&port->close_wait); - - restore_flags(flags); - func_exit (); -} - - -static unsigned int gs_baudrates[] = { - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, - 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 -}; - - -void gs_set_termios (struct tty_struct * tty, - struct termios * old_termios) -{ - struct gs_port *port; - int baudrate, tmp, rv; - struct termios *tiosp; - - func_enter(); - - if (!tty) return; - - port = tty->driver_data; - - if (!port) return; - - tiosp = tty->termios; - - if (gs_debug & GS_DEBUG_TERMIOS) { - gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp); - } - -#if 0 - /* This is an optimization that is only allowed for dumb cards */ - /* Smart cards require knowledge of iflags and oflags too: that - might change hardware cooking mode.... */ -#endif - if (old_termios) { - if( (tiosp->c_iflag == old_termios->c_iflag) - && (tiosp->c_oflag == old_termios->c_oflag) - && (tiosp->c_cflag == old_termios->c_cflag) - && (tiosp->c_lflag == old_termios->c_lflag) - && (tiosp->c_line == old_termios->c_line) - && (memcmp(tiosp->c_cc, old_termios->c_cc, NCC) == 0)) { - gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: optimized away\n"); - return /* 0 */; - } - } else - gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: no old_termios: " - "no optimization\n"); - - if(old_termios && (gs_debug & GS_DEBUG_TERMIOS)) { - if(tiosp->c_iflag != old_termios->c_iflag) printk("c_iflag changed\n"); - if(tiosp->c_oflag != old_termios->c_oflag) printk("c_oflag changed\n"); - if(tiosp->c_cflag != old_termios->c_cflag) printk("c_cflag changed\n"); - if(tiosp->c_lflag != old_termios->c_lflag) printk("c_lflag changed\n"); - if(tiosp->c_line != old_termios->c_line) printk("c_line changed\n"); - if(!memcmp(tiosp->c_cc, old_termios->c_cc, NCC)) printk("c_cc changed\n"); - } - - baudrate = tiosp->c_cflag & CBAUD; - if (baudrate & CBAUDEX) { - baudrate &= ~CBAUDEX; - if ((baudrate < 1) || (baudrate > 4)) - tiosp->c_cflag &= ~CBAUDEX; - else - baudrate += 15; - } - - baudrate = gs_baudrates[baudrate]; - if ((tiosp->c_cflag & CBAUD) == B38400) { - if ( (port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - baudrate = 57600; - else if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - baudrate = 115200; - else if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - baudrate = 230400; - else if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - baudrate = 460800; - else if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) - baudrate = (port->baud_base / port->custom_divisor); - } - - /* I recommend using THIS instead of the mess in termios (and - duplicating the above code). Next we should create a clean - interface towards this variable. If your card supports arbitrary - baud rates, (e.g. CD1400 or 16550 based cards) then everything - will be very easy..... */ - port->baud = baudrate; - - /* Two timer ticks seems enough to wakeup something like SLIP driver */ - /* Baudrate/10 is cps. Divide by HZ to get chars per tick. */ - tmp = (baudrate / 10 / HZ) * 2; - - if (tmp < 0) tmp = 0; - if (tmp >= SERIAL_XMIT_SIZE) tmp = SERIAL_XMIT_SIZE-1; - - port->wakeup_chars = tmp; - - /* We should really wait for the characters to be all sent before - changing the settings. -- CAL */ - rv = gs_wait_tx_flushed (port, MAX_SCHEDULE_TIMEOUT); - if (rv < 0) return /* rv */; - - rv = port->rd->set_real_termios(port); - if (rv < 0) return /* rv */; - - if ((!old_termios || - (old_termios->c_cflag & CRTSCTS)) && - !( tiosp->c_cflag & CRTSCTS)) { - tty->stopped = 0; - gs_start(tty); - } - -#ifdef tytso_patch_94Nov25_1726 - /* This "makes sense", Why is it commented out? */ - - if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios->c_cflag & CLOCAL)) - wake_up_interruptible(&info->open_wait); -#endif - - func_exit(); - return /* 0 */; -} - - - -/* Must be called with interrupts enabled */ -int gs_init_port(struct gs_port *port) -{ - unsigned long flags; - unsigned long page; - - save_flags (flags); - if (!tmp_buf) { - page = get_free_page(GFP_KERNEL); - - cli (); /* Don't expect this to make a difference. */ - if (tmp_buf) - free_page(page); - else - tmp_buf = (unsigned char *) page; - restore_flags (flags); - - if (!tmp_buf) { - return -ENOMEM; - } - } - - if (port->flags & ASYNC_INITIALIZED) - return 0; - - if (!port->xmit_buf) { - /* We may sleep in get_free_page() */ - unsigned long tmp; - - tmp = get_free_page(GFP_KERNEL); - - /* Spinlock? */ - cli (); - if (port->xmit_buf) - free_page (tmp); - else - port->xmit_buf = (unsigned char *) tmp; - restore_flags (flags); - - if (!port->xmit_buf) - return -ENOMEM; - } - - cli(); - - if (port->tty) - clear_bit(TTY_IO_ERROR, &port->tty->flags); - - port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; - - gs_set_termios(port->tty, NULL); - - port->flags |= ASYNC_INITIALIZED; - port->flags &= ~GS_TX_INTEN; - - restore_flags(flags); - return 0; -} - - -int gs_setserial(struct gs_port *port, struct serial_struct *sp) -{ - struct serial_struct sio; - - copy_from_user(&sio, sp, sizeof(struct serial_struct)); - - if (!capable(CAP_SYS_ADMIN)) { - if ((sio.baud_base != port->baud_base) || - (sio.close_delay != port->close_delay) || - ((sio.flags & ~ASYNC_USR_MASK) != - (port->flags & ~ASYNC_USR_MASK))) - return(-EPERM); - } - - port->flags = (port->flags & ~ASYNC_USR_MASK) | - (sio.flags & ASYNC_USR_MASK); - - port->baud_base = sio.baud_base; - port->close_delay = sio.close_delay; - port->closing_wait = sio.closing_wait; - port->custom_divisor = sio.custom_divisor; - - gs_set_termios (port->tty, NULL); - - return 0; -} - - -/*****************************************************************************/ - -/* - * Generate the serial struct info. - */ - -void gs_getserial(struct gs_port *port, struct serial_struct *sp) -{ - struct serial_struct sio; - - memset(&sio, 0, sizeof(struct serial_struct)); - sio.flags = port->flags; - sio.baud_base = port->baud_base; - sio.close_delay = port->close_delay; - sio.closing_wait = port->closing_wait; - sio.custom_divisor = port->custom_divisor; - sio.hub6 = 0; - - /* If you want you can override these. */ - sio.type = PORT_UNKNOWN; - sio.xmit_fifo_size = -1; - sio.line = -1; - sio.port = -1; - sio.irq = -1; - - if (port->rd->getserial) - port->rd->getserial (port, &sio); - - copy_to_user(sp, &sio, sizeof(struct serial_struct)); -} - -EXPORT_SYMBOL(gs_put_char); -EXPORT_SYMBOL(gs_write); -EXPORT_SYMBOL(gs_write_room); -EXPORT_SYMBOL(gs_chars_in_buffer); -EXPORT_SYMBOL(gs_flush_buffer); -EXPORT_SYMBOL(gs_flush_chars); -EXPORT_SYMBOL(gs_stop); -EXPORT_SYMBOL(gs_start); -EXPORT_SYMBOL(gs_hangup); -EXPORT_SYMBOL(gs_do_softint); -EXPORT_SYMBOL(gs_block_til_ready); -EXPORT_SYMBOL(gs_close); -EXPORT_SYMBOL(gs_set_termios); -EXPORT_SYMBOL(gs_init_port); -EXPORT_SYMBOL(gs_setserial); -EXPORT_SYMBOL(gs_getserial); - diff --git a/arch/mips/philips/drivers/uart-pr31700.c b/arch/mips/philips/drivers/uart-pr31700.c deleted file mode 100644 index 92adb7056..000000000 --- a/arch/mips/philips/drivers/uart-pr31700.c +++ /dev/null @@ -1,1313 +0,0 @@ -/* - * Serial driver for r39xx - * - * Copyright (C) 2000 Jim Pick <jim@jimpick.com> - * - * Inspired by, and/or includes bits from: - * - * drivers/char/serial.c (standard serial driver) - * drivers/char/sx.c (use of generic_serial interface) - * drivers/char/esp.c (another UART that uses DMA) - * arch/mips/vr41xx/serial.c (another MIPS serial driver) - * - * Please see those files for credits. - * - * Also, the original rough serial console code was: - * - * Copyright (C) 1999 Harald Koerfgen - * - * $Id: r39xx_serial.c,v 1.16 2001/01/11 20:24:47 pavel Exp $ - */ - -#include <linux/init.h> -#include <linux/config.h> -#include <linux/tty.h> -#include <linux/major.h> -#include <linux/ptrace.h> -#include <linux/init.h> -#include <linux/console.h> -#include <linux/fs.h> -#include <linux/mm.h> -#include <linux/malloc.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/pm.h> -#include <asm/uaccess.h> -#include <asm/philips/pr31700.h> -#include <asm/delay.h> -#include <asm/wbflush.h> -#include "uart-pr31700.h" - -/* Prototypes */ - -static void rs_disable_tx_interrupts (void * ptr); -static void rs_enable_tx_interrupts (void * ptr); -static void rs_disable_rx_interrupts (void * ptr); -static void rs_enable_rx_interrupts (void * ptr); -static int rs_get_CD (void * ptr); -static void rs_shutdown_port (void * ptr); -static int rs_set_real_termios (void *ptr); -static int rs_chars_in_buffer (void * ptr); -static void rs_hungup (void *ptr); -static void rs_close (void *ptr); - - - -static struct real_driver rs_real_driver = { - disable_tx_interrupts: rs_disable_tx_interrupts, - enable_tx_interrupts: rs_enable_tx_interrupts, - disable_rx_interrupts: rs_disable_rx_interrupts, - enable_rx_interrupts: rs_enable_rx_interrupts, - get_CD: rs_get_CD, - shutdown_port: rs_shutdown_port, - set_real_termios: rs_set_real_termios, - chars_in_buffer: rs_chars_in_buffer, - close: rs_close, - hungup: rs_hungup, -}; - -static struct tty_driver rs_driver, rs_callout_driver; - -static struct tty_struct * rs_table[RS_NPORTS] = { NULL, }; -static struct termios ** rs_termios; -static struct termios ** rs_termios_locked; - -struct rs_port *rs_ports; -int rs_refcount; -int rs_initialized = 0; - -#ifdef CONFIG_PM -static struct pm_dev *pmdev; -static int pm_request(struct pm_dev* dev, pm_request_t req, void* data); -#endif - -#define DEBUG -#undef DEBUG2 - -#ifdef DEBUG2 -int rs_debug = RS_DEBUG_ALL & ~RS_DEBUG_TRANSMIT; -#else -int rs_debug = 0; -#endif - - -/* - * Helper routines - */ - - -static inline unsigned int serial_in(struct rs_port *port, int offset) -{ - unsigned int tmp; - - tmp = *(volatile unsigned int *)(port->base + offset); - tmp &= 0xff; - barrier(); - return tmp; -} - -static inline void serial_out(struct rs_port *port, int offset, int value) -{ - *(volatile unsigned int *)(port->base + offset) = (unsigned char)value; - - barrier(); -} - -/* - * ---------------------------------------------------------------------- - * - * Here starts the interrupt handling routines. All of the following - * subroutines are declared as inline and are folded into - * rs_interrupt(). They were separated out for readability's sake. - * - * Note: rs_interrupt() is a "fast" interrupt, which means that it - * runs with interrupts turned off. People who may want to modify - * rs_interrupt() should try to keep the interrupt handler as fast as - * possible. After you are done making modifications, it is not a bad - * idea to do: - * - * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c - * - * and look at the resulting assemble code in serial.s. - * - * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 - * ----------------------------------------------------------------------- - */ - - - -static inline void receive_char_pio(struct rs_port *port) -{ - struct tty_struct *tty = port->gs.tty; - unsigned char ch; - int counter = 2048; - - /* While there are characters, get them ... */ - while (counter>0) { - // printk("R%08x", (int)port->base[UART_R39XX_CTRL1]); - if (!(port->base[UART_R39XX_CTRL1] & UART_RX_HOLD_FULL)) { - break; - } - ch = serial_in(port, UART_R39XX_DATA); - if (tty->flip.count < TTY_FLIPBUF_SIZE) { - *tty->flip.char_buf_ptr++ = ch; - *tty->flip.flag_buf_ptr++ = 0; - tty->flip.count++; - } - udelay(1); /* Allow things to happen - it take a while */ - counter--; - } - if (!counter) - printk( "Ugh, looped in receive_char_pio!\n" ); - - tty_flip_buffer_push(tty); -#if 0 - /* Now handle error conditions */ - if (*status & (INTTYPE(UART_RXOVERRUN_INT) | - INTTYPE(UART_FRAMEERR_INT) | - INTTYPE(UART_PARITYERR_INT) | - INTTYPE(UART_BREAK_INT))) { - - /* - * Now check to see if character should be - * ignored, and mask off conditions which - * should be ignored. - */ - if (*status & port->ignore_status_mask) { - goto ignore_char; - } - *status &= port->read_status_mask; - - if (*status & INTTYPE(UART_BREAK_INT)) { - rs_dprintk(RS_DEBUG_INTERRUPTS, "handling break...."); - *tty->flip.flag_buf_ptr = TTY_BREAK; - } - else if (*status & INTTYPE(UART_PARITYERR_INT)) { - *tty->flip.flag_buf_ptr = TTY_PARITY; - } - else if (*status & INTTYPE(UART_FRAMEERR_INT)) { - *tty->flip.flag_buf_ptr = TTY_FRAME; - } - if (*status & INTTYPE(UART_RXOVERRUN_INT)) { - /* - * Overrun is special, since it's - * reported immediately, and doesn't - * affect the current character - */ - if (tty->flip.count < TTY_FLIPBUF_SIZE) { - tty->flip.count++; - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - *tty->flip.flag_buf_ptr = TTY_OVERRUN; - } - } - } - - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; - - ignore_char: - - tty_flip_buffer_push(tty); -#endif -} - -static inline void transmit_char_pio(struct rs_port *port) -{ - /* While I'm able to transmit ... */ - for (;;) { - // printk("T%08x", (int)port->base[UART_R39XX_CTRL1]); - if (!(port->base[UART_R39XX_CTRL1] & UART_TX_EMPTY)) { - break; - } - else if (port->x_char) { - serial_out(port, UART_R39XX_DATA, port->x_char); - port->icount.tx++; - port->x_char = 0; - } - else if (port->gs.xmit_cnt <= 0 || port->gs.tty->stopped || - port->gs.tty->hw_stopped) { - break; - } - else { - serial_out(port, UART_R39XX_DATA, port->gs.xmit_buf[port->gs.xmit_tail++]); - port->icount.tx++; - port->gs.xmit_tail &= SERIAL_XMIT_SIZE-1; - if (--port->gs.xmit_cnt <= 0) { - break; - } - } - udelay(10); /* Allow things to happen - it take a while */ - } - - if (port->gs.xmit_cnt <= 0 || port->gs.tty->stopped || - port->gs.tty->hw_stopped) { - rs_disable_tx_interrupts(port); - } - - if (port->gs.xmit_cnt <= port->gs.wakeup_chars) { - if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - port->gs.tty->ldisc.write_wakeup) - (port->gs.tty->ldisc.write_wakeup)(port->gs.tty); - rs_dprintk (RS_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n", - port->gs.wakeup_chars); - wake_up_interruptible(&port->gs.tty->write_wait); - } -} - - - -static inline void check_modem_status(struct rs_port *port) -{ - /* We don't have a carrier detect line - but just respond - like we had one anyways so that open() becomes unblocked */ - wake_up_interruptible(&port->gs.open_wait); -} - -int count = 0; - -/* - * This is the serial driver's interrupt routine (inlined, because - * there are two different versions of this, one for each serial port, - * differing only by the bits used in interrupt status 2 register) - */ - -static inline void rs_rx_interrupt(int irq, void *dev_id, - struct pt_regs * regs, int intshift) -{ - struct rs_port * port; - unsigned long int2status; - unsigned long flags; - unsigned long ints; - - save_and_cli(flags); - - port = (struct rs_port *)dev_id; - /* rs_dprintk (RS_DEBUG_INTERRUPTS, "rs_interrupt (port %p, shift %d)...", port, intshift); */ - - /* Get the interrrupts we have enabled */ - int2status = IntStatus2 & IntEnable2; - - /* Get interrupts in easy to use form */ - ints = int2status >> intshift; - // printk("IR%03x%03x", (int)(IntStatus2 >> intshift), (int)(IntEnable2 >> intshift)); - - /* Clear any interrupts we might be about to handle */ - IntClear2 = int2status & ( - (INTTYPE(UART_RXOVERRUN_INT) | - INTTYPE(UART_FRAMEERR_INT) | - INTTYPE(UART_BREAK_INT) | - INTTYPE(UART_PARITYERR_INT) | - INTTYPE(UART_RX_INT)) << intshift); - - if (!port || !port->gs.tty) { - restore_flags(flags); - return; - } - - /* RX Receiver Holding Register Overrun */ - if (ints & INTTYPE(UART_RXOVERRUN_INT)) { - rs_dprintk (RS_DEBUG_INTERRUPTS, "overrun"); - port->icount.overrun++; - } - - /* RX Frame Error */ - if (ints & INTTYPE(UART_FRAMEERR_INT)) { - rs_dprintk (RS_DEBUG_INTERRUPTS, "frame error"); - port->icount.frame++; - } - - /* Break signal received */ - if (ints & INTTYPE(UART_BREAK_INT)) { - rs_dprintk (RS_DEBUG_INTERRUPTS, "break"); - port->icount.brk++; - } - - /* RX Parity Error */ - if (ints & INTTYPE(UART_PARITYERR_INT)) { - rs_dprintk (RS_DEBUG_INTERRUPTS, "parity error"); - port->icount.parity++; - } - - /* Receive byte (non-DMA) */ - if (ints & INTTYPE(UART_RX_INT)) { - receive_char_pio(port); - } - - /* - check_modem_status(); - */ - - // printk("OR%03x", (int)((IntStatus2 & IntEnable2) >> intshift)); - - restore_flags(flags); - -/* rs_dprintk (RS_DEBUG_INTERRUPTS, "end.\n"); */ - -} - -static inline void rs_tx_interrupt(int irq, void *dev_id, - struct pt_regs * regs, int intshift) -{ - struct rs_port * port; - unsigned long int2status; - unsigned long flags; - unsigned long ints; - - save_and_cli(flags); - - port = (struct rs_port *)dev_id; - /* rs_dprintk (RS_DEBUG_INTERRUPTS, "rs_interrupt (port %p, shift %d)...", port, intshift); */ - - /* Get the interrrupts we have enabled */ - int2status = IntStatus2 & IntEnable2; - - if (!port || !port->gs.tty) { - restore_flags(flags); - return; - } - - /* Get interrupts in easy to use form */ - ints = int2status >> intshift; - - /* Clear any interrupts we might be about to handle */ - IntClear2 = int2status & ( - (INTTYPE(UART_TX_INT) | - INTTYPE(UART_EMPTY_INT) | - INTTYPE(UART_TXOVERRUN_INT)) << intshift); - - //printk("IT%03x", (int)ints); - - /* TX holding register empty, so transmit byte (non-DMA) */ - if (ints & (INTTYPE(UART_TX_INT) | INTTYPE(UART_EMPTY_INT))) { - transmit_char_pio(port); - } - - /* TX Transmit Holding Register Overrun (shouldn't happen) */ - if (ints & INTTYPE(UART_TXOVERRUN_INT)) { - printk ( "rs: TX overrun\n"); - } - - /* - check_modem_status(); - */ - - restore_flags(flags); - -/* rs_dprintk (RS_DEBUG_INTERRUPTS, "end.\n"); */ - -} - -static void rs_rx_interrupt_uarta(int irq, void *dev_id, - struct pt_regs * regs) -{ - rs_rx_interrupt(irq, dev_id, regs, UARTA_SHIFT); -} - -static void rs_tx_interrupt_uarta(int irq, void *dev_id, - struct pt_regs * regs) -{ - rs_tx_interrupt(irq, dev_id, regs, UARTA_SHIFT); -} - -#if 0 -static void rs_interrupt_uartb(int irq, void *dev_id, - struct pt_regs * regs) -{ - rs_interrupt(irq, dev_id, regs, UARTB_SHIFT); -} -#endif - -/* - * ------------------------------------------------------------------- - * Here ends the serial interrupt routines. - * ------------------------------------------------------------------- - */ - - - - - -/* ********************************************************************** * - * Here are the routines that actually * - * interface with the generic_serial driver * - * ********************************************************************** */ - -static void rs_disable_tx_interrupts (void * ptr) -{ - struct rs_port *port = ptr; - unsigned long flags; - - save_and_cli(flags); - port->gs.flags &= ~GS_TX_INTEN; - - IntEnable2 &= ~((INTTYPE(UART_TX_INT) | - INTTYPE(UART_EMPTY_INT) | - INTTYPE(UART_TXOVERRUN_INT)) << port->intshift); - - IntClear2 = (INTTYPE(UART_TX_INT) | - INTTYPE(UART_EMPTY_INT) | - INTTYPE(UART_TXOVERRUN_INT)) << port->intshift; - - restore_flags(flags); -} - - -static void rs_enable_tx_interrupts (void * ptr) -{ - struct rs_port *port = ptr; - unsigned long flags; - - save_and_cli(flags); - - IntClear2 = (INTTYPE(UART_TX_INT) | - INTTYPE(UART_EMPTY_INT) | - INTTYPE(UART_TXOVERRUN_INT)) << port->intshift; - - IntEnable2 |= (INTTYPE(UART_TX_INT) | - INTTYPE(UART_EMPTY_INT) | - INTTYPE(UART_TXOVERRUN_INT)) << port->intshift; - - /* Send a char to start TX interrupts happening */ - transmit_char_pio(port); - - restore_flags(flags); -} - - -static void rs_disable_rx_interrupts (void * ptr) -{ - struct rs_port *port = ptr; - unsigned long flags; - - save_and_cli(flags); - - IntEnable2 &= ~((INTTYPE(UART_RX_INT) | - INTTYPE(UART_RXOVERRUN_INT) | - INTTYPE(UART_FRAMEERR_INT) | - INTTYPE(UART_BREAK_INT) | - INTTYPE(UART_PARITYERR_INT)) << port->intshift); - - IntClear2 = (INTTYPE(UART_RX_INT) | - INTTYPE(UART_RXOVERRUN_INT) | - INTTYPE(UART_FRAMEERR_INT) | - INTTYPE(UART_BREAK_INT) | - INTTYPE(UART_PARITYERR_INT)) << port->intshift; - - restore_flags(flags); -} - -static void rs_enable_rx_interrupts (void * ptr) -{ - struct rs_port *port = ptr; - unsigned long flags; - - save_and_cli(flags); - - IntEnable2 |= (INTTYPE(UART_RX_INT) | - INTTYPE(UART_RXOVERRUN_INT) | - INTTYPE(UART_FRAMEERR_INT) | - INTTYPE(UART_BREAK_INT) | - INTTYPE(UART_PARITYERR_INT)) << port->intshift; - - /* Empty the input buffer - apparently this is *vital* */ - while (port->base[UART_R39XX_CTRL1] & UART_RX_HOLD_FULL) { - serial_in(port, UART_R39XX_DATA); - } - - IntClear2 = (INTTYPE(UART_RX_INT) | - INTTYPE(UART_RXOVERRUN_INT) | - INTTYPE(UART_FRAMEERR_INT) | - INTTYPE(UART_BREAK_INT) | - INTTYPE(UART_PARITYERR_INT)) << port->intshift; - - restore_flags(flags); -} - - -static int rs_get_CD (void * ptr) -{ - struct rs_port *port = ptr; - func_enter2(); - - /* No Carried Detect in Hardware - just return true */ - - func_exit(); - return (1); -} - - - - -static void rs_shutdown_port (void * ptr) -{ - struct rs_port *port = ptr; - - func_enter(); - - port->gs.flags &= ~ GS_ACTIVE; - - /* Jim: Disable interrupts and power down port? */ - - func_exit(); -} - - - -static int rs_set_real_termios (void *ptr) -{ - struct rs_port *port = ptr; - int t; - - func_enter2(); - - switch (port->gs.baud) { - /* Save some typing work... */ -#define e(x) case x:t= SER_BAUD_ ## x ; break - e(300);e(600);e(1200);e(2400);e(4800);e(9600); - e(19200);e(38400);e(57600);e(76800);e(115200);e(230400); - case 0 :t = -1; - break; - default: - /* Can I return "invalid"? */ - t = SER_BAUD_9600; - printk (KERN_INFO "rs: unsupported baud rate: %d.\n", port->gs.baud); - break; - } -#undef e - if (t >= 0) { - /* Jim: Set Hardware Baud rate - there is some good - code in drivers/char/serial.c */ - - /* Program hardware for parity, data bits, stop bits (note: these are hardcoded to 8N1 */ - UartA_Ctrl1 &= 0xf000000f; - UartA_Ctrl1 &= ~(UART_DIS_TXD | SER_SEVEN_BIT | SER_EVEN_PARITY | SER_TWO_STOP); - -#define CFLAG port->gs.tty->termios->c_cflag - if (C_PARENB(port->gs.tty)) - if (!C_PARODD(port->gs.tty)) - UartA_Ctrl1 |= SER_EVEN_PARITY; - else - UartA_Ctrl1 |= SER_ODD_PARITY; - if ((CFLAG & CSIZE)==CS6) - printk(KERN_ERR "6 bits not supported\n"); - if ((CFLAG & CSIZE)==CS5) - printk(KERN_ERR "5 bits not supported\n"); - if ((CFLAG & CSIZE)==CS7) - UartA_Ctrl1 |= SER_SEVEN_BIT; - if (C_CSTOPB(port->gs.tty)) - UartA_Ctrl1 |= SER_TWO_STOP; - - UartA_Ctrl2 = t; - UartA_DMActl1 = 0; - UartA_DMActl2 = 0; - UartA_Ctrl1 |= UART_ON; - } - - /* Jim: Lots of good stuff in drivers/char/serial.c:change_speed() */ - - func_exit (); - return 0; -} - - -static int rs_chars_in_buffer (void * ptr) -{ - struct rs_port *port = ptr; - int scratch; -/* func_enter2(); */ - - scratch = serial_in(port, UART_R39XX_CTRL1); - -/* func_exit(); */ - return ( (scratch & UART_TX_EMPTY) ? 0 : 1 ); -} - - - -/* ********************************************************************** * - * Here are the routines that actually * - * interface with the rest of the system * - * ********************************************************************** */ - - -static int rs_open (struct tty_struct * tty, struct file * filp) -{ - struct rs_port *port; - int retval, line; - - func_enter(); - - if (!rs_initialized) { - return -EIO; - } - - line = MINOR(tty->device) - tty->driver.minor_start; - rs_dprintk (RS_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p)\n", - (int) current->pid, line, tty, current->tty); - - if ((line < 0) || (line >= RS_NPORTS)) - return -ENODEV; - - /* Pre-initialized already */ - port = & rs_ports[line]; - - rs_dprintk (RS_DEBUG_OPEN, "port = %p\n", port); - - tty->driver_data = port; - port->gs.tty = tty; - port->gs.count++; - - rs_dprintk (RS_DEBUG_OPEN, "starting port\n"); - - /* - * Start up serial port - */ - retval = gs_init_port(&port->gs); - rs_dprintk (RS_DEBUG_OPEN, "done gs_init\n"); - if (retval) { - port->gs.count--; - return retval; - } - - port->gs.flags |= GS_ACTIVE; - - rs_dprintk (RS_DEBUG_OPEN, "before inc_use_count (count=%d.\n", - port->gs.count); - if (port->gs.count == 1) { - MOD_INC_USE_COUNT; - } - rs_dprintk (RS_DEBUG_OPEN, "after inc_use_count\n"); - - /* Jim: Initialize port hardware here */ - - /* Enable high-priority interrupts for UARTA */ - IntEnable6 |= INT6_UARTARXINT; - rs_enable_rx_interrupts(&rs_ports[0]); - - retval = gs_block_til_ready(&port->gs, filp); - rs_dprintk (RS_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n", - retval, port->gs.count); - - if (retval) { - MOD_DEC_USE_COUNT; - port->gs.count--; - return retval; - } - /* tty->low_latency = 1; */ - - if ((port->gs.count == 1) && (port->gs.flags & ASYNC_SPLIT_TERMIOS)) { - if (tty->driver.subtype == SERIAL_TYPE_NORMAL) - *tty->termios = port->gs.normal_termios; - else - *tty->termios = port->gs.callout_termios; - rs_set_real_termios (port); - } - - port->gs.session = current->session; - port->gs.pgrp = current->pgrp; - func_exit(); - - /* Jim */ -/* cli(); */ - - return 0; - -} - - - -static void rs_close (void *ptr) -{ - func_enter (); - - /* Anything to do here? */ - - MOD_DEC_USE_COUNT; - func_exit (); -} - - -/* I haven't the foggiest why the decrement use count has to happen - here. The whole linux serial drivers stuff needs to be redesigned. - My guess is that this is a hack to minimize the impact of a bug - elsewhere. Thinking about it some more. (try it sometime) Try - running minicom on a serial port that is driven by a modularized - driver. Have the modem hangup. Then remove the driver module. Then - exit minicom. I expect an "oops". -- REW */ -static void rs_hungup (void *ptr) -{ - func_enter (); - MOD_DEC_USE_COUNT; - func_exit (); -} - -static int rs_ioctl (struct tty_struct * tty, struct file * filp, - unsigned int cmd, unsigned long arg) -{ - int rc; - struct rs_port *port = tty->driver_data; - int ival; - - /* func_enter2(); */ - - rc = 0; - switch (cmd) { - case TIOCGSOFTCAR: - rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0), - (unsigned int *) arg); - break; - case TIOCSSOFTCAR: - if ((rc = verify_area(VERIFY_READ, (void *) arg, - sizeof(int))) == 0) { - get_user(ival, (unsigned int *) arg); - tty->termios->c_cflag = - (tty->termios->c_cflag & ~CLOCAL) | - (ival ? CLOCAL : 0); - } - break; - case TIOCGSERIAL: - if ((rc = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(struct serial_struct))) == 0) - gs_getserial(&port->gs, (struct serial_struct *) arg); - break; - case TIOCSSERIAL: - if ((rc = verify_area(VERIFY_READ, (void *) arg, - sizeof(struct serial_struct))) == 0) - rc = gs_setserial(&port->gs, (struct serial_struct *) arg); - break; - default: - rc = -ENOIOCTLCMD; - break; - } - - /* func_exit(); */ - return rc; -} - - -/* - * This function is used to send a high-priority XON/XOFF character to - * the device - */ -static void rs_send_xchar(struct tty_struct * tty, char ch) -{ - struct rs_port *port = (struct rs_port *)tty->driver_data; - func_enter (); - - port->x_char = ch; - if (ch) { - /* Make sure transmit interrupts are on */ - rs_enable_tx_interrupts(tty); - } - - func_exit(); -} - - -/* - * ------------------------------------------------------------ - * rs_throttle() - * - * This routine is called by the upper-layer tty layer to signal that - * incoming characters should be throttled. - * ------------------------------------------------------------ - */ -static void rs_throttle(struct tty_struct * tty) -{ -#ifdef RS_DEBUG_THROTTLE - char buf[64]; - - printk("throttle %s: %d....\n", tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty)); -#endif - - func_enter (); - - if (I_IXOFF(tty)) - rs_send_xchar(tty, STOP_CHAR(tty)); - - func_exit (); -} - -static void rs_unthrottle(struct tty_struct * tty) -{ - struct rs_port *port = (struct rs_port *)tty->driver_data; -#ifdef RS_DEBUG_THROTTLE - char buf[64]; - - printk("unthrottle %s: %d....\n", tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty)); -#endif - - func_enter(); - - if (I_IXOFF(tty)) { - if (port->x_char) - port->x_char = 0; - else - rs_send_xchar(tty, START_CHAR(tty)); - } - - func_exit(); -} - - - - - -/* ********************************************************************** * - * Here are the initialization routines. * - * ********************************************************************** */ - -void * ckmalloc (int size) -{ - void *p; - - p = kmalloc(size, GFP_KERNEL); - if (p) - memset(p, 0, size); - return p; -} - - - -static int rs_init_portstructs(void) -{ - struct rs_port *port; - int i; - - func_enter(); - - /* Many drivers statically allocate the maximum number of ports - There is no reason not to allocate them dynamically. Is there? -- REW */ - rs_ports = ckmalloc(RS_NPORTS * sizeof (struct rs_port)); - if (!rs_ports) - return -ENOMEM; - - rs_termios = ckmalloc(RS_NPORTS * sizeof (struct termios *)); - if (!rs_termios) { - kfree (rs_ports); - return -ENOMEM; - } - - rs_termios_locked = ckmalloc(RS_NPORTS * sizeof (struct termios *)); - if (!rs_termios_locked) { - kfree (rs_ports); - kfree (rs_termios); - return -ENOMEM; - } - - /* Adjust the values in the "driver" */ - rs_driver.termios = rs_termios; - rs_driver.termios_locked = rs_termios_locked; - - port = rs_ports; - for (i=0; i < RS_NPORTS;i++) { - rs_dprintk (RS_DEBUG_INIT, "initing port %d\n", i); - port->gs.callout_termios = tty_std_termios; - port->gs.normal_termios = tty_std_termios; - port->gs.magic = SERIAL_MAGIC; - port->gs.close_delay = HZ/2; - port->gs.closing_wait = 30 * HZ; - port->gs.rd = &rs_real_driver; -#ifdef NEW_WRITE_LOCKING - port->gs.port_write_sem = MUTEX; -#endif -#ifdef DECLARE_WAITQUEUE - init_waitqueue_head(&port->gs.open_wait); - init_waitqueue_head(&port->gs.close_wait); -#endif - port->base = (i == 0) ? (unsigned long *) &UartA_Ctrl1 : - (unsigned long *) &UartB_Ctrl1; - port->intshift = (i == 0) ? UARTA_SHIFT : UARTB_SHIFT; - rs_dprintk (RS_DEBUG_INIT, "base %p intshift %d\n", - port->base, port->intshift); - port++; - } - - func_exit(); - return 0; -} - -static int rs_init_drivers(void) -{ - int error; - - func_enter(); - - memset(&rs_driver, 0, sizeof(rs_driver)); - rs_driver.magic = TTY_DRIVER_MAGIC; - rs_driver.driver_name = "serial"; - rs_driver.name = "ttyS"; - rs_driver.major = TTY_MAJOR; - rs_driver.minor_start = 64; - rs_driver.num = RS_NPORTS; - rs_driver.type = TTY_DRIVER_TYPE_SERIAL; - rs_driver.subtype = SERIAL_TYPE_NORMAL; - rs_driver.init_termios = tty_std_termios; - rs_driver.init_termios.c_cflag = - //B9600 | CS8 | CREAD | HUPCL | CLOCAL; - B115200 | CS8 | CREAD | HUPCL | CLOCAL; - rs_driver.flags = TTY_DRIVER_REAL_RAW; - rs_driver.refcount = &rs_refcount; - rs_driver.table = rs_table; - rs_driver.termios = rs_termios; - rs_driver.termios_locked = rs_termios_locked; - - rs_driver.open = rs_open; - rs_driver.close = gs_close; - rs_driver.write = gs_write; - rs_driver.put_char = gs_put_char; - rs_driver.flush_chars = gs_flush_chars; - rs_driver.write_room = gs_write_room; - rs_driver.chars_in_buffer = gs_chars_in_buffer; - rs_driver.flush_buffer = gs_flush_buffer; - rs_driver.ioctl = rs_ioctl; - rs_driver.throttle = rs_throttle; - rs_driver.unthrottle = rs_unthrottle; - rs_driver.set_termios = gs_set_termios; - rs_driver.stop = gs_stop; - rs_driver.start = gs_start; - rs_driver.hangup = gs_hangup; - - rs_callout_driver = rs_driver; - rs_callout_driver.name = "cua"; - rs_callout_driver.major = TTYAUX_MAJOR; - rs_callout_driver.subtype = SERIAL_TYPE_CALLOUT; - - if ((error = tty_register_driver(&rs_driver))) { - printk(KERN_ERR "Couldn't register serial driver, error = %d\n", - error); - return 1; - } - if ((error = tty_register_driver(&rs_callout_driver))) { - tty_unregister_driver(&rs_driver); - printk(KERN_ERR "Couldn't register callout driver, error = %d\n", - error); - return 1; - } - - func_exit(); - return 0; -} - - -static void rs_release_drivers(void) -{ - func_enter(); - tty_unregister_driver(&rs_driver); - tty_unregister_driver(&rs_callout_driver); -#ifdef CONFIG_PM - pm_unregister(pmdev); -#endif - func_exit(); -} - -#if defined(CONFIG_VTECH_HELIO) && defined(CONFIG_PM) -static -int pm_request(struct pm_dev* dev, pm_request_t req, void* data) -{ - static unsigned long ctrlA; - static unsigned long ctrlB; - static unsigned long clk; - static unsigned long out; - - switch (req) { - case PM_SUSPEND: - /* disable both uarts */ - ctrlA = UartA_Ctrl1 & (UART_ENABLE | UART_DIS_TXD); - UartA_Ctrl1 &= ~UART_ENABLE; -#if 0 /* would be nice if this worked, but it hangs the suspend process for me - 20001030 nop */ - while (UartA_Ctrl1 & UART_ON) - /*wait till its empty */; -#endif - UartA_Ctrl1 |= UART_DIS_TXD; - ctrlB = UartB_Ctrl1 & (UART_ENABLE | UART_DIS_TXD); - UartB_Ctrl1 &= ~UART_ENABLE; -#if 0 /* would be nice if this worked */ - while (UartB_Ctrl1 & UART_ON) - /*wait till its empty */; -#endif - UartB_Ctrl1 |= UART_DIS_TXD; - - /* turn the clocks off */ - clk = ClockControl & (CLK_EN_UART_A | CLK_EN_UART_B); - ClockControl &= ~(CLK_EN_UART_A | CLK_EN_UART_B); - - /* remember the state of these pins */ - out = MFIOOutput & (MFIO_PIN_UART_TX_ENABLE | - MFIO_PIN_UART_RX_DISABLE | - MFIO_PIN_MODEM_RTS); - - MFIOOutput &= ~MFIO_PIN_UART_TX_ENABLE; - MFIOOutput |= (MFIO_PIN_UART_RX_DISABLE | /* Set High (Disable RX) */ - MFIO_PIN_MODEM_RTS); - break; - - case PM_RESUME: - - /* restore the driver pin state */ - MFIOOutput = (MFIOOutput & ~(MFIO_PIN_UART_TX_ENABLE | - MFIO_PIN_UART_RX_DISABLE | - MFIO_PIN_MODEM_RTS)) | out; - - /* restore the clock */ - ClockControl = (ClockControl & ~(CLK_EN_UART_A | CLK_EN_UART_B)) | clk; - - /* restore the Uart state */ - UartA_Ctrl1 = (UartA_Ctrl1 & ~(UART_ENABLE | UART_DIS_TXD)) - | ctrlA; - UartB_Ctrl1 = (UartB_Ctrl1 & ~(UART_ENABLE | UART_DIS_TXD)) - | ctrlB; - break; - } - return 0; -} -#endif - - -int __init rs_init(void) -{ - int rc; - - func_enter(); - rs_dprintk (RS_DEBUG_INIT, "Initing serial module... (rs_debug=%d)\n", rs_debug); - - if (abs ((long) (&rs_debug) - rs_debug) < 0x10000) { - printk (KERN_WARNING "rs: rs_debug is an address, instead of a value. " - "Assuming -1.\n"); - printk ("(%p)\n", &rs_debug); - rs_debug=-1; - } - - rc = rs_init_portstructs (); - rs_init_drivers (); - if (request_irq(2, rs_tx_interrupt_uarta, SA_SHIRQ | SA_INTERRUPT, - "serial", &rs_ports[0])) { - printk(KERN_ERR "rs: Cannot allocate irq for UARTA.\n"); - rc = 0; - } - if (request_irq(3, rs_rx_interrupt_uarta, SA_SHIRQ | SA_INTERRUPT, - "serial", &rs_ports[0])) { - printk(KERN_ERR "rs: Cannot allocate irq for UARTA.\n"); - rc = 0; - } - - IntEnable6 |= INT6_UARTARXINT; - rs_enable_rx_interrupts(&rs_ports[0]); - -#ifndef CONFIG_SERIAL_CONSOLE - printk( "Initializing uart...\n" ); - earlyInitUartPR31700(); - printk( "okay\n" ); -#endif - - /* Note: I didn't do anything to enable the second UART */ - - if (rc >= 0) - rs_initialized++; - - func_exit(); - return 0; -} - - -void rs_exit(void) -{ - func_enter(); - rs_dprintk (RS_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n", rs_initialized); - if (rs_initialized) - rs_release_drivers (); - - kfree (rs_ports); - kfree (rs_termios); - kfree (rs_termios_locked); - func_exit(); - -} - -module_init(rs_init); -module_exit(rs_exit); - - -#ifdef DEBUG -void my_hd (unsigned char *addr, int len) -{ - int i, j, ch; - - for (i=0;i<len;i+=16) { - printk ("%08x ", (int) addr+i); - for (j=0;j<16;j++) { - printk ("%02x %s", addr[j+i], (j==7)?" ":""); - } - for (j=0;j<16;j++) { - ch = addr[j+i]; - printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch)); - } - printk ("\n"); - } -} -#endif - - - - -/* - * - * Very simple routines to get UART humming... - * - */ - -/* not static, its called from prom_init() too */ -void earlyInitUartPR31700(void) -{ - /* Setup master clock for UART */ - ClockControl &= ~CLK_SIBMCLKDIV_MASK; - ClockControl |= CLK_SIBMCLKDIR | CLK_ENSIBMCLK | - ((2 << CLK_SIBMCLKDIV_SHIFT) & CLK_SIBMCLKDIV_MASK) | - CLK_CSERSEL; - - /* Configure UARTA clock */ - ClockControl |= ((3 << CLK_CSERDIV_SHIFT) & CLK_CSERDIV_MASK) | - CLK_ENCSERCLK | CLK_EN_UART_A; - - /* Setup UARTA for 115200 baud, 8N1 */ - UartA_Ctrl1 &= 0xf000000f; - UartA_Ctrl1 &= ~UART_DIS_TXD; /* turn on txd */ - UartA_Ctrl1 &= ~SER_SEVEN_BIT; /* use 8-bit data */ - UartA_Ctrl1 &= ~SER_EVEN_PARITY; /* no parity */ - UartA_Ctrl1 &= ~SER_TWO_STOP; /* 1 stop bit */ - UartA_Ctrl2 = SER_BAUD_115200; - UartA_DMActl1 = 0; /* No DMA */ - UartA_DMActl2 = 0; /* No DMA */ - UartA_Ctrl1 |= UART_ON; /* Turn UART on */ - - while (~UartA_Ctrl1 & UART_ON); -} - -void serial_outc(unsigned char c) -{ - int i; - unsigned long int2; - #define BUSY_WAIT 10000 - - /* - * Turn UART A Interrupts off - */ - int2 = IntEnable2; - IntEnable2 &= - ~(INT2_UARTATXINT | INT2_UARTATXOVERRUN | INT2_UARTAEMPTY); - - /* - * The UART_TX_EMPTY bit in UartA_Ctrl1 seems - * not to be very reliable :-( - * - * Wait for the Tx register to become empty - */ - for (i = 0; !(IntStatus2 & INT2_UARTATXINT) && (i < BUSY_WAIT); i++); - - IntClear2 = INT2_UARTATXINT | INT2_UARTATXOVERRUN | INT2_UARTAEMPTY; - - UartA_Data = c; - for (i = 0; !(IntStatus2 & INT2_UARTATXINT) && (i < BUSY_WAIT); i++); - IntClear2 = INT2_UARTATXINT | INT2_UARTATXOVERRUN | INT2_UARTAEMPTY; - - IntEnable2 = int2; -} - -void serial_console_read_raw(struct console *co, char *buf, int size) -{ - int i; - unsigned int int2, flags; - - save_and_cli(flags); - - int2 = IntEnable2; - IntEnable2 = 0; - - for (i=0; i<size; i++) { - while (!(UartA_Ctrl1 & UART_RX_HOLD_FULL)) - ; - buf[i] = UartA_Data; - udelay(10); /* Allow things to happen - it take a while */ - } - IntEnable2 = int2; - restore_flags(flags); -} - -int serial_console_wait_key(struct console *co) -{ - unsigned int int2, res; - - int2 = IntEnable2; - IntEnable2 = 0; - - while (!(UartA_Ctrl1 & UART_RX_HOLD_FULL)) - ; - res = UartA_Data; - udelay(10); /* Allow things to happen - it take a while */ - - IntEnable2 = int2; - return res; -} - -/* used in slip? in Slip??? SLIP /ought/ to work with sl->tty! (PM2000) */ -void serial_console_write_raw(struct console *co, const char *s, - unsigned count) -{ - unsigned int i; - - for (i = 0; i < count; i++) { - serial_outc(*s++); - } -} - -#ifdef CONFIG_SERIAL_CONSOLE - -void serial_console_write(struct console *co, const char *s, - unsigned count) -{ - unsigned int i; - - for (i = 0; i < count; i++) { - if (*s == '\n') - serial_outc('\r'); - serial_outc(*s++); - } -} - -static kdev_t serial_console_device(struct console *c) -{ - return MKDEV(TTY_MAJOR, 64 + c->index); -} - -static __init int serial_console_setup(struct console *co, char *options) -{ - earlyInitUartPR31700(); - - return 0; -} - - -static struct console sercons = { - name: "ttyS", - write: serial_console_write, - device: serial_console_device, - wait_key: serial_console_wait_key, - setup: serial_console_setup, - flags: CON_PRINTBUFFER, - index: -1 -}; - -/* - * Register console. - */ - -void __init serial_console_init(void) -{ - register_console(&sercons); -} - -#endif diff --git a/arch/mips/philips/drivers/uart-pr31700.h b/arch/mips/philips/drivers/uart-pr31700.h deleted file mode 100644 index 221baa89f..000000000 --- a/arch/mips/philips/drivers/uart-pr31700.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Serial driver for r39xx - * - * Copyright (C) 2000 Jim Pick <jim@jimpick.com> - * - * Inspired by, and/or includes bits from: - * - * drivers/char/serial.c (standard serial driver) - * drivers/char/sx.c (use of generic_serial interface) - * drivers/char/esp.c (another UART that uses DMA) - * arch/mips/vr41xx/serial.c (another MIPS serial driver) - * - * Please see those files for credits. - * - * Also, the original rough serial console code was: - * - * Copyright (C) 1999 Harald Koerfgen - * - * $Id: r39xx_serial.h,v 1.3 2000/11/01 03:02:27 nop Exp $ - */ - -#include <linux/serial.h> -#include <linux/generic_serial.h> - - -/* r39xx UART Register Offsets */ -#define UART_R39XX_CTRL1 0 -#define UART_R39XX_CTRL2 1 -#define UART_R39XX_DMACTRL1 2 -#define UART_R39XX_DMACTRL2 3 -#define UART_R39XX_DMACNT 4 -#define UART_R39XX_DATA 5 - -/* UART Interrupt (Interrupt 2) bits (UARTA,UARTB) */ -#define UART_RX_INT 9 /* receiver holding register full (31, 21) */ -#define UART_RXOVERRUN_INT 8 /* receiver overrun error (30, 20) */ -#define UART_FRAMEERR_INT 7 /* receiver frame error (29, 19) */ -#define UART_BREAK_INT 6 /* received break signal (28, 18) */ -#define UART_PARITYERR_INT 5 /* receiver parity error (27, 17) */ -#define UART_TX_INT 4 /* transmit holding register empty (26, 16) */ -#define UART_TXOVERRUN_INT 3 /* transmit overrun error (25, 15) */ -#define UART_EMPTY_INT 2 /* both trans/recv regs empty (24, 14) */ -#define UART_DMAFULL_INT 1 /* DMA at end of buffer (23, 13) */ -#define UART_DMAHALF_INT 0 /* DMA halfway through buffer */ (22, 12) */ - -#define UARTA_SHIFT 22 -#define UARTB_SHIFT 12 - -#define INT2BIT(interrupttype, intshift) (1 << (interrupttype + intshift)) -#define INTTYPE(interrupttype) (1 << interrupttype) - -/* Driver status flags */ -#define RS_STAT_RX_TIMEOUT 0x01 -#define RS_STAT_DMA_RX 0x02 -#define RS_STAT_DMA_TX 0x04 -#define RS_STAT_NEVER_DMA 0x08 -#define RS_STAT_USE_PIO 0x10 - -/* - This driver can spew a whole lot of debugging output at you. If you - need maximum performance, you should disable the DEBUG define. To - aid in debugging in the field, I'm leaving the compile-time debug - features enabled, and disable them "runtime". That allows me to - instruct people with problems to enable debugging without requiring - them to recompile... -*/ -#define DEBUG - - -#ifdef DEBUG -#define rs_dprintk(f, str...) if (rs_debug & f) printk (str) -#else -#define rs_dprintk(f, str...) /* nothing */ -#endif - - - -#define func_enter() rs_dprintk (RS_DEBUG_FLOW, "rs: enter " __FUNCTION__ "\n") -#define func_exit() rs_dprintk (RS_DEBUG_FLOW, "rs: exit " __FUNCTION__ "\n") - -#define func_enter2() rs_dprintk (RS_DEBUG_FLOW, "rs: enter " __FUNCTION__ \ - "(port %p, base %p)\n", port, port->base) - - -/* Debug flags. Add these together to get more debug info. */ - -#define RS_DEBUG_OPEN 0x00000001 -#define RS_DEBUG_SETTING 0x00000002 -#define RS_DEBUG_FLOW 0x00000004 -#define RS_DEBUG_MODEMSIGNALS 0x00000008 -#define RS_DEBUG_TERMIOS 0x00000010 -#define RS_DEBUG_TRANSMIT 0x00000020 -#define RS_DEBUG_RECEIVE 0x00000040 -#define RS_DEBUG_INTERRUPTS 0x00000080 -#define RS_DEBUG_PROBE 0x00000100 -#define RS_DEBUG_INIT 0x00000200 -#define RS_DEBUG_CLEANUP 0x00000400 -#define RS_DEBUG_CLOSE 0x00000800 -#define RS_DEBUG_FIRMWARE 0x00001000 -#define RS_DEBUG_MEMTEST 0x00002000 -#define RS_DEBUG_THROTTLE 0x00004000 - -#define RS_DEBUG_ALL 0xffffffff - - -#define RS_NPORTS 2 - -struct rs_port { - /* must be first field! */ - struct gs_port gs; - - /* rest is private for this driver */ - unsigned long *base; - int intshift; /* for interrupt register */ - struct wait_queue *shutdown_wait; - int stat_flags; - struct async_icount icount; /* kernel counters for the 4 - input interrupts */ - int read_status_mask; - int ignore_status_mask; - int x_char; /* xon/xoff character */ -}; - - - -#define SERIAL_MAGIC 0x5301 diff --git a/arch/mips/philips/nino/Makefile b/arch/mips/philips/nino/Makefile index 7d31a66fb..bcdd9b2e3 100644 --- a/arch/mips/philips/nino/Makefile +++ b/arch/mips/philips/nino/Makefile @@ -17,10 +17,17 @@ all: nino.o obj-y := int-handler.o setup.o irq.o time.o reset.o rtc.o prom.o power.o wbflush.o -obj-$(CONFIG_BLK_DEV_INITRD) += ../boot/ramdisk.o +int-handler.o: int-handler.S obj-$(CONFIG_REMOTE_DEBUG) += kgdb.o -int-handler.o: int-handler.S +obj-$(CONFIG_BLK_DEV_INITRD) += ramdisk.o + +ramdisk.o: + $(MAKE) -C ramdisk + ln -sf ramdisk/ramdisk.o ramdisk.o + +clean: + rm -f *.o include $(TOPDIR)/Rules.make diff --git a/arch/mips/philips/nino/int-handler.S b/arch/mips/philips/nino/int-handler.S index 90d7f8818..ff2e48e90 100644 --- a/arch/mips/philips/nino/int-handler.S +++ b/arch/mips/philips/nino/int-handler.S @@ -1,22 +1,21 @@ /* * linux/arch/mips/philips/nino/int-handler.S * - * Copyright (C) 1999 Harald Koerfgen (Harald.Koerfgen@home.ivm.de) + * Copyright (C) 1999 Harald Koerfgen * Copyright (C) 2000 Jim Pick (jim@jimpick.com) - * Copyright (C) 2001 Steven Hill (sjhill@realitydiluted.com) + * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * Interrupt handler for PR31700. + * Interrupt handler for Philips Nino. */ #include <asm/asm.h> #include <asm/regdef.h> #include <asm/mipsregs.h> #include <asm/stackframe.h> -#include <asm/philips/pr31700.h> - +#include <asm/tx3912.h> .data .globl HighPriVect diff --git a/arch/mips/philips/nino/irq.c b/arch/mips/philips/nino/irq.c index 71aba8599..3d7a88afe 100644 --- a/arch/mips/philips/nino/irq.c +++ b/arch/mips/philips/nino/irq.c @@ -2,15 +2,15 @@ * linux/arch/mips/philips/nino/irq.c * * Copyright (C) 1992 Linus Torvalds - * Copyright (C) 1999 Harald Koerfgen (Harald.Koerfgen@home.ivm.de) + * Copyright (C) 1999 Harald Koerfgen * Copyright (C) 2000 Pavel Machek (pavel@suse.cz) - * Copyright (C) 2001 Steven Hill (sjhill@realitydiluted.com) + * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * Generic interrupt handler for PR31700. + * Generic interrupt handler for Philips Nino. */ #include <linux/errno.h> #include <linux/init.h> @@ -30,7 +30,7 @@ #include <asm/irq.h> #include <asm/mipsregs.h> #include <asm/system.h> -#include <asm/philips/pr31700.h> +#include <asm/tx3912.h> unsigned long spurious_count = 0; @@ -45,10 +45,12 @@ static inline void mask_irq(unsigned int irq_nr) IntEnable6 &= ~INT6_PERIODICINT; break; - case 3: /* Serial port receive interrupt */ + case 3: + /* Serial port receive interrupt */ break; - case 2: /* Serial port transmit interrupt */ + case 2: + /* Serial port transmit interrupt */ break; default: @@ -63,12 +65,12 @@ static inline void unmask_irq(unsigned int irq_nr) IntEnable6 |= INT6_PERIODICINT; break; - case 3: /* Serial port receive interrupt */ - /* FIXME: currently handled in driver */ + case 3: + /* Serial port receive interrupt */ break; - case 2: /* Serial port transmit interrupt */ - /* FIXME: currently handled in driver */ + case 2: + /* Serial port transmit interrupt */ break; default: @@ -149,17 +151,24 @@ asmlinkage void do_IRQ(int irq, struct pt_regs *regs) struct irqaction *action; int do_random, cpu; + if (irq == 20) { + if (IntStatus2 & 0xfffff00) { + if (IntStatus2 & 0x0f000000) + return do_IRQ(2, regs); + } + } + cpu = smp_processor_id(); irq_enter(cpu, irq); kstat.irqs[cpu][irq]++; if (irq == 20) { - printk("20 %08lx %08lx\n %08lx %08lx\n %08lx\n", - IntStatus1, IntStatus2, IntStatus3, - IntStatus4, IntStatus5 ); - printk("20 %08lx %08lx\n %08lx %08lx\n %08lx\n", - IntEnable1, IntEnable2, IntEnable3, - IntEnable4, IntEnable5 ); + printk("20 %08lx %08lx\n %08lx %08lx\n %08lx\n", + IntStatus1, IntStatus2, IntStatus3, + IntStatus4, IntStatus5 ); + printk("20 %08lx %08lx\n %08lx %08lx\n %08lx\n", + IntEnable1, IntEnable2, IntEnable3, + IntEnable4, IntEnable5 ); } @@ -179,6 +188,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs *regs) unmask_irq(irq); __cli(); } else { + IntClear1 = ~0; IntClear3 = ~0; IntClear4 = ~0; IntClear5 = ~0; diff --git a/arch/mips/philips/nino/kgdb.c b/arch/mips/philips/nino/kgdb.c index 0bb03e86f..0d3ebf23b 100644 --- a/arch/mips/philips/nino/kgdb.c +++ b/arch/mips/philips/nino/kgdb.c @@ -1,16 +1,16 @@ /* * linux/arch/mips/philips/nino/kgdb.c * - * Copyright (C) 2001 Steven Hill (sjhill@realitydiluted.com) + * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * Low level functions for remote debugging on PR31700. + * Kernel debugging on the Philips Nino. */ #include <asm/system.h> -#include <asm/philips/pr31700.h> +#include <asm/tx3912.h> static int remoteDebugInitialized = 0; diff --git a/arch/mips/philips/nino/power.c b/arch/mips/philips/nino/power.c index 907b134b7..fccf2fbdb 100644 --- a/arch/mips/philips/nino/power.c +++ b/arch/mips/philips/nino/power.c @@ -2,15 +2,15 @@ * linux/arch/mips/philips/nino/power.c * * Copyright (C) 2000 Jim Pick <jim@jimpick.com> - * Copyright (C) 2001 Steven Hill (sjhill@realitydiluted.com) + * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * Routines for power management on the Nino. + * Power management routines on the Philips Nino. */ -#include <asm/philips/pr31700.h> +#include <asm/tx3912.h> void nino_wait(void) { diff --git a/arch/mips/philips/nino/prom.c b/arch/mips/philips/nino/prom.c index bb4582099..b83d7a084 100644 --- a/arch/mips/philips/nino/prom.c +++ b/arch/mips/philips/nino/prom.c @@ -1,5 +1,5 @@ /* - * linux/arch/mips/philips-hpc/nino/prom.c + * linux/arch/mips/philips/nino/prom.c * * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) * @@ -7,50 +7,30 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * Early initialization code for the Nino. + * Early initialization code for the Philips Nino. */ #include <linux/config.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/string.h> #include <asm/bootinfo.h> +#include <asm/addrspace.h> +#include <asm/page.h> char arcs_cmdline[COMMAND_LINE_SIZE]; -#ifdef CONFIG_LL_DEBUG -extern void init_uart(void); - -int __init prom_printf(const char * fmt, ...) -{ - extern void serial_outc(char); - static char buf[1024]; - va_list args; - char c; - int i = 0; - - /* - * Printing messages via serial port - */ - va_start(args, fmt); - vsprintf(buf, fmt, args); - va_end(args); - - for (i = 0; buf[i] != '\0'; i++) { - c = buf[i]; - if (c == '\n') - serial_outc('\r'); - serial_outc(c); - } - - return i; -} +#ifdef CONFIG_FB_TX3912 +extern u_long tx3912fb_paddr; +extern u_long tx3912fb_vaddr; +extern u_long tx3912fb_size; #endif /* Do basic initialization */ void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec) { - int i; + u_long free_end, mem_size; + u_int i; /* * collect args and prepare cmd_line @@ -61,20 +41,37 @@ void __init prom_init(int argc, char **argv, strcat(arcs_cmdline, " "); } -#ifdef CONFIG_LL_DEBUG - earlyInitUartPR31700(); -#endif - mips_machgroup = MACH_GROUP_PHILIPS; mips_machtype = MACH_PHILIPS_NINO; - /* Add memory region */ #ifdef CONFIG_NINO_4MB - add_memory_region(0, 4 << 20, BOOT_MEM_RAM); + mem_size = 4 << 20; #elif CONFIG_NINO_8MB - add_memory_region(0, 8 << 20, BOOT_MEM_RAM); + mem_size = 8 << 20; #elif CONFIG_NINO_16MB - add_memory_region(0, 16 << 20, BOOT_MEM_RAM); + mem_size = 16 << 20; +#endif + +#ifdef CONFIG_FB_TX3912 + /* + * The LCD controller requires that the framebuffer + * start address fall within a 1MB segment and is + * aligned on a 16 byte boundary. The way to assure + * this is to place the framebuffer at the end of + * memory and mark it as reserved. + */ + free_end = (mem_size - tx3912fb_size) & PAGE_MASK; + add_memory_region(0, free_end, BOOT_MEM_RAM); + add_memory_region(free_end, (mem_size - free_end), BOOT_MEM_RESERVED); + + /* + * Calculate physical and virtual addresses for + * the beginning of the framebuffer. + */ + tx3912fb_paddr = PHYSADDR(free_end); + tx3912fb_vaddr = KSEG1ADDR(free_end); +#else + add_memory_region(0, mem_size, BOOT_MEM_RAM); #endif } diff --git a/arch/mips/philips/drivers/Makefile b/arch/mips/philips/nino/ramdisk/Makefile index a0e316db0..1e7658863 100644 --- a/arch/mips/philips/drivers/Makefile +++ b/arch/mips/philips/nino/ramdisk/Makefile @@ -1,20 +1,12 @@ # -# Makefile for the Philips Nino specific parts of the kernel +# Makefile for the Philips Nino ramdisk # # Note! Dependencies are done automagically by 'make dep', which also # removes any old dependencies. DON'T put your own dependencies here # unless it's something special (ie not a .c file). # -.S.s: - $(CPP) $(AFLAGS) $< -o $@ -.S.o: - $(CC) $(AFLAGS) -c $< -o $@ - -O_TARGET := drivers.o - -all: drivers.o - -obj-$(CONFIG_SERIAL) += uart-pr31700.o generic_serial.o +ramdisk.o: ramdisk.gz ld.script + $(LD) -T ld.script -b binary -o $@ ramdisk.gz include $(TOPDIR)/Rules.make diff --git a/arch/mips/philips/nino/ramdisk/ld.script b/arch/mips/philips/nino/ramdisk/ld.script new file mode 100644 index 000000000..87fd81108 --- /dev/null +++ b/arch/mips/philips/nino/ramdisk/ld.script @@ -0,0 +1,11 @@ +OUTPUT_FORMAT("ecoff-littlemips") +OUTPUT_ARCH(mips) +SECTIONS +{ + .data : + { + __rd_start = .; + *(.data) + __rd_end = .; + } +} diff --git a/arch/mips/philips/nino/reset.c b/arch/mips/philips/nino/reset.c index c809b6b93..51113f1bd 100644 --- a/arch/mips/philips/nino/reset.c +++ b/arch/mips/philips/nino/reset.c @@ -1,13 +1,13 @@ /* * linux/arch/mips/philips/nino/reset.c * - * Copyright (C) 2001 Steven Hill (sjhill@realitydiluted.com) + * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * Generic restart, halt and power off functions. + * Generic restart, halt and power off functions for Philips Nino. */ #include <linux/init.h> #include <asm/reboot.h> diff --git a/arch/mips/philips/nino/rtc.c b/arch/mips/philips/nino/rtc.c index 0b2584411..bcca11cf7 100644 --- a/arch/mips/philips/nino/rtc.c +++ b/arch/mips/philips/nino/rtc.c @@ -1,14 +1,15 @@ /* - * linux/arch/mips/philips-mobile/nino/rtc.c + * linux/arch/mips/philips/nino/rtc.c * - * Copyright (C) 2001 Steven Hill (sjhill@realitydiluted.com) + * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * Functions to access the RTC on the PR31700 chip. + * Functions to access RTC on the Philips Nino. */ +#include <linux/spinlock.h> #include <linux/mc146818rtc.h> static unsigned char nino_rtc_read_data(unsigned long addr) diff --git a/arch/mips/philips/nino/setup.c b/arch/mips/philips/nino/setup.c index 2554d3bfb..85e247cb4 100644 --- a/arch/mips/philips/nino/setup.c +++ b/arch/mips/philips/nino/setup.c @@ -1,13 +1,13 @@ /* * linux/arch/mips/philips/nino/setup.c * - * Copyright (C) 2001 Steven Hill (sjhill@realitydiluted.com) + * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * Interrupt and exception initialization for PR31700. + * Interrupt and exception initialization for Philips Nino. */ #include <linux/console.h> #include <linux/init.h> @@ -18,7 +18,7 @@ #include <asm/gdb-stub.h> #include <asm/irq.h> #include <asm/wbflush.h> -#include <asm/philips/pr31700.h> +#include <asm/tx3912.h> extern struct rtc_ops nino_rtc_ops; @@ -58,7 +58,7 @@ static void __init nino_irq_setup(void) * Enable only the interrupts for the UART and negative * edge (1-to-0) triggered multi-function I/O pins. */ - clear_cp0_status(ST0_BEV); + change_cp0_status(ST0_BEV, 0); tmp = read_32bit_cp0_register(CP0_STATUS); change_cp0_status(ST0_IM, tmp | IE_IRQ2 | IE_IRQ4); @@ -75,6 +75,8 @@ static void __init nino_irq_setup(void) static __init void nino_time_init(struct irqaction *irq) { + unsigned int scratch = 0; + /* * Enable periodic interrupts */ @@ -83,7 +85,10 @@ static __init void nino_time_init(struct irqaction *irq) RTCperiodTimer = PER_TIMER_COUNT; RTCtimerControl = TIM_ENPERTIMER; IntEnable5 |= INT5_PERIODICINT; - ClockControl |= CLK_ENTIMERCLK; + + scratch = inl(TX3912_CLK_CTRL_BASE); + scratch |= TX3912_CLK_CTRL_ENTIMERCLK; + outl(scratch, TX3912_CLK_CTRL_BASE); /* Enable all interrupts */ IntEnable6 |= INT6_GLOBALEN | INT6_PERIODICINT; @@ -96,7 +101,7 @@ void __init nino_setup(void) board_time_init = nino_time_init; /* Base address to use for PC type I/O accesses */ - mips_io_port_base = KSEG1ADDR(0x08000000); + mips_io_port_base = KSEG1ADDR(0xB0C00000); setup_nino_reset_vectors(); diff --git a/arch/mips/philips/nino/time.c b/arch/mips/philips/nino/time.c index b3bc87e7e..5a3c368c1 100644 --- a/arch/mips/philips/nino/time.c +++ b/arch/mips/philips/nino/time.c @@ -1,15 +1,15 @@ /* * linux/arch/mips/philips/nino/time.c * - * Copyright (C) 1999 Harald Koerfgen (Harald.Koerfgen@home.ivm.de) + * Copyright (C) 1999 Harald Koerfgen * Copyright (C) 2000 Pavel Machek (pavel@suse.cz) - * Copyright (C) 2001 Steven Hill (sjhill@realitydiluted.com) + * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * Time handling details for PR31700. + * Time handling functinos for Philips Nino. */ #include <linux/errno.h> #include <linux/init.h> @@ -21,7 +21,7 @@ #include <linux/interrupt.h> #include <linux/timex.h> #include <linux/delay.h> -#include <asm/philips/pr31700.h> +#include <asm/tx3912.h> extern volatile unsigned long wall_jiffies; extern rwlock_t xtime_lock; diff --git a/arch/mips/philips/nino/wbflush.c b/arch/mips/philips/nino/wbflush.c index 2b1056259..f70b5ef69 100644 --- a/arch/mips/philips/nino/wbflush.c +++ b/arch/mips/philips/nino/wbflush.c @@ -1,13 +1,13 @@ /* * linux/arch/mips/philips/nino/wbflush.c * - * Copyright (C) 2001 Steven Hill (sjhill@realitydiluted.com) + * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * Function to flush the write buffer on the PR31700 chip. + * Function to flush the write buffer on the Philips Nino. */ #include <linux/init.h> |