Merge git://git.skbuff.net/gitroot/yoshfuji/linux-2.6.14+advapi-fix/
[linux-2.6] / arch / mips / gt64120 / ev64120 / serialGT.c
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  ******************************/
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  ******************************/
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  ******************************/
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  ******************************/
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  ******************************/
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  ******************************/
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  ******************************/
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  ******************************/
209 void putDebugChar(char c)
210 {
211         serial_putc(DEBUG_CHANNEL, (int) c);
212 }