diff options
author | Antony Pavlov <antonynpavlov@gmail.com> | 2021-08-17 13:10:58 +0300 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2021-10-04 14:02:28 +0200 |
commit | b239e5920ed19e3d8cd0d1a8d3cf069beefa0bbd (patch) | |
tree | 363b95f2a3db7ff971914f596341f8c22efdc123 /drivers/serial | |
parent | 2312fdac8ce15c43256e91a9b91d3811754d337b (diff) | |
download | barebox-b239e5920ed19e3d8cd0d1a8d3cf069beefa0bbd.tar.gz barebox-b239e5920ed19e3d8cd0d1a8d3cf069beefa0bbd.tar.xz |
serial: add litex UART driver
Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com>
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Tested-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Link: https://lore.barebox.org/20210817101104.114945-3-antonynpavlov@gmail.com
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/Makefile | 1 | ||||
-rw-r--r-- | drivers/serial/serial_litex.c | 96 |
2 files changed, 97 insertions, 0 deletions
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 5120b17376..45055371ea 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -24,3 +24,4 @@ obj-$(CONFIG_DRIVER_SERIAL_DIGIC) += serial_digic.o obj-$(CONFIG_DRIVER_SERIAL_LPUART) += serial_lpuart.o obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o obj-$(CONFIG_SERIAL_SIFIVE) += serial_sifive.o +obj-$(CONFIG_SOC_LITEX) += serial_litex.o diff --git a/drivers/serial/serial_litex.c b/drivers/serial/serial_litex.c new file mode 100644 index 0000000000..8562a45ecc --- /dev/null +++ b/drivers/serial/serial_litex.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 Antony Pavlov <antonynpavlov@gmail.com> + * + */ + +#include <common.h> +#include <init.h> +#include <io.h> + +#define UART_RXTX 0x00 +#define UART_TXFULL 0x04 +#define UART_RXEMPTY 0x08 +#define UART_EV_PENDING 0x10 +#define UART_EV_RX (1 << 1) + +static inline uint32_t litex_serial_readb(struct console_device *cdev, + uint32_t offset) +{ + void __iomem *base = cdev->dev->priv; + + return readb(base + offset); +} + +static inline void litex_serial_writeb(struct console_device *cdev, + uint32_t value, uint32_t offset) +{ + void __iomem *base = cdev->dev->priv; + + writeb(value, base + offset); +} + +static void litex_serial_putc(struct console_device *cdev, char c) +{ + while (litex_serial_readb(cdev, UART_TXFULL)) + ; + + litex_serial_writeb(cdev, c, UART_RXTX); +} + +static int litex_serial_getc(struct console_device *cdev) +{ + int c; + + while (litex_serial_readb(cdev, UART_RXEMPTY)) + ; + + c = litex_serial_readb(cdev, UART_RXTX); + + /* refresh UART_RXEMPTY by writing UART_EV_RX to UART_EV_PENDING */ + litex_serial_writeb(cdev, UART_EV_RX, UART_EV_PENDING); + + return c; +} + +static int litex_serial_tstc(struct console_device *cdev) +{ + return !litex_serial_readb(cdev, UART_RXEMPTY); +} + +static int litex_serial_probe(struct device_d *dev) +{ + struct resource *iores; + struct console_device *cdev; + + cdev = xzalloc(sizeof(struct console_device)); + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + + dev->priv = IOMEM(iores->start); + cdev->dev = dev; + cdev->tstc = &litex_serial_tstc; + cdev->putc = &litex_serial_putc; + cdev->getc = &litex_serial_getc; + cdev->setbrg = NULL; + + console_register(cdev); + + return 0; +} + +static __maybe_unused struct of_device_id litex_serial_dt_ids[] = { + { + .compatible = "litex,uart", + }, { + /* sentinel */ + } +}; + +static struct driver_d litex_serial_driver = { + .name = "litex-uart", + .probe = litex_serial_probe, + .of_compatible = DRV_OF_COMPAT(litex_serial_dt_ids), +}; +console_platform_driver(litex_serial_driver); |