xref: /OK3568_Linux_fs/kernel/drivers/tty/serial/vr41xx_siu.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *  Driver for NEC VR4100 series Serial Interface Unit.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  *  Copyright (C) 2004-2008  Yoichi Yuasa <yuasa@linux-mips.org>
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  *  Based on drivers/serial/8250.c, by Russell King.
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/console.h>
11*4882a593Smuzhiyun #include <linux/errno.h>
12*4882a593Smuzhiyun #include <linux/init.h>
13*4882a593Smuzhiyun #include <linux/interrupt.h>
14*4882a593Smuzhiyun #include <linux/ioport.h>
15*4882a593Smuzhiyun #include <linux/module.h>
16*4882a593Smuzhiyun #include <linux/platform_device.h>
17*4882a593Smuzhiyun #include <linux/serial.h>
18*4882a593Smuzhiyun #include <linux/serial_core.h>
19*4882a593Smuzhiyun #include <linux/serial_reg.h>
20*4882a593Smuzhiyun #include <linux/tty.h>
21*4882a593Smuzhiyun #include <linux/tty_flip.h>
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #include <asm/io.h>
24*4882a593Smuzhiyun #include <asm/vr41xx/siu.h>
25*4882a593Smuzhiyun #include <asm/vr41xx/vr41xx.h>
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #define SIU_BAUD_BASE	1152000
28*4882a593Smuzhiyun #define SIU_MAJOR	204
29*4882a593Smuzhiyun #define SIU_MINOR_BASE	82
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #define RX_MAX_COUNT	256
32*4882a593Smuzhiyun #define TX_MAX_COUNT	15
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #define SIUIRSEL	0x08
35*4882a593Smuzhiyun  #define TMICMODE	0x20
36*4882a593Smuzhiyun  #define TMICTX		0x10
37*4882a593Smuzhiyun  #define IRMSEL		0x0c
38*4882a593Smuzhiyun  #define IRMSEL_HP	0x08
39*4882a593Smuzhiyun  #define IRMSEL_TEMIC	0x04
40*4882a593Smuzhiyun  #define IRMSEL_SHARP	0x00
41*4882a593Smuzhiyun  #define IRUSESEL	0x02
42*4882a593Smuzhiyun  #define SIRSEL		0x01
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun static struct uart_port siu_uart_ports[SIU_PORTS_MAX] = {
45*4882a593Smuzhiyun 	[0 ... SIU_PORTS_MAX-1] = {
46*4882a593Smuzhiyun 		.lock	= __SPIN_LOCK_UNLOCKED(siu_uart_ports->lock),
47*4882a593Smuzhiyun 		.irq	= 0,
48*4882a593Smuzhiyun 	},
49*4882a593Smuzhiyun };
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun #ifdef CONFIG_SERIAL_VR41XX_CONSOLE
52*4882a593Smuzhiyun static uint8_t lsr_break_flag[SIU_PORTS_MAX];
53*4882a593Smuzhiyun #endif
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun #define siu_read(port, offset)		readb((port)->membase + (offset))
56*4882a593Smuzhiyun #define siu_write(port, offset, value)	writeb((value), (port)->membase + (offset))
57*4882a593Smuzhiyun 
vr41xx_select_siu_interface(siu_interface_t interface)58*4882a593Smuzhiyun void vr41xx_select_siu_interface(siu_interface_t interface)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun 	struct uart_port *port;
61*4882a593Smuzhiyun 	unsigned long flags;
62*4882a593Smuzhiyun 	uint8_t irsel;
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	port = &siu_uart_ports[0];
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	spin_lock_irqsave(&port->lock, flags);
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	irsel = siu_read(port, SIUIRSEL);
69*4882a593Smuzhiyun 	if (interface == SIU_INTERFACE_IRDA)
70*4882a593Smuzhiyun 		irsel |= SIRSEL;
71*4882a593Smuzhiyun 	else
72*4882a593Smuzhiyun 		irsel &= ~SIRSEL;
73*4882a593Smuzhiyun 	siu_write(port, SIUIRSEL, irsel);
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	spin_unlock_irqrestore(&port->lock, flags);
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(vr41xx_select_siu_interface);
78*4882a593Smuzhiyun 
vr41xx_use_irda(irda_use_t use)79*4882a593Smuzhiyun void vr41xx_use_irda(irda_use_t use)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun 	struct uart_port *port;
82*4882a593Smuzhiyun 	unsigned long flags;
83*4882a593Smuzhiyun 	uint8_t irsel;
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	port = &siu_uart_ports[0];
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	spin_lock_irqsave(&port->lock, flags);
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	irsel = siu_read(port, SIUIRSEL);
90*4882a593Smuzhiyun 	if (use == FIR_USE_IRDA)
91*4882a593Smuzhiyun 		irsel |= IRUSESEL;
92*4882a593Smuzhiyun 	else
93*4882a593Smuzhiyun 		irsel &= ~IRUSESEL;
94*4882a593Smuzhiyun 	siu_write(port, SIUIRSEL, irsel);
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	spin_unlock_irqrestore(&port->lock, flags);
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(vr41xx_use_irda);
99*4882a593Smuzhiyun 
vr41xx_select_irda_module(irda_module_t module,irda_speed_t speed)100*4882a593Smuzhiyun void vr41xx_select_irda_module(irda_module_t module, irda_speed_t speed)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun 	struct uart_port *port;
103*4882a593Smuzhiyun 	unsigned long flags;
104*4882a593Smuzhiyun 	uint8_t irsel;
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	port = &siu_uart_ports[0];
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	spin_lock_irqsave(&port->lock, flags);
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	irsel = siu_read(port, SIUIRSEL);
111*4882a593Smuzhiyun 	irsel &= ~(IRMSEL | TMICTX | TMICMODE);
112*4882a593Smuzhiyun 	switch (module) {
113*4882a593Smuzhiyun 	case SHARP_IRDA:
114*4882a593Smuzhiyun 		irsel |= IRMSEL_SHARP;
115*4882a593Smuzhiyun 		break;
116*4882a593Smuzhiyun 	case TEMIC_IRDA:
117*4882a593Smuzhiyun 		irsel |= IRMSEL_TEMIC | TMICMODE;
118*4882a593Smuzhiyun 		if (speed == IRDA_TX_4MBPS)
119*4882a593Smuzhiyun 			irsel |= TMICTX;
120*4882a593Smuzhiyun 		break;
121*4882a593Smuzhiyun 	case HP_IRDA:
122*4882a593Smuzhiyun 		irsel |= IRMSEL_HP;
123*4882a593Smuzhiyun 		break;
124*4882a593Smuzhiyun 	default:
125*4882a593Smuzhiyun 		break;
126*4882a593Smuzhiyun 	}
127*4882a593Smuzhiyun 	siu_write(port, SIUIRSEL, irsel);
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	spin_unlock_irqrestore(&port->lock, flags);
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(vr41xx_select_irda_module);
132*4882a593Smuzhiyun 
siu_clear_fifo(struct uart_port * port)133*4882a593Smuzhiyun static inline void siu_clear_fifo(struct uart_port *port)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun 	siu_write(port, UART_FCR, UART_FCR_ENABLE_FIFO);
136*4882a593Smuzhiyun 	siu_write(port, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR |
137*4882a593Smuzhiyun 	                          UART_FCR_CLEAR_XMIT);
138*4882a593Smuzhiyun 	siu_write(port, UART_FCR, 0);
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun 
siu_port_size(struct uart_port * port)141*4882a593Smuzhiyun static inline unsigned long siu_port_size(struct uart_port *port)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun 	switch (port->type) {
144*4882a593Smuzhiyun 	case PORT_VR41XX_SIU:
145*4882a593Smuzhiyun 		return 11UL;
146*4882a593Smuzhiyun 	case PORT_VR41XX_DSIU:
147*4882a593Smuzhiyun 		return 8UL;
148*4882a593Smuzhiyun 	}
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	return 0;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun 
siu_check_type(struct uart_port * port)153*4882a593Smuzhiyun static inline unsigned int siu_check_type(struct uart_port *port)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun 	if (port->line == 0)
156*4882a593Smuzhiyun 		return PORT_VR41XX_SIU;
157*4882a593Smuzhiyun 	if (port->line == 1 && port->irq)
158*4882a593Smuzhiyun 		return PORT_VR41XX_DSIU;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	return PORT_UNKNOWN;
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun 
siu_type_name(struct uart_port * port)163*4882a593Smuzhiyun static inline const char *siu_type_name(struct uart_port *port)
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun 	switch (port->type) {
166*4882a593Smuzhiyun 	case PORT_VR41XX_SIU:
167*4882a593Smuzhiyun 		return "SIU";
168*4882a593Smuzhiyun 	case PORT_VR41XX_DSIU:
169*4882a593Smuzhiyun 		return "DSIU";
170*4882a593Smuzhiyun 	}
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	return NULL;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun 
siu_tx_empty(struct uart_port * port)175*4882a593Smuzhiyun static unsigned int siu_tx_empty(struct uart_port *port)
176*4882a593Smuzhiyun {
177*4882a593Smuzhiyun 	uint8_t lsr;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	lsr = siu_read(port, UART_LSR);
180*4882a593Smuzhiyun 	if (lsr & UART_LSR_TEMT)
181*4882a593Smuzhiyun 		return TIOCSER_TEMT;
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	return 0;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun 
siu_set_mctrl(struct uart_port * port,unsigned int mctrl)186*4882a593Smuzhiyun static void siu_set_mctrl(struct uart_port *port, unsigned int mctrl)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun 	uint8_t mcr = 0;
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	if (mctrl & TIOCM_DTR)
191*4882a593Smuzhiyun 		mcr |= UART_MCR_DTR;
192*4882a593Smuzhiyun 	if (mctrl & TIOCM_RTS)
193*4882a593Smuzhiyun 		mcr |= UART_MCR_RTS;
194*4882a593Smuzhiyun 	if (mctrl & TIOCM_OUT1)
195*4882a593Smuzhiyun 		mcr |= UART_MCR_OUT1;
196*4882a593Smuzhiyun 	if (mctrl & TIOCM_OUT2)
197*4882a593Smuzhiyun 		mcr |= UART_MCR_OUT2;
198*4882a593Smuzhiyun 	if (mctrl & TIOCM_LOOP)
199*4882a593Smuzhiyun 		mcr |= UART_MCR_LOOP;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	siu_write(port, UART_MCR, mcr);
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun 
siu_get_mctrl(struct uart_port * port)204*4882a593Smuzhiyun static unsigned int siu_get_mctrl(struct uart_port *port)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun 	uint8_t msr;
207*4882a593Smuzhiyun 	unsigned int mctrl = 0;
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	msr = siu_read(port, UART_MSR);
210*4882a593Smuzhiyun 	if (msr & UART_MSR_DCD)
211*4882a593Smuzhiyun 		mctrl |= TIOCM_CAR;
212*4882a593Smuzhiyun 	if (msr & UART_MSR_RI)
213*4882a593Smuzhiyun 		mctrl |= TIOCM_RNG;
214*4882a593Smuzhiyun 	if (msr & UART_MSR_DSR)
215*4882a593Smuzhiyun 		mctrl |= TIOCM_DSR;
216*4882a593Smuzhiyun 	if (msr & UART_MSR_CTS)
217*4882a593Smuzhiyun 		mctrl |= TIOCM_CTS;
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	return mctrl;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun 
siu_stop_tx(struct uart_port * port)222*4882a593Smuzhiyun static void siu_stop_tx(struct uart_port *port)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun 	unsigned long flags;
225*4882a593Smuzhiyun 	uint8_t ier;
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	spin_lock_irqsave(&port->lock, flags);
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	ier = siu_read(port, UART_IER);
230*4882a593Smuzhiyun 	ier &= ~UART_IER_THRI;
231*4882a593Smuzhiyun 	siu_write(port, UART_IER, ier);
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	spin_unlock_irqrestore(&port->lock, flags);
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun 
siu_start_tx(struct uart_port * port)236*4882a593Smuzhiyun static void siu_start_tx(struct uart_port *port)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun 	unsigned long flags;
239*4882a593Smuzhiyun 	uint8_t ier;
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	spin_lock_irqsave(&port->lock, flags);
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	ier = siu_read(port, UART_IER);
244*4882a593Smuzhiyun 	ier |= UART_IER_THRI;
245*4882a593Smuzhiyun 	siu_write(port, UART_IER, ier);
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	spin_unlock_irqrestore(&port->lock, flags);
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun 
siu_stop_rx(struct uart_port * port)250*4882a593Smuzhiyun static void siu_stop_rx(struct uart_port *port)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun 	unsigned long flags;
253*4882a593Smuzhiyun 	uint8_t ier;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	spin_lock_irqsave(&port->lock, flags);
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	ier = siu_read(port, UART_IER);
258*4882a593Smuzhiyun 	ier &= ~UART_IER_RLSI;
259*4882a593Smuzhiyun 	siu_write(port, UART_IER, ier);
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	port->read_status_mask &= ~UART_LSR_DR;
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	spin_unlock_irqrestore(&port->lock, flags);
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun 
siu_enable_ms(struct uart_port * port)266*4882a593Smuzhiyun static void siu_enable_ms(struct uart_port *port)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun 	unsigned long flags;
269*4882a593Smuzhiyun 	uint8_t ier;
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	spin_lock_irqsave(&port->lock, flags);
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	ier = siu_read(port, UART_IER);
274*4882a593Smuzhiyun 	ier |= UART_IER_MSI;
275*4882a593Smuzhiyun 	siu_write(port, UART_IER, ier);
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 	spin_unlock_irqrestore(&port->lock, flags);
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun 
siu_break_ctl(struct uart_port * port,int ctl)280*4882a593Smuzhiyun static void siu_break_ctl(struct uart_port *port, int ctl)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun 	unsigned long flags;
283*4882a593Smuzhiyun 	uint8_t lcr;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	spin_lock_irqsave(&port->lock, flags);
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 	lcr = siu_read(port, UART_LCR);
288*4882a593Smuzhiyun 	if (ctl == -1)
289*4882a593Smuzhiyun 		lcr |= UART_LCR_SBC;
290*4882a593Smuzhiyun 	else
291*4882a593Smuzhiyun 		lcr &= ~UART_LCR_SBC;
292*4882a593Smuzhiyun 	siu_write(port, UART_LCR, lcr);
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	spin_unlock_irqrestore(&port->lock, flags);
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun 
receive_chars(struct uart_port * port,uint8_t * status)297*4882a593Smuzhiyun static inline void receive_chars(struct uart_port *port, uint8_t *status)
298*4882a593Smuzhiyun {
299*4882a593Smuzhiyun 	uint8_t lsr, ch;
300*4882a593Smuzhiyun 	char flag;
301*4882a593Smuzhiyun 	int max_count = RX_MAX_COUNT;
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun 	lsr = *status;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	do {
306*4882a593Smuzhiyun 		ch = siu_read(port, UART_RX);
307*4882a593Smuzhiyun 		port->icount.rx++;
308*4882a593Smuzhiyun 		flag = TTY_NORMAL;
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun #ifdef CONFIG_SERIAL_VR41XX_CONSOLE
311*4882a593Smuzhiyun 		lsr |= lsr_break_flag[port->line];
312*4882a593Smuzhiyun 		lsr_break_flag[port->line] = 0;
313*4882a593Smuzhiyun #endif
314*4882a593Smuzhiyun 		if (unlikely(lsr & (UART_LSR_BI | UART_LSR_FE |
315*4882a593Smuzhiyun 		                    UART_LSR_PE | UART_LSR_OE))) {
316*4882a593Smuzhiyun 			if (lsr & UART_LSR_BI) {
317*4882a593Smuzhiyun 				lsr &= ~(UART_LSR_FE | UART_LSR_PE);
318*4882a593Smuzhiyun 				port->icount.brk++;
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 				if (uart_handle_break(port))
321*4882a593Smuzhiyun 					goto ignore_char;
322*4882a593Smuzhiyun 			}
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 			if (lsr & UART_LSR_FE)
325*4882a593Smuzhiyun 				port->icount.frame++;
326*4882a593Smuzhiyun 			if (lsr & UART_LSR_PE)
327*4882a593Smuzhiyun 				port->icount.parity++;
328*4882a593Smuzhiyun 			if (lsr & UART_LSR_OE)
329*4882a593Smuzhiyun 				port->icount.overrun++;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 			lsr &= port->read_status_mask;
332*4882a593Smuzhiyun 			if (lsr & UART_LSR_BI)
333*4882a593Smuzhiyun 				flag = TTY_BREAK;
334*4882a593Smuzhiyun 			if (lsr & UART_LSR_FE)
335*4882a593Smuzhiyun 				flag = TTY_FRAME;
336*4882a593Smuzhiyun 			if (lsr & UART_LSR_PE)
337*4882a593Smuzhiyun 				flag = TTY_PARITY;
338*4882a593Smuzhiyun 		}
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 		if (uart_handle_sysrq_char(port, ch))
341*4882a593Smuzhiyun 			goto ignore_char;
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 		uart_insert_char(port, lsr, UART_LSR_OE, ch, flag);
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	ignore_char:
346*4882a593Smuzhiyun 		lsr = siu_read(port, UART_LSR);
347*4882a593Smuzhiyun 	} while ((lsr & UART_LSR_DR) && (max_count-- > 0));
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	tty_flip_buffer_push(&port->state->port);
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	*status = lsr;
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun 
check_modem_status(struct uart_port * port)354*4882a593Smuzhiyun static inline void check_modem_status(struct uart_port *port)
355*4882a593Smuzhiyun {
356*4882a593Smuzhiyun 	uint8_t msr;
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	msr = siu_read(port, UART_MSR);
359*4882a593Smuzhiyun 	if ((msr & UART_MSR_ANY_DELTA) == 0)
360*4882a593Smuzhiyun 		return;
361*4882a593Smuzhiyun 	if (msr & UART_MSR_DDCD)
362*4882a593Smuzhiyun 		uart_handle_dcd_change(port, msr & UART_MSR_DCD);
363*4882a593Smuzhiyun 	if (msr & UART_MSR_TERI)
364*4882a593Smuzhiyun 		port->icount.rng++;
365*4882a593Smuzhiyun 	if (msr & UART_MSR_DDSR)
366*4882a593Smuzhiyun 		port->icount.dsr++;
367*4882a593Smuzhiyun 	if (msr & UART_MSR_DCTS)
368*4882a593Smuzhiyun 		uart_handle_cts_change(port, msr & UART_MSR_CTS);
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 	wake_up_interruptible(&port->state->port.delta_msr_wait);
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun 
transmit_chars(struct uart_port * port)373*4882a593Smuzhiyun static inline void transmit_chars(struct uart_port *port)
374*4882a593Smuzhiyun {
375*4882a593Smuzhiyun 	struct circ_buf *xmit;
376*4882a593Smuzhiyun 	int max_count = TX_MAX_COUNT;
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	xmit = &port->state->xmit;
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	if (port->x_char) {
381*4882a593Smuzhiyun 		siu_write(port, UART_TX, port->x_char);
382*4882a593Smuzhiyun 		port->icount.tx++;
383*4882a593Smuzhiyun 		port->x_char = 0;
384*4882a593Smuzhiyun 		return;
385*4882a593Smuzhiyun 	}
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
388*4882a593Smuzhiyun 		siu_stop_tx(port);
389*4882a593Smuzhiyun 		return;
390*4882a593Smuzhiyun 	}
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	do {
393*4882a593Smuzhiyun 		siu_write(port, UART_TX, xmit->buf[xmit->tail]);
394*4882a593Smuzhiyun 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
395*4882a593Smuzhiyun 		port->icount.tx++;
396*4882a593Smuzhiyun 		if (uart_circ_empty(xmit))
397*4882a593Smuzhiyun 			break;
398*4882a593Smuzhiyun 	} while (max_count-- > 0);
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
401*4882a593Smuzhiyun 		uart_write_wakeup(port);
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 	if (uart_circ_empty(xmit))
404*4882a593Smuzhiyun 		siu_stop_tx(port);
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun 
siu_interrupt(int irq,void * dev_id)407*4882a593Smuzhiyun static irqreturn_t siu_interrupt(int irq, void *dev_id)
408*4882a593Smuzhiyun {
409*4882a593Smuzhiyun 	struct uart_port *port;
410*4882a593Smuzhiyun 	uint8_t iir, lsr;
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun 	port = (struct uart_port *)dev_id;
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	iir = siu_read(port, UART_IIR);
415*4882a593Smuzhiyun 	if (iir & UART_IIR_NO_INT)
416*4882a593Smuzhiyun 		return IRQ_NONE;
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 	lsr = siu_read(port, UART_LSR);
419*4882a593Smuzhiyun 	if (lsr & UART_LSR_DR)
420*4882a593Smuzhiyun 		receive_chars(port, &lsr);
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 	check_modem_status(port);
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	if (lsr & UART_LSR_THRE)
425*4882a593Smuzhiyun 		transmit_chars(port);
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun 	return IRQ_HANDLED;
428*4882a593Smuzhiyun }
429*4882a593Smuzhiyun 
siu_startup(struct uart_port * port)430*4882a593Smuzhiyun static int siu_startup(struct uart_port *port)
431*4882a593Smuzhiyun {
432*4882a593Smuzhiyun 	int retval;
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 	if (port->membase == NULL)
435*4882a593Smuzhiyun 		return -ENODEV;
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 	siu_clear_fifo(port);
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 	(void)siu_read(port, UART_LSR);
440*4882a593Smuzhiyun 	(void)siu_read(port, UART_RX);
441*4882a593Smuzhiyun 	(void)siu_read(port, UART_IIR);
442*4882a593Smuzhiyun 	(void)siu_read(port, UART_MSR);
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	if (siu_read(port, UART_LSR) == 0xff)
445*4882a593Smuzhiyun 		return -ENODEV;
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	retval = request_irq(port->irq, siu_interrupt, 0, siu_type_name(port), port);
448*4882a593Smuzhiyun 	if (retval)
449*4882a593Smuzhiyun 		return retval;
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun 	if (port->type == PORT_VR41XX_DSIU)
452*4882a593Smuzhiyun 		vr41xx_enable_dsiuint(DSIUINT_ALL);
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun 	siu_write(port, UART_LCR, UART_LCR_WLEN8);
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun 	spin_lock_irq(&port->lock);
457*4882a593Smuzhiyun 	siu_set_mctrl(port, port->mctrl);
458*4882a593Smuzhiyun 	spin_unlock_irq(&port->lock);
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 	siu_write(port, UART_IER, UART_IER_RLSI | UART_IER_RDI);
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	(void)siu_read(port, UART_LSR);
463*4882a593Smuzhiyun 	(void)siu_read(port, UART_RX);
464*4882a593Smuzhiyun 	(void)siu_read(port, UART_IIR);
465*4882a593Smuzhiyun 	(void)siu_read(port, UART_MSR);
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 	return 0;
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun 
siu_shutdown(struct uart_port * port)470*4882a593Smuzhiyun static void siu_shutdown(struct uart_port *port)
471*4882a593Smuzhiyun {
472*4882a593Smuzhiyun 	unsigned long flags;
473*4882a593Smuzhiyun 	uint8_t lcr;
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	siu_write(port, UART_IER, 0);
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 	spin_lock_irqsave(&port->lock, flags);
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 	port->mctrl &= ~TIOCM_OUT2;
480*4882a593Smuzhiyun 	siu_set_mctrl(port, port->mctrl);
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 	spin_unlock_irqrestore(&port->lock, flags);
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	lcr = siu_read(port, UART_LCR);
485*4882a593Smuzhiyun 	lcr &= ~UART_LCR_SBC;
486*4882a593Smuzhiyun 	siu_write(port, UART_LCR, lcr);
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	siu_clear_fifo(port);
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 	(void)siu_read(port, UART_RX);
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 	if (port->type == PORT_VR41XX_DSIU)
493*4882a593Smuzhiyun 		vr41xx_disable_dsiuint(DSIUINT_ALL);
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun 	free_irq(port->irq, port);
496*4882a593Smuzhiyun }
497*4882a593Smuzhiyun 
siu_set_termios(struct uart_port * port,struct ktermios * new,struct ktermios * old)498*4882a593Smuzhiyun static void siu_set_termios(struct uart_port *port, struct ktermios *new,
499*4882a593Smuzhiyun                             struct ktermios *old)
500*4882a593Smuzhiyun {
501*4882a593Smuzhiyun 	tcflag_t c_cflag, c_iflag;
502*4882a593Smuzhiyun 	uint8_t lcr, fcr, ier;
503*4882a593Smuzhiyun 	unsigned int baud, quot;
504*4882a593Smuzhiyun 	unsigned long flags;
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	c_cflag = new->c_cflag;
507*4882a593Smuzhiyun 	switch (c_cflag & CSIZE) {
508*4882a593Smuzhiyun 	case CS5:
509*4882a593Smuzhiyun 		lcr = UART_LCR_WLEN5;
510*4882a593Smuzhiyun 		break;
511*4882a593Smuzhiyun 	case CS6:
512*4882a593Smuzhiyun 		lcr = UART_LCR_WLEN6;
513*4882a593Smuzhiyun 		break;
514*4882a593Smuzhiyun 	case CS7:
515*4882a593Smuzhiyun 		lcr = UART_LCR_WLEN7;
516*4882a593Smuzhiyun 		break;
517*4882a593Smuzhiyun 	default:
518*4882a593Smuzhiyun 		lcr = UART_LCR_WLEN8;
519*4882a593Smuzhiyun 		break;
520*4882a593Smuzhiyun 	}
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun 	if (c_cflag & CSTOPB)
523*4882a593Smuzhiyun 		lcr |= UART_LCR_STOP;
524*4882a593Smuzhiyun 	if (c_cflag & PARENB)
525*4882a593Smuzhiyun 		lcr |= UART_LCR_PARITY;
526*4882a593Smuzhiyun 	if ((c_cflag & PARODD) != PARODD)
527*4882a593Smuzhiyun 		lcr |= UART_LCR_EPAR;
528*4882a593Smuzhiyun 	if (c_cflag & CMSPAR)
529*4882a593Smuzhiyun 		lcr |= UART_LCR_SPAR;
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun 	baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16);
532*4882a593Smuzhiyun 	quot = uart_get_divisor(port, baud);
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun 	fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10;
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun 	spin_lock_irqsave(&port->lock, flags);
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun 	uart_update_timeout(port, c_cflag, baud);
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun 	c_iflag = new->c_iflag;
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun 	port->read_status_mask = UART_LSR_THRE | UART_LSR_OE | UART_LSR_DR;
543*4882a593Smuzhiyun 	if (c_iflag & INPCK)
544*4882a593Smuzhiyun 		port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
545*4882a593Smuzhiyun 	if (c_iflag & (IGNBRK | BRKINT | PARMRK))
546*4882a593Smuzhiyun 		port->read_status_mask |= UART_LSR_BI;
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun 	port->ignore_status_mask = 0;
549*4882a593Smuzhiyun 	if (c_iflag & IGNPAR)
550*4882a593Smuzhiyun 		port->ignore_status_mask |= UART_LSR_FE | UART_LSR_PE;
551*4882a593Smuzhiyun 	if (c_iflag & IGNBRK) {
552*4882a593Smuzhiyun 		port->ignore_status_mask |= UART_LSR_BI;
553*4882a593Smuzhiyun 		if (c_iflag & IGNPAR)
554*4882a593Smuzhiyun 			port->ignore_status_mask |= UART_LSR_OE;
555*4882a593Smuzhiyun 	}
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 	if ((c_cflag & CREAD) == 0)
558*4882a593Smuzhiyun 		port->ignore_status_mask |= UART_LSR_DR;
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun 	ier = siu_read(port, UART_IER);
561*4882a593Smuzhiyun 	ier &= ~UART_IER_MSI;
562*4882a593Smuzhiyun 	if (UART_ENABLE_MS(port, c_cflag))
563*4882a593Smuzhiyun 		ier |= UART_IER_MSI;
564*4882a593Smuzhiyun 	siu_write(port, UART_IER, ier);
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun 	siu_write(port, UART_LCR, lcr | UART_LCR_DLAB);
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun 	siu_write(port, UART_DLL, (uint8_t)quot);
569*4882a593Smuzhiyun 	siu_write(port, UART_DLM, (uint8_t)(quot >> 8));
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun 	siu_write(port, UART_LCR, lcr);
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun 	siu_write(port, UART_FCR, fcr);
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun 	siu_set_mctrl(port, port->mctrl);
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun 	spin_unlock_irqrestore(&port->lock, flags);
578*4882a593Smuzhiyun }
579*4882a593Smuzhiyun 
siu_pm(struct uart_port * port,unsigned int state,unsigned int oldstate)580*4882a593Smuzhiyun static void siu_pm(struct uart_port *port, unsigned int state, unsigned int oldstate)
581*4882a593Smuzhiyun {
582*4882a593Smuzhiyun 	switch (state) {
583*4882a593Smuzhiyun 	case 0:
584*4882a593Smuzhiyun 		switch (port->type) {
585*4882a593Smuzhiyun 		case PORT_VR41XX_SIU:
586*4882a593Smuzhiyun 			vr41xx_supply_clock(SIU_CLOCK);
587*4882a593Smuzhiyun 			break;
588*4882a593Smuzhiyun 		case PORT_VR41XX_DSIU:
589*4882a593Smuzhiyun 			vr41xx_supply_clock(DSIU_CLOCK);
590*4882a593Smuzhiyun 			break;
591*4882a593Smuzhiyun 		}
592*4882a593Smuzhiyun 		break;
593*4882a593Smuzhiyun 	case 3:
594*4882a593Smuzhiyun 		switch (port->type) {
595*4882a593Smuzhiyun 		case PORT_VR41XX_SIU:
596*4882a593Smuzhiyun 			vr41xx_mask_clock(SIU_CLOCK);
597*4882a593Smuzhiyun 			break;
598*4882a593Smuzhiyun 		case PORT_VR41XX_DSIU:
599*4882a593Smuzhiyun 			vr41xx_mask_clock(DSIU_CLOCK);
600*4882a593Smuzhiyun 			break;
601*4882a593Smuzhiyun 		}
602*4882a593Smuzhiyun 		break;
603*4882a593Smuzhiyun 	}
604*4882a593Smuzhiyun }
605*4882a593Smuzhiyun 
siu_type(struct uart_port * port)606*4882a593Smuzhiyun static const char *siu_type(struct uart_port *port)
607*4882a593Smuzhiyun {
608*4882a593Smuzhiyun 	return siu_type_name(port);
609*4882a593Smuzhiyun }
610*4882a593Smuzhiyun 
siu_release_port(struct uart_port * port)611*4882a593Smuzhiyun static void siu_release_port(struct uart_port *port)
612*4882a593Smuzhiyun {
613*4882a593Smuzhiyun 	unsigned long size;
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun 	if (port->flags	& UPF_IOREMAP) {
616*4882a593Smuzhiyun 		iounmap(port->membase);
617*4882a593Smuzhiyun 		port->membase = NULL;
618*4882a593Smuzhiyun 	}
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun 	size = siu_port_size(port);
621*4882a593Smuzhiyun 	release_mem_region(port->mapbase, size);
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun 
siu_request_port(struct uart_port * port)624*4882a593Smuzhiyun static int siu_request_port(struct uart_port *port)
625*4882a593Smuzhiyun {
626*4882a593Smuzhiyun 	unsigned long size;
627*4882a593Smuzhiyun 	struct resource *res;
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun 	size = siu_port_size(port);
630*4882a593Smuzhiyun 	res = request_mem_region(port->mapbase, size, siu_type_name(port));
631*4882a593Smuzhiyun 	if (res == NULL)
632*4882a593Smuzhiyun 		return -EBUSY;
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun 	if (port->flags & UPF_IOREMAP) {
635*4882a593Smuzhiyun 		port->membase = ioremap(port->mapbase, size);
636*4882a593Smuzhiyun 		if (port->membase == NULL) {
637*4882a593Smuzhiyun 			release_resource(res);
638*4882a593Smuzhiyun 			return -ENOMEM;
639*4882a593Smuzhiyun 		}
640*4882a593Smuzhiyun 	}
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun 	return 0;
643*4882a593Smuzhiyun }
644*4882a593Smuzhiyun 
siu_config_port(struct uart_port * port,int flags)645*4882a593Smuzhiyun static void siu_config_port(struct uart_port *port, int flags)
646*4882a593Smuzhiyun {
647*4882a593Smuzhiyun 	if (flags & UART_CONFIG_TYPE) {
648*4882a593Smuzhiyun 		port->type = siu_check_type(port);
649*4882a593Smuzhiyun 		(void)siu_request_port(port);
650*4882a593Smuzhiyun 	}
651*4882a593Smuzhiyun }
652*4882a593Smuzhiyun 
siu_verify_port(struct uart_port * port,struct serial_struct * serial)653*4882a593Smuzhiyun static int siu_verify_port(struct uart_port *port, struct serial_struct *serial)
654*4882a593Smuzhiyun {
655*4882a593Smuzhiyun 	if (port->type != PORT_VR41XX_SIU && port->type != PORT_VR41XX_DSIU)
656*4882a593Smuzhiyun 		return -EINVAL;
657*4882a593Smuzhiyun 	if (port->irq != serial->irq)
658*4882a593Smuzhiyun 		return -EINVAL;
659*4882a593Smuzhiyun 	if (port->iotype != serial->io_type)
660*4882a593Smuzhiyun 		return -EINVAL;
661*4882a593Smuzhiyun 	if (port->mapbase != (unsigned long)serial->iomem_base)
662*4882a593Smuzhiyun 		return -EINVAL;
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun 	return 0;
665*4882a593Smuzhiyun }
666*4882a593Smuzhiyun 
667*4882a593Smuzhiyun static const struct uart_ops siu_uart_ops = {
668*4882a593Smuzhiyun 	.tx_empty	= siu_tx_empty,
669*4882a593Smuzhiyun 	.set_mctrl	= siu_set_mctrl,
670*4882a593Smuzhiyun 	.get_mctrl	= siu_get_mctrl,
671*4882a593Smuzhiyun 	.stop_tx	= siu_stop_tx,
672*4882a593Smuzhiyun 	.start_tx	= siu_start_tx,
673*4882a593Smuzhiyun 	.stop_rx	= siu_stop_rx,
674*4882a593Smuzhiyun 	.enable_ms	= siu_enable_ms,
675*4882a593Smuzhiyun 	.break_ctl	= siu_break_ctl,
676*4882a593Smuzhiyun 	.startup	= siu_startup,
677*4882a593Smuzhiyun 	.shutdown	= siu_shutdown,
678*4882a593Smuzhiyun 	.set_termios	= siu_set_termios,
679*4882a593Smuzhiyun 	.pm		= siu_pm,
680*4882a593Smuzhiyun 	.type		= siu_type,
681*4882a593Smuzhiyun 	.release_port	= siu_release_port,
682*4882a593Smuzhiyun 	.request_port	= siu_request_port,
683*4882a593Smuzhiyun 	.config_port	= siu_config_port,
684*4882a593Smuzhiyun 	.verify_port	= siu_verify_port,
685*4882a593Smuzhiyun };
686*4882a593Smuzhiyun 
siu_init_ports(struct platform_device * pdev)687*4882a593Smuzhiyun static int siu_init_ports(struct platform_device *pdev)
688*4882a593Smuzhiyun {
689*4882a593Smuzhiyun 	struct uart_port *port;
690*4882a593Smuzhiyun 	struct resource *res;
691*4882a593Smuzhiyun 	int *type = dev_get_platdata(&pdev->dev);
692*4882a593Smuzhiyun 	int i;
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun 	if (!type)
695*4882a593Smuzhiyun 		return 0;
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun 	port = siu_uart_ports;
698*4882a593Smuzhiyun 	for (i = 0; i < SIU_PORTS_MAX; i++) {
699*4882a593Smuzhiyun 		port->type = type[i];
700*4882a593Smuzhiyun 		if (port->type == PORT_UNKNOWN)
701*4882a593Smuzhiyun 			continue;
702*4882a593Smuzhiyun 		port->irq = platform_get_irq(pdev, i);
703*4882a593Smuzhiyun 		port->uartclk = SIU_BAUD_BASE * 16;
704*4882a593Smuzhiyun 		port->fifosize = 16;
705*4882a593Smuzhiyun 		port->regshift = 0;
706*4882a593Smuzhiyun 		port->iotype = UPIO_MEM;
707*4882a593Smuzhiyun 		port->flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
708*4882a593Smuzhiyun 		port->line = i;
709*4882a593Smuzhiyun 		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
710*4882a593Smuzhiyun 		port->mapbase = res->start;
711*4882a593Smuzhiyun 		port++;
712*4882a593Smuzhiyun 	}
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun 	return i;
715*4882a593Smuzhiyun }
716*4882a593Smuzhiyun 
717*4882a593Smuzhiyun #ifdef CONFIG_SERIAL_VR41XX_CONSOLE
718*4882a593Smuzhiyun 
719*4882a593Smuzhiyun #define BOTH_EMPTY	(UART_LSR_TEMT | UART_LSR_THRE)
720*4882a593Smuzhiyun 
wait_for_xmitr(struct uart_port * port)721*4882a593Smuzhiyun static void wait_for_xmitr(struct uart_port *port)
722*4882a593Smuzhiyun {
723*4882a593Smuzhiyun 	int timeout = 10000;
724*4882a593Smuzhiyun 	uint8_t lsr, msr;
725*4882a593Smuzhiyun 
726*4882a593Smuzhiyun 	do {
727*4882a593Smuzhiyun 		lsr = siu_read(port, UART_LSR);
728*4882a593Smuzhiyun 		if (lsr & UART_LSR_BI)
729*4882a593Smuzhiyun 			lsr_break_flag[port->line] = UART_LSR_BI;
730*4882a593Smuzhiyun 
731*4882a593Smuzhiyun 		if ((lsr & BOTH_EMPTY) == BOTH_EMPTY)
732*4882a593Smuzhiyun 			break;
733*4882a593Smuzhiyun 	} while (timeout-- > 0);
734*4882a593Smuzhiyun 
735*4882a593Smuzhiyun 	if (port->flags & UPF_CONS_FLOW) {
736*4882a593Smuzhiyun 		timeout = 1000000;
737*4882a593Smuzhiyun 
738*4882a593Smuzhiyun 		do {
739*4882a593Smuzhiyun 			msr = siu_read(port, UART_MSR);
740*4882a593Smuzhiyun 			if ((msr & UART_MSR_CTS) != 0)
741*4882a593Smuzhiyun 				break;
742*4882a593Smuzhiyun 		} while (timeout-- > 0);
743*4882a593Smuzhiyun 	}
744*4882a593Smuzhiyun }
745*4882a593Smuzhiyun 
siu_console_putchar(struct uart_port * port,int ch)746*4882a593Smuzhiyun static void siu_console_putchar(struct uart_port *port, int ch)
747*4882a593Smuzhiyun {
748*4882a593Smuzhiyun 	wait_for_xmitr(port);
749*4882a593Smuzhiyun 	siu_write(port, UART_TX, ch);
750*4882a593Smuzhiyun }
751*4882a593Smuzhiyun 
siu_console_write(struct console * con,const char * s,unsigned count)752*4882a593Smuzhiyun static void siu_console_write(struct console *con, const char *s, unsigned count)
753*4882a593Smuzhiyun {
754*4882a593Smuzhiyun 	struct uart_port *port;
755*4882a593Smuzhiyun 	uint8_t ier;
756*4882a593Smuzhiyun 
757*4882a593Smuzhiyun 	port = &siu_uart_ports[con->index];
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun 	ier = siu_read(port, UART_IER);
760*4882a593Smuzhiyun 	siu_write(port, UART_IER, 0);
761*4882a593Smuzhiyun 
762*4882a593Smuzhiyun 	uart_console_write(port, s, count, siu_console_putchar);
763*4882a593Smuzhiyun 
764*4882a593Smuzhiyun 	wait_for_xmitr(port);
765*4882a593Smuzhiyun 	siu_write(port, UART_IER, ier);
766*4882a593Smuzhiyun }
767*4882a593Smuzhiyun 
siu_console_setup(struct console * con,char * options)768*4882a593Smuzhiyun static int __init siu_console_setup(struct console *con, char *options)
769*4882a593Smuzhiyun {
770*4882a593Smuzhiyun 	struct uart_port *port;
771*4882a593Smuzhiyun 	int baud = 9600;
772*4882a593Smuzhiyun 	int parity = 'n';
773*4882a593Smuzhiyun 	int bits = 8;
774*4882a593Smuzhiyun 	int flow = 'n';
775*4882a593Smuzhiyun 
776*4882a593Smuzhiyun 	if (con->index >= SIU_PORTS_MAX)
777*4882a593Smuzhiyun 		con->index = 0;
778*4882a593Smuzhiyun 
779*4882a593Smuzhiyun 	port = &siu_uart_ports[con->index];
780*4882a593Smuzhiyun 	if (port->membase == NULL) {
781*4882a593Smuzhiyun 		if (port->mapbase == 0)
782*4882a593Smuzhiyun 			return -ENODEV;
783*4882a593Smuzhiyun 		port->membase = ioremap(port->mapbase, siu_port_size(port));
784*4882a593Smuzhiyun 	}
785*4882a593Smuzhiyun 
786*4882a593Smuzhiyun 	if (port->type == PORT_VR41XX_SIU)
787*4882a593Smuzhiyun 		vr41xx_select_siu_interface(SIU_INTERFACE_RS232C);
788*4882a593Smuzhiyun 
789*4882a593Smuzhiyun 	if (options != NULL)
790*4882a593Smuzhiyun 		uart_parse_options(options, &baud, &parity, &bits, &flow);
791*4882a593Smuzhiyun 
792*4882a593Smuzhiyun 	return uart_set_options(port, con, baud, parity, bits, flow);
793*4882a593Smuzhiyun }
794*4882a593Smuzhiyun 
795*4882a593Smuzhiyun static struct uart_driver siu_uart_driver;
796*4882a593Smuzhiyun 
797*4882a593Smuzhiyun static struct console siu_console = {
798*4882a593Smuzhiyun 	.name	= "ttyVR",
799*4882a593Smuzhiyun 	.write	= siu_console_write,
800*4882a593Smuzhiyun 	.device	= uart_console_device,
801*4882a593Smuzhiyun 	.setup	= siu_console_setup,
802*4882a593Smuzhiyun 	.flags	= CON_PRINTBUFFER,
803*4882a593Smuzhiyun 	.index	= -1,
804*4882a593Smuzhiyun 	.data	= &siu_uart_driver,
805*4882a593Smuzhiyun };
806*4882a593Smuzhiyun 
siu_console_init(void)807*4882a593Smuzhiyun static int siu_console_init(void)
808*4882a593Smuzhiyun {
809*4882a593Smuzhiyun 	struct uart_port *port;
810*4882a593Smuzhiyun 	int i;
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun 	for (i = 0; i < SIU_PORTS_MAX; i++) {
813*4882a593Smuzhiyun 		port = &siu_uart_ports[i];
814*4882a593Smuzhiyun 		port->ops = &siu_uart_ops;
815*4882a593Smuzhiyun 	}
816*4882a593Smuzhiyun 
817*4882a593Smuzhiyun 	register_console(&siu_console);
818*4882a593Smuzhiyun 
819*4882a593Smuzhiyun 	return 0;
820*4882a593Smuzhiyun }
821*4882a593Smuzhiyun 
822*4882a593Smuzhiyun console_initcall(siu_console_init);
823*4882a593Smuzhiyun 
vr41xx_siu_early_setup(struct uart_port * port)824*4882a593Smuzhiyun void __init vr41xx_siu_early_setup(struct uart_port *port)
825*4882a593Smuzhiyun {
826*4882a593Smuzhiyun 	if (port->type == PORT_UNKNOWN)
827*4882a593Smuzhiyun 		return;
828*4882a593Smuzhiyun 
829*4882a593Smuzhiyun 	siu_uart_ports[port->line].line = port->line;
830*4882a593Smuzhiyun 	siu_uart_ports[port->line].type = port->type;
831*4882a593Smuzhiyun 	siu_uart_ports[port->line].uartclk = SIU_BAUD_BASE * 16;
832*4882a593Smuzhiyun 	siu_uart_ports[port->line].mapbase = port->mapbase;
833*4882a593Smuzhiyun 	siu_uart_ports[port->line].ops = &siu_uart_ops;
834*4882a593Smuzhiyun }
835*4882a593Smuzhiyun 
836*4882a593Smuzhiyun #define SERIAL_VR41XX_CONSOLE	&siu_console
837*4882a593Smuzhiyun #else
838*4882a593Smuzhiyun #define SERIAL_VR41XX_CONSOLE	NULL
839*4882a593Smuzhiyun #endif
840*4882a593Smuzhiyun 
841*4882a593Smuzhiyun static struct uart_driver siu_uart_driver = {
842*4882a593Smuzhiyun 	.owner		= THIS_MODULE,
843*4882a593Smuzhiyun 	.driver_name	= "SIU",
844*4882a593Smuzhiyun 	.dev_name	= "ttyVR",
845*4882a593Smuzhiyun 	.major		= SIU_MAJOR,
846*4882a593Smuzhiyun 	.minor		= SIU_MINOR_BASE,
847*4882a593Smuzhiyun 	.cons		= SERIAL_VR41XX_CONSOLE,
848*4882a593Smuzhiyun };
849*4882a593Smuzhiyun 
siu_probe(struct platform_device * dev)850*4882a593Smuzhiyun static int siu_probe(struct platform_device *dev)
851*4882a593Smuzhiyun {
852*4882a593Smuzhiyun 	struct uart_port *port;
853*4882a593Smuzhiyun 	int num, i, retval;
854*4882a593Smuzhiyun 
855*4882a593Smuzhiyun 	num = siu_init_ports(dev);
856*4882a593Smuzhiyun 	if (num <= 0)
857*4882a593Smuzhiyun 		return -ENODEV;
858*4882a593Smuzhiyun 
859*4882a593Smuzhiyun 	siu_uart_driver.nr = num;
860*4882a593Smuzhiyun 	retval = uart_register_driver(&siu_uart_driver);
861*4882a593Smuzhiyun 	if (retval)
862*4882a593Smuzhiyun 		return retval;
863*4882a593Smuzhiyun 
864*4882a593Smuzhiyun 	for (i = 0; i < num; i++) {
865*4882a593Smuzhiyun 		port = &siu_uart_ports[i];
866*4882a593Smuzhiyun 		port->ops = &siu_uart_ops;
867*4882a593Smuzhiyun 		port->dev = &dev->dev;
868*4882a593Smuzhiyun 		port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_VR41XX_CONSOLE);
869*4882a593Smuzhiyun 
870*4882a593Smuzhiyun 		retval = uart_add_one_port(&siu_uart_driver, port);
871*4882a593Smuzhiyun 		if (retval < 0) {
872*4882a593Smuzhiyun 			port->dev = NULL;
873*4882a593Smuzhiyun 			break;
874*4882a593Smuzhiyun 		}
875*4882a593Smuzhiyun 	}
876*4882a593Smuzhiyun 
877*4882a593Smuzhiyun 	if (i == 0 && retval < 0) {
878*4882a593Smuzhiyun 		uart_unregister_driver(&siu_uart_driver);
879*4882a593Smuzhiyun 		return retval;
880*4882a593Smuzhiyun 	}
881*4882a593Smuzhiyun 
882*4882a593Smuzhiyun 	return 0;
883*4882a593Smuzhiyun }
884*4882a593Smuzhiyun 
siu_remove(struct platform_device * dev)885*4882a593Smuzhiyun static int siu_remove(struct platform_device *dev)
886*4882a593Smuzhiyun {
887*4882a593Smuzhiyun 	struct uart_port *port;
888*4882a593Smuzhiyun 	int i;
889*4882a593Smuzhiyun 
890*4882a593Smuzhiyun 	for (i = 0; i < siu_uart_driver.nr; i++) {
891*4882a593Smuzhiyun 		port = &siu_uart_ports[i];
892*4882a593Smuzhiyun 		if (port->dev == &dev->dev) {
893*4882a593Smuzhiyun 			uart_remove_one_port(&siu_uart_driver, port);
894*4882a593Smuzhiyun 			port->dev = NULL;
895*4882a593Smuzhiyun 		}
896*4882a593Smuzhiyun 	}
897*4882a593Smuzhiyun 
898*4882a593Smuzhiyun 	uart_unregister_driver(&siu_uart_driver);
899*4882a593Smuzhiyun 
900*4882a593Smuzhiyun 	return 0;
901*4882a593Smuzhiyun }
902*4882a593Smuzhiyun 
siu_suspend(struct platform_device * dev,pm_message_t state)903*4882a593Smuzhiyun static int siu_suspend(struct platform_device *dev, pm_message_t state)
904*4882a593Smuzhiyun {
905*4882a593Smuzhiyun 	struct uart_port *port;
906*4882a593Smuzhiyun 	int i;
907*4882a593Smuzhiyun 
908*4882a593Smuzhiyun 	for (i = 0; i < siu_uart_driver.nr; i++) {
909*4882a593Smuzhiyun 		port = &siu_uart_ports[i];
910*4882a593Smuzhiyun 		if ((port->type == PORT_VR41XX_SIU ||
911*4882a593Smuzhiyun 		     port->type == PORT_VR41XX_DSIU) && port->dev == &dev->dev)
912*4882a593Smuzhiyun 			uart_suspend_port(&siu_uart_driver, port);
913*4882a593Smuzhiyun 
914*4882a593Smuzhiyun 	}
915*4882a593Smuzhiyun 
916*4882a593Smuzhiyun 	return 0;
917*4882a593Smuzhiyun }
918*4882a593Smuzhiyun 
siu_resume(struct platform_device * dev)919*4882a593Smuzhiyun static int siu_resume(struct platform_device *dev)
920*4882a593Smuzhiyun {
921*4882a593Smuzhiyun 	struct uart_port *port;
922*4882a593Smuzhiyun 	int i;
923*4882a593Smuzhiyun 
924*4882a593Smuzhiyun 	for (i = 0; i < siu_uart_driver.nr; i++) {
925*4882a593Smuzhiyun 		port = &siu_uart_ports[i];
926*4882a593Smuzhiyun 		if ((port->type == PORT_VR41XX_SIU ||
927*4882a593Smuzhiyun 		     port->type == PORT_VR41XX_DSIU) && port->dev == &dev->dev)
928*4882a593Smuzhiyun 			uart_resume_port(&siu_uart_driver, port);
929*4882a593Smuzhiyun 	}
930*4882a593Smuzhiyun 
931*4882a593Smuzhiyun 	return 0;
932*4882a593Smuzhiyun }
933*4882a593Smuzhiyun 
934*4882a593Smuzhiyun static struct platform_driver siu_device_driver = {
935*4882a593Smuzhiyun 	.probe		= siu_probe,
936*4882a593Smuzhiyun 	.remove		= siu_remove,
937*4882a593Smuzhiyun 	.suspend	= siu_suspend,
938*4882a593Smuzhiyun 	.resume		= siu_resume,
939*4882a593Smuzhiyun 	.driver		= {
940*4882a593Smuzhiyun 		.name	= "SIU",
941*4882a593Smuzhiyun 	},
942*4882a593Smuzhiyun };
943*4882a593Smuzhiyun 
944*4882a593Smuzhiyun module_platform_driver(siu_device_driver);
945*4882a593Smuzhiyun 
946*4882a593Smuzhiyun MODULE_LICENSE("GPL");
947*4882a593Smuzhiyun MODULE_ALIAS("platform:SIU");
948