X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fserial%2Fserial_xuartlite.c;h=f29a9a0b569c549732b3fb7ece637b65f5e92c49;hb=9452b7496f8b85ca3bdda1014495df1a6235a8de;hp=00d0eaac753ed19678fb812a99fc4c1a258c2809;hpb=ce0eb70333331da6942167c41e6841c8c7994a33;p=oweals%2Fu-boot.git diff --git a/drivers/serial/serial_xuartlite.c b/drivers/serial/serial_xuartlite.c index 00d0eaac75..f29a9a0b56 100644 --- a/drivers/serial/serial_xuartlite.c +++ b/drivers/serial/serial_xuartlite.c @@ -1,77 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * (C) Copyright 2008 Michal Simek + * (C) Copyright 2008 - 2015 Michal Simek * Clean driver and add xilinx constant from header file * * (C) Copyright 2004 Atmark Techno, Inc. * Yasushi SHOJI - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA */ #include +#include +#include #include +#include +#include +#include -#define RX_FIFO_OFFSET 0 /* receive FIFO, read only */ -#define TX_FIFO_OFFSET 4 /* transmit FIFO, write only */ -#define STATUS_REG_OFFSET 8 /* status register, read only */ +#define SR_TX_FIFO_FULL BIT(3) /* transmit FIFO full */ +#define SR_TX_FIFO_EMPTY BIT(2) /* transmit FIFO empty */ +#define SR_RX_FIFO_VALID_DATA BIT(0) /* data in receive FIFO */ +#define SR_RX_FIFO_FULL BIT(1) /* receive FIFO full */ -#define SR_TX_FIFO_FULL 0x08 /* transmit FIFO full */ -#define SR_RX_FIFO_VALID_DATA 0x01 /* data in receive FIFO */ -#define SR_RX_FIFO_FULL 0x02 /* receive FIFO full */ +#define ULITE_CONTROL_RST_TX 0x01 +#define ULITE_CONTROL_RST_RX 0x02 -#define UARTLITE_STATUS (CONFIG_SERIAL_BASE + STATUS_REG_OFFSET) -#define UARTLITE_TX_FIFO (CONFIG_SERIAL_BASE + TX_FIFO_OFFSET) -#define UARTLITE_RX_FIFO (CONFIG_SERIAL_BASE + RX_FIFO_OFFSET) +struct uartlite { + unsigned int rx_fifo; + unsigned int tx_fifo; + unsigned int status; + unsigned int control; +}; -int serial_init(void) +struct uartlite_platdata { + struct uartlite *regs; +}; + +static int uartlite_serial_putc(struct udevice *dev, const char ch) { - /* FIXME: Nothing for now. We should initialize fifo, etc */ + struct uartlite_platdata *plat = dev_get_platdata(dev); + struct uartlite *regs = plat->regs; + + if (in_be32(®s->status) & SR_TX_FIFO_FULL) + return -EAGAIN; + + out_be32(®s->tx_fifo, ch & 0xff); + return 0; } -void serial_setbrg(void) +static int uartlite_serial_getc(struct udevice *dev) { - /* FIXME: what's this for? */ + struct uartlite_platdata *plat = dev_get_platdata(dev); + struct uartlite *regs = plat->regs; + + if (!(in_be32(®s->status) & SR_RX_FIFO_VALID_DATA)) + return -EAGAIN; + + return in_be32(®s->rx_fifo) & 0xff; +} + +static int uartlite_serial_pending(struct udevice *dev, bool input) +{ + struct uartlite_platdata *plat = dev_get_platdata(dev); + struct uartlite *regs = plat->regs; + + if (input) + return in_be32(®s->status) & SR_RX_FIFO_VALID_DATA; + + return !(in_be32(®s->status) & SR_TX_FIFO_EMPTY); } -void serial_putc(const char c) +static int uartlite_serial_probe(struct udevice *dev) { - if (c == '\n') - serial_putc('\r'); - while (in_be32((u32 *) UARTLITE_STATUS) & SR_TX_FIFO_FULL); - out_be32((u32 *) UARTLITE_TX_FIFO, (unsigned char) (c & 0xff)); + struct uartlite_platdata *plat = dev_get_platdata(dev); + struct uartlite *regs = plat->regs; + + out_be32(®s->control, 0); + out_be32(®s->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX); + in_be32(®s->control); + + return 0; } -void serial_puts(const char * s) +static int uartlite_serial_ofdata_to_platdata(struct udevice *dev) { - while (*s) { - serial_putc(*s++); - } + struct uartlite_platdata *plat = dev_get_platdata(dev); + + plat->regs = (struct uartlite *)devfdt_get_addr(dev); + + return 0; } -int serial_getc(void) +static const struct dm_serial_ops uartlite_serial_ops = { + .putc = uartlite_serial_putc, + .pending = uartlite_serial_pending, + .getc = uartlite_serial_getc, +}; + +static const struct udevice_id uartlite_serial_ids[] = { + { .compatible = "xlnx,opb-uartlite-1.00.b", }, + { .compatible = "xlnx,xps-uartlite-1.00.a" }, + { } +}; + +U_BOOT_DRIVER(serial_uartlite) = { + .name = "serial_uartlite", + .id = UCLASS_SERIAL, + .of_match = uartlite_serial_ids, + .ofdata_to_platdata = uartlite_serial_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct uartlite_platdata), + .probe = uartlite_serial_probe, + .ops = &uartlite_serial_ops, +}; + +#ifdef CONFIG_DEBUG_UART_UARTLITE + +#include + +static inline void _debug_uart_init(void) { - while (!(in_be32((u32 *) UARTLITE_STATUS) & SR_RX_FIFO_VALID_DATA)); - return in_be32((u32 *) UARTLITE_RX_FIFO) & 0xff; + struct uartlite *regs = (struct uartlite *)CONFIG_DEBUG_UART_BASE; + + out_be32(®s->control, 0); + out_be32(®s->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX); + in_be32(®s->control); } -int serial_tstc(void) +static inline void _debug_uart_putc(int ch) { - return (in_be32((u32 *) UARTLITE_STATUS) & SR_RX_FIFO_VALID_DATA); + struct uartlite *regs = (struct uartlite *)CONFIG_DEBUG_UART_BASE; + + while (in_be32(®s->status) & SR_TX_FIFO_FULL) + ; + + out_be32(®s->tx_fifo, ch & 0xff); } + +DEBUG_UART_FUNCS +#endif