blob: 68469a4f358409673d4882061bd461784ad6906c [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>
Marek Vasut3ba8bf72010-09-09 09:50:39 +020035#include <asm/io.h>
wdenkc6097192002-11-03 00:24:07 +000036
Wolfgang Denkd87080b2006-03-31 18:32:53 +020037DECLARE_GLOBAL_DATA_PTR;
38
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +020039#define FFUART_INDEX 0
40#define BTUART_INDEX 1
41#define STUART_INDEX 2
stefano babic80172c62007-08-30 22:57:04 +020042
43#ifndef CONFIG_SERIAL_MULTI
44#if defined (CONFIG_FFUART)
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +020045#define UART_INDEX FFUART_INDEX
stefano babic80172c62007-08-30 22:57:04 +020046#elif defined (CONFIG_BTUART)
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +020047#define UART_INDEX BTUART_INDEX
stefano babic80172c62007-08-30 22:57:04 +020048#elif defined (CONFIG_STUART)
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +020049#define UART_INDEX STUART_INDEX
stefano babic80172c62007-08-30 22:57:04 +020050#else
51#error "Bad: you didn't configure serial ..."
52#endif
53#endif
54
55void pxa_setbrg_dev (unsigned int uart_index)
wdenkc6097192002-11-03 00:24:07 +000056{
wdenkc6097192002-11-03 00:24:07 +000057 unsigned int quot = 0;
58
59 if (gd->baudrate == 1200)
wdenk5f535fe2003-09-18 09:21:33 +000060 quot = 768;
wdenkc6097192002-11-03 00:24:07 +000061 else if (gd->baudrate == 9600)
62 quot = 96;
63 else if (gd->baudrate == 19200)
64 quot = 48;
65 else if (gd->baudrate == 38400)
66 quot = 24;
67 else if (gd->baudrate == 57600)
68 quot = 16;
69 else if (gd->baudrate == 115200)
70 quot = 8;
71 else
72 hang ();
73
stefano babic80172c62007-08-30 22:57:04 +020074 switch (uart_index) {
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +020075 case FFUART_INDEX:
Markus Klotzbüchere0269572006-02-07 20:04:48 +010076#ifdef CONFIG_CPU_MONAHANS
Marek Vasut3ba8bf72010-09-09 09:50:39 +020077 writel(readl(CKENA) | CKENA_22_FFUART, CKENA);
Markus Klotzbüchere0269572006-02-07 20:04:48 +010078#else
Marek Vasut3ba8bf72010-09-09 09:50:39 +020079 writel(readl(CKEN) | CKEN6_FFUART, CKEN);
Markus Klotzbüchere0269572006-02-07 20:04:48 +010080#endif /* CONFIG_CPU_MONAHANS */
wdenkc6097192002-11-03 00:24:07 +000081
Marek Vasut3ba8bf72010-09-09 09:50:39 +020082 writel(0, FFIER); /* Disable for now */
83 writel(0, FFFCR); /* No fifos enabled */
wdenkc6097192002-11-03 00:24:07 +000084
stefano babic80172c62007-08-30 22:57:04 +020085 /* set baud rate */
Marek Vasut3ba8bf72010-09-09 09:50:39 +020086 writel(LCR_WLS0 | LCR_WLS1 | LCR_DLAB, FFLCR);
87 writel(quot & 0xff, FFDLL);
88 writel(quot >> 8, FFDLH);
89 writel(LCR_WLS0 | LCR_WLS1, FFLCR);
wdenkc6097192002-11-03 00:24:07 +000090
Marek Vasut3ba8bf72010-09-09 09:50:39 +020091 writel(IER_UUE, FFIER); /* Enable FFUART */
stefano babic80172c62007-08-30 22:57:04 +020092 break;
wdenkc6097192002-11-03 00:24:07 +000093
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +020094 case BTUART_INDEX:
Markus Klotzbüchere0269572006-02-07 20:04:48 +010095#ifdef CONFIG_CPU_MONAHANS
Marek Vasut3ba8bf72010-09-09 09:50:39 +020096 writel(readl(CKENA) | CKENA_21_BTUART, CKENA);
Markus Klotzbüchere0269572006-02-07 20:04:48 +010097#else
Marek Vasut3ba8bf72010-09-09 09:50:39 +020098 writel(readl(CKEN) | CKEN7_BTUART, CKEN);
Markus Klotzbüchere0269572006-02-07 20:04:48 +010099#endif /* CONFIG_CPU_MONAHANS */
wdenk3e386912003-04-05 00:53:31 +0000100
Marek Vasut3ba8bf72010-09-09 09:50:39 +0200101 writel(0, BTIER);
102 writel(0, BTFCR);
wdenk3e386912003-04-05 00:53:31 +0000103
stefano babic80172c62007-08-30 22:57:04 +0200104 /* set baud rate */
Marek Vasut3ba8bf72010-09-09 09:50:39 +0200105 writel(LCR_DLAB, BTLCR);
106 writel(quot & 0xff, BTDLL);
107 writel(quot >> 8, BTDLH);
108 writel(LCR_WLS0 | LCR_WLS1, BTLCR);
wdenk3e386912003-04-05 00:53:31 +0000109
Marek Vasut3ba8bf72010-09-09 09:50:39 +0200110 writel(IER_UUE, BTIER); /* Enable BFUART */
wdenk3e386912003-04-05 00:53:31 +0000111
stefano babic80172c62007-08-30 22:57:04 +0200112 break;
113
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200114 case STUART_INDEX:
Markus Klotzbüchere0269572006-02-07 20:04:48 +0100115#ifdef CONFIG_CPU_MONAHANS
Marek Vasut3ba8bf72010-09-09 09:50:39 +0200116 writel(readl(CKENA) | CKENA_23_STUART, CKENA);
Markus Klotzbüchere0269572006-02-07 20:04:48 +0100117#else
Marek Vasut3ba8bf72010-09-09 09:50:39 +0200118 writel(readl(CKEN) | CKEN5_STUART, CKEN);
Markus Klotzbüchere0269572006-02-07 20:04:48 +0100119#endif /* CONFIG_CPU_MONAHANS */
wdenk5f535fe2003-09-18 09:21:33 +0000120
Marek Vasut3ba8bf72010-09-09 09:50:39 +0200121 writel(0, STIER);
122 writel(0, STFCR);
wdenk5f535fe2003-09-18 09:21:33 +0000123
stefano babic80172c62007-08-30 22:57:04 +0200124 /* set baud rate */
Marek Vasut3ba8bf72010-09-09 09:50:39 +0200125 writel(LCR_DLAB, STLCR);
126 writel(quot & 0xff, STDLL);
127 writel(quot >> 8, STDLH);
128 writel(LCR_WLS0 | LCR_WLS1, STLCR);
wdenk5f535fe2003-09-18 09:21:33 +0000129
Marek Vasut3ba8bf72010-09-09 09:50:39 +0200130 writel(IER_UUE, STIER); /* Enable STUART */
stefano babic80172c62007-08-30 22:57:04 +0200131 break;
wdenk5f535fe2003-09-18 09:21:33 +0000132
stefano babic80172c62007-08-30 22:57:04 +0200133 default:
134 hang();
135 }
wdenkc6097192002-11-03 00:24:07 +0000136}
137
138
139/*
140 * Initialise the serial port with the given baudrate. The settings
141 * are always 8 data bits, no parity, 1 stop bit, no start bits.
142 *
143 */
stefano babic80172c62007-08-30 22:57:04 +0200144int pxa_init_dev (unsigned int uart_index)
wdenkc6097192002-11-03 00:24:07 +0000145{
stefano babic80172c62007-08-30 22:57:04 +0200146 pxa_setbrg_dev (uart_index);
wdenkc6097192002-11-03 00:24:07 +0000147
148 return (0);
149}
150
151
152/*
153 * Output a single byte to the serial port.
154 */
stefano babic80172c62007-08-30 22:57:04 +0200155void pxa_putc_dev (unsigned int uart_index,const char c)
wdenkc6097192002-11-03 00:24:07 +0000156{
stefano babic80172c62007-08-30 22:57:04 +0200157 switch (uart_index) {
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200158 case FFUART_INDEX:
stefano babic80172c62007-08-30 22:57:04 +0200159 /* wait for room in the tx FIFO on FFUART */
Marek Vasut3ba8bf72010-09-09 09:50:39 +0200160 while ((readl(FFLSR) & LSR_TEMT) == 0)
stefano babic80172c62007-08-30 22:57:04 +0200161 WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */
Marek Vasut3ba8bf72010-09-09 09:50:39 +0200162 writel(c, FFTHR);
stefano babic80172c62007-08-30 22:57:04 +0200163 break;
164
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200165 case BTUART_INDEX:
Marek Vasut3ba8bf72010-09-09 09:50:39 +0200166 while ((readl(BTLSR) & LSR_TEMT) == 0)
stefano babic80172c62007-08-30 22:57:04 +0200167 WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */
Marek Vasut3ba8bf72010-09-09 09:50:39 +0200168 writel(c, BTTHR);
stefano babic80172c62007-08-30 22:57:04 +0200169 break;
170
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200171 case STUART_INDEX:
Marek Vasut3ba8bf72010-09-09 09:50:39 +0200172 while ((readl(STLSR) & LSR_TEMT) == 0)
stefano babic80172c62007-08-30 22:57:04 +0200173 WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */
Marek Vasut3ba8bf72010-09-09 09:50:39 +0200174 writel(c, STTHR);
stefano babic80172c62007-08-30 22:57:04 +0200175 break;
176 }
wdenkc6097192002-11-03 00:24:07 +0000177
178 /* If \n, also do \r */
179 if (c == '\n')
stefano babic80172c62007-08-30 22:57:04 +0200180 pxa_putc_dev (uart_index,'\r');
wdenkc6097192002-11-03 00:24:07 +0000181}
182
183/*
184 * Read a single byte from the serial port. Returns 1 on success, 0
185 * otherwise. When the function is succesfull, the character read is
186 * written into its argument c.
187 */
stefano babic80172c62007-08-30 22:57:04 +0200188int pxa_tstc_dev (unsigned int uart_index)
wdenkc6097192002-11-03 00:24:07 +0000189{
stefano babic80172c62007-08-30 22:57:04 +0200190 switch (uart_index) {
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200191 case FFUART_INDEX:
Marek Vasut3ba8bf72010-09-09 09:50:39 +0200192 return readl(FFLSR) & LSR_DR;
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200193 case BTUART_INDEX:
Marek Vasut3ba8bf72010-09-09 09:50:39 +0200194 return readl(BTLSR) & LSR_DR;
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200195 case STUART_INDEX:
Marek Vasut3ba8bf72010-09-09 09:50:39 +0200196 return readl(STLSR) & LSR_DR;
stefano babic80172c62007-08-30 22:57:04 +0200197 }
198 return -1;
wdenkc6097192002-11-03 00:24:07 +0000199}
200
201/*
202 * Read a single byte from the serial port. Returns 1 on success, 0
203 * otherwise. When the function is succesfull, the character read is
204 * written into its argument c.
205 */
stefano babic80172c62007-08-30 22:57:04 +0200206int pxa_getc_dev (unsigned int uart_index)
wdenkc6097192002-11-03 00:24:07 +0000207{
stefano babic80172c62007-08-30 22:57:04 +0200208 switch (uart_index) {
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200209 case FFUART_INDEX:
Marek Vasut3ba8bf72010-09-09 09:50:39 +0200210 while (!(readl(FFLSR) & LSR_DR))
211 /* Reset HW Watchdog, if needed */
212 WATCHDOG_RESET();
213 return (char) readl(FFRBR) & 0xff;
stefano babic80172c62007-08-30 22:57:04 +0200214
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200215 case BTUART_INDEX:
Marek Vasut3ba8bf72010-09-09 09:50:39 +0200216 while (!(readl(BTLSR) & LSR_DR))
217 /* Reset HW Watchdog, if needed */
218 WATCHDOG_RESET();
219 return (char) readl(BTRBR) & 0xff;
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200220 case STUART_INDEX:
Marek Vasut3ba8bf72010-09-09 09:50:39 +0200221 while (!(readl(STLSR) & LSR_DR))
222 /* Reset HW Watchdog, if needed */
223 WATCHDOG_RESET();
224 return (char) readl(STRBR) & 0xff;
stefano babic80172c62007-08-30 22:57:04 +0200225 }
226 return -1;
wdenkc6097192002-11-03 00:24:07 +0000227}
228
229void
stefano babic80172c62007-08-30 22:57:04 +0200230pxa_puts_dev (unsigned int uart_index,const char *s)
wdenkc6097192002-11-03 00:24:07 +0000231{
232 while (*s) {
stefano babic80172c62007-08-30 22:57:04 +0200233 pxa_putc_dev (uart_index,*s++);
wdenkc6097192002-11-03 00:24:07 +0000234 }
235}
stefano babic80172c62007-08-30 22:57:04 +0200236
237#if defined (CONFIG_FFUART)
238static int ffuart_init(void)
239{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200240 return pxa_init_dev(FFUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200241}
242
243static void ffuart_setbrg(void)
244{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200245 return pxa_setbrg_dev(FFUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200246}
247
248static void ffuart_putc(const char c)
249{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200250 return pxa_putc_dev(FFUART_INDEX,c);
stefano babic80172c62007-08-30 22:57:04 +0200251}
252
253static void ffuart_puts(const char *s)
254{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200255 return pxa_puts_dev(FFUART_INDEX,s);
stefano babic80172c62007-08-30 22:57:04 +0200256}
257
258static int ffuart_getc(void)
259{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200260 return pxa_getc_dev(FFUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200261}
262
263static int ffuart_tstc(void)
264{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200265 return pxa_tstc_dev(FFUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200266}
267
268struct serial_device serial_ffuart_device =
269{
270 "serial_ffuart",
stefano babic80172c62007-08-30 22:57:04 +0200271 ffuart_init,
Anatolij Gustschinfbb00302010-04-24 19:27:04 +0200272 NULL,
stefano babic80172c62007-08-30 22:57:04 +0200273 ffuart_setbrg,
274 ffuart_getc,
275 ffuart_tstc,
276 ffuart_putc,
277 ffuart_puts,
278};
279#endif
280
281#if defined (CONFIG_BTUART)
282static int btuart_init(void)
283{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200284 return pxa_init_dev(BTUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200285}
286
287static void btuart_setbrg(void)
288{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200289 return pxa_setbrg_dev(BTUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200290}
291
292static void btuart_putc(const char c)
293{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200294 return pxa_putc_dev(BTUART_INDEX,c);
stefano babic80172c62007-08-30 22:57:04 +0200295}
296
297static void btuart_puts(const char *s)
298{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200299 return pxa_puts_dev(BTUART_INDEX,s);
stefano babic80172c62007-08-30 22:57:04 +0200300}
301
302static int btuart_getc(void)
303{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200304 return pxa_getc_dev(BTUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200305}
306
307static int btuart_tstc(void)
308{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200309 return pxa_tstc_dev(BTUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200310}
311
312struct serial_device serial_btuart_device =
313{
314 "serial_btuart",
stefano babic80172c62007-08-30 22:57:04 +0200315 btuart_init,
Anatolij Gustschinfbb00302010-04-24 19:27:04 +0200316 NULL,
stefano babic80172c62007-08-30 22:57:04 +0200317 btuart_setbrg,
318 btuart_getc,
319 btuart_tstc,
320 btuart_putc,
321 btuart_puts,
322};
323#endif
324
325#if defined (CONFIG_STUART)
326static int stuart_init(void)
327{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200328 return pxa_init_dev(STUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200329}
330
331static void stuart_setbrg(void)
332{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200333 return pxa_setbrg_dev(STUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200334}
335
336static void stuart_putc(const char c)
337{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200338 return pxa_putc_dev(STUART_INDEX,c);
stefano babic80172c62007-08-30 22:57:04 +0200339}
340
341static void stuart_puts(const char *s)
342{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200343 return pxa_puts_dev(STUART_INDEX,s);
stefano babic80172c62007-08-30 22:57:04 +0200344}
345
346static int stuart_getc(void)
347{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200348 return pxa_getc_dev(STUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200349}
350
351static int stuart_tstc(void)
352{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200353 return pxa_tstc_dev(STUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200354}
355
356struct serial_device serial_stuart_device =
357{
358 "serial_stuart",
stefano babic80172c62007-08-30 22:57:04 +0200359 stuart_init,
Anatolij Gustschinfbb00302010-04-24 19:27:04 +0200360 NULL,
stefano babic80172c62007-08-30 22:57:04 +0200361 stuart_setbrg,
362 stuart_getc,
363 stuart_tstc,
364 stuart_putc,
365 stuart_puts,
366};
367#endif
368
369
370#ifndef CONFIG_SERIAL_MULTI
371inline int serial_init(void) {
372 return (pxa_init_dev(UART_INDEX));
373}
374void serial_setbrg(void) {
375 pxa_setbrg_dev(UART_INDEX);
376}
377int serial_getc(void) {
378 return(pxa_getc_dev(UART_INDEX));
379}
380int serial_tstc(void) {
381 return(pxa_tstc_dev(UART_INDEX));
382}
383void serial_putc(const char c) {
384 pxa_putc_dev(UART_INDEX,c);
385}
386void serial_puts(const char *s) {
387 pxa_puts_dev(UART_INDEX,s);
388}
389#endif /* CONFIG_SERIAL_MULTI */