diff options
author | 2023-10-10 14:33:42 +0000 | |
---|---|---|
committer | 2023-10-10 14:33:42 +0000 | |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/u-boot/drivers/serial/altera_uart.c | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot/drivers/serial/altera_uart.c')
-rw-r--r-- | roms/u-boot/drivers/serial/altera_uart.c | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/roms/u-boot/drivers/serial/altera_uart.c b/roms/u-boot/drivers/serial/altera_uart.c new file mode 100644 index 000000000..b18be6e24 --- /dev/null +++ b/roms/u-boot/drivers/serial/altera_uart.c @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <serial.h> +#include <asm/io.h> +#include <linux/bitops.h> + +/* status register */ +#define ALTERA_UART_TMT BIT(5) /* tx empty */ +#define ALTERA_UART_TRDY BIT(6) /* tx ready */ +#define ALTERA_UART_RRDY BIT(7) /* rx ready */ + +struct altera_uart_regs { + u32 rxdata; /* Rx data reg */ + u32 txdata; /* Tx data reg */ + u32 status; /* Status reg */ + u32 control; /* Control reg */ + u32 divisor; /* Baud rate divisor reg */ + u32 endofpacket; /* End-of-packet reg */ +}; + +struct altera_uart_plat { + struct altera_uart_regs *regs; + unsigned int uartclk; +}; + +static int altera_uart_setbrg(struct udevice *dev, int baudrate) +{ + struct altera_uart_plat *plat = dev_get_plat(dev); + struct altera_uart_regs *const regs = plat->regs; + u32 div; + + div = (plat->uartclk / baudrate) - 1; + writel(div, ®s->divisor); + + return 0; +} + +static int altera_uart_putc(struct udevice *dev, const char ch) +{ + struct altera_uart_plat *plat = dev_get_plat(dev); + struct altera_uart_regs *const regs = plat->regs; + + if (!(readl(®s->status) & ALTERA_UART_TRDY)) + return -EAGAIN; + + writel(ch, ®s->txdata); + + return 0; +} + +static int altera_uart_pending(struct udevice *dev, bool input) +{ + struct altera_uart_plat *plat = dev_get_plat(dev); + struct altera_uart_regs *const regs = plat->regs; + u32 st = readl(®s->status); + + if (input) + return st & ALTERA_UART_RRDY ? 1 : 0; + else + return !(st & ALTERA_UART_TMT); +} + +static int altera_uart_getc(struct udevice *dev) +{ + struct altera_uart_plat *plat = dev_get_plat(dev); + struct altera_uart_regs *const regs = plat->regs; + + if (!(readl(®s->status) & ALTERA_UART_RRDY)) + return -EAGAIN; + + return readl(®s->rxdata) & 0xff; +} + +static int altera_uart_probe(struct udevice *dev) +{ + return 0; +} + +static int altera_uart_of_to_plat(struct udevice *dev) +{ + struct altera_uart_plat *plat = dev_get_plat(dev); + + plat->regs = map_physmem(dev_read_addr(dev), + sizeof(struct altera_uart_regs), + MAP_NOCACHE); + plat->uartclk = dev_read_u32_default(dev, "clock-frequency", 0); + + return 0; +} + +static const struct dm_serial_ops altera_uart_ops = { + .putc = altera_uart_putc, + .pending = altera_uart_pending, + .getc = altera_uart_getc, + .setbrg = altera_uart_setbrg, +}; + +static const struct udevice_id altera_uart_ids[] = { + { .compatible = "altr,uart-1.0" }, + {} +}; + +U_BOOT_DRIVER(altera_uart) = { + .name = "altera_uart", + .id = UCLASS_SERIAL, + .of_match = altera_uart_ids, + .of_to_plat = altera_uart_of_to_plat, + .plat_auto = sizeof(struct altera_uart_plat), + .probe = altera_uart_probe, + .ops = &altera_uart_ops, +}; + +#ifdef CONFIG_DEBUG_UART_ALTERA_UART + +#include <debug_uart.h> + +static inline void _debug_uart_init(void) +{ + struct altera_uart_regs *regs = (void *)CONFIG_DEBUG_UART_BASE; + u32 div; + + div = (CONFIG_DEBUG_UART_CLOCK / CONFIG_BAUDRATE) - 1; + writel(div, ®s->divisor); +} + +static inline void _debug_uart_putc(int ch) +{ + struct altera_uart_regs *regs = (void *)CONFIG_DEBUG_UART_BASE; + + while (1) { + u32 st = readl(®s->status); + + if (st & ALTERA_UART_TRDY) + break; + } + + writel(ch, ®s->txdata); +} + +DEBUG_UART_FUNCS + +#endif |