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

Cache object: 4e4c6cc1fdacde09b66240f07de05c22


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