diff options
Diffstat (limited to 'drivers/tty/serial/uartlite.c')
| -rw-r--r-- | drivers/tty/serial/uartlite.c | 280 |
1 files changed, 160 insertions, 120 deletions
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index b8b912b5a8b9..39c1fd1ff9ce 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c @@ -8,6 +8,7 @@ #include <linux/platform_device.h> #include <linux/module.h> +#include <linux/bitfield.h> #include <linux/console.h> #include <linux/serial.h> #include <linux/serial_core.h> @@ -17,23 +18,26 @@ #include <linux/interrupt.h> #include <linux/init.h> #include <linux/io.h> +#include <linux/iopoll.h> #include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_device.h> -#include <linux/of_platform.h> #include <linux/clk.h> #include <linux/pm_runtime.h> #define ULITE_NAME "ttyUL" +#if CONFIG_SERIAL_UARTLITE_NR_UARTS > 4 +#define ULITE_MAJOR 0 /* use dynamic node allocation */ +#define ULITE_MINOR 0 +#else #define ULITE_MAJOR 204 #define ULITE_MINOR 187 +#endif #define ULITE_NR_UARTS CONFIG_SERIAL_UARTLITE_NR_UARTS /* --------------------------------------------------------------------- * Register definitions * * For register details see datasheet: - * http://www.xilinx.com/support/documentation/ip_documentation/opb_uartlite.pdf + * https://www.xilinx.com/support/documentation/ip_documentation/opb_uartlite.pdf */ #define ULITE_RX 0x00 @@ -55,17 +59,25 @@ #define ULITE_CONTROL_RST_TX 0x01 #define ULITE_CONTROL_RST_RX 0x02 #define ULITE_CONTROL_IE 0x10 -#define UART_AUTOSUSPEND_TIMEOUT 3000 +#define UART_AUTOSUSPEND_TIMEOUT 3000 /* ms */ /* Static pointer to console port */ #ifdef CONFIG_SERIAL_UARTLITE_CONSOLE static struct uart_port *console_port; #endif +/** + * struct uartlite_data - Driver private data + * @reg_ops: Functions to read/write registers + * @clk: Our parent clock, if present + * @baud: The baud rate configured when this device was synthesized + * @cflags: The cflags for parity and data bits + */ struct uartlite_data { const struct uartlite_reg_ops *reg_ops; struct clk *clk; - struct uart_driver *ulite_uart_driver; + unsigned int baud; + tcflag_t cflags; }; struct uartlite_reg_ops { @@ -119,6 +131,8 @@ static inline void uart_out32(u32 val, u32 offset, struct uart_port *port) static struct uart_port ulite_ports[ULITE_NR_UARTS]; +static struct uart_driver ulite_uart_driver; + /* --------------------------------------------------------------------- * Core UART driver operations */ @@ -175,7 +189,8 @@ static int ulite_receive(struct uart_port *port, int stat) static int ulite_transmit(struct uart_port *port, int stat) { - struct circ_buf *xmit = &port->state->xmit; + struct tty_port *tport = &port->state->port; + unsigned char ch; if (stat & ULITE_STATUS_TXFULL) return 0; @@ -187,15 +202,16 @@ static int ulite_transmit(struct uart_port *port, int stat) return 1; } - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) + if (uart_tx_stopped(port)) return 0; - uart_out32(xmit->buf[xmit->tail], ULITE_TX, port); - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1); - port->icount.tx++; + if (!uart_fifo_get(port, &ch)) + return 0; + + uart_out32(ch, ULITE_TX, port); /* wake up */ - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); return 1; @@ -208,11 +224,11 @@ static irqreturn_t ulite_isr(int irq, void *dev_id) unsigned long flags; do { - spin_lock_irqsave(&port->lock, flags); + uart_port_lock_irqsave(port, &flags); stat = uart_in32(ULITE_STATUS, port); busy = ulite_receive(port, stat); busy |= ulite_transmit(port, stat); - spin_unlock_irqrestore(&port->lock, flags); + uart_port_unlock_irqrestore(port, flags); n++; } while (busy); @@ -230,9 +246,9 @@ static unsigned int ulite_tx_empty(struct uart_port *port) unsigned long flags; unsigned int ret; - spin_lock_irqsave(&port->lock, flags); + uart_port_lock_irqsave(port, &flags); ret = uart_in32(ULITE_STATUS, port); - spin_unlock_irqrestore(&port->lock, flags); + uart_port_unlock_irqrestore(port, flags); return ret & ULITE_STATUS_TXEMPTY ? TIOCSER_TEMT : 0; } @@ -302,13 +318,20 @@ static void ulite_shutdown(struct uart_port *port) clk_disable(pdata->clk); } -static void ulite_set_termios(struct uart_port *port, struct ktermios *termios, - struct ktermios *old) +static void ulite_set_termios(struct uart_port *port, + struct ktermios *termios, + const struct ktermios *old) { unsigned long flags; - unsigned int baud; + struct uartlite_data *pdata = port->private_data; + + /* Set termios to what the hardware supports */ + termios->c_iflag &= ~BRKINT; + termios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CSIZE); + termios->c_cflag |= pdata->cflags & (PARENB | PARODD | CSIZE); + tty_termios_encode_baud_rate(termios, pdata->baud, pdata->baud); - spin_lock_irqsave(&port->lock, flags); + uart_port_lock_irqsave(port, &flags); port->read_status_mask = ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN | ULITE_STATUS_TXFULL; @@ -329,10 +352,9 @@ static void ulite_set_termios(struct uart_port *port, struct ktermios *termios, | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN; /* update timeout */ - baud = uart_get_baud_rate(port, termios, old, 0, 460800); - uart_update_timeout(port, termios->c_cflag, baud); + uart_update_timeout(port, termios->c_cflag, pdata->baud); - spin_unlock_irqrestore(&port->lock, flags); + uart_port_unlock_irqrestore(port, flags); } static const char *ulite_type(struct uart_port *port) @@ -393,8 +415,12 @@ static int ulite_verify_port(struct uart_port *port, struct serial_struct *ser) static void ulite_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) { + int ret; + if (!state) { - pm_runtime_get_sync(port->dev); + ret = pm_runtime_get_sync(port->dev); + if (ret < 0) + dev_err(port->dev, "Failed to enable clocks\n"); } else { pm_runtime_mark_last_busy(port->dev); pm_runtime_put_autosuspend(port->dev); @@ -451,27 +477,18 @@ static const struct uart_ops ulite_ops = { static void ulite_console_wait_tx(struct uart_port *port) { u8 val; - unsigned long timeout; /* * Spin waiting for TX fifo to have space available. * When using the Microblaze Debug Module this can take up to 1s */ - timeout = jiffies + msecs_to_jiffies(1000); - while (1) { - val = uart_in32(ULITE_STATUS, port); - if ((val & ULITE_STATUS_TXFULL) == 0) - break; - if (time_after(jiffies, timeout)) { - dev_warn(port->dev, - "timeout waiting for TX buffer empty\n"); - break; - } - cpu_relax(); - } + if (read_poll_timeout_atomic(uart_in32, val, !(val & ULITE_STATUS_TXFULL), + 0, 1000000, false, ULITE_STATUS, port)) + dev_warn(port->dev, + "timeout waiting for TX buffer empty\n"); } -static void ulite_console_putchar(struct uart_port *port, int ch) +static void ulite_console_putchar(struct uart_port *port, unsigned char ch) { ulite_console_wait_tx(port); uart_out32(ch, ULITE_TX, port); @@ -486,9 +503,9 @@ static void ulite_console_write(struct console *co, const char *s, int locked = 1; if (oops_in_progress) { - locked = spin_trylock_irqsave(&port->lock, flags); + locked = uart_port_trylock_irqsave(port, &flags); } else - spin_lock_irqsave(&port->lock, flags); + uart_port_lock_irqsave(port, &flags); /* save and disable interrupt */ ier = uart_in32(ULITE_STATUS, port) & ULITE_STATUS_IE; @@ -503,26 +520,28 @@ static void ulite_console_write(struct console *co, const char *s, uart_out32(ULITE_CONTROL_IE, ULITE_CONTROL, port); if (locked) - spin_unlock_irqrestore(&port->lock, flags); + uart_port_unlock_irqrestore(port, flags); } static int ulite_console_setup(struct console *co, char *options) { - struct uart_port *port; + struct uart_port *port = NULL; int baud = 9600; int bits = 8; int parity = 'n'; int flow = 'n'; - - port = console_port; + if (co->index >= 0 && co->index < ULITE_NR_UARTS) + port = ulite_ports + co->index; /* Has the device been initialized yet? */ - if (!port->mapbase) { + if (!port || !port->mapbase) { pr_debug("console on ttyUL%i not present\n", co->index); return -ENODEV; } + console_port = port; + /* not initialized yet? */ if (!port->membase) { if (ulite_request_port(port)) @@ -535,8 +554,6 @@ static int ulite_console_setup(struct console *co, char *options) return uart_set_options(port, co, baud, parity, bits, flow); } -static struct uart_driver ulite_uart_driver; - static struct console ulite_console = { .name = ULITE_NAME, .write = ulite_console_write, @@ -547,7 +564,7 @@ static struct console ulite_console = { .data = &ulite_uart_driver, }; -static void early_uartlite_putc(struct uart_port *port, int c) +static void early_uartlite_putc(struct uart_port *port, unsigned char c) { /* * Limit how many times we'll spin waiting for TX FIFO status. @@ -556,16 +573,15 @@ static void early_uartlite_putc(struct uart_port *port, int c) * This limit is pretty arbitrary, unless we are at about 10 baud * we'll never timeout on a working UART. */ - unsigned retries = 1000000; - /* read status bit - 0x8 offset */ - while (--retries && (readl(port->membase + 8) & (1 << 3))) + + while (--retries && + (readl(port->membase + ULITE_STATUS) & ULITE_STATUS_TXFULL)) ; /* Only attempt the iowrite if we didn't timeout */ - /* write to TX_FIFO - 0x4 offset */ if (retries) - writel(c & 0xff, port->membase + 4); + writel(c & 0xff, port->membase + ULITE_TX); } static void early_uartlite_write(struct console *console, @@ -616,7 +632,7 @@ static struct uart_driver ulite_uart_driver = { * * Returns: 0 on success, <0 otherwise */ -static int ulite_assign(struct device *dev, int id, u32 base, int irq, +static int ulite_assign(struct device *dev, int id, phys_addr_t base, int irq, struct uartlite_data *pdata) { struct uart_port *port; @@ -658,17 +674,6 @@ static int ulite_assign(struct device *dev, int id, u32 base, int irq, dev_set_drvdata(dev, port); -#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE - /* - * If console hasn't been found yet try to assign this port - * because it is required to be assigned for console setup function. - * If register_console() don't assign value, then console_port pointer - * is cleanup. - */ - if (ulite_uart_driver.cons->index == -1) - console_port = port; -#endif - /* Register the port */ rc = uart_add_one_port(&ulite_uart_driver, port); if (rc) { @@ -678,12 +683,6 @@ static int ulite_assign(struct device *dev, int id, u32 base, int irq, return rc; } -#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE - /* This is not port which is used for console that's why clean it up */ - if (ulite_uart_driver.cons->index == -1) - console_port = NULL; -#endif - return 0; } @@ -691,20 +690,15 @@ static int ulite_assign(struct device *dev, int id, u32 base, int irq, * * @dev: pointer to device structure */ -static int ulite_release(struct device *dev) +static void ulite_release(struct device *dev) { struct uart_port *port = dev_get_drvdata(dev); - int rc = 0; if (port) { - struct uartlite_data *pdata = port->private_data; - - rc = uart_remove_one_port(pdata->ulite_uart_driver, port); + uart_remove_one_port(&ulite_uart_driver, port); dev_set_drvdata(dev, NULL); port->mapbase = 0; } - - return rc; } /** @@ -717,11 +711,8 @@ static int __maybe_unused ulite_suspend(struct device *dev) { struct uart_port *port = dev_get_drvdata(dev); - if (port) { - struct uartlite_data *pdata = port->private_data; - - uart_suspend_port(pdata->ulite_uart_driver, port); - } + if (port) + uart_suspend_port(&ulite_uart_driver, port); return 0; } @@ -736,11 +727,8 @@ static int __maybe_unused ulite_resume(struct device *dev) { struct uart_port *port = dev_get_drvdata(dev); - if (port) { - struct uartlite_data *pdata = port->private_data; - - uart_resume_port(pdata->ulite_uart_driver, port); - } + if (port) + uart_resume_port(&ulite_uart_driver, port); return 0; } @@ -758,10 +746,16 @@ static int __maybe_unused ulite_runtime_resume(struct device *dev) { struct uart_port *port = dev_get_drvdata(dev); struct uartlite_data *pdata = port->private_data; + int ret; - clk_enable(pdata->clk); + ret = clk_enable(pdata->clk); + if (ret) { + dev_err(dev, "Cannot enable clock.\n"); + return ret; + } return 0; } + /* --------------------------------------------------------------------- * Platform bus binding */ @@ -788,41 +782,80 @@ static int ulite_probe(struct platform_device *pdev) struct uartlite_data *pdata; int irq, ret; int id = pdev->id; -#ifdef CONFIG_OF - const __be32 *prop; - - prop = of_get_property(pdev->dev.of_node, "port-number", NULL); - if (prop) - id = be32_to_cpup(prop); -#endif - if (id < 0) { - /* Look for a serialN alias */ - id = of_alias_get_id(pdev->dev.of_node, "serial"); - if (id < 0) - id = 0; - } - - if (!ulite_uart_driver.state) { - dev_dbg(&pdev->dev, "uartlite: calling uart_register_driver()\n"); - ret = uart_register_driver(&ulite_uart_driver); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to register driver\n"); - return ret; - } - } pdata = devm_kzalloc(&pdev->dev, sizeof(struct uartlite_data), GFP_KERNEL); if (!pdata) return -ENOMEM; + if (IS_ENABLED(CONFIG_OF)) { + const char *prop; + struct device_node *np = pdev->dev.of_node; + u32 val = 0; + + prop = "port-number"; + ret = of_property_read_u32(np, prop, &id); + if (ret && ret != -EINVAL) +of_err: + return dev_err_probe(&pdev->dev, ret, + "could not read %s\n", prop); + + prop = "current-speed"; + ret = of_property_read_u32(np, prop, &pdata->baud); + if (ret) + goto of_err; + + prop = "xlnx,use-parity"; + ret = of_property_read_u32(np, prop, &val); + if (ret && ret != -EINVAL) + goto of_err; + + if (val) { + prop = "xlnx,odd-parity"; + ret = of_property_read_u32(np, prop, &val); + if (ret) + goto of_err; + + if (val) + pdata->cflags |= PARODD; + pdata->cflags |= PARENB; + } + + val = 8; + prop = "xlnx,data-bits"; + ret = of_property_read_u32(np, prop, &val); + if (ret && ret != -EINVAL) + goto of_err; + + switch (val) { + case 5: + pdata->cflags |= CS5; + break; + case 6: + pdata->cflags |= CS6; + break; + case 7: + pdata->cflags |= CS7; + break; + case 8: + pdata->cflags |= CS8; + break; + default: + return dev_err_probe(&pdev->dev, -EINVAL, + "bad data bits %d\n", val); + } + } else { + pdata->baud = 9600; + pdata->cflags = CS8; + } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; irq = platform_get_irq(pdev, 0); - if (irq <= 0) - return -ENXIO; + if (irq < 0) + return irq; pdata->clk = devm_clk_get(&pdev->dev, "s_axi_aclk"); if (IS_ERR(pdata->clk)) { @@ -836,7 +869,6 @@ static int ulite_probe(struct platform_device *pdev) pdata->clk = NULL; } - pdata->ulite_uart_driver = &ulite_uart_driver; ret = clk_prepare_enable(pdata->clk); if (ret) { dev_err(&pdev->dev, "Failed to prepare clock\n"); @@ -856,18 +888,16 @@ static int ulite_probe(struct platform_device *pdev) return ret; } -static int ulite_remove(struct platform_device *pdev) +static void ulite_remove(struct platform_device *pdev) { struct uart_port *port = dev_get_drvdata(&pdev->dev); struct uartlite_data *pdata = port->private_data; - int rc; - clk_unprepare(pdata->clk); - rc = ulite_release(&pdev->dev); + clk_disable_unprepare(pdata->clk); + ulite_release(&pdev->dev); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev); - return rc; } /* work with hotplug and coldplug */ @@ -889,9 +919,19 @@ static struct platform_driver ulite_platform_driver = { static int __init ulite_init(void) { + int ret; + + pr_debug("uartlite: calling uart_register_driver()\n"); + ret = uart_register_driver(&ulite_uart_driver); + if (ret) + return ret; pr_debug("uartlite: calling platform_driver_register()\n"); - return platform_driver_register(&ulite_platform_driver); + ret = platform_driver_register(&ulite_platform_driver); + if (ret) + uart_unregister_driver(&ulite_uart_driver); + + return ret; } static void __exit ulite_exit(void) |
