1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright 2003 Digi International (www.digi.com)
4*4882a593Smuzhiyun * Scott H Kilau <Scott_Kilau at digi dot com>
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE!
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * This is shared code between Digi's CVS archive and the
9*4882a593Smuzhiyun * Linux Kernel sources.
10*4882a593Smuzhiyun * Changing the source just for reformatting needlessly breaks
11*4882a593Smuzhiyun * our CVS diff history.
12*4882a593Smuzhiyun *
13*4882a593Smuzhiyun * Send any bug fixes/changes to: Eng.Linux at digi dot com.
14*4882a593Smuzhiyun * Thank you.
15*4882a593Smuzhiyun *
16*4882a593Smuzhiyun */
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #include <linux/delay.h> /* For udelay */
19*4882a593Smuzhiyun #include <linux/io.h> /* For read[bwl]/write[bwl] */
20*4882a593Smuzhiyun #include <linux/serial.h> /* For struct async_serial */
21*4882a593Smuzhiyun #include <linux/serial_reg.h> /* For the various UART offsets */
22*4882a593Smuzhiyun #include <linux/pci.h>
23*4882a593Smuzhiyun #include <linux/tty.h>
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #include "jsm.h" /* Driver main header file */
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun static struct {
28*4882a593Smuzhiyun unsigned int rate;
29*4882a593Smuzhiyun unsigned int cflag;
30*4882a593Smuzhiyun } baud_rates[] = {
31*4882a593Smuzhiyun { 921600, B921600 },
32*4882a593Smuzhiyun { 460800, B460800 },
33*4882a593Smuzhiyun { 230400, B230400 },
34*4882a593Smuzhiyun { 115200, B115200 },
35*4882a593Smuzhiyun { 57600, B57600 },
36*4882a593Smuzhiyun { 38400, B38400 },
37*4882a593Smuzhiyun { 19200, B19200 },
38*4882a593Smuzhiyun { 9600, B9600 },
39*4882a593Smuzhiyun { 4800, B4800 },
40*4882a593Smuzhiyun { 2400, B2400 },
41*4882a593Smuzhiyun { 1200, B1200 },
42*4882a593Smuzhiyun { 600, B600 },
43*4882a593Smuzhiyun { 300, B300 },
44*4882a593Smuzhiyun { 200, B200 },
45*4882a593Smuzhiyun { 150, B150 },
46*4882a593Smuzhiyun { 134, B134 },
47*4882a593Smuzhiyun { 110, B110 },
48*4882a593Smuzhiyun { 75, B75 },
49*4882a593Smuzhiyun { 50, B50 },
50*4882a593Smuzhiyun };
51*4882a593Smuzhiyun
cls_set_cts_flow_control(struct jsm_channel * ch)52*4882a593Smuzhiyun static void cls_set_cts_flow_control(struct jsm_channel *ch)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun u8 lcrb = readb(&ch->ch_cls_uart->lcr);
55*4882a593Smuzhiyun u8 ier = readb(&ch->ch_cls_uart->ier);
56*4882a593Smuzhiyun u8 isr_fcr = 0;
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun /*
59*4882a593Smuzhiyun * The Enhanced Register Set may only be accessed when
60*4882a593Smuzhiyun * the Line Control Register is set to 0xBFh.
61*4882a593Smuzhiyun */
62*4882a593Smuzhiyun writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun /* Turn on CTS flow control, turn off IXON flow control */
67*4882a593Smuzhiyun isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_CTSDSR);
68*4882a593Smuzhiyun isr_fcr &= ~(UART_EXAR654_EFR_IXON);
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun /* Write old LCR value back out, which turns enhanced access off */
73*4882a593Smuzhiyun writeb(lcrb, &ch->ch_cls_uart->lcr);
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun /*
76*4882a593Smuzhiyun * Enable interrupts for CTS flow, turn off interrupts for
77*4882a593Smuzhiyun * received XOFF chars
78*4882a593Smuzhiyun */
79*4882a593Smuzhiyun ier |= (UART_EXAR654_IER_CTSDSR);
80*4882a593Smuzhiyun ier &= ~(UART_EXAR654_IER_XOFF);
81*4882a593Smuzhiyun writeb(ier, &ch->ch_cls_uart->ier);
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun /* Set the usual FIFO values */
84*4882a593Smuzhiyun writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_56 |
87*4882a593Smuzhiyun UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
88*4882a593Smuzhiyun &ch->ch_cls_uart->isr_fcr);
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun ch->ch_t_tlevel = 16;
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun
cls_set_ixon_flow_control(struct jsm_channel * ch)93*4882a593Smuzhiyun static void cls_set_ixon_flow_control(struct jsm_channel *ch)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun u8 lcrb = readb(&ch->ch_cls_uart->lcr);
96*4882a593Smuzhiyun u8 ier = readb(&ch->ch_cls_uart->ier);
97*4882a593Smuzhiyun u8 isr_fcr = 0;
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun /*
100*4882a593Smuzhiyun * The Enhanced Register Set may only be accessed when
101*4882a593Smuzhiyun * the Line Control Register is set to 0xBFh.
102*4882a593Smuzhiyun */
103*4882a593Smuzhiyun writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun /* Turn on IXON flow control, turn off CTS flow control */
108*4882a593Smuzhiyun isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_IXON);
109*4882a593Smuzhiyun isr_fcr &= ~(UART_EXAR654_EFR_CTSDSR);
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun /* Now set our current start/stop chars while in enhanced mode */
114*4882a593Smuzhiyun writeb(ch->ch_startc, &ch->ch_cls_uart->mcr);
115*4882a593Smuzhiyun writeb(0, &ch->ch_cls_uart->lsr);
116*4882a593Smuzhiyun writeb(ch->ch_stopc, &ch->ch_cls_uart->msr);
117*4882a593Smuzhiyun writeb(0, &ch->ch_cls_uart->spr);
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun /* Write old LCR value back out, which turns enhanced access off */
120*4882a593Smuzhiyun writeb(lcrb, &ch->ch_cls_uart->lcr);
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun /*
123*4882a593Smuzhiyun * Disable interrupts for CTS flow, turn on interrupts for
124*4882a593Smuzhiyun * received XOFF chars
125*4882a593Smuzhiyun */
126*4882a593Smuzhiyun ier &= ~(UART_EXAR654_IER_CTSDSR);
127*4882a593Smuzhiyun ier |= (UART_EXAR654_IER_XOFF);
128*4882a593Smuzhiyun writeb(ier, &ch->ch_cls_uart->ier);
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun /* Set the usual FIFO values */
131*4882a593Smuzhiyun writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 |
134*4882a593Smuzhiyun UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
135*4882a593Smuzhiyun &ch->ch_cls_uart->isr_fcr);
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun
cls_set_no_output_flow_control(struct jsm_channel * ch)138*4882a593Smuzhiyun static void cls_set_no_output_flow_control(struct jsm_channel *ch)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun u8 lcrb = readb(&ch->ch_cls_uart->lcr);
141*4882a593Smuzhiyun u8 ier = readb(&ch->ch_cls_uart->ier);
142*4882a593Smuzhiyun u8 isr_fcr = 0;
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun /*
145*4882a593Smuzhiyun * The Enhanced Register Set may only be accessed when
146*4882a593Smuzhiyun * the Line Control Register is set to 0xBFh.
147*4882a593Smuzhiyun */
148*4882a593Smuzhiyun writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun /* Turn off IXON flow control, turn off CTS flow control */
153*4882a593Smuzhiyun isr_fcr |= (UART_EXAR654_EFR_ECB);
154*4882a593Smuzhiyun isr_fcr &= ~(UART_EXAR654_EFR_CTSDSR | UART_EXAR654_EFR_IXON);
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun /* Write old LCR value back out, which turns enhanced access off */
159*4882a593Smuzhiyun writeb(lcrb, &ch->ch_cls_uart->lcr);
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun /*
162*4882a593Smuzhiyun * Disable interrupts for CTS flow, turn off interrupts for
163*4882a593Smuzhiyun * received XOFF chars
164*4882a593Smuzhiyun */
165*4882a593Smuzhiyun ier &= ~(UART_EXAR654_IER_CTSDSR);
166*4882a593Smuzhiyun ier &= ~(UART_EXAR654_IER_XOFF);
167*4882a593Smuzhiyun writeb(ier, &ch->ch_cls_uart->ier);
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun /* Set the usual FIFO values */
170*4882a593Smuzhiyun writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 |
173*4882a593Smuzhiyun UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
174*4882a593Smuzhiyun &ch->ch_cls_uart->isr_fcr);
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun ch->ch_r_watermark = 0;
177*4882a593Smuzhiyun ch->ch_t_tlevel = 16;
178*4882a593Smuzhiyun ch->ch_r_tlevel = 16;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
cls_set_rts_flow_control(struct jsm_channel * ch)181*4882a593Smuzhiyun static void cls_set_rts_flow_control(struct jsm_channel *ch)
182*4882a593Smuzhiyun {
183*4882a593Smuzhiyun u8 lcrb = readb(&ch->ch_cls_uart->lcr);
184*4882a593Smuzhiyun u8 ier = readb(&ch->ch_cls_uart->ier);
185*4882a593Smuzhiyun u8 isr_fcr = 0;
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun /*
188*4882a593Smuzhiyun * The Enhanced Register Set may only be accessed when
189*4882a593Smuzhiyun * the Line Control Register is set to 0xBFh.
190*4882a593Smuzhiyun */
191*4882a593Smuzhiyun writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun /* Turn on RTS flow control, turn off IXOFF flow control */
196*4882a593Smuzhiyun isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_RTSDTR);
197*4882a593Smuzhiyun isr_fcr &= ~(UART_EXAR654_EFR_IXOFF);
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun /* Write old LCR value back out, which turns enhanced access off */
202*4882a593Smuzhiyun writeb(lcrb, &ch->ch_cls_uart->lcr);
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun /* Enable interrupts for RTS flow */
205*4882a593Smuzhiyun ier |= (UART_EXAR654_IER_RTSDTR);
206*4882a593Smuzhiyun writeb(ier, &ch->ch_cls_uart->ier);
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun /* Set the usual FIFO values */
209*4882a593Smuzhiyun writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_56 |
212*4882a593Smuzhiyun UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
213*4882a593Smuzhiyun &ch->ch_cls_uart->isr_fcr);
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun ch->ch_r_watermark = 4;
216*4882a593Smuzhiyun ch->ch_r_tlevel = 8;
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun
cls_set_ixoff_flow_control(struct jsm_channel * ch)219*4882a593Smuzhiyun static void cls_set_ixoff_flow_control(struct jsm_channel *ch)
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun u8 lcrb = readb(&ch->ch_cls_uart->lcr);
222*4882a593Smuzhiyun u8 ier = readb(&ch->ch_cls_uart->ier);
223*4882a593Smuzhiyun u8 isr_fcr = 0;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun /*
226*4882a593Smuzhiyun * The Enhanced Register Set may only be accessed when
227*4882a593Smuzhiyun * the Line Control Register is set to 0xBFh.
228*4882a593Smuzhiyun */
229*4882a593Smuzhiyun writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun /* Turn on IXOFF flow control, turn off RTS flow control */
234*4882a593Smuzhiyun isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_IXOFF);
235*4882a593Smuzhiyun isr_fcr &= ~(UART_EXAR654_EFR_RTSDTR);
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun /* Now set our current start/stop chars while in enhanced mode */
240*4882a593Smuzhiyun writeb(ch->ch_startc, &ch->ch_cls_uart->mcr);
241*4882a593Smuzhiyun writeb(0, &ch->ch_cls_uart->lsr);
242*4882a593Smuzhiyun writeb(ch->ch_stopc, &ch->ch_cls_uart->msr);
243*4882a593Smuzhiyun writeb(0, &ch->ch_cls_uart->spr);
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun /* Write old LCR value back out, which turns enhanced access off */
246*4882a593Smuzhiyun writeb(lcrb, &ch->ch_cls_uart->lcr);
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun /* Disable interrupts for RTS flow */
249*4882a593Smuzhiyun ier &= ~(UART_EXAR654_IER_RTSDTR);
250*4882a593Smuzhiyun writeb(ier, &ch->ch_cls_uart->ier);
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun /* Set the usual FIFO values */
253*4882a593Smuzhiyun writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 |
256*4882a593Smuzhiyun UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
257*4882a593Smuzhiyun &ch->ch_cls_uart->isr_fcr);
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun
cls_set_no_input_flow_control(struct jsm_channel * ch)260*4882a593Smuzhiyun static void cls_set_no_input_flow_control(struct jsm_channel *ch)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun u8 lcrb = readb(&ch->ch_cls_uart->lcr);
263*4882a593Smuzhiyun u8 ier = readb(&ch->ch_cls_uart->ier);
264*4882a593Smuzhiyun u8 isr_fcr = 0;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun /*
267*4882a593Smuzhiyun * The Enhanced Register Set may only be accessed when
268*4882a593Smuzhiyun * the Line Control Register is set to 0xBFh.
269*4882a593Smuzhiyun */
270*4882a593Smuzhiyun writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun /* Turn off IXOFF flow control, turn off RTS flow control */
275*4882a593Smuzhiyun isr_fcr |= (UART_EXAR654_EFR_ECB);
276*4882a593Smuzhiyun isr_fcr &= ~(UART_EXAR654_EFR_RTSDTR | UART_EXAR654_EFR_IXOFF);
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun /* Write old LCR value back out, which turns enhanced access off */
281*4882a593Smuzhiyun writeb(lcrb, &ch->ch_cls_uart->lcr);
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun /* Disable interrupts for RTS flow */
284*4882a593Smuzhiyun ier &= ~(UART_EXAR654_IER_RTSDTR);
285*4882a593Smuzhiyun writeb(ier, &ch->ch_cls_uart->ier);
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun /* Set the usual FIFO values */
288*4882a593Smuzhiyun writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 |
291*4882a593Smuzhiyun UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
292*4882a593Smuzhiyun &ch->ch_cls_uart->isr_fcr);
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun ch->ch_t_tlevel = 16;
295*4882a593Smuzhiyun ch->ch_r_tlevel = 16;
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun /*
299*4882a593Smuzhiyun * cls_clear_break.
300*4882a593Smuzhiyun * Determines whether its time to shut off break condition.
301*4882a593Smuzhiyun *
302*4882a593Smuzhiyun * No locks are assumed to be held when calling this function.
303*4882a593Smuzhiyun * channel lock is held and released in this function.
304*4882a593Smuzhiyun */
cls_clear_break(struct jsm_channel * ch)305*4882a593Smuzhiyun static void cls_clear_break(struct jsm_channel *ch)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun unsigned long lock_flags;
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun spin_lock_irqsave(&ch->ch_lock, lock_flags);
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun /* Turn break off, and unset some variables */
312*4882a593Smuzhiyun if (ch->ch_flags & CH_BREAK_SENDING) {
313*4882a593Smuzhiyun u8 temp = readb(&ch->ch_cls_uart->lcr);
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun writeb((temp & ~UART_LCR_SBC), &ch->ch_cls_uart->lcr);
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun ch->ch_flags &= ~(CH_BREAK_SENDING);
318*4882a593Smuzhiyun jsm_dbg(IOCTL, &ch->ch_bd->pci_dev,
319*4882a593Smuzhiyun "clear break Finishing UART_LCR_SBC! finished: %lx\n",
320*4882a593Smuzhiyun jiffies);
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun
cls_disable_receiver(struct jsm_channel * ch)325*4882a593Smuzhiyun static void cls_disable_receiver(struct jsm_channel *ch)
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun u8 tmp = readb(&ch->ch_cls_uart->ier);
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun tmp &= ~(UART_IER_RDI);
330*4882a593Smuzhiyun writeb(tmp, &ch->ch_cls_uart->ier);
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun
cls_enable_receiver(struct jsm_channel * ch)333*4882a593Smuzhiyun static void cls_enable_receiver(struct jsm_channel *ch)
334*4882a593Smuzhiyun {
335*4882a593Smuzhiyun u8 tmp = readb(&ch->ch_cls_uart->ier);
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun tmp |= (UART_IER_RDI);
338*4882a593Smuzhiyun writeb(tmp, &ch->ch_cls_uart->ier);
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun /* Make the UART raise any of the output signals we want up */
cls_assert_modem_signals(struct jsm_channel * ch)342*4882a593Smuzhiyun static void cls_assert_modem_signals(struct jsm_channel *ch)
343*4882a593Smuzhiyun {
344*4882a593Smuzhiyun if (!ch)
345*4882a593Smuzhiyun return;
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun writeb(ch->ch_mostat, &ch->ch_cls_uart->mcr);
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun
cls_copy_data_from_uart_to_queue(struct jsm_channel * ch)350*4882a593Smuzhiyun static void cls_copy_data_from_uart_to_queue(struct jsm_channel *ch)
351*4882a593Smuzhiyun {
352*4882a593Smuzhiyun int qleft = 0;
353*4882a593Smuzhiyun u8 linestatus = 0;
354*4882a593Smuzhiyun u8 error_mask = 0;
355*4882a593Smuzhiyun u16 head;
356*4882a593Smuzhiyun u16 tail;
357*4882a593Smuzhiyun unsigned long flags;
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun if (!ch)
360*4882a593Smuzhiyun return;
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun spin_lock_irqsave(&ch->ch_lock, flags);
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun /* cache head and tail of queue */
365*4882a593Smuzhiyun head = ch->ch_r_head & RQUEUEMASK;
366*4882a593Smuzhiyun tail = ch->ch_r_tail & RQUEUEMASK;
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun /* Get our cached LSR */
369*4882a593Smuzhiyun linestatus = ch->ch_cached_lsr;
370*4882a593Smuzhiyun ch->ch_cached_lsr = 0;
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun /* Store how much space we have left in the queue */
373*4882a593Smuzhiyun qleft = tail - head - 1;
374*4882a593Smuzhiyun if (qleft < 0)
375*4882a593Smuzhiyun qleft += RQUEUEMASK + 1;
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun /*
378*4882a593Smuzhiyun * Create a mask to determine whether we should
379*4882a593Smuzhiyun * insert the character (if any) into our queue.
380*4882a593Smuzhiyun */
381*4882a593Smuzhiyun if (ch->ch_c_iflag & IGNBRK)
382*4882a593Smuzhiyun error_mask |= UART_LSR_BI;
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun while (1) {
385*4882a593Smuzhiyun /*
386*4882a593Smuzhiyun * Grab the linestatus register, we need to
387*4882a593Smuzhiyun * check to see if there is any data to read
388*4882a593Smuzhiyun */
389*4882a593Smuzhiyun linestatus = readb(&ch->ch_cls_uart->lsr);
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun /* Break out if there is no data to fetch */
392*4882a593Smuzhiyun if (!(linestatus & UART_LSR_DR))
393*4882a593Smuzhiyun break;
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun /*
396*4882a593Smuzhiyun * Discard character if we are ignoring the error mask
397*4882a593Smuzhiyun * which in this case is the break signal.
398*4882a593Smuzhiyun */
399*4882a593Smuzhiyun if (linestatus & error_mask) {
400*4882a593Smuzhiyun u8 discard;
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun linestatus = 0;
403*4882a593Smuzhiyun discard = readb(&ch->ch_cls_uart->txrx);
404*4882a593Smuzhiyun continue;
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun /*
408*4882a593Smuzhiyun * If our queue is full, we have no choice but to drop some
409*4882a593Smuzhiyun * data. The assumption is that HWFLOW or SWFLOW should have
410*4882a593Smuzhiyun * stopped things way way before we got to this point.
411*4882a593Smuzhiyun *
412*4882a593Smuzhiyun * I decided that I wanted to ditch the oldest data first,
413*4882a593Smuzhiyun * I hope thats okay with everyone? Yes? Good.
414*4882a593Smuzhiyun */
415*4882a593Smuzhiyun while (qleft < 1) {
416*4882a593Smuzhiyun tail = (tail + 1) & RQUEUEMASK;
417*4882a593Smuzhiyun ch->ch_r_tail = tail;
418*4882a593Smuzhiyun ch->ch_err_overrun++;
419*4882a593Smuzhiyun qleft++;
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun ch->ch_equeue[head] = linestatus & (UART_LSR_BI | UART_LSR_PE
423*4882a593Smuzhiyun | UART_LSR_FE);
424*4882a593Smuzhiyun ch->ch_rqueue[head] = readb(&ch->ch_cls_uart->txrx);
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun qleft--;
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun if (ch->ch_equeue[head] & UART_LSR_PE)
429*4882a593Smuzhiyun ch->ch_err_parity++;
430*4882a593Smuzhiyun if (ch->ch_equeue[head] & UART_LSR_BI)
431*4882a593Smuzhiyun ch->ch_err_break++;
432*4882a593Smuzhiyun if (ch->ch_equeue[head] & UART_LSR_FE)
433*4882a593Smuzhiyun ch->ch_err_frame++;
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun /* Add to, and flip head if needed */
436*4882a593Smuzhiyun head = (head + 1) & RQUEUEMASK;
437*4882a593Smuzhiyun ch->ch_rxcount++;
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun /*
441*4882a593Smuzhiyun * Write new final heads to channel structure.
442*4882a593Smuzhiyun */
443*4882a593Smuzhiyun ch->ch_r_head = head & RQUEUEMASK;
444*4882a593Smuzhiyun ch->ch_e_head = head & EQUEUEMASK;
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun spin_unlock_irqrestore(&ch->ch_lock, flags);
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun
cls_copy_data_from_queue_to_uart(struct jsm_channel * ch)449*4882a593Smuzhiyun static void cls_copy_data_from_queue_to_uart(struct jsm_channel *ch)
450*4882a593Smuzhiyun {
451*4882a593Smuzhiyun u16 tail;
452*4882a593Smuzhiyun int n;
453*4882a593Smuzhiyun int qlen;
454*4882a593Smuzhiyun u32 len_written = 0;
455*4882a593Smuzhiyun struct circ_buf *circ;
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun if (!ch)
458*4882a593Smuzhiyun return;
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun circ = &ch->uart_port.state->xmit;
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun /* No data to write to the UART */
463*4882a593Smuzhiyun if (uart_circ_empty(circ))
464*4882a593Smuzhiyun return;
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun /* If port is "stopped", don't send any data to the UART */
467*4882a593Smuzhiyun if ((ch->ch_flags & CH_STOP) || (ch->ch_flags & CH_BREAK_SENDING))
468*4882a593Smuzhiyun return;
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun /* We have to do it this way, because of the EXAR TXFIFO count bug. */
471*4882a593Smuzhiyun if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM)))
472*4882a593Smuzhiyun return;
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun n = 32;
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun /* cache tail of queue */
477*4882a593Smuzhiyun tail = circ->tail & (UART_XMIT_SIZE - 1);
478*4882a593Smuzhiyun qlen = uart_circ_chars_pending(circ);
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun /* Find minimum of the FIFO space, versus queue length */
481*4882a593Smuzhiyun n = min(n, qlen);
482*4882a593Smuzhiyun
483*4882a593Smuzhiyun while (n > 0) {
484*4882a593Smuzhiyun writeb(circ->buf[tail], &ch->ch_cls_uart->txrx);
485*4882a593Smuzhiyun tail = (tail + 1) & (UART_XMIT_SIZE - 1);
486*4882a593Smuzhiyun n--;
487*4882a593Smuzhiyun ch->ch_txcount++;
488*4882a593Smuzhiyun len_written++;
489*4882a593Smuzhiyun }
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun /* Update the final tail */
492*4882a593Smuzhiyun circ->tail = tail & (UART_XMIT_SIZE - 1);
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun if (len_written > ch->ch_t_tlevel)
495*4882a593Smuzhiyun ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun if (uart_circ_empty(circ))
498*4882a593Smuzhiyun uart_write_wakeup(&ch->uart_port);
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun
cls_parse_modem(struct jsm_channel * ch,u8 signals)501*4882a593Smuzhiyun static void cls_parse_modem(struct jsm_channel *ch, u8 signals)
502*4882a593Smuzhiyun {
503*4882a593Smuzhiyun u8 msignals = signals;
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun jsm_dbg(MSIGS, &ch->ch_bd->pci_dev,
506*4882a593Smuzhiyun "neo_parse_modem: port: %d msignals: %x\n",
507*4882a593Smuzhiyun ch->ch_portnum, msignals);
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun /*
510*4882a593Smuzhiyun * Scrub off lower bits.
511*4882a593Smuzhiyun * They signify delta's, which I don't care about
512*4882a593Smuzhiyun * Keep DDCD and DDSR though
513*4882a593Smuzhiyun */
514*4882a593Smuzhiyun msignals &= 0xf8;
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun if (msignals & UART_MSR_DDCD)
517*4882a593Smuzhiyun uart_handle_dcd_change(&ch->uart_port, msignals & UART_MSR_DCD);
518*4882a593Smuzhiyun if (msignals & UART_MSR_DDSR)
519*4882a593Smuzhiyun uart_handle_dcd_change(&ch->uart_port, msignals & UART_MSR_CTS);
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun if (msignals & UART_MSR_DCD)
522*4882a593Smuzhiyun ch->ch_mistat |= UART_MSR_DCD;
523*4882a593Smuzhiyun else
524*4882a593Smuzhiyun ch->ch_mistat &= ~UART_MSR_DCD;
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun if (msignals & UART_MSR_DSR)
527*4882a593Smuzhiyun ch->ch_mistat |= UART_MSR_DSR;
528*4882a593Smuzhiyun else
529*4882a593Smuzhiyun ch->ch_mistat &= ~UART_MSR_DSR;
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun if (msignals & UART_MSR_RI)
532*4882a593Smuzhiyun ch->ch_mistat |= UART_MSR_RI;
533*4882a593Smuzhiyun else
534*4882a593Smuzhiyun ch->ch_mistat &= ~UART_MSR_RI;
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun if (msignals & UART_MSR_CTS)
537*4882a593Smuzhiyun ch->ch_mistat |= UART_MSR_CTS;
538*4882a593Smuzhiyun else
539*4882a593Smuzhiyun ch->ch_mistat &= ~UART_MSR_CTS;
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun jsm_dbg(MSIGS, &ch->ch_bd->pci_dev,
542*4882a593Smuzhiyun "Port: %d DTR: %d RTS: %d CTS: %d DSR: %d " "RI: %d CD: %d\n",
543*4882a593Smuzhiyun ch->ch_portnum,
544*4882a593Smuzhiyun !!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_DTR),
545*4882a593Smuzhiyun !!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_RTS),
546*4882a593Smuzhiyun !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_CTS),
547*4882a593Smuzhiyun !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DSR),
548*4882a593Smuzhiyun !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_RI),
549*4882a593Smuzhiyun !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DCD));
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun /* Parse the ISR register for the specific port */
cls_parse_isr(struct jsm_board * brd,uint port)553*4882a593Smuzhiyun static inline void cls_parse_isr(struct jsm_board *brd, uint port)
554*4882a593Smuzhiyun {
555*4882a593Smuzhiyun struct jsm_channel *ch;
556*4882a593Smuzhiyun u8 isr = 0;
557*4882a593Smuzhiyun unsigned long flags;
558*4882a593Smuzhiyun
559*4882a593Smuzhiyun /*
560*4882a593Smuzhiyun * No need to verify board pointer, it was already
561*4882a593Smuzhiyun * verified in the interrupt routine.
562*4882a593Smuzhiyun */
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun if (port >= brd->nasync)
565*4882a593Smuzhiyun return;
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun ch = brd->channels[port];
568*4882a593Smuzhiyun if (!ch)
569*4882a593Smuzhiyun return;
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun /* Here we try to figure out what caused the interrupt to happen */
572*4882a593Smuzhiyun while (1) {
573*4882a593Smuzhiyun isr = readb(&ch->ch_cls_uart->isr_fcr);
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun /* Bail if no pending interrupt on port */
576*4882a593Smuzhiyun if (isr & UART_IIR_NO_INT)
577*4882a593Smuzhiyun break;
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun /* Receive Interrupt pending */
580*4882a593Smuzhiyun if (isr & (UART_IIR_RDI | UART_IIR_RDI_TIMEOUT)) {
581*4882a593Smuzhiyun /* Read data from uart -> queue */
582*4882a593Smuzhiyun cls_copy_data_from_uart_to_queue(ch);
583*4882a593Smuzhiyun jsm_check_queue_flow_control(ch);
584*4882a593Smuzhiyun }
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun /* Transmit Hold register empty pending */
587*4882a593Smuzhiyun if (isr & UART_IIR_THRI) {
588*4882a593Smuzhiyun /* Transfer data (if any) from Write Queue -> UART. */
589*4882a593Smuzhiyun spin_lock_irqsave(&ch->ch_lock, flags);
590*4882a593Smuzhiyun ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
591*4882a593Smuzhiyun spin_unlock_irqrestore(&ch->ch_lock, flags);
592*4882a593Smuzhiyun cls_copy_data_from_queue_to_uart(ch);
593*4882a593Smuzhiyun }
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun /*
596*4882a593Smuzhiyun * CTS/RTS change of state:
597*4882a593Smuzhiyun * Don't need to do anything, the cls_parse_modem
598*4882a593Smuzhiyun * below will grab the updated modem signals.
599*4882a593Smuzhiyun */
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun /* Parse any modem signal changes */
602*4882a593Smuzhiyun cls_parse_modem(ch, readb(&ch->ch_cls_uart->msr));
603*4882a593Smuzhiyun }
604*4882a593Smuzhiyun }
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun /* Channel lock MUST be held before calling this function! */
cls_flush_uart_write(struct jsm_channel * ch)607*4882a593Smuzhiyun static void cls_flush_uart_write(struct jsm_channel *ch)
608*4882a593Smuzhiyun {
609*4882a593Smuzhiyun u8 tmp = 0;
610*4882a593Smuzhiyun u8 i = 0;
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun if (!ch)
613*4882a593Smuzhiyun return;
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT),
616*4882a593Smuzhiyun &ch->ch_cls_uart->isr_fcr);
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun for (i = 0; i < 10; i++) {
619*4882a593Smuzhiyun /* Check to see if the UART feels it completely flushed FIFO */
620*4882a593Smuzhiyun tmp = readb(&ch->ch_cls_uart->isr_fcr);
621*4882a593Smuzhiyun if (tmp & UART_FCR_CLEAR_XMIT) {
622*4882a593Smuzhiyun jsm_dbg(IOCTL, &ch->ch_bd->pci_dev,
623*4882a593Smuzhiyun "Still flushing TX UART... i: %d\n", i);
624*4882a593Smuzhiyun udelay(10);
625*4882a593Smuzhiyun } else
626*4882a593Smuzhiyun break;
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
630*4882a593Smuzhiyun }
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun /* Channel lock MUST be held before calling this function! */
cls_flush_uart_read(struct jsm_channel * ch)633*4882a593Smuzhiyun static void cls_flush_uart_read(struct jsm_channel *ch)
634*4882a593Smuzhiyun {
635*4882a593Smuzhiyun if (!ch)
636*4882a593Smuzhiyun return;
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun /*
639*4882a593Smuzhiyun * For complete POSIX compatibility, we should be purging the
640*4882a593Smuzhiyun * read FIFO in the UART here.
641*4882a593Smuzhiyun *
642*4882a593Smuzhiyun * However, clearing the read FIFO (UART_FCR_CLEAR_RCVR) also
643*4882a593Smuzhiyun * incorrectly flushes write data as well as just basically trashing the
644*4882a593Smuzhiyun * FIFO.
645*4882a593Smuzhiyun *
646*4882a593Smuzhiyun * Presumably, this is a bug in this UART.
647*4882a593Smuzhiyun */
648*4882a593Smuzhiyun
649*4882a593Smuzhiyun udelay(10);
650*4882a593Smuzhiyun }
651*4882a593Smuzhiyun
cls_send_start_character(struct jsm_channel * ch)652*4882a593Smuzhiyun static void cls_send_start_character(struct jsm_channel *ch)
653*4882a593Smuzhiyun {
654*4882a593Smuzhiyun if (!ch)
655*4882a593Smuzhiyun return;
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun if (ch->ch_startc != __DISABLED_CHAR) {
658*4882a593Smuzhiyun ch->ch_xon_sends++;
659*4882a593Smuzhiyun writeb(ch->ch_startc, &ch->ch_cls_uart->txrx);
660*4882a593Smuzhiyun }
661*4882a593Smuzhiyun }
662*4882a593Smuzhiyun
cls_send_stop_character(struct jsm_channel * ch)663*4882a593Smuzhiyun static void cls_send_stop_character(struct jsm_channel *ch)
664*4882a593Smuzhiyun {
665*4882a593Smuzhiyun if (!ch)
666*4882a593Smuzhiyun return;
667*4882a593Smuzhiyun
668*4882a593Smuzhiyun if (ch->ch_stopc != __DISABLED_CHAR) {
669*4882a593Smuzhiyun ch->ch_xoff_sends++;
670*4882a593Smuzhiyun writeb(ch->ch_stopc, &ch->ch_cls_uart->txrx);
671*4882a593Smuzhiyun }
672*4882a593Smuzhiyun }
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun /*
675*4882a593Smuzhiyun * cls_param()
676*4882a593Smuzhiyun * Send any/all changes to the line to the UART.
677*4882a593Smuzhiyun */
cls_param(struct jsm_channel * ch)678*4882a593Smuzhiyun static void cls_param(struct jsm_channel *ch)
679*4882a593Smuzhiyun {
680*4882a593Smuzhiyun u8 lcr = 0;
681*4882a593Smuzhiyun u8 uart_lcr = 0;
682*4882a593Smuzhiyun u8 ier = 0;
683*4882a593Smuzhiyun u32 baud = 9600;
684*4882a593Smuzhiyun int quot = 0;
685*4882a593Smuzhiyun struct jsm_board *bd;
686*4882a593Smuzhiyun int i;
687*4882a593Smuzhiyun unsigned int cflag;
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun bd = ch->ch_bd;
690*4882a593Smuzhiyun if (!bd)
691*4882a593Smuzhiyun return;
692*4882a593Smuzhiyun
693*4882a593Smuzhiyun /*
694*4882a593Smuzhiyun * If baud rate is zero, flush queues, and set mval to drop DTR.
695*4882a593Smuzhiyun */
696*4882a593Smuzhiyun if ((ch->ch_c_cflag & (CBAUD)) == 0) {
697*4882a593Smuzhiyun ch->ch_r_head = 0;
698*4882a593Smuzhiyun ch->ch_r_tail = 0;
699*4882a593Smuzhiyun ch->ch_e_head = 0;
700*4882a593Smuzhiyun ch->ch_e_tail = 0;
701*4882a593Smuzhiyun
702*4882a593Smuzhiyun cls_flush_uart_write(ch);
703*4882a593Smuzhiyun cls_flush_uart_read(ch);
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun /* The baudrate is B0 so all modem lines are to be dropped. */
706*4882a593Smuzhiyun ch->ch_flags |= (CH_BAUD0);
707*4882a593Smuzhiyun ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR);
708*4882a593Smuzhiyun cls_assert_modem_signals(ch);
709*4882a593Smuzhiyun return;
710*4882a593Smuzhiyun }
711*4882a593Smuzhiyun
712*4882a593Smuzhiyun cflag = C_BAUD(ch->uart_port.state->port.tty);
713*4882a593Smuzhiyun baud = 9600;
714*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(baud_rates); i++) {
715*4882a593Smuzhiyun if (baud_rates[i].cflag == cflag) {
716*4882a593Smuzhiyun baud = baud_rates[i].rate;
717*4882a593Smuzhiyun break;
718*4882a593Smuzhiyun }
719*4882a593Smuzhiyun }
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun if (ch->ch_flags & CH_BAUD0)
722*4882a593Smuzhiyun ch->ch_flags &= ~(CH_BAUD0);
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun if (ch->ch_c_cflag & PARENB)
725*4882a593Smuzhiyun lcr |= UART_LCR_PARITY;
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun if (!(ch->ch_c_cflag & PARODD))
728*4882a593Smuzhiyun lcr |= UART_LCR_EPAR;
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun /*
731*4882a593Smuzhiyun * Not all platforms support mark/space parity,
732*4882a593Smuzhiyun * so this will hide behind an ifdef.
733*4882a593Smuzhiyun */
734*4882a593Smuzhiyun #ifdef CMSPAR
735*4882a593Smuzhiyun if (ch->ch_c_cflag & CMSPAR)
736*4882a593Smuzhiyun lcr |= UART_LCR_SPAR;
737*4882a593Smuzhiyun #endif
738*4882a593Smuzhiyun
739*4882a593Smuzhiyun if (ch->ch_c_cflag & CSTOPB)
740*4882a593Smuzhiyun lcr |= UART_LCR_STOP;
741*4882a593Smuzhiyun
742*4882a593Smuzhiyun switch (ch->ch_c_cflag & CSIZE) {
743*4882a593Smuzhiyun case CS5:
744*4882a593Smuzhiyun lcr |= UART_LCR_WLEN5;
745*4882a593Smuzhiyun break;
746*4882a593Smuzhiyun case CS6:
747*4882a593Smuzhiyun lcr |= UART_LCR_WLEN6;
748*4882a593Smuzhiyun break;
749*4882a593Smuzhiyun case CS7:
750*4882a593Smuzhiyun lcr |= UART_LCR_WLEN7;
751*4882a593Smuzhiyun break;
752*4882a593Smuzhiyun case CS8:
753*4882a593Smuzhiyun default:
754*4882a593Smuzhiyun lcr |= UART_LCR_WLEN8;
755*4882a593Smuzhiyun break;
756*4882a593Smuzhiyun }
757*4882a593Smuzhiyun
758*4882a593Smuzhiyun ier = readb(&ch->ch_cls_uart->ier);
759*4882a593Smuzhiyun uart_lcr = readb(&ch->ch_cls_uart->lcr);
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun quot = ch->ch_bd->bd_dividend / baud;
762*4882a593Smuzhiyun
763*4882a593Smuzhiyun if (quot != 0) {
764*4882a593Smuzhiyun writeb(UART_LCR_DLAB, &ch->ch_cls_uart->lcr);
765*4882a593Smuzhiyun writeb((quot & 0xff), &ch->ch_cls_uart->txrx);
766*4882a593Smuzhiyun writeb((quot >> 8), &ch->ch_cls_uart->ier);
767*4882a593Smuzhiyun writeb(lcr, &ch->ch_cls_uart->lcr);
768*4882a593Smuzhiyun }
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun if (uart_lcr != lcr)
771*4882a593Smuzhiyun writeb(lcr, &ch->ch_cls_uart->lcr);
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun if (ch->ch_c_cflag & CREAD)
774*4882a593Smuzhiyun ier |= (UART_IER_RDI | UART_IER_RLSI);
775*4882a593Smuzhiyun
776*4882a593Smuzhiyun ier |= (UART_IER_THRI | UART_IER_MSI);
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun writeb(ier, &ch->ch_cls_uart->ier);
779*4882a593Smuzhiyun
780*4882a593Smuzhiyun if (ch->ch_c_cflag & CRTSCTS)
781*4882a593Smuzhiyun cls_set_cts_flow_control(ch);
782*4882a593Smuzhiyun else if (ch->ch_c_iflag & IXON) {
783*4882a593Smuzhiyun /*
784*4882a593Smuzhiyun * If start/stop is set to disable,
785*4882a593Smuzhiyun * then we should disable flow control.
786*4882a593Smuzhiyun */
787*4882a593Smuzhiyun if ((ch->ch_startc == __DISABLED_CHAR) ||
788*4882a593Smuzhiyun (ch->ch_stopc == __DISABLED_CHAR))
789*4882a593Smuzhiyun cls_set_no_output_flow_control(ch);
790*4882a593Smuzhiyun else
791*4882a593Smuzhiyun cls_set_ixon_flow_control(ch);
792*4882a593Smuzhiyun } else
793*4882a593Smuzhiyun cls_set_no_output_flow_control(ch);
794*4882a593Smuzhiyun
795*4882a593Smuzhiyun if (ch->ch_c_cflag & CRTSCTS)
796*4882a593Smuzhiyun cls_set_rts_flow_control(ch);
797*4882a593Smuzhiyun else if (ch->ch_c_iflag & IXOFF) {
798*4882a593Smuzhiyun /*
799*4882a593Smuzhiyun * If start/stop is set to disable,
800*4882a593Smuzhiyun * then we should disable flow control.
801*4882a593Smuzhiyun */
802*4882a593Smuzhiyun if ((ch->ch_startc == __DISABLED_CHAR) ||
803*4882a593Smuzhiyun (ch->ch_stopc == __DISABLED_CHAR))
804*4882a593Smuzhiyun cls_set_no_input_flow_control(ch);
805*4882a593Smuzhiyun else
806*4882a593Smuzhiyun cls_set_ixoff_flow_control(ch);
807*4882a593Smuzhiyun } else
808*4882a593Smuzhiyun cls_set_no_input_flow_control(ch);
809*4882a593Smuzhiyun
810*4882a593Smuzhiyun cls_assert_modem_signals(ch);
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun /* get current status of the modem signals now */
813*4882a593Smuzhiyun cls_parse_modem(ch, readb(&ch->ch_cls_uart->msr));
814*4882a593Smuzhiyun }
815*4882a593Smuzhiyun
816*4882a593Smuzhiyun /*
817*4882a593Smuzhiyun * cls_intr()
818*4882a593Smuzhiyun *
819*4882a593Smuzhiyun * Classic specific interrupt handler.
820*4882a593Smuzhiyun */
cls_intr(int irq,void * voidbrd)821*4882a593Smuzhiyun static irqreturn_t cls_intr(int irq, void *voidbrd)
822*4882a593Smuzhiyun {
823*4882a593Smuzhiyun struct jsm_board *brd = voidbrd;
824*4882a593Smuzhiyun unsigned long lock_flags;
825*4882a593Smuzhiyun unsigned char uart_poll;
826*4882a593Smuzhiyun uint i = 0;
827*4882a593Smuzhiyun
828*4882a593Smuzhiyun /* Lock out the slow poller from running on this board. */
829*4882a593Smuzhiyun spin_lock_irqsave(&brd->bd_intr_lock, lock_flags);
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun /*
832*4882a593Smuzhiyun * Check the board's global interrupt offset to see if we
833*4882a593Smuzhiyun * acctually do have an interrupt pending on us.
834*4882a593Smuzhiyun */
835*4882a593Smuzhiyun uart_poll = readb(brd->re_map_membase + UART_CLASSIC_POLL_ADDR_OFFSET);
836*4882a593Smuzhiyun
837*4882a593Smuzhiyun jsm_dbg(INTR, &brd->pci_dev, "%s:%d uart_poll: %x\n",
838*4882a593Smuzhiyun __FILE__, __LINE__, uart_poll);
839*4882a593Smuzhiyun
840*4882a593Smuzhiyun if (!uart_poll) {
841*4882a593Smuzhiyun jsm_dbg(INTR, &brd->pci_dev,
842*4882a593Smuzhiyun "Kernel interrupted to me, but no pending interrupts...\n");
843*4882a593Smuzhiyun spin_unlock_irqrestore(&brd->bd_intr_lock, lock_flags);
844*4882a593Smuzhiyun return IRQ_NONE;
845*4882a593Smuzhiyun }
846*4882a593Smuzhiyun
847*4882a593Smuzhiyun /* At this point, we have at least SOMETHING to service, dig further. */
848*4882a593Smuzhiyun
849*4882a593Smuzhiyun /* Parse each port to find out what caused the interrupt */
850*4882a593Smuzhiyun for (i = 0; i < brd->nasync; i++)
851*4882a593Smuzhiyun cls_parse_isr(brd, i);
852*4882a593Smuzhiyun
853*4882a593Smuzhiyun spin_unlock_irqrestore(&brd->bd_intr_lock, lock_flags);
854*4882a593Smuzhiyun
855*4882a593Smuzhiyun return IRQ_HANDLED;
856*4882a593Smuzhiyun }
857*4882a593Smuzhiyun
858*4882a593Smuzhiyun /* Inits UART */
cls_uart_init(struct jsm_channel * ch)859*4882a593Smuzhiyun static void cls_uart_init(struct jsm_channel *ch)
860*4882a593Smuzhiyun {
861*4882a593Smuzhiyun unsigned char lcrb = readb(&ch->ch_cls_uart->lcr);
862*4882a593Smuzhiyun unsigned char isr_fcr = 0;
863*4882a593Smuzhiyun
864*4882a593Smuzhiyun writeb(0, &ch->ch_cls_uart->ier);
865*4882a593Smuzhiyun
866*4882a593Smuzhiyun /*
867*4882a593Smuzhiyun * The Enhanced Register Set may only be accessed when
868*4882a593Smuzhiyun * the Line Control Register is set to 0xBFh.
869*4882a593Smuzhiyun */
870*4882a593Smuzhiyun writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
871*4882a593Smuzhiyun
872*4882a593Smuzhiyun isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
873*4882a593Smuzhiyun
874*4882a593Smuzhiyun /* Turn on Enhanced/Extended controls */
875*4882a593Smuzhiyun isr_fcr |= (UART_EXAR654_EFR_ECB);
876*4882a593Smuzhiyun
877*4882a593Smuzhiyun writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun /* Write old LCR value back out, which turns enhanced access off */
880*4882a593Smuzhiyun writeb(lcrb, &ch->ch_cls_uart->lcr);
881*4882a593Smuzhiyun
882*4882a593Smuzhiyun /* Clear out UART and FIFO */
883*4882a593Smuzhiyun readb(&ch->ch_cls_uart->txrx);
884*4882a593Smuzhiyun
885*4882a593Smuzhiyun writeb((UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT),
886*4882a593Smuzhiyun &ch->ch_cls_uart->isr_fcr);
887*4882a593Smuzhiyun udelay(10);
888*4882a593Smuzhiyun
889*4882a593Smuzhiyun ch->ch_flags |= (CH_FIFO_ENABLED | CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
890*4882a593Smuzhiyun
891*4882a593Smuzhiyun readb(&ch->ch_cls_uart->lsr);
892*4882a593Smuzhiyun readb(&ch->ch_cls_uart->msr);
893*4882a593Smuzhiyun }
894*4882a593Smuzhiyun
895*4882a593Smuzhiyun /*
896*4882a593Smuzhiyun * Turns off UART.
897*4882a593Smuzhiyun */
cls_uart_off(struct jsm_channel * ch)898*4882a593Smuzhiyun static void cls_uart_off(struct jsm_channel *ch)
899*4882a593Smuzhiyun {
900*4882a593Smuzhiyun /* Stop all interrupts from accurring. */
901*4882a593Smuzhiyun writeb(0, &ch->ch_cls_uart->ier);
902*4882a593Smuzhiyun }
903*4882a593Smuzhiyun
904*4882a593Smuzhiyun /*
905*4882a593Smuzhiyun * cls_get_uarts_bytes_left.
906*4882a593Smuzhiyun * Returns 0 is nothing left in the FIFO, returns 1 otherwise.
907*4882a593Smuzhiyun *
908*4882a593Smuzhiyun * The channel lock MUST be held by the calling function.
909*4882a593Smuzhiyun */
cls_get_uart_bytes_left(struct jsm_channel * ch)910*4882a593Smuzhiyun static u32 cls_get_uart_bytes_left(struct jsm_channel *ch)
911*4882a593Smuzhiyun {
912*4882a593Smuzhiyun u8 left = 0;
913*4882a593Smuzhiyun u8 lsr = readb(&ch->ch_cls_uart->lsr);
914*4882a593Smuzhiyun
915*4882a593Smuzhiyun /* Determine whether the Transmitter is empty or not */
916*4882a593Smuzhiyun if (!(lsr & UART_LSR_TEMT))
917*4882a593Smuzhiyun left = 1;
918*4882a593Smuzhiyun else {
919*4882a593Smuzhiyun ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
920*4882a593Smuzhiyun left = 0;
921*4882a593Smuzhiyun }
922*4882a593Smuzhiyun
923*4882a593Smuzhiyun return left;
924*4882a593Smuzhiyun }
925*4882a593Smuzhiyun
926*4882a593Smuzhiyun /*
927*4882a593Smuzhiyun * cls_send_break.
928*4882a593Smuzhiyun * Starts sending a break thru the UART.
929*4882a593Smuzhiyun *
930*4882a593Smuzhiyun * The channel lock MUST be held by the calling function.
931*4882a593Smuzhiyun */
cls_send_break(struct jsm_channel * ch)932*4882a593Smuzhiyun static void cls_send_break(struct jsm_channel *ch)
933*4882a593Smuzhiyun {
934*4882a593Smuzhiyun /* Tell the UART to start sending the break */
935*4882a593Smuzhiyun if (!(ch->ch_flags & CH_BREAK_SENDING)) {
936*4882a593Smuzhiyun u8 temp = readb(&ch->ch_cls_uart->lcr);
937*4882a593Smuzhiyun
938*4882a593Smuzhiyun writeb((temp | UART_LCR_SBC), &ch->ch_cls_uart->lcr);
939*4882a593Smuzhiyun ch->ch_flags |= (CH_BREAK_SENDING);
940*4882a593Smuzhiyun }
941*4882a593Smuzhiyun }
942*4882a593Smuzhiyun
943*4882a593Smuzhiyun /*
944*4882a593Smuzhiyun * cls_send_immediate_char.
945*4882a593Smuzhiyun * Sends a specific character as soon as possible to the UART,
946*4882a593Smuzhiyun * jumping over any bytes that might be in the write queue.
947*4882a593Smuzhiyun *
948*4882a593Smuzhiyun * The channel lock MUST be held by the calling function.
949*4882a593Smuzhiyun */
cls_send_immediate_char(struct jsm_channel * ch,unsigned char c)950*4882a593Smuzhiyun static void cls_send_immediate_char(struct jsm_channel *ch, unsigned char c)
951*4882a593Smuzhiyun {
952*4882a593Smuzhiyun writeb(c, &ch->ch_cls_uart->txrx);
953*4882a593Smuzhiyun }
954*4882a593Smuzhiyun
955*4882a593Smuzhiyun struct board_ops jsm_cls_ops = {
956*4882a593Smuzhiyun .intr = cls_intr,
957*4882a593Smuzhiyun .uart_init = cls_uart_init,
958*4882a593Smuzhiyun .uart_off = cls_uart_off,
959*4882a593Smuzhiyun .param = cls_param,
960*4882a593Smuzhiyun .assert_modem_signals = cls_assert_modem_signals,
961*4882a593Smuzhiyun .flush_uart_write = cls_flush_uart_write,
962*4882a593Smuzhiyun .flush_uart_read = cls_flush_uart_read,
963*4882a593Smuzhiyun .disable_receiver = cls_disable_receiver,
964*4882a593Smuzhiyun .enable_receiver = cls_enable_receiver,
965*4882a593Smuzhiyun .send_break = cls_send_break,
966*4882a593Smuzhiyun .clear_break = cls_clear_break,
967*4882a593Smuzhiyun .send_start_character = cls_send_start_character,
968*4882a593Smuzhiyun .send_stop_character = cls_send_stop_character,
969*4882a593Smuzhiyun .copy_data_from_queue_to_uart = cls_copy_data_from_queue_to_uart,
970*4882a593Smuzhiyun .get_uart_bytes_left = cls_get_uart_bytes_left,
971*4882a593Smuzhiyun .send_immediate_char = cls_send_immediate_char
972*4882a593Smuzhiyun };
973*4882a593Smuzhiyun
974