xref: /OK3568_Linux_fs/kernel/arch/mips/include/asm/netlogic/xlp-hal/uart.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
3*4882a593Smuzhiyun  * reserved.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * This software is available to you under a choice of one of two
6*4882a593Smuzhiyun  * licenses.  You may choose to be licensed under the terms of the GNU
7*4882a593Smuzhiyun  * General Public License (GPL) Version 2, available from the file
8*4882a593Smuzhiyun  * COPYING in the main directory of this source tree, or the NetLogic
9*4882a593Smuzhiyun  * license below:
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * Redistribution and use in source and binary forms, with or without
12*4882a593Smuzhiyun  * modification, are permitted provided that the following conditions
13*4882a593Smuzhiyun  * are met:
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  * 1. Redistributions of source code must retain the above copyright
16*4882a593Smuzhiyun  *    notice, this list of conditions and the following disclaimer.
17*4882a593Smuzhiyun  * 2. Redistributions in binary form must reproduce the above copyright
18*4882a593Smuzhiyun  *    notice, this list of conditions and the following disclaimer in
19*4882a593Smuzhiyun  *    the documentation and/or other materials provided with the
20*4882a593Smuzhiyun  *    distribution.
21*4882a593Smuzhiyun  *
22*4882a593Smuzhiyun  * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
23*4882a593Smuzhiyun  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24*4882a593Smuzhiyun  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25*4882a593Smuzhiyun  * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
26*4882a593Smuzhiyun  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27*4882a593Smuzhiyun  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28*4882a593Smuzhiyun  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29*4882a593Smuzhiyun  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30*4882a593Smuzhiyun  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31*4882a593Smuzhiyun  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
32*4882a593Smuzhiyun  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33*4882a593Smuzhiyun  */
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #ifndef __XLP_HAL_UART_H__
36*4882a593Smuzhiyun #define __XLP_HAL_UART_H__
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun /* UART Specific registers */
39*4882a593Smuzhiyun #define UART_RX_DATA		0x00
40*4882a593Smuzhiyun #define UART_TX_DATA		0x00
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun #define UART_INT_EN		0x01
43*4882a593Smuzhiyun #define UART_INT_ID		0x02
44*4882a593Smuzhiyun #define UART_FIFO_CTL		0x02
45*4882a593Smuzhiyun #define UART_LINE_CTL		0x03
46*4882a593Smuzhiyun #define UART_MODEM_CTL		0x04
47*4882a593Smuzhiyun #define UART_LINE_STS		0x05
48*4882a593Smuzhiyun #define UART_MODEM_STS		0x06
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun #define UART_DIVISOR0		0x00
51*4882a593Smuzhiyun #define UART_DIVISOR1		0x01
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun #define BASE_BAUD		(XLP_IO_CLK/16)
54*4882a593Smuzhiyun #define BAUD_DIVISOR(baud)	(BASE_BAUD / baud)
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun /* LCR mask values */
57*4882a593Smuzhiyun #define LCR_5BITS		0x00
58*4882a593Smuzhiyun #define LCR_6BITS		0x01
59*4882a593Smuzhiyun #define LCR_7BITS		0x02
60*4882a593Smuzhiyun #define LCR_8BITS		0x03
61*4882a593Smuzhiyun #define LCR_STOPB		0x04
62*4882a593Smuzhiyun #define LCR_PENAB		0x08
63*4882a593Smuzhiyun #define LCR_PODD		0x00
64*4882a593Smuzhiyun #define LCR_PEVEN		0x10
65*4882a593Smuzhiyun #define LCR_PONE		0x20
66*4882a593Smuzhiyun #define LCR_PZERO		0x30
67*4882a593Smuzhiyun #define LCR_SBREAK		0x40
68*4882a593Smuzhiyun #define LCR_EFR_ENABLE		0xbf
69*4882a593Smuzhiyun #define LCR_DLAB		0x80
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun /* MCR mask values */
72*4882a593Smuzhiyun #define MCR_DTR			0x01
73*4882a593Smuzhiyun #define MCR_RTS			0x02
74*4882a593Smuzhiyun #define MCR_DRS			0x04
75*4882a593Smuzhiyun #define MCR_IE			0x08
76*4882a593Smuzhiyun #define MCR_LOOPBACK		0x10
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun /* FCR mask values */
79*4882a593Smuzhiyun #define FCR_RCV_RST		0x02
80*4882a593Smuzhiyun #define FCR_XMT_RST		0x04
81*4882a593Smuzhiyun #define FCR_RX_LOW		0x00
82*4882a593Smuzhiyun #define FCR_RX_MEDL		0x40
83*4882a593Smuzhiyun #define FCR_RX_MEDH		0x80
84*4882a593Smuzhiyun #define FCR_RX_HIGH		0xc0
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun /* IER mask values */
87*4882a593Smuzhiyun #define IER_ERXRDY		0x1
88*4882a593Smuzhiyun #define IER_ETXRDY		0x2
89*4882a593Smuzhiyun #define IER_ERLS		0x4
90*4882a593Smuzhiyun #define IER_EMSC		0x8
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun #if !defined(LOCORE) && !defined(__ASSEMBLY__)
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun #define nlm_read_uart_reg(b, r)		nlm_read_reg(b, r)
95*4882a593Smuzhiyun #define nlm_write_uart_reg(b, r, v)	nlm_write_reg(b, r, v)
96*4882a593Smuzhiyun #define nlm_get_uart_pcibase(node, inst)	\
97*4882a593Smuzhiyun 	nlm_pcicfg_base(cpu_is_xlp9xx() ?  XLP9XX_IO_UART_OFFSET(node) : \
98*4882a593Smuzhiyun 						XLP_IO_UART_OFFSET(node, inst))
99*4882a593Smuzhiyun #define nlm_get_uart_regbase(node, inst)	\
100*4882a593Smuzhiyun 			(nlm_get_uart_pcibase(node, inst) + XLP_IO_PCI_HDRSZ)
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun static inline void
nlm_uart_set_baudrate(uint64_t base,int baud)103*4882a593Smuzhiyun nlm_uart_set_baudrate(uint64_t base, int baud)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun 	uint32_t lcr;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	lcr = nlm_read_uart_reg(base, UART_LINE_CTL);
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	/* enable divisor register, and write baud values */
110*4882a593Smuzhiyun 	nlm_write_uart_reg(base, UART_LINE_CTL, lcr | (1 << 7));
111*4882a593Smuzhiyun 	nlm_write_uart_reg(base, UART_DIVISOR0,
112*4882a593Smuzhiyun 			(BAUD_DIVISOR(baud) & 0xff));
113*4882a593Smuzhiyun 	nlm_write_uart_reg(base, UART_DIVISOR1,
114*4882a593Smuzhiyun 			((BAUD_DIVISOR(baud) >> 8) & 0xff));
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	/* restore default lcr */
117*4882a593Smuzhiyun 	nlm_write_uart_reg(base, UART_LINE_CTL, lcr);
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun static inline void
nlm_uart_outbyte(uint64_t base,char c)121*4882a593Smuzhiyun nlm_uart_outbyte(uint64_t base, char c)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun 	uint32_t lsr;
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	for (;;) {
126*4882a593Smuzhiyun 		lsr = nlm_read_uart_reg(base, UART_LINE_STS);
127*4882a593Smuzhiyun 		if (lsr & 0x20)
128*4882a593Smuzhiyun 			break;
129*4882a593Smuzhiyun 	}
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	nlm_write_uart_reg(base, UART_TX_DATA, (int)c);
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun static inline char
nlm_uart_inbyte(uint64_t base)135*4882a593Smuzhiyun nlm_uart_inbyte(uint64_t base)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun 	int data, lsr;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	for (;;) {
140*4882a593Smuzhiyun 		lsr = nlm_read_uart_reg(base, UART_LINE_STS);
141*4882a593Smuzhiyun 		if (lsr & 0x80) { /* parity/frame/break-error - push a zero */
142*4882a593Smuzhiyun 			data = 0;
143*4882a593Smuzhiyun 			break;
144*4882a593Smuzhiyun 		}
145*4882a593Smuzhiyun 		if (lsr & 0x01) {	/* Rx data */
146*4882a593Smuzhiyun 			data = nlm_read_uart_reg(base, UART_RX_DATA);
147*4882a593Smuzhiyun 			break;
148*4882a593Smuzhiyun 		}
149*4882a593Smuzhiyun 	}
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	return (char)data;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun static inline int
nlm_uart_init(uint64_t base,int baud,int databits,int stopbits,int parity,int int_en,int loopback)155*4882a593Smuzhiyun nlm_uart_init(uint64_t base, int baud, int databits, int stopbits,
156*4882a593Smuzhiyun 	int parity, int int_en, int loopback)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun 	uint32_t lcr;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	lcr = 0;
161*4882a593Smuzhiyun 	if (databits >= 8)
162*4882a593Smuzhiyun 		lcr |= LCR_8BITS;
163*4882a593Smuzhiyun 	else if (databits == 7)
164*4882a593Smuzhiyun 		lcr |= LCR_7BITS;
165*4882a593Smuzhiyun 	else if (databits == 6)
166*4882a593Smuzhiyun 		lcr |= LCR_6BITS;
167*4882a593Smuzhiyun 	else
168*4882a593Smuzhiyun 		lcr |= LCR_5BITS;
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	if (stopbits > 1)
171*4882a593Smuzhiyun 		lcr |= LCR_STOPB;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	lcr |= parity << 3;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	/* setup default lcr */
176*4882a593Smuzhiyun 	nlm_write_uart_reg(base, UART_LINE_CTL, lcr);
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	/* Reset the FIFOs */
179*4882a593Smuzhiyun 	nlm_write_uart_reg(base, UART_LINE_CTL, FCR_RCV_RST | FCR_XMT_RST);
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	nlm_uart_set_baudrate(base, baud);
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	if (loopback)
184*4882a593Smuzhiyun 		nlm_write_uart_reg(base, UART_MODEM_CTL, 0x1f);
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun 	if (int_en)
187*4882a593Smuzhiyun 		nlm_write_uart_reg(base, UART_INT_EN, IER_ERXRDY | IER_ETXRDY);
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	return 0;
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun #endif /* !LOCORE && !__ASSEMBLY__ */
192*4882a593Smuzhiyun #endif /* __XLP_HAL_UART_H__ */
193