diff options
Diffstat (limited to 'drivers/staging/sb105x/sb_ser_core.h')
-rw-r--r-- | drivers/staging/sb105x/sb_ser_core.h | 368 |
1 files changed, 368 insertions, 0 deletions
diff --git a/drivers/staging/sb105x/sb_ser_core.h b/drivers/staging/sb105x/sb_ser_core.h new file mode 100644 index 000000000000..c8fb99173299 --- /dev/null +++ b/drivers/staging/sb105x/sb_ser_core.h @@ -0,0 +1,368 @@ +#include <linux/wait.h> + +#define UART_CONFIG_TYPE (1 << 0) +#define UART_CONFIG_IRQ (1 << 1) +#define UPIO_PORT (0) +#define UPIO_HUB6 (1) +#define UPIO_MEM (2) +#define UPIO_MEM32 (3) +#define UPIO_AU (4) /* Au1x00 type IO */ +#define UPIO_TSI (5) /* Tsi108/109 type IO */ +#define UPF_FOURPORT (1 << 1) +#define UPF_SAK (1 << 2) +#define UPF_SPD_MASK (0x1030) +#define UPF_SPD_HI (0x0010) +#define UPF_SPD_VHI (0x0020) +#define UPF_SPD_CUST (0x0030) +#define UPF_SPD_SHI (0x1000) +#define UPF_SPD_WARP (0x1010) +#define UPF_SKIP_TEST (1 << 6) +#define UPF_AUTO_IRQ (1 << 7) +#define UPF_HARDPPS_CD (1 << 11) +#define UPF_LOW_LATENCY (1 << 13) +#define UPF_BUGGY_UART (1 << 14) +#define UPF_MAGIC_MULTIPLIER (1 << 16) +#define UPF_CONS_FLOW (1 << 23) +#define UPF_SHARE_IRQ (1 << 24) +#define UPF_BOOT_AUTOCONF (1 << 28) +#define UPF_DEAD (1 << 30) +#define UPF_IOREMAP (1 << 31) +#define UPF_CHANGE_MASK (0x17fff) +#define UPF_USR_MASK (UPF_SPD_MASK|UPF_LOW_LATENCY) +#define USF_CLOSING_WAIT_INF (0) +#define USF_CLOSING_WAIT_NONE (~0U) + +#define UART_XMIT_SIZE PAGE_SIZE + +#define UIF_CHECK_CD (1 << 25) +#define UIF_CTS_FLOW (1 << 26) +#define UIF_NORMAL_ACTIVE (1 << 29) +#define UIF_INITIALIZED (1 << 31) +#define UIF_SUSPENDED (1 << 30) + +#define WAKEUP_CHARS 256 + +#define uart_circ_empty(circ) ((circ)->head == (circ)->tail) +#define uart_circ_clear(circ) ((circ)->head = (circ)->tail = 0) + +#define uart_circ_chars_pending(circ) \ + (CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE)) + +#define uart_circ_chars_free(circ) \ + (CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE)) + +#define uart_tx_stopped(port) \ + ((port)->info->tty->stopped || (port)->info->tty->hw_stopped) + +#define UART_ENABLE_MS(port,cflag) ((port)->flags & UPF_HARDPPS_CD || \ + (cflag) & CRTSCTS || \ + !((cflag) & CLOCAL)) + + +struct sb_uart_port; +struct sb_uart_info; +struct serial_struct; +struct device; + +struct sb_uart_ops { + unsigned int (*tx_empty)(struct sb_uart_port *); + void (*set_mctrl)(struct sb_uart_port *, unsigned int mctrl); + unsigned int (*get_mctrl)(struct sb_uart_port *); + void (*stop_tx)(struct sb_uart_port *); + void (*start_tx)(struct sb_uart_port *); + void (*send_xchar)(struct sb_uart_port *, char ch); + void (*stop_rx)(struct sb_uart_port *); + void (*enable_ms)(struct sb_uart_port *); + void (*break_ctl)(struct sb_uart_port *, int ctl); + int (*startup)(struct sb_uart_port *); + void (*shutdown)(struct sb_uart_port *); + void (*set_termios)(struct sb_uart_port *, struct MP_TERMIOS *new, + struct MP_TERMIOS *old); + void (*pm)(struct sb_uart_port *, unsigned int state, + unsigned int oldstate); + int (*set_wake)(struct sb_uart_port *, unsigned int state); + + const char *(*type)(struct sb_uart_port *); + + void (*release_port)(struct sb_uart_port *); + + int (*request_port)(struct sb_uart_port *); + void (*config_port)(struct sb_uart_port *, int); + int (*verify_port)(struct sb_uart_port *, struct serial_struct *); + int (*ioctl)(struct sb_uart_port *, unsigned int, unsigned long); +}; + + +struct sb_uart_icount { + __u32 cts; + __u32 dsr; + __u32 rng; + __u32 dcd; + __u32 rx; + __u32 tx; + __u32 frame; + __u32 overrun; + __u32 parity; + __u32 brk; + __u32 buf_overrun; +}; +typedef unsigned int upf_t; + +struct sb_uart_port { + spinlock_t lock; /* port lock */ + unsigned int iobase; /* in/out[bwl] */ + unsigned char __iomem *membase; /* read/write[bwl] */ + unsigned int irq; /* irq number */ + unsigned int uartclk; /* base uart clock */ + unsigned int fifosize; /* tx fifo size */ + unsigned char x_char; /* xon/xoff char */ + unsigned char regshift; /* reg offset shift */ + unsigned char iotype; /* io access style */ + unsigned char unused1; + + + unsigned int read_status_mask; /* driver specific */ + unsigned int ignore_status_mask; /* driver specific */ + struct sb_uart_info *info; /* pointer to parent info */ + struct sb_uart_icount icount; /* statistics */ + + struct console *cons; /* struct console, if any */ +#ifdef CONFIG_SERIAL_CORE_CONSOLE + unsigned long sysrq; /* sysrq timeout */ +#endif + + upf_t flags; + + unsigned int mctrl; /* current modem ctrl settings */ + unsigned int timeout; /* character-based timeout */ + unsigned int type; /* port type */ + const struct sb_uart_ops *ops; + unsigned int custom_divisor; + unsigned int line; /* port index */ + unsigned long mapbase; /* for ioremap */ + struct device *dev; /* parent device */ + unsigned char hub6; /* this should be in the 8250 driver */ + unsigned char unused[3]; +}; + +#define mdmode unused[2] +#define MDMODE_ADDR 0x1 +#define MDMODE_ENABLE 0x2 +#define MDMODE_AUTO 0x4 +#define MDMODE_ADDRSEND 0x8 + +struct sb_uart_state { + unsigned int close_delay; /* msec */ + unsigned int closing_wait; /* msec */ + + + int count; + int pm_state; + struct sb_uart_info *info; + struct sb_uart_port *port; + + struct mutex mutex; +}; + +typedef unsigned int uif_t; + +struct sb_uart_info { + struct tty_struct *tty; + struct circ_buf xmit; + uif_t flags; + + int blocked_open; + + struct tasklet_struct tlet; + + wait_queue_head_t open_wait; + wait_queue_head_t delta_msr_wait; +}; + + +struct module; +struct tty_driver; + +struct uart_driver { + struct module *owner; + const char *driver_name; + const char *dev_name; + int major; + int minor; + int nr; + struct console *cons; + + struct sb_uart_state *state; + struct tty_driver *tty_driver; +}; + +void sb_uart_write_wakeup(struct sb_uart_port *port) +{ + struct sb_uart_info *info = port->info; + tasklet_schedule(&info->tlet); +} + +void sb_uart_update_timeout(struct sb_uart_port *port, unsigned int cflag, + unsigned int baud) +{ + unsigned int bits; + + switch (cflag & CSIZE) + { + case CS5: + bits = 7; + break; + + case CS6: + bits = 8; + break; + + case CS7: + bits = 9; + break; + + default: + bits = 10; + break; + } + + if (cflag & CSTOPB) + { + bits++; + } + + if (cflag & PARENB) + { + bits++; + } + + bits = bits * port->fifosize; + + port->timeout = (HZ * bits) / baud + HZ/50; +} +unsigned int sb_uart_get_baud_rate(struct sb_uart_port *port, struct MP_TERMIOS *termios, + struct MP_TERMIOS *old, unsigned int min, + unsigned int max) +{ + unsigned int try, baud, altbaud = 38400; + upf_t flags = port->flags & UPF_SPD_MASK; + + if (flags == UPF_SPD_HI) + altbaud = 57600; + if (flags == UPF_SPD_VHI) + altbaud = 115200; + if (flags == UPF_SPD_SHI) + altbaud = 230400; + if (flags == UPF_SPD_WARP) + altbaud = 460800; + + for (try = 0; try < 2; try++) { + + switch (termios->c_cflag & (CBAUD | CBAUDEX)) + { + case B921600 : baud = 921600; break; + case B460800 : baud = 460800; break; + case B230400 : baud = 230400; break; + case B115200 : baud = 115200; break; + case B57600 : baud = 57600; break; + case B38400 : baud = 38400; break; + case B19200 : baud = 19200; break; + case B9600 : baud = 9600; break; + case B4800 : baud = 4800; break; + case B2400 : baud = 2400; break; + case B1800 : baud = 1800; break; + case B1200 : baud = 1200; break; + case B600 : baud = 600; break; + case B300 : baud = 300; break; + case B200 : baud = 200; break; + case B150 : baud = 150; break; + case B134 : baud = 134; break; + case B110 : baud = 110; break; + case B75 : baud = 75; break; + case B50 : baud = 50; break; + default : baud = 9600; break; + } + + if (baud == 38400) + baud = altbaud; + + if (baud == 0) + baud = 9600; + + if (baud >= min && baud <= max) + return baud; + + termios->c_cflag &= ~CBAUD; + if (old) { + termios->c_cflag |= old->c_cflag & CBAUD; + old = NULL; + continue; + } + + termios->c_cflag |= B9600; + } + + return 0; +} +unsigned int sb_uart_get_divisor(struct sb_uart_port *port, unsigned int baud) +{ + unsigned int quot; + + if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) + quot = port->custom_divisor; + else + quot = (port->uartclk + (8 * baud)) / (16 * baud); + + return quot; +} + + + +static inline int sb_uart_handle_break(struct sb_uart_port *port) +{ + struct sb_uart_info *info = port->info; + + if (port->flags & UPF_SAK) + do_SAK(info->tty); + return 0; +} + +static inline void sb_uart_handle_dcd_change(struct sb_uart_port *port, unsigned int status) +{ + struct sb_uart_info *info = port->info; + + port->icount.dcd++; + + if (info->flags & UIF_CHECK_CD) { + if (status) + wake_up_interruptible(&info->open_wait); + else if (info->tty) + tty_hangup(info->tty); + } +} + +static inline void sb_uart_handle_cts_change(struct sb_uart_port *port, unsigned int status) +{ + struct sb_uart_info *info = port->info; + struct tty_struct *tty = info->tty; + + port->icount.cts++; + + if (info->flags & UIF_CTS_FLOW) { + if (tty->hw_stopped) { + if (status) { + tty->hw_stopped = 0; + port->ops->start_tx(port); + sb_uart_write_wakeup(port); + } + } else { + if (!status) { + tty->hw_stopped = 1; + port->ops->stop_tx(port); + } + } + } +} + + + |