X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fserial%2Fserial_arc.c;h=925f0c2555446021ff24fca47f685273e2764acf;hb=914bb7ea2f9373fa59285ff77a95df73848c8f66;hp=e63d25d7949a47bbd73efc97e80685d162215c19;hpb=a87a0ce7028d5371c81d77ba72c1ba43a1ca77bc;p=u-boot diff --git a/drivers/serial/serial_arc.c b/drivers/serial/serial_arc.c index e63d25d794..925f0c2555 100644 --- a/drivers/serial/serial_arc.c +++ b/drivers/serial/serial_arc.c @@ -8,6 +8,7 @@ */ #include +#include #include DECLARE_GLOBAL_DATA_PTR; @@ -23,83 +24,135 @@ struct arc_serial_regs { unsigned int baudh; }; + +struct arc_serial_platdata { + 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) -struct arc_serial_regs *regs; - -static void arc_serial_setbrg(void) +static int arc_serial_setbrg(struct udevice *dev, int baudrate) { - int arc_console_baud; + struct arc_serial_platdata *plat = dev->platdata; + struct arc_serial_regs *const regs = plat->reg; + int arc_console_baud = gd->cpu_clk / (baudrate * 4) - 1; - if (!gd->baudrate) - gd->baudrate = CONFIG_BAUDRATE; + writeb(arc_console_baud & 0xff, ®s->baudl); + writeb((arc_console_baud & 0xff00) >> 8, ®s->baudh); - arc_console_baud = gd->cpu_clk / (gd->baudrate * 4) - 1; - writel(arc_console_baud & 0xff, ®s->baudl); - writel((arc_console_baud & 0xff00) >> 8, ®s->baudh); -} - -static int arc_serial_init(void) -{ - regs = (struct arc_serial_regs *)CONFIG_ARC_UART_BASE; - serial_setbrg(); return 0; } -static void arc_serial_putc(const char c) +static int arc_serial_putc(struct udevice *dev, const char c) { - if (c == '\n') - arc_serial_putc('\r'); + struct arc_serial_platdata *plat = dev->platdata; + struct arc_serial_regs *const regs = plat->reg; - while (!(readl(®s->status) & UART_TXEMPTY)) + while (!(readb(®s->status) & UART_TXEMPTY)) ; - writel(c, ®s->data); + 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_tstc(void) +static int arc_serial_pending(struct udevice *dev, bool input) { - return !(readl(®s->status) & UART_RXEMPTY); + struct arc_serial_platdata *plat = dev->platdata; + 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(void) +static int arc_serial_getc(struct udevice *dev) { - while (!arc_serial_tstc()) + struct arc_serial_platdata *plat = dev->platdata; + struct arc_serial_regs *const regs = plat->reg; + + while (!arc_serial_tstc(regs)) ; /* Check for overflow errors */ - if (readl(®s->status) & UART_OVERFLOW_ERR) + if (readb(®s->status) & UART_OVERFLOW_ERR) return 0; - return readl(®s->data) & 0xFF; + return readb(®s->data) & 0xFF; } -static void arc_serial_puts(const char *s) +static int arc_serial_probe(struct udevice *dev) { - while (*s) - arc_serial_putc(*s++); + return 0; } -static struct serial_device arc_serial_drv = { - .name = "arc_serial", - .start = arc_serial_init, - .stop = NULL, - .setbrg = arc_serial_setbrg, - .putc = arc_serial_putc, - .puts = arc_serial_puts, - .getc = arc_serial_getc, - .tstc = arc_serial_tstc, +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" }, + { } }; -void arc_serial_initialize(void) +static int arc_serial_ofdata_to_platdata(struct udevice *dev) { - serial_register(&arc_serial_drv); + struct arc_serial_platdata *plat = dev_get_platdata(dev); + DECLARE_GLOBAL_DATA_PTR; + + plat->reg = (struct arc_serial_regs *)devfdt_get_addr(dev); + plat->uartclk = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), + "clock-frequency", 0); + + return 0; } -__weak struct serial_device *default_serial_console(void) +U_BOOT_DRIVER(serial_arc) = { + .name = "serial_arc", + .id = UCLASS_SERIAL, + .of_match = arc_serial_ids, + .ofdata_to_platdata = arc_serial_ofdata_to_platdata, + .probe = arc_serial_probe, + .ops = &arc_serial_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +#ifdef CONFIG_DEBUG_ARC_SERIAL +#include + +static inline void _debug_uart_init(void) { - return &arc_serial_drv; + 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