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