]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/serial/serial_s3c24x0.c
Merge branch 'master' of git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / drivers / serial / serial_s3c24x0.c
1 /*
2  * (C) Copyright 2002
3  * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  */
20
21 #include <common.h>
22 #include <asm/arch/s3c24x0_cpu.h>
23
24 DECLARE_GLOBAL_DATA_PTR;
25
26 #ifdef CONFIG_SERIAL1
27 #define UART_NR S3C24X0_UART0
28
29 #elif defined(CONFIG_SERIAL2)
30 # if defined(CONFIG_TRAB)
31 #  error "TRAB supports only CONFIG_SERIAL1"
32 # endif
33 #define UART_NR S3C24X0_UART1
34
35 #elif defined(CONFIG_SERIAL3)
36 # if defined(CONFIG_TRAB)
37 #  error "TRAB supports only CONFIG_SERIAL1"
38 # endif
39 #define UART_NR S3C24X0_UART2
40
41 #else
42 #error "Bad: you didn't configure serial ..."
43 #endif
44
45 #include <asm/io.h>
46
47 #if defined(CONFIG_SERIAL_MULTI)
48 #include <serial.h>
49
50 /* Multi serial device functions */
51 #define DECLARE_S3C_SERIAL_FUNCTIONS(port) \
52         int s3serial##port##_init(void) \
53         { \
54                 return serial_init_dev(port); \
55         } \
56         void s3serial##port##_setbrg(void) \
57         { \
58                 serial_setbrg_dev(port); \
59         } \
60         int s3serial##port##_getc(void) \
61         { \
62                 return serial_getc_dev(port); \
63         } \
64         int s3serial##port##_tstc(void) \
65         { \
66                 return serial_tstc_dev(port); \
67         } \
68         void s3serial##port##_putc(const char c) \
69         { \
70                 serial_putc_dev(port, c); \
71         } \
72         void s3serial##port##_puts(const char *s) \
73         { \
74                 serial_puts_dev(port, s); \
75         }
76
77 #define INIT_S3C_SERIAL_STRUCTURE(port, name, bus) { \
78         name, \
79         bus, \
80         s3serial##port##_init, \
81         NULL,\
82         s3serial##port##_setbrg, \
83         s3serial##port##_getc, \
84         s3serial##port##_tstc, \
85         s3serial##port##_putc, \
86         s3serial##port##_puts, \
87 }
88
89 #endif /* CONFIG_SERIAL_MULTI */
90
91 #ifdef CONFIG_HWFLOW
92 static int hwflow;
93 #endif
94
95 void _serial_setbrg(const int dev_index)
96 {
97         struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
98         unsigned int reg = 0;
99         int i;
100
101         /* value is calculated so : (int)(PCLK/16./baudrate) -1 */
102         reg = get_PCLK() / (16 * gd->baudrate) - 1;
103
104         writel(reg, &uart->UBRDIV);
105         for (i = 0; i < 100; i++)
106                 /* Delay */ ;
107 }
108
109 #if defined(CONFIG_SERIAL_MULTI)
110 static inline void serial_setbrg_dev(unsigned int dev_index)
111 {
112         _serial_setbrg(dev_index);
113 }
114 #else
115 void serial_setbrg(void)
116 {
117         _serial_setbrg(UART_NR);
118 }
119 #endif
120
121
122 /* Initialise the serial port. The settings are always 8 data bits, no parity,
123  * 1 stop bit, no start bits.
124  */
125 static int serial_init_dev(const int dev_index)
126 {
127         struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
128
129 #ifdef CONFIG_HWFLOW
130         hwflow = 0;     /* turned off by default */
131 #endif
132
133         /* FIFO enable, Tx/Rx FIFO clear */
134         writel(0x07, &uart->UFCON);
135         writel(0x0, &uart->UMCON);
136
137         /* Normal,No parity,1 stop,8 bit */
138         writel(0x3, &uart->ULCON);
139         /*
140          * tx=level,rx=edge,disable timeout int.,enable rx error int.,
141          * normal,interrupt or polling
142          */
143         writel(0x245, &uart->UCON);
144
145 #ifdef CONFIG_HWFLOW
146         writel(0x1, &uart->UMCON);      /* RTS up */
147 #endif
148
149         /* FIXME: This is sooooooooooooooooooo ugly */
150 #if defined(CONFIG_ARCH_GTA02_v1) || defined(CONFIG_ARCH_GTA02_v2)
151         /* we need auto hw flow control on the gsm and gps port */
152         if (dev_index == 0 || dev_index == 1)
153                 writel(0x10, &uart->UMCON);
154 #endif
155         _serial_setbrg(dev_index);
156
157         return (0);
158 }
159
160 #if !defined(CONFIG_SERIAL_MULTI)
161 /* Initialise the serial port. The settings are always 8 data bits, no parity,
162  * 1 stop bit, no start bits.
163  */
164 int serial_init(void)
165 {
166         return serial_init_dev(UART_NR);
167 }
168 #endif
169
170 /*
171  * Read a single byte from the serial port. Returns 1 on success, 0
172  * otherwise. When the function is succesfull, the character read is
173  * written into its argument c.
174  */
175 int _serial_getc(const int dev_index)
176 {
177         struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
178
179         while (!(readl(&uart->UTRSTAT) & 0x1))
180                 /* wait for character to arrive */ ;
181
182         return readb(&uart->URXH) & 0xff;
183 }
184
185 #if defined(CONFIG_SERIAL_MULTI)
186 static inline int serial_getc_dev(unsigned int dev_index)
187 {
188         return _serial_getc(dev_index);
189 }
190 #else
191 int serial_getc(void)
192 {
193         return _serial_getc(UART_NR);
194 }
195 #endif
196
197 #ifdef CONFIG_HWFLOW
198 int hwflow_onoff(int on)
199 {
200         switch (on) {
201         case 0:
202         default:
203                 break;          /* return current */
204         case 1:
205                 hwflow = 1;     /* turn on */
206                 break;
207         case -1:
208                 hwflow = 0;     /* turn off */
209                 break;
210         }
211         return hwflow;
212 }
213 #endif
214
215 #ifdef CONFIG_MODEM_SUPPORT
216 static int be_quiet = 0;
217 void disable_putc(void)
218 {
219         be_quiet = 1;
220 }
221
222 void enable_putc(void)
223 {
224         be_quiet = 0;
225 }
226 #endif
227
228
229 /*
230  * Output a single byte to the serial port.
231  */
232 void _serial_putc(const char c, const int dev_index)
233 {
234         struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
235 #ifdef CONFIG_MODEM_SUPPORT
236         if (be_quiet)
237                 return;
238 #endif
239
240         while (!(readl(&uart->UTRSTAT) & 0x2))
241                 /* wait for room in the tx FIFO */ ;
242
243 #ifdef CONFIG_HWFLOW
244         while (hwflow && !(readl(&uart->UMSTAT) & 0x1))
245                 /* Wait for CTS up */ ;
246 #endif
247
248         writeb(c, &uart->UTXH);
249
250         /* If \n, also do \r */
251         if (c == '\n')
252                 serial_putc('\r');
253 }
254
255 #if defined(CONFIG_SERIAL_MULTI)
256 static inline void serial_putc_dev(unsigned int dev_index, const char c)
257 {
258         _serial_putc(c, dev_index);
259 }
260 #else
261 void serial_putc(const char c)
262 {
263         _serial_putc(c, UART_NR);
264 }
265 #endif
266
267
268 /*
269  * Test whether a character is in the RX buffer
270  */
271 int _serial_tstc(const int dev_index)
272 {
273         struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
274
275         return readl(&uart->UTRSTAT) & 0x1;
276 }
277
278 #if defined(CONFIG_SERIAL_MULTI)
279 static inline int serial_tstc_dev(unsigned int dev_index)
280 {
281         return _serial_tstc(dev_index);
282 }
283 #else
284 int serial_tstc(void)
285 {
286         return _serial_tstc(UART_NR);
287 }
288 #endif
289
290 void _serial_puts(const char *s, const int dev_index)
291 {
292         while (*s) {
293                 _serial_putc(*s++, dev_index);
294         }
295 }
296
297 #if defined(CONFIG_SERIAL_MULTI)
298 static inline void serial_puts_dev(int dev_index, const char *s)
299 {
300         _serial_puts(s, dev_index);
301 }
302 #else
303 void serial_puts(const char *s)
304 {
305         _serial_puts(s, UART_NR);
306 }
307 #endif
308
309 #if defined(CONFIG_SERIAL_MULTI)
310 DECLARE_S3C_SERIAL_FUNCTIONS(0);
311 struct serial_device s3c24xx_serial0_device =
312 INIT_S3C_SERIAL_STRUCTURE(0, "s3ser0", "S3UART1");
313 DECLARE_S3C_SERIAL_FUNCTIONS(1);
314 struct serial_device s3c24xx_serial1_device =
315 INIT_S3C_SERIAL_STRUCTURE(1, "s3ser1", "S3UART2");
316 DECLARE_S3C_SERIAL_FUNCTIONS(2);
317 struct serial_device s3c24xx_serial2_device =
318 INIT_S3C_SERIAL_STRUCTURE(2, "s3ser2", "S3UART3");
319 #endif /* CONFIG_SERIAL_MULTI */