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


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

FreeBSD/Linux Kernel Cross Reference
sys/dev/uart/uart_dev_imx.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) 2012 The FreeBSD Foundation
    5  *
    6  * This software was developed by Oleksandr Rybalko under sponsorship
    7  * from the FreeBSD Foundation.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1.   Redistributions of source code must retain the above copyright
   13  *      notice, this list of conditions and the following disclaimer.
   14  * 2.   Redistributions in binary form must reproduce the above copyright
   15  *      notice, this list of conditions and the following disclaimer in the
   16  *      documentation and/or other materials provided with the distribution.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD$");
   33 
   34 #include "opt_ddb.h"
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/bus.h>
   39 #include <sys/conf.h>
   40 #include <sys/kdb.h>
   41 #include <machine/bus.h>
   42 
   43 #include <dev/uart/uart.h>
   44 #include <dev/uart/uart_cpu.h>
   45 #include <dev/uart/uart_cpu_fdt.h>
   46 #include <dev/uart/uart_bus.h>
   47 #include <dev/uart/uart_dev_imx.h>
   48 
   49 #if defined(__aarch64__)
   50 #define IMX_ENABLE_CLOCKS
   51 #endif
   52 
   53 #ifdef IMX_ENABLE_CLOCKS
   54 #include <dev/extres/clk/clk.h>
   55 #endif
   56 
   57 #include "uart_if.h"
   58 
   59 #include <arm/freescale/imx/imx_ccmvar.h>
   60 
   61 /*
   62  * The hardare FIFOs are 32 bytes.  We want an interrupt when there are 24 bytes
   63  * available to read or space for 24 more bytes to write.  While 8 bytes of
   64  * slack before over/underrun might seem excessive, the hardware can run at
   65  * 5mbps, which means 2uS per char, so at full speed 8 bytes provides only 16uS
   66  * to get into the interrupt handler and service the fifo.
   67  */
   68 #define IMX_FIFOSZ              32
   69 #define IMX_RXFIFO_LEVEL        24
   70 #define IMX_TXFIFO_LEVEL        24
   71 
   72 /*
   73  * Low-level UART interface.
   74  */
   75 static int imx_uart_probe(struct uart_bas *bas);
   76 static void imx_uart_init(struct uart_bas *bas, int, int, int, int);
   77 static void imx_uart_term(struct uart_bas *bas);
   78 static void imx_uart_putc(struct uart_bas *bas, int);
   79 static int imx_uart_rxready(struct uart_bas *bas);
   80 static int imx_uart_getc(struct uart_bas *bas, struct mtx *);
   81 
   82 static struct uart_ops uart_imx_uart_ops = {
   83         .probe = imx_uart_probe,
   84         .init = imx_uart_init,
   85         .term = imx_uart_term,
   86         .putc = imx_uart_putc,
   87         .rxready = imx_uart_rxready,
   88         .getc = imx_uart_getc,
   89 };
   90 
   91 #if 0 /* Handy when debugging. */
   92 static void
   93 dumpregs(struct uart_bas *bas, const char * msg)
   94 {
   95 
   96         if (!bootverbose)
   97                 return;
   98         printf("%s bsh 0x%08lx UCR1 0x%08x UCR2 0x%08x "
   99                 "UCR3 0x%08x UCR4 0x%08x USR1 0x%08x USR2 0x%08x\n",
  100             msg, bas->bsh,
  101             GETREG(bas, REG(UCR1)), GETREG(bas, REG(UCR2)), 
  102             GETREG(bas, REG(UCR3)), GETREG(bas, REG(UCR4)),
  103             GETREG(bas, REG(USR1)), GETREG(bas, REG(USR2)));
  104 }
  105 #endif
  106 
  107 static int
  108 imx_uart_probe(struct uart_bas *bas)
  109 {
  110 
  111         return (0);
  112 }
  113 
  114 static u_int
  115 imx_uart_getbaud(struct uart_bas *bas)
  116 {
  117         uint32_t rate, ubir, ubmr;
  118         u_int baud, blo, bhi, i;
  119         static const u_int predivs[] = {6, 5, 4, 3, 2, 1, 7, 1};
  120         static const u_int std_rates[] = {
  121                 9600, 14400, 19200, 38400, 57600, 115200, 230400, 460800, 921600
  122         };
  123 
  124         /*
  125          * Get the baud rate the hardware is programmed for, then search the
  126          * table of standard baud rates for a number that's within 3% of the
  127          * actual rate the hardware is programmed for.  It's more comforting to
  128          * see that your console is running at 115200 than 114942.  Note that
  129          * here we cannot make a simplifying assumption that the predivider and
  130          * numerator are 1 (like we do when setting the baud rate), because we
  131          * don't know what u-boot might have set up.
  132          */
  133         i = (GETREG(bas, REG(UFCR)) & IMXUART_UFCR_RFDIV_MASK) >>
  134             IMXUART_UFCR_RFDIV_SHIFT;
  135         rate = bas->rclk / predivs[i];
  136         ubir = GETREG(bas, REG(UBIR)) + 1;
  137         ubmr = GETREG(bas, REG(UBMR)) + 1;
  138         baud = ((rate / 16 ) * ubir) / ubmr;
  139 
  140         blo = (baud * 100) / 103;
  141         bhi = (baud * 100) / 97;
  142         for (i = 0; i < nitems(std_rates); i++) {
  143                 rate = std_rates[i];
  144                 if (rate >= blo && rate <= bhi) {
  145                         baud = rate;
  146                         break;
  147                 }
  148         }
  149 
  150         return (baud);
  151 }
  152 
  153 static void
  154 imx_uart_init(struct uart_bas *bas, int baudrate, int databits, 
  155     int stopbits, int parity)
  156 {
  157         uint32_t baseclk, reg;
  158 
  159         /* Enable the device and the RX/TX channels. */
  160         SET(bas, REG(UCR1), FLD(UCR1, UARTEN));
  161         SET(bas, REG(UCR2), FLD(UCR2, RXEN) | FLD(UCR2, TXEN));
  162 
  163         if (databits == 7)
  164                 DIS(bas, UCR2, WS);
  165         else
  166                 ENA(bas, UCR2, WS);
  167 
  168         if (stopbits == 2)
  169                 ENA(bas, UCR2, STPB);
  170         else
  171                 DIS(bas, UCR2, STPB);
  172 
  173         switch (parity) {
  174         case UART_PARITY_ODD:
  175                 DIS(bas, UCR2, PROE);
  176                 ENA(bas, UCR2, PREN);
  177                 break;
  178         case UART_PARITY_EVEN:
  179                 ENA(bas, UCR2, PROE);
  180                 ENA(bas, UCR2, PREN);
  181                 break;
  182         case UART_PARITY_MARK:
  183         case UART_PARITY_SPACE:
  184                 /* FALLTHROUGH: Hardware doesn't support mark/space. */
  185         case UART_PARITY_NONE:
  186         default:
  187                 DIS(bas, UCR2, PREN);
  188                 break;
  189         }
  190 
  191         /*
  192          * The hardware has an extremely flexible baud clock: it allows setting
  193          * both the numerator and denominator of the divider, as well as a
  194          * separate pre-divider.  We simplify the problem of coming up with a
  195          * workable pair of numbers by assuming a pre-divider and numerator of
  196          * one because our base clock is so fast we can reach virtually any
  197          * reasonable speed with a simple divisor.  The numerator value actually
  198          * includes the 16x over-sampling (so a value of 16 means divide by 1);
  199          * the register value is the numerator-1, so we have a hard-coded 15.
  200          * Note that a quirk of the hardware requires that both UBIR and UBMR be
  201          * set back to back in order for the change to take effect.
  202          */
  203         if ((baudrate > 0) && (bas->rclk != 0)) {
  204                 baseclk = bas->rclk;
  205                 reg = GETREG(bas, REG(UFCR));
  206                 reg = (reg & ~IMXUART_UFCR_RFDIV_MASK) | IMXUART_UFCR_RFDIV_DIV1;
  207                 SETREG(bas, REG(UFCR), reg);
  208                 SETREG(bas, REG(UBIR), 15);
  209                 SETREG(bas, REG(UBMR), (baseclk / baudrate) - 1);
  210         }
  211 
  212         /*
  213          * Program the tx lowater and rx hiwater levels at which fifo-service
  214          * interrupts are signaled.  The tx value is interpetted as "when there
  215          * are only this many bytes remaining" (not "this many free").
  216          */
  217         reg = GETREG(bas, REG(UFCR));
  218         reg &= ~(IMXUART_UFCR_TXTL_MASK | IMXUART_UFCR_RXTL_MASK);
  219         reg |= (IMX_FIFOSZ - IMX_TXFIFO_LEVEL) << IMXUART_UFCR_TXTL_SHIFT;
  220         reg |= IMX_RXFIFO_LEVEL << IMXUART_UFCR_RXTL_SHIFT;
  221         SETREG(bas, REG(UFCR), reg);
  222 }
  223 
  224 static void
  225 imx_uart_term(struct uart_bas *bas)
  226 {
  227 
  228 }
  229 
  230 static void
  231 imx_uart_putc(struct uart_bas *bas, int c)
  232 {
  233 
  234         while (!(IS(bas, USR1, TRDY)))
  235                 ;
  236         SETREG(bas, REG(UTXD), c);
  237 }
  238 
  239 static int
  240 imx_uart_rxready(struct uart_bas *bas)
  241 {
  242 
  243         return ((IS(bas, USR2, RDR)) ? 1 : 0);
  244 }
  245 
  246 static int
  247 imx_uart_getc(struct uart_bas *bas, struct mtx *hwmtx)
  248 {
  249         int c;
  250 
  251         uart_lock(hwmtx);
  252         while (!(IS(bas, USR2, RDR)))
  253                 ;
  254 
  255         c = GETREG(bas, REG(URXD));
  256         uart_unlock(hwmtx);
  257 #if defined(KDB)
  258         if (c & FLD(URXD, BRK)) {
  259                 if (kdb_break())
  260                         return (0);
  261         }
  262 #endif
  263         return (c & 0xff);
  264 }
  265 
  266 /*
  267  * High-level UART interface.
  268  */
  269 struct imx_uart_softc {
  270         struct uart_softc base;
  271 };
  272 
  273 static int imx_uart_bus_attach(struct uart_softc *);
  274 static int imx_uart_bus_detach(struct uart_softc *);
  275 static int imx_uart_bus_flush(struct uart_softc *, int);
  276 static int imx_uart_bus_getsig(struct uart_softc *);
  277 static int imx_uart_bus_ioctl(struct uart_softc *, int, intptr_t);
  278 static int imx_uart_bus_ipend(struct uart_softc *);
  279 static int imx_uart_bus_param(struct uart_softc *, int, int, int, int);
  280 static int imx_uart_bus_probe(struct uart_softc *);
  281 static int imx_uart_bus_receive(struct uart_softc *);
  282 static int imx_uart_bus_setsig(struct uart_softc *, int);
  283 static int imx_uart_bus_transmit(struct uart_softc *);
  284 static void imx_uart_bus_grab(struct uart_softc *);
  285 static void imx_uart_bus_ungrab(struct uart_softc *);
  286 
  287 static kobj_method_t imx_uart_methods[] = {
  288         KOBJMETHOD(uart_attach,         imx_uart_bus_attach),
  289         KOBJMETHOD(uart_detach,         imx_uart_bus_detach),
  290         KOBJMETHOD(uart_flush,          imx_uart_bus_flush),
  291         KOBJMETHOD(uart_getsig,         imx_uart_bus_getsig),
  292         KOBJMETHOD(uart_ioctl,          imx_uart_bus_ioctl),
  293         KOBJMETHOD(uart_ipend,          imx_uart_bus_ipend),
  294         KOBJMETHOD(uart_param,          imx_uart_bus_param),
  295         KOBJMETHOD(uart_probe,          imx_uart_bus_probe),
  296         KOBJMETHOD(uart_receive,        imx_uart_bus_receive),
  297         KOBJMETHOD(uart_setsig,         imx_uart_bus_setsig),
  298         KOBJMETHOD(uart_transmit,       imx_uart_bus_transmit),
  299         KOBJMETHOD(uart_grab,           imx_uart_bus_grab),
  300         KOBJMETHOD(uart_ungrab,         imx_uart_bus_ungrab),
  301         { 0, 0 }
  302 };
  303 
  304 static struct uart_class uart_imx_class = {
  305         "imx",
  306         imx_uart_methods,
  307         sizeof(struct imx_uart_softc),
  308         .uc_ops = &uart_imx_uart_ops,
  309         .uc_range = 0x100,
  310         .uc_rclk = 24000000, /* TODO: get value from CCM */
  311         .uc_rshift = 0
  312 };
  313 
  314 static struct ofw_compat_data compat_data[] = {
  315         {"fsl,imx6q-uart",      (uintptr_t)&uart_imx_class},
  316         {"fsl,imx53-uart",      (uintptr_t)&uart_imx_class},
  317         {"fsl,imx51-uart",      (uintptr_t)&uart_imx_class},
  318         {"fsl,imx31-uart",      (uintptr_t)&uart_imx_class},
  319         {"fsl,imx27-uart",      (uintptr_t)&uart_imx_class},
  320         {"fsl,imx25-uart",      (uintptr_t)&uart_imx_class},
  321         {"fsl,imx21-uart",      (uintptr_t)&uart_imx_class},
  322         {NULL,                  (uintptr_t)NULL},
  323 };
  324 UART_FDT_CLASS_AND_DEVICE(compat_data);
  325 
  326 #define SIGCHG(c, i, s, d)                              \
  327         if (c) {                                        \
  328                 i |= (i & s) ? s : s | d;               \
  329         } else {                                        \
  330                 i = (i & s) ? (i & ~s) | d : i;         \
  331         }
  332 
  333 #ifdef IMX_ENABLE_CLOCKS
  334 static int
  335 imx_uart_setup_clocks(struct uart_softc *sc)
  336 {
  337         struct uart_bas *bas;
  338         clk_t ipgclk, perclk;
  339         uint64_t freq;
  340         int error;
  341 
  342         bas = &sc->sc_bas;
  343 
  344         if (clk_get_by_ofw_name(sc->sc_dev, 0, "ipg", &ipgclk) != 0)
  345                 return (ENOENT);
  346 
  347         if (clk_get_by_ofw_name(sc->sc_dev, 0, "per", &perclk) != 0) {
  348                 return (ENOENT);
  349         }
  350 
  351         error = clk_enable(ipgclk);
  352         if (error != 0) {
  353                 device_printf(sc->sc_dev, "cannot enable ipg clock\n");
  354                 return (error);
  355         }
  356 
  357         error = clk_get_freq(perclk, &freq);
  358         if (error != 0) {
  359                 device_printf(sc->sc_dev, "cannot get frequency\n");
  360                 return (error);
  361         }
  362 
  363         bas->rclk = (uint32_t)freq;
  364 
  365         return (0);
  366 }
  367 #endif
  368 
  369 static int
  370 imx_uart_bus_attach(struct uart_softc *sc)
  371 {
  372         struct uart_bas *bas;
  373         struct uart_devinfo *di;
  374 
  375         bas = &sc->sc_bas;
  376 
  377 #ifdef IMX_ENABLE_CLOCKS
  378         int error = imx_uart_setup_clocks(sc);
  379         if (error)
  380                 return (error);
  381 #else
  382         bas->rclk = imx_ccm_uart_hz();
  383 #endif
  384 
  385         if (sc->sc_sysdev != NULL) {
  386                 di = sc->sc_sysdev;
  387                 imx_uart_init(bas, di->baudrate, di->databits, di->stopbits,
  388                     di->parity);
  389         } else {
  390                 imx_uart_init(bas, 115200, 8, 1, 0);
  391         }
  392 
  393         (void)imx_uart_bus_getsig(sc);
  394 
  395         /* Clear all pending interrupts. */
  396         SETREG(bas, REG(USR1), 0xffff);
  397         SETREG(bas, REG(USR2), 0xffff);
  398 
  399         DIS(bas, UCR4, DREN);
  400         ENA(bas, UCR1, RRDYEN);
  401         DIS(bas, UCR1, IDEN);
  402         DIS(bas, UCR3, RXDSEN);
  403         ENA(bas, UCR2, ATEN);
  404         DIS(bas, UCR1, TXMPTYEN);
  405         DIS(bas, UCR1, TRDYEN);
  406         DIS(bas, UCR4, TCEN);
  407         DIS(bas, UCR4, OREN);
  408         ENA(bas, UCR4, BKEN);
  409         DIS(bas, UCR4, WKEN);
  410         DIS(bas, UCR1, ADEN);
  411         DIS(bas, UCR3, ACIEN);
  412         DIS(bas, UCR2, ESCI);
  413         DIS(bas, UCR4, ENIRI);
  414         DIS(bas, UCR3, AIRINTEN);
  415         DIS(bas, UCR3, AWAKEN);
  416         DIS(bas, UCR3, FRAERREN);
  417         DIS(bas, UCR3, PARERREN);
  418         DIS(bas, UCR1, RTSDEN);
  419         DIS(bas, UCR2, RTSEN);
  420         DIS(bas, UCR3, DTREN);
  421         DIS(bas, UCR3, RI);
  422         DIS(bas, UCR3, DCD);
  423         DIS(bas, UCR3, DTRDEN);
  424         ENA(bas, UCR2, IRTS);
  425         ENA(bas, UCR3, RXDMUXSEL);
  426 
  427         return (0);
  428 }
  429 
  430 static int
  431 imx_uart_bus_detach(struct uart_softc *sc)
  432 {
  433 
  434         SETREG(&sc->sc_bas, REG(UCR4), 0);
  435 
  436         return (0);
  437 }
  438 
  439 static int
  440 imx_uart_bus_flush(struct uart_softc *sc, int what)
  441 {
  442 
  443         /* TODO */
  444         return (0);
  445 }
  446 
  447 static int
  448 imx_uart_bus_getsig(struct uart_softc *sc)
  449 {
  450         uint32_t new, old, sig;
  451         uint8_t bes;
  452 
  453         do {
  454                 old = sc->sc_hwsig;
  455                 sig = old;
  456                 uart_lock(sc->sc_hwmtx);
  457                 bes = GETREG(&sc->sc_bas, REG(USR2));
  458                 uart_unlock(sc->sc_hwmtx);
  459                 /* XXX: chip can show delta */
  460                 SIGCHG(bes & FLD(USR2, DCDIN), sig, SER_DCD, SER_DDCD);
  461                 new = sig & ~SER_MASK_DELTA;
  462         } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
  463 
  464         return (sig);
  465 }
  466 
  467 static int
  468 imx_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
  469 {
  470         struct uart_bas *bas;
  471         int error;
  472 
  473         bas = &sc->sc_bas;
  474         error = 0;
  475         uart_lock(sc->sc_hwmtx);
  476         switch (request) {
  477         case UART_IOCTL_BREAK:
  478                 /* TODO */
  479                 break;
  480         case UART_IOCTL_BAUD:
  481                 *(u_int*)data = imx_uart_getbaud(bas);
  482                 break;
  483         default:
  484                 error = EINVAL;
  485                 break;
  486         }
  487         uart_unlock(sc->sc_hwmtx);
  488 
  489         return (error);
  490 }
  491 
  492 static int
  493 imx_uart_bus_ipend(struct uart_softc *sc)
  494 {
  495         struct uart_bas *bas;
  496         int ipend;
  497         uint32_t usr1, usr2;
  498         uint32_t ucr1, ucr2, ucr4;
  499 
  500         bas = &sc->sc_bas;
  501         ipend = 0;
  502 
  503         uart_lock(sc->sc_hwmtx);
  504 
  505         /* Read pending interrupts */
  506         usr1 = GETREG(bas, REG(USR1));
  507         usr2 = GETREG(bas, REG(USR2));
  508         /* ACK interrupts */
  509         SETREG(bas, REG(USR1), usr1);
  510         SETREG(bas, REG(USR2), usr2);
  511 
  512         ucr1 = GETREG(bas, REG(UCR1));
  513         ucr2 = GETREG(bas, REG(UCR2));
  514         ucr4 = GETREG(bas, REG(UCR4));
  515 
  516         /* If we have reached tx low-water, we can tx some more now. */
  517         if ((usr1 & FLD(USR1, TRDY)) && (ucr1 & FLD(UCR1, TRDYEN))) {
  518                 DIS(bas, UCR1, TRDYEN);
  519                 ipend |= SER_INT_TXIDLE;
  520         }
  521 
  522         /*
  523          * If we have reached the rx high-water, or if there are bytes in the rx
  524          * fifo and no new data has arrived for 8 character periods (aging
  525          * timer), we have input data to process.
  526          */
  527         if (((usr1 & FLD(USR1, RRDY)) && (ucr1 & FLD(UCR1, RRDYEN))) || 
  528             ((usr1 & FLD(USR1, AGTIM)) && (ucr2 & FLD(UCR2, ATEN)))) {
  529                 DIS(bas, UCR1, RRDYEN);
  530                 DIS(bas, UCR2, ATEN);
  531                 ipend |= SER_INT_RXREADY;
  532         }
  533 
  534         /* A break can come in at any time, it never gets disabled. */
  535         if ((usr2 & FLD(USR2, BRCD)) && (ucr4 & FLD(UCR4, BKEN)))
  536                 ipend |= SER_INT_BREAK;
  537 
  538         uart_unlock(sc->sc_hwmtx);
  539 
  540         return (ipend);
  541 }
  542 
  543 static int
  544 imx_uart_bus_param(struct uart_softc *sc, int baudrate, int databits,
  545     int stopbits, int parity)
  546 {
  547 
  548         uart_lock(sc->sc_hwmtx);
  549         imx_uart_init(&sc->sc_bas, baudrate, databits, stopbits, parity);
  550         uart_unlock(sc->sc_hwmtx);
  551         return (0);
  552 }
  553 
  554 static int
  555 imx_uart_bus_probe(struct uart_softc *sc)
  556 {
  557         int error;
  558 
  559         error = imx_uart_probe(&sc->sc_bas);
  560         if (error)
  561                 return (error);
  562 
  563         /*
  564          * On input we can read up to the full fifo size at once.  On output, we
  565          * want to write only as much as the programmed tx low water level,
  566          * because that's all we can be certain we have room for in the fifo
  567          * when we get a tx-ready interrupt.
  568          */
  569         sc->sc_rxfifosz = IMX_FIFOSZ;
  570         sc->sc_txfifosz = IMX_TXFIFO_LEVEL;
  571 
  572         device_set_desc(sc->sc_dev, "Freescale i.MX UART");
  573         return (0);
  574 }
  575 
  576 static int
  577 imx_uart_bus_receive(struct uart_softc *sc)
  578 {
  579         struct uart_bas *bas;
  580         int xc, out;
  581 
  582         bas = &sc->sc_bas;
  583         uart_lock(sc->sc_hwmtx);
  584 
  585         /*
  586          * Empty the rx fifo.  We get the RRDY interrupt when IMX_RXFIFO_LEVEL
  587          * (the rx high-water level) is reached, but we set sc_rxfifosz to the
  588          * full hardware fifo size, so we can safely process however much is
  589          * there, not just the highwater size.
  590          */
  591         while (IS(bas, USR2, RDR)) {
  592                 if (uart_rx_full(sc)) {
  593                         /* No space left in input buffer */
  594                         sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
  595                         break;
  596                 }
  597                 xc = GETREG(bas, REG(URXD));
  598                 out = xc & 0x000000ff;
  599                 if (xc & FLD(URXD, FRMERR))
  600                         out |= UART_STAT_FRAMERR;
  601                 if (xc & FLD(URXD, PRERR))
  602                         out |= UART_STAT_PARERR;
  603                 if (xc & FLD(URXD, OVRRUN))
  604                         out |= UART_STAT_OVERRUN;
  605                 if (xc & FLD(URXD, BRK))
  606                         out |= UART_STAT_BREAK;
  607 
  608                 uart_rx_put(sc, out);
  609         }
  610         ENA(bas, UCR1, RRDYEN);
  611         ENA(bas, UCR2, ATEN);
  612 
  613         uart_unlock(sc->sc_hwmtx);
  614         return (0);
  615 }
  616 
  617 static int
  618 imx_uart_bus_setsig(struct uart_softc *sc, int sig)
  619 {
  620 
  621         return (0);
  622 }
  623 
  624 static int
  625 imx_uart_bus_transmit(struct uart_softc *sc)
  626 {
  627         struct uart_bas *bas = &sc->sc_bas;
  628         int i;
  629 
  630         bas = &sc->sc_bas;
  631         uart_lock(sc->sc_hwmtx);
  632 
  633         /*
  634          * Fill the tx fifo.  The uart core puts at most IMX_TXFIFO_LEVEL bytes
  635          * into the txbuf (because that's what sc_txfifosz is set to), and
  636          * because we got the TRDY (low-water reached) interrupt we know at
  637          * least that much space is available in the fifo.
  638          */
  639         for (i = 0; i < sc->sc_txdatasz; i++) {
  640                 SETREG(bas, REG(UTXD), sc->sc_txbuf[i] & 0xff);
  641         }
  642         sc->sc_txbusy = 1;
  643         ENA(bas, UCR1, TRDYEN);
  644 
  645         uart_unlock(sc->sc_hwmtx);
  646 
  647         return (0);
  648 }
  649 
  650 static void
  651 imx_uart_bus_grab(struct uart_softc *sc)
  652 {
  653         struct uart_bas *bas = &sc->sc_bas;
  654 
  655         bas = &sc->sc_bas;
  656         uart_lock(sc->sc_hwmtx);
  657         DIS(bas, UCR1, RRDYEN);
  658         DIS(bas, UCR2, ATEN);
  659         uart_unlock(sc->sc_hwmtx);
  660 }
  661 
  662 static void
  663 imx_uart_bus_ungrab(struct uart_softc *sc)
  664 {
  665         struct uart_bas *bas = &sc->sc_bas;
  666 
  667         bas = &sc->sc_bas;
  668         uart_lock(sc->sc_hwmtx);
  669         ENA(bas, UCR1, RRDYEN);
  670         ENA(bas, UCR2, ATEN);
  671         uart_unlock(sc->sc_hwmtx);
  672 }

Cache object: 121fc2303f398643378d1913f1fbc03b


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