blob: e4579801f2dde5af9cc9e688a9c1078449f965f1 [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",
271 "PXA",
272 ffuart_init,
Anatolij Gustschinfbb00302010-04-24 19:27:04 +0200273 NULL,
stefano babic80172c62007-08-30 22:57:04 +0200274 ffuart_setbrg,
275 ffuart_getc,
276 ffuart_tstc,
277 ffuart_putc,
278 ffuart_puts,
279};
280#endif
281
282#if defined (CONFIG_BTUART)
283static int btuart_init(void)
284{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200285 return pxa_init_dev(BTUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200286}
287
288static void btuart_setbrg(void)
289{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200290 return pxa_setbrg_dev(BTUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200291}
292
293static void btuart_putc(const char c)
294{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200295 return pxa_putc_dev(BTUART_INDEX,c);
stefano babic80172c62007-08-30 22:57:04 +0200296}
297
298static void btuart_puts(const char *s)
299{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200300 return pxa_puts_dev(BTUART_INDEX,s);
stefano babic80172c62007-08-30 22:57:04 +0200301}
302
303static int btuart_getc(void)
304{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200305 return pxa_getc_dev(BTUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200306}
307
308static int btuart_tstc(void)
309{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200310 return pxa_tstc_dev(BTUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200311}
312
313struct serial_device serial_btuart_device =
314{
315 "serial_btuart",
316 "PXA",
317 btuart_init,
Anatolij Gustschinfbb00302010-04-24 19:27:04 +0200318 NULL,
stefano babic80172c62007-08-30 22:57:04 +0200319 btuart_setbrg,
320 btuart_getc,
321 btuart_tstc,
322 btuart_putc,
323 btuart_puts,
324};
325#endif
326
327#if defined (CONFIG_STUART)
328static int stuart_init(void)
329{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200330 return pxa_init_dev(STUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200331}
332
333static void stuart_setbrg(void)
334{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200335 return pxa_setbrg_dev(STUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200336}
337
338static void stuart_putc(const char c)
339{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200340 return pxa_putc_dev(STUART_INDEX,c);
stefano babic80172c62007-08-30 22:57:04 +0200341}
342
343static void stuart_puts(const char *s)
344{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200345 return pxa_puts_dev(STUART_INDEX,s);
stefano babic80172c62007-08-30 22:57:04 +0200346}
347
348static int stuart_getc(void)
349{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200350 return pxa_getc_dev(STUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200351}
352
353static int stuart_tstc(void)
354{
Marcel Ziswiler2a4741d2007-10-19 00:25:33 +0200355 return pxa_tstc_dev(STUART_INDEX);
stefano babic80172c62007-08-30 22:57:04 +0200356}
357
358struct serial_device serial_stuart_device =
359{
360 "serial_stuart",
361 "PXA",
362 stuart_init,
Anatolij Gustschinfbb00302010-04-24 19:27:04 +0200363 NULL,
stefano babic80172c62007-08-30 22:57:04 +0200364 stuart_setbrg,
365 stuart_getc,
366 stuart_tstc,
367 stuart_putc,
368 stuart_puts,
369};
370#endif
371
372
373#ifndef CONFIG_SERIAL_MULTI
374inline int serial_init(void) {
375 return (pxa_init_dev(UART_INDEX));
376}
377void serial_setbrg(void) {
378 pxa_setbrg_dev(UART_INDEX);
379}
380int serial_getc(void) {
381 return(pxa_getc_dev(UART_INDEX));
382}
383int serial_tstc(void) {
384 return(pxa_tstc_dev(UART_INDEX));
385}
386void serial_putc(const char c) {
387 pxa_putc_dev(UART_INDEX,c);
388}
389void serial_puts(const char *s) {
390 pxa_puts_dev(UART_INDEX,s);
391}
392#endif /* CONFIG_SERIAL_MULTI */