blob: 9ba457e75aabfa97794a0689dbb6d0b3af191c2f [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>
wdenk5958f4a2003-09-18 09:21:33 +000032#include <watchdog.h>
stefano babic5ab4f032007-08-30 22:57:04 +020033#include <serial.h>
wdenkc6097192002-11-03 00:24:07 +000034#include <asm/arch/pxa-regs.h>
35
Wolfgang Denk6405a152006-03-31 18:32:53 +020036DECLARE_GLOBAL_DATA_PTR;
37
Marcel Ziswiler53761bc2007-10-19 00:25:33 +020038#define FFUART_INDEX 0
39#define BTUART_INDEX 1
40#define STUART_INDEX 2
stefano babic5ab4f032007-08-30 22:57:04 +020041
42#ifndef CONFIG_SERIAL_MULTI
43#if defined (CONFIG_FFUART)
Marcel Ziswiler53761bc2007-10-19 00:25:33 +020044#define UART_INDEX FFUART_INDEX
stefano babic5ab4f032007-08-30 22:57:04 +020045#elif defined (CONFIG_BTUART)
Marcel Ziswiler53761bc2007-10-19 00:25:33 +020046#define UART_INDEX BTUART_INDEX
stefano babic5ab4f032007-08-30 22:57:04 +020047#elif defined (CONFIG_STUART)
Marcel Ziswiler53761bc2007-10-19 00:25:33 +020048#define UART_INDEX STUART_INDEX
stefano babic5ab4f032007-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)
wdenk5958f4a2003-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 babic5ab4f032007-08-30 22:57:04 +020073 switch (uart_index) {
Marcel Ziswiler53761bc2007-10-19 00:25:33 +020074 case FFUART_INDEX:
Markus Klotzbücher21e69a02006-02-07 20:04:48 +010075#ifdef CONFIG_CPU_MONAHANS
stefano babic5ab4f032007-08-30 22:57:04 +020076 CKENA |= CKENA_22_FFUART;
Markus Klotzbücher21e69a02006-02-07 20:04:48 +010077#else
stefano babic5ab4f032007-08-30 22:57:04 +020078 CKEN |= CKEN6_FFUART;
Markus Klotzbücher21e69a02006-02-07 20:04:48 +010079#endif /* CONFIG_CPU_MONAHANS */
wdenkc6097192002-11-03 00:24:07 +000080
stefano babic5ab4f032007-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 babic5ab4f032007-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 babic5ab4f032007-08-30 22:57:04 +020090 FFIER = IER_UUE; /* Enable FFUART */
91 break;
wdenkc6097192002-11-03 00:24:07 +000092
Marcel Ziswiler53761bc2007-10-19 00:25:33 +020093 case BTUART_INDEX:
Markus Klotzbücher21e69a02006-02-07 20:04:48 +010094#ifdef CONFIG_CPU_MONAHANS
stefano babic5ab4f032007-08-30 22:57:04 +020095 CKENA |= CKENA_21_BTUART;
Markus Klotzbücher21e69a02006-02-07 20:04:48 +010096#else
stefano babic5ab4f032007-08-30 22:57:04 +020097 CKEN |= CKEN7_BTUART;
Markus Klotzbücher21e69a02006-02-07 20:04:48 +010098#endif /* CONFIG_CPU_MONAHANS */
wdenkb02744a2003-04-05 00:53:31 +000099
stefano babic5ab4f032007-08-30 22:57:04 +0200100 BTIER = 0;
101 BTFCR = 0;
wdenkb02744a2003-04-05 00:53:31 +0000102
stefano babic5ab4f032007-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;
wdenkb02744a2003-04-05 00:53:31 +0000108
stefano babic5ab4f032007-08-30 22:57:04 +0200109 BTIER = IER_UUE; /* Enable BFUART */
wdenkb02744a2003-04-05 00:53:31 +0000110
stefano babic5ab4f032007-08-30 22:57:04 +0200111 break;
112
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200113 case STUART_INDEX:
Markus Klotzbücher21e69a02006-02-07 20:04:48 +0100114#ifdef CONFIG_CPU_MONAHANS
stefano babic5ab4f032007-08-30 22:57:04 +0200115 CKENA |= CKENA_23_STUART;
Markus Klotzbücher21e69a02006-02-07 20:04:48 +0100116#else
stefano babic5ab4f032007-08-30 22:57:04 +0200117 CKEN |= CKEN5_STUART;
Markus Klotzbücher21e69a02006-02-07 20:04:48 +0100118#endif /* CONFIG_CPU_MONAHANS */
wdenk5958f4a2003-09-18 09:21:33 +0000119
stefano babic5ab4f032007-08-30 22:57:04 +0200120 STIER = 0;
121 STFCR = 0;
wdenk5958f4a2003-09-18 09:21:33 +0000122
stefano babic5ab4f032007-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;
wdenk5958f4a2003-09-18 09:21:33 +0000128
stefano babic5ab4f032007-08-30 22:57:04 +0200129 STIER = IER_UUE; /* Enable STUART */
130 break;
wdenk5958f4a2003-09-18 09:21:33 +0000131
stefano babic5ab4f032007-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 babic5ab4f032007-08-30 22:57:04 +0200143int pxa_init_dev (unsigned int uart_index)
wdenkc6097192002-11-03 00:24:07 +0000144{
stefano babic5ab4f032007-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 babic5ab4f032007-08-30 22:57:04 +0200154void pxa_putc_dev (unsigned int uart_index,const char c)
wdenkc6097192002-11-03 00:24:07 +0000155{
stefano babic5ab4f032007-08-30 22:57:04 +0200156 switch (uart_index) {
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200157 case FFUART_INDEX:
stefano babic5ab4f032007-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 Ziswiler53761bc2007-10-19 00:25:33 +0200164 case BTUART_INDEX:
stefano babic5ab4f032007-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 Ziswiler53761bc2007-10-19 00:25:33 +0200170 case STUART_INDEX:
stefano babic5ab4f032007-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 babic5ab4f032007-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 babic5ab4f032007-08-30 22:57:04 +0200187int pxa_tstc_dev (unsigned int uart_index)
wdenkc6097192002-11-03 00:24:07 +0000188{
stefano babic5ab4f032007-08-30 22:57:04 +0200189 switch (uart_index) {
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200190 case FFUART_INDEX:
stefano babic5ab4f032007-08-30 22:57:04 +0200191 return FFLSR & LSR_DR;
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200192 case BTUART_INDEX:
stefano babic5ab4f032007-08-30 22:57:04 +0200193 return BTLSR & LSR_DR;
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200194 case STUART_INDEX:
stefano babic5ab4f032007-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 babic5ab4f032007-08-30 22:57:04 +0200205int pxa_getc_dev (unsigned int uart_index)
wdenkc6097192002-11-03 00:24:07 +0000206{
stefano babic5ab4f032007-08-30 22:57:04 +0200207 switch (uart_index) {
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200208 case FFUART_INDEX:
stefano babic5ab4f032007-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 Ziswiler53761bc2007-10-19 00:25:33 +0200213 case BTUART_INDEX:
stefano babic5ab4f032007-08-30 22:57:04 +0200214 while (!(BTLSR & LSR_DR))
215 WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */
216 return (char) BTRBR & 0xff;
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200217 case STUART_INDEX:
stefano babic5ab4f032007-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 babic5ab4f032007-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 babic5ab4f032007-08-30 22:57:04 +0200229 pxa_putc_dev (uart_index,*s++);
wdenkc6097192002-11-03 00:24:07 +0000230 }
231}
stefano babic5ab4f032007-08-30 22:57:04 +0200232
233#if defined (CONFIG_FFUART)
234static int ffuart_init(void)
235{
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200236 return pxa_init_dev(FFUART_INDEX);
stefano babic5ab4f032007-08-30 22:57:04 +0200237}
238
239static void ffuart_setbrg(void)
240{
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200241 return pxa_setbrg_dev(FFUART_INDEX);
stefano babic5ab4f032007-08-30 22:57:04 +0200242}
243
244static void ffuart_putc(const char c)
245{
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200246 return pxa_putc_dev(FFUART_INDEX,c);
stefano babic5ab4f032007-08-30 22:57:04 +0200247}
248
249static void ffuart_puts(const char *s)
250{
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200251 return pxa_puts_dev(FFUART_INDEX,s);
stefano babic5ab4f032007-08-30 22:57:04 +0200252}
253
254static int ffuart_getc(void)
255{
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200256 return pxa_getc_dev(FFUART_INDEX);
stefano babic5ab4f032007-08-30 22:57:04 +0200257}
258
259static int ffuart_tstc(void)
260{
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200261 return pxa_tstc_dev(FFUART_INDEX);
stefano babic5ab4f032007-08-30 22:57:04 +0200262}
263
264struct serial_device serial_ffuart_device =
265{
266 "serial_ffuart",
267 "PXA",
268 ffuart_init,
269 ffuart_setbrg,
270 ffuart_getc,
271 ffuart_tstc,
272 ffuart_putc,
273 ffuart_puts,
274};
275#endif
276
277#if defined (CONFIG_BTUART)
278static int btuart_init(void)
279{
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200280 return pxa_init_dev(BTUART_INDEX);
stefano babic5ab4f032007-08-30 22:57:04 +0200281}
282
283static void btuart_setbrg(void)
284{
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200285 return pxa_setbrg_dev(BTUART_INDEX);
stefano babic5ab4f032007-08-30 22:57:04 +0200286}
287
288static void btuart_putc(const char c)
289{
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200290 return pxa_putc_dev(BTUART_INDEX,c);
stefano babic5ab4f032007-08-30 22:57:04 +0200291}
292
293static void btuart_puts(const char *s)
294{
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200295 return pxa_puts_dev(BTUART_INDEX,s);
stefano babic5ab4f032007-08-30 22:57:04 +0200296}
297
298static int btuart_getc(void)
299{
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200300 return pxa_getc_dev(BTUART_INDEX);
stefano babic5ab4f032007-08-30 22:57:04 +0200301}
302
303static int btuart_tstc(void)
304{
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200305 return pxa_tstc_dev(BTUART_INDEX);
stefano babic5ab4f032007-08-30 22:57:04 +0200306}
307
308struct serial_device serial_btuart_device =
309{
310 "serial_btuart",
311 "PXA",
312 btuart_init,
313 btuart_setbrg,
314 btuart_getc,
315 btuart_tstc,
316 btuart_putc,
317 btuart_puts,
318};
319#endif
320
321#if defined (CONFIG_STUART)
322static int stuart_init(void)
323{
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200324 return pxa_init_dev(STUART_INDEX);
stefano babic5ab4f032007-08-30 22:57:04 +0200325}
326
327static void stuart_setbrg(void)
328{
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200329 return pxa_setbrg_dev(STUART_INDEX);
stefano babic5ab4f032007-08-30 22:57:04 +0200330}
331
332static void stuart_putc(const char c)
333{
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200334 return pxa_putc_dev(STUART_INDEX,c);
stefano babic5ab4f032007-08-30 22:57:04 +0200335}
336
337static void stuart_puts(const char *s)
338{
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200339 return pxa_puts_dev(STUART_INDEX,s);
stefano babic5ab4f032007-08-30 22:57:04 +0200340}
341
342static int stuart_getc(void)
343{
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200344 return pxa_getc_dev(STUART_INDEX);
stefano babic5ab4f032007-08-30 22:57:04 +0200345}
346
347static int stuart_tstc(void)
348{
Marcel Ziswiler53761bc2007-10-19 00:25:33 +0200349 return pxa_tstc_dev(STUART_INDEX);
stefano babic5ab4f032007-08-30 22:57:04 +0200350}
351
352struct serial_device serial_stuart_device =
353{
354 "serial_stuart",
355 "PXA",
356 stuart_init,
357 stuart_setbrg,
358 stuart_getc,
359 stuart_tstc,
360 stuart_putc,
361 stuart_puts,
362};
363#endif
364
365
366#ifndef CONFIG_SERIAL_MULTI
367inline int serial_init(void) {
368 return (pxa_init_dev(UART_INDEX));
369}
370void serial_setbrg(void) {
371 pxa_setbrg_dev(UART_INDEX);
372}
373int serial_getc(void) {
374 return(pxa_getc_dev(UART_INDEX));
375}
376int serial_tstc(void) {
377 return(pxa_tstc_dev(UART_INDEX));
378}
379void serial_putc(const char c) {
380 pxa_putc_dev(UART_INDEX,c);
381}
382void serial_puts(const char *s) {
383 pxa_puts_dev(UART_INDEX,s);
384}
385#endif /* CONFIG_SERIAL_MULTI */