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