linux/drivers/tty/serial/8250/8250_dma.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * 8250_dma.c - DMA Engine API support for 8250.c
   4 *
   5 * Copyright (C) 2013 Intel Corporation
   6 */
   7#include <linux/tty.h>
   8#include <linux/tty_flip.h>
   9#include <linux/serial_reg.h>
  10#include <linux/dma-mapping.h>
  11
  12#include "8250.h"
  13
  14static void __dma_tx_complete(void *param)
  15{
  16        struct uart_8250_port   *p = param;
  17        struct uart_8250_dma    *dma = p->dma;
  18        struct circ_buf         *xmit = &p->port.state->xmit;
  19        unsigned long   flags;
  20        int             ret;
  21
  22        dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr,
  23                                UART_XMIT_SIZE, DMA_TO_DEVICE);
  24
  25        spin_lock_irqsave(&p->port.lock, flags);
  26
  27        dma->tx_running = 0;
  28
  29        xmit->tail += dma->tx_size;
  30        xmit->tail &= UART_XMIT_SIZE - 1;
  31        p->port.icount.tx += dma->tx_size;
  32
  33        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
  34                uart_write_wakeup(&p->port);
  35
  36        ret = serial8250_tx_dma(p);
  37        if (ret)
  38                serial8250_set_THRI(p);
  39
  40        spin_unlock_irqrestore(&p->port.lock, flags);
  41}
  42
  43static void __dma_rx_complete(void *param)
  44{
  45        struct uart_8250_port   *p = param;
  46        struct uart_8250_dma    *dma = p->dma;
  47        struct tty_port         *tty_port = &p->port.state->port;
  48        struct dma_tx_state     state;
  49        int                     count;
  50
  51        dma->rx_running = 0;
  52        dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
  53
  54        count = dma->rx_size - state.residue;
  55
  56        tty_insert_flip_string(tty_port, dma->rx_buf, count);
  57        p->port.icount.rx += count;
  58
  59        tty_flip_buffer_push(tty_port);
  60}
  61
  62int serial8250_tx_dma(struct uart_8250_port *p)
  63{
  64        struct uart_8250_dma            *dma = p->dma;
  65        struct circ_buf                 *xmit = &p->port.state->xmit;
  66        struct dma_async_tx_descriptor  *desc;
  67        int ret;
  68
  69        if (dma->tx_running)
  70                return 0;
  71
  72        if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) {
  73                /* We have been called from __dma_tx_complete() */
  74                serial8250_rpm_put_tx(p);
  75                return 0;
  76        }
  77
  78        dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
  79
  80        desc = dmaengine_prep_slave_single(dma->txchan,
  81                                           dma->tx_addr + xmit->tail,
  82                                           dma->tx_size, DMA_MEM_TO_DEV,
  83                                           DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
  84        if (!desc) {
  85                ret = -EBUSY;
  86                goto err;
  87        }
  88
  89        dma->tx_running = 1;
  90        desc->callback = __dma_tx_complete;
  91        desc->callback_param = p;
  92
  93        dma->tx_cookie = dmaengine_submit(desc);
  94
  95        dma_sync_single_for_device(dma->txchan->device->dev, dma->tx_addr,
  96                                   UART_XMIT_SIZE, DMA_TO_DEVICE);
  97
  98        dma_async_issue_pending(dma->txchan);
  99        if (dma->tx_err) {
 100                dma->tx_err = 0;
 101                serial8250_clear_THRI(p);
 102        }
 103        return 0;
 104err:
 105        dma->tx_err = 1;
 106        return ret;
 107}
 108
 109int serial8250_rx_dma(struct uart_8250_port *p)
 110{
 111        struct uart_8250_dma            *dma = p->dma;
 112        struct dma_async_tx_descriptor  *desc;
 113
 114        if (dma->rx_running)
 115                return 0;
 116
 117        desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
 118                                           dma->rx_size, DMA_DEV_TO_MEM,
 119                                           DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 120        if (!desc)
 121                return -EBUSY;
 122
 123        dma->rx_running = 1;
 124        desc->callback = __dma_rx_complete;
 125        desc->callback_param = p;
 126
 127        dma->rx_cookie = dmaengine_submit(desc);
 128
 129        dma_async_issue_pending(dma->rxchan);
 130
 131        return 0;
 132}
 133
 134void serial8250_rx_dma_flush(struct uart_8250_port *p)
 135{
 136        struct uart_8250_dma *dma = p->dma;
 137
 138        if (dma->rx_running) {
 139                dmaengine_pause(dma->rxchan);
 140                __dma_rx_complete(p);
 141                dmaengine_terminate_async(dma->rxchan);
 142        }
 143}
 144EXPORT_SYMBOL_GPL(serial8250_rx_dma_flush);
 145
 146int serial8250_request_dma(struct uart_8250_port *p)
 147{
 148        struct uart_8250_dma    *dma = p->dma;
 149        phys_addr_t rx_dma_addr = dma->rx_dma_addr ?
 150                                  dma->rx_dma_addr : p->port.mapbase;
 151        phys_addr_t tx_dma_addr = dma->tx_dma_addr ?
 152                                  dma->tx_dma_addr : p->port.mapbase;
 153        dma_cap_mask_t          mask;
 154        struct dma_slave_caps   caps;
 155        int                     ret;
 156
 157        /* Default slave configuration parameters */
 158        dma->rxconf.direction           = DMA_DEV_TO_MEM;
 159        dma->rxconf.src_addr_width      = DMA_SLAVE_BUSWIDTH_1_BYTE;
 160        dma->rxconf.src_addr            = rx_dma_addr + UART_RX;
 161
 162        dma->txconf.direction           = DMA_MEM_TO_DEV;
 163        dma->txconf.dst_addr_width      = DMA_SLAVE_BUSWIDTH_1_BYTE;
 164        dma->txconf.dst_addr            = tx_dma_addr + UART_TX;
 165
 166        dma_cap_zero(mask);
 167        dma_cap_set(DMA_SLAVE, mask);
 168
 169        /* Get a channel for RX */
 170        dma->rxchan = dma_request_slave_channel_compat(mask,
 171                                                       dma->fn, dma->rx_param,
 172                                                       p->port.dev, "rx");
 173        if (!dma->rxchan)
 174                return -ENODEV;
 175
 176        /* 8250 rx dma requires dmaengine driver to support pause/terminate */
 177        ret = dma_get_slave_caps(dma->rxchan, &caps);
 178        if (ret)
 179                goto release_rx;
 180        if (!caps.cmd_pause || !caps.cmd_terminate ||
 181            caps.residue_granularity == DMA_RESIDUE_GRANULARITY_DESCRIPTOR) {
 182                ret = -EINVAL;
 183                goto release_rx;
 184        }
 185
 186        dmaengine_slave_config(dma->rxchan, &dma->rxconf);
 187
 188        /* Get a channel for TX */
 189        dma->txchan = dma_request_slave_channel_compat(mask,
 190                                                       dma->fn, dma->tx_param,
 191                                                       p->port.dev, "tx");
 192        if (!dma->txchan) {
 193                ret = -ENODEV;
 194                goto release_rx;
 195        }
 196
 197        /* 8250 tx dma requires dmaengine driver to support terminate */
 198        ret = dma_get_slave_caps(dma->txchan, &caps);
 199        if (ret)
 200                goto err;
 201        if (!caps.cmd_terminate) {
 202                ret = -EINVAL;
 203                goto err;
 204        }
 205
 206        dmaengine_slave_config(dma->txchan, &dma->txconf);
 207
 208        /* RX buffer */
 209        if (!dma->rx_size)
 210                dma->rx_size = PAGE_SIZE;
 211
 212        dma->rx_buf = dma_alloc_coherent(dma->rxchan->device->dev, dma->rx_size,
 213                                        &dma->rx_addr, GFP_KERNEL);
 214        if (!dma->rx_buf) {
 215                ret = -ENOMEM;
 216                goto err;
 217        }
 218
 219        /* TX buffer */
 220        dma->tx_addr = dma_map_single(dma->txchan->device->dev,
 221                                        p->port.state->xmit.buf,
 222                                        UART_XMIT_SIZE,
 223                                        DMA_TO_DEVICE);
 224        if (dma_mapping_error(dma->txchan->device->dev, dma->tx_addr)) {
 225                dma_free_coherent(dma->rxchan->device->dev, dma->rx_size,
 226                                  dma->rx_buf, dma->rx_addr);
 227                ret = -ENOMEM;
 228                goto err;
 229        }
 230
 231        dev_dbg_ratelimited(p->port.dev, "got both dma channels\n");
 232
 233        return 0;
 234err:
 235        dma_release_channel(dma->txchan);
 236release_rx:
 237        dma_release_channel(dma->rxchan);
 238        return ret;
 239}
 240EXPORT_SYMBOL_GPL(serial8250_request_dma);
 241
 242void serial8250_release_dma(struct uart_8250_port *p)
 243{
 244        struct uart_8250_dma *dma = p->dma;
 245
 246        if (!dma)
 247                return;
 248
 249        /* Release RX resources */
 250        dmaengine_terminate_sync(dma->rxchan);
 251        dma_free_coherent(dma->rxchan->device->dev, dma->rx_size, dma->rx_buf,
 252                          dma->rx_addr);
 253        dma_release_channel(dma->rxchan);
 254        dma->rxchan = NULL;
 255
 256        /* Release TX resources */
 257        dmaengine_terminate_sync(dma->txchan);
 258        dma_unmap_single(dma->txchan->device->dev, dma->tx_addr,
 259                         UART_XMIT_SIZE, DMA_TO_DEVICE);
 260        dma_release_channel(dma->txchan);
 261        dma->txchan = NULL;
 262        dma->tx_running = 0;
 263
 264        dev_dbg_ratelimited(p->port.dev, "dma channels released\n");
 265}
 266EXPORT_SYMBOL_GPL(serial8250_release_dma);
 267