]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/serial/serial_s3c24x0.c
tools/proftool: remove REG_NOERROR
[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 <linux/compiler.h>
23 #include <asm/arch/s3c24x0_cpu.h>
24
25 DECLARE_GLOBAL_DATA_PTR;
26
27 #ifdef CONFIG_SERIAL1
28 #define UART_NR S3C24X0_UART0
29
30 #elif defined(CONFIG_SERIAL2)
31 #define UART_NR S3C24X0_UART1
32
33 #elif defined(CONFIG_SERIAL3)
34 #define UART_NR S3C24X0_UART2
35
36 #else
37 #error "Bad: you didn't configure serial ..."
38 #endif
39
40 #include <asm/io.h>
41 #include <serial.h>
42
43 /* Multi serial device functions */
44 #define DECLARE_S3C_SERIAL_FUNCTIONS(port) \
45         int s3serial##port##_init(void) \
46         { \
47                 return serial_init_dev(port); \
48         } \
49         void s3serial##port##_setbrg(void) \
50         { \
51                 serial_setbrg_dev(port); \
52         } \
53         int s3serial##port##_getc(void) \
54         { \
55                 return serial_getc_dev(port); \
56         } \
57         int s3serial##port##_tstc(void) \
58         { \
59                 return serial_tstc_dev(port); \
60         } \
61         void s3serial##port##_putc(const char c) \
62         { \
63                 serial_putc_dev(port, c); \
64         } \
65         void s3serial##port##_puts(const char *s) \
66         { \
67                 serial_puts_dev(port, s); \
68         }
69
70 #define INIT_S3C_SERIAL_STRUCTURE(port, __name) {       \
71         .name   = __name,                               \
72         .start  = s3serial##port##_init,                \
73         .stop   = NULL,                                 \
74         .setbrg = s3serial##port##_setbrg,              \
75         .getc   = s3serial##port##_getc,                \
76         .tstc   = s3serial##port##_tstc,                \
77         .putc   = s3serial##port##_putc,                \
78         .puts   = s3serial##port##_puts,                \
79 }
80
81 #ifdef CONFIG_HWFLOW
82 static int hwflow;
83 #endif
84
85 void _serial_setbrg(const int dev_index)
86 {
87         struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
88         unsigned int reg = 0;
89         int i;
90
91         /* value is calculated so : (int)(PCLK/16./baudrate) -1 */
92         reg = get_PCLK() / (16 * gd->baudrate) - 1;
93
94         writel(reg, &uart->ubrdiv);
95         for (i = 0; i < 100; i++)
96                 /* Delay */ ;
97 }
98
99 static inline void serial_setbrg_dev(unsigned int dev_index)
100 {
101         _serial_setbrg(dev_index);
102 }
103
104 /* Initialise the serial port. The settings are always 8 data bits, no parity,
105  * 1 stop bit, no start bits.
106  */
107 static int serial_init_dev(const int dev_index)
108 {
109         struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
110
111 #ifdef CONFIG_HWFLOW
112         hwflow = 0;     /* turned off by default */
113 #endif
114
115         /* FIFO enable, Tx/Rx FIFO clear */
116         writel(0x07, &uart->ufcon);
117         writel(0x0, &uart->umcon);
118
119         /* Normal,No parity,1 stop,8 bit */
120         writel(0x3, &uart->ulcon);
121         /*
122          * tx=level,rx=edge,disable timeout int.,enable rx error int.,
123          * normal,interrupt or polling
124          */
125         writel(0x245, &uart->ucon);
126
127 #ifdef CONFIG_HWFLOW
128         writel(0x1, &uart->umcon);      /* rts up */
129 #endif
130
131         /* FIXME: This is sooooooooooooooooooo ugly */
132 #if defined(CONFIG_ARCH_GTA02_v1) || defined(CONFIG_ARCH_GTA02_v2)
133         /* we need auto hw flow control on the gsm and gps port */
134         if (dev_index == 0 || dev_index == 1)
135                 writel(0x10, &uart->umcon);
136 #endif
137         _serial_setbrg(dev_index);
138
139         return (0);
140 }
141
142 /*
143  * Read a single byte from the serial port. Returns 1 on success, 0
144  * otherwise. When the function is succesfull, the character read is
145  * written into its argument c.
146  */
147 int _serial_getc(const int dev_index)
148 {
149         struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
150
151         while (!(readl(&uart->utrstat) & 0x1))
152                 /* wait for character to arrive */ ;
153
154         return readb(&uart->urxh) & 0xff;
155 }
156
157 static inline int serial_getc_dev(unsigned int dev_index)
158 {
159         return _serial_getc(dev_index);
160 }
161
162 #ifdef CONFIG_HWFLOW
163 int hwflow_onoff(int on)
164 {
165         switch (on) {
166         case 0:
167         default:
168                 break;          /* return current */
169         case 1:
170                 hwflow = 1;     /* turn on */
171                 break;
172         case -1:
173                 hwflow = 0;     /* turn off */
174                 break;
175         }
176         return hwflow;
177 }
178 #endif
179
180 #ifdef CONFIG_MODEM_SUPPORT
181 static int be_quiet = 0;
182 void disable_putc(void)
183 {
184         be_quiet = 1;
185 }
186
187 void enable_putc(void)
188 {
189         be_quiet = 0;
190 }
191 #endif
192
193
194 /*
195  * Output a single byte to the serial port.
196  */
197 void _serial_putc(const char c, const int dev_index)
198 {
199         struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
200 #ifdef CONFIG_MODEM_SUPPORT
201         if (be_quiet)
202                 return;
203 #endif
204
205         while (!(readl(&uart->utrstat) & 0x2))
206                 /* wait for room in the tx FIFO */ ;
207
208 #ifdef CONFIG_HWFLOW
209         while (hwflow && !(readl(&uart->umstat) & 0x1))
210                 /* Wait for CTS up */ ;
211 #endif
212
213         writeb(c, &uart->utxh);
214
215         /* If \n, also do \r */
216         if (c == '\n')
217                 serial_putc('\r');
218 }
219
220 static inline void serial_putc_dev(unsigned int dev_index, const char c)
221 {
222         _serial_putc(c, dev_index);
223 }
224
225 /*
226  * Test whether a character is in the RX buffer
227  */
228 int _serial_tstc(const int dev_index)
229 {
230         struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
231
232         return readl(&uart->utrstat) & 0x1;
233 }
234
235 static inline int serial_tstc_dev(unsigned int dev_index)
236 {
237         return _serial_tstc(dev_index);
238 }
239
240 void _serial_puts(const char *s, const int dev_index)
241 {
242         while (*s) {
243                 _serial_putc(*s++, dev_index);
244         }
245 }
246
247 static inline void serial_puts_dev(int dev_index, const char *s)
248 {
249         _serial_puts(s, dev_index);
250 }
251
252 DECLARE_S3C_SERIAL_FUNCTIONS(0);
253 struct serial_device s3c24xx_serial0_device =
254 INIT_S3C_SERIAL_STRUCTURE(0, "s3ser0");
255 DECLARE_S3C_SERIAL_FUNCTIONS(1);
256 struct serial_device s3c24xx_serial1_device =
257 INIT_S3C_SERIAL_STRUCTURE(1, "s3ser1");
258 DECLARE_S3C_SERIAL_FUNCTIONS(2);
259 struct serial_device s3c24xx_serial2_device =
260 INIT_S3C_SERIAL_STRUCTURE(2, "s3ser2");
261
262 __weak struct serial_device *default_serial_console(void)
263 {
264 #if defined(CONFIG_SERIAL1)
265         return &s3c24xx_serial0_device;
266 #elif defined(CONFIG_SERIAL2)
267         return &s3c24xx_serial1_device;
268 #elif defined(CONFIG_SERIAL3)
269         return &s3c24xx_serial2_device;
270 #else
271 #error "CONFIG_SERIAL? missing."
272 #endif
273 }
274
275 void s3c24xx_serial_initialize(void)
276 {
277         serial_register(&s3c24xx_serial0_device);
278         serial_register(&s3c24xx_serial1_device);
279         serial_register(&s3c24xx_serial2_device);
280 }