xref: /rk3399_rockchip-uboot/drivers/serial/serial_xuartlite.c (revision a821c4af79e4f5ce9b629b20473863397bbe9b10)
11378df79SJean-Christophe PLAGNIOL-VILLARD /*
293768393SMichal Simek  * (C) Copyright 2008 - 2015 Michal Simek <monstr@monstr.eu>
353ea981cSMichal Simek  * Clean driver and add xilinx constant from header file
41378df79SJean-Christophe PLAGNIOL-VILLARD  *
553ea981cSMichal Simek  * (C) Copyright 2004 Atmark Techno, Inc.
61378df79SJean-Christophe PLAGNIOL-VILLARD  * Yasushi SHOJI <yashi@atmark-techno.com>
71378df79SJean-Christophe PLAGNIOL-VILLARD  *
81a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
91378df79SJean-Christophe PLAGNIOL-VILLARD  */
101378df79SJean-Christophe PLAGNIOL-VILLARD 
111378df79SJean-Christophe PLAGNIOL-VILLARD #include <config.h>
1249a23e4aSMichal Simek #include <common.h>
1393768393SMichal Simek #include <dm.h>
1453ea981cSMichal Simek #include <asm/io.h>
1549a23e4aSMichal Simek #include <linux/compiler.h>
1649a23e4aSMichal Simek #include <serial.h>
171378df79SJean-Christophe PLAGNIOL-VILLARD 
1893768393SMichal Simek DECLARE_GLOBAL_DATA_PTR;
1993768393SMichal Simek 
2093768393SMichal Simek #define SR_TX_FIFO_FULL		BIT(3) /* transmit FIFO full */
2193768393SMichal Simek #define SR_TX_FIFO_EMPTY	BIT(2) /* transmit FIFO empty */
2293768393SMichal Simek #define SR_RX_FIFO_VALID_DATA	BIT(0) /* data in receive FIFO */
2393768393SMichal Simek #define SR_RX_FIFO_FULL		BIT(1) /* receive FIFO full */
241378df79SJean-Christophe PLAGNIOL-VILLARD 
258c3bd6b5SMichal Simek #define ULITE_CONTROL_RST_TX	0x01
268c3bd6b5SMichal Simek #define ULITE_CONTROL_RST_RX	0x02
278c3bd6b5SMichal Simek 
2849a23e4aSMichal Simek struct uartlite {
2949a23e4aSMichal Simek 	unsigned int rx_fifo;
3049a23e4aSMichal Simek 	unsigned int tx_fifo;
3149a23e4aSMichal Simek 	unsigned int status;
328c3bd6b5SMichal Simek 	unsigned int control;
3349a23e4aSMichal Simek };
341378df79SJean-Christophe PLAGNIOL-VILLARD 
3593768393SMichal Simek struct uartlite_platdata {
3693768393SMichal Simek 	struct uartlite *regs;
3749a23e4aSMichal Simek };
3849a23e4aSMichal Simek 
uartlite_serial_putc(struct udevice * dev,const char ch)3993768393SMichal Simek static int uartlite_serial_putc(struct udevice *dev, const char ch)
4049a23e4aSMichal Simek {
4193768393SMichal Simek 	struct uartlite_platdata *plat = dev_get_platdata(dev);
4293768393SMichal Simek 	struct uartlite *regs = plat->regs;
4349a23e4aSMichal Simek 
4493768393SMichal Simek 	if (in_be32(&regs->status) & SR_TX_FIFO_FULL)
4593768393SMichal Simek 		return -EAGAIN;
4649a23e4aSMichal Simek 
4793768393SMichal Simek 	out_be32(&regs->tx_fifo, ch & 0xff);
4849a23e4aSMichal Simek 
4925239e12SMichal Simek 	return 0;
508c3bd6b5SMichal Simek }
518c3bd6b5SMichal Simek 
uartlite_serial_getc(struct udevice * dev)5293768393SMichal Simek static int uartlite_serial_getc(struct udevice *dev)
5349a23e4aSMichal Simek {
5493768393SMichal Simek 	struct uartlite_platdata *plat = dev_get_platdata(dev);
5593768393SMichal Simek 	struct uartlite *regs = plat->regs;
5625239e12SMichal Simek 
5793768393SMichal Simek 	if (!(in_be32(&regs->status) & SR_RX_FIFO_VALID_DATA))
5893768393SMichal Simek 		return -EAGAIN;
5993768393SMichal Simek 
6093768393SMichal Simek 	return in_be32(&regs->rx_fifo) & 0xff;
6149a23e4aSMichal Simek }
6287d69229SMarek Vasut 
uartlite_serial_pending(struct udevice * dev,bool input)6393768393SMichal Simek static int uartlite_serial_pending(struct udevice *dev, bool input)
6487d69229SMarek Vasut {
6593768393SMichal Simek 	struct uartlite_platdata *plat = dev_get_platdata(dev);
6693768393SMichal Simek 	struct uartlite *regs = plat->regs;
6793768393SMichal Simek 
6893768393SMichal Simek 	if (input)
6993768393SMichal Simek 		return in_be32(&regs->status) & SR_RX_FIFO_VALID_DATA;
7093768393SMichal Simek 
7193768393SMichal Simek 	return !(in_be32(&regs->status) & SR_TX_FIFO_EMPTY);
7287d69229SMarek Vasut }
7393768393SMichal Simek 
uartlite_serial_probe(struct udevice * dev)7493768393SMichal Simek static int uartlite_serial_probe(struct udevice *dev)
7593768393SMichal Simek {
7693768393SMichal Simek 	struct uartlite_platdata *plat = dev_get_platdata(dev);
7793768393SMichal Simek 	struct uartlite *regs = plat->regs;
7893768393SMichal Simek 
7993768393SMichal Simek 	out_be32(&regs->control, 0);
8093768393SMichal Simek 	out_be32(&regs->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX);
8193768393SMichal Simek 	in_be32(&regs->control);
8293768393SMichal Simek 
8393768393SMichal Simek 	return 0;
8493768393SMichal Simek }
8593768393SMichal Simek 
uartlite_serial_ofdata_to_platdata(struct udevice * dev)8693768393SMichal Simek static int uartlite_serial_ofdata_to_platdata(struct udevice *dev)
8793768393SMichal Simek {
8893768393SMichal Simek 	struct uartlite_platdata *plat = dev_get_platdata(dev);
8993768393SMichal Simek 
90*a821c4afSSimon Glass 	plat->regs = (struct uartlite *)devfdt_get_addr(dev);
9193768393SMichal Simek 
9293768393SMichal Simek 	return 0;
9393768393SMichal Simek }
9493768393SMichal Simek 
9593768393SMichal Simek static const struct dm_serial_ops uartlite_serial_ops = {
9693768393SMichal Simek 	.putc = uartlite_serial_putc,
9793768393SMichal Simek 	.pending = uartlite_serial_pending,
9893768393SMichal Simek 	.getc = uartlite_serial_getc,
9993768393SMichal Simek };
10093768393SMichal Simek 
10193768393SMichal Simek static const struct udevice_id uartlite_serial_ids[] = {
10293768393SMichal Simek 	{ .compatible = "xlnx,opb-uartlite-1.00.b", },
10393768393SMichal Simek 	{ .compatible = "xlnx,xps-uartlite-1.00.a" },
10493768393SMichal Simek 	{ }
10593768393SMichal Simek };
10693768393SMichal Simek 
10793768393SMichal Simek U_BOOT_DRIVER(serial_uartlite) = {
10893768393SMichal Simek 	.name	= "serial_uartlite",
10993768393SMichal Simek 	.id	= UCLASS_SERIAL,
11093768393SMichal Simek 	.of_match = uartlite_serial_ids,
11193768393SMichal Simek 	.ofdata_to_platdata = uartlite_serial_ofdata_to_platdata,
11293768393SMichal Simek 	.platdata_auto_alloc_size = sizeof(struct uartlite_platdata),
11393768393SMichal Simek 	.probe = uartlite_serial_probe,
11493768393SMichal Simek 	.ops	= &uartlite_serial_ops,
11593768393SMichal Simek 	.flags = DM_FLAG_PRE_RELOC,
11693768393SMichal Simek };
1174166ba3bSMichal Simek 
1184166ba3bSMichal Simek #ifdef CONFIG_DEBUG_UART_UARTLITE
1194166ba3bSMichal Simek 
1204166ba3bSMichal Simek #include <debug_uart.h>
1214166ba3bSMichal Simek 
_debug_uart_init(void)1224166ba3bSMichal Simek static inline void _debug_uart_init(void)
1234166ba3bSMichal Simek {
1244166ba3bSMichal Simek 	struct uartlite *regs = (struct uartlite *)CONFIG_DEBUG_UART_BASE;
1254166ba3bSMichal Simek 
1264166ba3bSMichal Simek 	out_be32(&regs->control, 0);
1274166ba3bSMichal Simek 	out_be32(&regs->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX);
1284166ba3bSMichal Simek 	in_be32(&regs->control);
1294166ba3bSMichal Simek }
1304166ba3bSMichal Simek 
_debug_uart_putc(int ch)1314166ba3bSMichal Simek static inline void _debug_uart_putc(int ch)
1324166ba3bSMichal Simek {
1334166ba3bSMichal Simek 	struct uartlite *regs = (struct uartlite *)CONFIG_DEBUG_UART_BASE;
1344166ba3bSMichal Simek 
1354166ba3bSMichal Simek 	while (in_be32(&regs->status) & SR_TX_FIFO_FULL)
1364166ba3bSMichal Simek 		;
1374166ba3bSMichal Simek 
1384166ba3bSMichal Simek 	out_be32(&regs->tx_fifo, ch & 0xff);
1394166ba3bSMichal Simek }
1404166ba3bSMichal Simek 
1414166ba3bSMichal Simek DEBUG_UART_FUNCS
1424166ba3bSMichal Simek #endif
143