blob: aa928efdc0082ec431f4242cc6fa472704c1db91 [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>
Simon Glassf11478f2019-12-28 10:45:07 -070023#include <hang.h>
wdenkc6097192002-11-03 00:24:07 +000024#include <asm/arch/pxa-regs.h>
Marek Vasutac737ff2011-08-28 03:35:13 +020025#include <asm/arch/regs-uart.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060026#include <asm/global_data.h>
Marek Vasut2db1e962010-09-09 09:50:39 +020027#include <asm/io.h>
Marcel Ziswiler90392d02016-11-14 21:40:26 +010028#include <dm.h>
29#include <dm/platform_data/serial_pxa.h>
Marek Vasutbc53d142012-09-12 12:26:30 +020030#include <linux/compiler.h>
Marcel Ziswiler7cfcbee2015-08-16 04:16:29 +020031#include <serial.h>
32#include <watchdog.h>
wdenkc6097192002-11-03 00:24:07 +000033
Wolfgang Denk6405a152006-03-31 18:32:53 +020034DECLARE_GLOBAL_DATA_PTR;
35
Marcel Ziswiler90392d02016-11-14 21:40:26 +010036static uint32_t pxa_uart_get_baud_divider(int baudrate)
Marek Vasutac737ff2011-08-28 03:35:13 +020037{
Marcel Ziswiler90392d02016-11-14 21:40:26 +010038 return 921600 / baudrate;
Marek Vasutac737ff2011-08-28 03:35:13 +020039}
wdenkc6097192002-11-03 00:24:07 +000040
Marek Vasutbcf48722012-09-12 12:59:42 +020041static void pxa_uart_toggle_clock(uint32_t uart_index, int enable)
Marek Vasutac737ff2011-08-28 03:35:13 +020042{
43 uint32_t clk_reg, clk_offset, reg;
wdenkc6097192002-11-03 00:24:07 +000044
Marek Vasutac737ff2011-08-28 03:35:13 +020045 clk_reg = UART_CLK_REG;
46 clk_offset = UART_CLK_BASE << uart_index;
wdenkc6097192002-11-03 00:24:07 +000047
Marek Vasutac737ff2011-08-28 03:35:13 +020048 reg = readl(clk_reg);
wdenkc6097192002-11-03 00:24:07 +000049
Marek Vasutac737ff2011-08-28 03:35:13 +020050 if (enable)
51 reg |= clk_offset;
52 else
53 reg &= ~clk_offset;
wdenkb02744a2003-04-05 00:53:31 +000054
Marek Vasutac737ff2011-08-28 03:35:13 +020055 writel(reg, clk_reg);
56}
wdenkb02744a2003-04-05 00:53:31 +000057
Marek Vasutac737ff2011-08-28 03:35:13 +020058/*
59 * Enable clock and set baud rate, parity etc.
60 */
Marcel Ziswiler90392d02016-11-14 21:40:26 +010061void pxa_setbrg_common(struct pxa_uart_regs *uart_regs, int port, int baudrate)
Marek Vasutac737ff2011-08-28 03:35:13 +020062{
Marcel Ziswiler90392d02016-11-14 21:40:26 +010063 uint32_t divider = pxa_uart_get_baud_divider(baudrate);
Marek Vasutac737ff2011-08-28 03:35:13 +020064 if (!divider)
65 hang();
stefano babic5ab4f032007-08-30 22:57:04 +020066
wdenk5958f4a2003-09-18 09:21:33 +000067
Marcel Ziswiler90392d02016-11-14 21:40:26 +010068 pxa_uart_toggle_clock(port, 1);
wdenk5958f4a2003-09-18 09:21:33 +000069
Marek Vasutac737ff2011-08-28 03:35:13 +020070 /* Disable interrupts and FIFOs */
71 writel(0, &uart_regs->ier);
72 writel(0, &uart_regs->fcr);
wdenk5958f4a2003-09-18 09:21:33 +000073
Marek Vasutac737ff2011-08-28 03:35:13 +020074 /* Set baud rate */
75 writel(LCR_WLS0 | LCR_WLS1 | LCR_DLAB, &uart_regs->lcr);
76 writel(divider & 0xff, &uart_regs->dll);
77 writel(divider >> 8, &uart_regs->dlh);
78 writel(LCR_WLS0 | LCR_WLS1, &uart_regs->lcr);
wdenk5958f4a2003-09-18 09:21:33 +000079
Marek Vasutac737ff2011-08-28 03:35:13 +020080 /* Enable UART */
81 writel(IER_UUE, &uart_regs->ier);
wdenkc6097192002-11-03 00:24:07 +000082}
83
Marcel Ziswiler90392d02016-11-14 21:40:26 +010084#ifndef CONFIG_DM_SERIAL
85static struct pxa_uart_regs *pxa_uart_index_to_regs(uint32_t uart_index)
86{
87 switch (uart_index) {
88 case FFUART_INDEX: return (struct pxa_uart_regs *)FFUART_BASE;
89 case BTUART_INDEX: return (struct pxa_uart_regs *)BTUART_BASE;
90 case STUART_INDEX: return (struct pxa_uart_regs *)STUART_BASE;
Marcel Ziswiler90392d02016-11-14 21:40:26 +010091 default:
92 return NULL;
93 }
94}
95
96/*
97 * Enable clock and set baud rate, parity etc.
98 */
99void pxa_setbrg_dev(uint32_t uart_index)
100{
101 struct pxa_uart_regs *uart_regs = pxa_uart_index_to_regs(uart_index);
102 if (!uart_regs)
103 panic("Failed getting UART registers\n");
104
105 pxa_setbrg_common(uart_regs, uart_index, gd->baudrate);
106}
107
wdenkc6097192002-11-03 00:24:07 +0000108/*
109 * Initialise the serial port with the given baudrate. The settings
110 * are always 8 data bits, no parity, 1 stop bit, no start bits.
wdenkc6097192002-11-03 00:24:07 +0000111 */
Marek Vasutac737ff2011-08-28 03:35:13 +0200112int pxa_init_dev(unsigned int uart_index)
wdenkc6097192002-11-03 00:24:07 +0000113{
Marcel Ziswiler90392d02016-11-14 21:40:26 +0100114 pxa_setbrg_dev(uart_index);
Marek Vasutac737ff2011-08-28 03:35:13 +0200115 return 0;
wdenkc6097192002-11-03 00:24:07 +0000116}
117
wdenkc6097192002-11-03 00:24:07 +0000118/*
119 * Output a single byte to the serial port.
120 */
Marek Vasutac737ff2011-08-28 03:35:13 +0200121void pxa_putc_dev(unsigned int uart_index, const char c)
wdenkc6097192002-11-03 00:24:07 +0000122{
Marek Vasutac737ff2011-08-28 03:35:13 +0200123 struct pxa_uart_regs *uart_regs;
stefano babic5ab4f032007-08-30 22:57:04 +0200124
Alison Wang23e06b52016-03-02 11:00:37 +0800125 /* If \n, also do \r */
126 if (c == '\n')
127 pxa_putc_dev(uart_index, '\r');
128
Marek Vasutac737ff2011-08-28 03:35:13 +0200129 uart_regs = pxa_uart_index_to_regs(uart_index);
130 if (!uart_regs)
131 hang();
stefano babic5ab4f032007-08-30 22:57:04 +0200132
Marek Vasutac737ff2011-08-28 03:35:13 +0200133 while (!(readl(&uart_regs->lsr) & LSR_TEMT))
134 WATCHDOG_RESET();
135 writel(c, &uart_regs->thr);
wdenkc6097192002-11-03 00:24:07 +0000136}
137
138/*
139 * Read a single byte from the serial port. Returns 1 on success, 0
140 * otherwise. When the function is succesfull, the character read is
141 * written into its argument c.
142 */
Marek Vasutac737ff2011-08-28 03:35:13 +0200143int pxa_tstc_dev(unsigned int uart_index)
wdenkc6097192002-11-03 00:24:07 +0000144{
Marek Vasutac737ff2011-08-28 03:35:13 +0200145 struct pxa_uart_regs *uart_regs;
146
147 uart_regs = pxa_uart_index_to_regs(uart_index);
148 if (!uart_regs)
149 return -1;
150
151 return readl(&uart_regs->lsr) & LSR_DR;
wdenkc6097192002-11-03 00:24:07 +0000152}
153
154/*
155 * Read a single byte from the serial port. Returns 1 on success, 0
156 * otherwise. When the function is succesfull, the character read is
157 * written into its argument c.
158 */
Marek Vasutac737ff2011-08-28 03:35:13 +0200159int pxa_getc_dev(unsigned int uart_index)
wdenkc6097192002-11-03 00:24:07 +0000160{
Marek Vasutac737ff2011-08-28 03:35:13 +0200161 struct pxa_uart_regs *uart_regs;
stefano babic5ab4f032007-08-30 22:57:04 +0200162
Marek Vasutac737ff2011-08-28 03:35:13 +0200163 uart_regs = pxa_uart_index_to_regs(uart_index);
164 if (!uart_regs)
165 return -1;
stefano babic5ab4f032007-08-30 22:57:04 +0200166
Marek Vasutac737ff2011-08-28 03:35:13 +0200167 while (!(readl(&uart_regs->lsr) & LSR_DR))
168 WATCHDOG_RESET();
169 return readl(&uart_regs->rbr) & 0xff;
stefano babic5ab4f032007-08-30 22:57:04 +0200170}
171
Marek Vasutac737ff2011-08-28 03:35:13 +0200172void pxa_puts_dev(unsigned int uart_index, const char *s)
stefano babic5ab4f032007-08-30 22:57:04 +0200173{
Marek Vasutac737ff2011-08-28 03:35:13 +0200174 while (*s)
175 pxa_putc_dev(uart_index, *s++);
stefano babic5ab4f032007-08-30 22:57:04 +0200176}
177
Marek Vasutac737ff2011-08-28 03:35:13 +0200178#define pxa_uart(uart, UART) \
179 int uart##_init(void) \
180 { \
181 return pxa_init_dev(UART##_INDEX); \
182 } \
183 \
184 void uart##_setbrg(void) \
185 { \
186 return pxa_setbrg_dev(UART##_INDEX); \
187 } \
188 \
189 void uart##_putc(const char c) \
190 { \
191 return pxa_putc_dev(UART##_INDEX, c); \
192 } \
193 \
194 void uart##_puts(const char *s) \
195 { \
196 return pxa_puts_dev(UART##_INDEX, s); \
197 } \
198 \
199 int uart##_getc(void) \
200 { \
201 return pxa_getc_dev(UART##_INDEX); \
202 } \
203 \
204 int uart##_tstc(void) \
205 { \
206 return pxa_tstc_dev(UART##_INDEX); \
207 } \
stefano babic5ab4f032007-08-30 22:57:04 +0200208
Marek Vasutac737ff2011-08-28 03:35:13 +0200209#define pxa_uart_desc(uart) \
210 struct serial_device serial_##uart##_device = \
211 { \
Marek Vasut5bcdf242012-09-09 18:48:28 +0200212 .name = "serial_"#uart, \
213 .start = uart##_init, \
214 .stop = NULL, \
215 .setbrg = uart##_setbrg, \
216 .getc = uart##_getc, \
217 .tstc = uart##_tstc, \
218 .putc = uart##_putc, \
219 .puts = uart##_puts, \
Marek Vasutac737ff2011-08-28 03:35:13 +0200220 };
stefano babic5ab4f032007-08-30 22:57:04 +0200221
Marek Vasutac737ff2011-08-28 03:35:13 +0200222#define pxa_uart_multi(uart, UART) \
223 pxa_uart(uart, UART) \
224 pxa_uart_desc(uart)
stefano babic5ab4f032007-08-30 22:57:04 +0200225
Marek Vasutac737ff2011-08-28 03:35:13 +0200226#if defined(CONFIG_HWUART)
227 pxa_uart_multi(hwuart, HWUART)
stefano babic5ab4f032007-08-30 22:57:04 +0200228#endif
Marek Vasutac737ff2011-08-28 03:35:13 +0200229#if defined(CONFIG_STUART)
230 pxa_uart_multi(stuart, STUART)
stefano babic5ab4f032007-08-30 22:57:04 +0200231#endif
Marek Vasutac737ff2011-08-28 03:35:13 +0200232#if defined(CONFIG_FFUART)
233 pxa_uart_multi(ffuart, FFUART)
stefano babic5ab4f032007-08-30 22:57:04 +0200234#endif
Marek Vasutac737ff2011-08-28 03:35:13 +0200235#if defined(CONFIG_BTUART)
236 pxa_uart_multi(btuart, BTUART)
237#endif
stefano babic5ab4f032007-08-30 22:57:04 +0200238
Marek Vasutbc53d142012-09-12 12:26:30 +0200239__weak struct serial_device *default_serial_console(void)
240{
241#if CONFIG_CONS_INDEX == 1
242 return &serial_hwuart_device;
243#elif CONFIG_CONS_INDEX == 2
244 return &serial_stuart_device;
245#elif CONFIG_CONS_INDEX == 3
246 return &serial_ffuart_device;
247#elif CONFIG_CONS_INDEX == 4
248 return &serial_btuart_device;
249#else
250#error "Bad CONFIG_CONS_INDEX."
251#endif
252}
Marek Vasutf3442012012-09-12 13:57:58 +0200253
254void pxa_serial_initialize(void)
255{
256#if defined(CONFIG_FFUART)
257 serial_register(&serial_ffuart_device);
258#endif
259#if defined(CONFIG_BTUART)
260 serial_register(&serial_btuart_device);
261#endif
262#if defined(CONFIG_STUART)
263 serial_register(&serial_stuart_device);
264#endif
265}
Marcel Ziswiler90392d02016-11-14 21:40:26 +0100266#endif /* CONFIG_DM_SERIAL */
267
268#ifdef CONFIG_DM_SERIAL
269static int pxa_serial_probe(struct udevice *dev)
270{
Simon Glass95588622020-12-22 19:30:28 -0700271 struct pxa_serial_plat *plat = dev_get_plat(dev);
Marcel Ziswiler90392d02016-11-14 21:40:26 +0100272
273 pxa_setbrg_common((struct pxa_uart_regs *)plat->base, plat->port,
274 plat->baudrate);
275 return 0;
276}
277
278static int pxa_serial_putc(struct udevice *dev, const char ch)
279{
Simon Glass95588622020-12-22 19:30:28 -0700280 struct pxa_serial_plat *plat = dev_get_plat(dev);
Marcel Ziswiler90392d02016-11-14 21:40:26 +0100281 struct pxa_uart_regs *uart_regs = (struct pxa_uart_regs *)plat->base;
282
283 /* Wait for last character to go. */
284 if (!(readl(&uart_regs->lsr) & LSR_TEMT))
285 return -EAGAIN;
286
287 writel(ch, &uart_regs->thr);
288
289 return 0;
290}
291
292static int pxa_serial_getc(struct udevice *dev)
293{
Simon Glass95588622020-12-22 19:30:28 -0700294 struct pxa_serial_plat *plat = dev_get_plat(dev);
Marcel Ziswiler90392d02016-11-14 21:40:26 +0100295 struct pxa_uart_regs *uart_regs = (struct pxa_uart_regs *)plat->base;
296
297 /* Wait for a character to arrive. */
298 if (!(readl(&uart_regs->lsr) & LSR_DR))
299 return -EAGAIN;
300
301 return readl(&uart_regs->rbr) & 0xff;
302}
303
304int pxa_serial_setbrg(struct udevice *dev, int baudrate)
305{
Simon Glass95588622020-12-22 19:30:28 -0700306 struct pxa_serial_plat *plat = dev_get_plat(dev);
Marcel Ziswiler90392d02016-11-14 21:40:26 +0100307 struct pxa_uart_regs *uart_regs = (struct pxa_uart_regs *)plat->base;
308 int port = plat->port;
309
310 pxa_setbrg_common(uart_regs, port, baudrate);
311
312 return 0;
313}
314
315static int pxa_serial_pending(struct udevice *dev, bool input)
316{
Simon Glass95588622020-12-22 19:30:28 -0700317 struct pxa_serial_plat *plat = dev_get_plat(dev);
Marcel Ziswiler90392d02016-11-14 21:40:26 +0100318 struct pxa_uart_regs *uart_regs = (struct pxa_uart_regs *)plat->base;
319
320 if (input)
321 return readl(&uart_regs->lsr) & LSR_DR ? 1 : 0;
322 else
323 return readl(&uart_regs->lsr) & LSR_TEMT ? 0 : 1;
324
325 return 0;
326}
327
328static const struct dm_serial_ops pxa_serial_ops = {
329 .putc = pxa_serial_putc,
330 .pending = pxa_serial_pending,
331 .getc = pxa_serial_getc,
332 .setbrg = pxa_serial_setbrg,
333};
334
335U_BOOT_DRIVER(serial_pxa) = {
336 .name = "serial_pxa",
337 .id = UCLASS_SERIAL,
338 .probe = pxa_serial_probe,
339 .ops = &pxa_serial_ops,
340 .flags = DM_FLAG_PRE_RELOC,
341};
342#endif /* CONFIG_DM_SERIAL */