The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/uart/uart_dev_mvebu.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2017 Semihalf.
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25 */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include <sys/param.h>
   31 #include <sys/bus.h>
   32 #include <sys/conf.h>
   33 #include <sys/kernel.h>
   34 #include <sys/sysctl.h>
   35 #include <sys/systm.h>
   36 
   37 #include <machine/bus.h>
   38 
   39 #include <dev/ofw/ofw_bus_subr.h>
   40 #include <dev/uart/uart.h>
   41 #include <dev/uart/uart_bus.h>
   42 #include <dev/uart/uart_cpu.h>
   43 #include <dev/uart/uart_cpu_fdt.h>
   44 
   45 #include "uart_if.h"
   46 
   47 #define UART_RBR                0x00            /* Receiver Buffer */
   48 #define RBR_BRK_DET             (1 << 15)       /* Break Detect */
   49 #define RBR_FRM_ERR_DET         (1 << 14)       /* Frame Error Detect */
   50 #define RBR_PAR_ERR_DET         (1 << 13)       /* Parity Error Detect */
   51 #define RBR_OVR_ERR_DET         (1 << 12)       /* Overrun Error */
   52 
   53 #define UART_TSH                0x04            /* Transmitter Holding Register */
   54 
   55 #define UART_CTRL               0x08            /* Control Register */
   56 #define CTRL_SOFT_RST           (1 << 31)       /* Soft Reset */
   57 #define CTRL_TX_FIFO_RST        (1 << 15)       /* TX FIFO Reset */
   58 #define CTRL_RX_FIFO_RST        (1 << 14)       /* RX FIFO Reset */
   59 #define CTRL_ST_MIRR_EN         (1 << 13)       /* Status Mirror Enable */
   60 #define CTRL_LPBK_EN            (1 << 12)       /* Loopback Mode Enable */
   61 #define CTRL_SND_BRK_SEQ        (1 << 11)       /* Send Break Sequence */
   62 #define CTRL_PAR_EN             (1 << 10)       /* Parity Enable */
   63 #define CTRL_TWO_STOP           (1 << 9)        /* Two Stop Bits */
   64 #define CTRL_TX_HALF_INT        (1 << 8)        /* TX Half-Full Interrupt Enable */
   65 #define CTRL_RX_HALF_INT        (1 << 7)        /* RX Half-Full Interrupt Enable */
   66 #define CTRL_TX_EMPT_INT        (1 << 6)        /* TX Empty Interrupt Enable */
   67 #define CTRL_TX_RDY_INT         (1 << 5)        /* TX Ready Interrupt Enable */
   68 #define CTRL_RX_RDY_INT         (1 << 4)        /* RX Ready Interrupt Enable */
   69 #define CTRL_BRK_DET_INT        (1 << 3)        /* Break Detect Interrupt Enable */
   70 #define CTRL_FRM_ERR_INT        (1 << 2)        /* Frame Error Interrupt Enable */
   71 #define CTRL_PAR_ERR_INT        (1 << 1)        /* Parity Error Interrupt Enable */
   72 #define CTRL_OVR_ERR_INT        (1 << 0)        /* Overrun Error Interrupt Enable */
   73 #define CTRL_INTR_MASK          0x1ff
   74 #define CTRL_TX_IDLE_INT        CTRL_TX_RDY_INT
   75 #define CTRL_IPEND_MASK         (CTRL_OVR_ERR_INT | CTRL_BRK_DET_INT | \
   76     CTRL_RX_RDY_INT)
   77 
   78 #define UART_STAT               0x0c            /* Status Register */
   79 #define STAT_TX_FIFO_EMPT       (1 << 13)       /* TX FIFO Empty */
   80 #define STAT_RX_FIFO_EMPT       (1 << 12)       /* RX FIFO Empty */
   81 #define STAT_TX_FIFO_FULL       (1 << 11)       /* TX FIFO Full */
   82 #define STAT_TX_FIFO_HALF       (1 << 10)       /* TX FIFO Half Full */
   83 #define STAT_RX_TOGL            (1 << 9)        /* RX Toogled */
   84 #define STAT_RX_FIFO_FULL       (1 << 8)        /* RX FIFO Full */
   85 #define STAT_RX_FIFO_HALF       (1 << 7)        /* RX FIFO Half Full */
   86 #define STAT_TX_EMPT            (1 << 6)        /* TX Empty */
   87 #define STAT_TX_RDY             (1 << 5)        /* TX Ready */
   88 #define STAT_RX_RDY             (1 << 4)        /* RX Ready */
   89 #define STAT_BRK_DET            (1 << 3)        /* Break Detect */
   90 #define STAT_FRM_ERR            (1 << 2)        /* Frame Error */
   91 #define STAT_PAR_ERR            (1 << 1)        /* Parity Error */
   92 #define STAT_OVR_ERR            (1 << 0)        /* Overrun Error */
   93 #define STAT_TX_IDLE            STAT_TX_RDY
   94 #define STAT_TRANS_MASK         (STAT_OVR_ERR | STAT_BRK_DET | STAT_RX_RDY)
   95 
   96 #define UART_CCR                0x10            /* Clock Control Register */
   97 #define CCR_BAUDRATE_DIV        0x3ff           /* Baud Rate Divisor */
   98 
   99 #define DEFAULT_RCLK            25804800
  100 #define ONE_FRAME_TIME          87
  101 
  102 #define stat_ipend_trans(i) (                   \
  103             (i & STAT_OVR_ERR) << 16 |          \
  104             (i & STAT_BRK_DET) << 14 |          \
  105             (i & STAT_RX_RDY) << 14)
  106 
  107 /*
  108  * For debugging purposes
  109  */
  110 #if 0
  111 #ifdef EARLY_PRINTF
  112 #if defined(SOCDEV_PA) && defined(SOCDEV_VA)
  113 #define UART_REG_OFFSET 0x12000
  114 static void
  115 uart_mvebu_early_putc(int c)
  116 {
  117         volatile uint32_t *tsh;
  118         volatile uint32_t *stat;
  119 
  120         tsh = (uint32_t *)(SOCDEV_VA + UART_REG_OFFSET + UART_TSH);
  121         stat = (uint32_t *)(SOCDEV_VA + UART_REG_OFFSET + UART_STAT);
  122 
  123         while(!(*stat & STAT_TX_RDY))
  124                 ;
  125 
  126         *tsh = c & 0xff;
  127 }
  128 
  129 early_putc_t *early_putc = uart_mvebu_early_putc;
  130 #endif
  131 #endif
  132 #endif
  133 
  134 /*
  135  * Low-level UART interface.
  136  */
  137 static int uart_mvebu_probe(struct uart_bas *);
  138 static void uart_mvebu_init(struct uart_bas *, int, int, int, int);
  139 static void uart_mvebu_putc(struct uart_bas *, int);
  140 static int uart_mvebu_rxready(struct uart_bas *);
  141 static int uart_mvebu_getc(struct uart_bas *, struct mtx *);
  142 
  143 static struct uart_ops uart_mvebu_ops = {
  144         .probe = uart_mvebu_probe,
  145         .init = uart_mvebu_init,
  146         .term = NULL,
  147         .putc = uart_mvebu_putc,
  148         .rxready = uart_mvebu_rxready,
  149         .getc = uart_mvebu_getc,
  150 };
  151 
  152 static int
  153 uart_mvebu_probe(struct uart_bas *bas)
  154 {
  155 
  156         return (0);
  157 }
  158 
  159 static int
  160 uart_mvebu_divisor(int rclk, int baudrate)
  161 {
  162         int divisor;
  163 
  164         if (baudrate == 0)
  165                 return (0);
  166 
  167         divisor = (rclk >> 4) / baudrate;
  168         if (divisor <= 1 || divisor >= 1024)
  169                 return (0);
  170 
  171         return (divisor);
  172 }
  173 
  174 static int
  175 uart_mvebu_param(struct uart_bas *bas, int baudrate, int databits, int stopbits,
  176     int parity)
  177 {
  178         uint32_t ctrl = 0;
  179         uint32_t ccr;
  180         int divisor, ret = 0;
  181 
  182         /* Reset UART */
  183         ctrl = uart_getreg(bas, UART_CTRL);
  184         uart_setreg(bas, UART_CTRL, ctrl | CTRL_TX_FIFO_RST | CTRL_RX_FIFO_RST |
  185             CTRL_LPBK_EN);
  186         uart_barrier(bas);
  187 
  188         switch (stopbits) {
  189         case 2:
  190                 ctrl |= CTRL_TWO_STOP;
  191                 break;
  192         case 1:
  193         default:
  194                 ctrl &=~ CTRL_TWO_STOP;
  195         }
  196 
  197         switch (parity) {
  198         case 3: /* Even parity bit */
  199                 ctrl |= CTRL_PAR_EN;
  200                 break;
  201         default:
  202                 ctrl &=~ CTRL_PAR_EN;
  203         }
  204 
  205         /* Set baudrate. */
  206         if (baudrate > 0) {
  207                 divisor = uart_mvebu_divisor(bas->rclk, baudrate);
  208                 if (divisor == 0) {
  209                         ret = EINVAL;
  210                 } else {
  211                         ccr = uart_getreg(bas, UART_CCR);
  212                         ccr &=~CCR_BAUDRATE_DIV;
  213 
  214                         uart_setreg(bas, UART_CCR, ccr | divisor);
  215                         uart_barrier(bas);
  216                 }
  217         }
  218 
  219         /* Set mirroring of status bits */
  220         ctrl |= CTRL_ST_MIRR_EN;
  221 
  222         uart_setreg(bas, UART_CTRL, ctrl);
  223         uart_barrier(bas);
  224 
  225         return (ret);
  226 }
  227 
  228 static void
  229 uart_mvebu_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
  230     int parity)
  231 {
  232         /* Set default frequency */
  233         bas->rclk = DEFAULT_RCLK;
  234 
  235         /* Mask interrupts */
  236         uart_setreg(bas, UART_CTRL, uart_getreg(bas, UART_CTRL) &
  237             ~CTRL_INTR_MASK);
  238         uart_barrier(bas);
  239 
  240         uart_mvebu_param(bas, baudrate, databits, stopbits, parity);
  241 }
  242 
  243 static void
  244 uart_mvebu_putc(struct uart_bas *bas, int c)
  245 {
  246         while (uart_getreg(bas, UART_STAT) & STAT_TX_FIFO_FULL)
  247                 ;
  248         uart_setreg(bas, UART_TSH, c & 0xff);
  249 }
  250 
  251 static int
  252 uart_mvebu_rxready(struct uart_bas *bas)
  253 {
  254         if (uart_getreg(bas, UART_STAT) & STAT_RX_RDY)
  255                 return 1;
  256         return 0;
  257 }
  258 
  259 static int
  260 uart_mvebu_getc(struct uart_bas *bas, struct mtx *hwmtx)
  261 {
  262         int c;
  263 
  264         uart_lock(hwmtx);
  265         while (!(uart_getreg(bas, UART_STAT) & STAT_RX_RDY))
  266                 ;
  267 
  268         c = uart_getreg(bas, UART_RBR) & 0xff;
  269         uart_unlock(hwmtx);
  270 
  271         return c;
  272 }
  273 
  274 /*
  275  * UART driver methods implementation.
  276  */
  277 struct uart_mvebu_softc {
  278         struct uart_softc base;
  279         uint16_t intrm;
  280 };
  281 
  282 static int uart_mvebu_bus_attach(struct uart_softc *);
  283 static int uart_mvebu_bus_detach(struct uart_softc *);
  284 static int uart_mvebu_bus_flush(struct uart_softc *, int);
  285 static int uart_mvebu_bus_getsig(struct uart_softc *);
  286 static int uart_mvebu_bus_ioctl(struct uart_softc *, int, intptr_t);
  287 static int uart_mvebu_bus_ipend(struct uart_softc *);
  288 static int uart_mvebu_bus_param(struct uart_softc *, int, int, int, int);
  289 static int uart_mvebu_bus_probe(struct uart_softc *);
  290 static int uart_mvebu_bus_receive(struct uart_softc *);
  291 static int uart_mvebu_bus_setsig(struct uart_softc *, int);
  292 static int uart_mvebu_bus_transmit(struct uart_softc *);
  293 static void uart_mvebu_bus_grab(struct uart_softc *);
  294 static void uart_mvebu_bus_ungrab(struct uart_softc *);
  295 
  296 static kobj_method_t uart_mvebu_methods[] = {
  297         KOBJMETHOD(uart_attach,         uart_mvebu_bus_attach),
  298         KOBJMETHOD(uart_detach,         uart_mvebu_bus_detach),
  299         KOBJMETHOD(uart_flush,          uart_mvebu_bus_flush),
  300         KOBJMETHOD(uart_getsig,         uart_mvebu_bus_getsig),
  301         KOBJMETHOD(uart_ioctl,          uart_mvebu_bus_ioctl),
  302         KOBJMETHOD(uart_ipend,          uart_mvebu_bus_ipend),
  303         KOBJMETHOD(uart_param,          uart_mvebu_bus_param),
  304         KOBJMETHOD(uart_probe,          uart_mvebu_bus_probe),
  305         KOBJMETHOD(uart_receive,        uart_mvebu_bus_receive),
  306         KOBJMETHOD(uart_setsig,         uart_mvebu_bus_setsig),
  307         KOBJMETHOD(uart_transmit,       uart_mvebu_bus_transmit),
  308         KOBJMETHOD(uart_grab,           uart_mvebu_bus_grab),
  309         KOBJMETHOD(uart_ungrab,         uart_mvebu_bus_ungrab),
  310         { 0, 0 }
  311 };
  312 
  313 struct uart_class uart_mvebu_class = {
  314         "mvebu-uart",
  315         uart_mvebu_methods,
  316         sizeof(struct uart_mvebu_softc),
  317         .uc_ops = &uart_mvebu_ops,
  318         .uc_range = 0x14,
  319         .uc_rclk = DEFAULT_RCLK,
  320         .uc_rshift = 0,
  321         .uc_riowidth = 4
  322 };
  323 
  324 static struct ofw_compat_data compat_data[] = {
  325         {"marvell,armada-3700-uart",    (uintptr_t)&uart_mvebu_class},
  326         {NULL,                          (uintptr_t)NULL},
  327 };
  328 UART_FDT_CLASS_AND_DEVICE(compat_data);
  329 
  330 static int
  331 uart_mvebu_bus_attach(struct uart_softc *sc)
  332 {
  333         struct uart_bas *bas;
  334         int ctrl;
  335 
  336         bas = &sc->sc_bas;
  337         uart_lock(sc->sc_hwmtx);
  338 
  339         ctrl = uart_getreg(bas, UART_CTRL);
  340 
  341         /* Enable interrupts */
  342         ctrl &=~ CTRL_INTR_MASK;
  343         ctrl |= CTRL_IPEND_MASK;
  344 
  345         /* Set interrupts */
  346         uart_setreg(bas, UART_CTRL, ctrl);
  347         uart_barrier(bas);
  348 
  349         uart_unlock(sc->sc_hwmtx);
  350 
  351         return (0);
  352 }
  353 
  354 static int
  355 uart_mvebu_bus_detach(struct uart_softc *sc)
  356 {
  357 
  358         return (0);
  359 }
  360 
  361 static int
  362 uart_mvebu_bus_flush(struct uart_softc *sc, int what)
  363 {
  364         struct uart_bas *bas;
  365         int ctrl, ret = 0;
  366 
  367         bas = &sc->sc_bas;
  368         uart_lock(sc->sc_hwmtx);
  369         ctrl = uart_getreg(bas, UART_CTRL);
  370 
  371         switch (what) {
  372         case UART_FLUSH_RECEIVER:
  373                 uart_setreg(bas, UART_CTRL, ctrl | CTRL_RX_FIFO_RST);
  374                 uart_barrier(bas);
  375                 break;
  376 
  377         case UART_FLUSH_TRANSMITTER:
  378                 uart_setreg(bas, UART_CTRL, ctrl | CTRL_TX_FIFO_RST);
  379                 uart_barrier(bas);
  380                 break;
  381 
  382         default:
  383                 ret = EINVAL;
  384                 break;
  385         }
  386 
  387         /* Back to normal operation */
  388         if (!ret) {
  389                 uart_setreg(bas, UART_CTRL, ctrl);
  390                 uart_barrier(bas);
  391         }
  392 
  393         uart_unlock(sc->sc_hwmtx);
  394         return (ret);
  395 }
  396 
  397 static int
  398 uart_mvebu_bus_getsig(struct uart_softc *sc)
  399 {
  400 
  401         return (0);
  402 }
  403 
  404 static int
  405 uart_mvebu_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
  406 {
  407         struct uart_bas *bas;
  408         int ctrl, ret = 0;
  409         int divisor, baudrate;
  410 
  411         bas = &sc->sc_bas;
  412         uart_lock(sc->sc_hwmtx);
  413         switch (request) {
  414         case UART_IOCTL_BREAK:
  415                 ctrl = uart_getreg(bas, UART_CTRL);
  416                 if (data)
  417                         ctrl |= CTRL_SND_BRK_SEQ;
  418                 else
  419                         ctrl &=~ CTRL_SND_BRK_SEQ;
  420                 uart_setreg(bas, UART_CTRL, ctrl);
  421                 uart_barrier(bas);
  422                 break;
  423 
  424         case UART_IOCTL_BAUD:
  425                 divisor = uart_getreg(bas, UART_CCR) & CCR_BAUDRATE_DIV;
  426                 baudrate = bas->rclk/(divisor * 16);
  427                 *(int *)data = baudrate;
  428                 break;
  429 
  430         default:
  431                 ret = ENOTTY;
  432                 break;
  433         }
  434         uart_unlock(sc->sc_hwmtx);
  435 
  436         return (ret);
  437 }
  438 
  439 static int
  440 uart_mvebu_bus_ipend(struct uart_softc *sc)
  441 {
  442         struct uart_bas *bas;
  443         int ipend, ctrl, ret = 0;
  444 
  445         bas = &sc->sc_bas;
  446         uart_lock(sc->sc_hwmtx);
  447         ipend = uart_getreg(bas, UART_STAT);
  448         ctrl = uart_getreg(bas, UART_CTRL);
  449 
  450         if (((ipend & STAT_TX_IDLE) == STAT_TX_IDLE) &&
  451             (ctrl & CTRL_TX_IDLE_INT) == CTRL_TX_IDLE_INT) {
  452                 /* Disable TX IDLE Interrupt generation */
  453                 uart_setreg(bas, UART_CTRL, ctrl & ~CTRL_TX_IDLE_INT);
  454                 uart_barrier(bas);
  455 
  456                 /* SER_INT_TXIDLE means empty TX FIFO. Wait until it cleans */
  457                 while(!(uart_getreg(bas, UART_STAT) & STAT_TX_FIFO_EMPT))
  458                         DELAY(ONE_FRAME_TIME/2);
  459 
  460                 ret |= SER_INT_TXIDLE;
  461         }
  462 
  463         ret |= stat_ipend_trans(ipend & STAT_TRANS_MASK);
  464 
  465         uart_unlock(sc->sc_hwmtx);
  466 
  467         return (ret);
  468 }
  469 
  470 static int
  471 uart_mvebu_bus_param(struct uart_softc *sc, int baudrate, int databits,
  472     int stopbits, int parity)
  473 {
  474         int ret;
  475 
  476         uart_lock(sc->sc_hwmtx);
  477         ret = uart_mvebu_param(&sc->sc_bas, baudrate, databits, stopbits, parity);
  478         uart_unlock(sc->sc_hwmtx);
  479 
  480         return (ret);
  481 }
  482 
  483 static int
  484 uart_mvebu_bus_probe(struct uart_softc *sc)
  485 {
  486         if (!ofw_bus_status_okay(sc->sc_dev))
  487                 return (ENXIO);
  488 
  489         if (!ofw_bus_search_compatible(sc->sc_dev, compat_data)->ocd_data)
  490                 return (ENXIO);
  491 
  492         device_set_desc(sc->sc_dev, "Marvell Armada 3700 UART");
  493 
  494         sc->sc_txfifosz = 32;
  495         sc->sc_rxfifosz = 64;
  496         sc->sc_hwiflow = 0;
  497         sc->sc_hwoflow = 0;
  498 
  499         return (0);
  500 }
  501 
  502 int
  503 uart_mvebu_bus_receive(struct uart_softc *sc)
  504 {
  505         struct uart_bas *bas;
  506         uint32_t xc;
  507         int rx, er;
  508 
  509         bas = &sc->sc_bas;
  510         uart_lock(sc->sc_hwmtx);
  511 
  512         while (!(uart_getreg(bas, UART_STAT) & STAT_RX_FIFO_EMPT)) {
  513                 if (uart_rx_full(sc)) {
  514                         sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
  515                         break;
  516                 }
  517 
  518                 xc = uart_getreg(bas, UART_RBR);
  519                 rx = xc & 0xff;
  520                 er = xc & 0xf000;
  521                 /*
  522                  * Formula which translates marvell error bits
  523                  * Only valid when CTRL_ST_MIRR_EN is set
  524                  */
  525                 er = (er & RBR_BRK_DET) >> 7 |
  526                     (er & RBR_FRM_ERR_DET) >> 5 |
  527                     (er & RBR_PAR_ERR_DET) >> 2 |
  528                     (er & RBR_OVR_ERR_DET) >> 2;
  529 
  530                 uart_rx_put(sc, rx | er);
  531                 uart_barrier(bas);
  532         }
  533         /*
  534          * uart_if.m says that receive interrupt
  535          * should be cleared, so we need to reset
  536          * RX FIFO
  537          */
  538 
  539         if (!(uart_getreg(bas, UART_STAT) & STAT_RX_FIFO_EMPT)) {
  540                 uart_mvebu_bus_flush(sc, UART_FLUSH_RECEIVER);
  541         }
  542 
  543         uart_unlock(sc->sc_hwmtx);
  544         return (0);
  545 }
  546 
  547 static int
  548 uart_mvebu_bus_setsig(struct uart_softc *sc, int sig)
  549 {
  550         /* Not supported by hardware */
  551         return (0);
  552 }
  553 
  554 int
  555 uart_mvebu_bus_transmit(struct uart_softc *sc)
  556 {
  557         struct uart_bas *bas;
  558         int i, ctrl;
  559 
  560         bas = &sc->sc_bas;
  561         uart_lock(sc->sc_hwmtx);
  562 
  563         /* Turn off all interrupts during send */
  564         ctrl = uart_getreg(bas, UART_CTRL);
  565         uart_setreg(bas, UART_CTRL, ctrl & ~CTRL_INTR_MASK);
  566         uart_barrier(bas);
  567 
  568         for (i = 0; i < sc->sc_txdatasz; i++) {
  569                 uart_setreg(bas, UART_TSH, sc->sc_txbuf[i] & 0xff);
  570                 uart_barrier(bas);
  571         }
  572 
  573         /*
  574          * Make sure that interrupt is generated
  575          * when FIFO can get more data.
  576          */
  577         uart_setreg(bas, UART_CTRL, ctrl | CTRL_TX_IDLE_INT);
  578         uart_barrier(bas);
  579 
  580         /* Mark busy */
  581         sc->sc_txbusy = 1;
  582 
  583         uart_unlock(sc->sc_hwmtx);
  584         return (0);
  585 }
  586 
  587 static void
  588 uart_mvebu_bus_grab(struct uart_softc *sc)
  589 {
  590         struct uart_mvebu_softc *msc = (struct uart_mvebu_softc *)sc;
  591         struct uart_bas *bas = &sc->sc_bas;
  592         uint32_t ctrl;
  593 
  594         /* Mask all interrupts */
  595         uart_lock(sc->sc_hwmtx);
  596         ctrl = uart_getreg(bas, UART_CTRL);
  597         msc->intrm = ctrl & CTRL_INTR_MASK;
  598         uart_setreg(bas, UART_CTRL, ctrl & ~CTRL_INTR_MASK);
  599         uart_barrier(bas);
  600         uart_unlock(sc->sc_hwmtx);
  601 }
  602 
  603 static void
  604 uart_mvebu_bus_ungrab(struct uart_softc *sc)
  605 {
  606         struct uart_mvebu_softc *msc = (struct uart_mvebu_softc *)sc;
  607         struct uart_bas *bas = &sc->sc_bas;
  608         uint32_t ctrl;
  609 
  610         /* Restore interrupts */
  611         uart_lock(sc->sc_hwmtx);
  612         ctrl = uart_getreg(bas, UART_CTRL) & ~CTRL_INTR_MASK;
  613         uart_setreg(bas, UART_CTRL, ctrl | msc->intrm);
  614         uart_barrier(bas);
  615         uart_unlock(sc->sc_hwmtx);
  616 }

Cache object: e90b6c0d5d195377724f0771cf04a7af


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.