#include <linux/keyboard.h>
#include <linux/init.h>
#include <linux/pm.h>
-#include <linux/pm_legacy.h>
#include <linux/bitops.h>
#include <linux/delay.h>
struct tty_driver *serial_driver;
-/* serial subtype definitions */
-#define SERIAL_TYPE_NORMAL 1
-
/* number of characters left in xmit buffer before we ask for more */
#define WAKEUP_CHARS 256
local_irq_restore(flags);
}
-static void rs_put_char(char ch)
+static int rs_put_char(char ch)
{
int flags, loops = 0;
UTX_TXDATA = ch;
udelay(5);
local_irq_restore(flags);
+ return 1;
}
static void rs_start(struct tty_struct *tty)
{
#if 0
if(status & DCD) {
- if((info->tty->termios->c_cflag & CRTSCTS) &&
+ if((info->port.tty->termios->c_cflag & CRTSCTS) &&
((info->curregs[3] & AUTO_ENAB)==0)) {
info->curregs[3] |= AUTO_ENAB;
info->pendregs[3] |= AUTO_ENAB;
static void receive_chars(struct m68k_serial *info, unsigned short rx)
{
- struct tty_struct *tty = info->tty;
+ struct tty_struct *tty = info->port.tty;
m68328_uart *uart = &uart_addr[info->line];
unsigned char ch, flag;
goto clear_and_return;
}
- if((info->xmit_cnt <= 0) || info->tty->stopped) {
+ if((info->xmit_cnt <= 0) || info->port.tty->stopped) {
/* That's peculiar... TX ints off */
uart->ustcnt &= ~USTCNT_TX_INTR_MASK;
goto clear_and_return;
return IRQ_HANDLED;
}
-static void do_softint(void *private)
+static void do_softint(struct work_struct *work)
{
- struct m68k_serial *info = (struct m68k_serial *) private;
+ struct m68k_serial *info = container_of(work, struct m68k_serial, tqueue);
struct tty_struct *tty;
- tty = info->tty;
+ tty = info->port.tty;
if (!tty)
return;
#if 0
* do_serial_hangup() -> tty->hangup() -> rs_hangup()
*
*/
-static void do_serial_hangup(void *private)
+static void do_serial_hangup(struct work_struct *work)
{
- struct m68k_serial *info = (struct m68k_serial *) private;
+ struct m68k_serial *info = container_of(work, struct m68k_serial, tqueue_hangup);
struct tty_struct *tty;
- tty = info->tty;
+ tty = info->port.tty;
if (!tty)
return;
uart->ustcnt = USTCNT_UEN | USTCNT_RXEN | USTCNT_RX_INTR_MASK;
#endif
- if (info->tty)
- clear_bit(TTY_IO_ERROR, &info->tty->flags);
+ if (info->port.tty)
+ clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
/*
info->xmit_buf = 0;
}
- if (info->tty)
- set_bit(TTY_IO_ERROR, &info->tty->flags);
+ if (info->port.tty)
+ set_bit(TTY_IO_ERROR, &info->port.tty->flags);
info->flags &= ~S_INITIALIZED;
local_irq_restore(flags);
unsigned cflag;
int i;
- if (!info->tty || !info->tty->termios)
+ if (!info->port.tty || !info->port.tty->termios)
return;
- cflag = info->tty->termios->c_cflag;
+ cflag = info->port.tty->termios->c_cflag;
if (!(port = info->port))
return;
tty_wait_until_sent(tty, 0);
send_break(info, arg ? arg*(100) : 250);
return 0;
- case TIOCGSOFTCAR:
- error = put_user(C_CLOCAL(tty) ? 1 : 0,
- (unsigned long *) arg);
- if (error)
- return error;
- return 0;
- case TIOCSSOFTCAR:
- get_user(arg, (unsigned long *) arg);
- tty->termios->c_cflag =
- ((tty->termios->c_cflag & ~CLOCAL) |
- (arg ? CLOCAL : 0));
- return 0;
case TIOCGSERIAL:
if (access_ok(VERIFY_WRITE, (void *) arg,
sizeof(struct serial_struct)))
{
struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
- if (tty->termios->c_cflag == old_termios->c_cflag)
- return;
-
change_speed(info);
if ((old_termios->c_cflag & CRTSCTS) &&
uart->ustcnt &= ~(USTCNT_RXEN | USTCNT_RX_INTR_MASK);
shutdown(info);
- if (tty->driver->flush_buffer)
- tty->driver->flush_buffer(tty);
+ rs_flush_buffer(tty);
tty_ldisc_flush(tty);
tty->closing = 0;
info->event = 0;
- info->tty = 0;
+ info->port.tty = NULL;
#warning "This is not and has never been valid so fix it"
#if 0
if (tty->ldisc.num != ldiscs[N_TTY].num) {
info->event = 0;
info->count = 0;
info->flags &= ~S_NORMAL_ACTIVE;
- info->tty = 0;
+ info->port.tty = NULL;
wake_up_interruptible(&info->open_wait);
}
info->count++;
tty->driver_data = info;
- info->tty = tty;
+ info->port.tty = tty;
/*
* Start up serial port
printk("MC68328 serial driver version 1.00\n");
}
-#ifdef CONFIG_PM_LEGACY
-/* Serial Power management
- * The console (currently fixed at line 0) is a special case for power
- * management because the kernel is so chatty. The console will be
- * explicitly disabled my our power manager as the last minute, so we won't
- * mess with it here.
- */
-static struct pm_dev *serial_pm[NR_PORTS];
-
-static int serial_pm_callback(struct pm_dev *dev, pm_request_t request, void *data)
-{
- struct m68k_serial *info = (struct m68k_serial *)dev->data;
-
- if(info == NULL)
- return -1;
-
- /* special case for line 0 - pm restores it */
- if(info->line == 0)
- return 0;
-
- switch (request) {
- case PM_SUSPEND:
- shutdown(info);
- break;
-
- case PM_RESUME:
- startup(info);
- break;
- }
- return 0;
-}
-
-void shutdown_console(void)
-{
- struct m68k_serial *info = &m68k_soft[0];
-
- /* HACK: wait a bit for any pending printk's to be dumped */
- {
- int i = 10000;
- while(i--);
- }
-
- shutdown(info);
-}
-
-void startup_console(void)
-{
- struct m68k_serial *info = &m68k_soft[0];
- startup(info);
-}
-#endif /* CONFIG_PM_LEGACY */
-
-
static const struct tty_operations rs_ops = {
.open = rs_open,
.close = rs_close,
info = &m68k_soft[i];
info->magic = SERIAL_MAGIC;
info->port = (int) &uart_addr[i];
- info->tty = 0;
+ info->port.tty = NULL;
info->irq = uart_irqs[i];
info->custom_divisor = 16;
info->close_delay = 50;
info->event = 0;
info->count = 0;
info->blocked_open = 0;
- INIT_WORK(&info->tqueue, do_softint, info);
- INIT_WORK(&info->tqueue_hangup, do_serial_hangup, info);
+ INIT_WORK(&info->tqueue, do_softint);
+ INIT_WORK(&info->tqueue_hangup, do_serial_hangup);
init_waitqueue_head(&info->open_wait);
init_waitqueue_head(&info->close_wait);
info->line = i;
if (request_irq(uart_irqs[i],
rs_interrupt,
- IRQ_FLG_STD,
+ IRQF_DISABLED,
"M68328_UART", NULL))
panic("Unable to attach 68328 serial interrupt\n");
-#ifdef CONFIG_PM_LEGACY
- serial_pm[i] = pm_register(PM_SYS_DEV, PM_SYS_COM, serial_pm_callback);
- if (serial_pm[i])
- serial_pm[i]->data = info;
-#endif
}
local_irq_restore(flags);
return 0;