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        spin_unlock(&port->lock);
 230        tty_flip_buffer_push(tport);
 231        spin_lock(&port->lock);
 232}
 233
 234static irqreturn_t meson_uart_interrupt(int irq, void *dev_id)
 235{
 236        struct uart_port *port = (struct uart_port *)dev_id;
 237
 238        spin_lock(&port->lock);
 239
 240        if (!(readl(port->membase + AML_UART_STATUS) & AML_UART_RX_EMPTY))
 241                meson_receive_chars(port);
 242
 243        if (!(readl(port->membase + AML_UART_STATUS) & AML_UART_TX_FULL)) {
 244                if (readl(port->membase + AML_UART_CONTROL) & AML_UART_TX_INT_EN)
 245                        meson_uart_start_tx(port);
 246        }
 247
 248        spin_unlock(&port->lock);
 249
 250        return IRQ_HANDLED;
 251}
 252
 253static const char *meson_uart_type(struct uart_port *port)
 254{
 255        return (port->type == PORT_MESON) ? "meson_uart" : NULL;
 256}
 257
 258static void meson_uart_reset(struct uart_port *port)
 259{
 260        u32 val;
 261
 262        val = readl(port->membase + AML_UART_CONTROL);
 263        val |= (AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLEAR_ERR);
 264        writel(val, port->membase + AML_UART_CONTROL);
 265
 266        val &= ~(AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLEAR_ERR);
 267        writel(val, port->membase + AML_UART_CONTROL);
 268}
 269
 270static int meson_uart_startup(struct uart_port *port)
 271{
 272        u32 val;
 273        int ret = 0;
 274
 275        val = readl(port->membase + AML_UART_CONTROL);
 276        val |= AML_UART_CLEAR_ERR;
 277        writel(val, port->membase + AML_UART_CONTROL);
 278        val &= ~AML_UART_CLEAR_ERR;
 279        writel(val, port->membase + AML_UART_CONTROL);
 280
 281        val |= (AML_UART_RX_EN | AML_UART_TX_EN);
 282        writel(val, port->membase + AML_UART_CONTROL);
 283
 284        val |= (AML_UART_RX_INT_EN | AML_UART_TX_INT_EN);
 285        writel(val, port->membase + AML_UART_CONTROL);
 286
 287        val = (AML_UART_RECV_IRQ(1) | AML_UART_XMIT_IRQ(port->fifosize / 2));
 288        writel(val, port->membase + AML_UART_MISC);
 289
 290        ret = request_irq(port->irq, meson_uart_interrupt, 0,
 291                          port->name, port);
 292
 293        return ret;
 294}
 295
 296static void meson_uart_change_speed(struct uart_port *port, unsigned long baud)
 297{
 298        u32 val;
 299
 300        while (!meson_uart_tx_empty(port))
 301                cpu_relax();
 302
 303        if (port->uartclk == 24000000) {
 304                val = ((port->uartclk / 3) / baud) - 1;
 305                val |= AML_UART_BAUD_XTAL;
 306        } else {
 307                val = ((port->uartclk * 10 / (baud * 4) + 5) / 10) - 1;
 308        }
 309        val |= AML_UART_BAUD_USE;
 310        writel(val, port->membase + AML_UART_REG5);
 311}
 312
 313static void meson_uart_set_termios(struct uart_port *port,
 314                                   struct ktermios *termios,
 315                                   struct ktermios *old)
 316{
 317        unsigned int cflags, iflags, baud;
 318        unsigned long flags;
 319        u32 val;
 320
 321        spin_lock_irqsave(&port->lock, flags);
 322
 323        cflags = termios->c_cflag;
 324        iflags = termios->c_iflag;
 325
 326        val = readl(port->membase + AML_UART_CONTROL);
 327
 328        val &= ~AML_UART_DATA_LEN_MASK;
 329        switch (cflags & CSIZE) {
 330        case CS8:
 331                val |= AML_UART_DATA_LEN_8BIT;
 332                break;
 333        case CS7:
 334                val |= AML_UART_DATA_LEN_7BIT;
 335                break;
 336        case CS6:
 337                val |= AML_UART_DATA_LEN_6BIT;
 338                break;
 339        case CS5:
 340                val |= AML_UART_DATA_LEN_5BIT;
 341                break;
 342        }
 343
 344        if (cflags & PARENB)
 345                val |= AML_UART_PARITY_EN;
 346        else
 347                val &= ~AML_UART_PARITY_EN;
 348
 349        if (cflags & PARODD)
 350                val |= AML_UART_PARITY_TYPE;
 351        else
 352                val &= ~AML_UART_PARITY_TYPE;
 353
 354        val &= ~AML_UART_STOP_BIT_LEN_MASK;
 355        if (cflags & CSTOPB)
 356                val |= AML_UART_STOP_BIT_2SB;
 357        else
 358                val |= AML_UART_STOP_BIT_1SB;
 359
 360        if (cflags & CRTSCTS)
 361                val &= ~AML_UART_TWO_WIRE_EN;
 362        else
 363                val |= AML_UART_TWO_WIRE_EN;
 364
 365        writel(val, port->membase + AML_UART_CONTROL);
 366
 367        baud = uart_get_baud_rate(port, termios, old, 50, 4000000);
 368        meson_uart_change_speed(port, baud);
 369
 370        port->read_status_mask = AML_UART_TX_FIFO_WERR;
 371        if (iflags & INPCK)
 372                port->read_status_mask |= AML_UART_PARITY_ERR |
 373                                          AML_UART_FRAME_ERR;
 374
 375        port->ignore_status_mask = 0;
 376        if (iflags & IGNPAR)
 377                port->ignore_status_mask |= AML_UART_PARITY_ERR |
 378                                            AML_UART_FRAME_ERR;
 379
 380        uart_update_timeout(port, termios->c_cflag, baud);
 381        spin_unlock_irqrestore(&port->lock, flags);
 382}
 383
 384static int meson_uart_verify_port(struct uart_port *port,
 385                                  struct serial_struct *ser)
 386{
 387        int ret = 0;
 388
 389        if (port->type != PORT_MESON)
 390                ret = -EINVAL;
 391        if (port->irq != ser->irq)
 392                ret = -EINVAL;
 393        if (ser->baud_base < 9600)
 394                ret = -EINVAL;
 395        return ret;
 396}
 397
 398static void meson_uart_release_port(struct uart_port *port)
 399{
 400        devm_iounmap(port->dev, port->membase);
 401        port->membase = NULL;
 402        devm_release_mem_region(port->dev, port->mapbase, port->mapsize);
 403}
 404
 405static int meson_uart_request_port(struct uart_port *port)
 406{
 407        if (!devm_request_mem_region(port->dev, port->mapbase, port->mapsize,
 408                                     dev_name(port->dev))) {
 409                dev_err(port->dev, "Memory region busy\n");
 410                return -EBUSY;
 411        }
 412
 413        port->membase = devm_ioremap(port->dev, port->mapbase,
 414                                             port->mapsize);
 415        if (!port->membase)
 416                return -ENOMEM;
 417
 418        return 0;
 419}
 420
 421static void meson_uart_config_port(struct uart_port *port, int flags)
 422{
 423        if (flags & UART_CONFIG_TYPE) {
 424                port->type = PORT_MESON;
 425                meson_uart_request_port(port);
 426        }
 427}
 428
 429#ifdef CONFIG_CONSOLE_POLL
 430/*
 431 * Console polling routines for writing and reading from the uart while
 432 * in an interrupt or debug context (i.e. kgdb).
 433 */
 434
 435static int meson_uart_poll_get_char(struct uart_port *port)
 436{
 437        u32 c;
 438        unsigned long flags;
 439
 440        spin_lock_irqsave(&port->lock, flags);
 441
 442        if (readl(port->membase + AML_UART_STATUS) & AML_UART_RX_EMPTY)
 443                c = NO_POLL_CHAR;
 444        else
 445                c = readl(port->membase + AML_UART_RFIFO);
 446
 447        spin_unlock_irqrestore(&port->lock, flags);
 448
 449        return c;
 450}
 451
 452static void meson_uart_poll_put_char(struct uart_port *port, unsigned char c)
 453{
 454        unsigned long flags;
 455        u32 reg;
 456        int ret;
 457
 458        spin_lock_irqsave(&port->lock, flags);
 459
 460        /* Wait until FIFO is empty or timeout */
 461        ret = readl_poll_timeout_atomic(port->membase + AML_UART_STATUS, reg,
 462                                        reg & AML_UART_TX_EMPTY,
 463                                        AML_UART_POLL_USEC,
 464                                        AML_UART_TIMEOUT_USEC);
 465        if (ret == -ETIMEDOUT) {
 466                dev_err(port->dev, "Timeout waiting for UART TX EMPTY\n");
 467                goto out;
 468        }
 469
 470        /* Write the character */
 471        writel(c, port->membase + AML_UART_WFIFO);
 472
 473        /* Wait until FIFO is empty or timeout */
 474        ret = readl_poll_timeout_atomic(port->membase + AML_UART_STATUS, reg,
 475                                        reg & AML_UART_TX_EMPTY,
 476                                        AML_UART_POLL_USEC,
 477                                        AML_UART_TIMEOUT_USEC);
 478        if (ret == -ETIMEDOUT)
 479                dev_err(port->dev, "Timeout waiting for UART TX EMPTY\n");
 480
 481out:
 482        spin_unlock_irqrestore(&port->lock, flags);
 483}
 484
 485#endif /* CONFIG_CONSOLE_POLL */
 486
 487static const struct uart_ops meson_uart_ops = {
 488        .set_mctrl      = meson_uart_set_mctrl,
 489        .get_mctrl      = meson_uart_get_mctrl,
 490        .tx_empty       = meson_uart_tx_empty,
 491        .start_tx       = meson_uart_start_tx,
 492        .stop_tx        = meson_uart_stop_tx,
 493        .stop_rx        = meson_uart_stop_rx,
 494        .startup        = meson_uart_startup,
 495        .shutdown       = meson_uart_shutdown,
 496        .set_termios    = meson_uart_set_termios,
 497        .type           = meson_uart_type,
 498        .config_port    = meson_uart_config_port,
 499        .request_port   = meson_uart_request_port,
 500        .release_port   = meson_uart_release_port,
 501        .verify_port    = meson_uart_verify_port,
 502#ifdef CONFIG_CONSOLE_POLL
 503        .poll_get_char  = meson_uart_poll_get_char,
 504        .poll_put_char  = meson_uart_poll_put_char,
 505#endif
 506};
 507
 508#ifdef CONFIG_SERIAL_MESON_CONSOLE
 509static void meson_uart_enable_tx_engine(struct uart_port *port)
 510{
 511        u32 val;
 512
 513        val = readl(port->membase + AML_UART_CONTROL);
 514        val |= AML_UART_TX_EN;
 515        writel(val, port->membase + AML_UART_CONTROL);
 516}
 517
 518static void meson_console_putchar(struct uart_port *port, int ch)
 519{
 520        if (!port->membase)
 521                return;
 522
 523        while (readl(port->membase + AML_UART_STATUS) & AML_UART_TX_FULL)
 524                cpu_relax();
 525        writel(ch, port->membase + AML_UART_WFIFO);
 526}
 527
 528static void meson_serial_port_write(struct uart_port *port, const char *s,
 529                                    u_int count)
 530{
 531        unsigned long flags;
 532        int locked;
 533        u32 val, tmp;
 534
 535        local_irq_save(flags);
 536        if (port->sysrq) {
 537                locked = 0;
 538        } else if (oops_in_progress) {
 539                locked = spin_trylock(&port->lock);
 540        } else {
 541                spin_lock(&port->lock);
 542                locked = 1;
 543        }
 544
 545        val = readl(port->membase + AML_UART_CONTROL);
 546        tmp = val & ~(AML_UART_TX_INT_EN | AML_UART_RX_INT_EN);
 547        writel(tmp, port->membase + AML_UART_CONTROL);
 548
 549        uart_console_write(port, s, count, meson_console_putchar);
 550        writel(val, port->membase + AML_UART_CONTROL);
 551
 552        if (locked)
 553                spin_unlock(&port->lock);
 554        local_irq_restore(flags);
 555}
 556
 557static void meson_serial_console_write(struct console *co, const char *s,
 558                                       u_int count)
 559{
 560        struct uart_port *port;
 561
 562        port = meson_ports[co->index];
 563        if (!port)
 564                return;
 565
 566        meson_serial_port_write(port, s, count);
 567}
 568
 569static int meson_serial_console_setup(struct console *co, char *options)
 570{
 571        struct uart_port *port;
 572        int baud = 115200;
 573        int bits = 8;
 574        int parity = 'n';
 575        int flow = 'n';
 576
 577        if (co->index < 0 || co->index >= AML_UART_PORT_NUM)
 578                return -EINVAL;
 579
 580        port = meson_ports[co->index];
 581        if (!port || !port->membase)
 582                return -ENODEV;
 583
 584        meson_uart_enable_tx_engine(port);
 585
 586        if (options)
 587                uart_parse_options(options, &baud, &parity, &bits, &flow);
 588
 589        return uart_set_options(port, co, baud, parity, bits, flow);
 590}
 591
 592static struct console meson_serial_console = {
 593        .name           = AML_UART_DEV_NAME,
 594        .write          = meson_serial_console_write,
 595        .device         = uart_console_device,
 596        .setup          = meson_serial_console_setup,
 597        .flags          = CON_PRINTBUFFER,
 598        .index          = -1,
 599        .data           = &meson_uart_driver,
 600};
 601
 602static int __init meson_serial_console_init(void)
 603{
 604        register_console(&meson_serial_console);
 605        return 0;
 606}
 607
 608static void meson_serial_early_console_write(struct console *co,
 609                                             const char *s,
 610                                             u_int count)
 611{
 612        struct earlycon_device *dev = co->data;
 613
 614        meson_serial_port_write(&dev->port, s, count);
 615}
 616
 617static int __init
 618meson_serial_early_console_setup(struct earlycon_device *device, const char *opt)
 619{
 620        if (!device->port.membase)
 621                return -ENODEV;
 622
 623        meson_uart_enable_tx_engine(&device->port);
 624        device->con->write = meson_serial_early_console_write;
 625        return 0;
 626}
 627/* Legacy bindings, should be removed when no more used */
 628OF_EARLYCON_DECLARE(meson, "amlogic,meson-uart",
 629                    meson_serial_early_console_setup);
 630/* Stable bindings */
 631OF_EARLYCON_DECLARE(meson, "amlogic,meson-ao-uart",
 632                    meson_serial_early_console_setup);
 633
 634#define MESON_SERIAL_CONSOLE    (&meson_serial_console)
 635#else
 636static int __init meson_serial_console_init(void) {
 637        return 0;
 638}
 639#define MESON_SERIAL_CONSOLE    NULL
 640#endif
 641
 642static struct uart_driver meson_uart_driver = {
 643        .owner          = THIS_MODULE,
 644        .driver_name    = "meson_uart",
 645        .dev_name       = AML_UART_DEV_NAME,
 646        .nr             = AML_UART_PORT_NUM,
 647        .cons           = MESON_SERIAL_CONSOLE,
 648};
 649
 650static inline struct clk *meson_uart_probe_clock(struct device *dev,
 651                                                 const char *id)
 652{
 653        struct clk *clk = NULL;
 654        int ret;
 655
 656        clk = devm_clk_get(dev, id);
 657        if (IS_ERR(clk))
 658                return clk;
 659
 660        ret = clk_prepare_enable(clk);
 661        if (ret) {
 662                dev_err(dev, "couldn't enable clk\n");
 663                return ERR_PTR(ret);
 664        }
 665
 666        devm_add_action_or_reset(dev,
 667                        (void(*)(void *))clk_disable_unprepare,
 668                        clk);
 669
 670        return clk;
 671}
 672
 673/*
 674 * This function gets clocks in the legacy non-stable DT bindings.
 675 * This code will be remove once all the platforms switch to the
 676 * new DT bindings.
 677 */
 678static int meson_uart_probe_clocks_legacy(struct platform_device *pdev,
 679                                          struct uart_port *port)
 680{
 681        struct clk *clk = NULL;
 682
 683        clk = meson_uart_probe_clock(&pdev->dev, NULL);
 684        if (IS_ERR(clk))
 685                return PTR_ERR(clk);
 686
 687        port->uartclk = clk_get_rate(clk);
 688
 689        return 0;
 690}
 691
 692static int meson_uart_probe_clocks(struct platform_device *pdev,
 693                                   struct uart_port *port)
 694{
 695        struct clk *clk_xtal = NULL;
 696        struct clk *clk_pclk = NULL;
 697        struct clk *clk_baud = NULL;
 698
 699        clk_pclk = meson_uart_probe_clock(&pdev->dev, "pclk");
 700        if (IS_ERR(clk_pclk))
 701                return PTR_ERR(clk_pclk);
 702
 703        clk_xtal = meson_uart_probe_clock(&pdev->dev, "xtal");
 704        if (IS_ERR(clk_xtal))
 705                return PTR_ERR(clk_xtal);
 706
 707        clk_baud = meson_uart_probe_clock(&pdev->dev, "baud");
 708        if (IS_ERR(clk_baud))
 709                return PTR_ERR(clk_baud);
 710
 711        port->uartclk = clk_get_rate(clk_baud);
 712
 713        return 0;
 714}
 715
 716static int meson_uart_probe(struct platform_device *pdev)
 717{
 718        struct resource *res_mem, *res_irq;
 719        struct uart_port *port;
 720        int ret = 0;
 721        int id = -1;
 722
 723        if (pdev->dev.of_node)
 724                pdev->id = of_alias_get_id(pdev->dev.of_node, "serial");
 725
 726        if (pdev->id < 0) {
 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        if (meson_ports[pdev->id]) {
 747                dev_err(&pdev->dev, "port %d already allocated\n", pdev->id);
 748                return -EBUSY;
 749        }
 750
 751        port = devm_kzalloc(&pdev->dev, sizeof(struct uart_port), GFP_KERNEL);
 752        if (!port)
 753                return -ENOMEM;
 754
 755        /* Use legacy way until all platforms switch to new bindings */
 756        if (of_device_is_compatible(pdev->dev.of_node, "amlogic,meson-uart"))
 757                ret = meson_uart_probe_clocks_legacy(pdev, port);
 758        else
 759                ret = meson_uart_probe_clocks(pdev, port);
 760
 761        if (ret)
 762                return ret;
 763
 764        port->iotype = UPIO_MEM;
 765        port->mapbase = res_mem->start;
 766        port->mapsize = resource_size(res_mem);
 767        port->irq = res_irq->start;
 768        port->flags = UPF_BOOT_AUTOCONF | UPF_LOW_LATENCY;
 769        port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MESON_CONSOLE);
 770        port->dev = &pdev->dev;
 771        port->line = pdev->id;
 772        port->type = PORT_MESON;
 773        port->x_char = 0;
 774        port->ops = &meson_uart_ops;
 775        port->fifosize = 64;
 776
 777        meson_ports[pdev->id] = port;
 778        platform_set_drvdata(pdev, port);
 779
 780        /* reset port before registering (and possibly registering console) */
 781        if (meson_uart_request_port(port) >= 0) {
 782                meson_uart_reset(port);
 783                meson_uart_release_port(port);
 784        }
 785
 786        ret = uart_add_one_port(&meson_uart_driver, port);
 787        if (ret)
 788                meson_ports[pdev->id] = NULL;
 789
 790        return ret;
 791}
 792
 793static int meson_uart_remove(struct platform_device *pdev)
 794{
 795        struct uart_port *port;
 796
 797        port = platform_get_drvdata(pdev);
 798        uart_remove_one_port(&meson_uart_driver, port);
 799        meson_ports[pdev->id] = NULL;
 800
 801        return 0;
 802}
 803
 804static const struct of_device_id meson_uart_dt_match[] = {
 805        /* Legacy bindings, should be removed when no more used */
 806        { .compatible = "amlogic,meson-uart" },
 807        /* Stable bindings */
 808        { .compatible = "amlogic,meson6-uart" },
 809        { .compatible = "amlogic,meson8-uart" },
 810        { .compatible = "amlogic,meson8b-uart" },
 811        { .compatible = "amlogic,meson-gx-uart" },
 812        { /* sentinel */ },
 813};
 814MODULE_DEVICE_TABLE(of, meson_uart_dt_match);
 815
 816static  struct platform_driver meson_uart_platform_driver = {
 817        .probe          = meson_uart_probe,
 818        .remove         = meson_uart_remove,
 819        .driver         = {
 820                .name           = "meson_uart",
 821                .of_match_table = meson_uart_dt_match,
 822        },
 823};
 824
 825static int __init meson_uart_init(void)
 826{
 827        int ret;
 828
 829        ret = meson_serial_console_init();
 830        if (ret)
 831                return ret;
 832        
 833        ret = uart_register_driver(&meson_uart_driver);
 834        if (ret)
 835                return ret;
 836
 837        ret = platform_driver_register(&meson_uart_platform_driver);
 838        if (ret)
 839                uart_unregister_driver(&meson_uart_driver);
 840
 841        return ret;
 842}
 843
 844static void __exit meson_uart_exit(void)
 845{
 846        platform_driver_unregister(&meson_uart_platform_driver);
 847        uart_unregister_driver(&meson_uart_driver);
 848}
 849
 850module_init(meson_uart_init);
 851module_exit(meson_uart_exit);
 852
 853MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
 854MODULE_DESCRIPTION("Amlogic Meson serial port driver");
 855MODULE_LICENSE("GPL v2");
 856