Author: ian
Date: Sat May 23 19:27:04 2015
New Revision: 283321
URL: https://svnweb.freebsd.org/changeset/base/283321

Log:
  MFC r272399, r272602, r274451, r274452:
  
    Add uart driver for Qualcomm MSM 7000/8000 series chips.
    It is working on IFC6410 board which has Qualcomm Snapdragon SoC.
  
    Use documented compat string for msm uart.
  
    Make PL011 UART to wait on putc only when TX FIFO is full
  
    Make uart_bus_fdt a decendant of ofwbus

Added:
  stable/10/sys/dev/uart/uart_dev_msm.c
     - copied unchanged from r272399, head/sys/dev/uart/uart_dev_msm.c
  stable/10/sys/dev/uart/uart_dev_msm.h
     - copied unchanged from r272399, head/sys/dev/uart/uart_dev_msm.h
Modified:
  stable/10/sys/dev/uart/uart.h
  stable/10/sys/dev/uart/uart_bus_fdt.c
  stable/10/sys/dev/uart/uart_dev_pl011.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/uart/uart.h
==============================================================================
--- stable/10/sys/dev/uart/uart.h       Sat May 23 19:09:04 2015        
(r283320)
+++ stable/10/sys/dev/uart/uart.h       Sat May 23 19:27:04 2015        
(r283321)
@@ -65,6 +65,7 @@ struct uart_bas {
 struct uart_class;
 
 extern struct uart_class uart_imx_class __attribute__((weak));
+extern struct uart_class uart_msm_class __attribute__((weak));
 extern struct uart_class uart_ns8250_class __attribute__((weak));
 extern struct uart_class uart_quicc_class __attribute__((weak));
 extern struct uart_class uart_s3c2410_class __attribute__((weak));

Modified: stable/10/sys/dev/uart/uart_bus_fdt.c
==============================================================================
--- stable/10/sys/dev/uart/uart_bus_fdt.c       Sat May 23 19:09:04 2015        
(r283320)
+++ stable/10/sys/dev/uart/uart_bus_fdt.c       Sat May 23 19:27:04 2015        
(r283321)
@@ -84,6 +84,7 @@ static struct ofw_compat_data compat_dat
        {"fsl,imx21-uart",      (uintptr_t)&uart_imx_class},
        {"fsl,mvf600-uart",     (uintptr_t)&uart_vybrid_class},
        {"lpc,uart",            (uintptr_t)&uart_lpc_class},
+       {"qcom,msm-uartdm",     (uintptr_t)&uart_msm_class},
        {"ti,ns16550",          (uintptr_t)&uart_ti8250_class},
        {"ns16550",             (uintptr_t)&uart_ns8250_class},
        {NULL,                  (uintptr_t)NULL},
@@ -156,3 +157,4 @@ uart_fdt_probe(device_t dev)
 }
 
 DRIVER_MODULE(uart, simplebus, uart_fdt_driver, uart_devclass, 0, 0);
+DRIVER_MODULE(uart, ofwbus, uart_fdt_driver, uart_devclass, 0, 0);

Copied: stable/10/sys/dev/uart/uart_dev_msm.c (from r272399, 
head/sys/dev/uart/uart_dev_msm.c)
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ stable/10/sys/dev/uart/uart_dev_msm.c       Sat May 23 19:27:04 2015        
(r283321, copy of r272399, head/sys/dev/uart/uart_dev_msm.c)
@@ -0,0 +1,568 @@
+/*-
+ * Copyright (c) 2014 Ganbold Tsagaankhuu <ganb...@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Qualcomm MSM7K/8K uart driver */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_ddb.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kdb.h>
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_bus.h>
+#include <dev/uart/uart_dev_msm.h>
+
+#include "uart_if.h"
+
+#define        DEF_CLK         7372800
+
+#define        GETREG(bas, reg)        \
+    bus_space_read_4((bas)->bst, (bas)->bsh, (reg))
+#define        SETREG(bas, reg, value) \
+    bus_space_write_4((bas)->bst, (bas)->bsh, (reg), (value))
+
+static int msm_uart_param(struct uart_bas *, int, int, int, int);
+
+/*
+ * Low-level UART interface.
+ */
+static int     msm_probe(struct uart_bas *bas);
+static void    msm_init(struct uart_bas *bas, int, int, int, int);
+static void    msm_term(struct uart_bas *bas);
+static void    msm_putc(struct uart_bas *bas, int);
+static int     msm_rxready(struct uart_bas *bas);
+static int     msm_getc(struct uart_bas *bas, struct mtx *mtx);
+
+extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
+
+static int
+msm_uart_param(struct uart_bas *bas, int baudrate, int databits,
+    int stopbits, int parity)
+{
+       int ulcon;
+
+       ulcon = 0;
+
+       switch (databits) {
+       case 5:
+               ulcon |= (UART_DM_5_BPS << 4);
+               break;
+       case 6:
+               ulcon |= (UART_DM_6_BPS << 4);
+               break;
+       case 7:
+               ulcon |= (UART_DM_7_BPS << 4);
+               break;
+       case 8:
+               ulcon |= (UART_DM_8_BPS << 4);
+               break;
+       default:
+               return (EINVAL);
+       }
+
+       switch (parity) {
+       case UART_PARITY_NONE:
+               ulcon |= UART_DM_NO_PARITY;
+               break;
+       case UART_PARITY_ODD:
+               ulcon |= UART_DM_ODD_PARITY;
+               break;
+       case UART_PARITY_EVEN:
+               ulcon |= UART_DM_EVEN_PARITY;
+               break;
+       case UART_PARITY_SPACE:
+               ulcon |= UART_DM_SPACE_PARITY;
+               break;
+       case UART_PARITY_MARK:
+       default:
+               return (EINVAL);
+       }
+
+       switch (stopbits) {
+       case 1:
+               ulcon |= (UART_DM_SBL_1 << 2);
+               break;
+       case 2:
+               ulcon |= (UART_DM_SBL_2 << 2);
+               break;
+       default:
+               return (EINVAL);
+       }
+       uart_setreg(bas, UART_DM_MR2, ulcon);
+
+       /* Set 115200 for both TX and RX. */;
+       uart_setreg(bas, UART_DM_CSR, UART_DM_CSR_115200);
+       uart_barrier(bas);
+
+       return (0);
+}
+
+struct uart_ops uart_msm_ops = {
+       .probe = msm_probe,
+       .init = msm_init,
+       .term = msm_term,
+       .putc = msm_putc,
+       .rxready = msm_rxready,
+       .getc = msm_getc,
+};
+
+static int
+msm_probe(struct uart_bas *bas)
+{
+
+       return (0);
+}
+
+static void
+msm_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
+    int parity)
+{
+
+       if (bas->rclk == 0)
+               bas->rclk = DEF_CLK;
+
+       KASSERT(bas->rclk != 0, ("msm_init: Invalid rclk"));
+
+       /* Set default parameters */
+       msm_uart_param(bas, baudrate, databits, stopbits, parity);
+
+       /*
+        * Configure UART mode registers MR1 and MR2.
+        * Hardware flow control isn't supported.
+        */
+       uart_setreg(bas, UART_DM_MR1, 0x0);
+
+       /* Reset interrupt mask register. */
+       uart_setreg(bas, UART_DM_IMR, 0);
+
+       /*
+        * Configure Tx and Rx watermarks configuration registers.
+        * TX watermark value is set to 0 - interrupt is generated when
+        * FIFO level is less than or equal to 0.
+        */
+       uart_setreg(bas, UART_DM_TFWR, UART_DM_TFW_VALUE);
+
+       /* Set RX watermark value */
+       uart_setreg(bas, UART_DM_RFWR, UART_DM_RFW_VALUE);
+
+       /*
+        * Configure Interrupt Programming Register.
+        * Set initial Stale timeout value.
+        */
+       uart_setreg(bas, UART_DM_IPR, UART_DM_STALE_TIMEOUT_LSB);
+
+       /* Disable IRDA mode */
+       uart_setreg(bas, UART_DM_IRDA, 0x0);
+
+       /*
+        * Configure and enable sim interface if required.
+        * Configure hunt character value in HCR register.
+        * Keep it in reset state.
+        */
+       uart_setreg(bas, UART_DM_HCR, 0x0);
+
+       /* Issue soft reset command */
+       SETREG(bas, UART_DM_CR, UART_DM_RESET_TX);
+       SETREG(bas, UART_DM_CR, UART_DM_RESET_RX);
+       SETREG(bas, UART_DM_CR, UART_DM_RESET_ERROR_STATUS);
+       SETREG(bas, UART_DM_CR, UART_DM_RESET_BREAK_INT);
+       SETREG(bas, UART_DM_CR, UART_DM_RESET_STALE_INT);
+
+       /* Enable/Disable Rx/Tx DM interfaces */
+       /* Disable Data Mover for now. */
+       uart_setreg(bas, UART_DM_DMEN, 0x0);
+
+       /* Enable transmitter and receiver */
+       uart_setreg(bas, UART_DM_CR, UART_DM_CR_RX_ENABLE);
+       uart_setreg(bas, UART_DM_CR, UART_DM_CR_TX_ENABLE);
+
+       uart_barrier(bas);
+}
+
+static void
+msm_term(struct uart_bas *bas)
+{
+
+       /* XXX */
+}
+
+static void
+msm_putc(struct uart_bas *bas, int c)
+{
+       int limit;
+
+       /*
+        * Write to NO_CHARS_FOR_TX register the number of characters
+        * to be transmitted. However, before writing TX_FIFO must
+        * be empty as indicated by TX_READY interrupt in IMR register
+        */
+
+       /*
+        * Check if transmit FIFO is empty.
+        * If not wait for TX_READY interrupt.
+        */
+       limit = 1000;
+       if (!(uart_getreg(bas, UART_DM_SR) & UART_DM_SR_TXEMT)) {
+               while ((uart_getreg(bas, UART_DM_ISR) & UART_DM_TX_READY) == 0
+                   && --limit)
+                       DELAY(4);
+       }
+       /* FIFO is ready, write number of characters to be written */
+       uart_setreg(bas, UART_DM_NO_CHARS_FOR_TX, 1);
+
+       /* Wait till TX FIFO has space */
+       while ((uart_getreg(bas, UART_DM_SR) & UART_DM_SR_TXRDY) == 0)
+               DELAY(4);
+
+       /* TX FIFO has space. Write char */
+       SETREG(bas, UART_DM_TF(0), (c & 0xff));
+}
+
+static int
+msm_rxready(struct uart_bas *bas)
+{
+
+       /* Wait for a character to come ready */
+       return ((uart_getreg(bas, UART_DM_SR) & UART_DM_SR_RXRDY) ==
+           UART_DM_SR_RXRDY);
+}
+
+static int
+msm_getc(struct uart_bas *bas, struct mtx *mtx)
+{
+       int c;
+
+       uart_lock(mtx);
+
+       /* Wait for a character to come ready */
+       while ((uart_getreg(bas, UART_DM_SR) & UART_DM_SR_RXRDY) !=
+           UART_DM_SR_RXRDY)
+               DELAY(4);
+
+       /* Check for Overrun error. If so reset Error Status */
+       if (uart_getreg(bas, UART_DM_SR) & UART_DM_SR_UART_OVERRUN)
+               uart_setreg(bas, UART_DM_CR, UART_DM_RESET_ERROR_STATUS);
+
+       /* Read char */
+       c = uart_getreg(bas, UART_DM_RF(0));
+
+       uart_unlock(mtx);
+
+       return (c);
+}
+
+/*
+ * High-level UART interface.
+ */
+struct msm_uart_softc {
+       struct uart_softc base;
+       uint32_t ier;
+};
+
+static int     msm_bus_probe(struct uart_softc *sc);
+static int     msm_bus_attach(struct uart_softc *sc);
+static int     msm_bus_flush(struct uart_softc *, int);
+static int     msm_bus_getsig(struct uart_softc *);
+static int     msm_bus_ioctl(struct uart_softc *, int, intptr_t);
+static int     msm_bus_ipend(struct uart_softc *);
+static int     msm_bus_param(struct uart_softc *, int, int, int, int);
+static int     msm_bus_receive(struct uart_softc *);
+static int     msm_bus_setsig(struct uart_softc *, int);
+static int     msm_bus_transmit(struct uart_softc *);
+static void    msm_bus_grab(struct uart_softc *);
+static void    msm_bus_ungrab(struct uart_softc *);
+
+static kobj_method_t msm_methods[] = {
+       KOBJMETHOD(uart_probe,          msm_bus_probe),
+       KOBJMETHOD(uart_attach,         msm_bus_attach),
+       KOBJMETHOD(uart_flush,          msm_bus_flush),
+       KOBJMETHOD(uart_getsig,         msm_bus_getsig),
+       KOBJMETHOD(uart_ioctl,          msm_bus_ioctl),
+       KOBJMETHOD(uart_ipend,          msm_bus_ipend),
+       KOBJMETHOD(uart_param,          msm_bus_param),
+       KOBJMETHOD(uart_receive,        msm_bus_receive),
+       KOBJMETHOD(uart_setsig,         msm_bus_setsig),
+       KOBJMETHOD(uart_transmit,       msm_bus_transmit),
+       KOBJMETHOD(uart_grab,           msm_bus_grab),
+       KOBJMETHOD(uart_ungrab,         msm_bus_ungrab),
+       {0, 0 }
+};
+
+int
+msm_bus_probe(struct uart_softc *sc)
+{
+
+       sc->sc_txfifosz = 64;
+       sc->sc_rxfifosz = 64;
+
+       device_set_desc(sc->sc_dev, "Qualcomm HSUART");
+
+       return (0);
+}
+
+static int
+msm_bus_attach(struct uart_softc *sc)
+{
+       struct msm_uart_softc *u = (struct msm_uart_softc *)sc;
+       struct uart_bas *bas = &sc->sc_bas;
+
+       sc->sc_hwiflow = 0;
+       sc->sc_hwoflow = 0;
+
+       /* Set TX_READY, TXLEV, RXLEV, RXSTALE */
+       u->ier = UART_DM_IMR_ENABLED;
+
+       /* Configure Interrupt Mask register IMR */
+       uart_setreg(bas, UART_DM_IMR, u->ier);
+
+       return (0);
+}
+
+/*
+ * Write the current transmit buffer to the TX FIFO. 
+ */
+static int
+msm_bus_transmit(struct uart_softc *sc)
+{
+       struct msm_uart_softc *u = (struct msm_uart_softc *)sc;
+       struct uart_bas *bas = &sc->sc_bas;
+       int i;
+
+       uart_lock(sc->sc_hwmtx);
+
+       /* Write some data */
+       for (i = 0; i < sc->sc_txdatasz; i++) {
+               /* Write TX data */
+               msm_putc(bas, sc->sc_txbuf[i]);
+               uart_barrier(bas);
+       }
+
+       /* TX FIFO is empty now, enable TX_READY interrupt */
+       u->ier |= UART_DM_TX_READY;
+       SETREG(bas, UART_DM_IMR, u->ier);
+       uart_barrier(bas);
+
+       /*
+        * Inform upper layer that it is transmitting data to hardware,
+        * this will be cleared when TXIDLE interrupt occurs.
+        */
+       sc->sc_txbusy = 1;
+       uart_unlock(sc->sc_hwmtx);
+
+       return (0);
+}
+
+static int
+msm_bus_setsig(struct uart_softc *sc, int sig)
+{
+
+       return (0);
+}
+
+static int
+msm_bus_receive(struct uart_softc *sc)
+{
+       struct msm_uart_softc *u = (struct msm_uart_softc *)sc;
+       struct uart_bas *bas;
+       int c;
+
+       bas = &sc->sc_bas;
+       uart_lock(sc->sc_hwmtx);
+
+       /* Initialize Receive Path and interrupt */
+       SETREG(bas, UART_DM_CR, UART_DM_RESET_STALE_INT);
+       SETREG(bas, UART_DM_CR, UART_DM_STALE_EVENT_ENABLE);
+       u->ier |= UART_DM_RXLEV;
+       SETREG(bas, UART_DM_IMR, u->ier);
+
+       /* Loop over until we are full, or no data is available */
+       while (uart_getreg(bas, UART_DM_SR) & UART_DM_SR_RXRDY) {
+               if (uart_rx_full(sc)) {
+                       /* No space left in input buffer */
+                       sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
+                       break;
+               }
+
+               /* Read RX FIFO */
+               c = uart_getreg(bas, UART_DM_RF(0));
+               uart_barrier(bas);
+
+               uart_rx_put(sc, c);
+       }
+
+       uart_unlock(sc->sc_hwmtx);
+
+       return (0);
+}
+
+static int
+msm_bus_param(struct uart_softc *sc, int baudrate, int databits,
+    int stopbits, int parity)
+{
+       int error;
+
+       if (sc->sc_bas.rclk == 0)
+               sc->sc_bas.rclk = DEF_CLK;
+
+       KASSERT(sc->sc_bas.rclk != 0, ("msm_init: Invalid rclk"));
+
+       uart_lock(sc->sc_hwmtx);
+       error = msm_uart_param(&sc->sc_bas, baudrate, databits, stopbits,
+           parity);
+       uart_unlock(sc->sc_hwmtx);
+
+       return (error);
+}
+
+static int
+msm_bus_ipend(struct uart_softc *sc)
+{
+       struct msm_uart_softc *u = (struct msm_uart_softc *)sc;
+       struct uart_bas *bas = &sc->sc_bas;
+       uint32_t isr;
+       int ipend;
+
+       uart_lock(sc->sc_hwmtx);
+
+       /* Get ISR status */
+       isr = GETREG(bas, UART_DM_MISR);
+
+       ipend = 0;
+
+       /* Uart RX starting, notify upper layer */
+       if (isr & UART_DM_RXLEV) {
+               u->ier &= ~UART_DM_RXLEV;
+               SETREG(bas, UART_DM_IMR, u->ier);
+               uart_barrier(bas);
+               ipend |= SER_INT_RXREADY;
+       }
+
+       /* Stale RX interrupt */
+       if (isr & UART_DM_RXSTALE) {
+               /* Disable and reset it */
+               SETREG(bas, UART_DM_CR, UART_DM_STALE_EVENT_DISABLE);
+               SETREG(bas, UART_DM_CR, UART_DM_RESET_STALE_INT);
+               uart_barrier(bas);
+               ipend |= SER_INT_RXREADY;
+       }
+
+       /* TX READY interrupt */
+       if (isr & UART_DM_TX_READY) {
+               /* Clear  TX Ready */
+               SETREG(bas, UART_DM_CR, UART_DM_CLEAR_TX_READY);
+
+               /* Disable TX_READY */
+               u->ier &= ~UART_DM_TX_READY;
+               SETREG(bas, UART_DM_IMR, u->ier);
+               uart_barrier(bas);
+
+               if (sc->sc_txbusy != 0)
+                       ipend |= SER_INT_TXIDLE;
+       }
+
+       if (isr & UART_DM_TXLEV) {
+               /* TX FIFO is empty */
+               u->ier &= ~UART_DM_TXLEV;
+               SETREG(bas, UART_DM_IMR, u->ier);
+               uart_barrier(bas);
+
+               if (sc->sc_txbusy != 0)
+                       ipend |= SER_INT_TXIDLE;
+       }
+
+       uart_unlock(sc->sc_hwmtx);
+       return (ipend);
+}
+
+static int
+msm_bus_flush(struct uart_softc *sc, int what)
+{
+
+       return (0);
+}
+
+static int
+msm_bus_getsig(struct uart_softc *sc)
+{
+
+       return (0);
+}
+
+static int
+msm_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
+{
+
+       return (EINVAL);
+}
+
+static void
+msm_bus_grab(struct uart_softc *sc)
+{
+       struct uart_bas *bas = &sc->sc_bas;
+
+       /*
+        * XXX: Turn off all interrupts to enter polling mode. Leave the
+        * saved mask alone. We'll restore whatever it was in ungrab.
+        */
+       uart_lock(sc->sc_hwmtx);
+       SETREG(bas, UART_DM_CR, UART_DM_RESET_STALE_INT);
+       SETREG(bas, UART_DM_IMR, 0);
+       uart_barrier(bas);
+       uart_unlock(sc->sc_hwmtx);
+}
+
+static void
+msm_bus_ungrab(struct uart_softc *sc)
+{
+       struct msm_uart_softc *u = (struct msm_uart_softc *)sc;
+       struct uart_bas *bas = &sc->sc_bas;
+
+       /*
+        * Restore previous interrupt mask
+        */
+       uart_lock(sc->sc_hwmtx);
+       SETREG(bas, UART_DM_IMR, u->ier);
+       uart_barrier(bas);
+       uart_unlock(sc->sc_hwmtx);
+}
+
+struct uart_class uart_msm_class = {
+       "msm",
+       msm_methods,
+       sizeof(struct msm_uart_softc),
+       .uc_ops = &uart_msm_ops,
+       .uc_range = 8,
+       .uc_rclk = DEF_CLK,
+};

Copied: stable/10/sys/dev/uart/uart_dev_msm.h (from r272399, 
head/sys/dev/uart/uart_dev_msm.h)
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ stable/10/sys/dev/uart/uart_dev_msm.h       Sat May 23 19:27:04 2015        
(r283321, copy of r272399, head/sys/dev/uart/uart_dev_msm.h)
@@ -0,0 +1,229 @@
+/*-
+ * Copyright (c) 2014 Ganbold Tsagaankhuu <ganb...@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef        _UART_DM_H_
+#define        _UART_DM_H_
+
+#define        UART_DM_EXTR_BITS(value, start_pos, end_pos) \
+           ((value << (32 - end_pos)) >> (32 - (end_pos - start_pos)))
+
+/* UART Parity Mode */
+enum UART_DM_PARITY_MODE {
+       UART_DM_NO_PARITY,
+       UART_DM_ODD_PARITY,
+       UART_DM_EVEN_PARITY,
+       UART_DM_SPACE_PARITY
+};
+
+/* UART Stop Bit Length */
+enum UART_DM_STOP_BIT_LEN {
+       UART_DM_SBL_9_16,
+       UART_DM_SBL_1,
+       UART_DM_SBL_1_9_16,
+       UART_DM_SBL_2
+};
+
+/* UART Bits per Char */
+enum UART_DM_BITS_PER_CHAR {
+       UART_DM_5_BPS,
+       UART_DM_6_BPS,
+       UART_DM_7_BPS,
+       UART_DM_8_BPS
+};
+
+/* 8-N-1 Configuration */
+#define        UART_DM_8_N_1_MODE                      (UART_DM_NO_PARITY | \
+                                               (UART_DM_SBL_1 << 2) | \
+                                               (UART_DM_8_BPS << 4))
+
+/* UART_DM Registers */
+
+/* UART Operational Mode Registers (HSUART) */
+#define        UART_DM_MR1                             0x00
+#define         UART_DM_MR1_AUTO_RFR_LEVEL1_BMSK       0xffffff00
+#define         UART_DM_MR1_AUTO_RFR_LEVEL0_BMSK       0x3f
+#define         UART_DM_MR1_CTS_CTL_BMSK               0x40
+#define         UART_DM_MR1_RX_RDY_CTL_BMSK            0x80
+
+#define        UART_DM_MR2                             0x04
+#define         UART_DM_MR2_ERROR_MODE_BMSK            0x40
+#define         UART_DM_MR2_BITS_PER_CHAR_BMSK         0x30
+#define         UART_DM_MR2_STOP_BIT_LEN_BMSK          0x0c
+#define         UART_DM_MR2_PARITY_MODE_BMSK           0x03
+#define         UART_DM_RXBRK_ZERO_CHAR_OFF            (1 << 8)
+#define         UART_DM_LOOPBACK                       (1 << 7)
+
+/* UART Clock Selection Register, write only */
+#define        UART_DM_CSR                             0x08
+#define         UART_DM_CSR_115200                     0xff
+#define         UART_DM_CSR_57600                      0xee
+#define         UART_DM_CSR_38400                      0xdd
+#define         UART_DM_CSR_28800                      0xcc
+#define         UART_DM_CSR_19200                      0xbb
+#define         UART_DM_CSR_14400                      0xaa
+#define         UART_DM_CSR_9600                       0x99
+#define         UART_DM_CSR_7200                       0x88
+#define         UART_DM_CSR_4800                       0x77
+#define         UART_DM_CSR_3600                       0x66
+#define         UART_DM_CSR_2400                       0x55
+#define         UART_DM_CSR_1200                       0x44
+#define         UART_DM_CSR_600                        0x33
+#define         UART_DM_CSR_300                        0x22
+#define         UART_DM_CSR_150                        0x11
+#define         UART_DM_CSR_75                         0x00
+
+/* UART DM TX FIFO Registers - 4, write only */
+#define        UART_DM_TF(x)                           (0x70 + (4 * (x)))
+
+/* UART Command Register, write only */
+#define        UART_DM_CR                              0x10
+#define         UART_DM_CR_RX_ENABLE                   (1 << 0)
+#define         UART_DM_CR_RX_DISABLE                  (1 << 1)
+#define         UART_DM_CR_TX_ENABLE                   (1 << 2)
+#define         UART_DM_CR_TX_DISABLE                  (1 << 3)
+
+/* UART_DM_CR channel command bit value (register field is bits 8:4) */
+#define        UART_DM_RESET_RX                        0x10
+#define        UART_DM_RESET_TX                        0x20
+#define        UART_DM_RESET_ERROR_STATUS              0x30
+#define        UART_DM_RESET_BREAK_INT                 0x40
+#define        UART_DM_START_BREAK                     0x50
+#define        UART_DM_STOP_BREAK                      0x60
+#define        UART_DM_RESET_CTS                       0x70
+#define        UART_DM_RESET_STALE_INT                 0x80
+#define        UART_DM_RFR_LOW                         0xD0
+#define        UART_DM_RFR_HIGH                        0xE0
+#define        UART_DM_CR_PROTECTION_EN                0x100
+#define        UART_DM_STALE_EVENT_ENABLE              0x500
+#define        UART_DM_STALE_EVENT_DISABLE             0x600
+#define        UART_DM_FORCE_STALE_EVENT               0x400
+#define        UART_DM_CLEAR_TX_READY                  0x300
+#define        UART_DM_RESET_TX_ERROR                  0x800
+#define        UART_DM_RESET_TX_DONE                   0x810
+
+/* UART Interrupt Mask Register */
+#define        UART_DM_IMR                             0x14
+/* these can be used for both ISR and IMR registers */
+#define        UART_DM_TXLEV                           (1 << 0)
+#define        UART_DM_RXHUNT                          (1 << 1)
+#define        UART_DM_RXBRK_CHNG                      (1 << 2)
+#define        UART_DM_RXSTALE                         (1 << 3)
+#define        UART_DM_RXLEV                           (1 << 4)
+#define        UART_DM_DELTA_CTS                       (1 << 5)
+#define        UART_DM_CURRENT_CTS                     (1 << 6)
+#define        UART_DM_TX_READY                        (1 << 7)
+#define        UART_DM_TX_ERROR                        (1 << 8)
+#define        UART_DM_TX_DONE                         (1 << 9)
+#define        UART_DM_RXBREAK_START                   (1 << 10)
+#define        UART_DM_RXBREAK_END                     (1 << 11)
+#define        UART_DM_PAR_FRAME_ERR_IRQ               (1 << 12)
+
+#define        UART_DM_IMR_ENABLED                     (UART_DM_TX_READY | \
+                                               UART_DM_TXLEV | \
+                                               UART_DM_RXLEV | \
+                                               UART_DM_RXSTALE)
+
+/* UART Interrupt Programming Register */
+#define        UART_DM_IPR                             0x18
+#define        UART_DM_STALE_TIMEOUT_LSB               0x0f
+#define        UART_DM_STALE_TIMEOUT_MSB               0x00
+#define        UART_DM_IPR_STALE_TIMEOUT_MSB_BMSK      0xffffff80
+#define        UART_DM_IPR_STALE_LSB_BMSK              0x1f
+
+/* UART Transmit/Receive FIFO Watermark Register */
+#define        UART_DM_TFWR                            0x1c
+/* Interrupt is generated when FIFO level is less than or equal to this value 
*/
+#define        UART_DM_TFW_VALUE                       0
+
+#define        UART_DM_RFWR                            0x20
+/* Interrupt generated when no of words in RX FIFO is greater than this value 
*/
+#define        UART_DM_RFW_VALUE                       0
+
+/* UART Hunt Character Register */
+#define        UART_DM_HCR                             0x24
+
+/* Used for RX transfer initialization */
+#define        UART_DM_DMRX                            0x34
+/* Default DMRX value - any value bigger than FIFO size would be fine */
+#define        UART_DM_DMRX_DEF_VALUE                  0x220
+
+/* Register to enable IRDA function */
+#define        UART_DM_IRDA                            0x38
+
+/* UART Data Mover Enable Register */
+#define        UART_DM_DMEN                            0x3c
+
+/* Number of characters for Transmission */
+#define        UART_DM_NO_CHARS_FOR_TX                 0x40
+
+/* UART RX FIFO Base Address */
+#define        UART_DM_BADR                            0x44
+
+#define        UART_DM_SIM_CFG_ADDR                    0x80
+
+/* Read only registers */
+/* UART Status Register */
+#define        UART_DM_SR                              0x08
+/* register field mask mapping */
+#define         UART_DM_SR_RXRDY                       (1 << 0)
+#define         UART_DM_SR_RXFULL                      (1 << 1)
+#define         UART_DM_SR_TXRDY                       (1 << 2)
+#define         UART_DM_SR_TXEMT                       (1 << 3)
+#define         UART_DM_SR_UART_OVERRUN                (1 << 4)
+#define         UART_DM_SR_PAR_FRAME_ERR               (1 << 5)
+#define         UART_DM_RX_BREAK                       (1 << 6)
+#define         UART_DM_HUNT_CHAR                      (1 << 7)
+#define         UART_DM_RX_BRK_START_LAST              (1 << 8)
+
+/* UART Receive FIFO Registers - 4 in numbers */
+#define        UART_DM_RF(x)                           (0x70 + (4 * (x)))
+
+/* UART Masked Interrupt Status Register */
+#define        UART_DM_MISR                            0x10
+
+/* UART Interrupt Status Register */
+#define        UART_DM_ISR                             0x14
+
+/* Number of characters received since the end of last RX transfer */
+#define        UART_DM_RX_TOTAL_SNAP                   0x38
+
+/* UART TX FIFO Status Register */
+#define        UART_DM_TXFS                            0x4c
+#define         UART_DM_TXFS_STATE_LSB(x)              UART_DM_EXTR_BITS(x,0,6)
+#define         UART_DM_TXFS_STATE_MSB(x)              
UART_DM_EXTR_BITS(x,14,31)
+#define         UART_DM_TXFS_BUF_STATE(x)              UART_DM_EXTR_BITS(x,7,9)
+#define         UART_DM_TXFS_ASYNC_STATE(x)            
UART_DM_EXTR_BITS(x,10,13)
+
+/* UART RX FIFO Status Register */
+#define        UART_DM_RXFS                            0x50
+#define         UART_DM_RXFS_STATE_LSB(x)              UART_DM_EXTR_BITS(x,0,6)
+#define         UART_DM_RXFS_STATE_MSB(x)              
UART_DM_EXTR_BITS(x,14,31)
+#define         UART_DM_RXFS_BUF_STATE(x)              UART_DM_EXTR_BITS(x,7,9)
+#define         UART_DM_RXFS_ASYNC_STATE(x)            
UART_DM_EXTR_BITS(x,10,13)
+
+#endif /* _UART_DM_H_ */

Modified: stable/10/sys/dev/uart/uart_dev_pl011.c
==============================================================================
--- stable/10/sys/dev/uart/uart_dev_pl011.c     Sat May 23 19:09:04 2015        
(r283320)
+++ stable/10/sys/dev/uart/uart_dev_pl011.c     Sat May 23 19:27:04 2015        
(r283321)
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
 #define        DR_OE           (1 << 11)       /* Overrun error */
 
 #define        UART_FR         0x06            /* Flag register */
+#define        FR_TXFF         (1 << 5)        /* Transmit FIFO/reg full */
 #define        FR_RXFF         (1 << 6)        /* Receive FIFO/reg full */
 #define        FR_TXFE         (1 << 7)        /* Transmit FIFO/reg empty */
 
@@ -194,7 +195,8 @@ static void
 uart_pl011_putc(struct uart_bas *bas, int c)
 {
 
-       while (!(__uart_getreg(bas, UART_FR) & FR_TXFE))
+       /* Wait when TX FIFO full. Push character otherwise. */
+       while (__uart_getreg(bas, UART_FR) & FR_TXFF)
                ;
        __uart_setreg(bas, UART_DR, c & 0xff);
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to