Blame view
drivers/input/ps2ser.c
2.94 KB
1c43771ba
|
1 2 |
/*********************************************************************** * |
200779e3e
|
3 |
* (C) Copyright 2004-2009 |
1c43771ba
|
4 5 |
* DENX Software Engineering * Wolfgang Denk, wd@denx.de |
1c43771ba
|
6 7 8 9 10 11 12 13 14 15 |
* * Simple 16550A serial driver * * Originally from linux source (drivers/char/ps2ser.c) * * Used by the PS/2 multiplexer driver (ps2mult.c) * ***********************************************************************/ #include <common.h> |
1c43771ba
|
16 17 18 |
#include <asm/io.h> #include <asm/atomic.h> #include <ps2mult.h> |
200779e3e
|
19 20 21 |
/* This is needed for ns16550.h */ #ifndef CONFIG_SYS_NS16550_REG_SIZE #define CONFIG_SYS_NS16550_REG_SIZE 1 |
bc8bb6d45
|
22 |
#endif |
200779e3e
|
23 |
#include <ns16550.h> |
1c43771ba
|
24 |
|
d87080b72
|
25 |
DECLARE_GLOBAL_DATA_PTR; |
1c43771ba
|
26 27 28 |
/* #define DEBUG */ #define PS2SER_BAUD 57600 |
bc8bb6d45
|
29 |
#if CONFIG_PS2SERIAL == 1 |
6d0f6bcf3
|
30 |
#define COM_BASE (CONFIG_SYS_CCSRBAR+0x4500) |
bc8bb6d45
|
31 |
#elif CONFIG_PS2SERIAL == 2 |
6d0f6bcf3
|
32 |
#define COM_BASE (CONFIG_SYS_CCSRBAR+0x4600) |
bc8bb6d45
|
33 34 35 |
#else #error CONFIG_PS2SERIAL must be in 1 ... 2 #endif |
1c43771ba
|
36 37 38 39 |
static int ps2ser_getc_hw(void); static void ps2ser_interrupt(void *dev_id); extern struct serial_state rs_table[]; /* in serial.c */ |
1c43771ba
|
40 41 42 43 44 |
static u_char ps2buf[PS2BUF_SIZE]; static atomic_t ps2buf_cnt; static int ps2buf_in_idx; static int ps2buf_out_idx; |
bc8bb6d45
|
45 46 47 48 49 |
int ps2ser_init(void) { NS16550_t com_port = (NS16550_t)COM_BASE; com_port->ier = 0x00; |
200779e3e
|
50 |
com_port->lcr = UART_LCR_BKSE | UART_LCR_8N1; |
6d0f6bcf3
|
51 52 |
com_port->dll = (CONFIG_SYS_NS16550_CLK / 16 / PS2SER_BAUD) & 0xff; com_port->dlm = ((CONFIG_SYS_NS16550_CLK / 16 / PS2SER_BAUD) >> 8) & 0xff; |
200779e3e
|
53 54 55 |
com_port->lcr = UART_LCR_8N1; com_port->mcr = (UART_MCR_DTR | UART_MCR_RTS); com_port->fcr = (UART_FCR_FIFO_EN | UART_FCR_RXSR | UART_FCR_TXSR); |
bc8bb6d45
|
56 57 58 |
return (0); } |
1c43771ba
|
59 60 |
void ps2ser_putc(int chr) { |
bc8bb6d45
|
61 |
NS16550_t com_port = (NS16550_t)COM_BASE; |
77efe35fe
|
62 63 |
debug(">>>> 0x%02x ", chr); |
1c43771ba
|
64 |
|
200779e3e
|
65 |
while ((com_port->lsr & UART_LSR_THRE) == 0); |
bc8bb6d45
|
66 |
com_port->thr = chr; |
1c43771ba
|
67 68 69 70 |
} static int ps2ser_getc_hw(void) { |
bc8bb6d45
|
71 |
NS16550_t com_port = (NS16550_t)COM_BASE; |
1c43771ba
|
72 |
int res = -1; |
200779e3e
|
73 |
if (com_port->lsr & UART_LSR_DR) { |
bc8bb6d45
|
74 75 |
res = com_port->rbr; } |
1c43771ba
|
76 77 78 79 80 81 82 83 |
return res; } int ps2ser_getc(void) { volatile int chr; int flags; |
77efe35fe
|
84 |
debug("<< "); |
1c43771ba
|
85 86 87 88 89 90 91 92 93 94 95 96 97 |
flags = disable_interrupts(); do { if (atomic_read(&ps2buf_cnt) != 0) { chr = ps2buf[ps2buf_out_idx++]; ps2buf_out_idx &= (PS2BUF_SIZE - 1); atomic_dec(&ps2buf_cnt); } else { chr = ps2ser_getc_hw(); } } while (chr < 0); |
77efe35fe
|
98 99 |
if (flags) enable_interrupts(); |
1c43771ba
|
100 |
|
77efe35fe
|
101 102 |
debug("0x%02x ", chr); |
1c43771ba
|
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
return chr; } int ps2ser_check(void) { int flags; flags = disable_interrupts(); ps2ser_interrupt(NULL); if (flags) enable_interrupts(); return atomic_read(&ps2buf_cnt); } static void ps2ser_interrupt(void *dev_id) { |
bc8bb6d45
|
120 |
NS16550_t com_port = (NS16550_t)COM_BASE; |
1c43771ba
|
121 |
int chr; |
7e6bf358d
|
122 |
int status; |
1c43771ba
|
123 124 125 |
do { chr = ps2ser_getc_hw(); |
77efe35fe
|
126 |
status = com_port->lsr; |
1c43771ba
|
127 128 129 130 131 132 133 134 135 136 |
if (chr < 0) continue; if (atomic_read(&ps2buf_cnt) < PS2BUF_SIZE) { ps2buf[ps2buf_in_idx++] = chr; ps2buf_in_idx &= (PS2BUF_SIZE - 1); atomic_inc(&ps2buf_cnt); } else { printf ("ps2ser.c: buffer overflow "); } |
77efe35fe
|
137 |
} while (status & UART_LSR_DR); |
1c43771ba
|
138 139 140 141 |
if (atomic_read(&ps2buf_cnt)) { ps2mult_callback(atomic_read(&ps2buf_cnt)); } } |