blob: eb234108746d094a5bf5cbb6fc32a06c123f8d5f [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenk12490652004-04-18 21:13:41 +00002/*
Michal Simek7e4372a2015-12-01 14:24:20 +01003 * (C) Copyright 2008 - 2015 Michal Simek <monstr@monstr.eu>
Michal Simek403d6192008-07-11 10:10:31 +02004 * Clean driver and add xilinx constant from header file
wdenk12490652004-04-18 21:13:41 +00005 *
Michal Simek403d6192008-07-11 10:10:31 +02006 * (C) Copyright 2004 Atmark Techno, Inc.
wdenk12490652004-04-18 21:13:41 +00007 * Yasushi SHOJI <yashi@atmark-techno.com>
wdenk12490652004-04-18 21:13:41 +00008 */
9
10#include <config.h>
Michal Simek7e4372a2015-12-01 14:24:20 +010011#include <dm.h>
Michal Simek403d6192008-07-11 10:10:31 +020012#include <asm/io.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060013#include <linux/bitops.h>
Michal Simek75348da2011-09-25 21:03:08 +000014#include <linux/compiler.h>
15#include <serial.h>
wdenk12490652004-04-18 21:13:41 +000016
Michal Simek7e4372a2015-12-01 14:24:20 +010017#define SR_TX_FIFO_FULL BIT(3) /* transmit FIFO full */
18#define SR_TX_FIFO_EMPTY BIT(2) /* transmit FIFO empty */
19#define SR_RX_FIFO_VALID_DATA BIT(0) /* data in receive FIFO */
20#define SR_RX_FIFO_FULL BIT(1) /* receive FIFO full */
wdenk12490652004-04-18 21:13:41 +000021
Michal Simeke5b3c1d2014-01-21 07:29:47 +010022#define ULITE_CONTROL_RST_TX 0x01
23#define ULITE_CONTROL_RST_RX 0x02
24
Michal Simek8e4e5f02024-02-14 12:52:32 +010025static bool little_endian __section(".data");
T Karthik Reddy070ffd22020-08-14 03:02:15 -060026
Michal Simek75348da2011-09-25 21:03:08 +000027struct uartlite {
28 unsigned int rx_fifo;
29 unsigned int tx_fifo;
30 unsigned int status;
Michal Simeke5b3c1d2014-01-21 07:29:47 +010031 unsigned int control;
Michal Simek75348da2011-09-25 21:03:08 +000032};
33
Simon Glassb75b15b2020-12-03 16:55:23 -070034struct uartlite_plat {
Michal Simek7e4372a2015-12-01 14:24:20 +010035 struct uartlite *regs;
Michal Simek75348da2011-09-25 21:03:08 +000036};
37
T Karthik Reddy070ffd22020-08-14 03:02:15 -060038static u32 uart_in32(void __iomem *addr)
39{
40 if (little_endian)
41 return in_le32(addr);
42 else
43 return in_be32(addr);
44}
45
46static void uart_out32(void __iomem *addr, u32 val)
47{
48 if (little_endian)
49 out_le32(addr, val);
50 else
51 out_be32(addr, val);
52}
53
Michal Simek7e4372a2015-12-01 14:24:20 +010054static int uartlite_serial_putc(struct udevice *dev, const char ch)
Michal Simek75348da2011-09-25 21:03:08 +000055{
Simon Glassb75b15b2020-12-03 16:55:23 -070056 struct uartlite_plat *plat = dev_get_plat(dev);
Michal Simek7e4372a2015-12-01 14:24:20 +010057 struct uartlite *regs = plat->regs;
Michal Simek75348da2011-09-25 21:03:08 +000058
T Karthik Reddy070ffd22020-08-14 03:02:15 -060059 if (uart_in32(&regs->status) & SR_TX_FIFO_FULL)
Michal Simek7e4372a2015-12-01 14:24:20 +010060 return -EAGAIN;
Michal Simek75348da2011-09-25 21:03:08 +000061
T Karthik Reddy070ffd22020-08-14 03:02:15 -060062 uart_out32(&regs->tx_fifo, ch & 0xff);
Michal Simek75348da2011-09-25 21:03:08 +000063
Michal Simek7e4372a2015-12-01 14:24:20 +010064 return 0;
Michal Simek75348da2011-09-25 21:03:08 +000065}
66
Michal Simek7e4372a2015-12-01 14:24:20 +010067static int uartlite_serial_getc(struct udevice *dev)
Michal Simek75348da2011-09-25 21:03:08 +000068{
Simon Glassb75b15b2020-12-03 16:55:23 -070069 struct uartlite_plat *plat = dev_get_plat(dev);
Michal Simek7e4372a2015-12-01 14:24:20 +010070 struct uartlite *regs = plat->regs;
71
T Karthik Reddy070ffd22020-08-14 03:02:15 -060072 if (!(uart_in32(&regs->status) & SR_RX_FIFO_VALID_DATA))
Michal Simek7e4372a2015-12-01 14:24:20 +010073 return -EAGAIN;
Michal Simek75348da2011-09-25 21:03:08 +000074
T Karthik Reddy070ffd22020-08-14 03:02:15 -060075 return uart_in32(&regs->rx_fifo) & 0xff;
Michal Simek75348da2011-09-25 21:03:08 +000076}
77
Michal Simek7e4372a2015-12-01 14:24:20 +010078static int uartlite_serial_pending(struct udevice *dev, bool input)
Michal Simek75348da2011-09-25 21:03:08 +000079{
Simon Glassb75b15b2020-12-03 16:55:23 -070080 struct uartlite_plat *plat = dev_get_plat(dev);
Michal Simek7e4372a2015-12-01 14:24:20 +010081 struct uartlite *regs = plat->regs;
wdenk12490652004-04-18 21:13:41 +000082
Michal Simek7e4372a2015-12-01 14:24:20 +010083 if (input)
T Karthik Reddy070ffd22020-08-14 03:02:15 -060084 return uart_in32(&regs->status) & SR_RX_FIFO_VALID_DATA;
Michal Simek7e4372a2015-12-01 14:24:20 +010085
T Karthik Reddy070ffd22020-08-14 03:02:15 -060086 return !(uart_in32(&regs->status) & SR_TX_FIFO_EMPTY);
Michal Simek75348da2011-09-25 21:03:08 +000087}
88
Michal Simek7e4372a2015-12-01 14:24:20 +010089static int uartlite_serial_probe(struct udevice *dev)
Michal Simekd40a2522012-07-02 10:32:18 +020090{
Simon Glassb75b15b2020-12-03 16:55:23 -070091 struct uartlite_plat *plat = dev_get_plat(dev);
Michal Simek7e4372a2015-12-01 14:24:20 +010092 struct uartlite *regs = plat->regs;
T Karthik Reddy070ffd22020-08-14 03:02:15 -060093 int ret;
Michal Simeke5b3c1d2014-01-21 07:29:47 +010094
T Karthik Reddy070ffd22020-08-14 03:02:15 -060095 uart_out32(&regs->control, 0);
96 uart_out32(&regs->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX);
97 ret = uart_in32(&regs->status);
98 /* Endianness detection */
99 if ((ret & SR_TX_FIFO_EMPTY) != SR_TX_FIFO_EMPTY) {
100 little_endian = true;
101 uart_out32(&regs->control, ULITE_CONTROL_RST_RX |
102 ULITE_CONTROL_RST_TX);
103 }
Michal Simeke5b3c1d2014-01-21 07:29:47 +0100104
Michal Simek7e4372a2015-12-01 14:24:20 +0100105 return 0;
Michal Simekd40a2522012-07-02 10:32:18 +0200106}
107
Simon Glassaad29ae2020-12-03 16:55:21 -0700108static int uartlite_serial_of_to_plat(struct udevice *dev)
Michal Simek7e4372a2015-12-01 14:24:20 +0100109{
Simon Glassb75b15b2020-12-03 16:55:23 -0700110 struct uartlite_plat *plat = dev_get_plat(dev);
Michal Simek7e4372a2015-12-01 14:24:20 +0100111
Masahiro Yamada1096ae12020-07-17 14:36:46 +0900112 plat->regs = dev_read_addr_ptr(dev);
Michal Simek75348da2011-09-25 21:03:08 +0000113
Michal Simek7e4372a2015-12-01 14:24:20 +0100114 return 0;
Marek Vasut5bcdf242012-09-09 18:48:28 +0200115}
Michal Simek75348da2011-09-25 21:03:08 +0000116
Michal Simek7e4372a2015-12-01 14:24:20 +0100117static const struct dm_serial_ops uartlite_serial_ops = {
118 .putc = uartlite_serial_putc,
119 .pending = uartlite_serial_pending,
120 .getc = uartlite_serial_getc,
121};
Michal Simekd40a2522012-07-02 10:32:18 +0200122
Michal Simek7e4372a2015-12-01 14:24:20 +0100123static const struct udevice_id uartlite_serial_ids[] = {
124 { .compatible = "xlnx,opb-uartlite-1.00.b", },
125 { .compatible = "xlnx,xps-uartlite-1.00.a" },
126 { }
127};
Marek Vasutd97fb5c2012-09-12 19:45:58 +0200128
Michal Simek7e4372a2015-12-01 14:24:20 +0100129U_BOOT_DRIVER(serial_uartlite) = {
130 .name = "serial_uartlite",
131 .id = UCLASS_SERIAL,
132 .of_match = uartlite_serial_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -0700133 .of_to_plat = uartlite_serial_of_to_plat,
Simon Glassb75b15b2020-12-03 16:55:23 -0700134 .plat_auto = sizeof(struct uartlite_plat),
Michal Simek7e4372a2015-12-01 14:24:20 +0100135 .probe = uartlite_serial_probe,
136 .ops = &uartlite_serial_ops,
Michal Simek7e4372a2015-12-01 14:24:20 +0100137};
Michal Simek8af618b2015-12-14 16:55:10 +0100138
139#ifdef CONFIG_DEBUG_UART_UARTLITE
140
141#include <debug_uart.h>
142
143static inline void _debug_uart_init(void)
144{
Pali Rohár8864b352022-05-27 22:15:24 +0200145 struct uartlite *regs = (struct uartlite *)CONFIG_VAL(DEBUG_UART_BASE);
T Karthik Reddy070ffd22020-08-14 03:02:15 -0600146 int ret;
Michal Simek8af618b2015-12-14 16:55:10 +0100147
T Karthik Reddy070ffd22020-08-14 03:02:15 -0600148 uart_out32(&regs->control, 0);
149 uart_out32(&regs->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX);
Ashok Reddy Soma5190dec2020-12-01 00:34:47 -0700150 ret = uart_in32(&regs->status);
T Karthik Reddy070ffd22020-08-14 03:02:15 -0600151 /* Endianness detection */
152 if ((ret & SR_TX_FIFO_EMPTY) != SR_TX_FIFO_EMPTY) {
153 little_endian = true;
154 uart_out32(&regs->control, ULITE_CONTROL_RST_RX |
155 ULITE_CONTROL_RST_TX);
156 }
Michal Simek8af618b2015-12-14 16:55:10 +0100157}
158
159static inline void _debug_uart_putc(int ch)
160{
Pali Rohár8864b352022-05-27 22:15:24 +0200161 struct uartlite *regs = (struct uartlite *)CONFIG_VAL(DEBUG_UART_BASE);
Michal Simek8af618b2015-12-14 16:55:10 +0100162
T Karthik Reddy070ffd22020-08-14 03:02:15 -0600163 while (uart_in32(&regs->status) & SR_TX_FIFO_FULL)
Michal Simek8af618b2015-12-14 16:55:10 +0100164 ;
165
T Karthik Reddy070ffd22020-08-14 03:02:15 -0600166 uart_out32(&regs->tx_fifo, ch & 0xff);
Michal Simek8af618b2015-12-14 16:55:10 +0100167}
168
169DEBUG_UART_FUNCS
170#endif