X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fserial%2Fip22zilog.c;h=651772474ac17d6687b4722f337b06765c2e7524;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=93ce80526fb71cc527b6fbb50c0714bca06d4787;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c index 93ce80526..651772474 100644 --- a/drivers/serial/ip22zilog.c +++ b/drivers/serial/ip22zilog.c @@ -47,8 +47,6 @@ #include "ip22zilog.h" -int ip22serial_current_minor = 64; - void ip22_do_break(void); /* @@ -59,10 +57,10 @@ void ip22_do_break(void); #define ZSDELAY_LONG() udelay(20) #define ZS_WSYNC(channel) do { } while (0) -#define NUM_IP22ZILOG 1 -#define NUM_CHANNELS (NUM_IP22ZILOG * 2) +#define NUM_IP22ZILOG 1 +#define NUM_CHANNELS (NUM_IP22ZILOG * 2) -#define ZS_CLOCK 4915200 /* Zilog input clock rate. */ +#define ZS_CLOCK 3672000 /* Zilog input clock rate. */ #define ZS_CLOCK_DIVISOR 16 /* Divisor this driver uses. */ /* @@ -86,7 +84,7 @@ struct uart_ip22zilog_port { #define IP22ZILOG_FLAG_TX_STOPPED 0x00000080 #define IP22ZILOG_FLAG_TX_ACTIVE 0x00000100 - unsigned int cflag; + unsigned int cflag; /* L1-A keyboard break state. */ int kbd_id; @@ -217,7 +215,7 @@ static void __load_zsregs(struct zilog_channel *channel, unsigned char *regs) /* Lower and upper byte of baud rate generator divisor. */ write_zsreg(channel, R12, regs[R12]); write_zsreg(channel, R13, regs[R13]); - + /* Now rewrite R14, with BRENAB (if set). */ write_zsreg(channel, R14, regs[R14]); @@ -261,13 +259,7 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up, struct tty_struct *tty = up->port.info->tty; /* XXX info==NULL? */ while (1) { - unsigned char ch, r1; - - if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { - tty->flip.work.func((void *)tty); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - return; /* XXX Ignores SysRq when we need it most. Fix. */ - } + unsigned char ch, r1, flag; r1 = read_zsreg(channel, R1); if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) { @@ -305,8 +297,7 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up, } /* A real serial line, record the character and status. */ - *tty->flip.char_buf_ptr = ch; - *tty->flip.flag_buf_ptr = TTY_NORMAL; + flag = TTY_NORMAL; up->port.icount.rx++; if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) { if (r1 & BRK_ABRT) { @@ -323,28 +314,21 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up, up->port.icount.overrun++; r1 &= up->port.read_status_mask; if (r1 & BRK_ABRT) - *tty->flip.flag_buf_ptr = TTY_BREAK; + flag = TTY_BREAK; else if (r1 & PAR_ERR) - *tty->flip.flag_buf_ptr = TTY_PARITY; + flag = TTY_PARITY; else if (r1 & CRC_ERR) - *tty->flip.flag_buf_ptr = TTY_FRAME; + flag = TTY_FRAME; } if (uart_handle_sysrq_char(&up->port, ch, regs)) goto next_char; if (up->port.ignore_status_mask == 0xff || - (r1 & up->port.ignore_status_mask) == 0) { - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; - } - if ((r1 & Rx_OVR) && - tty->flip.count < TTY_FLIPBUF_SIZE) { - *tty->flip.flag_buf_ptr = TTY_OVERRUN; - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; - } + (r1 & up->port.ignore_status_mask) == 0) + tty_insert_flip_char(tty, ch, flag); + + if (r1 & Rx_OVR) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); next_char: ch = readb(&channel->control); ZSDELAY(); @@ -436,10 +420,8 @@ static void ip22zilog_transmit_chars(struct uart_ip22zilog_port *up, if (up->port.info == NULL) goto ack_tx_int; xmit = &up->port.info->xmit; - if (uart_circ_empty(xmit)) { - uart_write_wakeup(&up->port); + if (uart_circ_empty(xmit)) goto ack_tx_int; - } if (uart_tx_stopped(&up->port)) goto ack_tx_int; @@ -520,27 +502,28 @@ static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id, struct pt_regs *re static __inline__ unsigned char ip22zilog_read_channel_status(struct uart_port *port) { struct zilog_channel *channel; - unsigned long flags; unsigned char status; - spin_lock_irqsave(&port->lock, flags); - channel = ZILOG_CHANNEL_FROM_PORT(port); status = readb(&channel->control); ZSDELAY(); - spin_unlock_irqrestore(&port->lock, flags); - return status; } /* The port lock is not held. */ static unsigned int ip22zilog_tx_empty(struct uart_port *port) { + unsigned long flags; unsigned char status; unsigned int ret; + spin_lock_irqsave(&port->lock, flags); + status = ip22zilog_read_channel_status(port); + + spin_unlock_irqrestore(&port->lock, flags); + if (status & Tx_BUF_EMP) ret = TIOCSER_TEMT; else @@ -549,7 +532,7 @@ static unsigned int ip22zilog_tx_empty(struct uart_port *port) return ret; } -/* The port lock is not held. */ +/* The port lock is held and interrupts are disabled. */ static unsigned int ip22zilog_get_mctrl(struct uart_port *port) { unsigned char status; @@ -586,14 +569,14 @@ static void ip22zilog_set_mctrl(struct uart_port *port, unsigned int mctrl) else clear_bits |= DTR; - /* NOTE: Not subject to 'transmitter active' rule. */ + /* NOTE: Not subject to 'transmitter active' rule. */ up->curregs[R5] |= set_bits; up->curregs[R5] &= ~clear_bits; write_zsreg(channel, R5, up->curregs[R5]); } /* The port lock is held and interrupts are disabled. */ -static void ip22zilog_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void ip22zilog_stop_tx(struct uart_port *port) { struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port; @@ -601,7 +584,7 @@ static void ip22zilog_stop_tx(struct uart_port *port, unsigned int tty_stop) } /* The port lock is held and interrupts are disabled. */ -static void ip22zilog_start_tx(struct uart_port *port, unsigned int tty_start) +static void ip22zilog_start_tx(struct uart_port *port) { struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port; struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); @@ -642,46 +625,36 @@ static void ip22zilog_start_tx(struct uart_port *port, unsigned int tty_start) } } -/* The port lock is not held. */ +/* The port lock is held and interrupts are disabled. */ static void ip22zilog_stop_rx(struct uart_port *port) { struct uart_ip22zilog_port *up = UART_ZILOG(port); struct zilog_channel *channel; - unsigned long flags; if (ZS_IS_CONS(up)) return; - spin_lock_irqsave(&port->lock, flags); - channel = ZILOG_CHANNEL_FROM_PORT(port); /* Disable all RX interrupts. */ up->curregs[R1] &= ~RxINT_MASK; ip22zilog_maybe_update_regs(up, channel); - - spin_unlock_irqrestore(&port->lock, flags); } -/* The port lock is not held. */ +/* The port lock is held. */ static void ip22zilog_enable_ms(struct uart_port *port) { struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port; struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); unsigned char new_reg; - unsigned long flags; - - spin_lock_irqsave(&port->lock, flags); new_reg = up->curregs[R15] | (DCDIE | SYNCIE | CTSIE); if (new_reg != up->curregs[R15]) { up->curregs[R15] = new_reg; - /* NOTE: Not subject to 'transmitter active' rule. */ + /* NOTE: Not subject to 'transmitter active' rule. */ write_zsreg(channel, R15, up->curregs[R15]); } - - spin_unlock_irqrestore(&port->lock, flags); } /* The port lock is not held. */ @@ -705,7 +678,7 @@ static void ip22zilog_break_ctl(struct uart_port *port, int break_state) if (new_reg != up->curregs[R5]) { up->curregs[R5] = new_reg; - /* NOTE: Not subject to 'transmitter active' rule. */ + /* NOTE: Not subject to 'transmitter active' rule. */ write_zsreg(channel, R5, up->curregs[R5]); } @@ -807,7 +780,7 @@ ip22zilog_convert_to_zs(struct uart_ip22zilog_port *up, unsigned int cflag, up->curregs[R4] |= X16CLK; up->curregs[R12] = brg & 0xff; up->curregs[R13] = (brg >> 8) & 0xff; - up->curregs[R14] = BRSRC | BRENAB; + up->curregs[R14] = BRENAB; /* Character size, stop bits, and parity. */ up->curregs[3] &= ~RxN_MASK; @@ -950,13 +923,6 @@ static struct zilog_layout **ip22zilog_chip_regs; static struct uart_ip22zilog_port *ip22zilog_irq_chain; static int zilog_irq = -1; -static struct uart_driver ip22zilog_reg = { - .owner = THIS_MODULE, - .driver_name = "ttyS", - .devfs_name = "tty/", - .major = TTY_MAJOR, -}; - static void * __init alloc_one_table(unsigned long size) { void *ret; @@ -990,7 +956,7 @@ static struct zilog_layout * __init get_zs(int chip) } /* Not probe-able, hard code it. */ - base = (unsigned long) &sgioc->serport; + base = (unsigned long) &sgioc->uart; zilog_irq = SGI_SERIAL_IRQ; request_mem_region(base, 8, "IP22-Zilog"); @@ -1001,8 +967,9 @@ static struct zilog_layout * __init get_zs(int chip) #define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */ #ifdef CONFIG_SERIAL_IP22_ZILOG_CONSOLE -static void ip22zilog_put_char(struct zilog_channel *channel, unsigned char ch) +static void ip22zilog_put_char(struct uart_port *port, int ch) { + struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); int loops = ZS_PUT_CHAR_MAX_DELAY; /* This is a timed polling loop so do not switch the explicit @@ -1026,16 +993,10 @@ static void ip22zilog_console_write(struct console *con, const char *s, unsigned int count) { struct uart_ip22zilog_port *up = &ip22zilog_port_table[con->index]; - struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port); unsigned long flags; - int i; spin_lock_irqsave(&up->port.lock, flags); - for (i = 0; i < count; i++, s++) { - ip22zilog_put_char(channel, *s); - if (*s == 10) - ip22zilog_put_char(channel, 13); - } + uart_console_write(&up->port, s, count, ip22zilog_put_char); udelay(2); spin_unlock_irqrestore(&up->port.lock, flags); } @@ -1047,9 +1008,6 @@ ip22serial_console_termios(struct console *con, char *options) int parity = 'n'; int flow = 'n'; - if (!serial_console) - return; - if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); @@ -1077,8 +1035,7 @@ static int __init ip22zilog_console_setup(struct console *con, char *options) unsigned long flags; int baud, brg; - printk("Console: ttyS%d (IP22-Zilog)\n", - (ip22zilog_reg.minor - 64) + con->index); + printk("Console: ttyS%d (IP22-Zilog)\n", con->index); /* Get firmware console settings. */ ip22serial_console_termios(con, options); @@ -1112,6 +1069,8 @@ static int __init ip22zilog_console_setup(struct console *con, char *options) return 0; } +static struct uart_driver ip22zilog_reg; + static struct console ip22zilog_console = { .name = "ttyS", .write = ip22zilog_console_write, @@ -1121,32 +1080,20 @@ static struct console ip22zilog_console = { .index = -1, .data = &ip22zilog_reg, }; -#define IP22ZILOG_CONSOLE (&ip22zilog_console) - -static int __init ip22zilog_console_init(void) -{ - int i; - - if (con_is_present()) - return 0; +#endif /* CONFIG_SERIAL_IP22_ZILOG_CONSOLE */ - for (i = 0; i < NUM_CHANNELS; i++) { - int this_minor = ip22zilog_reg.minor + i; - - if ((this_minor - 64) == (serial_console - 1)) - break; - } - if (i == NUM_CHANNELS) - return 0; - - ip22zilog_console.index = i; - register_console(&ip22zilog_console); - return 0; -} -#else /* CONFIG_SERIAL_IP22_ZILOG_CONSOLE */ -#define IP22ZILOG_CONSOLE (NULL) -#define ip22zilog_console_init() do { } while (0) +static struct uart_driver ip22zilog_reg = { + .owner = THIS_MODULE, + .driver_name = "serial", + .devfs_name = "tts/", + .dev_name = "ttyS", + .major = TTY_MAJOR, + .minor = 64, + .nr = NUM_CHANNELS, +#ifdef CONFIG_SERIAL_IP22_ZILOG_CONSOLE + .cons = &ip22zilog_console, #endif +}; static void __init ip22zilog_prepare(void) { @@ -1160,17 +1107,24 @@ static void __init ip22zilog_prepare(void) for (channel = 0; channel < NUM_CHANNELS; channel++) spin_lock_init(&ip22zilog_port_table[channel].port.lock); - ip22zilog_irq_chain = up = &ip22zilog_port_table[0]; - for (channel = 0; channel < NUM_CHANNELS - 1; channel++) - up[channel].next = &up[channel + 1]; + ip22zilog_irq_chain = &ip22zilog_port_table[NUM_CHANNELS - 1]; + up = &ip22zilog_port_table[0]; + for (channel = NUM_CHANNELS - 1 ; channel > 0; channel--) + up[channel].next = &up[channel - 1]; up[channel].next = NULL; for (chip = 0; chip < NUM_IP22ZILOG; chip++) { if (!ip22zilog_chip_regs[chip]) { ip22zilog_chip_regs[chip] = rp = get_zs(chip); - up[(chip * 2) + 0].port.membase = (char *) &rp->channelA; - up[(chip * 2) + 1].port.membase = (char *) &rp->channelB; + up[(chip * 2) + 0].port.membase = (char *) &rp->channelB; + up[(chip * 2) + 1].port.membase = (char *) &rp->channelA; + + /* In theory mapbase is the physical address ... */ + up[(chip * 2) + 0].port.mapbase = + (unsigned long) ioremap((unsigned long) &rp->channelB, 8); + up[(chip * 2) + 1].port.mapbase = + (unsigned long) ioremap((unsigned long) &rp->channelA, 8); } /* Channel A */ @@ -1182,7 +1136,7 @@ static void __init ip22zilog_prepare(void) up[(chip * 2) + 0].port.type = PORT_IP22ZILOG; up[(chip * 2) + 0].port.flags = 0; up[(chip * 2) + 0].port.line = (chip * 2) + 0; - up[(chip * 2) + 0].flags |= IP22ZILOG_FLAG_IS_CHANNEL_A; + up[(chip * 2) + 0].flags = 0; /* Channel B */ up[(chip * 2) + 1].port.iotype = UPIO_MEM; @@ -1191,9 +1145,9 @@ static void __init ip22zilog_prepare(void) up[(chip * 2) + 1].port.fifosize = 1; up[(chip * 2) + 1].port.ops = &ip22zilog_pops; up[(chip * 2) + 1].port.type = PORT_IP22ZILOG; - up[(chip * 2) + 1].port.flags = 0; + up[(chip * 2) + 1].port.flags |= IP22ZILOG_FLAG_IS_CHANNEL_A; up[(chip * 2) + 1].port.line = (chip * 2) + 1; - up[(chip * 2) + 1].flags |= 0; + up[(chip * 2) + 1].flags = 0; } } @@ -1228,8 +1182,10 @@ static void __init ip22zilog_init_hw(void) brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); up->curregs[R12] = (brg & 0xff); up->curregs[R13] = (brg >> 8) & 0xff; - up->curregs[R14] = BRSRC | BRENAB; + up->curregs[R14] = BRENAB; __load_zsregs(channel, up->curregs); + /* set master interrupt enable */ + write_zsreg(channel, R9, up->curregs[R9]); spin_unlock_irqrestore(&up->port.lock, flags); } @@ -1250,15 +1206,6 @@ static int __init ip22zilog_ports_init(void) ip22zilog_init_hw(); - /* We can only init this once we have probed the Zilogs - * in the system. - */ - ip22zilog_reg.nr = NUM_CHANNELS; - ip22zilog_reg.cons = IP22ZILOG_CONSOLE; - - ip22zilog_reg.minor = ip22serial_current_minor; - ip22serial_current_minor += NUM_CHANNELS; - ret = uart_register_driver(&ip22zilog_reg); if (ret == 0) { int i; @@ -1276,11 +1223,8 @@ static int __init ip22zilog_ports_init(void) static int __init ip22zilog_init(void) { /* IP22 Zilog setup is hard coded, no probing to do. */ - ip22zilog_alloc_tables(); - ip22zilog_ports_init(); - ip22zilog_console_init(); return 0; }