linux-bk/arch/ppc/4xx_io/serial_sicc.c
<<
>>
Prefs
   1/*
   2 *  arch/ppc/4xx_io/serial_sicc.c
   3 *
   4 *  Driver for IBM STB3xxx SICC serial port
   5 *
   6 *  Based on drivers/char/serial_amba.c, by ARM Ltd.
   7 *
   8 *  Copyright 2001 IBM Crop.
   9 *  Author: IBM China Research Lab
  10 *            Yudong Yang <yangyud@cn.ibm.com>
  11 *            Yi Ge       <geyi@cn.ibm.com>
  12 *
  13 * This program is free software; you can redistribute it and/or modify
  14 * it under the terms of the GNU General Public License as published by
  15 * the Free Software Foundation; either version 2 of the License, or
  16 * (at your option) any later version.
  17 *
  18 * This program is distributed in the hope that it will be useful,
  19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21 * GNU General Public License for more details.
  22 *
  23 * You should have received a copy of the GNU General Public License
  24 * along with this program; if not, write to the Free Software
  25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  26 *
  27 *
  28 * This is a driver for SICC serial port on IBM Redwood 4 evaluation board.
  29 * The driver support both as a console device and normal serial device and
  30 * is compatible with normal ttyS* devices.
  31 */
  32
  33#include <linux/config.h>
  34#include <linux/module.h>
  35#include <linux/kernel.h>
  36#include <linux/errno.h>
  37#include <linux/signal.h>
  38#include <linux/sched.h>
  39#include <linux/interrupt.h>
  40#include <linux/tty.h>
  41#include <linux/tty_flip.h>
  42#include <linux/major.h>
  43#include <linux/string.h>
  44#include <linux/fcntl.h>
  45#include <linux/ptrace.h>
  46#include <linux/ioport.h>
  47#include <linux/mm.h>
  48#include <linux/slab.h>
  49#include <linux/init.h>
  50#include <linux/circ_buf.h>
  51#include <linux/serial.h>
  52#include <linux/console.h>
  53#include <linux/sysrq.h>
  54#include <linux/bitops.h>
  55
  56#include <asm/system.h>
  57#include <asm/io.h>
  58#include <asm/irq.h>
  59#include <asm/uaccess.h>
  60#include <asm/serial.h>
  61
  62
  63#include <linux/serialP.h>
  64
  65
  66/* -----------------------------------------------------------------------------
  67 *  From STB03xxx SICC UART Specification
  68 * -----------------------------------------------------------------------------
  69 *  UART Register Offsets.
  70 */
  71
  72#define BL_SICC_LSR   0x0000000      /* line status register read/clear */
  73#define BL_SICC_LSRS  0x0000001      /* set line status register read/set */
  74#define BL_SICC_HSR   0x0000002      /* handshake status register r/clear */
  75#define BL_SICC_HSRS  0x0000003      /* set handshake status register r/set */
  76#define BL_SICC_BRDH  0x0000004      /* baudrate divisor high reg r/w */
  77#define BL_SICC_BRDL  0x0000005      /* baudrate divisor low reg r/w */
  78#define BL_SICC_LCR   0x0000006      /* control register r/w */
  79#define BL_SICC_RCR   0x0000007      /* receiver command register r/w */
  80#define BL_SICC_TxCR  0x0000008      /* transmitter command register r/w */
  81#define BL_SICC_RBR   0x0000009      /* receive buffer r */
  82#define BL_SICC_TBR   0x0000009      /* transmit buffer w */
  83#define BL_SICC_CTL2  0x000000A      /* added for Vesta */
  84#define BL_SICC_IrCR  0x000000B      /* added for Vesta IR */
  85
  86/* masks and definitions for serial port control register */
  87
  88#define _LCR_LM_MASK  0xc0            /* loop back modes */
  89#define _LCR_DTR_MASK 0x20            /* data terminal ready 0-inactive */
  90#define _LCR_RTS_MASK 0x10            /* request to send 0-inactive */
  91#define _LCR_DB_MASK  0x08            /* data bits mask */
  92#define _LCR_PE_MASK  0x04            /* parity enable */
  93#define _LCR_PTY_MASK 0x02            /* parity */
  94#define _LCR_SB_MASK  0x01            /* stop bit mask */
  95
  96#define _LCR_LM_NORM  0x00            /* normal operation */
  97#define _LCR_LM_LOOP  0x40            /* internal loopback mode */
  98#define _LCR_LM_ECHO  0x80            /* automatic echo mode */
  99#define _LCR_LM_RES   0xc0            /* reserved */
 100
 101#define _LCR_DTR_ACTIVE       _LCR_DTR_MASK /* DTR is active */
 102#define _LCR_RTS_ACTIVE       _LCR_RTS_MASK /* RTS is active */
 103#define _LCR_DB_8_BITS        _LCR_DB_MASK  /*  8 data bits */
 104#define _LCR_DB_7_BITS        0x00          /*  7 data bits */
 105#define _LCR_PE_ENABLE        _LCR_PE_MASK  /* parity enabled */
 106#define _LCR_PE_DISABLE       0x00          /* parity disabled */
 107#define _LCR_PTY_EVEN         0x00          /* even parity */
 108#define _LCR_PTY_ODD          _LCR_PTY_MASK /* odd parity */
 109#define _LCR_SB_1_BIT         0x00          /* one stop bit */
 110#define _LCR_SB_2_BIT         _LCR_SB_MASK  /* two stop bit */
 111
 112/* serial port handshake register */
 113
 114#define _HSR_DIS_MASK  0x80            /* DSR input inactive error mask */
 115#define _HSR_CS_MASK   0x40            /* CTS input inactive error mask */
 116#define _HSR_DIS_ACT   0x00            /* dsr input is active */
 117#define _HSR_DIS_INACT _HSR_DIS_MASK   /* dsr input is inactive */
 118#define _HSR_CS_ACT    0x00            /* cts input is active */
 119#define _HSR_CS_INACT  _HSR_CS_MASK    /* cts input is active */
 120
 121/* serial port line status register */
 122
 123#define _LSR_RBR_MASK  0x80            /* receive buffer ready mask */
 124#define _LSR_FE_MASK   0x40            /* framing error */
 125#define _LSR_OE_MASK   0x20            /* overrun error */
 126#define _LSR_PE_MASK   0x10            /* parity error */
 127#define _LSR_LB_MASK   0x08            /* line break */
 128#define _LSR_TBR_MASK  0x04            /* transmit buffer ready */
 129#define _LSR_TSR_MASK  0x02            /* transmit shift register ready */
 130
 131#define _LSR_RBR_FULL  _LSR_RBR_MASK  /* receive buffer is full */
 132#define _LSR_FE_ERROR  _LSR_FE_MASK   /* framing error detected */
 133#define _LSR_OE_ERROR  _LSR_OE_MASK   /* overrun error detected */
 134#define _LSR_PE_ERROR  _LSR_PE_MASK   /* parity error detected */
 135#define _LSR_LB_BREAK  _LSR_LB_MASK   /* line break detected */
 136#define _LSR_TBR_EMPTY _LSR_TBR_MASK  /* transmit buffer is ready */
 137#define _LSR_TSR_EMPTY _LSR_TSR_MASK  /* transmit shift register is empty */
 138#define _LSR_TX_ALL    0x06           /* all physical transmit is done */
 139
 140#define _LSR_RX_ERR    (_LSR_LB_BREAK | _LSR_FE_MASK | _LSR_OE_MASK | \
 141                         _LSR_PE_MASK )
 142
 143/* serial port receiver command register */
 144
 145#define _RCR_ER_MASK   0x80           /* enable receiver mask */
 146#define _RCR_DME_MASK  0x60           /* dma mode */
 147#define _RCR_EIE_MASK  0x10           /* error interrupt enable mask */
 148#define _RCR_PME_MASK  0x08           /* pause mode mask */
 149
 150#define _RCR_ER_ENABLE _RCR_ER_MASK   /* receiver enabled */
 151#define _RCR_DME_DISABLE 0x00         /* dma disabled */
 152#define _RCR_DME_RXRDY 0x20           /* dma disabled, RxRDY interrupt enabled*/
 153#define _RCR_DME_ENABLE2 0x40         /* dma enabled,receiver src channel 2 */
 154#define _RCR_DME_ENABLE3 0x60         /* dma enabled,receiver src channel 3 */
 155#define _RCR_PME_HARD  _RCR_PME_MASK  /* RTS controlled by hardware */
 156#define _RCR_PME_SOFT  0x00           /* RTS controlled by software */
 157
 158/* serial port transmit command register */
 159
 160#define _TxCR_ET_MASK   0x80           /* transmiter enable mask */
 161#define _TxCR_DME_MASK  0x60           /* dma mode mask */
 162#define _TxCR_TIE_MASK  0x10           /* empty interrupt enable mask */
 163#define _TxCR_EIE_MASK  0x08           /* error interrupt enable mask */
 164#define _TxCR_SPE_MASK  0x04           /* stop/pause mask */
 165#define _TxCR_TB_MASK   0x02           /* transmit break mask */
 166
 167#define _TxCR_ET_ENABLE _TxCR_ET_MASK  /* transmiter enabled */
 168#define _TxCR_DME_DISABLE 0x00         /* transmiter disabled, TBR intr disabled */
 169#define _TxCR_DME_TBR   0x20           /* transmiter disabled, TBR intr enabled */
 170#define _TxCR_DME_CHAN_2 0x40          /* dma enabled, destination chann 2 */
 171#define _TxCR_DME_CHAN_3 0x60          /* dma enabled, destination chann 3 */
 172
 173/* serial ctl reg 2 - added for Vesta */
 174
 175#define _CTL2_EXTERN  0x80            /*  */
 176#define _CTL2_USEFIFO 0x40            /*  */
 177#define _CTL2_RESETRF 0x08            /*  */
 178#define _CTL2_RESETTF 0x04            /*  */
 179
 180
 181
 182#define SERIAL_SICC_NAME    "ttySICC"
 183#define SERIAL_SICC_MAJOR   150
 184#define SERIAL_SICC_MINOR   1
 185#define SERIAL_SICC_NR      1
 186
 187#ifndef TRUE
 188#define TRUE 1
 189#endif
 190#ifndef FALSE
 191#define FALSE 0
 192#endif
 193
 194/*
 195 * Things needed by tty driver
 196 */
 197static struct tty_driver *siccnormal_driver;
 198
 199#if defined(CONFIG_SERIAL_SICC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 200#define SUPPORT_SYSRQ
 201#endif
 202
 203/*
 204 * Things needed internally to this driver
 205 */
 206
 207/*
 208 * tmp_buf is used as a temporary buffer by serial_write.  We need to
 209 * lock it in case the copy_from_user blocks while swapping in a page,
 210 * and some other program tries to do a serial write at the same time.
 211 * Since the lock will only come under contention when the system is
 212 * swapping and available memory is low, it makes sense to share one
 213 * buffer across all the serial ports, since it significantly saves
 214 * memory if large numbers of serial ports are open.
 215 */
 216static u_char *tmp_buf;
 217static DECLARE_MUTEX(tmp_buf_sem);
 218
 219#define HIGH_BITS_OFFSET    ((sizeof(long)-sizeof(int))*8)
 220
 221/* number of characters left in xmit buffer before we ask for more */
 222#define WAKEUP_CHARS        256
 223#define SICC_ISR_PASS_LIMIT 256
 224
 225#define EVT_WRITE_WAKEUP    0
 226
 227struct SICC_icount {
 228    __u32   cts;
 229    __u32   dsr;
 230    __u32   rng;
 231    __u32   dcd;
 232    __u32   rx;
 233    __u32   tx;
 234    __u32   frame;
 235    __u32   overrun;
 236    __u32   parity;
 237    __u32   brk;
 238    __u32   buf_overrun;
 239};
 240
 241/*
 242 * Static information about the port
 243 */
 244struct SICC_port {
 245    unsigned int        uart_base;
 246    unsigned int        uart_base_phys;
 247    unsigned int        irqrx;
 248    unsigned int        irqtx;
 249    unsigned int        uartclk;
 250    unsigned int        fifosize;
 251    unsigned int        tiocm_support;
 252    void (*set_mctrl)(struct SICC_port *, u_int mctrl);
 253};
 254
 255/*
 256 * This is the state information which is persistent across opens
 257 */
 258struct SICC_state {
 259    struct SICC_icount  icount;
 260    unsigned int        line;
 261    unsigned int        close_delay;
 262    unsigned int        closing_wait;
 263    unsigned int        custom_divisor;
 264    unsigned int        flags;
 265    int         count;
 266    struct SICC_info    *info;
 267    spinlock_t          sicc_lock;
 268};
 269
 270#define SICC_XMIT_SIZE 1024
 271/*
 272 * This is the state information which is only valid when the port is open.
 273 */
 274struct SICC_info {
 275    struct SICC_port    *port;
 276    struct SICC_state   *state;
 277    struct tty_struct   *tty;
 278    unsigned char       x_char;
 279    unsigned char       old_status;
 280    unsigned char       read_status_mask;
 281    unsigned char       ignore_status_mask;
 282    struct circ_buf     xmit;
 283    unsigned int        flags;
 284#ifdef SUPPORT_SYSRQ
 285    unsigned long       sysrq;
 286#endif
 287
 288    unsigned int        event;
 289    unsigned int        timeout;
 290    unsigned int        lcr_h;
 291    unsigned int        mctrl;
 292    int         blocked_open;
 293
 294    struct tasklet_struct   tlet;
 295
 296    wait_queue_head_t   open_wait;
 297    wait_queue_head_t   close_wait;
 298    wait_queue_head_t   delta_msr_wait;
 299};
 300
 301#ifdef CONFIG_SERIAL_SICC_CONSOLE
 302static struct console siccuart_cons;
 303#endif
 304static void siccuart_change_speed(struct SICC_info *info, struct termios *old_termios);
 305static void siccuart_wait_until_sent(struct tty_struct *tty, int timeout);
 306
 307
 308
 309static void powerpcMtcic_cr(unsigned long value)
 310{
 311    mtdcr(DCRN_CICCR, value);
 312}
 313
 314static unsigned long powerpcMfcic_cr(void)
 315{
 316    return mfdcr(DCRN_CICCR);
 317}
 318
 319static unsigned long powerpcMfclkgpcr(void)
 320{
 321    return mfdcr(DCRN_SCCR);
 322}
 323
 324static void sicc_set_mctrl_null(struct SICC_port *port, u_int mctrl)
 325{
 326}
 327
 328static struct SICC_port sicc_ports[SERIAL_SICC_NR] = {
 329    {
 330        .uart_base = 0,
 331        .uart_base_phys = SICC0_IO_BASE,
 332        .irqrx =    SICC0_INTRX,
 333        .irqtx =    SICC0_INTTX,
 334//      .uartclk =    0,
 335        .fifosize = 1,
 336        .set_mctrl = sicc_set_mctrl_null,
 337    }
 338};
 339
 340static struct SICC_state sicc_state[SERIAL_SICC_NR];
 341
 342static void siccuart_enable_rx_interrupt(struct SICC_info *info)
 343{
 344    unsigned char cr;
 345
 346    cr = readb(info->port->uart_base+BL_SICC_RCR);
 347    cr &= ~_RCR_DME_MASK;
 348    cr |= _RCR_DME_RXRDY;
 349    writeb(cr, info->port->uart_base+BL_SICC_RCR);
 350}
 351
 352static void siccuart_disable_rx_interrupt(struct SICC_info *info)
 353{
 354    unsigned char cr;
 355
 356    cr = readb(info->port->uart_base+BL_SICC_RCR);
 357    cr &= ~_RCR_DME_MASK;
 358    cr |=  _RCR_DME_DISABLE;
 359    writeb(cr, info->port->uart_base+BL_SICC_RCR);
 360}
 361
 362
 363static void siccuart_enable_tx_interrupt(struct SICC_info *info)
 364{
 365    unsigned char cr;
 366
 367    cr = readb(info->port->uart_base+BL_SICC_TxCR);
 368    cr &= ~_TxCR_DME_MASK;
 369    cr |= _TxCR_DME_TBR;
 370    writeb(cr, info->port->uart_base+BL_SICC_TxCR);
 371}
 372
 373static void siccuart_disable_tx_interrupt(struct SICC_info *info)
 374{
 375    unsigned char cr;
 376
 377    cr = readb(info->port->uart_base+BL_SICC_TxCR);
 378    cr &= ~_TxCR_DME_MASK;
 379    cr |=  _TxCR_DME_DISABLE;
 380    writeb(cr, info->port->uart_base+BL_SICC_TxCR);
 381}
 382
 383
 384static void siccuart_stop(struct tty_struct *tty)
 385{
 386    struct SICC_info *info = tty->driver_data;
 387    unsigned long flags;
 388
 389    /* disable interrupts while stopping serial port interrupts */
 390    spin_lock_irqsave(&info->state->sicc_lock,flags);
 391    siccuart_disable_tx_interrupt(info);
 392    spin_unlock_irqrestore(&info->state->sicc_lock,flags);
 393}
 394
 395static void siccuart_start(struct tty_struct *tty)
 396{
 397    struct SICC_info *info = tty->driver_data;
 398    unsigned long flags;
 399
 400    /* disable interrupts while starting serial port interrupts */
 401    spin_lock_irqsave(&info->state->sicc_lock,flags);
 402    if (info->xmit.head != info->xmit.tail
 403        && info->xmit.buf)
 404        siccuart_enable_tx_interrupt(info);
 405    spin_unlock_irqrestore(&info->state->sicc_lock,flags);
 406}
 407
 408
 409/*
 410 * This routine is used by the interrupt handler to schedule
 411 * processing in the software interrupt portion of the driver.
 412 */
 413static void siccuart_event(struct SICC_info *info, int event)
 414{
 415    info->event |= 1 << event;
 416    tasklet_schedule(&info->tlet);
 417}
 418
 419static void
 420siccuart_rx_chars(struct SICC_info *info, struct pt_regs *regs)
 421{
 422    struct tty_struct *tty = info->tty;
 423    unsigned int status, ch, rsr, flg, ignored = 0;
 424    struct SICC_icount *icount = &info->state->icount;
 425    struct SICC_port *port = info->port;
 426
 427    status = readb(port->uart_base+BL_SICC_LSR );
 428    while (status & _LSR_RBR_FULL) {
 429        ch = readb(port->uart_base+BL_SICC_RBR);
 430
 431        if (tty->flip.count >= TTY_FLIPBUF_SIZE)
 432            goto ignore_char;
 433        icount->rx++;
 434
 435        flg = TTY_NORMAL;
 436
 437        /*
 438         * Note that the error handling code is
 439         * out of the main execution path
 440         */
 441        rsr = readb(port->uart_base+BL_SICC_LSR);
 442        if (rsr & _LSR_RX_ERR)
 443            goto handle_error;
 444#ifdef SUPPORT_SYSRQ
 445        if (info->sysrq) {
 446            if (ch && time_before(jiffies, info->sysrq)) {
 447                handle_sysrq(ch, regs, NULL);
 448                info->sysrq = 0;
 449                goto ignore_char;
 450            }
 451            info->sysrq = 0;
 452        }
 453#endif
 454    error_return:
 455        *tty->flip.flag_buf_ptr++ = flg;
 456        *tty->flip.char_buf_ptr++ = ch;
 457        tty->flip.count++;
 458    ignore_char:
 459        status = readb(port->uart_base+BL_SICC_LSR );
 460    }
 461out:
 462    tty_flip_buffer_push(tty);
 463    return;
 464
 465handle_error:
 466    if (rsr & _LSR_LB_BREAK) {
 467        rsr &= ~(_LSR_FE_MASK | _LSR_PE_MASK);
 468        icount->brk++;
 469
 470#ifdef SUPPORT_SYSRQ
 471        if (info->state->line == siccuart_cons.index) {
 472            if (!info->sysrq) {
 473                info->sysrq = jiffies + HZ*5;
 474                goto ignore_char;
 475            }
 476        }
 477#endif
 478    } else if (rsr & _LSR_PE_MASK)
 479        icount->parity++;
 480    else if (rsr & _LSR_FE_MASK)
 481        icount->frame++;
 482    if (rsr & _LSR_OE_MASK)
 483        icount->overrun++;
 484
 485    if (rsr & info->ignore_status_mask) {
 486        if (++ignored > 100)
 487            goto out;
 488        goto ignore_char;
 489    }
 490    rsr &= info->read_status_mask;
 491
 492    if (rsr & _LSR_LB_BREAK)
 493        flg = TTY_BREAK;
 494    else if (rsr &  _LSR_PE_MASK)
 495        flg = TTY_PARITY;
 496    else if (rsr &  _LSR_FE_MASK)
 497        flg = TTY_FRAME;
 498
 499    if (rsr &  _LSR_OE_MASK) {
 500        /*
 501         * CHECK: does overrun affect the current character?
 502         * ASSUMPTION: it does not.
 503         */
 504        *tty->flip.flag_buf_ptr++ = flg;
 505        *tty->flip.char_buf_ptr++ = ch;
 506        tty->flip.count++;
 507        if (tty->flip.count >= TTY_FLIPBUF_SIZE)
 508            goto ignore_char;
 509        ch = 0;
 510        flg = TTY_OVERRUN;
 511    }
 512#ifdef SUPPORT_SYSRQ
 513    info->sysrq = 0;
 514#endif
 515    goto error_return;
 516}
 517
 518static void siccuart_tx_chars(struct SICC_info *info)
 519{
 520    struct SICC_port *port = info->port;
 521    int count;
 522        unsigned char status;
 523
 524
 525    if (info->x_char) {
 526        writeb(info->x_char, port->uart_base+ BL_SICC_TBR);
 527        info->state->icount.tx++;
 528        info->x_char = 0;
 529        return;
 530    }
 531    if (info->xmit.head == info->xmit.tail
 532        || info->tty->stopped
 533        || info->tty->hw_stopped) {
 534        siccuart_disable_tx_interrupt(info);
 535                writeb(status&(~_LSR_RBR_MASK),port->uart_base+BL_SICC_LSR);
 536        return;
 537    }
 538
 539    count = port->fifosize;
 540    do {
 541        writeb(info->xmit.buf[info->xmit.tail], port->uart_base+ BL_SICC_TBR);
 542        info->xmit.tail = (info->xmit.tail + 1) & (SICC_XMIT_SIZE - 1);
 543        info->state->icount.tx++;
 544        if (info->xmit.head == info->xmit.tail)
 545            break;
 546    } while (--count > 0);
 547
 548    if (CIRC_CNT(info->xmit.head,
 549             info->xmit.tail,
 550             SICC_XMIT_SIZE) < WAKEUP_CHARS)
 551        siccuart_event(info, EVT_WRITE_WAKEUP);
 552
 553    if (info->xmit.head == info->xmit.tail) {
 554        siccuart_disable_tx_interrupt(info);
 555    }
 556}
 557
 558
 559static irqreturn_t siccuart_int_rx(int irq, void *dev_id, struct pt_regs *regs)
 560{
 561    struct SICC_info *info = dev_id;
 562    siccuart_rx_chars(info, regs);
 563    return IRQ_HANDLED;
 564}
 565
 566
 567static irqreturn_t siccuart_int_tx(int irq, void *dev_id, struct pt_regs *regs)
 568{
 569    struct SICC_info *info = dev_id;
 570    siccuart_tx_chars(info);
 571    return IRQ_HANDLED;
 572}
 573
 574static void siccuart_tasklet_action(unsigned long data)
 575{
 576    struct SICC_info *info = (struct SICC_info *)data;
 577    struct tty_struct *tty;
 578
 579    tty = info->tty;
 580    if (!tty || !test_and_clear_bit(EVT_WRITE_WAKEUP, &info->event))
 581        return;
 582
 583    if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
 584        tty->ldisc.write_wakeup)
 585        (tty->ldisc.write_wakeup)(tty);
 586    wake_up_interruptible(&tty->write_wait);
 587}
 588
 589static int siccuart_startup(struct SICC_info *info)
 590{
 591    unsigned long flags;
 592    unsigned long page;
 593    int retval = 0;
 594
 595    if (info->flags & ASYNC_INITIALIZED) {
 596        return 0;
 597    }
 598
 599    page = get_zeroed_page(GFP_KERNEL);
 600    if (!page)
 601        return -ENOMEM;
 602
 603    if (info->port->uart_base == 0)
 604        info->port->uart_base = (int)ioremap(info->port->uart_base_phys, PAGE_SIZE);
 605    if (info->port->uart_base == 0) {
 606        free_page(page);
 607        return -ENOMEM;
 608    }
 609
 610    /* lock access to info while doing setup */
 611    spin_lock_irqsave(&info->state->sicc_lock,flags);
 612
 613    if (info->xmit.buf)
 614        free_page(page);
 615    else
 616        info->xmit.buf = (unsigned char *) page;
 617
 618
 619    info->mctrl = 0;
 620    if (info->tty->termios->c_cflag & CBAUD)
 621        info->mctrl = TIOCM_RTS | TIOCM_DTR;
 622    info->port->set_mctrl(info->port, info->mctrl);
 623
 624    /*
 625     * initialise the old status of the modem signals
 626     */
 627    info->old_status = 0; // UART_GET_FR(info->port) & AMBA_UARTFR_MODEM_ANY;
 628
 629
 630    if (info->tty)
 631        clear_bit(TTY_IO_ERROR, &info->tty->flags);
 632    info->xmit.head = info->xmit.tail = 0;
 633
 634    /*
 635     * Set up the tty->alt_speed kludge
 636     */
 637    if (info->tty) {
 638        if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
 639            info->tty->alt_speed = 57600;
 640        if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
 641            info->tty->alt_speed = 115200;
 642        if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
 643            info->tty->alt_speed = 230400;
 644        if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
 645            info->tty->alt_speed = 460800;
 646    }
 647
 648
 649    writeb( 0x00, info->port->uart_base + BL_SICC_IrCR );  // disable IrDA
 650
 651
 652    /*
 653     * and set the speed of the serial port
 654     */
 655    siccuart_change_speed(info, 0);
 656
 657    // enable rx/tx ports
 658    writeb(_RCR_ER_ENABLE /*| _RCR_PME_HARD*/, info->port->uart_base + BL_SICC_RCR);
 659    writeb(_TxCR_ET_ENABLE               , info->port->uart_base + BL_SICC_TxCR);
 660
 661    readb(info->port->uart_base + BL_SICC_RBR); // clear rx port
 662
 663    writeb(0xf8, info->port->uart_base + BL_SICC_LSR);   /* reset bits 0-4 of LSR */
 664
 665    /*
 666     * Finally, enable interrupts
 667     */
 668
 669     /*
 670     * Allocate the IRQ
 671     */
 672        retval = request_irq(info->port->irqrx, siccuart_int_rx, 0, "SICC rx", info);
 673        if (retval) {
 674             if (capable(CAP_SYS_ADMIN)) {
 675                   if (info->tty)
 676                          set_bit(TTY_IO_ERROR, &info->tty->flags);
 677                   retval = 0;
 678             }
 679              goto errout;
 680         }
 681    retval = request_irq(info->port->irqtx, siccuart_int_tx, 0, "SICC tx", info);
 682    if (retval) {
 683        if (capable(CAP_SYS_ADMIN)) {
 684            if (info->tty)
 685                set_bit(TTY_IO_ERROR, &info->tty->flags);
 686            retval = 0;
 687        }
 688        free_irq(info->port->irqrx, info);
 689        goto errout;
 690    }
 691
 692    siccuart_enable_rx_interrupt(info);
 693
 694    info->flags |= ASYNC_INITIALIZED;
 695    spin_unlock_irqrestore(&info->state->sicc_lock,flags);
 696    return 0;
 697
 698
 699errout:
 700    spin_unlock_irqrestore(&info->state->sicc_lock,flags);
 701    return retval;
 702}
 703
 704/*
 705 * This routine will shutdown a serial port; interrupts are disabled, and
 706 * DTR is dropped if the hangup on close termio flag is on.
 707 */
 708static void siccuart_shutdown(struct SICC_info *info)
 709{
 710    unsigned long flags;
 711
 712    if (!(info->flags & ASYNC_INITIALIZED))
 713        return;
 714
 715    /* lock while shutting down port */
 716    spin_lock_irqsave(&info->state->sicc_lock,flags); /* Disable interrupts */
 717
 718    /*
 719     * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
 720     * here so the queue might never be woken up
 721     */
 722    wake_up_interruptible(&info->delta_msr_wait);
 723
 724    /*
 725     * disable all interrupts, disable the port
 726     */
 727    siccuart_disable_rx_interrupt(info);
 728    siccuart_disable_tx_interrupt(info);
 729
 730    /*
 731     * Free the IRQ
 732     */
 733    free_irq(info->port->irqtx, info);
 734    free_irq(info->port->irqrx, info);
 735
 736    if (info->xmit.buf) {
 737        unsigned long pg = (unsigned long) info->xmit.buf;
 738        info->xmit.buf = NULL;
 739        free_page(pg);
 740    }
 741
 742
 743    if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
 744        info->mctrl &= ~(TIOCM_DTR|TIOCM_RTS);
 745    info->port->set_mctrl(info->port, info->mctrl);
 746
 747    /* kill off our tasklet */
 748    tasklet_kill(&info->tlet);
 749    if (info->tty)
 750        set_bit(TTY_IO_ERROR, &info->tty->flags);
 751
 752    info->flags &= ~ASYNC_INITIALIZED;
 753
 754    spin_unlock_irqrestore(&info->state->sicc_lock,flags);
 755}
 756
 757
 758static void siccuart_change_speed(struct SICC_info *info, struct termios *old_termios)
 759{
 760    unsigned int lcr_h, baud, quot, cflag, old_rcr, old_tcr, bits;
 761    unsigned long flags;
 762
 763    if (!info->tty || !info->tty->termios)
 764        return;
 765
 766    cflag = info->tty->termios->c_cflag;
 767
 768    pr_debug("siccuart_set_cflag(0x%x) called\n", cflag);
 769    /* byte size and parity */
 770    switch (cflag & CSIZE) {
 771    case CS7: lcr_h =   _LCR_PE_DISABLE | _LCR_DB_7_BITS | _LCR_SB_1_BIT; bits = 9;  break;
 772    default:  lcr_h =   _LCR_PE_DISABLE | _LCR_DB_8_BITS | _LCR_SB_1_BIT; bits = 10; break; // CS8
 773    }
 774    if (cflag & CSTOPB) {
 775        lcr_h |= _LCR_SB_2_BIT;
 776        bits ++;
 777    }
 778    if (cflag & PARENB) {
 779        lcr_h |=  _LCR_PE_ENABLE;
 780        bits++;
 781        if (!(cflag & PARODD))
 782            lcr_h |=  _LCR_PTY_ODD;
 783        else
 784            lcr_h |=  _LCR_PTY_EVEN;
 785    }
 786
 787    do {
 788        /* Determine divisor based on baud rate */
 789        baud = tty_get_baud_rate(info->tty);
 790        if (!baud)
 791            baud = 9600;
 792
 793
 794        {
 795           // here is ppc403SetBaud(com_port, baud);
 796           unsigned long divisor, clockSource, temp;
 797
 798           /* Ensure CICCR[7] is 0 to select Internal Baud Clock */
 799           powerpcMtcic_cr((unsigned long)(powerpcMfcic_cr() & 0xFEFFFFFF));
 800
 801           /* Determine Internal Baud Clock Frequency */
 802           /* powerpcMfclkgpcr() reads DCR 0x120 - the*/
 803           /* SCCR (Serial Clock Control Register) on Vesta */
 804           temp = powerpcMfclkgpcr();
 805
 806           if(temp & 0x00000080) {
 807               clockSource = 324000000;
 808           }
 809           else {
 810               clockSource = 216000000;
 811           }
 812           clockSource = clockSource/(unsigned long)((temp&0x00FC0000)>>18);
 813           divisor = clockSource/(16*baud) - 1;
 814           /* divisor has only 12 bits of resolution */
 815           if(divisor>0x00000FFF){
 816               divisor=0x00000FFF;
 817           }
 818
 819           quot = divisor;
 820        }
 821
 822        if (baud == 38400 &&
 823            ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
 824            quot = info->state->custom_divisor;
 825
 826        if (!quot && old_termios) {
 827            info->tty->termios->c_cflag &= ~CBAUD;
 828            info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
 829            old_termios = NULL;
 830        }
 831    } while (quot == 0 && old_termios);
 832
 833    /* As a last resort, if the quotient is zero, default to 9600 bps */
 834    if (!quot)
 835        quot = (info->port->uartclk / (16 * 9600)) - 1;
 836
 837    info->timeout = info->port->fifosize * HZ * bits / baud;
 838    info->timeout += HZ/50;     /* Add .02 seconds of slop */
 839
 840    if (cflag & CRTSCTS)
 841        info->flags |= ASYNC_CTS_FLOW;
 842    else
 843        info->flags &= ~ASYNC_CTS_FLOW;
 844    if (cflag & CLOCAL)
 845        info->flags &= ~ASYNC_CHECK_CD;
 846    else
 847        info->flags |= ASYNC_CHECK_CD;
 848
 849    /*
 850     * Set up parity check flag
 851     */
 852#define RELEVENT_IFLAG(iflag)   ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
 853
 854    info->read_status_mask = _LSR_OE_MASK;
 855    if (I_INPCK(info->tty))
 856        info->read_status_mask |= _LSR_FE_MASK | _LSR_PE_MASK;
 857    if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
 858        info->read_status_mask |= _LSR_LB_MASK;
 859
 860    /*
 861     * Characters to ignore
 862     */
 863    info->ignore_status_mask = 0;
 864    if (I_IGNPAR(info->tty))
 865        info->ignore_status_mask |= _LSR_FE_MASK | _LSR_PE_MASK;
 866    if (I_IGNBRK(info->tty)) {
 867        info->ignore_status_mask |=  _LSR_LB_MASK;
 868        /*
 869         * If we're ignoring parity and break indicators,
 870         * ignore overruns to (for real raw support).
 871         */
 872        if (I_IGNPAR(info->tty))
 873            info->ignore_status_mask |=  _LSR_OE_MASK;
 874    }
 875
 876    /* disable interrupts while reading and clearing registers */
 877    spin_lock_irqsave(&info->state->sicc_lock,flags);
 878
 879    old_rcr = readb(info->port->uart_base + BL_SICC_RCR);
 880    old_tcr = readb(info->port->uart_base + BL_SICC_TxCR);
 881
 882
 883    writeb(0, info->port->uart_base + BL_SICC_RCR);
 884    writeb(0, info->port->uart_base + BL_SICC_TxCR);
 885
 886    /*RLBtrace (&ppc403Chan0, 0x2000000c, 0, 0);*/
 887
 888
 889    spin_unlock_irqrestore(&info->state->sicc_lock,flags);
 890
 891
 892    /* Set baud rate */
 893    writeb((quot & 0x00000F00)>>8, info->port->uart_base + BL_SICC_BRDH );
 894    writeb( quot & 0x00000FF,      info->port->uart_base + BL_SICC_BRDL );
 895
 896    /* Set CTL2 reg to use external clock (ExtClk) and enable FIFOs. */
 897    /* For now, do NOT use FIFOs since 403 UART did not have this    */
 898    /* capability and this driver was inherited from 403UART.        */
 899    writeb(_CTL2_EXTERN, info->port->uart_base + BL_SICC_CTL2);
 900
 901    writeb(lcr_h, info->port->uart_base + BL_SICC_LCR);
 902
 903    writeb(old_rcr, info->port->uart_base + BL_SICC_RCR);  // restore rcr
 904    writeb(old_tcr, info->port->uart_base + BL_SICC_TxCR); // restore txcr
 905
 906}
 907
 908
 909static void siccuart_put_char(struct tty_struct *tty, u_char ch)
 910{
 911    struct SICC_info *info = tty->driver_data;
 912    unsigned long flags;
 913
 914    if (!tty || !info->xmit.buf)
 915        return;
 916
 917    /* lock info->xmit while adding character to tx buffer */
 918    spin_lock_irqsave(&info->state->sicc_lock,flags);
 919    if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SICC_XMIT_SIZE) != 0) {
 920        info->xmit.buf[info->xmit.head] = ch;
 921        info->xmit.head = (info->xmit.head + 1) & (SICC_XMIT_SIZE - 1);
 922    }
 923    spin_unlock_irqrestore(&info->state->sicc_lock,flags);
 924}
 925
 926static void siccuart_flush_chars(struct tty_struct *tty)
 927{
 928    struct SICC_info *info = tty->driver_data;
 929    unsigned long flags;
 930
 931    if (info->xmit.head == info->xmit.tail
 932        || tty->stopped
 933        || tty->hw_stopped
 934        || !info->xmit.buf)
 935        return;
 936
 937    /* disable interrupts while transmitting characters */
 938    spin_lock_irqsave(&info->state->sicc_lock,flags);
 939    siccuart_enable_tx_interrupt(info);
 940    spin_unlock_irqrestore(&info->state->sicc_lock,flags);
 941}
 942
 943static int siccuart_write(struct tty_struct *tty,
 944              const u_char * buf, int count)
 945{
 946    struct SICC_info *info = tty->driver_data;
 947    unsigned long flags;
 948    int c, ret = 0;
 949
 950    if (!tty || !info->xmit.buf || !tmp_buf)
 951        return 0;
 952
 953    /* lock info->xmit while removing characters from buffer */
 954    spin_lock_irqsave(&info->state->sicc_lock,flags);
 955    while (1) {
 956        c = CIRC_SPACE_TO_END(info->xmit.head,
 957                      info->xmit.tail,
 958                      SICC_XMIT_SIZE);
 959        if (count < c)
 960            c = count;
 961        if (c <= 0)
 962            break;
 963        memcpy(info->xmit.buf + info->xmit.head, buf, c);
 964        info->xmit.head = (info->xmit.head + c) &
 965                  (SICC_XMIT_SIZE - 1);
 966        buf += c;
 967        count -= c;
 968        ret += c;
 969    }
 970    if (info->xmit.head != info->xmit.tail
 971        && !tty->stopped
 972        && !tty->hw_stopped)
 973        siccuart_enable_tx_interrupt(info);
 974    spin_unlock_irqrestore(&info->state->sicc_lock,flags);
 975    return ret;
 976}
 977
 978static int siccuart_write_room(struct tty_struct *tty)
 979{
 980    struct SICC_info *info = tty->driver_data;
 981
 982    return CIRC_SPACE(info->xmit.head, info->xmit.tail, SICC_XMIT_SIZE);
 983}
 984
 985static int siccuart_chars_in_buffer(struct tty_struct *tty)
 986{
 987    struct SICC_info *info = tty->driver_data;
 988
 989    return CIRC_CNT(info->xmit.head, info->xmit.tail, SICC_XMIT_SIZE);
 990}
 991
 992static void siccuart_flush_buffer(struct tty_struct *tty)
 993{
 994    struct SICC_info *info = tty->driver_data;
 995    unsigned long flags;
 996
 997    pr_debug("siccuart_flush_buffer(%d) called\n", tty->index);
 998    /* lock info->xmit while zeroing buffer counts */
 999    spin_lock_irqsave(&info->state->sicc_lock,flags);
1000    info->xmit.head = info->xmit.tail = 0;
1001    spin_unlock_irqrestore(&info->state->sicc_lock,flags);
1002    wake_up_interruptible(&tty->write_wait);
1003    if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
1004        tty->ldisc.write_wakeup)
1005        (tty->ldisc.write_wakeup)(tty);
1006}
1007
1008/*
1009 * This function is used to send a high-priority XON/XOFF character to
1010 * the device
1011 */
1012static void siccuart_send_xchar(struct tty_struct *tty, char ch)
1013{
1014    struct SICC_info *info = tty->driver_data;
1015
1016    info->x_char = ch;
1017    if (ch)
1018       siccuart_enable_tx_interrupt(info);
1019}
1020
1021static void siccuart_throttle(struct tty_struct *tty)
1022{
1023    struct SICC_info *info = tty->driver_data;
1024    unsigned long flags;
1025
1026    if (I_IXOFF(tty))
1027        siccuart_send_xchar(tty, STOP_CHAR(tty));
1028
1029    if (tty->termios->c_cflag & CRTSCTS) {
1030        /* disable interrupts while setting modem control lines */
1031        spin_lock_irqsave(&info->state->sicc_lock,flags);
1032        info->mctrl &= ~TIOCM_RTS;
1033        info->port->set_mctrl(info->port, info->mctrl);
1034        spin_unlock_irqrestore(&info->state->sicc_lock,flags);
1035    }
1036}
1037
1038static void siccuart_unthrottle(struct tty_struct *tty)
1039{
1040    struct SICC_info *info = (struct SICC_info *) tty->driver_data;
1041    unsigned long flags;
1042
1043    if (I_IXOFF(tty)) {
1044        if (info->x_char)
1045            info->x_char = 0;
1046        else
1047            siccuart_send_xchar(tty, START_CHAR(tty));
1048    }
1049
1050    if (tty->termios->c_cflag & CRTSCTS) {
1051        /* disable interrupts while setting modem control lines */
1052        spin_lock_irqsave(&info->state->sicc_lock,flags);
1053        info->mctrl |= TIOCM_RTS;
1054        info->port->set_mctrl(info->port, info->mctrl);
1055        spin_unlock_irqrestore(&info->state->sicc_lock,flags);
1056    }
1057}
1058
1059static int get_serial_info(struct SICC_info *info, struct serial_struct *retinfo)
1060{
1061    struct SICC_state *state = info->state;
1062    struct SICC_port *port = info->port;
1063    struct serial_struct tmp;
1064
1065    memset(&tmp, 0, sizeof(tmp));
1066    tmp.type       = 0;
1067    tmp.line       = state->line;
1068    tmp.port       = port->uart_base;
1069    if (HIGH_BITS_OFFSET)
1070        tmp.port_high = port->uart_base >> HIGH_BITS_OFFSET;
1071    tmp.irq        = port->irqrx;
1072    tmp.flags      = 0;
1073    tmp.xmit_fifo_size = port->fifosize;
1074    tmp.baud_base      = port->uartclk / 16;
1075    tmp.close_delay    = state->close_delay;
1076    tmp.closing_wait   = state->closing_wait;
1077    tmp.custom_divisor = state->custom_divisor;
1078
1079    if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
1080        return -EFAULT;
1081    return 0;
1082}
1083
1084static int set_serial_info(struct SICC_info *info,
1085               struct serial_struct *newinfo)
1086{
1087    struct serial_struct new_serial;
1088    struct SICC_state *state, old_state;
1089    struct SICC_port *port;
1090    unsigned long new_port;
1091    unsigned int i, change_irq, change_port;
1092    int retval = 0;
1093
1094    if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
1095        return -EFAULT;
1096
1097    state = info->state;
1098    old_state = *state;
1099    port = info->port;
1100
1101    new_port = new_serial.port;
1102    if (HIGH_BITS_OFFSET)
1103        new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
1104
1105    change_irq  = new_serial.irq != port->irqrx;
1106    change_port = new_port != port->uart_base;
1107
1108    if (!capable(CAP_SYS_ADMIN)) {
1109        if (change_irq || change_port ||
1110            (new_serial.baud_base != port->uartclk / 16) ||
1111            (new_serial.close_delay != state->close_delay) ||
1112            (new_serial.xmit_fifo_size != port->fifosize) ||
1113            ((new_serial.flags & ~ASYNC_USR_MASK) !=
1114             (state->flags & ~ASYNC_USR_MASK)))
1115            return -EPERM;
1116        state->flags = ((state->flags & ~ASYNC_USR_MASK) |
1117                (new_serial.flags & ASYNC_USR_MASK));
1118        info->flags = ((info->flags & ~ASYNC_USR_MASK) |
1119                   (new_serial.flags & ASYNC_USR_MASK));
1120        state->custom_divisor = new_serial.custom_divisor;
1121        goto check_and_exit;
1122    }
1123
1124    if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
1125        (new_serial.baud_base < 9600))
1126        return -EINVAL;
1127
1128    if (new_serial.type && change_port) {
1129        for (i = 0; i < SERIAL_SICC_NR; i++)
1130            if ((port != sicc_ports + i) &&
1131                sicc_ports[i].uart_base != new_port)
1132                return -EADDRINUSE;
1133    }
1134
1135    if ((change_port || change_irq) && (state->count > 1))
1136        return -EBUSY;
1137
1138    /*
1139     * OK, past this point, all the error checking has been done.
1140     * At this point, we start making changes.....
1141     */
1142    port->uartclk = new_serial.baud_base * 16;
1143    state->flags = ((state->flags & ~ASYNC_FLAGS) |
1144            (new_serial.flags & ASYNC_FLAGS));
1145    info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) |
1146               (info->flags & ASYNC_INTERNAL_FLAGS));
1147    state->custom_divisor = new_serial.custom_divisor;
1148    state->close_delay = new_serial.close_delay * HZ / 100;
1149    state->closing_wait = new_serial.closing_wait * HZ / 100;
1150    info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
1151    port->fifosize = new_serial.xmit_fifo_size;
1152
1153    if (change_port || change_irq) {
1154        /*
1155         * We need to shutdown the serial port at the old
1156         * port/irq combination.
1157         */
1158        siccuart_shutdown(info);
1159        port->irqrx = new_serial.irq;
1160        port->uart_base = new_port;
1161    }
1162
1163check_and_exit:
1164    if (!port->uart_base)
1165        return 0;
1166    if (info->flags & ASYNC_INITIALIZED) {
1167        if ((old_state.flags & ASYNC_SPD_MASK) !=
1168            (state->flags & ASYNC_SPD_MASK) ||
1169            (old_state.custom_divisor != state->custom_divisor)) {
1170            if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
1171                info->tty->alt_speed = 57600;
1172            if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
1173                info->tty->alt_speed = 115200;
1174            if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
1175                info->tty->alt_speed = 230400;
1176            if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
1177                info->tty->alt_speed = 460800;
1178            siccuart_change_speed(info, NULL);
1179        }
1180    } else
1181        retval = siccuart_startup(info);
1182    return retval;
1183}
1184
1185
1186/*
1187 * get_lsr_info - get line status register info
1188 */
1189static int get_lsr_info(struct SICC_info *info, unsigned int *value)
1190{
1191    unsigned int result, status;
1192    unsigned long flags;
1193
1194    /* disable interrupts while reading status from port */
1195    spin_lock_irqsave(&info->state->sicc_lock,flags);
1196    status = readb(info->port->uart_base +  BL_SICC_LSR);
1197    spin_unlock_irqrestore(&info->state->sicc_lock,flags);
1198    result = status & _LSR_TSR_EMPTY ? TIOCSER_TEMT : 0;
1199
1200    /*
1201     * If we're about to load something into the transmit
1202     * register, we'll pretend the transmitter isn't empty to
1203     * avoid a race condition (depending on when the transmit
1204     * interrupt happens).
1205     */
1206    if (info->x_char ||
1207        ((CIRC_CNT(info->xmit.head, info->xmit.tail,
1208               SICC_XMIT_SIZE) > 0) &&
1209         !info->tty->stopped && !info->tty->hw_stopped))
1210        result &= TIOCSER_TEMT;
1211
1212    return put_user(result, value);
1213}
1214
1215static int get_modem_info(struct SICC_info *info, unsigned int *value)
1216{
1217    unsigned int result = info->mctrl;
1218
1219    return put_user(result, value);
1220}
1221
1222static int set_modem_info(struct SICC_info *info, unsigned int cmd,
1223              unsigned int *value)
1224{
1225    unsigned int arg, old;
1226    unsigned long flags;
1227
1228    if (get_user(arg, value))
1229        return -EFAULT;
1230
1231    old = info->mctrl;
1232    switch (cmd) {
1233    case TIOCMBIS:
1234        info->mctrl |= arg;
1235        break;
1236
1237    case TIOCMBIC:
1238        info->mctrl &= ~arg;
1239        break;
1240
1241    case TIOCMSET:
1242        info->mctrl = arg;
1243        break;
1244
1245    default:
1246        return -EINVAL;
1247    }
1248    /* disable interrupts while setting modem control lines */
1249    spin_lock_irqsave(&info->state->sicc_lock,flags);
1250    if (old != info->mctrl)
1251        info->port->set_mctrl(info->port, info->mctrl);
1252    spin_unlock_irqrestore(&info->state->sicc_lock,flags);
1253    return 0;
1254}
1255
1256static void siccuart_break_ctl(struct tty_struct *tty, int break_state)
1257{
1258    struct SICC_info *info = tty->driver_data;
1259    unsigned long flags;
1260    unsigned int lcr_h;
1261
1262
1263    /* disable interrupts while setting break state */
1264    spin_lock_irqsave(&info->state->sicc_lock,flags);
1265    lcr_h = readb(info->port + BL_SICC_LSR);
1266    if (break_state == -1)
1267        lcr_h |=  _LSR_LB_MASK;
1268    else
1269        lcr_h &= ~_LSR_LB_MASK;
1270    writeb(lcr_h, info->port + BL_SICC_LSRS);
1271    spin_unlock_irqrestore(&info->state->sicc_lock,flags);
1272}
1273
1274static int siccuart_ioctl(struct tty_struct *tty, struct file *file,
1275               unsigned int cmd, unsigned long arg)
1276{
1277    struct SICC_info *info = tty->driver_data;
1278    struct SICC_icount cnow;
1279    struct serial_icounter_struct icount;
1280    unsigned long flags;
1281
1282    if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
1283        (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
1284        (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
1285        if (tty->flags & (1 << TTY_IO_ERROR))
1286            return -EIO;
1287    }
1288
1289    switch (cmd) {
1290        case TIOCMGET:
1291            return get_modem_info(info, (unsigned int *)arg);
1292        case TIOCMBIS:
1293        case TIOCMBIC:
1294        case TIOCMSET:
1295            return set_modem_info(info, cmd, (unsigned int *)arg);
1296        case TIOCGSERIAL:
1297            return get_serial_info(info,
1298                           (struct serial_struct *)arg);
1299        case TIOCSSERIAL:
1300            return set_serial_info(info,
1301                           (struct serial_struct *)arg);
1302        case TIOCSERGETLSR: /* Get line status register */
1303            return get_lsr_info(info, (unsigned int *)arg);
1304        /*
1305         * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
1306         * - mask passed in arg for lines of interest
1307         *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
1308         * Caller should use TIOCGICOUNT to see which one it was
1309         */
1310        case TIOCMIWAIT:
1311            return 0;
1312        /*
1313         * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
1314         * Return: write counters to the user passed counter struct
1315         * NB: both 1->0 and 0->1 transitions are counted except for
1316         *     RI where only 0->1 is counted.
1317         */
1318        case TIOCGICOUNT:
1319            /* disable interrupts while getting interrupt count */
1320            spin_lock_irqsave(&info->state->sicc_lock,flags);
1321            cnow = info->state->icount;
1322            spin_unlock_irqrestore(&info->state->sicc_lock,flags);
1323            icount.cts = cnow.cts;
1324            icount.dsr = cnow.dsr;
1325            icount.rng = cnow.rng;
1326            icount.dcd = cnow.dcd;
1327            icount.rx  = cnow.rx;
1328            icount.tx  = cnow.tx;
1329            icount.frame = cnow.frame;
1330            icount.overrun = cnow.overrun;
1331            icount.parity = cnow.parity;
1332            icount.brk = cnow.brk;
1333            icount.buf_overrun = cnow.buf_overrun;
1334
1335            return copy_to_user((void *)arg, &icount, sizeof(icount))
1336                    ? -EFAULT : 0;
1337
1338        default:
1339            return -ENOIOCTLCMD;
1340    }
1341    return 0;
1342}
1343
1344static void siccuart_set_termios(struct tty_struct *tty, struct termios *old_termios)
1345{
1346    struct SICC_info *info = tty->driver_data;
1347    unsigned long flags;
1348    unsigned int cflag = tty->termios->c_cflag;
1349
1350    if ((cflag ^ old_termios->c_cflag) == 0 &&
1351        RELEVENT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)
1352        return;
1353
1354    siccuart_change_speed(info, old_termios);
1355
1356    /* Handle transition to B0 status */
1357    if ((old_termios->c_cflag & CBAUD) &&
1358        !(cflag & CBAUD)) {
1359        /* disable interrupts while setting break state */
1360        spin_lock_irqsave(&info->state->sicc_lock,flags);
1361        info->mctrl &= ~(TIOCM_RTS | TIOCM_DTR);
1362        info->port->set_mctrl(info->port, info->mctrl);
1363        spin_unlock_irqrestore(&info->state->sicc_lock,flags);
1364    }
1365
1366    /* Handle transition away from B0 status */
1367    if (!(old_termios->c_cflag & CBAUD) &&
1368        (cflag & CBAUD)) {
1369        /* disable interrupts while setting break state */
1370        spin_lock_irqsave(&info->state->sicc_lock,flags);
1371        info->mctrl |= TIOCM_DTR;
1372        if (!(cflag & CRTSCTS) ||
1373            !test_bit(TTY_THROTTLED, &tty->flags))
1374            info->mctrl |= TIOCM_RTS;
1375        info->port->set_mctrl(info->port, info->mctrl);
1376        spin_unlock_irqrestore(&info->state->sicc_lock,flags);
1377    }
1378
1379    /* Handle turning off CRTSCTS */
1380    if ((old_termios->c_cflag & CRTSCTS) &&
1381        !(cflag & CRTSCTS)) {
1382        tty->hw_stopped = 0;
1383        siccuart_start(tty);
1384    }
1385
1386#if 0
1387    /*
1388     * No need to wake up processes in open wait, since they
1389     * sample the CLOCAL flag once, and don't recheck it.
1390     * XXX  It's not clear whether the current behavior is correct
1391     * or not.  Hence, this may change.....
1392     */
1393    if (!(old_termios->c_cflag & CLOCAL) &&
1394        (tty->termios->c_cflag & CLOCAL))
1395        wake_up_interruptible(&info->open_wait);
1396#endif
1397}
1398
1399static void siccuart_close(struct tty_struct *tty, struct file *filp)
1400{
1401    struct SICC_info *info = tty->driver_data;
1402    struct SICC_state *state;
1403    unsigned long flags;
1404
1405    if (!info)
1406        return;
1407
1408    state = info->state;
1409
1410    //pr_debug("siccuart_close() called\n");
1411
1412    /* lock tty->driver_data while closing port */
1413    spin_lock_irqsave(&info->state->sicc_lock,flags);
1414
1415    if (tty_hung_up_p(filp)) {
1416        goto quick_close;
1417    }
1418
1419    if ((tty->count == 1) && (state->count != 1)) {
1420        /*
1421         * Uh, oh.  tty->count is 1, which means that the tty
1422         * structure will be freed.  state->count should always
1423         * be one in these conditions.  If it's greater than
1424         * one, we've got real problems, since it means the
1425         * serial port won't be shutdown.
1426         */
1427        printk("siccuart_close: bad serial port count; tty->count is 1, state->count is %d\n", state->count);
1428        state->count = 1;
1429    }
1430    if (--state->count < 0) {
1431        printk("rs_close: bad serial port count for %s: %d\n", tty->name, state->count);
1432        state->count = 0;
1433    }
1434    if (state->count) {
1435        goto quick_close;
1436    }
1437    info->flags |= ASYNC_CLOSING;
1438    spin_unlock_irqrestore(&info->state->sicc_lock,flags);
1439    /*
1440     * Now we wait for the transmit buffer to clear; and we notify
1441     * the line discipline to only process XON/XOFF characters.
1442     */
1443    tty->closing = 1;
1444    if (info->state->closing_wait != ASYNC_CLOSING_WAIT_NONE)
1445        tty_wait_until_sent(tty, info->state->closing_wait);
1446    /*
1447     * At this point, we stop accepting input.  To do this, we
1448     * disable the receive line status interrupts.
1449     */
1450    if (info->flags & ASYNC_INITIALIZED) {
1451        siccuart_disable_rx_interrupt(info);
1452        /*
1453         * Before we drop DTR, make sure the UART transmitter
1454         * has completely drained; this is especially
1455         * important if there is a transmit FIFO!
1456         */
1457        siccuart_wait_until_sent(tty, info->timeout);
1458    }
1459    siccuart_shutdown(info);
1460    if (tty->driver->flush_buffer)
1461        tty->driver->flush_buffer(tty);
1462    if (tty->ldisc.flush_buffer)
1463        tty->ldisc.flush_buffer(tty);
1464    tty->closing = 0;
1465    info->event = 0;
1466    info->tty = NULL;
1467    if (info->blocked_open) {
1468        if (info->state->close_delay) {
1469            set_current_state(TASK_INTERRUPTIBLE);
1470            schedule_timeout(info->state->close_delay);
1471        }
1472        wake_up_interruptible(&info->open_wait);
1473    }
1474    info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
1475    wake_up_interruptible(&info->close_wait);
1476    return;
1477
1478quick_close:
1479    spin_unlock_irqrestore(&info->state->sicc_lock,flags);
1480    return;
1481}
1482
1483static void siccuart_wait_until_sent(struct tty_struct *tty, int timeout)
1484{
1485    struct SICC_info *info = (struct SICC_info *) tty->driver_data;
1486    unsigned long char_time, expire;
1487
1488    if (info->port->fifosize == 0)
1489        return;
1490
1491    /*
1492     * Set the check interval to be 1/5 of the estimated time to
1493     * send a single character, and make it at least 1.  The check
1494     * interval should also be less than the timeout.
1495     *
1496     * Note: we have to use pretty tight timings here to satisfy
1497     * the NIST-PCTS.
1498     */
1499    char_time = (info->timeout - HZ/50) / info->port->fifosize;
1500    char_time = char_time / 5;
1501    if (char_time == 0)
1502        char_time = 1;
1503
1504    // Crazy!!   sometimes the input arg 'timeout' can be negtive numbers  :-(
1505    if (timeout >= 0 && timeout < char_time)
1506        char_time = timeout;
1507    /*
1508     * If the transmitter hasn't cleared in twice the approximate
1509     * amount of time to send the entire FIFO, it probably won't
1510     * ever clear.  This assumes the UART isn't doing flow
1511     * control, which is currently the case.  Hence, if it ever
1512     * takes longer than info->timeout, this is probably due to a
1513     * UART bug of some kind.  So, we clamp the timeout parameter at
1514     * 2*info->timeout.
1515     */
1516    if (!timeout || timeout > 2 * info->timeout)
1517        timeout = 2 * info->timeout;
1518
1519    expire = jiffies + timeout;
1520    pr_debug("siccuart_wait_until_sent(%d), jiff=%lu, expire=%lu  char_time=%lu...\n",
1521           tty->index, jiffies,
1522           expire, char_time);
1523    while ((readb(info->port->uart_base + BL_SICC_LSR) & _LSR_TX_ALL) != _LSR_TX_ALL) {
1524        set_current_state(TASK_INTERRUPTIBLE);
1525        schedule_timeout(char_time);
1526        if (signal_pending(current))
1527            break;
1528        if (timeout && time_after(jiffies, expire))
1529            break;
1530    }
1531    set_current_state(TASK_RUNNING);
1532}
1533
1534static void siccuart_hangup(struct tty_struct *tty)
1535{
1536    struct SICC_info *info = tty->driver_data;
1537    struct SICC_state *state = info->state;
1538
1539    siccuart_flush_buffer(tty);
1540    if (info->flags & ASYNC_CLOSING)
1541        return;
1542    siccuart_shutdown(info);
1543    info->event = 0;
1544    state->count = 0;
1545    info->flags &= ~ASYNC_NORMAL_ACTIVE;
1546    info->tty = NULL;
1547    wake_up_interruptible(&info->open_wait);
1548}
1549
1550static int block_til_ready(struct tty_struct *tty, struct file *filp,
1551               struct SICC_info *info)
1552{
1553    DECLARE_WAITQUEUE(wait, current);
1554    struct SICC_state *state = info->state;
1555    unsigned long flags;
1556    int do_clocal = 0, extra_count = 0, retval;
1557
1558    /*
1559     * If the device is in the middle of being closed, then block
1560     * until it's done, and then try again.
1561     */
1562    if (tty_hung_up_p(filp) ||
1563        (info->flags & ASYNC_CLOSING)) {
1564        if (info->flags & ASYNC_CLOSING)
1565            interruptible_sleep_on(&info->close_wait);
1566        return (info->flags & ASYNC_HUP_NOTIFY) ?
1567            -EAGAIN : -ERESTARTSYS;
1568    }
1569
1570    /*
1571     * If non-blocking mode is set, or the port is not enabled,
1572     * then make the check up front and then exit.
1573     */
1574    if ((filp->f_flags & O_NONBLOCK) ||
1575        (tty->flags & (1 << TTY_IO_ERROR))) {
1576        info->flags |= ASYNC_NORMAL_ACTIVE;
1577        return 0;
1578    }
1579
1580    if (tty->termios->c_cflag & CLOCAL)
1581        do_clocal = 1;
1582
1583    /*
1584     * Block waiting for the carrier detect and the line to become
1585     * free (i.e., not in use by the callout).  While we are in
1586     * this loop, state->count is dropped by one, so that
1587     * rs_close() knows when to free things.  We restore it upon
1588     * exit, either normal or abnormal.
1589     */
1590    retval = 0;
1591    add_wait_queue(&info->open_wait, &wait);
1592    /* lock while decrementing state->count */
1593    spin_lock_irqsave(&info->state->sicc_lock,flags);
1594    if (!tty_hung_up_p(filp)) {
1595        extra_count = 1;
1596        state->count--;
1597    }
1598    spin_unlock_irqrestore(&info->state->sicc_lock,flags);
1599    info->blocked_open++;
1600    while (1) {
1601        /* disable interrupts while setting modem control lines */
1602        spin_lock_irqsave(&info->state->sicc_lock,flags);
1603        if (tty->termios->c_cflag & CBAUD) {
1604            info->mctrl = TIOCM_DTR | TIOCM_RTS;
1605            info->port->set_mctrl(info->port, info->mctrl);
1606        }
1607        spin_unlock_irqrestore(&info->state->sicc_lock,flags);
1608        set_current_state(TASK_INTERRUPTIBLE);
1609        if (tty_hung_up_p(filp) ||
1610            !(info->flags & ASYNC_INITIALIZED)) {
1611            if (info->flags & ASYNC_HUP_NOTIFY)
1612                retval = -EAGAIN;
1613            else
1614                retval = -ERESTARTSYS;
1615            break;
1616        }
1617        if (!(info->flags & ASYNC_CLOSING) &&
1618            (do_clocal /*|| (UART_GET_FR(info->port) & SICC_UARTFR_DCD)*/))
1619            break;
1620        if (signal_pending(current)) {
1621            retval = -ERESTARTSYS;
1622            break;
1623        }
1624        schedule();
1625    }
1626    set_current_state(TASK_RUNNING);
1627    remove_wait_queue(&info->open_wait, &wait);
1628    if (extra_count)
1629        state->count++;
1630    info->blocked_open--;
1631    if (retval)
1632        return retval;
1633    info->flags |= ASYNC_NORMAL_ACTIVE;
1634    return 0;
1635}
1636
1637static struct SICC_info *siccuart_get(int line)
1638{
1639    struct SICC_info *info;
1640    struct SICC_state *state = sicc_state + line;
1641
1642    state->count++;
1643    if (state->info)
1644        return state->info;
1645    info = kmalloc(sizeof(struct SICC_info), GFP_KERNEL);
1646    if (info) {
1647        memset(info, 0, sizeof(struct SICC_info));
1648        init_waitqueue_head(&info->open_wait);
1649        init_waitqueue_head(&info->close_wait);
1650        init_waitqueue_head(&info->delta_msr_wait);
1651        info->flags = state->flags;
1652        info->state = state;
1653        info->port  = sicc_ports + line;
1654        tasklet_init(&info->tlet, siccuart_tasklet_action,
1655                 (unsigned long)info);
1656    }
1657    if (state->info) {
1658        kfree(info);
1659        return state->info;
1660    }
1661    state->info = info;
1662    return info;
1663}
1664
1665static int siccuart_open(struct tty_struct *tty, struct file *filp)
1666{
1667    struct SICC_info *info;
1668    int retval, line = tty->index;
1669
1670
1671    // is this a line that we've got?
1672    if (line >= SERIAL_SICC_NR) {
1673        return -ENODEV;
1674    }
1675
1676    info = siccuart_get(line);
1677    if (!info)
1678        return -ENOMEM;
1679
1680    tty->driver_data = info;
1681    info->tty = tty;
1682    info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
1683
1684    /*
1685     * Make sure we have the temporary buffer allocated
1686     */
1687    if (!tmp_buf) {
1688        unsigned long page = get_zeroed_page(GFP_KERNEL);
1689        if (tmp_buf)
1690            free_page(page);
1691        else if (!page) {
1692            return -ENOMEM;
1693        }
1694        tmp_buf = (u_char *)page;
1695    }
1696
1697    /*
1698     * If the port is in the middle of closing, bail out now.
1699     */
1700    if (tty_hung_up_p(filp) ||
1701        (info->flags & ASYNC_CLOSING)) {
1702        if (info->flags & ASYNC_CLOSING)
1703            interruptible_sleep_on(&info->close_wait);
1704        return -EAGAIN;
1705    }
1706
1707    /*
1708     * Start up the serial port
1709     */
1710    retval = siccuart_startup(info);
1711    if (retval) {
1712        return retval;
1713    }
1714
1715    retval = block_til_ready(tty, filp, info);
1716    if (retval) {
1717        return retval;
1718    }
1719
1720#ifdef CONFIG_SERIAL_SICC_CONSOLE
1721    if (siccuart_cons.cflag && siccuart_cons.index == line) {
1722        tty->termios->c_cflag = siccuart_cons.cflag;
1723        siccuart_cons.cflag = 0;
1724        siccuart_change_speed(info, NULL);
1725    }
1726#endif
1727    return 0;
1728}
1729
1730static struct tty_operations sicc_ops = {
1731        .open = siccuart_open,
1732        .close = siccuart_close,
1733        .write = siccuart_write,
1734        .put_char = siccuart_put_char,
1735        .flush_chars = siccuart_flush_chars,
1736        .write_room = siccuart_write_room,
1737        .chars_in_buffer = siccuart_chars_in_buffer,
1738        .flush_buffer  = siccuart_flush_buffer,
1739        .ioctl = siccuart_ioctl,
1740        .throttle = siccuart_throttle,
1741        .unthrottle = siccuart_unthrottle,
1742        .send_xchar = siccuart_send_xchar,
1743        .set_termios = siccuart_set_termios,
1744        .stop = siccuart_stop,
1745        .start = siccuart_start,
1746        .hangup = siccuart_hangup,
1747        .break_ctl = siccuart_break_ctl,
1748        .wait_until_sent = siccuart_wait_until_sent,
1749};
1750
1751int __init siccuart_init(void)
1752{
1753    int i;
1754    siccnormal_driver = alloc_tty_driver(SERIAL_SICC_NR);
1755    if (!siccnormal_driver)
1756        return -ENOMEM;
1757    printk("IBM Vesta SICC serial port driver V 0.1 by Yudong Yang and Yi Ge / IBM CRL .\n");
1758    siccnormal_driver->driver_name = "serial_sicc";
1759    siccnormal_driver->owner = THIS_MODULE;
1760    siccnormal_driver->name = SERIAL_SICC_NAME;
1761    siccnormal_driver->major = SERIAL_SICC_MAJOR;
1762    siccnormal_driver->minor_start = SERIAL_SICC_MINOR;
1763    siccnormal_driver->type = TTY_DRIVER_TYPE_SERIAL;
1764    siccnormal_driver->subtype = SERIAL_TYPE_NORMAL;
1765    siccnormal_driver->init_termios = tty_std_termios;
1766    siccnormal_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1767    siccnormal_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
1768    tty_set_operations(siccnormal_driver, &sicc_ops);
1769
1770    if (tty_register_driver(siccnormal_driver))
1771        panic("Couldn't register SICC serial driver\n");
1772
1773    for (i = 0; i < SERIAL_SICC_NR; i++) {
1774        struct SICC_state *state = sicc_state + i;
1775        state->line     = i;
1776        state->close_delay  = 5 * HZ / 10;
1777        state->closing_wait = 30 * HZ;
1778        spin_lock_init(&state->sicc_lock);
1779    }
1780
1781
1782    return 0;
1783}
1784
1785__initcall(siccuart_init);
1786
1787#ifdef CONFIG_SERIAL_SICC_CONSOLE
1788/************** console driver *****************/
1789
1790/*
1791 * This code is currently never used; console->read is never called.
1792 * Therefore, although we have an implementation, we don't use it.
1793 * FIXME: the "const char *s" should be fixed to "char *s" some day.
1794 * (when the definition in include/linux/console.h is also fixed)
1795 */
1796#ifdef used_and_not_const_char_pointer
1797static int siccuart_console_read(struct console *co, const char *s, u_int count)
1798{
1799    struct SICC_port *port = &sicc_ports[co->index];
1800    unsigned int status;
1801    char *w;
1802    int c;
1803
1804    pr_debug("siccuart_console_read() called\n");
1805
1806    c = 0;
1807    w = s;
1808    while (c < count) {
1809        if(readb(port->uart_base +  BL_SICC_LSR) & _LSR_RBR_FULL) {
1810            *w++ = readb(port->uart_base +  BL_SICC_RBR);
1811            c++;
1812        } else {
1813            // nothing more to get, return
1814            return c;
1815        }
1816    }
1817    // return the count
1818    return c;
1819}
1820#endif
1821
1822/*
1823 *  Print a string to the serial port trying not to disturb
1824 *  any possible real use of the port...
1825 *
1826 *  The console_lock must be held when we get here.
1827 */
1828static void siccuart_console_write(struct console *co, const char *s, u_int count)
1829{
1830    struct SICC_port *port = &sicc_ports[co->index];
1831    unsigned int old_cr;
1832    int i;
1833
1834    /*
1835     *  First save the CR then disable the interrupts
1836     */
1837    old_cr = readb(port->uart_base +  BL_SICC_TxCR);
1838    writeb(old_cr & ~_TxCR_DME_MASK, port->uart_base +  BL_SICC_TxCR);
1839
1840    /*
1841     *  Now, do each character
1842     */
1843    for (i = 0; i < count; i++) {
1844        while ((readb(port->uart_base +  BL_SICC_LSR)&_LSR_TX_ALL) != _LSR_TX_ALL);
1845        writeb(s[i], port->uart_base +  BL_SICC_TBR);
1846        if (s[i] == '\n') {
1847            while ((readb(port->uart_base +  BL_SICC_LSR)&_LSR_TX_ALL) != _LSR_TX_ALL);
1848            writeb('\r', port->uart_base +  BL_SICC_TBR);
1849        }
1850    }
1851
1852    /*
1853     *  Finally, wait for transmitter to become empty
1854     *  and restore the TCR
1855     */
1856    while ((readb(port->uart_base +  BL_SICC_LSR)&_LSR_TX_ALL) != _LSR_TX_ALL);
1857    writeb(old_cr, port->uart_base +  BL_SICC_TxCR);
1858}
1859
1860/*
1861 *  Receive character from the serial port
1862 */
1863static int siccuart_console_wait_key(struct console *co)
1864{
1865    struct SICC_port *port = &sicc_ports[co->index];
1866    int c;
1867
1868    while(!(readb(port->uart_base +  BL_SICC_LSR) & _LSR_RBR_FULL));
1869    c = readb(port->uart_base +  BL_SICC_RBR);
1870    return c;
1871}
1872
1873static struct tty_driver *siccuart_console_device(struct console *c, int *index)
1874{
1875        *index = c->index;
1876        return siccnormal_driver;
1877}
1878
1879static int __init siccuart_console_setup(struct console *co, char *options)
1880{
1881    struct SICC_port *port;
1882    int baud = 9600;
1883    int bits = 8;
1884    int parity = 'n';
1885    u_int cflag = CREAD | HUPCL | CLOCAL;
1886    u_int lcr_h, quot;
1887
1888
1889    if (co->index >= SERIAL_SICC_NR)
1890        co->index = 0;
1891
1892    port = &sicc_ports[co->index];
1893
1894    if (port->uart_base == 0)
1895        port->uart_base = (int)ioremap(port->uart_base_phys, PAGE_SIZE);
1896
1897    if (options) {
1898        char *s = options;
1899        baud = simple_strtoul(s, NULL, 10);
1900        while (*s >= '0' && *s <= '9')
1901            s++;
1902        if (*s) parity = *s++;
1903        if (*s) bits = *s - '0';
1904    }
1905
1906    /*
1907     *    Now construct a cflag setting.
1908     */
1909    switch (baud) {
1910    case 1200:  cflag |= B1200;         break;
1911    case 2400:  cflag |= B2400;         break;
1912    case 4800:  cflag |= B4800;         break;
1913    default:    cflag |= B9600;   baud = 9600;  break;
1914    case 19200: cflag |= B19200;        break;
1915    case 38400: cflag |= B38400;        break;
1916    case 57600: cflag |= B57600;        break;
1917    case 115200:    cflag |= B115200;       break;
1918    }
1919    switch (bits) {
1920    case 7:   cflag |= CS7; lcr_h = _LCR_PE_DISABLE | _LCR_DB_7_BITS | _LCR_SB_1_BIT;   break;
1921    default:  cflag |= CS8; lcr_h = _LCR_PE_DISABLE | _LCR_DB_8_BITS | _LCR_SB_1_BIT;   break;
1922    }
1923    switch (parity) {
1924    case 'o':
1925    case 'O': cflag |= PARODD; lcr_h |= _LCR_PTY_ODD;   break;
1926    case 'e':
1927    case 'E': cflag |= PARENB; lcr_h |= _LCR_PE_ENABLE |  _LCR_PTY_ODD; break;
1928    }
1929
1930    co->cflag = cflag;
1931
1932
1933       {
1934           // a copy of is inserted here ppc403SetBaud(com_port, (int)9600);
1935           unsigned long divisor, clockSource, temp;
1936           unsigned int rate = baud;
1937
1938          /* Ensure CICCR[7] is 0 to select Internal Baud Clock */
1939          powerpcMtcic_cr((unsigned long)(powerpcMfcic_cr() & 0xFEFFFFFF));
1940
1941          /* Determine Internal Baud Clock Frequency */
1942          /* powerpcMfclkgpcr() reads DCR 0x120 - the*/
1943          /* SCCR (Serial Clock Control Register) on Vesta */
1944          temp = powerpcMfclkgpcr();
1945
1946          if(temp & 0x00000080) {
1947              clockSource = 324000000;
1948          }
1949          else {
1950              clockSource = 216000000;
1951          }
1952          clockSource = clockSource/(unsigned long)((temp&0x00FC0000)>>18);
1953          divisor = clockSource/(16*rate) - 1;
1954          /* divisor has only 12 bits of resolution */
1955          if(divisor>0x00000FFF){
1956               divisor=0x00000FFF;
1957          }
1958
1959          quot = divisor;
1960       }
1961
1962    writeb((quot & 0x00000F00)>>8, port->uart_base + BL_SICC_BRDH );
1963    writeb( quot & 0x00000FF,      port->uart_base   + BL_SICC_BRDL );
1964
1965    /* Set CTL2 reg to use external clock (ExtClk) and enable FIFOs. */
1966    /* For now, do NOT use FIFOs since 403 UART did not have this    */
1967    /* capability and this driver was inherited from 403UART.        */
1968    writeb(_CTL2_EXTERN, port->uart_base  + BL_SICC_CTL2);
1969
1970    writeb(lcr_h, port->uart_base + BL_SICC_LCR);
1971    writeb(_RCR_ER_ENABLE | _RCR_PME_HARD, port->uart_base + BL_SICC_RCR);
1972    writeb( _TxCR_ET_ENABLE , port->uart_base + BL_SICC_TxCR);
1973
1974    // writeb(, info->port->uart_base + BL_SICC_RCR );
1975    /*
1976     * Transmitter Command Register: Transmitter enabled & DMA + TBR interrupt
1977     * + Transmitter Empty interrupt + Transmitter error interrupt disabled &
1978     * Stop mode when CTS active enabled & Transmit Break + Pattern Generation
1979     * mode disabled.
1980     */
1981
1982    writeb( 0x00, port->uart_base + BL_SICC_IrCR );  // disable IrDA
1983
1984    readb(port->uart_base + BL_SICC_RBR);
1985
1986    writeb(0xf8, port->uart_base + BL_SICC_LSR);   /* reset bits 0-4 of LSR */
1987
1988    /* we will enable the port as we need it */
1989
1990    return 0;
1991}
1992
1993static struct console siccuart_cons =
1994{
1995    .name =     SERIAL_SICC_NAME,
1996    .write =    siccuart_console_write,
1997#ifdef used_and_not_const_char_pointer
1998    .read =     siccuart_console_read,
1999#endif
2000    .device =   siccuart_console_device,
2001    .wait_key = siccuart_console_wait_key,
2002    .setup =    siccuart_console_setup,
2003    .flags =    CON_PRINTBUFFER,
2004    .index =    -1,
2005};
2006
2007void __init sicc_console_init(void)
2008{
2009    register_console(&siccuart_cons);
2010}
2011
2012#endif /* CONFIG_SERIAL_SICC_CONSOLE */
2013
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.