blob: b74e43957ff70d4024efc78d6b0618c437823664 [file] [log] [blame]
wdenkc6097192002-11-03 00:24:07 +00001/*
2 * (C) Copyright 2002
3 * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
4 *
5 * (C) Copyright 2002
6 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
7 * Marius Groeger <mgroeger@sysgo.de>
8 *
9 * (C) Copyright 2002
10 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
11 * Alex Zuepke <azu@sysgo.de>
12 *
13 * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 */
30
31#include <common.h>
wdenk5f535fe2003-09-18 09:21:33 +000032#include <watchdog.h>
stefano babic80172c62007-08-30 22:57:04 +020033#include <serial.h>
wdenkc6097192002-11-03 00:24:07 +000034#include <asm/arch/pxa-regs.h>
35
Wolfgang Denkd87080b2006-03-31 18:32:53 +020036DECLARE_GLOBAL_DATA_PTR;
37
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +020038#define FFUART_INDEX 0
39#define BTUART_INDEX 1
40#define STUART_INDEX 2
stefano babic80172c62007-08-30 22:57:04 +020041
42#ifndef CONFIG_SERIAL_MULTI
43#if defined (CONFIG_FFUART)
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +020044#define UART_INDEX FFUART_INDEX
stefano babic80172c62007-08-30 22:57:04 +020045#elif defined (CONFIG_BTUART)
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +020046#define UART_INDEX BTUART_INDEX
stefano babic80172c62007-08-30 22:57:04 +020047#elif defined (CONFIG_STUART)
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +020048#define UART_INDEX STUART_INDEX
stefano babic80172c62007-08-30 22:57:04 +020049#else
50#error "Bad: you didn't configure serial ..."
51#endif
52#endif
53
54void pxa_setbrg_dev (unsigned int uart_index)
wdenkc6097192002-11-03 00:24:07 +000055{
wdenkc6097192002-11-03 00:24:07 +000056 unsigned int quot = 0;
57
58 if (gd->baudrate == 1200)
wdenk5f535fe2003-09-18 09:21:33 +000059 quot = 768;
wdenkc6097192002-11-03 00:24:07 +000060 else if (gd->baudrate == 9600)
61 quot = 96;
62 else if (gd->baudrate == 19200)
63 quot = 48;
64 else if (gd->baudrate == 38400)
65 quot = 24;
66 else if (gd->baudrate == 57600)
67 quot = 16;
68 else if (gd->baudrate == 115200)
69 quot = 8;
70 else
71 hang ();
72
stefano babic80172c62007-08-30 22:57:04 +020073 switch (uart_index) {
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +020074 case FFUART_INDEX:
Markus Klotzbüchere0269572006-02-07 20:04:48 +010075#ifdef CONFIG_CPU_MONAHANS
stefano babic80172c62007-08-30 22:57:04 +020076 CKENA |= CKENA_22_FFUART;
Markus Klotzbüchere0269572006-02-07 20:04:48 +010077#else
stefano babic80172c62007-08-30 22:57:04 +020078 CKEN |= CKEN6_FFUART;
Markus Klotzbüchere0269572006-02-07 20:04:48 +010079#endif /* CONFIG_CPU_MONAHANS */
wdenkc6097192002-11-03 00:24:07 +000080
stefano babic80172c62007-08-30 22:57:04 +020081 FFIER = 0; /* Disable for now */
82 FFFCR = 0; /* No fifos enabled */
wdenkc6097192002-11-03 00:24:07 +000083
stefano babic80172c62007-08-30 22:57:04 +020084 /* set baud rate */
85 FFLCR = LCR_WLS0 | LCR_WLS1 | LCR_DLAB;
86 FFDLL = quot & 0xff;
87 FFDLH = quot >> 8;
88 FFLCR = LCR_WLS0 | LCR_WLS1;
wdenkc6097192002-11-03 00:24:07 +000089
stefano babic80172c62007-08-30 22:57:04 +020090 FFIER = IER_UUE; /* Enable FFUART */
91 break;
wdenkc6097192002-11-03 00:24:07 +000092
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +020093 case BTUART_INDEX:
Markus Klotzbüchere0269572006-02-07 20:04:48 +010094#ifdef CONFIG_CPU_MONAHANS
stefano babic80172c62007-08-30 22:57:04 +020095 CKENA |= CKENA_21_BTUART;
Markus Klotzbüchere0269572006-02-07 20:04:48 +010096#else
stefano babic80172c62007-08-30 22:57:04 +020097 CKEN |= CKEN7_BTUART;
Markus Klotzbüchere0269572006-02-07 20:04:48 +010098#endif /* CONFIG_CPU_MONAHANS */
wdenk3e386912003-04-05 00:53:31 +000099
stefano babic80172c62007-08-30 22:57:04 +0200100 BTIER = 0;
101 BTFCR = 0;
wdenk3e386912003-04-05 00:53:31 +0000102
stefano babic80172c62007-08-30 22:57:04 +0200103 /* set baud rate */
104 BTLCR = LCR_DLAB;
105 BTDLL = quot & 0xff;
106 BTDLH = quot >> 8;
107 BTLCR = LCR_WLS0 | LCR_WLS1;
wdenk3e386912003-04-05 00:53:31 +0000108
stefano babic80172c62007-08-30 22:57:04 +0200109 BTIER = IER_UUE; /* Enable BFUART */
wdenk3e386912003-04-05 00:53:31 +0000110
stefano babic80172c62007-08-30 22:57:04 +0200111 break;
112
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200113 case STUART_INDEX:
Markus Klotzbüchere0269572006-02-07 20:04:48 +0100114#ifdef CONFIG_CPU_MONAHANS
stefano babic80172c62007-08-30 22:57:04 +0200115 CKENA |= CKENA_23_STUART;
Markus Klotzbüchere0269572006-02-07 20:04:48 +0100116#else
stefano babic80172c62007-08-30 22:57:04 +0200117 CKEN |= CKEN5_STUART;
Markus Klotzbüchere0269572006-02-07 20:04:48 +0100118#endif /* CONFIG_CPU_MONAHANS */
wdenk5f535fe2003-09-18 09:21:33 +0000119
stefano babic80172c62007-08-30 22:57:04 +0200120 STIER = 0;
121 STFCR = 0;
wdenk5f535fe2003-09-18 09:21:33 +0000122
stefano babic80172c62007-08-30 22:57:04 +0200123 /* set baud rate */
124 STLCR = LCR_DLAB;
125 STDLL = quot & 0xff;
126 STDLH = quot >> 8;
127 STLCR = LCR_WLS0 | LCR_WLS1;
wdenk5f535fe2003-09-18 09:21:33 +0000128
stefano babic80172c62007-08-30 22:57:04 +0200129 STIER = IER_UUE; /* Enable STUART */
130 break;
wdenk5f535fe2003-09-18 09:21:33 +0000131
stefano babic80172c62007-08-30 22:57:04 +0200132 default:
133 hang();
134 }
wdenkc6097192002-11-03 00:24:07 +0000135}
136
137
138/*
139 * Initialise the serial port with the given baudrate. The settings
140 * are always 8 data bits, no parity, 1 stop bit, no start bits.
141 *
142 */
stefano babic80172c62007-08-30 22:57:04 +0200143int pxa_init_dev (unsigned int uart_index)
wdenkc6097192002-11-03 00:24:07 +0000144{
stefano babic80172c62007-08-30 22:57:04 +0200145 pxa_setbrg_dev (uart_index);
wdenkc6097192002-11-03 00:24:07 +0000146
147 return (0);
148}
149
150
151/*
152 * Output a single byte to the serial port.
153 */
stefano babic80172c62007-08-30 22:57:04 +0200154void pxa_putc_dev (unsigned int uart_index,const char c)
wdenkc6097192002-11-03 00:24:07 +0000155{
stefano babic80172c62007-08-30 22:57:04 +0200156 switch (uart_index) {
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200157 case FFUART_INDEX:
stefano babic80172c62007-08-30 22:57:04 +0200158 /* wait for room in the tx FIFO on FFUART */
159 while ((FFLSR & LSR_TEMT) == 0)
160 WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */
161 FFTHR = c;
162 break;
163
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200164 case BTUART_INDEX:
stefano babic80172c62007-08-30 22:57:04 +0200165 while ((BTLSR & LSR_TEMT ) == 0 )
166 WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */
167 BTTHR = c;
168 break;
169
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200170 case STUART_INDEX:
stefano babic80172c62007-08-30 22:57:04 +0200171 while ((STLSR & LSR_TEMT ) == 0 )
172 WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */
173 STTHR = c;
174 break;
175 }
wdenkc6097192002-11-03 00:24:07 +0000176
177 /* If \n, also do \r */
178 if (c == '\n')
stefano babic80172c62007-08-30 22:57:04 +0200179 pxa_putc_dev (uart_index,'\r');
wdenkc6097192002-11-03 00:24:07 +0000180}
181
182/*
183 * Read a single byte from the serial port. Returns 1 on success, 0
184 * otherwise. When the function is succesfull, the character read is
185 * written into its argument c.
186 */
stefano babic80172c62007-08-30 22:57:04 +0200187int pxa_tstc_dev (unsigned int uart_index)
wdenkc6097192002-11-03 00:24:07 +0000188{
stefano babic80172c62007-08-30 22:57:04 +0200189 switch (uart_index) {
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200190 case FFUART_INDEX:
stefano babic80172c62007-08-30 22:57:04 +0200191 return FFLSR & LSR_DR;
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200192 case BTUART_INDEX:
stefano babic80172c62007-08-30 22:57:04 +0200193 return BTLSR & LSR_DR;
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200194 case STUART_INDEX:
stefano babic80172c62007-08-30 22:57:04 +0200195 return STLSR & LSR_DR;
196 }
197 return -1;
wdenkc6097192002-11-03 00:24:07 +0000198}
199
200/*
201 * Read a single byte from the serial port. Returns 1 on success, 0
202 * otherwise. When the function is succesfull, the character read is
203 * written into its argument c.
204 */
stefano babic80172c62007-08-30 22:57:04 +0200205int pxa_getc_dev (unsigned int uart_index)
wdenkc6097192002-11-03 00:24:07 +0000206{
stefano babic80172c62007-08-30 22:57:04 +0200207 switch (uart_index) {
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200208 case FFUART_INDEX:
stefano babic80172c62007-08-30 22:57:04 +0200209 while (!(FFLSR & LSR_DR))
210 WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */
211 return (char) FFRBR & 0xff;
212
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200213 case BTUART_INDEX:
stefano babic80172c62007-08-30 22:57:04 +0200214 while (!(BTLSR & LSR_DR))
215 WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */
216 return (char) BTRBR & 0xff;
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200217 case STUART_INDEX:
stefano babic80172c62007-08-30 22:57:04 +0200218 while (!(STLSR & LSR_DR))
219 WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */
220 return (char) STRBR & 0xff;
221 }
222 return -1;
wdenkc6097192002-11-03 00:24:07 +0000223}
224
225void
stefano babic80172c62007-08-30 22:57:04 +0200226pxa_puts_dev (unsigned int uart_index,const char *s)
wdenkc6097192002-11-03 00:24:07 +0000227{
228 while (*s) {
stefano babic80172c62007-08-30 22:57:04 +0200229 pxa_putc_dev (uart_index,*s++);
wdenkc6097192002-11-03 00:24:07 +0000230 }
231}
stefano babic80172c62007-08-30 22:57:04 +0200232
233#if defined (CONFIG_FFUART)
234static int ffuart_init(void)
235{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200236 return pxa_init_dev(FFUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200237}
238
239static void ffuart_setbrg(void)
240{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200241 return pxa_setbrg_dev(FFUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200242}
243
244static void ffuart_putc(const char c)
245{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200246 return pxa_putc_dev(FFUART_INDEX,c);
stefano babic80172c62007-08-30 22:57:04 +0200247}
248
249static void ffuart_puts(const char *s)
250{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200251 return pxa_puts_dev(FFUART_INDEX,s);
stefano babic80172c62007-08-30 22:57:04 +0200252}
253
254static int ffuart_getc(void)
255{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200256 return pxa_getc_dev(FFUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200257}
258
259static int ffuart_tstc(void)
260{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200261 return pxa_tstc_dev(FFUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200262}
263
264struct serial_device serial_ffuart_device =
265{
266 "serial_ffuart",
267 "PXA",
268 ffuart_init,
Anatolij Gustschinfbb00302010-04-24 19:27:04 +0200269 NULL,
stefano babic80172c62007-08-30 22:57:04 +0200270 ffuart_setbrg,
271 ffuart_getc,
272 ffuart_tstc,
273 ffuart_putc,
274 ffuart_puts,
275};
276#endif
277
278#if defined (CONFIG_BTUART)
279static int btuart_init(void)
280{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200281 return pxa_init_dev(BTUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200282}
283
284static void btuart_setbrg(void)
285{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200286 return pxa_setbrg_dev(BTUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200287}
288
289static void btuart_putc(const char c)
290{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200291 return pxa_putc_dev(BTUART_INDEX,c);
stefano babic80172c62007-08-30 22:57:04 +0200292}
293
294static void btuart_puts(const char *s)
295{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200296 return pxa_puts_dev(BTUART_INDEX,s);
stefano babic80172c62007-08-30 22:57:04 +0200297}
298
299static int btuart_getc(void)
300{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200301 return pxa_getc_dev(BTUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200302}
303
304static int btuart_tstc(void)
305{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200306 return pxa_tstc_dev(BTUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200307}
308
309struct serial_device serial_btuart_device =
310{
311 "serial_btuart",
312 "PXA",
313 btuart_init,
Anatolij Gustschinfbb00302010-04-24 19:27:04 +0200314 NULL,
stefano babic80172c62007-08-30 22:57:04 +0200315 btuart_setbrg,
316 btuart_getc,
317 btuart_tstc,
318 btuart_putc,
319 btuart_puts,
320};
321#endif
322
323#if defined (CONFIG_STUART)
324static int stuart_init(void)
325{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200326 return pxa_init_dev(STUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200327}
328
329static void stuart_setbrg(void)
330{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200331 return pxa_setbrg_dev(STUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200332}
333
334static void stuart_putc(const char c)
335{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200336 return pxa_putc_dev(STUART_INDEX,c);
stefano babic80172c62007-08-30 22:57:04 +0200337}
338
339static void stuart_puts(const char *s)
340{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200341 return pxa_puts_dev(STUART_INDEX,s);
stefano babic80172c62007-08-30 22:57:04 +0200342}
343
344static int stuart_getc(void)
345{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200346 return pxa_getc_dev(STUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200347}
348
349static int stuart_tstc(void)
350{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200351 return pxa_tstc_dev(STUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200352}
353
354struct serial_device serial_stuart_device =
355{
356 "serial_stuart",
357 "PXA",
358 stuart_init,
Anatolij Gustschinfbb00302010-04-24 19:27:04 +0200359 NULL,
stefano babic80172c62007-08-30 22:57:04 +0200360 stuart_setbrg,
361 stuart_getc,
362 stuart_tstc,
363 stuart_putc,
364 stuart_puts,
365};
366#endif
367
368
369#ifndef CONFIG_SERIAL_MULTI
370inline int serial_init(void) {
371 return (pxa_init_dev(UART_INDEX));
372}
373void serial_setbrg(void) {
374 pxa_setbrg_dev(UART_INDEX);
375}
376int serial_getc(void) {
377 return(pxa_getc_dev(UART_INDEX));
378}
379int serial_tstc(void) {
380 return(pxa_tstc_dev(UART_INDEX));
381}
382void serial_putc(const char c) {
383 pxa_putc_dev(UART_INDEX,c);
384}
385void serial_puts(const char *s) {
386 pxa_puts_dev(UART_INDEX,s);
387}
388#endif /* CONFIG_SERIAL_MULTI */