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

Cache object: 153b05266148e6e3a3feaca836abc51e


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