xref: /rk3399_rockchip-uboot/drivers/input/ps2ser.c (revision 16b195c82a18cbfd164800f17a1ef9db2e48331a)
1*16b195c8SJean-Christophe PLAGNIOL-VILLARD /***********************************************************************
2*16b195c8SJean-Christophe PLAGNIOL-VILLARD  *
3*16b195c8SJean-Christophe PLAGNIOL-VILLARD  * (C) Copyright 2004
4*16b195c8SJean-Christophe PLAGNIOL-VILLARD  * DENX Software Engineering
5*16b195c8SJean-Christophe PLAGNIOL-VILLARD  * Wolfgang Denk, wd@denx.de
6*16b195c8SJean-Christophe PLAGNIOL-VILLARD  * All rights reserved.
7*16b195c8SJean-Christophe PLAGNIOL-VILLARD  *
8*16b195c8SJean-Christophe PLAGNIOL-VILLARD  * Simple 16550A serial driver
9*16b195c8SJean-Christophe PLAGNIOL-VILLARD  *
10*16b195c8SJean-Christophe PLAGNIOL-VILLARD  * Originally from linux source (drivers/char/ps2ser.c)
11*16b195c8SJean-Christophe PLAGNIOL-VILLARD  *
12*16b195c8SJean-Christophe PLAGNIOL-VILLARD  * Used by the PS/2 multiplexer driver (ps2mult.c)
13*16b195c8SJean-Christophe PLAGNIOL-VILLARD  *
14*16b195c8SJean-Christophe PLAGNIOL-VILLARD  ***********************************************************************/
15*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
16*16b195c8SJean-Christophe PLAGNIOL-VILLARD #include <common.h>
17*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
18*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_PS2SERIAL
19*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
20*16b195c8SJean-Christophe PLAGNIOL-VILLARD #include <asm/io.h>
21*16b195c8SJean-Christophe PLAGNIOL-VILLARD #include <asm/atomic.h>
22*16b195c8SJean-Christophe PLAGNIOL-VILLARD #include <ps2mult.h>
23*16b195c8SJean-Christophe PLAGNIOL-VILLARD #if defined(CFG_NS16550) || defined(CONFIG_MPC85xx)
24*16b195c8SJean-Christophe PLAGNIOL-VILLARD #include <ns16550.h>
25*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
26*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
27*16b195c8SJean-Christophe PLAGNIOL-VILLARD DECLARE_GLOBAL_DATA_PTR;
28*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
29*16b195c8SJean-Christophe PLAGNIOL-VILLARD /* #define	DEBUG */
30*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
31*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define PS2SER_BAUD	57600
32*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
33*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx
34*16b195c8SJean-Christophe PLAGNIOL-VILLARD #if CONFIG_PS2SERIAL == 1
35*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC1
36*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 2
37*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC2
38*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 3
39*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC3
40*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MGT5100)
41*16b195c8SJean-Christophe PLAGNIOL-VILLARD #error CONFIG_PS2SERIAL must be in 1, 2 or 3
42*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 4
43*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC4
44*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 5
45*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC5
46*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 6
47*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define PSC_BASE MPC5XXX_PSC6
48*16b195c8SJean-Christophe PLAGNIOL-VILLARD #else
49*16b195c8SJean-Christophe PLAGNIOL-VILLARD #error CONFIG_PS2SERIAL must be in 1 ... 6
50*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
51*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
52*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555)
53*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
54*16b195c8SJean-Christophe PLAGNIOL-VILLARD #if CONFIG_PS2SERIAL == 1
55*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define COM_BASE (CFG_CCSRBAR+0x4500)
56*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif CONFIG_PS2SERIAL == 2
57*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define COM_BASE (CFG_CCSRBAR+0x4600)
58*16b195c8SJean-Christophe PLAGNIOL-VILLARD #else
59*16b195c8SJean-Christophe PLAGNIOL-VILLARD #error CONFIG_PS2SERIAL must be in 1 ... 2
60*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
61*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
62*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif /* CONFIG_MPC5xxx / CONFIG_MPC8540 / other */
63*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
64*16b195c8SJean-Christophe PLAGNIOL-VILLARD static int	ps2ser_getc_hw(void);
65*16b195c8SJean-Christophe PLAGNIOL-VILLARD static void	ps2ser_interrupt(void *dev_id);
66*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
67*16b195c8SJean-Christophe PLAGNIOL-VILLARD extern struct	serial_state rs_table[]; /* in serial.c */
68*16b195c8SJean-Christophe PLAGNIOL-VILLARD #if !defined(CONFIG_MPC5xxx) && !defined(CONFIG_MPC8540) && !defined(CONFIG_MPC8541) && !defined(CONFIG_MPC8555)
69*16b195c8SJean-Christophe PLAGNIOL-VILLARD static struct	serial_state *state;
70*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
71*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
72*16b195c8SJean-Christophe PLAGNIOL-VILLARD static u_char	ps2buf[PS2BUF_SIZE];
73*16b195c8SJean-Christophe PLAGNIOL-VILLARD static atomic_t	ps2buf_cnt;
74*16b195c8SJean-Christophe PLAGNIOL-VILLARD static int	ps2buf_in_idx;
75*16b195c8SJean-Christophe PLAGNIOL-VILLARD static int	ps2buf_out_idx;
76*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
77*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx
78*16b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2ser_init(void)
79*16b195c8SJean-Christophe PLAGNIOL-VILLARD {
80*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
81*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	unsigned long baseclk;
82*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	int div;
83*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
84*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	/* reset PSC */
85*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	psc->command = PSC_SEL_MODE_REG_1;
86*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
87*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	/* select clock sources */
88*16b195c8SJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_MGT5100)
89*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	psc->psc_clock_select = 0xdd00;
90*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	baseclk = (CFG_MPC5XXX_CLKIN + 16) / 32;
91*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC5200)
92*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	psc->psc_clock_select = 0;
93*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	baseclk = (gd->ipb_clk + 16) / 32;
94*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
95*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
96*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	/* switch to UART mode */
97*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	psc->sicr = 0;
98*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
99*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	/* configure parity, bit length and so on */
100*16b195c8SJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_MGT5100)
101*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	psc->mode = PSC_MODE_ERR | PSC_MODE_8_BITS | PSC_MODE_PARNONE;
102*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC5200)
103*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	psc->mode = PSC_MODE_8_BITS | PSC_MODE_PARNONE;
104*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
105*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	psc->mode = PSC_MODE_ONE_STOP;
106*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
107*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	/* set up UART divisor */
108*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	div = (baseclk + (PS2SER_BAUD/2)) / PS2SER_BAUD;
109*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	psc->ctur = (div >> 8) & 0xff;
110*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	psc->ctlr = div & 0xff;
111*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
112*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	/* disable all interrupts */
113*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	psc->psc_imr = 0;
114*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
115*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	/* reset and enable Rx/Tx */
116*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	psc->command = PSC_RST_RX;
117*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	psc->command = PSC_RST_TX;
118*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	psc->command = PSC_RX_ENABLE | PSC_TX_ENABLE;
119*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
120*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	return (0);
121*16b195c8SJean-Christophe PLAGNIOL-VILLARD }
122*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
123*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555)
124*16b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2ser_init(void)
125*16b195c8SJean-Christophe PLAGNIOL-VILLARD {
126*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	NS16550_t com_port = (NS16550_t)COM_BASE;
127*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
128*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	com_port->ier = 0x00;
129*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	com_port->lcr = LCR_BKSE | LCR_8N1;
130*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	com_port->dll = (CFG_NS16550_CLK / 16 / PS2SER_BAUD) & 0xff;
131*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	com_port->dlm = ((CFG_NS16550_CLK / 16 / PS2SER_BAUD) >> 8) & 0xff;
132*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	com_port->lcr = LCR_8N1;
133*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	com_port->mcr = (MCR_DTR | MCR_RTS);
134*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	com_port->fcr = (FCR_FIFO_EN | FCR_RXSR | FCR_TXSR);
135*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
136*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	return (0);
137*16b195c8SJean-Christophe PLAGNIOL-VILLARD }
138*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
139*16b195c8SJean-Christophe PLAGNIOL-VILLARD #else /* !CONFIG_MPC5xxx && !CONFIG_MPC8540 / other */
140*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
141*16b195c8SJean-Christophe PLAGNIOL-VILLARD static inline unsigned int ps2ser_in(int offset)
142*16b195c8SJean-Christophe PLAGNIOL-VILLARD {
143*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	return readb((unsigned long) state->iomem_base + offset);
144*16b195c8SJean-Christophe PLAGNIOL-VILLARD }
145*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
146*16b195c8SJean-Christophe PLAGNIOL-VILLARD static inline void ps2ser_out(int offset, int value)
147*16b195c8SJean-Christophe PLAGNIOL-VILLARD {
148*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	writeb(value, (unsigned long) state->iomem_base + offset);
149*16b195c8SJean-Christophe PLAGNIOL-VILLARD }
150*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
151*16b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2ser_init(void)
152*16b195c8SJean-Christophe PLAGNIOL-VILLARD {
153*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	int quot;
154*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	unsigned cval;
155*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
156*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	state = rs_table + CONFIG_PS2SERIAL;
157*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
158*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	quot = state->baud_base / PS2SER_BAUD;
159*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	cval = 0x3; /* 8N1 - 8 data bits, no parity bits, 1 stop bit */
160*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
161*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	  /* Set speed, enable interrupts, enable FIFO
162*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	   */
163*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	ps2ser_out(UART_LCR, cval | UART_LCR_DLAB);
164*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	ps2ser_out(UART_DLL, quot & 0xff);
165*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	ps2ser_out(UART_DLM, quot >> 8);
166*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	ps2ser_out(UART_LCR, cval);
167*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	ps2ser_out(UART_IER, UART_IER_RDI);
168*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	ps2ser_out(UART_MCR, UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS);
169*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	ps2ser_out(UART_FCR,
170*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	    UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
171*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
172*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	/* If we read 0xff from the LSR, there is no UART here
173*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	 */
174*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (ps2ser_in(UART_LSR) == 0xff) {
175*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		printf ("ps2ser.c: no UART found\n");
176*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		return -1;
177*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
178*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
179*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	irq_install_handler(state->irq, ps2ser_interrupt, NULL);
180*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
181*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	return 0;
182*16b195c8SJean-Christophe PLAGNIOL-VILLARD }
183*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif /* CONFIG_MPC5xxx / CONFIG_MPC8540 / other */
184*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
185*16b195c8SJean-Christophe PLAGNIOL-VILLARD void ps2ser_putc(int chr)
186*16b195c8SJean-Christophe PLAGNIOL-VILLARD {
187*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx
188*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
189*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555)
190*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	NS16550_t com_port = (NS16550_t)COM_BASE;
191*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
192*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG
193*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	printf(">>>> 0x%02x\n", chr);
194*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
195*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
196*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx
197*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	while (!(psc->psc_status & PSC_SR_TXRDY));
198*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
199*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	psc->psc_buffer_8 = chr;
200*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555)
201*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	while ((com_port->lsr & LSR_THRE) == 0);
202*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	com_port->thr = chr;
203*16b195c8SJean-Christophe PLAGNIOL-VILLARD #else
204*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	while (!(ps2ser_in(UART_LSR) & UART_LSR_THRE));
205*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
206*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	ps2ser_out(UART_TX, chr);
207*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
208*16b195c8SJean-Christophe PLAGNIOL-VILLARD }
209*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
210*16b195c8SJean-Christophe PLAGNIOL-VILLARD static int ps2ser_getc_hw(void)
211*16b195c8SJean-Christophe PLAGNIOL-VILLARD {
212*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx
213*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
214*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555)
215*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	NS16550_t com_port = (NS16550_t)COM_BASE;
216*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
217*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	int res = -1;
218*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
219*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx
220*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (psc->psc_status & PSC_SR_RXRDY) {
221*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		res = (psc->psc_buffer_8);
222*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
223*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555)
224*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (com_port->lsr & LSR_DR) {
225*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		res = com_port->rbr;
226*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
227*16b195c8SJean-Christophe PLAGNIOL-VILLARD #else
228*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (ps2ser_in(UART_LSR) & UART_LSR_DR) {
229*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		res = (ps2ser_in(UART_RX));
230*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
231*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
232*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
233*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	return res;
234*16b195c8SJean-Christophe PLAGNIOL-VILLARD }
235*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
236*16b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2ser_getc(void)
237*16b195c8SJean-Christophe PLAGNIOL-VILLARD {
238*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	volatile int chr;
239*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	int flags;
240*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
241*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG
242*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	printf("<< ");
243*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
244*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
245*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	flags = disable_interrupts();
246*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
247*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	do {
248*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		if (atomic_read(&ps2buf_cnt) != 0) {
249*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			chr = ps2buf[ps2buf_out_idx++];
250*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			ps2buf_out_idx &= (PS2BUF_SIZE - 1);
251*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			atomic_dec(&ps2buf_cnt);
252*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		} else {
253*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			chr = ps2ser_getc_hw();
254*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		}
255*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
256*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	while (chr < 0);
257*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
258*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (flags) enable_interrupts();
259*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
260*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG
261*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	printf("0x%02x\n", chr);
262*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
263*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
264*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	return chr;
265*16b195c8SJean-Christophe PLAGNIOL-VILLARD }
266*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
267*16b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2ser_check(void)
268*16b195c8SJean-Christophe PLAGNIOL-VILLARD {
269*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	int flags;
270*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
271*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	flags = disable_interrupts();
272*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	ps2ser_interrupt(NULL);
273*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (flags) enable_interrupts();
274*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
275*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	return atomic_read(&ps2buf_cnt);
276*16b195c8SJean-Christophe PLAGNIOL-VILLARD }
277*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
278*16b195c8SJean-Christophe PLAGNIOL-VILLARD static void ps2ser_interrupt(void *dev_id)
279*16b195c8SJean-Christophe PLAGNIOL-VILLARD {
280*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx
281*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
282*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555)
283*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	NS16550_t com_port = (NS16550_t)COM_BASE;
284*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
285*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	int chr;
286*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	int status;
287*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
288*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	do {
289*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		chr = ps2ser_getc_hw();
290*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx
291*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		status = psc->psc_status;
292*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555)
293*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		status = com_port->lsr;
294*16b195c8SJean-Christophe PLAGNIOL-VILLARD #else
295*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		status = ps2ser_in(UART_IIR);
296*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
297*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		if (chr < 0) continue;
298*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
299*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		if (atomic_read(&ps2buf_cnt) < PS2BUF_SIZE) {
300*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			ps2buf[ps2buf_in_idx++] = chr;
301*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			ps2buf_in_idx &= (PS2BUF_SIZE - 1);
302*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			atomic_inc(&ps2buf_cnt);
303*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		} else {
304*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			printf ("ps2ser.c: buffer overflow\n");
305*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		}
306*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC5xxx
307*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	} while (status & PSC_SR_RXRDY);
308*16b195c8SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555)
309*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	} while (status & LSR_DR);
310*16b195c8SJean-Christophe PLAGNIOL-VILLARD #else
311*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	} while (status & UART_IIR_RDI);
312*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
313*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
314*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (atomic_read(&ps2buf_cnt)) {
315*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		ps2mult_callback(atomic_read(&ps2buf_cnt));
316*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
317*16b195c8SJean-Christophe PLAGNIOL-VILLARD }
318*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
319*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif /* CONFIG_PS2SERIAL */
320