Revert "tty: serial: Add UART driver for Cortina-Access platform"
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 24 Jun 2021 12:46:32 +0000 (14:46 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 24 Jun 2021 12:46:32 +0000 (14:46 +0200)
This reverts commit b61c8bf4694b5115766849378dcb8787ff54e65e.  It never
made it to a public mailing list and still needs some work based on the
review comments.  So revert it for now.

Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
Link: https://lore.kernel.org/r/CAMuHMdXA9-ajoAza2JAW5879ECieMm1dbBbKHgJhDa7=3kWu3w@mail.gmail.com
Cc: Jason Li <jason.li@cortina-access.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
MAINTAINERS
drivers/tty/serial/Kconfig
drivers/tty/serial/Makefile
drivers/tty/serial/serial_cortina-access.c [deleted file]

index f20502df69b894e03057dd2a6cbb77b52b96b401..25d7d864cfbd1cbfec7989ae9eaaa76226ee6325 100644 (file)
@@ -4680,11 +4680,6 @@ S:       Maintained
 W:     http://www.fi.muni.cz/~kas/cosa/
 F:     drivers/net/wan/cosa*
 
-CORTINA-ACCESS SERIAL CONSOLE DRIVER
-M:     Jason Li <jason.li@cortina-access.com>
-S:     Supported
-F:     drivers/tty/serial/serial_cortina-access.c
-
 COUNTER SUBSYSTEM
 M:     William Breathitt Gray <vilhelm.gray@gmail.com>
 L:     linux-iio@vger.kernel.org
index 2fa39cd78c56ef065d21ee136ffe91966a975152..24282ad99d85029cb48a5a54c3c8ed079f760057 100644 (file)
@@ -1561,25 +1561,6 @@ config SERIAL_LITEUART_CONSOLE
          and warnings and which allows logins in single user mode).
          Otherwise, say 'N'.
 
-config SERIAL_CORTINA_ACCESS
-       tristate "Cortina-Access serial port support"
-       select SERIAL_CORE
-       help
-         This driver is for Cortina-Access SoC's UART. If you have a machine
-         based on the Cortina-Access SoC and wish to use the serial port,
-         say 'Y' here. Otherwise, say 'N'.
-
-config SERIAL_CORTINA_ACCESS_CONSOLE
-       bool "Console on Cortina-ACCESS serial port"
-       depends on SERIAL_CORTINA_ACCESS=y
-       select SERIAL_CORE_CONSOLE
-       select SERIAL_EARLYCON
-       help
-         Say 'Y' here if you wish to use Cortina-Access UART as the system
-         console. (the system console is the device which receives all kernel
-         messages and warnings and which allows logins in single user mode)
-         /dev/ttyS* is default device node.
-
 endmenu
 
 config SERIAL_MCTRL_GPIO
index f3f531a48854b2f5adb573ada1f77e7da7bf873b..7da0856cd19828357bd1a81088c28c632511deb1 100644 (file)
@@ -87,7 +87,6 @@ obj-$(CONFIG_SERIAL_RDA)      += rda-uart.o
 obj-$(CONFIG_SERIAL_MILBEAUT_USIO) += milbeaut_usio.o
 obj-$(CONFIG_SERIAL_SIFIVE)    += sifive.o
 obj-$(CONFIG_SERIAL_LITEUART) += liteuart.o
-obj-$(CONFIG_SERIAL_CORTINA_ACCESS)    += serial_cortina-access.o
 
 # GPIOLIB helpers for modem control lines
 obj-$(CONFIG_SERIAL_MCTRL_GPIO)        += serial_mctrl_gpio.o
diff --git a/drivers/tty/serial/serial_cortina-access.c b/drivers/tty/serial/serial_cortina-access.c
deleted file mode 100644 (file)
index b4b9362..0000000
+++ /dev/null
@@ -1,798 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- *  UART driver for Cortina-Access Soc platform
- *  Copyright (C) 2021 Cortina-Access Inc.
- */
-#include <linux/module.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/sysrq.h>
-#include <linux/console.h>
-#include <linux/serial_core.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-
-/***************************************
- *     UART Related registers
- ****************************************/
-/* register definitions */
-#define        CFG                     0x00
-#define        FC                      0x04
-#define        RX_SAMPLE               0x08
-#define        RT_TUNE                 0x0C
-#define        TX_DAT                  0x10
-#define        RX_DAT                  0x14
-#define        INFO                    0x18
-#define        IE                      0x1C
-#define        INT                     0x24
-#define        STATUS                  0x2C
-
-/* CFG */
-#define        CFG_STOP_2BIT           BIT(2)
-#define        CFG_PARITY_EVEN BIT(3)
-#define        CFG_PARITY_EN           BIT(4)
-#define        CFG_TX_EN               BIT(5)
-#define        CFG_RX_EN               BIT(6)
-#define        CFG_UART_EN             BIT(7)
-#define        CFG_BAUD_SART_SHIFT     8
-
-/* INFO */
-#define        INFO_TX_EMPTY           BIT(3)
-#define        INFO_TX_FULL            BIT(2)
-#define        INFO_RX_EMPTY           BIT(1)
-#define        INFO_RX_FULL            BIT(0)
-
-/* Interrupt */
-#define        RX_BREAK                BIT(7)
-#define        RX_FIFO_NONEMPTYE       BIT(6)
-#define        TX_FIFO_EMPTYE          BIT(5)
-#define        RX_FIFO_UNDERRUNE       BIT(4)
-#define        RX_FIFO_OVERRUNE        BIT(3)
-#define        RX_PARITY_ERRE          BIT(2)
-#define        RX_STOP_ERRE            BIT(1)
-#define        TX_FIFO_OVERRUNE        BIT(0)
-
-#define TX_TIMEOUT             5000
-#define UART_NR 4
-#define CA_UART_NAME_LEN       32
-struct cortina_uart_port {
-       struct uart_port uart;
-       char name[CA_UART_NAME_LEN];
-       char has_bi;
-       unsigned int may_wakeup;
-};
-
-static struct cortina_uart_port *cortina_uart_ports;
-
-static irqreturn_t cortina_uart_interrupt(int irq, void *dev_id);
-
-/* Return uart_port pointer base on index */
-struct cortina_uart_port *cortina_uart_get_port(unsigned int index)
-{
-       struct cortina_uart_port *pca_port = cortina_uart_ports;
-
-       if (index >= UART_NR) {
-               /* return 1st element if invalid index */
-               index = 0;
-       }
-
-       pca_port += index;
-
-       return pca_port;
-}
-
-/* uart_ops functions */
-static unsigned int cortina_uart_tx_empty(struct uart_port *port)
-{
-       /* Return 0 on FIXO condition, TIOCSER_TEMT otherwise */
-       return (readl(port->membase + INFO) & INFO_TX_EMPTY) ? TIOCSER_TEMT : 0;
-}
-
-static void cortina_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-/*
- * Even if we do not support configuring the modem control lines, this
- * function must be proided to the serial core.
- * port->ops->set_mctrl() be called in uart_configure_port()
- */
-}
-
-static unsigned int cortina_uart_get_mctrl(struct uart_port *port)
-{
-       /* Unimplemented signals asserted, per Documentation/serial/driver */
-       return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
-}
-
-static void cortina_uart_stop_tx(struct uart_port *port)
-{
-       /* Turn off Tx interrupts. The port lock is held at this point */
-       unsigned int reg_v;
-
-       reg_v = readl(port->membase + IE);
-       writel(reg_v & ~TX_FIFO_EMPTYE, port->membase + IE);
-}
-
-static inline void cortina_transmit_buffer(struct uart_port *port)
-{
-       struct circ_buf *xmit = &port->state->xmit;
-
-       if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
-               cortina_uart_stop_tx(port);
-               return;
-       }
-
-       do {
-               /* send xmit->buf[xmit->tail] out the port here */
-               writel(xmit->buf[xmit->tail], port->membase + TX_DAT);
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               port->icount.tx++;
-               if ((readl(port->membase + INFO) & INFO_TX_FULL))
-                       break;
-       } while (!uart_circ_empty(xmit));
-
-       if (uart_circ_empty(xmit))
-               cortina_uart_stop_tx(port);
-}
-
-static void cortina_uart_start_tx(struct uart_port *port)
-{
-       /* Turn on Tx interrupts. The port lock is held at this point */
-       unsigned int reg_v;
-
-       reg_v = readl(port->membase + IE);
-       writel((reg_v | TX_FIFO_EMPTYE), port->membase + IE);
-
-       reg_v = readl(port->membase + CFG);
-       writel(reg_v | CFG_TX_EN, port->membase + CFG);
-
-       if (readl(port->membase + INFO) & INFO_TX_EMPTY)
-               cortina_transmit_buffer(port);
-}
-
-static void cortina_uart_stop_rx(struct uart_port *port)
-{
-       /* Turn off Rx interrupts. The port lock is held at this point */
-       unsigned int reg_v;
-
-       reg_v = readl(port->membase + IE);
-       writel(reg_v & ~RX_FIFO_NONEMPTYE, port->membase + IE);
-}
-
-static void cortina_uart_enable_ms(struct uart_port *port)
-{
-       /* Nope, you really can't hope to attach a modem to this */
-}
-
-static int cortina_uart_startup(struct uart_port *port)
-{
-       unsigned int reg_v;
-       int retval;
-       unsigned long flags;
-
-       /* Disable interrupt */
-       writel(0, port->membase + IE);
-
-       retval =
-           request_irq(port->irq, cortina_uart_interrupt, 0, "cortina_uart",
-                       port);
-       if (retval)
-               return retval;
-
-       spin_lock_irqsave(&port->lock, flags);
-
-       reg_v = readl(port->membase + CFG);
-       reg_v |= (CFG_UART_EN | CFG_TX_EN | CFG_RX_EN | 0x3 /* 8-bits data */);
-       writel(reg_v, port->membase + CFG);
-       reg_v = readl(port->membase + IE);
-       writel(reg_v | RX_FIFO_NONEMPTYE | TX_FIFO_EMPTYE, port->membase + IE);
-
-       spin_unlock_irqrestore(&port->lock, flags);
-       return 0;
-}
-
-static void cortina_uart_shutdown(struct uart_port *port)
-{
-       cortina_uart_stop_tx(port);
-       cortina_uart_stop_rx(port);
-       free_irq(port->irq, port);
-}
-
-static void cortina_uart_set_termios(struct uart_port *port,
-                                    struct ktermios *termios,
-                                    struct ktermios *old)
-{
-       unsigned long flags;
-       int baud;
-       unsigned int reg_v, sample_freq = 0;
-
-       baud = uart_get_baud_rate(port, termios, old, 0, 230400);
-       reg_v = readl(port->membase + CFG);
-       /* mask off the baud settings */
-       reg_v &= 0xff;
-       reg_v |= (port->uartclk / baud) << CFG_BAUD_SART_SHIFT;
-
-       /* Sampling rate should be half of baud count */
-       sample_freq = (reg_v >> CFG_BAUD_SART_SHIFT) / 2;
-
-       /* See include/uapi/asm-generic/termbits.h for CSIZE definition */
-       /* mask off the data width */
-       reg_v &= 0xfffffffc;
-       switch (termios->c_cflag & CSIZE) {
-       case CS5:
-               reg_v |= 0x0;
-               break;
-       case CS6:
-               reg_v |= 0x1;
-               break;
-       case CS7:
-               reg_v |= 0x2;
-               break;
-       case CS8:
-       default:
-               reg_v |= 0x3;
-               break;
-       }
-
-       /* mask off Stop bits */
-       reg_v &= ~(CFG_STOP_2BIT);
-       if (termios->c_cflag & CSTOPB)
-               reg_v |= CFG_STOP_2BIT;
-
-       /* Parity */
-       reg_v &= ~(CFG_PARITY_EN);
-       reg_v |= CFG_PARITY_EVEN;
-       if (termios->c_cflag & PARENB) {
-               reg_v |= CFG_PARITY_EN;
-               if (termios->c_cflag & PARODD)
-                       reg_v &= ~(CFG_PARITY_EVEN);
-       }
-
-       spin_lock_irqsave(&port->lock, flags);
-       writel(reg_v, port->membase + CFG);
-       writel(sample_freq, port->membase + RX_SAMPLE);
-       spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static const char *cortina_uart_type(struct uart_port *port)
-{
-       return container_of(port, struct cortina_uart_port, uart)->name;
-}
-
-static void cortina_uart_config_port(struct uart_port *port, int flags)
-{
-       /*
-        * Driver core for serial ports forces a non-zero value for port type.
-        * Write an arbitrary value here to accommodate the serial core driver,
-        * as ID part of UAPI is redundant.
-        */
-       port->type = 1;
-}
-
-static int cortina_uart_verify_port(struct uart_port *port,
-                                   struct serial_struct *ser)
-{
-       if (ser->type != PORT_UNKNOWN && ser->type != 1)
-               return -EINVAL;
-       return 0;
-}
-
-static void cortina_access_power(struct uart_port *port, unsigned int state,
-                     unsigned int oldstate)
-{
-       unsigned int reg_v;
-
-       /* Read Config register */
-       reg_v = readl(port->membase + CFG);
-       switch (state) {
-       case UART_PM_STATE_ON:
-               reg_v |= CFG_UART_EN;
-               break;
-       case UART_PM_STATE_OFF:
-               reg_v &= ~CFG_UART_EN;
-               break;
-       default:
-               pr_err("cortina-access serial: Unknown PM state %d\n", state);
-       }
-       writel(reg_v, port->membase + CFG);
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-static int cortina_poll_get_char(struct uart_port *port)
-{
-       unsigned int rx;
-
-       if (readl(port->membase + INFO) & INFO_RX_EMPTY)
-               return NO_POLL_CHAR;
-
-       rx = readl(port->membase + RX_DAT);
-
-       return rx;
-}
-
-static void cortina_poll_put_char(struct uart_port *port, unsigned char c)
-{
-       unsigned long time_out;
-
-       time_out = jiffies + usecs_to_jiffies(TX_TIMEOUT);
-
-       while (time_before(jiffies, time_out) &&
-               (readl(port->membase + INFO) & INFO_TX_FULL))
-               cpu_relax();
-
-       /* Give up if FIFO stuck! */
-       if ((readl(port->membase + INFO) & INFO_TX_FULL))
-               return;
-
-       writel(c, port->membase + TX_DAT);
-}
-
-#endif
-
-static const struct uart_ops cortina_uart_ops = {
-       .tx_empty = cortina_uart_tx_empty,
-       .set_mctrl = cortina_uart_set_mctrl,
-       .get_mctrl = cortina_uart_get_mctrl,
-       .stop_tx = cortina_uart_stop_tx,
-       .start_tx = cortina_uart_start_tx,
-       .stop_rx = cortina_uart_stop_rx,
-       .enable_ms = cortina_uart_enable_ms,
-       .startup = cortina_uart_startup,
-       .shutdown = cortina_uart_shutdown,
-       .set_termios = cortina_uart_set_termios,
-       .type = cortina_uart_type,
-       .config_port = cortina_uart_config_port,
-       .verify_port = cortina_uart_verify_port,
-       .pm = cortina_access_power,
-#ifdef CONFIG_CONSOLE_POLL
-       .poll_get_char = cortina_poll_get_char,
-       .poll_put_char = cortina_poll_put_char,
-#endif
-};
-
-static inline void cortina_uart_interrupt_rx_chars(struct uart_port *port,
-                                                  unsigned long status)
-{
-       struct tty_port *ttyport = &port->state->port;
-       unsigned int ch;
-       unsigned int rx, flg;
-       struct cortina_uart_port *pca_port;
-
-       rx = readl(port->membase + INFO);
-       if (INFO_RX_EMPTY & rx)
-               return;
-
-       if (status & RX_FIFO_OVERRUNE)
-               port->icount.overrun++;
-
-       pca_port = cortina_uart_get_port(port->line);
-
-       /* Read the character while FIFO is not empty */
-       do {
-               flg = TTY_NORMAL;
-               port->icount.rx++;
-               ch = readl(port->membase + RX_DAT);
-               if (status & RX_PARITY_ERRE) {
-                       port->icount.parity++;
-                       flg = TTY_PARITY;
-               }
-
-               if (pca_port->has_bi) {
-                       /* If BI supported ? */
-                       if (status & RX_BREAK) {
-                               port->icount.brk++;
-                               if (uart_handle_break(port))
-                                       goto ignore;
-                       }
-               } else {
-                       /* Treat stop err as BI */
-                       if (status & RX_STOP_ERRE) {
-                               port->icount.brk++;
-                               if (uart_handle_break(port))
-                                       goto ignore;
-                       }
-               }
-               if (!(ch & 0x100)) /* RX char is not valid */
-                       goto ignore;
-
-               if (uart_handle_sysrq_char(port, (unsigned char)ch))
-                       goto ignore;
-
-               tty_insert_flip_char(ttyport, ch, flg);
- ignore:
-               rx = readl(port->membase + INFO);
-       } while (!(INFO_RX_EMPTY & rx));
-
-       spin_unlock(&port->lock);
-       tty_flip_buffer_push(ttyport);
-       spin_lock(&port->lock);
-}
-
-static inline void cortina_uart_interrupt_tx_chars(struct uart_port *port)
-{
-       struct circ_buf *xmit = &port->state->xmit;
-
-       /* Process out of band chars */
-       if (port->x_char) {
-               /* Send next char */
-               writel(port->x_char, port->membase + TX_DAT);
-               goto done;
-       }
-
-       /* Nothing to do ? */
-       if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
-               cortina_uart_stop_tx(port);
-               goto done;
-       }
-
-       cortina_transmit_buffer(port);
-
-       /* Wake up */
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(port);
-
-       /* Maybe we're done after all */
-       if (uart_circ_empty(xmit))
-               cortina_uart_stop_tx(port);
-
- done:
-       return;
-}
-
-irqreturn_t cortina_uart_interrupt(int irq, void *dev_id)
-{
-       struct uart_port *port = (struct uart_port *)dev_id;
-       unsigned int irq_status;
-
-       spin_lock(&port->lock);
-
-       /* Clear interrupt! */
-       irq_status = readl(port->membase + INT);
-       writel(irq_status, port->membase + INT);
-
-       /* Process any Rx chars first */
-       cortina_uart_interrupt_rx_chars(port, irq_status);
-       /* Then use any Tx space */
-       cortina_uart_interrupt_tx_chars(port);
-
-       spin_unlock(&port->lock);
-
-       return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_SERIAL_CORTINA_ACCESS_CONSOLE
-void cortina_console_write(struct console *co, const char *s,
-                          unsigned int count)
-{
-       struct uart_port *port;
-       struct cortina_uart_port *pca_port;
-       unsigned int i, previous;
-       unsigned long flags;
-       int locked;
-
-       pca_port = cortina_uart_get_port(co->index);
-       port = &pca_port->uart;
-
-       local_irq_save(flags);
-       if (port->sysrq) {
-               locked = 0;
-       } else if (oops_in_progress) {
-               locked = spin_trylock(&port->lock);
-       } else {
-               spin_lock(&port->lock);
-               locked = 1;
-       }
-
-       /* Save current state */
-       previous = readl(port->membase + IE);
-       /* Disable Tx interrupts so this all goes out in one go */
-       cortina_uart_stop_tx(port);
-
-       /* Write all the chars */
-       for (i = 0; i < count; i++) {
-               /* Wait the TX buffer to be empty, which can't take forever */
-               while (!(readl(port->membase + INFO) & INFO_TX_EMPTY))
-                       cpu_relax();
-
-               /* Send the char */
-               writel(*s, port->membase + TX_DAT);
-
-               /* CR/LF stuff */
-               if (*s++ == '\n') {
-                       /* Wait the TX buffer to be empty */
-                       while (!(readl(port->membase + INFO) & INFO_TX_EMPTY))
-                               cpu_relax();
-                       writel('\r', port->membase + TX_DAT);
-               }
-       }
-
-       writel(previous, port->membase + IE);   /* Put it all back */
-
-       if (locked)
-               spin_unlock(&port->lock);
-       local_irq_restore(flags);
-}
-
-static int __init cortina_console_setup(struct console *co, char *options)
-{
-       struct uart_port *port;
-       struct cortina_uart_port *pca_port;
-       int baud = 115200;
-       int bits = 8;
-       int parity = 'n';
-       int flow = 'n';
-
-       if (co->index < 0 || co->index >= UART_NR)
-               return -ENODEV;
-
-       pca_port = cortina_uart_get_port(co->index);
-       port = &pca_port->uart;
-
-       /* This isn't going to do much, but it might change the baud rate. */
-       if (options)
-               uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-       return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver cortina_uart_driver;
-
-static struct console cortina_console = {
-       .name = "ttyS",
-       .write = cortina_console_write,
-       .device = uart_console_device,
-       .setup = cortina_console_setup,
-       .flags = CON_PRINTBUFFER,
-       .index = -1,            /* Only possible option. */
-       .data = &cortina_uart_driver,
-};
-#define CORTINA_CONSOLE (&cortina_console)
-
-/* Support EARLYCON */
-static void cortina_putc(struct uart_port *port, int c)
-{
-       unsigned int tmout;
-
-       /* No jiffie at early boot stage!
-        * Wait up to 5ms for the character to be sent.
-        */
-       tmout = TX_TIMEOUT;
-       while (--tmout) {
-               if (!(readl(port->membase + INFO) & INFO_TX_FULL))
-                       break;
-               udelay(1);
-       }
-
-       /* Give up if FIFO stuck! */
-       while ((readl(port->membase + INFO) & INFO_TX_FULL))
-               return;
-
-       /* Send the char */
-       writel(c, port->membase + TX_DAT);
-}
-
-static void cortina_early_write(struct console *con, const char *s,
-                               unsigned int n)
-{
-       struct earlycon_device *dev = con->data;
-
-       uart_console_write(&dev->port, s, n, cortina_putc);
-}
-
-static int __init cortina_early_console_setup(struct earlycon_device *device,
-                                             const char *opt)
-{
-       if (!device->port.membase)
-               return -ENODEV;
-
-       device->con->write = cortina_early_write;
-       return 0;
-}
-
-EARLYCON_DECLARE(serial, cortina_early_console_setup);
-OF_EARLYCON_DECLARE(serial, "cortina-access,serial", cortina_early_console_setup);
-#else
-#define CORTINA_CONSOLE        NULL
-#endif
-
-static struct uart_driver cortina_uart_driver = {
-       .owner = THIS_MODULE,
-       .driver_name = "cortina-access_uart",
-       .dev_name = "ttyS",
-       .major = TTY_MAJOR,
-       .minor = 64,
-       .nr = UART_NR,
-       .cons = CORTINA_CONSOLE,
-};
-
-/* Match table for of_platform binding */
-static const struct of_device_id cortina_uart_of_match[] = {
-       {.compatible = "cortina-access,serial",},
-       {}
-};
-MODULE_DEVICE_TABLE(of, cortina_uart_of_match);
-
-static int serial_cortina_probe(struct platform_device *pdev)
-{
-       int ret;
-       void __iomem *base;
-       struct cortina_uart_port *port;
-       const struct of_device_id *match;
-
-       /* assign DT node pointer */
-       struct device_node *np = pdev->dev.of_node;
-       struct resource mem_resource;
-       u32 of_clock_frequency;
-       struct clk *pclk_info;
-       int uart_idx;
-
-       /* search DT for a match */
-       match = of_match_device(cortina_uart_of_match, &pdev->dev);
-       if (!match)
-               return -EINVAL;
-
-       if (cortina_uart_ports == NULL)
-               cortina_uart_ports = kzalloc(UART_NR * sizeof(struct cortina_uart_port),
-                                            GFP_KERNEL);
-
-       port = cortina_uart_ports;
-       for (uart_idx = 0; uart_idx < UART_NR; ++uart_idx) {
-               /* Find first empty slot */
-               if (strlen(port->name) == 0)
-                       break;
-               port++;
-       }
-
-       if (uart_idx >= UART_NR)
-               return -EINVAL;
-
-       snprintf(port->name, sizeof(port->name), "Cortina-Access UART%d", uart_idx);
-
-       /* Retrieve HW base address */
-       ret = of_address_to_resource(np, 0, &mem_resource);
-       if (ret) {
-               dev_warn(&pdev->dev, "invalid address %d\n", ret);
-               return ret;
-       }
-
-       base = devm_ioremap(&pdev->dev, mem_resource.start,
-                           resource_size(&mem_resource));
-       if (!base) {
-               devm_kfree(&pdev->dev, port);
-               return -ENOMEM;
-       }
-
-       /* assign reg base and irq from DT */
-       port->uart.irq = irq_of_parse_and_map(np, 0);
-       port->uart.membase = base;
-       port->uart.mapbase = mem_resource.start;
-       port->uart.ops = &cortina_uart_ops;
-       port->uart.dev = &pdev->dev;
-       port->uart.line = uart_idx;
-       port->uart.has_sysrq = IS_ENABLED(CONFIG_SERIAL_CORTINA_ACCESS_CONSOLE);
-
-       /* get clock-freqency tuple from DT and store value */
-       if (of_property_read_u32(np, "clock-frequency", &of_clock_frequency)) {
-               /* If we are here, it means DT node did not contain
-                * clock-frequency tuple. Therefore, instead try to get
-                * clk rate through the clk driver that DT has stated
-                * we are consuming.
-                */
-               pclk_info = clk_get(&pdev->dev, NULL);
-               if (IS_ERR(pclk_info)) {
-                       dev_warn(&pdev->dev,
-                                "clk or clock-frequency not defined\n");
-                       return PTR_ERR(pclk_info);
-               }
-
-               clk_prepare_enable(pclk_info);
-               of_clock_frequency = clk_get_rate(pclk_info);
-       }
-       port->uart.uartclk = of_clock_frequency;
-
-       if (of_property_read_bool(np, "wakeup-source"))
-               port->may_wakeup = true;
-       if (of_property_read_bool(np, "break-indicator"))
-               port->has_bi = true;
-
-       port->uart.type = PORT_UNKNOWN;
-
-       if (port->may_wakeup)
-               device_init_wakeup(&pdev->dev, true);
-
-       ret = uart_add_one_port(&cortina_uart_driver, &port->uart);
-       if (ret)
-               return ret;
-
-       platform_set_drvdata(pdev, port);
-
-       return 0;
-}
-
-static int serial_cortina_remove(struct platform_device *pdev)
-{
-       struct uart_port *port = platform_get_drvdata(pdev);
-       struct cortina_uart_port *pca_port;
-
-       if (port) {
-               pca_port = cortina_uart_get_port(port->line);
-               memset(pca_port->name, 0, CA_UART_NAME_LEN);
-               uart_remove_one_port(&cortina_uart_driver, port);
-       }
-
-       platform_set_drvdata(pdev, NULL);
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int serial_cortina_suspend(struct platform_device *pdev,
-                                 pm_message_t state)
-{
-       struct cortina_uart_port *p =
-           (struct cortina_uart_port *)pdev->dev.driver_data;
-
-       uart_suspend_port(&cortina_uart_driver, &p->uart);
-
-       return 0;
-}
-
-static int serial_cortina_resume(struct platform_device *pdev)
-{
-       struct cortina_uart_port *p =
-           (struct cortina_uart_port *)pdev->dev.driver_data;
-
-       uart_resume_port(&cortina_uart_driver, &p->uart);
-
-       return 0;
-}
-#else
-#define serial_cortina_suspend NULL
-#define serial_cortina_resume NULL
-#endif
-
-static struct platform_driver serial_cortina_driver = {
-       .probe = serial_cortina_probe,
-       .remove = serial_cortina_remove,
-#ifdef CONFIG_PM
-       .suspend = serial_cortina_suspend,
-       .resume = serial_cortina_resume,
-#endif
-       .driver = {
-                  .name = "cortina-access_serial",
-                  .owner = THIS_MODULE,
-                  .of_match_table = cortina_uart_of_match,
-       },
-};
-
-static int __init cortina_uart_init(void)
-{
-       int ret;
-
-       ret = uart_register_driver(&cortina_uart_driver);
-       if (ret)
-               return ret;
-
-       ret = platform_driver_register(&serial_cortina_driver);
-       if (ret)
-               uart_unregister_driver(&cortina_uart_driver);
-
-       return ret;
-}
-
-static void __exit cortina_uart_exit(void)
-{
-       platform_driver_unregister(&serial_cortina_driver);
-       uart_unregister_driver(&cortina_uart_driver);
-}
-
-module_init(cortina_uart_init);
-module_exit(cortina_uart_exit);
-
-MODULE_AUTHOR("Cortina-Access Inc.");
-MODULE_DESCRIPTION(" Cortina-Access UART driver");
-MODULE_LICENSE("GPL");