source: trunk/target/linux/ifxmips/patches-2.6.30/120-serial.patch @ 20273

Last change on this file since 20273 was 20273, checked in by blogic, 6 years ago

[ifxmips] Bugfix: do not call request_irq() with interrupts disabled, signed off by Ithamar R. Adema

File size: 17.3 KB
  • drivers/serial/Kconfig

    old new  
    13651365        help 
    13661366          Support for Console on the NWP serial ports. 
    13671367 
     1368config SERIAL_IFXMIPS 
     1369        bool "IFXMips serial driver" 
     1370        depends on IFXMIPS 
     1371        select SERIAL_CORE 
     1372        select SERIAL_CORE_CONSOLE 
     1373        help 
     1374          Driver for the ifxmipss built in ASC hardware 
     1375 
    13681376config SERIAL_QE 
    13691377        tristate "Freescale QUICC Engine serial port support" 
    13701378        depends on QUICC_ENGINE 
  • drivers/serial/Makefile

    old new  
    7777obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o 
    7878obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o 
    7979obj-$(CONFIG_SERIAL_QE) += ucc_uart.o 
     80obj-$(CONFIG_SERIAL_IFXMIPS) += ifxmips_asc.o 
  • new file linux-2.6.30.10/drivers/serial/ifxmips_asc.c

    - +  
     1/* 
     2 *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. 
     3 * 
     4 * This program is free software; you can redistribute it and/or modify 
     5 * it under the terms of the GNU General Public License as published by 
     6 * the Free Software Foundation; either version 2 of the License, or 
     7 * (at your option) any later version. 
     8 * 
     9 * This program is distributed in the hope that it will be useful, 
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     12 * GNU General Public License for more details. 
     13 * 
     14 * You should have received a copy of the GNU General Public License 
     15 * along with this program; if not, write to the Free Software 
     16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
     17 * 
     18 * Copyright (C) 2004 Infineon IFAP DC COM CPE 
     19 * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org> 
     20 * Copyright (C) 2007 John Crispin <blogic@openwrt.org> 
     21 */ 
     22 
     23#include <linux/module.h> 
     24#include <linux/errno.h> 
     25#include <linux/signal.h> 
     26#include <linux/sched.h> 
     27#include <linux/interrupt.h> 
     28#include <linux/tty.h> 
     29#include <linux/tty_flip.h> 
     30#include <linux/major.h> 
     31#include <linux/string.h> 
     32#include <linux/fcntl.h> 
     33#include <linux/ptrace.h> 
     34#include <linux/ioport.h> 
     35#include <linux/mm.h> 
     36#include <linux/slab.h> 
     37#include <linux/init.h> 
     38#include <linux/circ_buf.h> 
     39#include <linux/serial.h> 
     40#include <linux/serial_core.h> 
     41#include <linux/console.h> 
     42#include <linux/sysrq.h> 
     43#include <linux/irq.h> 
     44#include <linux/platform_device.h> 
     45#include <linux/io.h> 
     46#include <linux/uaccess.h> 
     47#include <linux/bitops.h> 
     48 
     49#include <asm/system.h> 
     50 
     51#include <ifxmips.h> 
     52#include <ifxmips_irq.h> 
     53 
     54#define PORT_IFXMIPSASC  111 
     55 
     56#include <linux/serial_core.h> 
     57 
     58#define UART_DUMMY_UER_RX 1 
     59 
     60static void ifxmipsasc_tx_chars(struct uart_port *port); 
     61extern void prom_printf(const char *fmt, ...); 
     62static struct uart_port ifxmipsasc_port[2]; 
     63static struct uart_driver ifxmipsasc_reg; 
     64extern unsigned int ifxmips_get_fpi_hz(void); 
     65 
     66static void ifxmipsasc_stop_tx(struct uart_port *port) 
     67{ 
     68        return; 
     69} 
     70 
     71static void ifxmipsasc_start_tx(struct uart_port *port) 
     72{ 
     73        unsigned long flags; 
     74        local_irq_save(flags); 
     75        ifxmipsasc_tx_chars(port); 
     76        local_irq_restore(flags); 
     77        return; 
     78} 
     79 
     80static void ifxmipsasc_stop_rx(struct uart_port *port) 
     81{ 
     82        ifxmips_w32(ASCWHBSTATE_CLRREN, port->membase + IFXMIPS_ASC_WHBSTATE); 
     83} 
     84 
     85static void ifxmipsasc_enable_ms(struct uart_port *port) 
     86{ 
     87} 
     88 
     89#include <linux/version.h> 
     90 
     91static void ifxmipsasc_rx_chars(struct uart_port *port) 
     92{ 
     93#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)) 
     94        struct tty_struct *tty = port->info->port.tty; 
     95#else 
     96        struct tty_struct *tty = port->info->tty; 
     97#endif 
     98        unsigned int ch = 0, rsr = 0, fifocnt; 
     99 
     100        fifocnt = ifxmips_r32(port->membase + IFXMIPS_ASC_FSTAT) & ASCFSTAT_RXFFLMASK; 
     101        while (fifocnt--) { 
     102                u8 flag = TTY_NORMAL; 
     103                ch = ifxmips_r32(port->membase + IFXMIPS_ASC_RBUF); 
     104                rsr = (ifxmips_r32(port->membase + IFXMIPS_ASC_STATE) & ASCSTATE_ANY) | UART_DUMMY_UER_RX; 
     105                tty_flip_buffer_push(tty); 
     106                port->icount.rx++; 
     107 
     108                /* 
     109                 * Note that the error handling code is 
     110                 * out of the main execution path 
     111                 */ 
     112                if (rsr & ASCSTATE_ANY) { 
     113                        if (rsr & ASCSTATE_PE) { 
     114                                port->icount.parity++; 
     115                                ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_WHBSTATE) | ASCWHBSTATE_CLRPE, port->membase + IFXMIPS_ASC_WHBSTATE); 
     116                        } else if (rsr & ASCSTATE_FE) { 
     117                                port->icount.frame++; 
     118                                ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_WHBSTATE) | ASCWHBSTATE_CLRFE, port->membase + IFXMIPS_ASC_WHBSTATE); 
     119                        } 
     120                        if (rsr & ASCSTATE_ROE) { 
     121                                port->icount.overrun++; 
     122                                ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_WHBSTATE) | ASCWHBSTATE_CLRROE, port->membase + IFXMIPS_ASC_WHBSTATE); 
     123                        } 
     124 
     125                        rsr &= port->read_status_mask; 
     126 
     127                        if (rsr & ASCSTATE_PE) 
     128                                flag = TTY_PARITY; 
     129                        else if (rsr & ASCSTATE_FE) 
     130                                flag = TTY_FRAME; 
     131                } 
     132 
     133                if ((rsr & port->ignore_status_mask) == 0) 
     134                        tty_insert_flip_char(tty, ch, flag); 
     135 
     136                if (rsr & ASCSTATE_ROE) 
     137                        /* 
     138                         * Overrun is special, since it's reported 
     139                         * immediately, and doesn't affect the current 
     140                         * character 
     141                         */ 
     142                        tty_insert_flip_char(tty, 0, TTY_OVERRUN); 
     143        } 
     144        if (ch != 0) 
     145                tty_flip_buffer_push(tty); 
     146        return; 
     147} 
     148 
     149 
     150static void ifxmipsasc_tx_chars(struct uart_port *port) 
     151{ 
     152        struct circ_buf *xmit = &port->info->xmit; 
     153        if (uart_tx_stopped(port)) { 
     154                ifxmipsasc_stop_tx(port); 
     155                return; 
     156        } 
     157 
     158        while (((ifxmips_r32(port->membase + IFXMIPS_ASC_FSTAT) & ASCFSTAT_TXFFLMASK) 
     159                        >> ASCFSTAT_TXFFLOFF) != TXFIFO_FULL) { 
     160                if (port->x_char) { 
     161                        ifxmips_w32(port->x_char, port->membase + IFXMIPS_ASC_TBUF); 
     162                        port->icount.tx++; 
     163                        port->x_char = 0; 
     164                        continue; 
     165                } 
     166 
     167                if (uart_circ_empty(xmit)) 
     168                        break; 
     169 
     170                ifxmips_w32(port->info->xmit.buf[port->info->xmit.tail], port->membase + IFXMIPS_ASC_TBUF); 
     171                xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); 
     172                port->icount.tx++; 
     173        } 
     174 
     175        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 
     176                uart_write_wakeup(port); 
     177} 
     178 
     179static irqreturn_t ifxmipsasc_tx_int(int irq, void *_port) 
     180{ 
     181        struct uart_port *port = (struct uart_port *)_port; 
     182        ifxmips_w32(ASC_IRNCR_TIR, port->membase + IFXMIPS_ASC_IRNCR); 
     183        ifxmipsasc_start_tx(port); 
     184        ifxmips_mask_and_ack_irq(irq); 
     185        return IRQ_HANDLED; 
     186} 
     187 
     188static irqreturn_t ifxmipsasc_er_int(int irq, void *_port) 
     189{ 
     190        struct uart_port *port = (struct uart_port *)_port; 
     191        /* clear any pending interrupts */ 
     192        ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_WHBSTATE) | ASCWHBSTATE_CLRPE | 
     193                        ASCWHBSTATE_CLRFE | ASCWHBSTATE_CLRROE, port->membase + IFXMIPS_ASC_WHBSTATE); 
     194        return IRQ_HANDLED; 
     195} 
     196 
     197static irqreturn_t ifxmipsasc_rx_int(int irq, void *_port) 
     198{ 
     199        struct uart_port *port = (struct uart_port *)_port; 
     200        ifxmips_w32(ASC_IRNCR_RIR, port->membase + IFXMIPS_ASC_IRNCR); 
     201        ifxmipsasc_rx_chars((struct uart_port *)port); 
     202        ifxmips_mask_and_ack_irq(irq); 
     203        return IRQ_HANDLED; 
     204} 
     205 
     206static unsigned int ifxmipsasc_tx_empty(struct uart_port *port) 
     207{ 
     208        int status; 
     209        status = ifxmips_r32(port->membase + IFXMIPS_ASC_FSTAT) & ASCFSTAT_TXFFLMASK; 
     210        return status ? 0 : TIOCSER_TEMT; 
     211} 
     212 
     213static unsigned int ifxmipsasc_get_mctrl(struct uart_port *port) 
     214{ 
     215        return TIOCM_CTS | TIOCM_CAR | TIOCM_DSR; 
     216} 
     217 
     218static void ifxmipsasc_set_mctrl(struct uart_port *port, u_int mctrl) 
     219{ 
     220} 
     221 
     222static void ifxmipsasc_break_ctl(struct uart_port *port, int break_state) 
     223{ 
     224} 
     225 
     226static int ifxmipsasc_startup(struct uart_port *port) 
     227{ 
     228        int retval; 
     229 
     230        port->uartclk = ifxmips_get_fpi_hz(); 
     231 
     232        ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_CLC) & ~IFXMIPS_ASC_CLC_DISS, port->membase + IFXMIPS_ASC_CLC); 
     233        ifxmips_w32(((ifxmips_r32(port->membase + IFXMIPS_ASC_CLC) & ~ASCCLC_RMCMASK)) | (1 << ASCCLC_RMCOFFSET), port->membase + IFXMIPS_ASC_CLC); 
     234        ifxmips_w32(0, port->membase + IFXMIPS_ASC_PISEL); 
     235        ifxmips_w32(((TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) | ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU, port->membase + IFXMIPS_ASC_TXFCON); 
     236        ifxmips_w32(((RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK) | ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU, port->membase + IFXMIPS_ASC_RXFCON); 
     237        wmb(); 
     238        ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_CON) | ASCCON_M_8ASYNC | ASCCON_FEN | ASCCON_TOEN | ASCCON_ROEN, port->membase + IFXMIPS_ASC_CON); 
     239 
     240        retval = request_irq(port->irq, ifxmipsasc_tx_int, IRQF_DISABLED, "asc_tx", port); 
     241        if (retval) { 
     242                printk(KERN_ERR "failed to request ifxmipsasc_tx_int\n"); 
     243                return retval; 
     244        } 
     245 
     246        retval = request_irq(port->irq + 2, ifxmipsasc_rx_int, IRQF_DISABLED, "asc_rx", port); 
     247        if (retval) { 
     248                printk(KERN_ERR "failed to request ifxmipsasc_rx_int\n"); 
     249                goto err1; 
     250        } 
     251 
     252        retval = request_irq(port->irq + 3, ifxmipsasc_er_int, IRQF_DISABLED, "asc_er", port); 
     253        if (retval) { 
     254                printk(KERN_ERR "failed to request ifxmipsasc_er_int\n"); 
     255                goto err2; 
     256        } 
     257 
     258        ifxmips_w32(ASC_IRNREN_RX_BUF | ASC_IRNREN_TX_BUF | ASC_IRNREN_ERR | ASC_IRNREN_TX, port->membase + IFXMIPS_ASC_IRNREN); 
     259        return 0; 
     260 
     261err2: 
     262        free_irq(port->irq + 2, port); 
     263err1: 
     264        free_irq(port->irq, port); 
     265        return retval; 
     266} 
     267 
     268static void ifxmipsasc_shutdown(struct uart_port *port) 
     269{ 
     270        free_irq(port->irq, port); 
     271        free_irq(port->irq + 2, port); 
     272        free_irq(port->irq + 3, port); 
     273 
     274        ifxmips_w32(0, port->membase + IFXMIPS_ASC_CON); 
     275        ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_RXFCON) | ASCRXFCON_RXFFLU, port->membase + IFXMIPS_ASC_RXFCON); 
     276        ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_RXFCON) & ~ASCRXFCON_RXFEN, port->membase + IFXMIPS_ASC_RXFCON); 
     277        ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_TXFCON) | ASCTXFCON_TXFFLU, port->membase + IFXMIPS_ASC_TXFCON); 
     278        ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_TXFCON) & ~ASCTXFCON_TXFEN, port->membase + IFXMIPS_ASC_TXFCON); 
     279} 
     280 
     281static void ifxmipsasc_set_termios(struct uart_port *port, struct ktermios *new, struct ktermios *old) 
     282{ 
     283        unsigned int cflag; 
     284        unsigned int iflag; 
     285        unsigned int quot; 
     286        unsigned int baud; 
     287        unsigned int con = 0; 
     288        unsigned long flags; 
     289 
     290        cflag = new->c_cflag; 
     291        iflag = new->c_iflag; 
     292 
     293        switch (cflag & CSIZE) { 
     294        case CS7: 
     295                con = ASCCON_M_7ASYNC; 
     296                break; 
     297 
     298        case CS5: 
     299        case CS6: 
     300        default: 
     301                con = ASCCON_M_8ASYNC; 
     302                break; 
     303        } 
     304 
     305        if (cflag & CSTOPB) 
     306                con |= ASCCON_STP; 
     307 
     308        if (cflag & PARENB) { 
     309                if (!(cflag & PARODD)) 
     310                        con &= ~ASCCON_ODD; 
     311                else 
     312                        con |= ASCCON_ODD; 
     313        } 
     314 
     315        port->read_status_mask = ASCSTATE_ROE; 
     316        if (iflag & INPCK) 
     317                port->read_status_mask |= ASCSTATE_FE | ASCSTATE_PE; 
     318 
     319        port->ignore_status_mask = 0; 
     320        if (iflag & IGNPAR) 
     321                port->ignore_status_mask |= ASCSTATE_FE | ASCSTATE_PE; 
     322 
     323        if (iflag & IGNBRK) { 
     324                /* 
     325                 * If we're ignoring parity and break indicators, 
     326                 * ignore overruns too (for real raw support). 
     327                 */ 
     328                if (iflag & IGNPAR) 
     329                        port->ignore_status_mask |= ASCSTATE_ROE; 
     330        } 
     331 
     332        if ((cflag & CREAD) == 0) 
     333                port->ignore_status_mask |= UART_DUMMY_UER_RX; 
     334 
     335        /* set error signals  - framing, parity  and overrun, enable receiver */ 
     336        con |= ASCCON_FEN | ASCCON_TOEN | ASCCON_ROEN; 
     337 
     338        local_irq_save(flags); 
     339 
     340        /* set up CON */ 
     341        ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_CON) | con, port->membase + IFXMIPS_ASC_CON); 
     342 
     343        /* Set baud rate - take a divider of 2 into account */ 
     344        baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16); 
     345        quot = uart_get_divisor(port, baud); 
     346        quot = quot / 2 - 1; 
     347 
     348        /* disable the baudrate generator */ 
     349        ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_CON) & ~ASCCON_R, port->membase + IFXMIPS_ASC_CON); 
     350 
     351        /* make sure the fractional divider is off */ 
     352        ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_CON) & ~ASCCON_FDE, port->membase + IFXMIPS_ASC_CON); 
     353 
     354        /* set up to use divisor of 2 */ 
     355        ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_CON) & ~ASCCON_BRS, port->membase + IFXMIPS_ASC_CON); 
     356 
     357        /* now we can write the new baudrate into the register */ 
     358        ifxmips_w32(quot, port->membase + IFXMIPS_ASC_BG); 
     359 
     360        /* turn the baudrate generator back on */ 
     361        ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_CON) | ASCCON_R, port->membase + IFXMIPS_ASC_CON); 
     362 
     363        /* enable rx */ 
     364        ifxmips_w32(ASCWHBSTATE_SETREN, port->membase + IFXMIPS_ASC_WHBSTATE); 
     365 
     366        local_irq_restore(flags); 
     367} 
     368 
     369static const char *ifxmipsasc_type(struct uart_port *port) 
     370{ 
     371        if (port->type == PORT_IFXMIPSASC) { 
     372                if (port->membase == (void *)IFXMIPS_ASC_BASE_ADDR) 
     373                        return "asc0"; 
     374                else 
     375                        return "asc1"; 
     376        } else { 
     377                return NULL; 
     378        } 
     379} 
     380 
     381static void ifxmipsasc_release_port(struct uart_port *port) 
     382{ 
     383} 
     384 
     385static int ifxmipsasc_request_port(struct uart_port *port) 
     386{ 
     387        return 0; 
     388} 
     389 
     390static void ifxmipsasc_config_port(struct uart_port *port, int flags) 
     391{ 
     392        if (flags & UART_CONFIG_TYPE) { 
     393                port->type = PORT_IFXMIPSASC; 
     394                ifxmipsasc_request_port(port); 
     395        } 
     396} 
     397 
     398static int ifxmipsasc_verify_port(struct uart_port *port, struct serial_struct *ser) 
     399{ 
     400        int ret = 0; 
     401        if (ser->type != PORT_UNKNOWN && ser->type != PORT_IFXMIPSASC) 
     402                ret = -EINVAL; 
     403        if (ser->irq < 0 || ser->irq >= NR_IRQS) 
     404                ret = -EINVAL; 
     405        if (ser->baud_base < 9600) 
     406                ret = -EINVAL; 
     407        return ret; 
     408} 
     409 
     410static struct uart_ops ifxmipsasc_pops = { 
     411        .tx_empty =     ifxmipsasc_tx_empty, 
     412        .set_mctrl =    ifxmipsasc_set_mctrl, 
     413        .get_mctrl =    ifxmipsasc_get_mctrl, 
     414        .stop_tx =      ifxmipsasc_stop_tx, 
     415        .start_tx =     ifxmipsasc_start_tx, 
     416        .stop_rx =      ifxmipsasc_stop_rx, 
     417        .enable_ms =    ifxmipsasc_enable_ms, 
     418        .break_ctl =    ifxmipsasc_break_ctl, 
     419        .startup =      ifxmipsasc_startup, 
     420        .shutdown =     ifxmipsasc_shutdown, 
     421        .set_termios =  ifxmipsasc_set_termios, 
     422        .type =         ifxmipsasc_type, 
     423        .release_port = ifxmipsasc_release_port, 
     424        .request_port = ifxmipsasc_request_port, 
     425        .config_port =  ifxmipsasc_config_port, 
     426        .verify_port =  ifxmipsasc_verify_port, 
     427}; 
     428 
     429static struct uart_port ifxmipsasc_port[2] = { 
     430        { 
     431                .membase =              (void *)IFXMIPS_ASC_BASE_ADDR, 
     432                .mapbase =              IFXMIPS_ASC_BASE_ADDR, 
     433                .iotype =               SERIAL_IO_MEM, 
     434                .irq =                  IFXMIPSASC_TIR(0), 
     435                .uartclk =              0, 
     436                .fifosize =             16, 
     437                .type =                 PORT_IFXMIPSASC, 
     438                .ops =                  &ifxmipsasc_pops, 
     439                .flags =                ASYNC_BOOT_AUTOCONF, 
     440                .line =                 0 
     441        }, { 
     442                .membase =              (void *)(IFXMIPS_ASC_BASE_ADDR + IFXMIPS_ASC_BASE_DIFF), 
     443                .mapbase =              IFXMIPS_ASC_BASE_ADDR + IFXMIPS_ASC_BASE_DIFF, 
     444                .iotype =               SERIAL_IO_MEM, 
     445                .irq =                  IFXMIPSASC_TIR(1), 
     446                .uartclk =              0, 
     447                .fifosize =             16, 
     448                .type =                 PORT_IFXMIPSASC, 
     449                .ops =                  &ifxmipsasc_pops, 
     450                .flags =                ASYNC_BOOT_AUTOCONF, 
     451                .line =                 1 
     452        } 
     453}; 
     454 
     455static void ifxmipsasc_console_write(struct console *co, const char *s, u_int count) 
     456{ 
     457        int port = co->index; 
     458        int i, fifocnt; 
     459        unsigned long flags; 
     460        local_irq_save(flags); 
     461        for (i = 0; i < count; i++) { 
     462                do { 
     463                        fifocnt = (ifxmips_r32((u32 *)(IFXMIPS_ASC_BASE_ADDR + (port * IFXMIPS_ASC_BASE_DIFF) + IFXMIPS_ASC_FSTAT)) & ASCFSTAT_TXFFLMASK) 
     464                                >> ASCFSTAT_TXFFLOFF; 
     465                } while (fifocnt == TXFIFO_FULL); 
     466 
     467                if (s[i] == '\0') 
     468                        break; 
     469 
     470                if (s[i] == '\n') { 
     471                        ifxmips_w32('\r', (u32 *)(IFXMIPS_ASC_BASE_ADDR + (port * IFXMIPS_ASC_BASE_DIFF) + IFXMIPS_ASC_TBUF)); 
     472                        do { 
     473                                fifocnt = (ifxmips_r32((u32 *)(IFXMIPS_ASC_BASE_ADDR + (port * IFXMIPS_ASC_BASE_DIFF) + IFXMIPS_ASC_FSTAT)) & ASCFSTAT_TXFFLMASK) 
     474                                        >> ASCFSTAT_TXFFLOFF; 
     475                        } while (fifocnt == TXFIFO_FULL); 
     476                } 
     477                ifxmips_w32(s[i], (u32 *)(IFXMIPS_ASC_BASE_ADDR + (port * IFXMIPS_ASC_BASE_DIFF) + IFXMIPS_ASC_TBUF)); 
     478        } 
     479 
     480        local_irq_restore(flags); 
     481} 
     482 
     483static int __init ifxmipsasc_console_setup(struct console *co, char *options) 
     484{ 
     485        int port = co->index; 
     486        int baud = 115200; 
     487        int bits = 8; 
     488        int parity = 'n'; 
     489        int flow = 'n'; 
     490        ifxmipsasc_port[port].uartclk = ifxmips_get_fpi_hz(); 
     491        ifxmipsasc_port[port].type = PORT_IFXMIPSASC; 
     492        if (options) 
     493                uart_parse_options(options, &baud, &parity, &bits, &flow); 
     494        return uart_set_options(&ifxmipsasc_port[port], co, baud, parity, bits, flow); 
     495} 
     496 
     497static struct console ifxmipsasc_console[2] = 
     498{ 
     499        { 
     500                .name =         "ttyS", 
     501                .write =                ifxmipsasc_console_write, 
     502                .device =               uart_console_device, 
     503                .setup =                ifxmipsasc_console_setup, 
     504                .flags =                CON_PRINTBUFFER, 
     505                .index =                0, 
     506                .data =         &ifxmipsasc_reg, 
     507        }, { 
     508                .name =         "ttyS", 
     509                .write =        ifxmipsasc_console_write, 
     510                .device =       uart_console_device, 
     511                .setup =        ifxmipsasc_console_setup, 
     512                .flags =        CON_PRINTBUFFER, 
     513                .index =        1, 
     514                .data =         &ifxmipsasc_reg, 
     515        } 
     516}; 
     517 
     518static int __init ifxmipsasc_console_init(void) 
     519{ 
     520        register_console(&ifxmipsasc_console[0]); 
     521        register_console(&ifxmipsasc_console[1]); 
     522        return 0; 
     523} 
     524console_initcall(ifxmipsasc_console_init); 
     525 
     526static struct uart_driver ifxmipsasc_reg = { 
     527        .owner =        THIS_MODULE, 
     528        .driver_name =  "serial", 
     529        .dev_name =     "ttyS", 
     530        .major =        TTY_MAJOR, 
     531        .minor =        64, 
     532        .nr =           2, 
     533        .cons =         &ifxmipsasc_console[1], 
     534}; 
     535 
     536int __init ifxmipsasc_init(void) 
     537{ 
     538        int ret; 
     539        uart_register_driver(&ifxmipsasc_reg); 
     540        ret = uart_add_one_port(&ifxmipsasc_reg, &ifxmipsasc_port[0]); 
     541        ret = uart_add_one_port(&ifxmipsasc_reg, &ifxmipsasc_port[1]); 
     542        return 0; 
     543} 
     544 
     545void __exit ifxmipsasc_exit(void) 
     546{ 
     547        uart_unregister_driver(&ifxmipsasc_reg); 
     548} 
     549 
     550module_init(ifxmipsasc_init); 
     551module_exit(ifxmipsasc_exit); 
     552 
     553MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); 
     554MODULE_DESCRIPTION("MIPS IFXMips serial port driver"); 
     555MODULE_LICENSE("GPL"); 
Note: See TracBrowser for help on using the repository browser.