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