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/mips/atheros/uart_dev_ar933x.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  *
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/bus.h>
   35 #include <sys/conf.h>
   36 #include <machine/bus.h>
   37 
   38 #include <dev/uart/uart.h>
   39 #include <dev/uart/uart_cpu.h>
   40 #include <dev/uart/uart_bus.h>
   41 
   42 #include <mips/atheros/ar933x_uart.h>
   43 
   44 #include "uart_if.h"
   45 
   46 /*
   47  * Default system clock is 25MHz; see ar933x_chip.c for how
   48  * the startup process determines whether it's 25MHz or 40MHz.
   49  */
   50 #define DEFAULT_RCLK    (25 * 1000 * 1000)
   51 
   52 #define ar933x_getreg(bas, reg)           \
   53         bus_space_read_4((bas)->bst, (bas)->bsh, reg)
   54 #define ar933x_setreg(bas, reg, value)    \
   55         bus_space_write_4((bas)->bst, (bas)->bsh, reg, value)
   56 
   57 static int
   58 ar933x_drain(struct uart_bas *bas, int what)
   59 {
   60         int limit;
   61 
   62         if (what & UART_DRAIN_TRANSMITTER) {
   63                 limit = 10*1024;
   64 
   65                 /* Loop over until the TX FIFO shows entirely clear */
   66                 while (--limit) {
   67                         if ((ar933x_getreg(bas, AR933X_UART_CS_REG)
   68                             & AR933X_UART_CS_TX_BUSY) == 0)
   69                                 break;
   70                 }
   71                 if (limit == 0) {
   72                         return (EIO);
   73                 }
   74         }
   75 
   76         if (what & UART_DRAIN_RECEIVER) {
   77                 limit=10*4096;
   78                 while (--limit) {
   79                         /* XXX duplicated from ar933x_getc() */
   80                         /* XXX TODO: refactor! */
   81 
   82                         /* If there's nothing to read, stop! */
   83                         if ((ar933x_getreg(bas, AR933X_UART_DATA_REG) &
   84                             AR933X_UART_DATA_RX_CSR) == 0) {
   85                                 break;
   86                         }
   87 
   88                         /* Read the top of the RX FIFO */
   89                         (void) ar933x_getreg(bas, AR933X_UART_DATA_REG);
   90 
   91                         /* Remove that entry from said RX FIFO */
   92                         ar933x_setreg(bas, AR933X_UART_DATA_REG,
   93                             AR933X_UART_DATA_RX_CSR);
   94 
   95                         uart_barrier(bas);
   96                         DELAY(2);
   97                 }
   98                 if (limit == 0) {
   99                         return (EIO);
  100                 }
  101         }
  102         return (0);
  103 }
  104 
  105 /*
  106  * Calculate the baud from the given chip configuration parameters.
  107  */
  108 static unsigned long
  109 ar933x_uart_get_baud(unsigned int clk, unsigned int scale,
  110     unsigned int step)
  111 {
  112         uint64_t t;
  113         uint32_t div;
  114 
  115         div = (2 << 16) * (scale + 1);
  116         t = clk;
  117         t *= step;
  118         t += (div / 2);
  119         t = t / div;
  120 
  121         return (t);
  122 }
  123 
  124 /*
  125  * Calculate the scale/step with the lowest possible deviation from
  126  * the target baudrate.
  127  */
  128 static void
  129 ar933x_uart_get_scale_step(struct uart_bas *bas, unsigned int baud,
  130     unsigned int *scale, unsigned int *step)
  131 {
  132         unsigned int tscale;
  133         uint32_t clk;
  134         long min_diff;
  135 
  136         clk = bas->rclk;
  137         *scale = 0;
  138         *step = 0;
  139 
  140         min_diff = baud;
  141         for (tscale = 0; tscale < AR933X_UART_MAX_SCALE; tscale++) {
  142                 uint64_t tstep;
  143                 int diff;
  144 
  145                 tstep = baud * (tscale + 1);
  146                 tstep *= (2 << 16);
  147                 tstep = tstep / clk;
  148 
  149                 if (tstep > AR933X_UART_MAX_STEP)
  150                         break;
  151 
  152                 diff = abs(ar933x_uart_get_baud(clk, tscale, tstep) - baud);
  153                 if (diff < min_diff) {
  154                         min_diff = diff;
  155                         *scale = tscale;
  156                         *step = tstep;
  157                 }
  158         }
  159 }
  160 
  161 static int
  162 ar933x_param(struct uart_bas *bas, int baudrate, int databits, int stopbits,
  163     int parity)
  164 {
  165         /* UART always 8 bits */
  166 
  167         /* UART always 1 stop bit */
  168 
  169         /* UART parity is controllable by bits 0:1, ignore for now */
  170 
  171         /* Set baudrate if required. */
  172         if (baudrate > 0) {
  173                 uint32_t clock_scale, clock_step;
  174 
  175                 /* Find the best fit for the given baud rate */
  176                 ar933x_uart_get_scale_step(bas, baudrate, &clock_scale,
  177                     &clock_step);
  178 
  179                 /*
  180                  * Program the clock register in its entirety - no need
  181                  * for Read-Modify-Write.
  182                  */
  183                 ar933x_setreg(bas, AR933X_UART_CLOCK_REG,
  184                     ((clock_scale & AR933X_UART_CLOCK_SCALE_M)
  185                       << AR933X_UART_CLOCK_SCALE_S) |
  186                     (clock_step & AR933X_UART_CLOCK_STEP_M));
  187         }
  188 
  189         uart_barrier(bas);
  190         return (0);
  191 }
  192 
  193 /*
  194  * Low-level UART interface.
  195  */
  196 static int ar933x_probe(struct uart_bas *bas);
  197 static void ar933x_init(struct uart_bas *bas, int, int, int, int);
  198 static void ar933x_term(struct uart_bas *bas);
  199 static void ar933x_putc(struct uart_bas *bas, int);
  200 static int ar933x_rxready(struct uart_bas *bas);
  201 static int ar933x_getc(struct uart_bas *bas, struct mtx *);
  202 
  203 static struct uart_ops uart_ar933x_ops = {
  204         .probe = ar933x_probe,
  205         .init = ar933x_init,
  206         .term = ar933x_term,
  207         .putc = ar933x_putc,
  208         .rxready = ar933x_rxready,
  209         .getc = ar933x_getc,
  210 };
  211 
  212 static int
  213 ar933x_probe(struct uart_bas *bas)
  214 {
  215 
  216         /* We always know this will be here */
  217         return (0);
  218 }
  219 
  220 static void
  221 ar933x_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
  222     int parity)
  223 {
  224         uint32_t reg;
  225 
  226         /* Setup default parameters */
  227         ar933x_param(bas, baudrate, databits, stopbits, parity);
  228 
  229         /* XXX Force enable UART in case it was disabled */
  230 
  231         /* Disable all interrupts */
  232         ar933x_setreg(bas, AR933X_UART_INT_EN_REG, 0x00000000);
  233 
  234         /* Disable the host interrupt */
  235         reg = ar933x_getreg(bas, AR933X_UART_CS_REG);
  236         reg &= ~AR933X_UART_CS_HOST_INT_EN;
  237         ar933x_setreg(bas, AR933X_UART_CS_REG, reg);
  238 
  239         uart_barrier(bas);
  240 
  241         /* XXX Set RTS/DTR? */
  242 }
  243 
  244 /*
  245  * Detach from console.
  246  */
  247 static void
  248 ar933x_term(struct uart_bas *bas)
  249 {
  250 
  251         /* XXX TODO */
  252 }
  253 
  254 static void
  255 ar933x_putc(struct uart_bas *bas, int c)
  256 {
  257         int limit;
  258 
  259         limit = 250000;
  260 
  261         /* Wait for space in the TX FIFO */
  262         while ( ((ar933x_getreg(bas, AR933X_UART_DATA_REG) &
  263             AR933X_UART_DATA_TX_CSR) == 0) && --limit)
  264                 DELAY(4);
  265 
  266         /* Write the actual byte */
  267         ar933x_setreg(bas, AR933X_UART_DATA_REG,
  268             (c & 0xff) | AR933X_UART_DATA_TX_CSR);
  269 }
  270 
  271 static int
  272 ar933x_rxready(struct uart_bas *bas)
  273 {
  274 
  275         /* Wait for a character to come ready */
  276         return (!!(ar933x_getreg(bas, AR933X_UART_DATA_REG)
  277             & AR933X_UART_DATA_RX_CSR));
  278 }
  279 
  280 static int
  281 ar933x_getc(struct uart_bas *bas, struct mtx *hwmtx)
  282 {
  283         int c;
  284 
  285         uart_lock(hwmtx);
  286 
  287         /* Wait for a character to come ready */
  288         while ((ar933x_getreg(bas, AR933X_UART_DATA_REG) &
  289             AR933X_UART_DATA_RX_CSR) == 0) {
  290                 uart_unlock(hwmtx);
  291                 DELAY(4);
  292                 uart_lock(hwmtx);
  293         }
  294 
  295         /* Read the top of the RX FIFO */
  296         c = ar933x_getreg(bas, AR933X_UART_DATA_REG) & 0xff;
  297 
  298         /* Remove that entry from said RX FIFO */
  299         ar933x_setreg(bas, AR933X_UART_DATA_REG, AR933X_UART_DATA_RX_CSR);
  300 
  301         uart_unlock(hwmtx);
  302 
  303         return (c);
  304 }
  305 
  306 /*
  307  * High-level UART interface.
  308  */
  309 struct ar933x_softc {
  310         struct uart_softc base;
  311 
  312         uint32_t        u_ier;
  313 };
  314 
  315 static int ar933x_bus_attach(struct uart_softc *);
  316 static int ar933x_bus_detach(struct uart_softc *);
  317 static int ar933x_bus_flush(struct uart_softc *, int);
  318 static int ar933x_bus_getsig(struct uart_softc *);
  319 static int ar933x_bus_ioctl(struct uart_softc *, int, intptr_t);
  320 static int ar933x_bus_ipend(struct uart_softc *);
  321 static int ar933x_bus_param(struct uart_softc *, int, int, int, int);
  322 static int ar933x_bus_probe(struct uart_softc *);
  323 static int ar933x_bus_receive(struct uart_softc *);
  324 static int ar933x_bus_setsig(struct uart_softc *, int);
  325 static int ar933x_bus_transmit(struct uart_softc *);
  326 static void ar933x_bus_grab(struct uart_softc *);
  327 static void ar933x_bus_ungrab(struct uart_softc *);
  328 
  329 static kobj_method_t ar933x_methods[] = {
  330         KOBJMETHOD(uart_attach,         ar933x_bus_attach),
  331         KOBJMETHOD(uart_detach,         ar933x_bus_detach),
  332         KOBJMETHOD(uart_flush,          ar933x_bus_flush),
  333         KOBJMETHOD(uart_getsig,         ar933x_bus_getsig),
  334         KOBJMETHOD(uart_ioctl,          ar933x_bus_ioctl),
  335         KOBJMETHOD(uart_ipend,          ar933x_bus_ipend),
  336         KOBJMETHOD(uart_param,          ar933x_bus_param),
  337         KOBJMETHOD(uart_probe,          ar933x_bus_probe),
  338         KOBJMETHOD(uart_receive,        ar933x_bus_receive),
  339         KOBJMETHOD(uart_setsig,         ar933x_bus_setsig),
  340         KOBJMETHOD(uart_transmit,       ar933x_bus_transmit),
  341         KOBJMETHOD(uart_grab,           ar933x_bus_grab),
  342         KOBJMETHOD(uart_ungrab,         ar933x_bus_ungrab),
  343         { 0, 0 }
  344 };
  345 
  346 struct uart_class uart_ar933x_class = {
  347         "ar933x",
  348         ar933x_methods,
  349         sizeof(struct ar933x_softc),
  350         .uc_ops = &uart_ar933x_ops,
  351         .uc_range = 8,
  352         .uc_rclk = DEFAULT_RCLK,
  353         .uc_rshift = 0
  354 };
  355 
  356 #define SIGCHG(c, i, s, d)                              \
  357         if (c) {                                        \
  358                 i |= (i & s) ? s : s | d;               \
  359         } else {                                        \
  360                 i = (i & s) ? (i & ~s) | d : i;         \
  361         }
  362 
  363 static int
  364 ar933x_bus_attach(struct uart_softc *sc)
  365 {
  366         struct ar933x_softc *u = (struct ar933x_softc *)sc;
  367         struct uart_bas *bas = &sc->sc_bas;
  368         uint32_t reg;
  369 
  370         /* XXX TODO: flush transmitter */
  371 
  372         /*
  373          * Setup initial interrupt notifications.
  374          *
  375          * XXX for now, just RX FIFO valid.
  376          * Later on (when they're handled), also handle
  377          * RX errors/overflow.
  378          */
  379         u->u_ier = AR933X_UART_INT_RX_VALID;
  380 
  381         /* Enable RX interrupts to kick-start things */
  382         ar933x_setreg(bas, AR933X_UART_INT_EN_REG, u->u_ier);
  383 
  384         /* Enable the host interrupt now */
  385         reg = ar933x_getreg(bas, AR933X_UART_CS_REG);
  386         reg |= AR933X_UART_CS_HOST_INT_EN;
  387         ar933x_setreg(bas, AR933X_UART_CS_REG, reg);
  388 
  389         return (0);
  390 }
  391 
  392 static int
  393 ar933x_bus_detach(struct uart_softc *sc)
  394 {
  395         struct uart_bas *bas = &sc->sc_bas;
  396         uint32_t reg;
  397 
  398         /* Disable all interrupts */
  399         ar933x_setreg(bas, AR933X_UART_INT_EN_REG, 0x00000000);
  400 
  401         /* Disable the host interrupt */
  402         reg = ar933x_getreg(bas, AR933X_UART_CS_REG);
  403         reg &= ~AR933X_UART_CS_HOST_INT_EN;
  404         ar933x_setreg(bas, AR933X_UART_CS_REG, reg);
  405         uart_barrier(bas);
  406 
  407         return (0);
  408 }
  409 
  410 static int
  411 ar933x_bus_flush(struct uart_softc *sc, int what)
  412 {
  413         struct uart_bas *bas;
  414 
  415         bas = &sc->sc_bas;
  416         uart_lock(sc->sc_hwmtx);
  417         ar933x_drain(bas, what);
  418         uart_unlock(sc->sc_hwmtx);
  419 
  420         return (0);
  421 }
  422 
  423 static int
  424 ar933x_bus_getsig(struct uart_softc *sc)
  425 {
  426         uint32_t sig = sc->sc_hwsig;
  427 
  428         /*
  429          * For now, let's just return that DSR/DCD/CTS is asserted.
  430          */
  431         SIGCHG(1, sig, SER_DSR, SER_DDSR);
  432         SIGCHG(1, sig, SER_CTS, SER_DCTS);
  433         SIGCHG(1, sig, SER_DCD, SER_DDCD);
  434         SIGCHG(1, sig,  SER_RI,  SER_DRI);
  435 
  436         sc->sc_hwsig = sig & ~SER_MASK_DELTA;
  437 
  438         return (sig);
  439 }
  440 
  441 /*
  442  * XXX TODO: actually implement the rest of this!
  443  */
  444 static int
  445 ar933x_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
  446 {
  447         int error = 0;
  448 
  449         /* XXX lock */
  450         switch (request) {
  451         case UART_IOCTL_BREAK:
  452         case UART_IOCTL_IFLOW:
  453         case UART_IOCTL_OFLOW:
  454                 break;
  455         case UART_IOCTL_BAUD:
  456                 *(int*)data = 115200;
  457                 break;
  458         default:
  459                 error = EINVAL;
  460                 break;
  461         }
  462 
  463         /* XXX unlock */
  464 
  465         return (error);
  466 }
  467 
  468 /*
  469  * Bus interrupt handler.
  470  *
  471  * For now, system interrupts are disabled.
  472  * So this is just called from a callout in uart_core.c
  473  * to poll various state.
  474  */
  475 static int
  476 ar933x_bus_ipend(struct uart_softc *sc)
  477 {
  478         struct ar933x_softc *u = (struct ar933x_softc *)sc;
  479         struct uart_bas *bas = &sc->sc_bas;
  480         int ipend = 0;
  481         uint32_t isr;
  482 
  483         uart_lock(sc->sc_hwmtx);
  484 
  485         /*
  486          * Fetch/ACK the ISR status.
  487          */
  488         isr = ar933x_getreg(bas, AR933X_UART_INT_REG);
  489         ar933x_setreg(bas, AR933X_UART_INT_REG, isr);
  490         uart_barrier(bas);
  491 
  492         /*
  493          * RX ready - notify upper layer.
  494          */
  495         if (isr & AR933X_UART_INT_RX_VALID) {
  496                 ipend |= SER_INT_RXREADY;
  497         }
  498 
  499         /*
  500          * If we get this interrupt, we should disable
  501          * it from the interrupt mask and inform the uart
  502          * driver appropriately.
  503          *
  504          * We can't keep setting SER_INT_TXIDLE or SER_INT_SIGCHG
  505          * all the time or IO stops working.  So we will always
  506          * clear this interrupt if we get it, then we only signal
  507          * the upper layer if we were doing active TX in the
  508          * first place.
  509          *
  510          * Also, the name is misleading.  This actually means
  511          * "the FIFO is almost empty."  So if we just write some
  512          * more data to the FIFO without checking whether it can
  513          * take said data, we'll overflow the thing.
  514          *
  515          * Unfortunately the FreeBSD uart device has no concept of
  516          * partial UART writes - it expects that the whole buffer
  517          * is written to the hardware.  Thus for now, ar933x_bus_transmit()
  518          * will wait for the FIFO to finish draining before it pushes
  519          * more frames into it.
  520          */
  521         if (isr & AR933X_UART_INT_TX_EMPTY) {
  522                 /*
  523                  * Update u_ier to disable TX notifications; update hardware
  524                  */
  525                 u->u_ier &= ~AR933X_UART_INT_TX_EMPTY;
  526                 ar933x_setreg(bas, AR933X_UART_INT_EN_REG, u->u_ier);
  527                 uart_barrier(bas);
  528         }
  529 
  530         /*
  531          * Only signal TX idle if we're not busy transmitting.
  532          *
  533          * XXX I never get _out_ of txbusy? Debug that!
  534          */
  535         if (sc->sc_txbusy) {
  536                 if (isr & AR933X_UART_INT_TX_EMPTY) {
  537                         ipend |= SER_INT_TXIDLE;
  538                 } else {
  539                         ipend |= SER_INT_SIGCHG;
  540                 }
  541         }
  542 
  543         uart_unlock(sc->sc_hwmtx);
  544         return (ipend);
  545 }
  546 
  547 static int
  548 ar933x_bus_param(struct uart_softc *sc, int baudrate, int databits,
  549     int stopbits, int parity)
  550 {
  551         struct uart_bas *bas;
  552         int error;
  553 
  554         bas = &sc->sc_bas;
  555         uart_lock(sc->sc_hwmtx);
  556         error = ar933x_param(bas, baudrate, databits, stopbits, parity);
  557         uart_unlock(sc->sc_hwmtx);
  558         return (error);
  559 }
  560 
  561 static int
  562 ar933x_bus_probe(struct uart_softc *sc)
  563 {
  564         struct uart_bas *bas;
  565         int error;
  566 
  567         bas = &sc->sc_bas;
  568 
  569         error = ar933x_probe(bas);
  570         if (error)
  571                 return (error);
  572 
  573         /* Reset FIFOs. */
  574         ar933x_drain(bas, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER);
  575 
  576         /* XXX TODO: actually find out what the FIFO depth is! */
  577         sc->sc_rxfifosz = 16;
  578         sc->sc_txfifosz = 16;
  579 
  580         return (0);
  581 }
  582 
  583 static int
  584 ar933x_bus_receive(struct uart_softc *sc)
  585 {
  586         struct uart_bas *bas = &sc->sc_bas;
  587         int xc;
  588 
  589         uart_lock(sc->sc_hwmtx);
  590 
  591         /* Loop over until we are full, or no data is available */
  592         while (ar933x_rxready(bas)) {
  593                 if (uart_rx_full(sc)) {
  594                         sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
  595                         break;
  596                 }
  597 
  598                 /* Read the top of the RX FIFO */
  599                 xc = ar933x_getreg(bas, AR933X_UART_DATA_REG) & 0xff;
  600 
  601                 /* Remove that entry from said RX FIFO */
  602                 ar933x_setreg(bas, AR933X_UART_DATA_REG,
  603                     AR933X_UART_DATA_RX_CSR);
  604                 uart_barrier(bas);
  605 
  606                 /* XXX frame, parity error */
  607                 uart_rx_put(sc, xc);
  608         }
  609 
  610         /*
  611          * XXX TODO: Discard everything left in the Rx FIFO?
  612          * XXX only if we've hit an overrun condition?
  613          */
  614 
  615         uart_unlock(sc->sc_hwmtx);
  616 
  617         return (0);
  618 }
  619 
  620 static int
  621 ar933x_bus_setsig(struct uart_softc *sc, int sig)
  622 {
  623 #if 0
  624         struct ar933x_softc *ns8250 = (struct ar933x_softc*)sc;
  625         struct uart_bas *bas;
  626         uint32_t new, old;
  627 
  628         bas = &sc->sc_bas;
  629         do {
  630                 old = sc->sc_hwsig;
  631                 new = old;
  632                 if (sig & SER_DDTR) {
  633                         SIGCHG(sig & SER_DTR, new, SER_DTR,
  634                             SER_DDTR);
  635                 }
  636                 if (sig & SER_DRTS) {
  637                         SIGCHG(sig & SER_RTS, new, SER_RTS,
  638                             SER_DRTS);
  639                 }
  640         } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
  641         uart_lock(sc->sc_hwmtx);
  642         ns8250->mcr &= ~(MCR_DTR|MCR_RTS);
  643         if (new & SER_DTR)
  644                 ns8250->mcr |= MCR_DTR;
  645         if (new & SER_RTS)
  646                 ns8250->mcr |= MCR_RTS;
  647         uart_setreg(bas, REG_MCR, ns8250->mcr);
  648         uart_barrier(bas);
  649         uart_unlock(sc->sc_hwmtx);
  650 #endif
  651         return (0);
  652 }
  653 
  654 /*
  655  * Write the current transmit buffer to the TX FIFO.
  656  *
  657  * Unfortunately the FreeBSD uart device has no concept of
  658  * partial UART writes - it expects that the whole buffer
  659  * is written to the hardware.  Thus for now, this will wait for
  660  * the FIFO to finish draining before it pushes more frames into it.
  661  *
  662  * If non-blocking operation is truely needed here, either
  663  * the FreeBSD uart device will need to handle partial writes
  664  * in xxx_bus_transmit(), or we'll need to do TX FIFO buffering
  665  * of our own here.
  666  */
  667 static int
  668 ar933x_bus_transmit(struct uart_softc *sc)
  669 {
  670         struct uart_bas *bas = &sc->sc_bas;
  671         struct ar933x_softc *u = (struct ar933x_softc *)sc;
  672         int i;
  673 
  674         uart_lock(sc->sc_hwmtx);
  675 
  676         /* Wait for the FIFO to be clear - see above */
  677         while (ar933x_getreg(bas, AR933X_UART_CS_REG) &
  678             AR933X_UART_CS_TX_BUSY)
  679                 ;
  680 
  681         /*
  682          * Write some data!
  683          */
  684         for (i = 0; i < sc->sc_txdatasz; i++) {
  685                 /* Write the TX data */
  686                 ar933x_setreg(bas, AR933X_UART_DATA_REG,
  687                     (sc->sc_txbuf[i] & 0xff) | AR933X_UART_DATA_TX_CSR);
  688                 uart_barrier(bas);
  689         }
  690 
  691         /*
  692          * Now that we're transmitting, get interrupt notification
  693          * when the FIFO is (almost) empty - see above.
  694          */
  695         u->u_ier |= AR933X_UART_INT_TX_EMPTY;
  696         ar933x_setreg(bas, AR933X_UART_INT_EN_REG, u->u_ier);
  697         uart_barrier(bas);
  698 
  699         /*
  700          * Inform the upper layer that we are presently transmitting
  701          * data to the hardware; this will be cleared when the
  702          * TXIDLE interrupt occurs.
  703          */
  704         sc->sc_txbusy = 1;
  705         uart_unlock(sc->sc_hwmtx);
  706 
  707         return (0);
  708 }
  709 
  710 static void
  711 ar933x_bus_grab(struct uart_softc *sc)
  712 {
  713         struct uart_bas *bas = &sc->sc_bas;
  714         uint32_t reg;
  715 
  716         /* Disable the host interrupt now */
  717         uart_lock(sc->sc_hwmtx);
  718         reg = ar933x_getreg(bas, AR933X_UART_CS_REG);
  719         reg &= ~AR933X_UART_CS_HOST_INT_EN;
  720         ar933x_setreg(bas, AR933X_UART_CS_REG, reg);
  721         uart_unlock(sc->sc_hwmtx);
  722 }
  723 
  724 static void
  725 ar933x_bus_ungrab(struct uart_softc *sc)
  726 {
  727         struct uart_bas *bas = &sc->sc_bas;
  728         uint32_t reg;
  729 
  730         /* Enable the host interrupt now */
  731         uart_lock(sc->sc_hwmtx);
  732         reg = ar933x_getreg(bas, AR933X_UART_CS_REG);
  733         reg |= AR933X_UART_CS_HOST_INT_EN;
  734         ar933x_setreg(bas, AR933X_UART_CS_REG, reg);
  735         uart_unlock(sc->sc_hwmtx);
  736 }

Cache object: 660cadb915739361f925b2f7d0131bcc


[ 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.