blob: cf4d8f64427240d03d12def7b43e991a29074070 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenkc6097192002-11-03 00:24:07 +00002/*
Marek Vasutac737ff2011-08-28 03:35:13 +02003 * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
4 *
wdenkc6097192002-11-03 00:24:07 +00005 * (C) Copyright 2002
6 * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
7 *
8 * (C) Copyright 2002
9 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
10 * Marius Groeger <mgroeger@sysgo.de>
11 *
12 * (C) Copyright 2002
13 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
14 * Alex Zuepke <azu@sysgo.de>
15 *
16 * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
17 *
Marcel Ziswiler90392d02016-11-14 21:40:26 +010018 * Modified to add driver model (DM) support
19 * (C) Copyright 2016 Marcel Ziswiler <marcel.ziswiler@toradex.com>
wdenkc6097192002-11-03 00:24:07 +000020 */
21
22#include <common.h>
23#include <asm/arch/pxa-regs.h>
Marek Vasutac737ff2011-08-28 03:35:13 +020024#include <asm/arch/regs-uart.h>
Marek Vasut2db1e962010-09-09 09:50:39 +020025#include <asm/io.h>
Marcel Ziswiler90392d02016-11-14 21:40:26 +010026#include <dm.h>
27#include <dm/platform_data/serial_pxa.h>
Marek Vasutbc53d142012-09-12 12:26:30 +020028#include <linux/compiler.h>
Marcel Ziswiler7cfcbee2015-08-16 04:16:29 +020029#include <serial.h>
30#include <watchdog.h>
wdenkc6097192002-11-03 00:24:07 +000031
Wolfgang Denk6405a152006-03-31 18:32:53 +020032DECLARE_GLOBAL_DATA_PTR;
33
Marcel Ziswiler90392d02016-11-14 21:40:26 +010034static uint32_t pxa_uart_get_baud_divider(int baudrate)
Marek Vasutac737ff2011-08-28 03:35:13 +020035{
Marcel Ziswiler90392d02016-11-14 21:40:26 +010036 return 921600 / baudrate;
Marek Vasutac737ff2011-08-28 03:35:13 +020037}
wdenkc6097192002-11-03 00:24:07 +000038
Marek Vasutbcf48722012-09-12 12:59:42 +020039static void pxa_uart_toggle_clock(uint32_t uart_index, int enable)
Marek Vasutac737ff2011-08-28 03:35:13 +020040{
41 uint32_t clk_reg, clk_offset, reg;
wdenkc6097192002-11-03 00:24:07 +000042
Marek Vasutac737ff2011-08-28 03:35:13 +020043 clk_reg = UART_CLK_REG;
44 clk_offset = UART_CLK_BASE << uart_index;
wdenkc6097192002-11-03 00:24:07 +000045
Marek Vasutac737ff2011-08-28 03:35:13 +020046 reg = readl(clk_reg);
wdenkc6097192002-11-03 00:24:07 +000047
Marek Vasutac737ff2011-08-28 03:35:13 +020048 if (enable)
49 reg |= clk_offset;
50 else
51 reg &= ~clk_offset;
wdenkb02744a2003-04-05 00:53:31 +000052
Marek Vasutac737ff2011-08-28 03:35:13 +020053 writel(reg, clk_reg);
54}
wdenkb02744a2003-04-05 00:53:31 +000055
Marek Vasutac737ff2011-08-28 03:35:13 +020056/*
57 * Enable clock and set baud rate, parity etc.
58 */
Marcel Ziswiler90392d02016-11-14 21:40:26 +010059void pxa_setbrg_common(struct pxa_uart_regs *uart_regs, int port, int baudrate)
Marek Vasutac737ff2011-08-28 03:35:13 +020060{
Marcel Ziswiler90392d02016-11-14 21:40:26 +010061 uint32_t divider = pxa_uart_get_baud_divider(baudrate);
Marek Vasutac737ff2011-08-28 03:35:13 +020062 if (!divider)
63 hang();
stefano babic5ab4f032007-08-30 22:57:04 +020064
wdenk5958f4a2003-09-18 09:21:33 +000065
Marcel Ziswiler90392d02016-11-14 21:40:26 +010066 pxa_uart_toggle_clock(port, 1);
wdenk5958f4a2003-09-18 09:21:33 +000067
Marek Vasutac737ff2011-08-28 03:35:13 +020068 /* Disable interrupts and FIFOs */
69 writel(0, &uart_regs->ier);
70 writel(0, &uart_regs->fcr);
wdenk5958f4a2003-09-18 09:21:33 +000071
Marek Vasutac737ff2011-08-28 03:35:13 +020072 /* Set baud rate */
73 writel(LCR_WLS0 | LCR_WLS1 | LCR_DLAB, &uart_regs->lcr);
74 writel(divider & 0xff, &uart_regs->dll);
75 writel(divider >> 8, &uart_regs->dlh);
76 writel(LCR_WLS0 | LCR_WLS1, &uart_regs->lcr);
wdenk5958f4a2003-09-18 09:21:33 +000077
Marek Vasutac737ff2011-08-28 03:35:13 +020078 /* Enable UART */
79 writel(IER_UUE, &uart_regs->ier);
wdenkc6097192002-11-03 00:24:07 +000080}
81
Marcel Ziswiler90392d02016-11-14 21:40:26 +010082#ifndef CONFIG_DM_SERIAL
83static struct pxa_uart_regs *pxa_uart_index_to_regs(uint32_t uart_index)
84{
85 switch (uart_index) {
86 case FFUART_INDEX: return (struct pxa_uart_regs *)FFUART_BASE;
87 case BTUART_INDEX: return (struct pxa_uart_regs *)BTUART_BASE;
88 case STUART_INDEX: return (struct pxa_uart_regs *)STUART_BASE;
89 case HWUART_INDEX: return (struct pxa_uart_regs *)HWUART_BASE;
90 default:
91 return NULL;
92 }
93}
94
95/*
96 * Enable clock and set baud rate, parity etc.
97 */
98void pxa_setbrg_dev(uint32_t uart_index)
99{
100 struct pxa_uart_regs *uart_regs = pxa_uart_index_to_regs(uart_index);
101 if (!uart_regs)
102 panic("Failed getting UART registers\n");
103
104 pxa_setbrg_common(uart_regs, uart_index, gd->baudrate);
105}
106
wdenkc6097192002-11-03 00:24:07 +0000107/*
108 * Initialise the serial port with the given baudrate. The settings
109 * are always 8 data bits, no parity, 1 stop bit, no start bits.
wdenkc6097192002-11-03 00:24:07 +0000110 */
Marek Vasutac737ff2011-08-28 03:35:13 +0200111int pxa_init_dev(unsigned int uart_index)
wdenkc6097192002-11-03 00:24:07 +0000112{
Marcel Ziswiler90392d02016-11-14 21:40:26 +0100113 pxa_setbrg_dev(uart_index);
Marek Vasutac737ff2011-08-28 03:35:13 +0200114 return 0;
wdenkc6097192002-11-03 00:24:07 +0000115}
116
wdenkc6097192002-11-03 00:24:07 +0000117/*
118 * Output a single byte to the serial port.
119 */
Marek Vasutac737ff2011-08-28 03:35:13 +0200120void pxa_putc_dev(unsigned int uart_index, const char c)
wdenkc6097192002-11-03 00:24:07 +0000121{
Marek Vasutac737ff2011-08-28 03:35:13 +0200122 struct pxa_uart_regs *uart_regs;
stefano babic5ab4f032007-08-30 22:57:04 +0200123
Alison Wang23e06b52016-03-02 11:00:37 +0800124 /* If \n, also do \r */
125 if (c == '\n')
126 pxa_putc_dev(uart_index, '\r');
127
Marek Vasutac737ff2011-08-28 03:35:13 +0200128 uart_regs = pxa_uart_index_to_regs(uart_index);
129 if (!uart_regs)
130 hang();
stefano babic5ab4f032007-08-30 22:57:04 +0200131
Marek Vasutac737ff2011-08-28 03:35:13 +0200132 while (!(readl(&uart_regs->lsr) & LSR_TEMT))
133 WATCHDOG_RESET();
134 writel(c, &uart_regs->thr);
wdenkc6097192002-11-03 00:24:07 +0000135}
136
137/*
138 * Read a single byte from the serial port. Returns 1 on success, 0
139 * otherwise. When the function is succesfull, the character read is
140 * written into its argument c.
141 */
Marek Vasutac737ff2011-08-28 03:35:13 +0200142int pxa_tstc_dev(unsigned int uart_index)
wdenkc6097192002-11-03 00:24:07 +0000143{
Marek Vasutac737ff2011-08-28 03:35:13 +0200144 struct pxa_uart_regs *uart_regs;
145
146 uart_regs = pxa_uart_index_to_regs(uart_index);
147 if (!uart_regs)
148 return -1;
149
150 return readl(&uart_regs->lsr) & LSR_DR;
wdenkc6097192002-11-03 00:24:07 +0000151}
152
153/*
154 * Read a single byte from the serial port. Returns 1 on success, 0
155 * otherwise. When the function is succesfull, the character read is
156 * written into its argument c.
157 */
Marek Vasutac737ff2011-08-28 03:35:13 +0200158int pxa_getc_dev(unsigned int uart_index)
wdenkc6097192002-11-03 00:24:07 +0000159{
Marek Vasutac737ff2011-08-28 03:35:13 +0200160 struct pxa_uart_regs *uart_regs;
stefano babic5ab4f032007-08-30 22:57:04 +0200161
Marek Vasutac737ff2011-08-28 03:35:13 +0200162 uart_regs = pxa_uart_index_to_regs(uart_index);
163 if (!uart_regs)
164 return -1;
stefano babic5ab4f032007-08-30 22:57:04 +0200165
Marek Vasutac737ff2011-08-28 03:35:13 +0200166 while (!(readl(&uart_regs->lsr) & LSR_DR))
167 WATCHDOG_RESET();
168 return readl(&uart_regs->rbr) & 0xff;
stefano babic5ab4f032007-08-30 22:57:04 +0200169}
170
Marek Vasutac737ff2011-08-28 03:35:13 +0200171void pxa_puts_dev(unsigned int uart_index, const char *s)
stefano babic5ab4f032007-08-30 22:57:04 +0200172{
Marek Vasutac737ff2011-08-28 03:35:13 +0200173 while (*s)
174 pxa_putc_dev(uart_index, *s++);
stefano babic5ab4f032007-08-30 22:57:04 +0200175}
176
Marek Vasutac737ff2011-08-28 03:35:13 +0200177#define pxa_uart(uart, UART) \
178 int uart##_init(void) \
179 { \
180 return pxa_init_dev(UART##_INDEX); \
181 } \
182 \
183 void uart##_setbrg(void) \
184 { \
185 return pxa_setbrg_dev(UART##_INDEX); \
186 } \
187 \
188 void uart##_putc(const char c) \
189 { \
190 return pxa_putc_dev(UART##_INDEX, c); \
191 } \
192 \
193 void uart##_puts(const char *s) \
194 { \
195 return pxa_puts_dev(UART##_INDEX, s); \
196 } \
197 \
198 int uart##_getc(void) \
199 { \
200 return pxa_getc_dev(UART##_INDEX); \
201 } \
202 \
203 int uart##_tstc(void) \
204 { \
205 return pxa_tstc_dev(UART##_INDEX); \
206 } \
stefano babic5ab4f032007-08-30 22:57:04 +0200207
Marek Vasutac737ff2011-08-28 03:35:13 +0200208#define pxa_uart_desc(uart) \
209 struct serial_device serial_##uart##_device = \
210 { \
Marek Vasut5bcdf242012-09-09 18:48:28 +0200211 .name = "serial_"#uart, \
212 .start = uart##_init, \
213 .stop = NULL, \
214 .setbrg = uart##_setbrg, \
215 .getc = uart##_getc, \
216 .tstc = uart##_tstc, \
217 .putc = uart##_putc, \
218 .puts = uart##_puts, \
Marek Vasutac737ff2011-08-28 03:35:13 +0200219 };
stefano babic5ab4f032007-08-30 22:57:04 +0200220
Marek Vasutac737ff2011-08-28 03:35:13 +0200221#define pxa_uart_multi(uart, UART) \
222 pxa_uart(uart, UART) \
223 pxa_uart_desc(uart)
stefano babic5ab4f032007-08-30 22:57:04 +0200224
Marek Vasutac737ff2011-08-28 03:35:13 +0200225#if defined(CONFIG_HWUART)
226 pxa_uart_multi(hwuart, HWUART)
stefano babic5ab4f032007-08-30 22:57:04 +0200227#endif
Marek Vasutac737ff2011-08-28 03:35:13 +0200228#if defined(CONFIG_STUART)
229 pxa_uart_multi(stuart, STUART)
stefano babic5ab4f032007-08-30 22:57:04 +0200230#endif
Marek Vasutac737ff2011-08-28 03:35:13 +0200231#if defined(CONFIG_FFUART)
232 pxa_uart_multi(ffuart, FFUART)
stefano babic5ab4f032007-08-30 22:57:04 +0200233#endif
Marek Vasutac737ff2011-08-28 03:35:13 +0200234#if defined(CONFIG_BTUART)
235 pxa_uart_multi(btuart, BTUART)
236#endif
stefano babic5ab4f032007-08-30 22:57:04 +0200237
Marek Vasutbc53d142012-09-12 12:26:30 +0200238__weak struct serial_device *default_serial_console(void)
239{
240#if CONFIG_CONS_INDEX == 1
241 return &serial_hwuart_device;
242#elif CONFIG_CONS_INDEX == 2
243 return &serial_stuart_device;
244#elif CONFIG_CONS_INDEX == 3
245 return &serial_ffuart_device;
246#elif CONFIG_CONS_INDEX == 4
247 return &serial_btuart_device;
248#else
249#error "Bad CONFIG_CONS_INDEX."
250#endif
251}
Marek Vasutf3442012012-09-12 13:57:58 +0200252
253void pxa_serial_initialize(void)
254{
255#if defined(CONFIG_FFUART)
256 serial_register(&serial_ffuart_device);
257#endif
258#if defined(CONFIG_BTUART)
259 serial_register(&serial_btuart_device);
260#endif
261#if defined(CONFIG_STUART)
262 serial_register(&serial_stuart_device);
263#endif
264}
Marcel Ziswiler90392d02016-11-14 21:40:26 +0100265#endif /* CONFIG_DM_SERIAL */
266
267#ifdef CONFIG_DM_SERIAL
268static int pxa_serial_probe(struct udevice *dev)
269{
270 struct pxa_serial_platdata *plat = dev->platdata;
271
272 pxa_setbrg_common((struct pxa_uart_regs *)plat->base, plat->port,
273 plat->baudrate);
274 return 0;
275}
276
277static int pxa_serial_putc(struct udevice *dev, const char ch)
278{
279 struct pxa_serial_platdata *plat = dev->platdata;
280 struct pxa_uart_regs *uart_regs = (struct pxa_uart_regs *)plat->base;
281
282 /* Wait for last character to go. */
283 if (!(readl(&uart_regs->lsr) & LSR_TEMT))
284 return -EAGAIN;
285
286 writel(ch, &uart_regs->thr);
287
288 return 0;
289}
290
291static int pxa_serial_getc(struct udevice *dev)
292{
293 struct pxa_serial_platdata *plat = dev->platdata;
294 struct pxa_uart_regs *uart_regs = (struct pxa_uart_regs *)plat->base;
295
296 /* Wait for a character to arrive. */
297 if (!(readl(&uart_regs->lsr) & LSR_DR))
298 return -EAGAIN;
299
300 return readl(&uart_regs->rbr) & 0xff;
301}
302
303int pxa_serial_setbrg(struct udevice *dev, int baudrate)
304{
305 struct pxa_serial_platdata *plat = dev->platdata;
306 struct pxa_uart_regs *uart_regs = (struct pxa_uart_regs *)plat->base;
307 int port = plat->port;
308
309 pxa_setbrg_common(uart_regs, port, baudrate);
310
311 return 0;
312}
313
314static int pxa_serial_pending(struct udevice *dev, bool input)
315{
316 struct pxa_serial_platdata *plat = dev->platdata;
317 struct pxa_uart_regs *uart_regs = (struct pxa_uart_regs *)plat->base;
318
319 if (input)
320 return readl(&uart_regs->lsr) & LSR_DR ? 1 : 0;
321 else
322 return readl(&uart_regs->lsr) & LSR_TEMT ? 0 : 1;
323
324 return 0;
325}
326
327static const struct dm_serial_ops pxa_serial_ops = {
328 .putc = pxa_serial_putc,
329 .pending = pxa_serial_pending,
330 .getc = pxa_serial_getc,
331 .setbrg = pxa_serial_setbrg,
332};
333
334U_BOOT_DRIVER(serial_pxa) = {
335 .name = "serial_pxa",
336 .id = UCLASS_SERIAL,
337 .probe = pxa_serial_probe,
338 .ops = &pxa_serial_ops,
339 .flags = DM_FLAG_PRE_RELOC,
340};
341#endif /* CONFIG_DM_SERIAL */