1 /*
2  * serialGT.c
3  *
4  * BRIEF MODULE DESCRIPTION
5  *  Low Level Serial Port control for use
6  *  with the Galileo EVB64120A MIPS eval board and
7  *  its on board two channel 16552 Uart.
8  *
9  * Copyright (C) 2000 RidgeRun, Inc.
10  * Author: RidgeRun, Inc.
11  *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
12  *
13  *  This program is free software; you can redistribute  it and/or modify it
14  *  under  the terms of  the GNU General  Public License as published by the
15  *  Free Software Foundation;  either version 2 of the  License, or (at your
16  *  option) any later version.
17  *
18  *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
19  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
20  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
21  *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
22  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
24  *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
26  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *  You should have received a copy of the  GNU General Public License along
30  *  with this program; if not, write  to the Free Software Foundation, Inc.,
31  *  675 Mass Ave, Cambridge, MA 02139, USA.
32  *
33  */
34 
35 // Note:
36 //   Serial CHANNELS - 0 is the bottom connector of evb64120A.
37 //                       (The one that maps to the "B" channel of the
38 //                       board's uart)
39 //                     1 is the top connector of evb64120A.
40 //                       (The one that maps to the "A" channel of the
41 //                       board's uart)
42 int DEBUG_CHANNEL = 0;		// See Note Above
43 int CONSOLE_CHANNEL = 1;	// See Note Above
44 
45 #define DUART 0xBD000000	/* Base address of Uart. */
46 #define CHANNELOFFSET 0x20	/* DUART+CHANNELOFFSET gets you to the ChanA
47 				   register set of the 16552 Uart device.
48 				   DUART+0 gets you to the ChanB register set.
49 				 */
50 #define DUART_DELTA 0x4
51 #define FIFO_ENABLE 0x07
52 #define INT_ENABLE  0x04	/* default interrupt mask */
53 
54 #define RBR 0x00
55 #define THR 0x00
56 #define DLL 0x00
57 #define IER 0x01
58 #define DLM 0x01
59 #define IIR 0x02
60 #define FCR 0x02
61 #define LCR 0x03
62 #define MCR 0x04
63 #define LSR 0x05
64 #define MSR 0x06
65 #define SCR 0x07
66 
67 #define LCR_DLAB 0x80
68 #define XTAL 1843200
69 #define LSR_THRE 0x20
70 #define LSR_BI   0x10
71 #define LSR_DR   0x01
72 #define MCR_LOOP 0x10
73 #define ACCESS_DELAY 0x10000
74 
75 /******************************
76  Routine:
77  Description:
78  ******************************/
inreg(int channel,int reg)79 int inreg(int channel, int reg)
80 {
81 	int val;
82 	val =
83 	    *((volatile unsigned char *) DUART +
84 	      (channel * CHANNELOFFSET) + (reg * DUART_DELTA));
85 	return val;
86 }
87 
88 /******************************
89  Routine:
90  Description:
91  ******************************/
outreg(int channel,int reg,unsigned char val)92 void outreg(int channel, int reg, unsigned char val)
93 {
94 	*((volatile unsigned char *) DUART + (channel * CHANNELOFFSET)
95 	  + (reg * DUART_DELTA)) = val;
96 }
97 
98 /******************************
99  Routine:
100  Description:
101    Initialize the device driver.
102  ******************************/
serial_init(int channel)103 void serial_init(int channel)
104 {
105 	/*
106 	 * Configure active port, (CHANNELOFFSET already set.)
107 	 *
108 	 * Set 8 bits, 1 stop bit, no parity.
109 	 *
110 	 * LCR<7>       0       divisor latch access bit
111 	 * LCR<6>       0       break control (1=send break)
112 	 * LCR<5>       0       stick parity (0=space, 1=mark)
113 	 * LCR<4>       0       parity even (0=odd, 1=even)
114 	 * LCR<3>       0       parity enable (1=enabled)
115 	 * LCR<2>       0       # stop bits (0=1, 1=1.5)
116 	 * LCR<1:0>     11      bits per character(00=5, 01=6, 10=7, 11=8)
117 	 */
118 	outreg(channel, LCR, 0x3);
119 
120 	outreg(channel, FCR, FIFO_ENABLE);	/* Enable the FIFO */
121 
122 	outreg(channel, IER, INT_ENABLE);	/* Enable appropriate interrupts */
123 }
124 
125 /******************************
126  Routine:
127  Description:
128    Set the baud rate.
129  ******************************/
serial_set(int channel,unsigned long baud)130 void serial_set(int channel, unsigned long baud)
131 {
132 	unsigned char sav_lcr;
133 
134 	/*
135 	 * Enable access to the divisor latches by setting DLAB in LCR.
136 	 *
137 	 */
138 	sav_lcr = inreg(channel, LCR);
139 
140 #if 0
141 	/*
142 	 * Set baud rate
143 	 */
144 	outreg(channel, LCR, LCR_DLAB | sav_lcr);
145 	//  outreg(DLL,(XTAL/(16*2*(baud))-2));
146 	outreg(channel, DLL, XTAL / (16 * baud));
147 	//  outreg(DLM,(XTAL/(16*2*(baud))-2)>>8);
148 	outreg(channel, DLM, (XTAL / (16 * baud)) >> 8);
149 #else
150 	/*
151 	 * Note: Set baud rate, hardcoded here for rate of 115200
152 	 * since became unsure of above "buad rate" algorithm (??).
153 	 */
154 	outreg(channel, LCR, 0x83);
155 	outreg(channel, DLM, 0x00);	// See note above
156 	outreg(channel, DLL, 0x02);	// See note above.
157 	outreg(channel, LCR, 0x03);
158 #endif
159 
160 	/*
161 	 * Restore line control register
162 	 */
163 	outreg(channel, LCR, sav_lcr);
164 }
165 
166 
167 /******************************
168  Routine:
169  Description:
170    Transmit a character.
171  ******************************/
serial_putc(int channel,int c)172 void serial_putc(int channel, int c)
173 {
174 	while ((inreg(channel, LSR) & LSR_THRE) == 0);
175 	outreg(channel, THR, c);
176 }
177 
178 /******************************
179  Routine:
180  Description:
181     Read a received character if one is
182     available.  Return -1 otherwise.
183  ******************************/
serial_getc(int channel)184 int serial_getc(int channel)
185 {
186 	if (inreg(channel, LSR) & LSR_DR) {
187 		return inreg(channel, RBR);
188 	}
189 	return -1;
190 }
191 
192 /******************************
193  Routine:
194  Description:
195    Used by embedded gdb client. (example; gdb-stub.c)
196  ******************************/
getDebugChar()197 char getDebugChar()
198 {
199 	int val;
200 	while ((val = serial_getc(DEBUG_CHANNEL)) == -1);	// loop until we get a character in.
201 	return (char) val;
202 }
203 
204 /******************************
205  Routine:
206  Description:
207    Used by embedded gdb target. (example; gdb-stub.c)
208  ******************************/
putDebugChar(char c)209 void putDebugChar(char c)
210 {
211 	serial_putc(DEBUG_CHANNEL, (int) c);
212 }
213