xref: /openbmc/u-boot/drivers/serial/serial_pxa.c (revision 8875833a)
1 /*
2  * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
3  *
4  * (C) Copyright 2002
5  * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
6  *
7  * (C) Copyright 2002
8  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
9  * Marius Groeger <mgroeger@sysgo.de>
10  *
11  * (C) Copyright 2002
12  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
13  * Alex Zuepke <azu@sysgo.de>
14  *
15  * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
16  *
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation; either version 2 of the License, or
20  * (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
30  *
31  */
32 
33 #include <common.h>
34 #include <watchdog.h>
35 #include <serial.h>
36 #include <asm/arch/pxa-regs.h>
37 #include <asm/arch/regs-uart.h>
38 #include <asm/io.h>
39 
40 DECLARE_GLOBAL_DATA_PTR;
41 
42 /*
43  * The numbering scheme differs here for PXA25x, PXA27x and PXA3xx so we can
44  * easily handle enabling of clock.
45  */
46 #ifdef	CONFIG_CPU_MONAHANS
47 #define	UART_CLK_BASE	CKENA_21_BTUART
48 #define	UART_CLK_REG	CKENA
49 #define	BTUART_INDEX	0
50 #define	FFUART_INDEX	1
51 #define	STUART_INDEX	2
52 #elif	CONFIG_CPU_PXA25X
53 #define	UART_CLK_BASE	(1 << 4)	/* HWUART */
54 #define	UART_CLK_REG	CKEN
55 #define	HWUART_INDEX	0
56 #define	STUART_INDEX	1
57 #define	FFUART_INDEX	2
58 #define	BTUART_INDEX	3
59 #else	/* PXA27x */
60 #define	UART_CLK_BASE	CKEN5_STUART
61 #define	UART_CLK_REG	CKEN
62 #define	STUART_INDEX	0
63 #define	FFUART_INDEX	1
64 #define	BTUART_INDEX	2
65 #endif
66 
67 /*
68  * Only PXA250 has HWUART, to avoid poluting the code with more macros,
69  * artificially introduce this.
70  */
71 #ifndef	CONFIG_CPU_PXA25X
72 #define	HWUART_INDEX	0xff
73 #endif
74 
75 #ifndef CONFIG_SERIAL_MULTI
76 #if defined(CONFIG_FFUART)
77 #define UART_INDEX	FFUART_INDEX
78 #elif defined(CONFIG_BTUART)
79 #define UART_INDEX	BTUART_INDEX
80 #elif defined(CONFIG_STUART)
81 #define UART_INDEX	STUART_INDEX
82 #elif defined(CONFIG_HWUART)
83 #define UART_INDEX	HWUART_INDEX
84 #else
85 #error "Please select CONFIG_(FF|BT|ST|HW)UART in board config file."
86 #endif
87 #endif
88 
89 uint32_t pxa_uart_get_baud_divider(void)
90 {
91 	if (gd->baudrate == 1200)
92 		return 768;
93 	else if (gd->baudrate == 9600)
94 		return 96;
95 	else if (gd->baudrate == 19200)
96 		return 48;
97 	else if (gd->baudrate == 38400)
98 		return 24;
99 	else if (gd->baudrate == 57600)
100 		return 16;
101 	else if (gd->baudrate == 115200)
102 		return 8;
103 	else	/* Unsupported baudrate */
104 		return 0;
105 }
106 
107 struct pxa_uart_regs *pxa_uart_index_to_regs(uint32_t uart_index)
108 {
109 	switch (uart_index) {
110 	case FFUART_INDEX: return (struct pxa_uart_regs *)FFUART_BASE;
111 	case BTUART_INDEX: return (struct pxa_uart_regs *)BTUART_BASE;
112 	case STUART_INDEX: return (struct pxa_uart_regs *)STUART_BASE;
113 	case HWUART_INDEX: return (struct pxa_uart_regs *)HWUART_BASE;
114 	default:
115 		return NULL;
116 	}
117 }
118 
119 void pxa_uart_toggle_clock(uint32_t uart_index, int enable)
120 {
121 	uint32_t clk_reg, clk_offset, reg;
122 
123 	clk_reg = UART_CLK_REG;
124 	clk_offset = UART_CLK_BASE << uart_index;
125 
126 	reg = readl(clk_reg);
127 
128 	if (enable)
129 		reg |= clk_offset;
130 	else
131 		reg &= ~clk_offset;
132 
133 	writel(reg, clk_reg);
134 }
135 
136 /*
137  * Enable clock and set baud rate, parity etc.
138  */
139 void pxa_setbrg_dev(uint32_t uart_index)
140 {
141 	uint32_t divider = 0;
142 	struct pxa_uart_regs *uart_regs;
143 
144 	divider = pxa_uart_get_baud_divider();
145 	if (!divider)
146 		hang();
147 
148 	uart_regs = pxa_uart_index_to_regs(uart_index);
149 	if (!uart_regs)
150 		hang();
151 
152 	pxa_uart_toggle_clock(uart_index, 1);
153 
154 	/* Disable interrupts and FIFOs */
155 	writel(0, &uart_regs->ier);
156 	writel(0, &uart_regs->fcr);
157 
158 	/* Set baud rate */
159 	writel(LCR_WLS0 | LCR_WLS1 | LCR_DLAB, &uart_regs->lcr);
160 	writel(divider & 0xff, &uart_regs->dll);
161 	writel(divider >> 8, &uart_regs->dlh);
162 	writel(LCR_WLS0 | LCR_WLS1, &uart_regs->lcr);
163 
164 	/* Enable UART */
165 	writel(IER_UUE, &uart_regs->ier);
166 }
167 
168 /*
169  * Initialise the serial port with the given baudrate. The settings
170  * are always 8 data bits, no parity, 1 stop bit, no start bits.
171  */
172 int pxa_init_dev(unsigned int uart_index)
173 {
174 	pxa_setbrg_dev (uart_index);
175 	return 0;
176 }
177 
178 /*
179  * Output a single byte to the serial port.
180  */
181 void pxa_putc_dev(unsigned int uart_index, const char c)
182 {
183 	struct pxa_uart_regs *uart_regs;
184 
185 	uart_regs = pxa_uart_index_to_regs(uart_index);
186 	if (!uart_regs)
187 		hang();
188 
189 	while (!(readl(&uart_regs->lsr) & LSR_TEMT))
190 		WATCHDOG_RESET();
191 	writel(c, &uart_regs->thr);
192 
193 	/* If \n, also do \r */
194 	if (c == '\n')
195 		pxa_putc_dev (uart_index,'\r');
196 }
197 
198 /*
199  * Read a single byte from the serial port. Returns 1 on success, 0
200  * otherwise. When the function is succesfull, the character read is
201  * written into its argument c.
202  */
203 int pxa_tstc_dev(unsigned int uart_index)
204 {
205 	struct pxa_uart_regs *uart_regs;
206 
207 	uart_regs = pxa_uart_index_to_regs(uart_index);
208 	if (!uart_regs)
209 		return -1;
210 
211 	return readl(&uart_regs->lsr) & LSR_DR;
212 }
213 
214 /*
215  * Read a single byte from the serial port. Returns 1 on success, 0
216  * otherwise. When the function is succesfull, the character read is
217  * written into its argument c.
218  */
219 int pxa_getc_dev(unsigned int uart_index)
220 {
221 	struct pxa_uart_regs *uart_regs;
222 
223 	uart_regs = pxa_uart_index_to_regs(uart_index);
224 	if (!uart_regs)
225 		return -1;
226 
227 	while (!(readl(&uart_regs->lsr) & LSR_DR))
228 		WATCHDOG_RESET();
229 	return readl(&uart_regs->rbr) & 0xff;
230 }
231 
232 void pxa_puts_dev(unsigned int uart_index, const char *s)
233 {
234 	while (*s)
235 		pxa_putc_dev(uart_index, *s++);
236 }
237 
238 #define	pxa_uart(uart, UART)						\
239 	int uart##_init(void)						\
240 	{								\
241 		return pxa_init_dev(UART##_INDEX);			\
242 	}								\
243 									\
244 	void uart##_setbrg(void)					\
245 	{								\
246 		return pxa_setbrg_dev(UART##_INDEX);			\
247 	}								\
248 									\
249 	void uart##_putc(const char c)					\
250 	{								\
251 		return pxa_putc_dev(UART##_INDEX, c);			\
252 	}								\
253 									\
254 	void uart##_puts(const char *s)					\
255 	{								\
256 		return pxa_puts_dev(UART##_INDEX, s);			\
257 	}								\
258 									\
259 	int uart##_getc(void)						\
260 	{								\
261 		return pxa_getc_dev(UART##_INDEX);			\
262 	}								\
263 									\
264 	int uart##_tstc(void)						\
265 	{								\
266 		return pxa_tstc_dev(UART##_INDEX);			\
267 	}								\
268 
269 #define	pxa_uart_desc(uart)						\
270 	struct serial_device serial_##uart##_device =			\
271 	{								\
272 		"serial_"#uart,						\
273 		uart##_init,						\
274 		NULL,							\
275 		uart##_setbrg,						\
276 		uart##_getc,						\
277 		uart##_tstc,						\
278 		uart##_putc,						\
279 		uart##_puts,						\
280 	};
281 
282 #define	pxa_uart_multi(uart, UART)					\
283 	pxa_uart(uart, UART)						\
284 	pxa_uart_desc(uart)
285 
286 #if defined(CONFIG_HWUART)
287 	pxa_uart_multi(hwuart, HWUART)
288 #endif
289 #if defined(CONFIG_STUART)
290 	pxa_uart_multi(stuart, STUART)
291 #endif
292 #if defined(CONFIG_FFUART)
293 	pxa_uart_multi(ffuart, FFUART)
294 #endif
295 #if defined(CONFIG_BTUART)
296 	pxa_uart_multi(btuart, BTUART)
297 #endif
298 
299 #ifndef	CONFIG_SERIAL_MULTI
300 	pxa_uart(serial, UART)
301 #endif
302