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: releng/10.4/sys/mips/atheros/uart_dev_ar933x.c 262649 2014-03-01 04:16:54Z imp $");
   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 };
  356 
  357 #define SIGCHG(c, i, s, d)                              \
  358         if (c) {                                        \
  359                 i |= (i & s) ? s : s | d;               \
  360         } else {                                        \
  361                 i = (i & s) ? (i & ~s) | d : i;         \
  362         }
  363 
  364 static int
  365 ar933x_bus_attach(struct uart_softc *sc)
  366 {
  367         struct ar933x_softc *u = (struct ar933x_softc *)sc;
  368         struct uart_bas *bas = &sc->sc_bas;
  369         uint32_t reg;
  370 
  371         /* XXX TODO: flush transmitter */
  372 
  373         /*
  374          * Setup initial interrupt notifications.
  375          *
  376          * XXX for now, just RX FIFO valid.
  377          * Later on (when they're handled), also handle
  378          * RX errors/overflow.
  379          */
  380         u->u_ier = AR933X_UART_INT_RX_VALID;
  381 
  382         /* Enable RX interrupts to kick-start things */
  383         ar933x_setreg(bas, AR933X_UART_INT_EN_REG, u->u_ier);
  384 
  385         /* Enable the host interrupt now */
  386         reg = ar933x_getreg(bas, AR933X_UART_CS_REG);
  387         reg |= AR933X_UART_CS_HOST_INT_EN;
  388         ar933x_setreg(bas, AR933X_UART_CS_REG, reg);
  389 
  390         return (0);
  391 }
  392 
  393 static int
  394 ar933x_bus_detach(struct uart_softc *sc)
  395 {
  396         struct uart_bas *bas = &sc->sc_bas;
  397         uint32_t reg;
  398 
  399         /* Disable all interrupts */
  400         ar933x_setreg(bas, AR933X_UART_INT_EN_REG, 0x00000000);
  401 
  402         /* Disable the host interrupt */
  403         reg = ar933x_getreg(bas, AR933X_UART_CS_REG);
  404         reg &= ~AR933X_UART_CS_HOST_INT_EN;
  405         ar933x_setreg(bas, AR933X_UART_CS_REG, reg);
  406         uart_barrier(bas);
  407 
  408         return (0);
  409 }
  410 
  411 static int
  412 ar933x_bus_flush(struct uart_softc *sc, int what)
  413 {
  414         struct uart_bas *bas;
  415 
  416         bas = &sc->sc_bas;
  417         uart_lock(sc->sc_hwmtx);
  418         ar933x_drain(bas, what);
  419         uart_unlock(sc->sc_hwmtx);
  420 
  421         return (0);
  422 }
  423 
  424 static int
  425 ar933x_bus_getsig(struct uart_softc *sc)
  426 {
  427         uint32_t sig = sc->sc_hwsig;
  428 
  429         /*
  430          * For now, let's just return that DSR/DCD/CTS is asserted.
  431          *
  432          * XXX TODO: actually verify whether this is correct!
  433          */
  434         SIGCHG(1, sig, SER_DSR, SER_DDSR);
  435         SIGCHG(1, sig, SER_CTS, SER_DCTS);
  436         SIGCHG(1, sig, SER_DCD, SER_DDCD);
  437         SIGCHG(1, sig,  SER_RI,  SER_DRI);
  438 
  439         sc->sc_hwsig = sig & ~SER_MASK_DELTA;
  440 
  441         return (sig);
  442 }
  443 
  444 static int
  445 ar933x_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
  446 {
  447 #if 0
  448         struct uart_bas *bas;
  449         int baudrate, divisor, error;
  450         uint8_t efr, lcr;
  451 
  452         bas = &sc->sc_bas;
  453         error = 0;
  454         uart_lock(sc->sc_hwmtx);
  455         switch (request) {
  456         case UART_IOCTL_BREAK:
  457                 lcr = uart_getreg(bas, REG_LCR);
  458                 if (data)
  459                         lcr |= LCR_SBREAK;
  460                 else
  461                         lcr &= ~LCR_SBREAK;
  462                 uart_setreg(bas, REG_LCR, lcr);
  463                 uart_barrier(bas);
  464                 break;
  465         case UART_IOCTL_IFLOW:
  466                 lcr = uart_getreg(bas, REG_LCR);
  467                 uart_barrier(bas);
  468                 uart_setreg(bas, REG_LCR, 0xbf);
  469                 uart_barrier(bas);
  470                 efr = uart_getreg(bas, REG_EFR);
  471                 if (data)
  472                         efr |= EFR_RTS;
  473                 else
  474                         efr &= ~EFR_RTS;
  475                 uart_setreg(bas, REG_EFR, efr);
  476                 uart_barrier(bas);
  477                 uart_setreg(bas, REG_LCR, lcr);
  478                 uart_barrier(bas);
  479                 break;
  480         case UART_IOCTL_OFLOW:
  481                 lcr = uart_getreg(bas, REG_LCR);
  482                 uart_barrier(bas);
  483                 uart_setreg(bas, REG_LCR, 0xbf);
  484                 uart_barrier(bas);
  485                 efr = uart_getreg(bas, REG_EFR);
  486                 if (data)
  487                         efr |= EFR_CTS;
  488                 else
  489                         efr &= ~EFR_CTS;
  490                 uart_setreg(bas, REG_EFR, efr);
  491                 uart_barrier(bas);
  492                 uart_setreg(bas, REG_LCR, lcr);
  493                 uart_barrier(bas);
  494                 break;
  495         case UART_IOCTL_BAUD:
  496                 lcr = uart_getreg(bas, REG_LCR);
  497                 uart_setreg(bas, REG_LCR, lcr | LCR_DLAB);
  498                 uart_barrier(bas);
  499                 divisor = uart_getreg(bas, REG_DLL) |
  500                     (uart_getreg(bas, REG_DLH) << 8);
  501                 uart_barrier(bas);
  502                 uart_setreg(bas, REG_LCR, lcr);
  503                 uart_barrier(bas);
  504                 baudrate = (divisor > 0) ? bas->rclk / divisor / 16 : 0;
  505                 if (baudrate > 0)
  506                         *(int*)data = baudrate;
  507                 else
  508                         error = ENXIO;
  509                 break;
  510         default:
  511                 error = EINVAL;
  512                 break;
  513         }
  514         uart_unlock(sc->sc_hwmtx);
  515         return (error);
  516 #endif
  517         return (ENXIO);
  518 }
  519 
  520 /*
  521  * Bus interrupt handler.
  522  *
  523  * For now, system interrupts are disabled.
  524  * So this is just called from a callout in uart_core.c
  525  * to poll various state.
  526  */
  527 static int
  528 ar933x_bus_ipend(struct uart_softc *sc)
  529 {
  530         struct ar933x_softc *u = (struct ar933x_softc *)sc;
  531         struct uart_bas *bas = &sc->sc_bas;
  532         int ipend = 0;
  533         uint32_t isr;
  534 
  535         uart_lock(sc->sc_hwmtx);
  536 
  537         /*
  538          * Fetch/ACK the ISR status.
  539          */
  540         isr = ar933x_getreg(bas, AR933X_UART_INT_REG);
  541         ar933x_setreg(bas, AR933X_UART_INT_REG, isr);
  542         uart_barrier(bas);
  543 
  544         /*
  545          * RX ready - notify upper layer.
  546          */
  547         if (isr & AR933X_UART_INT_RX_VALID) {
  548                 ipend |= SER_INT_RXREADY;
  549         }
  550 
  551         /*
  552          * If we get this interrupt, we should disable
  553          * it from the interrupt mask and inform the uart
  554          * driver appropriately.
  555          *
  556          * We can't keep setting SER_INT_TXIDLE or SER_INT_SIGCHG
  557          * all the time or IO stops working.  So we will always
  558          * clear this interrupt if we get it, then we only signal
  559          * the upper layer if we were doing active TX in the
  560          * first place.
  561          *
  562          * Also, the name is misleading.  This actually means
  563          * "the FIFO is almost empty."  So if we just write some
  564          * more data to the FIFO without checking whether it can
  565          * take said data, we'll overflow the thing.
  566          *
  567          * Unfortunately the FreeBSD uart device has no concept of
  568          * partial UART writes - it expects that the whole buffer
  569          * is written to the hardware.  Thus for now, ar933x_bus_transmit()
  570          * will wait for the FIFO to finish draining before it pushes
  571          * more frames into it.
  572          */
  573         if (isr & AR933X_UART_INT_TX_EMPTY) {
  574                 /*
  575                  * Update u_ier to disable TX notifications; update hardware
  576                  */
  577                 u->u_ier &= ~AR933X_UART_INT_TX_EMPTY;
  578                 ar933x_setreg(bas, AR933X_UART_INT_EN_REG, u->u_ier);
  579                 uart_barrier(bas);
  580         }
  581 
  582         /*
  583          * Only signal TX idle if we're not busy transmitting.
  584          */
  585         if (sc->sc_txbusy) {
  586                 if (isr & AR933X_UART_INT_TX_EMPTY) {
  587                         ipend |= SER_INT_TXIDLE;
  588                 } else {
  589                         ipend |= SER_INT_SIGCHG;
  590                 }
  591         }
  592 
  593         uart_unlock(sc->sc_hwmtx);
  594         return (ipend);
  595 }
  596 
  597 static int
  598 ar933x_bus_param(struct uart_softc *sc, int baudrate, int databits,
  599     int stopbits, int parity)
  600 {
  601         struct uart_bas *bas;
  602         int error;
  603 
  604         bas = &sc->sc_bas;
  605         uart_lock(sc->sc_hwmtx);
  606         error = ar933x_param(bas, baudrate, databits, stopbits, parity);
  607         uart_unlock(sc->sc_hwmtx);
  608         return (error);
  609 }
  610 
  611 static int
  612 ar933x_bus_probe(struct uart_softc *sc)
  613 {
  614         struct uart_bas *bas;
  615         int error;
  616 
  617         bas = &sc->sc_bas;
  618 
  619         error = ar933x_probe(bas);
  620         if (error)
  621                 return (error);
  622 
  623         /* Reset FIFOs. */
  624         ar933x_drain(bas, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER);
  625 
  626         /* XXX TODO: actually find out what the FIFO depth is! */
  627         sc->sc_rxfifosz = 16;
  628         sc->sc_txfifosz = 16;
  629 
  630         return (0);
  631 }
  632 
  633 static int
  634 ar933x_bus_receive(struct uart_softc *sc)
  635 {
  636         struct uart_bas *bas = &sc->sc_bas;
  637         int xc;
  638 
  639         uart_lock(sc->sc_hwmtx);
  640 
  641         /* Loop over until we are full, or no data is available */
  642         while (ar933x_rxready(bas)) {
  643                 if (uart_rx_full(sc)) {
  644                         sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
  645                         break;
  646                 }
  647 
  648                 /* Read the top of the RX FIFO */
  649                 xc = ar933x_getreg(bas, AR933X_UART_DATA_REG) & 0xff;
  650 
  651                 /* Remove that entry from said RX FIFO */
  652                 ar933x_setreg(bas, AR933X_UART_DATA_REG,
  653                     AR933X_UART_DATA_RX_CSR);
  654                 uart_barrier(bas);
  655 
  656                 /* XXX frame, parity error */
  657                 uart_rx_put(sc, xc);
  658         }
  659 
  660         /*
  661          * XXX TODO: Discard everything left in the Rx FIFO?
  662          * XXX only if we've hit an overrun condition?
  663          */
  664 
  665         uart_unlock(sc->sc_hwmtx);
  666 
  667         return (0);
  668 }
  669 
  670 static int
  671 ar933x_bus_setsig(struct uart_softc *sc, int sig)
  672 {
  673 #if 0
  674         struct ar933x_softc *ns8250 = (struct ar933x_softc*)sc;
  675         struct uart_bas *bas;
  676         uint32_t new, old;
  677 
  678         bas = &sc->sc_bas;
  679         do {
  680                 old = sc->sc_hwsig;
  681                 new = old;
  682                 if (sig & SER_DDTR) {
  683                         SIGCHG(sig & SER_DTR, new, SER_DTR,
  684                             SER_DDTR);
  685                 }
  686                 if (sig & SER_DRTS) {
  687                         SIGCHG(sig & SER_RTS, new, SER_RTS,
  688                             SER_DRTS);
  689                 }
  690         } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
  691         uart_lock(sc->sc_hwmtx);
  692         ns8250->mcr &= ~(MCR_DTR|MCR_RTS);
  693         if (new & SER_DTR)
  694                 ns8250->mcr |= MCR_DTR;
  695         if (new & SER_RTS)
  696                 ns8250->mcr |= MCR_RTS;
  697         uart_setreg(bas, REG_MCR, ns8250->mcr);
  698         uart_barrier(bas);
  699         uart_unlock(sc->sc_hwmtx);
  700 #endif
  701         return (0);
  702 }
  703 
  704 /*
  705  * Write the current transmit buffer to the TX FIFO.
  706  *
  707  * Unfortunately the FreeBSD uart device has no concept of
  708  * partial UART writes - it expects that the whole buffer
  709  * is written to the hardware.  Thus for now, this will wait for
  710  * the FIFO to finish draining before it pushes more frames into it.
  711  *
  712  * If non-blocking operation is truely needed here, either
  713  * the FreeBSD uart device will need to handle partial writes
  714  * in xxx_bus_transmit(), or we'll need to do TX FIFO buffering
  715  * of our own here.
  716  */
  717 static int
  718 ar933x_bus_transmit(struct uart_softc *sc)
  719 {
  720         struct uart_bas *bas = &sc->sc_bas;
  721         struct ar933x_softc *u = (struct ar933x_softc *)sc;
  722         int i;
  723 
  724         uart_lock(sc->sc_hwmtx);
  725 
  726         /* Wait for the FIFO to be clear - see above */
  727         while (ar933x_getreg(bas, AR933X_UART_CS_REG) &
  728             AR933X_UART_CS_TX_BUSY)
  729                 ;
  730 
  731         /*
  732          * Write some data!
  733          */
  734         for (i = 0; i < sc->sc_txdatasz; i++) {
  735                 /* Write the TX data */
  736                 ar933x_setreg(bas, AR933X_UART_DATA_REG,
  737                     (sc->sc_txbuf[i] & 0xff) | AR933X_UART_DATA_TX_CSR);
  738                 uart_barrier(bas);
  739         }
  740 
  741         /*
  742          * Now that we're transmitting, get interrupt notification
  743          * when the FIFO is (almost) empty - see above.
  744          */
  745         u->u_ier |= AR933X_UART_INT_TX_EMPTY;
  746         ar933x_setreg(bas, AR933X_UART_INT_EN_REG, u->u_ier);
  747         uart_barrier(bas);
  748 
  749         /*
  750          * Inform the upper layer that we are presently transmitting
  751          * data to the hardware; this will be cleared when the
  752          * TXIDLE interrupt occurs.
  753          */
  754         sc->sc_txbusy = 1;
  755         uart_unlock(sc->sc_hwmtx);
  756 
  757         return (0);
  758 }
  759 
  760 static void
  761 ar933x_bus_grab(struct uart_softc *sc)
  762 {
  763         struct uart_bas *bas = &sc->sc_bas;
  764         uint32_t reg;
  765 
  766         /* Disable the host interrupt now */
  767         uart_lock(sc->sc_hwmtx);
  768         reg = ar933x_getreg(bas, AR933X_UART_CS_REG);
  769         reg &= ~AR933X_UART_CS_HOST_INT_EN;
  770         ar933x_setreg(bas, AR933X_UART_CS_REG, reg);
  771         uart_unlock(sc->sc_hwmtx);
  772 }
  773 
  774 static void
  775 ar933x_bus_ungrab(struct uart_softc *sc)
  776 {
  777         struct uart_bas *bas = &sc->sc_bas;
  778         uint32_t reg;
  779 
  780         /* Enable the host interrupt now */
  781         uart_lock(sc->sc_hwmtx);
  782         reg = ar933x_getreg(bas, AR933X_UART_CS_REG);
  783         reg |= AR933X_UART_CS_HOST_INT_EN;
  784         ar933x_setreg(bas, AR933X_UART_CS_REG, reg);
  785         uart_unlock(sc->sc_hwmtx);
  786 }

Cache object: 642bb8ac0aae4a6f6c0893f05a753b88


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