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/serial_arc.c | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot/drivers/serial/serial_arc.c')
-rw-r--r-- | roms/u-boot/drivers/serial/serial_arc.c | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/roms/u-boot/drivers/serial/serial_arc.c b/roms/u-boot/drivers/serial/serial_arc.c new file mode 100644 index 000000000..8f3e4dd44 --- /dev/null +++ b/roms/u-boot/drivers/serial/serial_arc.c @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <common.h> +#include <dm.h> +#include <serial.h> +#include <asm/global_data.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct arc_serial_regs { + unsigned int id0; + unsigned int id1; + unsigned int id2; + unsigned int id3; + unsigned int data; + unsigned int status; + unsigned int baudl; + unsigned int baudh; +}; + + +struct arc_serial_plat { + struct arc_serial_regs *reg; + unsigned int uartclk; +}; + +/* Bit definitions of STATUS register */ +#define UART_RXEMPTY (1 << 5) +#define UART_OVERFLOW_ERR (1 << 1) +#define UART_TXEMPTY (1 << 7) + +static int arc_serial_setbrg(struct udevice *dev, int baudrate) +{ + struct arc_serial_plat *plat = dev_get_plat(dev); + struct arc_serial_regs *const regs = plat->reg; + int arc_console_baud = gd->cpu_clk / (baudrate * 4) - 1; + + writeb(arc_console_baud & 0xff, ®s->baudl); + writeb((arc_console_baud & 0xff00) >> 8, ®s->baudh); + + return 0; +} + +static int arc_serial_putc(struct udevice *dev, const char c) +{ + struct arc_serial_plat *plat = dev_get_plat(dev); + struct arc_serial_regs *const regs = plat->reg; + + while (!(readb(®s->status) & UART_TXEMPTY)) + ; + + writeb(c, ®s->data); + + return 0; +} + +static int arc_serial_tstc(struct arc_serial_regs *const regs) +{ + return !(readb(®s->status) & UART_RXEMPTY); +} + +static int arc_serial_pending(struct udevice *dev, bool input) +{ + struct arc_serial_plat *plat = dev_get_plat(dev); + struct arc_serial_regs *const regs = plat->reg; + uint32_t status = readb(®s->status); + + if (input) + return status & UART_RXEMPTY ? 0 : 1; + else + return status & UART_TXEMPTY ? 0 : 1; +} + +static int arc_serial_getc(struct udevice *dev) +{ + struct arc_serial_plat *plat = dev_get_plat(dev); + struct arc_serial_regs *const regs = plat->reg; + + while (!arc_serial_tstc(regs)) + ; + + /* Check for overflow errors */ + if (readb(®s->status) & UART_OVERFLOW_ERR) + return 0; + + return readb(®s->data) & 0xFF; +} + +static int arc_serial_probe(struct udevice *dev) +{ + return 0; +} + +static const struct dm_serial_ops arc_serial_ops = { + .putc = arc_serial_putc, + .pending = arc_serial_pending, + .getc = arc_serial_getc, + .setbrg = arc_serial_setbrg, +}; + +static const struct udevice_id arc_serial_ids[] = { + { .compatible = "snps,arc-uart" }, + { } +}; + +static int arc_serial_of_to_plat(struct udevice *dev) +{ + struct arc_serial_plat *plat = dev_get_plat(dev); + DECLARE_GLOBAL_DATA_PTR; + + plat->reg = dev_read_addr_ptr(dev); + plat->uartclk = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), + "clock-frequency", 0); + + return 0; +} + +U_BOOT_DRIVER(serial_arc) = { + .name = "serial_arc", + .id = UCLASS_SERIAL, + .of_match = arc_serial_ids, + .of_to_plat = arc_serial_of_to_plat, + .plat_auto = sizeof(struct arc_serial_plat), + .probe = arc_serial_probe, + .ops = &arc_serial_ops, +}; + +#ifdef CONFIG_DEBUG_ARC_SERIAL +#include <debug_uart.h> + +static inline void _debug_uart_init(void) +{ + struct arc_serial_regs *regs = (struct arc_serial_regs *)CONFIG_DEBUG_UART_BASE; + int arc_console_baud = CONFIG_DEBUG_UART_CLOCK / (CONFIG_BAUDRATE * 4) - 1; + + writeb(arc_console_baud & 0xff, ®s->baudl); + writeb((arc_console_baud & 0xff00) >> 8, ®s->baudh); +} + +static inline void _debug_uart_putc(int c) +{ + struct arc_serial_regs *regs = (struct arc_serial_regs *)CONFIG_DEBUG_UART_BASE; + + while (!(readb(®s->status) & UART_TXEMPTY)) + ; + + writeb(c, ®s->data); +} + +DEBUG_UART_FUNCS + +#endif |