linux/drivers/tty/serial/meson_uart.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *  Based on meson_uart.c, by AMLOGIC, INC.
   4 *
   5 * Copyright (C) 2014 Carlo Caione <carlo@caione.org>
   6 */
   7
   8#if defined(CONFIG_SERIAL_MESON_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
   9#define SUPPORT_SYSRQ
  10#endif
  11
  12#include <linux/clk.h>
  13#include <linux/console.h>
  14#include <linux/delay.h>
  15#include <linux/init.h>
  16#include <linux/io.h>
  17#include <linux/module.h>
  18#include <linux/kernel.h>
  19#include <linux/of.h>
  20#include <linux/platform_device.h>
  21#include <linux/serial.h>
  22#include <linux/serial_core.h>
  23#include <linux/tty.h>
  24#include <linux/tty_flip.h>
  25
  26/* Register offsets */
  27#define AML_UART_WFIFO                  0x00
  28#define AML_UART_RFIFO                  0x04
  29#define AML_UART_CONTROL                0x08
  30#define AML_UART_STATUS                 0x0c
  31#define AML_UART_MISC                   0x10
  32#define AML_UART_REG5                   0x14
  33
  34/* AML_UART_CONTROL bits */
  35#define AML_UART_TX_EN                  BIT(12)
  36#define AML_UART_RX_EN                  BIT(13)
  37#define AML_UART_TWO_WIRE_EN            BIT(15)
  38#define AML_UART_STOP_BIT_LEN_MASK      (0x03 << 16)
  39#define AML_UART_STOP_BIT_1SB           (0x00 << 16)
  40#define AML_UART_STOP_BIT_2SB           (0x01 << 16)
  41#define AML_UART_PARITY_TYPE            BIT(18)
  42#define AML_UART_PARITY_EN              BIT(19)
  43#define AML_UART_TX_RST                 BIT(22)
  44#define AML_UART_RX_RST                 BIT(23)
  45#define AML_UART_CLEAR_ERR              BIT(24)
  46#define AML_UART_RX_INT_EN              BIT(27)
  47#define AML_UART_TX_INT_EN              BIT(28)
  48#define AML_UART_DATA_LEN_MASK          (0x03 << 20)
  49#define AML_UART_DATA_LEN_8BIT          (0x00 << 20)
  50#define AML_UART_DATA_LEN_7BIT          (0x01 << 20)
  51#define AML_UART_DATA_LEN_6BIT          (0x02 << 20)
  52#define AML_UART_DATA_LEN_5BIT          (0x03 << 20)
  53
  54/* AML_UART_STATUS bits */
  55#define AML_UART_PARITY_ERR             BIT(16)
  56#define AML_UART_FRAME_ERR              BIT(17)
  57#define AML_UART_TX_FIFO_WERR           BIT(18)
  58#define AML_UART_RX_EMPTY               BIT(20)
  59#define AML_UART_TX_FULL                BIT(21)
  60#define AML_UART_TX_EMPTY               BIT(22)
  61#define AML_UART_XMIT_BUSY              BIT(25)
  62#define AML_UART_ERR                    (AML_UART_PARITY_ERR | \
  63                                         AML_UART_FRAME_ERR  | \
  64                                         AML_UART_TX_FIFO_WERR)
  65
  66/* AML_UART_MISC bits */
  67#define AML_UART_XMIT_IRQ(c)            (((c) & 0xff) << 8)
  68#define AML_UART_RECV_IRQ(c)            ((c) & 0xff)
  69
  70/* AML_UART_REG5 bits */
  71#define AML_UART_BAUD_MASK              0x7fffff
  72#define AML_UART_BAUD_USE               BIT(23)
  73#define AML_UART_BAUD_XTAL              BIT(24)
  74
  75#define AML_UART_PORT_NUM               12
  76#define AML_UART_PORT_OFFSET            6
  77#define AML_UART_DEV_NAME               "ttyAML"
  78
  79
  80static struct uart_driver meson_uart_driver;
  81
  82static struct uart_port *meson_ports[AML_UART_PORT_NUM];
  83
  84static void meson_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
  85{
  86}
  87
  88static unsigned int meson_uart_get_mctrl(struct uart_port *port)
  89{
  90        return TIOCM_CTS;
  91}
  92
  93static unsigned int meson_uart_tx_empty(struct uart_port *port)
  94{
  95        u32 val;
  96
  97        val = readl(port->membase + AML_UART_STATUS);
  98        val &= (AML_UART_TX_EMPTY | AML_UART_XMIT_BUSY);
  99        return (val == AML_UART_TX_EMPTY) ? TIOCSER_TEMT : 0;
 100}
 101
 102static void meson_uart_stop_tx(struct uart_port *port)
 103{
 104        u32 val;
 105
 106        val = readl(port->membase + AML_UART_CONTROL);
 107        val &= ~AML_UART_TX_INT_EN;
 108        writel(val, port->membase + AML_UART_CONTROL);
 109}
 110
 111static void meson_uart_stop_rx(struct uart_port *port)
 112{
 113        u32 val;
 114
 115        val = readl(port->membase + AML_UART_CONTROL);
 116        val &= ~AML_UART_RX_EN;
 117        writel(val, port->membase + AML_UART_CONTROL);
 118}
 119
 120static void meson_uart_shutdown(struct uart_port *port)
 121{
 122        unsigned long flags;
 123        u32 val;
 124
 125        free_irq(port->irq, port);
 126
 127        spin_lock_irqsave(&port->lock, flags);
 128
 129        val = readl(port->membase + AML_UART_CONTROL);
 130        val &= ~AML_UART_RX_EN;
 131        val &= ~(AML_UART_RX_INT_EN | AML_UART_TX_INT_EN);
 132        writel(val, port->membase + AML_UART_CONTROL);
 133
 134        spin_unlock_irqrestore(&port->lock, flags);
 135}
 136
 137static void meson_uart_start_tx(struct uart_port *port)
 138{
 139        struct circ_buf *xmit = &port->state->xmit;
 140        unsigned int ch;
 141        u32 val;
 142
 143        if (uart_tx_stopped(port)) {
 144                meson_uart_stop_tx(port);
 145                return;
 146        }
 147
 148        while (!(readl(port->membase + AML_UART_STATUS) & AML_UART_TX_FULL)) {
 149                if (port->x_char) {
 150                        writel(port->x_char, port->membase + AML_UART_WFIFO);
 151                        port->icount.tx++;
 152                        port->x_char = 0;
 153                        continue;
 154                }
 155
 156                if (uart_circ_empty(xmit))
 157                        break;
 158
 159                ch = xmit->buf[xmit->tail];
 160                writel(ch, port->membase + AML_UART_WFIFO);
 161                xmit->tail = (xmit->tail+1) & (SERIAL_XMIT_SIZE - 1);
 162                port->icount.tx++;
 163        }
 164
 165        if (!uart_circ_empty(xmit)) {
 166                val = readl(port->membase + AML_UART_CONTROL);
 167                val |= AML_UART_TX_INT_EN;
 168                writel(val, port->membase + AML_UART_CONTROL);
 169        }
 170
 171        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 172                uart_write_wakeup(port);
 173}
 174
 175static void meson_receive_chars(struct uart_port *port)
 176{
 177        struct tty_port *tport = &port->state->port;
 178        char flag;
 179        u32 ostatus, status, ch, mode;
 180
 181        do {
 182                flag = TTY_NORMAL;
 183                port->icount.rx++;
 184                ostatus = status = readl(port->membase + AML_UART_STATUS);
 185
 186                if (status & AML_UART_ERR) {
 187                        if (status & AML_UART_TX_FIFO_WERR)
 188                                port->icount.overrun++;
 189                        else if (status & AML_UART_FRAME_ERR)
 190                                port->icount.frame++;
 191                        else if (status & AML_UART_PARITY_ERR)
 192                                port->icount.frame++;
 193
 194                        mode = readl(port->membase + AML_UART_CONTROL);
 195                        mode |= AML_UART_CLEAR_ERR;
 196                        writel(mode, port->membase + AML_UART_CONTROL);
 197
 198                        /* It doesn't clear to 0 automatically */
 199                        mode &= ~AML_UART_CLEAR_ERR;
 200                        writel(mode, port->membase + AML_UART_CONTROL);
 201
 202                        status &= port->read_status_mask;
 203                        if (status & AML_UART_FRAME_ERR)
 204                                flag = TTY_FRAME;
 205                        else if (status & AML_UART_PARITY_ERR)
 206                                flag = TTY_PARITY;
 207                }
 208
 209                ch = readl(port->membase + AML_UART_RFIFO);
 210                ch &= 0xff;
 211
 212                if ((ostatus & AML_UART_FRAME_ERR) && (ch == 0)) {
 213                        port->icount.brk++;
 214                        flag = TTY_BREAK;
 215                        if (uart_handle_break(port))
 216                                continue;
 217                }
 218
 219                if (uart_handle_sysrq_char(port, ch))
 220                        continue;
 221
 222                if ((status & port->ignore_status_mask) == 0)
 223                        tty_insert_flip_char(tport, ch, flag);
 224
 225                if (status & AML_UART_TX_FIFO_WERR)
 226                        tty_insert_flip_char(tport, 0, TTY_OVERRUN);
 227
 228        } while (!(readl(port->membase + AML_UART_STATUS) & AML_UART_RX_EMPTY));
 229
 230        spin_unlock(&port->lock);
 231        tty_flip_buffer_push(tport);
 232        spin_lock(&port->lock);
 233}
 234
 235static irqreturn_t meson_uart_interrupt(int irq, void *dev_id)
 236{
 237        struct uart_port *port = (struct uart_port *)dev_id;
 238
 239        spin_lock(&port->lock);
 240
 241        if (!(readl(port->membase + AML_UART_STATUS) & AML_UART_RX_EMPTY))
 242                meson_receive_chars(port);
 243
 244        if (!(readl(port->membase + AML_UART_STATUS) & AML_UART_TX_FULL)) {
 245                if (readl(port->membase + AML_UART_CONTROL) & AML_UART_TX_INT_EN)
 246                        meson_uart_start_tx(port);
 247        }
 248
 249        spin_unlock(&port->lock);
 250
 251        return IRQ_HANDLED;
 252}
 253
 254static const char *meson_uart_type(struct uart_port *port)
 255{
 256        return (port->type == PORT_MESON) ? "meson_uart" : NULL;
 257}
 258
 259static void meson_uart_reset(struct uart_port *port)
 260{
 261        u32 val;
 262
 263        val = readl(port->membase + AML_UART_CONTROL);
 264        val |= (AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLEAR_ERR);
 265        writel(val, port->membase + AML_UART_CONTROL);
 266
 267        val &= ~(AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLEAR_ERR);
 268        writel(val, port->membase + AML_UART_CONTROL);
 269}
 270
 271static int meson_uart_startup(struct uart_port *port)
 272{
 273        u32 val;
 274        int ret = 0;
 275
 276        val = readl(port->membase + AML_UART_CONTROL);
 277        val |= AML_UART_CLEAR_ERR;
 278        writel(val, port->membase + AML_UART_CONTROL);
 279        val &= ~AML_UART_CLEAR_ERR;
 280        writel(val, port->membase + AML_UART_CONTROL);
 281
 282        val |= (AML_UART_RX_EN | AML_UART_TX_EN);
 283        writel(val, port->membase + AML_UART_CONTROL);
 284
 285        val |= (AML_UART_RX_INT_EN | AML_UART_TX_INT_EN);
 286        writel(val, port->membase + AML_UART_CONTROL);
 287
 288        val = (AML_UART_RECV_IRQ(1) | AML_UART_XMIT_IRQ(port->fifosize / 2));
 289        writel(val, port->membase + AML_UART_MISC);
 290
 291        ret = request_irq(port->irq, meson_uart_interrupt, 0,
 292                          port->name, port);
 293
 294        return ret;
 295}
 296
 297static void meson_uart_change_speed(struct uart_port *port, unsigned long baud)
 298{
 299        u32 val;
 300
 301        while (!meson_uart_tx_empty(port))
 302                cpu_relax();
 303
 304        if (port->uartclk == 24000000) {
 305                val = ((port->uartclk / 3) / baud) - 1;
 306                val |= AML_UART_BAUD_XTAL;
 307        } else {
 308                val = ((port->uartclk * 10 / (baud * 4) + 5) / 10) - 1;
 309        }
 310        val |= AML_UART_BAUD_USE;
 311        writel(val, port->membase + AML_UART_REG5);
 312}
 313
 314static void meson_uart_set_termios(struct uart_port *port,
 315                                   struct ktermios *termios,
 316                                   struct ktermios *old)
 317{
 318        unsigned int cflags, iflags, baud;
 319        unsigned long flags;
 320        u32 val;
 321
 322        spin_lock_irqsave(&port->lock, flags);
 323
 324        cflags = termios->c_cflag;
 325        iflags = termios->c_iflag;
 326
 327        val = readl(port->membase + AML_UART_CONTROL);
 328
 329        val &= ~AML_UART_DATA_LEN_MASK;
 330        switch (cflags & CSIZE) {
 331        case CS8:
 332                val |= AML_UART_DATA_LEN_8BIT;
 333                break;
 334        case CS7:
 335                val |= AML_UART_DATA_LEN_7BIT;
 336                break;
 337        case CS6:
 338                val |= AML_UART_DATA_LEN_6BIT;
 339                break;
 340        case CS5:
 341                val |= AML_UART_DATA_LEN_5BIT;
 342                break;
 343        }
 344
 345        if (cflags & PARENB)
 346                val |= AML_UART_PARITY_EN;
 347        else
 348                val &= ~AML_UART_PARITY_EN;
 349
 350        if (cflags & PARODD)
 351                val |= AML_UART_PARITY_TYPE;
 352        else
 353                val &= ~AML_UART_PARITY_TYPE;
 354
 355        val &= ~AML_UART_STOP_BIT_LEN_MASK;
 356        if (cflags & CSTOPB)
 357                val |= AML_UART_STOP_BIT_2SB;
 358        else
 359                val |= AML_UART_STOP_BIT_1SB;
 360
 361        if (cflags & CRTSCTS)
 362                val &= ~AML_UART_TWO_WIRE_EN;
 363        else
 364                val |= AML_UART_TWO_WIRE_EN;
 365
 366        writel(val, port->membase + AML_UART_CONTROL);
 367
 368        baud = uart_get_baud_rate(port, termios, old, 50, 4000000);
 369        meson_uart_change_speed(port, baud);
 370
 371        port->read_status_mask = AML_UART_TX_FIFO_WERR;
 372        if (iflags & INPCK)
 373                port->read_status_mask |= AML_UART_PARITY_ERR |
 374                                          AML_UART_FRAME_ERR;
 375
 376        port->ignore_status_mask = 0;
 377        if (iflags & IGNPAR)
 378                port->ignore_status_mask |= AML_UART_PARITY_ERR |
 379                                            AML_UART_FRAME_ERR;
 380
 381        uart_update_timeout(port, termios->c_cflag, baud);
 382        spin_unlock_irqrestore(&port->lock, flags);
 383}
 384
 385static int meson_uart_verify_port(struct uart_port *port,
 386                                  struct serial_struct *ser)
 387{
 388        int ret = 0;
 389
 390        if (port->type != PORT_MESON)
 391                ret = -EINVAL;
 392        if (port->irq != ser->irq)
 393                ret = -EINVAL;
 394        if (ser->baud_base < 9600)
 395                ret = -EINVAL;
 396        return ret;
 397}
 398
 399static void meson_uart_release_port(struct uart_port *port)
 400{
 401        devm_iounmap(port->dev, port->membase);
 402        port->membase = NULL;
 403        devm_release_mem_region(port->dev, port->mapbase, port->mapsize);
 404}
 405
 406static int meson_uart_request_port(struct uart_port *port)
 407{
 408        if (!devm_request_mem_region(port->dev, port->mapbase, port->mapsize,
 409                                     dev_name(port->dev))) {
 410                dev_err(port->dev, "Memory region busy\n");
 411                return -EBUSY;
 412        }
 413
 414        port->membase = devm_ioremap_nocache(port->dev, port->mapbase,
 415                                             port->mapsize);
 416        if (!port->membase)
 417                return -ENOMEM;
 418
 419        return 0;
 420}
 421
 422static void meson_uart_config_port(struct uart_port *port, int flags)
 423{
 424        if (flags & UART_CONFIG_TYPE) {
 425                port->type = PORT_MESON;
 426                meson_uart_request_port(port);
 427        }
 428}
 429
 430static const struct uart_ops meson_uart_ops = {
 431        .set_mctrl      = meson_uart_set_mctrl,
 432        .get_mctrl      = meson_uart_get_mctrl,
 433        .tx_empty       = meson_uart_tx_empty,
 434        .start_tx       = meson_uart_start_tx,
 435        .stop_tx        = meson_uart_stop_tx,
 436        .stop_rx        = meson_uart_stop_rx,
 437        .startup        = meson_uart_startup,
 438        .shutdown       = meson_uart_shutdown,
 439        .set_termios    = meson_uart_set_termios,
 440        .type           = meson_uart_type,
 441        .config_port    = meson_uart_config_port,
 442        .request_port   = meson_uart_request_port,
 443        .release_port   = meson_uart_release_port,
 444        .verify_port    = meson_uart_verify_port,
 445};
 446
 447#ifdef CONFIG_SERIAL_MESON_CONSOLE
 448static void meson_uart_enable_tx_engine(struct uart_port *port)
 449{
 450        u32 val;
 451
 452        val = readl(port->membase + AML_UART_CONTROL);
 453        val |= AML_UART_TX_EN;
 454        writel(val, port->membase + AML_UART_CONTROL);
 455}
 456
 457static void meson_console_putchar(struct uart_port *port, int ch)
 458{
 459        if (!port->membase)
 460                return;
 461
 462        while (readl(port->membase + AML_UART_STATUS) & AML_UART_TX_FULL)
 463                cpu_relax();
 464        writel(ch, port->membase + AML_UART_WFIFO);
 465}
 466
 467static void meson_serial_port_write(struct uart_port *port, const char *s,
 468                                    u_int count)
 469{
 470        unsigned long flags;
 471        int locked;
 472        u32 val, tmp;
 473
 474        local_irq_save(flags);
 475        if (port->sysrq) {
 476                locked = 0;
 477        } else if (oops_in_progress) {
 478                locked = spin_trylock(&port->lock);
 479        } else {
 480                spin_lock(&port->lock);
 481                locked = 1;
 482        }
 483
 484        val = readl(port->membase + AML_UART_CONTROL);
 485        tmp = val & ~(AML_UART_TX_INT_EN | AML_UART_RX_INT_EN);
 486        writel(tmp, port->membase + AML_UART_CONTROL);
 487
 488        uart_console_write(port, s, count, meson_console_putchar);
 489        writel(val, port->membase + AML_UART_CONTROL);
 490
 491        if (locked)
 492                spin_unlock(&port->lock);
 493        local_irq_restore(flags);
 494}
 495
 496static void meson_serial_console_write(struct console *co, const char *s,
 497                                       u_int count)
 498{
 499        struct uart_port *port;
 500
 501        port = meson_ports[co->index];
 502        if (!port)
 503                return;
 504
 505        meson_serial_port_write(port, s, count);
 506}
 507
 508static int meson_serial_console_setup(struct console *co, char *options)
 509{
 510        struct uart_port *port;
 511        int baud = 115200;
 512        int bits = 8;
 513        int parity = 'n';
 514        int flow = 'n';
 515
 516        if (co->index < 0 || co->index >= AML_UART_PORT_NUM)
 517                return -EINVAL;
 518
 519        port = meson_ports[co->index];
 520        if (!port || !port->membase)
 521                return -ENODEV;
 522
 523        meson_uart_enable_tx_engine(port);
 524
 525        if (options)
 526                uart_parse_options(options, &baud, &parity, &bits, &flow);
 527
 528        return uart_set_options(port, co, baud, parity, bits, flow);
 529}
 530
 531static struct console meson_serial_console = {
 532        .name           = AML_UART_DEV_NAME,
 533        .write          = meson_serial_console_write,
 534        .device         = uart_console_device,
 535        .setup          = meson_serial_console_setup,
 536        .flags          = CON_PRINTBUFFER,
 537        .index          = -1,
 538        .data           = &meson_uart_driver,
 539};
 540
 541static int __init meson_serial_console_init(void)
 542{
 543        register_console(&meson_serial_console);
 544        return 0;
 545}
 546console_initcall(meson_serial_console_init);
 547
 548static void meson_serial_early_console_write(struct console *co,
 549                                             const char *s,
 550                                             u_int count)
 551{
 552        struct earlycon_device *dev = co->data;
 553
 554        meson_serial_port_write(&dev->port, s, count);
 555}
 556
 557static int __init
 558meson_serial_early_console_setup(struct earlycon_device *device, const char *opt)
 559{
 560        if (!device->port.membase)
 561                return -ENODEV;
 562
 563        meson_uart_enable_tx_engine(&device->port);
 564        device->con->write = meson_serial_early_console_write;
 565        return 0;
 566}
 567/* Legacy bindings, should be removed when no more used */
 568OF_EARLYCON_DECLARE(meson, "amlogic,meson-uart",
 569                    meson_serial_early_console_setup);
 570/* Stable bindings */
 571OF_EARLYCON_DECLARE(meson, "amlogic,meson-ao-uart",
 572                    meson_serial_early_console_setup);
 573
 574#define MESON_SERIAL_CONSOLE    (&meson_serial_console)
 575#else
 576#define MESON_SERIAL_CONSOLE    NULL
 577#endif
 578
 579static struct uart_driver meson_uart_driver = {
 580        .owner          = THIS_MODULE,
 581        .driver_name    = "meson_uart",
 582        .dev_name       = AML_UART_DEV_NAME,
 583        .nr             = AML_UART_PORT_NUM,
 584        .cons           = MESON_SERIAL_CONSOLE,
 585};
 586
 587static inline struct clk *meson_uart_probe_clock(struct device *dev,
 588                                                 const char *id)
 589{
 590        struct clk *clk = NULL;
 591        int ret;
 592
 593        clk = devm_clk_get(dev, id);
 594        if (IS_ERR(clk))
 595                return clk;
 596
 597        ret = clk_prepare_enable(clk);
 598        if (ret) {
 599                dev_err(dev, "couldn't enable clk\n");
 600                return ERR_PTR(ret);
 601        }
 602
 603        devm_add_action_or_reset(dev,
 604                        (void(*)(void *))clk_disable_unprepare,
 605                        clk);
 606
 607        return clk;
 608}
 609
 610/*
 611 * This function gets clocks in the legacy non-stable DT bindings.
 612 * This code will be remove once all the platforms switch to the
 613 * new DT bindings.
 614 */
 615static int meson_uart_probe_clocks_legacy(struct platform_device *pdev,
 616                                          struct uart_port *port)
 617{
 618        struct clk *clk = NULL;
 619
 620        clk = meson_uart_probe_clock(&pdev->dev, NULL);
 621        if (IS_ERR(clk))
 622                return PTR_ERR(clk);
 623
 624        port->uartclk = clk_get_rate(clk);
 625
 626        return 0;
 627}
 628
 629static int meson_uart_probe_clocks(struct platform_device *pdev,
 630                                   struct uart_port *port)
 631{
 632        struct clk *clk_xtal = NULL;
 633        struct clk *clk_pclk = NULL;
 634        struct clk *clk_baud = NULL;
 635
 636        clk_pclk = meson_uart_probe_clock(&pdev->dev, "pclk");
 637        if (IS_ERR(clk_pclk))
 638                return PTR_ERR(clk_pclk);
 639
 640        clk_xtal = meson_uart_probe_clock(&pdev->dev, "xtal");
 641        if (IS_ERR(clk_xtal))
 642                return PTR_ERR(clk_xtal);
 643
 644        clk_baud = meson_uart_probe_clock(&pdev->dev, "baud");
 645        if (IS_ERR(clk_baud))
 646                return PTR_ERR(clk_baud);
 647
 648        port->uartclk = clk_get_rate(clk_baud);
 649
 650        return 0;
 651}
 652
 653static int meson_uart_probe(struct platform_device *pdev)
 654{
 655        struct resource *res_mem, *res_irq;
 656        struct uart_port *port;
 657        int ret = 0;
 658        int id = -1;
 659
 660        if (pdev->dev.of_node)
 661                pdev->id = of_alias_get_id(pdev->dev.of_node, "serial");
 662
 663        if (pdev->id < 0) {
 664                for (id = AML_UART_PORT_OFFSET; id < AML_UART_PORT_NUM; id++) {
 665                        if (!meson_ports[id]) {
 666                                pdev->id = id;
 667                                break;
 668                        }
 669                }
 670        }
 671
 672        if (pdev->id < 0 || pdev->id >= AML_UART_PORT_NUM)
 673                return -EINVAL;
 674
 675        res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 676        if (!res_mem)
 677                return -ENODEV;
 678
 679        res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 680        if (!res_irq)
 681                return -ENODEV;
 682
 683        if (meson_ports[pdev->id]) {
 684                dev_err(&pdev->dev, "port %d already allocated\n", pdev->id);
 685                return -EBUSY;
 686        }
 687
 688        port = devm_kzalloc(&pdev->dev, sizeof(struct uart_port), GFP_KERNEL);
 689        if (!port)
 690                return -ENOMEM;
 691
 692        /* Use legacy way until all platforms switch to new bindings */
 693        if (of_device_is_compatible(pdev->dev.of_node, "amlogic,meson-uart"))
 694                ret = meson_uart_probe_clocks_legacy(pdev, port);
 695        else
 696                ret = meson_uart_probe_clocks(pdev, port);
 697
 698        if (ret)
 699                return ret;
 700
 701        port->iotype = UPIO_MEM;
 702        port->mapbase = res_mem->start;
 703        port->mapsize = resource_size(res_mem);
 704        port->irq = res_irq->start;
 705        port->flags = UPF_BOOT_AUTOCONF | UPF_LOW_LATENCY;
 706        port->dev = &pdev->dev;
 707        port->line = pdev->id;
 708        port->type = PORT_MESON;
 709        port->x_char = 0;
 710        port->ops = &meson_uart_ops;
 711        port->fifosize = 64;
 712
 713        meson_ports[pdev->id] = port;
 714        platform_set_drvdata(pdev, port);
 715
 716        /* reset port before registering (and possibly registering console) */
 717        if (meson_uart_request_port(port) >= 0) {
 718                meson_uart_reset(port);
 719                meson_uart_release_port(port);
 720        }
 721
 722        ret = uart_add_one_port(&meson_uart_driver, port);
 723        if (ret)
 724                meson_ports[pdev->id] = NULL;
 725
 726        return ret;
 727}
 728
 729static int meson_uart_remove(struct platform_device *pdev)
 730{
 731        struct uart_port *port;
 732
 733        port = platform_get_drvdata(pdev);
 734        uart_remove_one_port(&meson_uart_driver, port);
 735        meson_ports[pdev->id] = NULL;
 736
 737        return 0;
 738}
 739
 740static const struct of_device_id meson_uart_dt_match[] = {
 741        /* Legacy bindings, should be removed when no more used */
 742        { .compatible = "amlogic,meson-uart" },
 743        /* Stable bindings */
 744        { .compatible = "amlogic,meson6-uart" },
 745        { .compatible = "amlogic,meson8-uart" },
 746        { .compatible = "amlogic,meson8b-uart" },
 747        { .compatible = "amlogic,meson-gx-uart" },
 748        { /* sentinel */ },
 749};
 750MODULE_DEVICE_TABLE(of, meson_uart_dt_match);
 751
 752static  struct platform_driver meson_uart_platform_driver = {
 753        .probe          = meson_uart_probe,
 754        .remove         = meson_uart_remove,
 755        .driver         = {
 756                .name           = "meson_uart",
 757                .of_match_table = meson_uart_dt_match,
 758        },
 759};
 760
 761static int __init meson_uart_init(void)
 762{
 763        int ret;
 764
 765        ret = uart_register_driver(&meson_uart_driver);
 766        if (ret)
 767                return ret;
 768
 769        ret = platform_driver_register(&meson_uart_platform_driver);
 770        if (ret)
 771                uart_unregister_driver(&meson_uart_driver);
 772
 773        return ret;
 774}
 775
 776static void __exit meson_uart_exit(void)
 777{
 778        platform_driver_unregister(&meson_uart_platform_driver);
 779        uart_unregister_driver(&meson_uart_driver);
 780}
 781
 782module_init(meson_uart_init);
 783module_exit(meson_uart_exit);
 784
 785MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
 786MODULE_DESCRIPTION("Amlogic Meson serial port driver");
 787MODULE_LICENSE("GPL v2");
 788