/*
 * (C) Copyright 2001
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
 * (C) Copyright 2001
 * James Dougherty (jfd@cs.stanford.edu)
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#ifndef __NS16552_H
#define __NS16552_H

/*
 * NS16552D Serial Port
 */

typedef struct ns16550_uart_ {

/*
 * The register is selected by
 * 1. If the DLAB bit is set to 1, then the Divisor_Latch_LSB will be active.
 * 2. If the DLAB bit is reset, then 
 *    a. A read is performed from the Rx_Buffer_Register.
 *    b. A write to is performed on the Tx_Holding_Register.
 */
    union 
    {
        volatile unsigned char Rx_Buffer;  /* Rx buffer ready reg RD only */
        volatile unsigned char Tx_Holding; /* Tx holding register WR only */
        volatile unsigned char DLL;        /* Divisor latch LS Byte */
    } RBS_THR_DLAB1;    
#define RxBuf       RBS_THR_DLAB1.Rx_Buffer
#define TxBuf       RBS_THR_DLAB1.Tx_Holding
#define DLL         RBS_THR_DLAB1.DLL
/*
 * The register is selected by
 *
 * If the DLAB bit is set to 1, then the Divisor_Latch_LSB will be active, else
 * Interrupt enable register is active. 
 */ 
    union
    {
        volatile unsigned char DLM; /* Divisor latch MS Byte */
        volatile unsigned char IER; /* Intr. enable register */
    } IER_DLAB2;
#define DLM    IER_DLAB2.DLM
#define IER    IER_DLAB2.IER

/*
 * If the DLAB bit is 1, then Alternate function register is selected.
 * If the DLAB bit is 0, then
 * 1. A read is always performed from the Interrupt Indentification register.
 * 2. A write is always performed on the FIFO control register.
 */
  union{
    volatile unsigned char IIR;  /* Intr. identification RD */
    volatile unsigned char FCR;  /* FIFO control WR only */
    volatile unsigned char AFR;  /* When DLAB is 1 */
  } IIR_FCR_AFR;
#define IIR       IIR_FCR_AFR.IIR
#define FCR       IIR_FCR_AFR.FCR
#define AFR       IIR_FCR_AFR.AFR
  volatile unsigned char LCR;    /* Line Control register */
  volatile unsigned char MCR;    /* Modem Control register */
  volatile unsigned char LSR;    /* Line Status register */
  volatile unsigned char MSR;    /* Modem Status register */
  volatile unsigned char SR;     /* Scratch pad register */
} ns16550_uart;



/* NSC 16550 Interrupt Enable register definitions */
#define IER_ENABLE_RX_DATA    0x01    /* Enable Recevied Data available intr*/
#define IER_ENABLE_THRE       0x02    /* Enable Tx holding reg empty intr */
#define IER_ENABLE_RX_LSR     0x04    /* Enable receiver Line status intr */
#define IER_ENABLE_MODEM_STAT 0x08    /* Enable receiver Modem status intr*/

/* NSC 16550 Interrupt Identification register bit settings */
#define IIR_MSTAT              0x00    /* Modem changed status indication */
#define IIR_NOPENDING_INTR     0x01    /* Interrupt not pending, indication */
#define IIR_THRE               0x02    /* Tx holding reg empty indication */
#define IIR_CHAR_TIMEOUT       0x0c    /* Character timeout indication */
#define IIR_RX_DATA_AVAIL      0x04    /* Received data available indication */
#define IIR_RLS                0x06    /* Receiver line status (either OE, PE, 
					  FE or BI received) */

/* NSC 16550 FIFO Control register bit settings */
#define FCR_ENABLE      0x01    /* Rx and Tx FIFO's enabler */
#define FCR_RX_CLR      0x02    /* Clear the Rx FIFO and set offset to 0 */
#define FCR_TX_CLR      0x04    /* Clear the Rx FIFO and set offset to 0 */
#define FCR_DMA_MODE    0x08    /* Will enable DMA transfers for Rx and Tx */

/*
 * Receiver FIFO trigger level, is the number characters needed to be in the 
 * FIFO, before an interrupt is generated. Bits ( 7 & 8 ) of the above
 * register.
 */
#define TRIGGER_ON_1    0x00    /* Trigger after receiving 1 byte */
#define TRIGGER_ON_4    0x01    /* Trigger after receiving 4 byte */
#define TRIGGER_ON_8    0x02    /* Trigger after receiving 8 byte */
#define TRIGGER_ON_14   0x03    /* Trigger after receiving 14 byte */
#define FIFO_COUNT        16        /* 16 byte deep FIFO */

/* NSC 16550 Line control register bit settings */
/*
 * Bits 
 * 0   1  - Character length
 * 2      - Stops bit length (used along with the bits 0 & 1)
 * 3      - Parity enable bit
 * 4      - Even parity select bit (only active when parity is enabled. 
 *               = 0, Odd parity
 *               = 1, Even Parity
 * 5      - Sticky bit parity.
 * 6      - Break control bit, causes break condition to be transmitted 
 * 7      - Divisor latch access bit for setting the baud rate divisor
 */
#define LCR_5BITS    0x00    /* Character length is 5 bits */
#define LCR_6BITS    0x01    /* Character length is 6 bits */
#define LCR_7BITS    0x02    /* Character length is 7 bits */
#define LCR_8BITS    0x03    /* Character length is 8 bits */
#define LCR_1_SB     0x00    /* Bit 2 should be 0, for 1 stop bit */
#define LCR_15_SB    0x04    /* Bit 2 should be 1 and LCR_5BITS 
                                must be selected for 1.5 bits */
#define LCR_2_SB     0x04    /* When character length is 6,7 or 8 */
#define LCR_PARITY_ENABLE    0x08    /* Enable parity on Rx and Tx */
#define LCR_EVEN_PARITY      0x10    /* When parity enabled */
#define LCR_STICKY_PARITY    0x20    /* Sticky parity enable */
#define LCR_BREAK_CTRL       0x40    /* Break control bit */
#define LCR_DLAB             0x80    /* Divisor latch access bit */

/* NSC 16550 Modem Control register bit definitions */
#define MCR_DTR     0x01    /* Data terminal ready */
#define MCR_RTS     0x02    /* Request to send */
#define MCR_OUT1    0x04    /* Out1 */
#define MCR_OUT2    0x08    /* Out1 */
#define MCR_LOOP    0x10    /* Set loop mode */

/* NSC 16550 Line status register bit definitions */
#define LSR_DATAREADY      0x01    /* Data ready */
#define LSR_OVERRUN_ERR    0x02    /* Overrun Error */
#define LSR_PARITY_ERR     0x04    /* Parity Error */
#define LSR_FRAME_ERR      0x08    /* Framing Error */
#define LSR_BREAK_INTR     0x10    /* Break Interrupt */
#define LSR_THRE           0x20    /* Transmit holding register empty */
#define LSR_TEMT           0x40    /* Transmiter empty */
#define LSR_RX_FIFO_ERR    0x80    /* Error on Receiver FIFO */

/* NSC 16550 Modem status register bit definitions */
#define MSR_DELTA_CTS    0x01    /* Delta CTS */
#define MSR_DELTA_DSR    0x02    /* Delta DSR */
#define MSR_TERI         0x04    /* Trailing Edge ring indicator */
#define MSR_DELTA_DCD    0x08    /* Delta DCD */
#define MSR_CTS     0x10    /* CTS */
#define MSR_DSR     0x20    /* DSR */
#define MSR_RI      0x40    /* RI */
#define MSR_DCD     0x80    /* DCD */

#define HIGH_WATER_MARK 1664  /* High water mark, at which the h/w flow control
                                 will take affect */

/* Baud Rate settings */
/* 
 * This particular chip can set the baud rate by writing to the Divisor latch.
 * This divisor latch is a 16 bit latch and can be written only when DLAB bit
 * is set. The baud rate depends on the input clock frequency. 
 * 
 * To calculate the number to be loaded into the latch use the following
 * formula
 *
 * Divisor # = (Clock Freq) / (16 * Speed in bauds).
 * Eg. On a 18.432 MHz to get a baud rate of 115.2kbps ...
 * Divisor # = (18432000)/(115200*16)
 * Divisor # = 10
 * 
 * NOTE: If the clock frequency is changed new values for these variables have
 *       to be calculated.
 */

#define B50     50
#define B75     75
#define B110    110
#define B150    150
#define B300    300
#define B600    600
#define B1200   1200
#define B1800    1800    
#define B2000    2000
#define B2400    2400
#define B3600    3600
#define B4800    4800
#define B7200    7200
#define B9600    9600
#define B14400    14400
#define B19200    19200
#define B28800    28800
#define B38400    38400
#define B56000    56000
#define B57600    57600
#define B115200    115200
#define B128000    128000
/*
 * Possible only with a 24 MHz crystal clock input.
 */
#define B250k    250000
#define B300k    300000
#define B375k    375000
#define B500k    500000
#define B750k    750000
#define B1500k   1500000

typedef struct ns16550_baud_rate_table_ {
    int baudrate;
    unsigned short value;
} ns16550_baud_rate_table;


int ns16550_check_break (void);
int ns16550_check_char (void);
unsigned char ns16550_putc (unsigned char ch);
int ns16550_getc (void);
int ns16550_setspeed (int speed);
void ns16550_init (int baud);
int ns16550_tstc(void);


#endif /* __NS16552_H */
