linux/drivers/tty/serial/timbuart.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * timbuart.c timberdale FPGA UART driver
   4 * Copyright (c) 2009 Intel Corporation
   5 */
   6
   7/* Supports:
   8 * Timberdale FPGA UART
   9 */
  10
  11#include <linux/pci.h>
  12#include <linux/interrupt.h>
  13#include <linux/serial_core.h>
  14#include <linux/tty.h>
  15#include <linux/tty_flip.h>
  16#include <linux/kernel.h>
  17#include <linux/platform_device.h>
  18#include <linux/ioport.h>
  19#include <linux/slab.h>
  20#include <linux/module.h>
  21
  22#include "timbuart.h"
  23
  24struct timbuart_port {
  25        struct uart_port        port;
  26        struct tasklet_struct   tasklet;
  27        int                     usedma;
  28        u32                     last_ier;
  29        struct platform_device  *dev;
  30};
  31
  32static int baudrates[] = {9600, 19200, 38400, 57600, 115200, 230400, 460800,
  33        921600, 1843200, 3250000};
  34
  35static void timbuart_mctrl_check(struct uart_port *port, u32 isr, u32 *ier);
  36
  37static irqreturn_t timbuart_handleinterrupt(int irq, void *devid);
  38
  39static void timbuart_stop_rx(struct uart_port *port)
  40{
  41        /* spin lock held by upper layer, disable all RX interrupts */
  42        u32 ier = ioread32(port->membase + TIMBUART_IER) & ~RXFLAGS;
  43        iowrite32(ier, port->membase + TIMBUART_IER);
  44}
  45
  46static void timbuart_stop_tx(struct uart_port *port)
  47{
  48        /* spinlock held by upper layer, disable TX interrupt */
  49        u32 ier = ioread32(port->membase + TIMBUART_IER) & ~TXBAE;
  50        iowrite32(ier, port->membase + TIMBUART_IER);
  51}
  52
  53static void timbuart_start_tx(struct uart_port *port)
  54{
  55        struct timbuart_port *uart =
  56                container_of(port, struct timbuart_port, port);
  57
  58        /* do not transfer anything here -> fire off the tasklet */
  59        tasklet_schedule(&uart->tasklet);
  60}
  61
  62static unsigned int timbuart_tx_empty(struct uart_port *port)
  63{
  64        u32 isr = ioread32(port->membase + TIMBUART_ISR);
  65
  66        return (isr & TXBE) ? TIOCSER_TEMT : 0;
  67}
  68
  69static void timbuart_flush_buffer(struct uart_port *port)
  70{
  71        if (!timbuart_tx_empty(port)) {
  72                u8 ctl = ioread8(port->membase + TIMBUART_CTRL) |
  73                        TIMBUART_CTRL_FLSHTX;
  74
  75                iowrite8(ctl, port->membase + TIMBUART_CTRL);
  76                iowrite32(TXBF, port->membase + TIMBUART_ISR);
  77        }
  78}
  79
  80static void timbuart_rx_chars(struct uart_port *port)
  81{
  82        struct tty_port *tport = &port->state->port;
  83
  84        while (ioread32(port->membase + TIMBUART_ISR) & RXDP) {
  85                u8 ch = ioread8(port->membase + TIMBUART_RXFIFO);
  86                port->icount.rx++;
  87                tty_insert_flip_char(tport, ch, TTY_NORMAL);
  88        }
  89
  90        spin_unlock(&port->lock);
  91        tty_flip_buffer_push(tport);
  92        spin_lock(&port->lock);
  93
  94        dev_dbg(port->dev, "%s - total read %d bytes\n",
  95                __func__, port->icount.rx);
  96}
  97
  98static void timbuart_tx_chars(struct uart_port *port)
  99{
 100        struct circ_buf *xmit = &port->state->xmit;
 101
 102        while (!(ioread32(port->membase + TIMBUART_ISR) & TXBF) &&
 103                !uart_circ_empty(xmit)) {
 104                iowrite8(xmit->buf[xmit->tail],
 105                        port->membase + TIMBUART_TXFIFO);
 106                xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 107                port->icount.tx++;
 108        }
 109
 110        dev_dbg(port->dev,
 111                "%s - total written %d bytes, CTL: %x, RTS: %x, baud: %x\n",
 112                 __func__,
 113                port->icount.tx,
 114                ioread8(port->membase + TIMBUART_CTRL),
 115                port->mctrl & TIOCM_RTS,
 116                ioread8(port->membase + TIMBUART_BAUDRATE));
 117}
 118
 119static void timbuart_handle_tx_port(struct uart_port *port, u32 isr, u32 *ier)
 120{
 121        struct timbuart_port *uart =
 122                container_of(port, struct timbuart_port, port);
 123        struct circ_buf *xmit = &port->state->xmit;
 124
 125        if (uart_circ_empty(xmit) || uart_tx_stopped(port))
 126                return;
 127
 128        if (port->x_char)
 129                return;
 130
 131        if (isr & TXFLAGS) {
 132                timbuart_tx_chars(port);
 133                /* clear all TX interrupts */
 134                iowrite32(TXFLAGS, port->membase + TIMBUART_ISR);
 135
 136                if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 137                        uart_write_wakeup(port);
 138        } else
 139                /* Re-enable any tx interrupt */
 140                *ier |= uart->last_ier & TXFLAGS;
 141
 142        /* enable interrupts if there are chars in the transmit buffer,
 143         * Or if we delivered some bytes and want the almost empty interrupt
 144         * we wake up the upper layer later when we got the interrupt
 145         * to give it some time to go out...
 146         */
 147        if (!uart_circ_empty(xmit))
 148                *ier |= TXBAE;
 149
 150        dev_dbg(port->dev, "%s - leaving\n", __func__);
 151}
 152
 153static void timbuart_handle_rx_port(struct uart_port *port, u32 isr, u32 *ier)
 154{
 155        if (isr & RXFLAGS) {
 156                /* Some RX status is set */
 157                if (isr & RXBF) {
 158                        u8 ctl = ioread8(port->membase + TIMBUART_CTRL) |
 159                                TIMBUART_CTRL_FLSHRX;
 160                        iowrite8(ctl, port->membase + TIMBUART_CTRL);
 161                        port->icount.overrun++;
 162                } else if (isr & (RXDP))
 163                        timbuart_rx_chars(port);
 164
 165                /* ack all RX interrupts */
 166                iowrite32(RXFLAGS, port->membase + TIMBUART_ISR);
 167        }
 168
 169        /* always have the RX interrupts enabled */
 170        *ier |= RXBAF | RXBF | RXTT;
 171
 172        dev_dbg(port->dev, "%s - leaving\n", __func__);
 173}
 174
 175static void timbuart_tasklet(unsigned long arg)
 176{
 177        struct timbuart_port *uart = (struct timbuart_port *)arg;
 178        u32 isr, ier = 0;
 179
 180        spin_lock(&uart->port.lock);
 181
 182        isr = ioread32(uart->port.membase + TIMBUART_ISR);
 183        dev_dbg(uart->port.dev, "%s ISR: %x\n", __func__, isr);
 184
 185        if (!uart->usedma)
 186                timbuart_handle_tx_port(&uart->port, isr, &ier);
 187
 188        timbuart_mctrl_check(&uart->port, isr, &ier);
 189
 190        if (!uart->usedma)
 191                timbuart_handle_rx_port(&uart->port, isr, &ier);
 192
 193        iowrite32(ier, uart->port.membase + TIMBUART_IER);
 194
 195        spin_unlock(&uart->port.lock);
 196        dev_dbg(uart->port.dev, "%s leaving\n", __func__);
 197}
 198
 199static unsigned int timbuart_get_mctrl(struct uart_port *port)
 200{
 201        u8 cts = ioread8(port->membase + TIMBUART_CTRL);
 202        dev_dbg(port->dev, "%s - cts %x\n", __func__, cts);
 203
 204        if (cts & TIMBUART_CTRL_CTS)
 205                return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
 206        else
 207                return TIOCM_DSR | TIOCM_CAR;
 208}
 209
 210static void timbuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
 211{
 212        dev_dbg(port->dev, "%s - %x\n", __func__, mctrl);
 213
 214        if (mctrl & TIOCM_RTS)
 215                iowrite8(TIMBUART_CTRL_RTS, port->membase + TIMBUART_CTRL);
 216        else
 217                iowrite8(0, port->membase + TIMBUART_CTRL);
 218}
 219
 220static void timbuart_mctrl_check(struct uart_port *port, u32 isr, u32 *ier)
 221{
 222        unsigned int cts;
 223
 224        if (isr & CTS_DELTA) {
 225                /* ack */
 226                iowrite32(CTS_DELTA, port->membase + TIMBUART_ISR);
 227                cts = timbuart_get_mctrl(port);
 228                uart_handle_cts_change(port, cts & TIOCM_CTS);
 229                wake_up_interruptible(&port->state->port.delta_msr_wait);
 230        }
 231
 232        *ier |= CTS_DELTA;
 233}
 234
 235static void timbuart_break_ctl(struct uart_port *port, int ctl)
 236{
 237        /* N/A */
 238}
 239
 240static int timbuart_startup(struct uart_port *port)
 241{
 242        struct timbuart_port *uart =
 243                container_of(port, struct timbuart_port, port);
 244
 245        dev_dbg(port->dev, "%s\n", __func__);
 246
 247        iowrite8(TIMBUART_CTRL_FLSHRX, port->membase + TIMBUART_CTRL);
 248        iowrite32(0x1ff, port->membase + TIMBUART_ISR);
 249        /* Enable all but TX interrupts */
 250        iowrite32(RXBAF | RXBF | RXTT | CTS_DELTA,
 251                port->membase + TIMBUART_IER);
 252
 253        return request_irq(port->irq, timbuart_handleinterrupt, IRQF_SHARED,
 254                "timb-uart", uart);
 255}
 256
 257static void timbuart_shutdown(struct uart_port *port)
 258{
 259        struct timbuart_port *uart =
 260                container_of(port, struct timbuart_port, port);
 261        dev_dbg(port->dev, "%s\n", __func__);
 262        free_irq(port->irq, uart);
 263        iowrite32(0, port->membase + TIMBUART_IER);
 264
 265        timbuart_flush_buffer(port);
 266}
 267
 268static int get_bindex(int baud)
 269{
 270        int i;
 271
 272        for (i = 0; i < ARRAY_SIZE(baudrates); i++)
 273                if (baud <= baudrates[i])
 274                        return i;
 275
 276        return -1;
 277}
 278
 279static void timbuart_set_termios(struct uart_port *port,
 280        struct ktermios *termios,
 281        struct ktermios *old)
 282{
 283        unsigned int baud;
 284        short bindex;
 285        unsigned long flags;
 286
 287        baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
 288        bindex = get_bindex(baud);
 289        dev_dbg(port->dev, "%s - bindex %d\n", __func__, bindex);
 290
 291        if (bindex < 0)
 292                bindex = 0;
 293        baud = baudrates[bindex];
 294
 295        /* The serial layer calls into this once with old = NULL when setting
 296           up initially */
 297        if (old)
 298                tty_termios_copy_hw(termios, old);
 299        tty_termios_encode_baud_rate(termios, baud, baud);
 300
 301        spin_lock_irqsave(&port->lock, flags);
 302        iowrite8((u8)bindex, port->membase + TIMBUART_BAUDRATE);
 303        uart_update_timeout(port, termios->c_cflag, baud);
 304        spin_unlock_irqrestore(&port->lock, flags);
 305}
 306
 307static const char *timbuart_type(struct uart_port *port)
 308{
 309        return port->type == PORT_UNKNOWN ? "timbuart" : NULL;
 310}
 311
 312/* We do not request/release mappings of the registers here,
 313 * currently it's done in the proble function.
 314 */
 315static void timbuart_release_port(struct uart_port *port)
 316{
 317        struct platform_device *pdev = to_platform_device(port->dev);
 318        int size =
 319                resource_size(platform_get_resource(pdev, IORESOURCE_MEM, 0));
 320
 321        if (port->flags & UPF_IOREMAP) {
 322                iounmap(port->membase);
 323                port->membase = NULL;
 324        }
 325
 326        release_mem_region(port->mapbase, size);
 327}
 328
 329static int timbuart_request_port(struct uart_port *port)
 330{
 331        struct platform_device *pdev = to_platform_device(port->dev);
 332        int size =
 333                resource_size(platform_get_resource(pdev, IORESOURCE_MEM, 0));
 334
 335        if (!request_mem_region(port->mapbase, size, "timb-uart"))
 336                return -EBUSY;
 337
 338        if (port->flags & UPF_IOREMAP) {
 339                port->membase = ioremap(port->mapbase, size);
 340                if (port->membase == NULL) {
 341                        release_mem_region(port->mapbase, size);
 342                        return -ENOMEM;
 343                }
 344        }
 345
 346        return 0;
 347}
 348
 349static irqreturn_t timbuart_handleinterrupt(int irq, void *devid)
 350{
 351        struct timbuart_port *uart = (struct timbuart_port *)devid;
 352
 353        if (ioread8(uart->port.membase + TIMBUART_IPR)) {
 354                uart->last_ier = ioread32(uart->port.membase + TIMBUART_IER);
 355
 356                /* disable interrupts, the tasklet enables them again */
 357                iowrite32(0, uart->port.membase + TIMBUART_IER);
 358
 359                /* fire off bottom half */
 360                tasklet_schedule(&uart->tasklet);
 361
 362                return IRQ_HANDLED;
 363        } else
 364                return IRQ_NONE;
 365}
 366
 367/*
 368 * Configure/autoconfigure the port.
 369 */
 370static void timbuart_config_port(struct uart_port *port, int flags)
 371{
 372        if (flags & UART_CONFIG_TYPE) {
 373                port->type = PORT_TIMBUART;
 374                timbuart_request_port(port);
 375        }
 376}
 377
 378static int timbuart_verify_port(struct uart_port *port,
 379        struct serial_struct *ser)
 380{
 381        /* we don't want the core code to modify any port params */
 382        return -EINVAL;
 383}
 384
 385static const struct uart_ops timbuart_ops = {
 386        .tx_empty = timbuart_tx_empty,
 387        .set_mctrl = timbuart_set_mctrl,
 388        .get_mctrl = timbuart_get_mctrl,
 389        .stop_tx = timbuart_stop_tx,
 390        .start_tx = timbuart_start_tx,
 391        .flush_buffer = timbuart_flush_buffer,
 392        .stop_rx = timbuart_stop_rx,
 393        .break_ctl = timbuart_break_ctl,
 394        .startup = timbuart_startup,
 395        .shutdown = timbuart_shutdown,
 396        .set_termios = timbuart_set_termios,
 397        .type = timbuart_type,
 398        .release_port = timbuart_release_port,
 399        .request_port = timbuart_request_port,
 400        .config_port = timbuart_config_port,
 401        .verify_port = timbuart_verify_port
 402};
 403
 404static struct uart_driver timbuart_driver = {
 405        .owner = THIS_MODULE,
 406        .driver_name = "timberdale_uart",
 407        .dev_name = "ttyTU",
 408        .major = TIMBUART_MAJOR,
 409        .minor = TIMBUART_MINOR,
 410        .nr = 1
 411};
 412
 413static int timbuart_probe(struct platform_device *dev)
 414{
 415        int err, irq;
 416        struct timbuart_port *uart;
 417        struct resource *iomem;
 418
 419        dev_dbg(&dev->dev, "%s\n", __func__);
 420
 421        uart = kzalloc(sizeof(*uart), GFP_KERNEL);
 422        if (!uart) {
 423                err = -EINVAL;
 424                goto err_mem;
 425        }
 426
 427        uart->usedma = 0;
 428
 429        uart->port.uartclk = 3250000 * 16;
 430        uart->port.fifosize  = TIMBUART_FIFO_SIZE;
 431        uart->port.regshift  = 2;
 432        uart->port.iotype  = UPIO_MEM;
 433        uart->port.ops = &timbuart_ops;
 434        uart->port.irq = 0;
 435        uart->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
 436        uart->port.line  = 0;
 437        uart->port.dev  = &dev->dev;
 438
 439        iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
 440        if (!iomem) {
 441                err = -ENOMEM;
 442                goto err_register;
 443        }
 444        uart->port.mapbase = iomem->start;
 445        uart->port.membase = NULL;
 446
 447        irq = platform_get_irq(dev, 0);
 448        if (irq < 0) {
 449                err = -EINVAL;
 450                goto err_register;
 451        }
 452        uart->port.irq = irq;
 453
 454        tasklet_init(&uart->tasklet, timbuart_tasklet, (unsigned long)uart);
 455
 456        err = uart_register_driver(&timbuart_driver);
 457        if (err)
 458                goto err_register;
 459
 460        err = uart_add_one_port(&timbuart_driver, &uart->port);
 461        if (err)
 462                goto err_add_port;
 463
 464        platform_set_drvdata(dev, uart);
 465
 466        return 0;
 467
 468err_add_port:
 469        uart_unregister_driver(&timbuart_driver);
 470err_register:
 471        kfree(uart);
 472err_mem:
 473        printk(KERN_ERR "timberdale: Failed to register Timberdale UART: %d\n",
 474                err);
 475
 476        return err;
 477}
 478
 479static int timbuart_remove(struct platform_device *dev)
 480{
 481        struct timbuart_port *uart = platform_get_drvdata(dev);
 482
 483        tasklet_kill(&uart->tasklet);
 484        uart_remove_one_port(&timbuart_driver, &uart->port);
 485        uart_unregister_driver(&timbuart_driver);
 486        kfree(uart);
 487
 488        return 0;
 489}
 490
 491static struct platform_driver timbuart_platform_driver = {
 492        .driver = {
 493                .name   = "timb-uart",
 494        },
 495        .probe          = timbuart_probe,
 496        .remove         = timbuart_remove,
 497};
 498
 499module_platform_driver(timbuart_platform_driver);
 500
 501MODULE_DESCRIPTION("Timberdale UART driver");
 502MODULE_LICENSE("GPL v2");
 503MODULE_ALIAS("platform:timb-uart");
 504
 505