add Synopsys Degisnware UART (dw-apb-uart) support
authoruaa <uaa@openbsd.org>
Tue, 11 Jan 2022 11:51:14 +0000 (11:51 +0000)
committeruaa <uaa@openbsd.org>
Tue, 11 Jan 2022 11:51:14 +0000 (11:51 +0000)
To fix Allwinner H6's UART problem, need to add dw-apb-uart special code.
ok kettenis@

sys/dev/fdt/com_fdt.c
sys/dev/ic/com.c
sys/dev/ic/comreg.h
sys/dev/ic/comvar.h
sys/dev/ic/ns16550reg.h

index 5ee3b6d..473658a 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: com_fdt.c,v 1.6 2021/10/24 17:52:26 mpi Exp $ */
+/* $OpenBSD: com_fdt.c,v 1.7 2022/01/11 11:51:14 uaa Exp $ */
 /*
  * Copyright (c) 2016 Patrick Wildt <patrick@blueri.se>
  *
@@ -33,8 +33,6 @@
 #include <dev/ofw/ofw_clock.h>
 #include <dev/ofw/ofw_pinctrl.h>
 
-#define com_usr 31     /* Synopsys DesignWare UART */
-
 int    com_fdt_match(struct device *, void *, void *);
 void   com_fdt_attach(struct device *, struct device *, void *);
 int    com_fdt_intr_designware(void *);
@@ -144,8 +142,10 @@ com_fdt_attach(struct device *parent, struct device *self, void *aux)
        sc->sc_reg_shift = OF_getpropint(faa->fa_node, "reg-shift", shift);
 
        if (OF_is_compatible(faa->fa_node, "snps,dw-apb-uart") ||
-           OF_is_compatible(faa->fa_node, "marvell,armada-38x-uart"))
+           OF_is_compatible(faa->fa_node, "marvell,armada-38x-uart")) {
+               sc->sc_uarttype = COM_UART_DW_APB;
                intr = com_fdt_intr_designware;
+       }
 
        if (OF_is_compatible(faa->fa_node, "ti,omap3-uart") ||
            OF_is_compatible(faa->fa_node, "ti,omap4-uart"))
index e1aa05e..a5ecfde 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: com.c,v 1.174 2021/05/06 20:35:21 kettenis Exp $      */
+/*     $OpenBSD: com.c,v 1.175 2022/01/11 11:51:14 uaa Exp $   */
 /*     $NetBSD: com.c,v 1.82.4.1 1996/06/02 09:08:00 mrg Exp $ */
 
 /*
@@ -1300,7 +1300,8 @@ void
 com_attach_subr(struct com_softc *sc)
 {
        int probe = 0;
-       u_int8_t lcr;
+       u_int8_t lcr, fifo;
+       u_int32_t cpr;
 
        sc->sc_ier = 0;
        /* disable interrupts */
@@ -1480,6 +1481,27 @@ com_attach_subr(struct com_softc *sc)
                SET(sc->sc_hwflags, COM_HW_FIFO);
                sc->sc_fifolen = 256;
                break;
+       case COM_UART_DW_APB:
+               printf(": dw16550");
+               SET(sc->sc_hwflags, COM_HW_FIFO);
+               cpr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, com_cpr << 2);
+               sc->sc_fifolen = CPR_FIFO_MODE(cpr) * 16;
+               if (sc->sc_fifolen) {
+                       printf(", %d byte fifo\n", sc->sc_fifolen);
+               } else {
+                       printf("\n");
+                       /*
+                        * The DW-APB configuration on the Allwinner H6 SoC
+                        * does not provide the CPR register and will be
+                        * detected as having no FIFO.  But it does have a
+                        * 256-byte FIFO and with the FIFO disabled the
+                        * LSR_RXRDY bit remains set even if the input
+                        * buffer is empty.  As a workaround, treat as a
+                        * 1-byte FIFO.
+                        */
+                       sc->sc_fifolen = 1;
+               }
+               break;
        default:
                panic("comattach: bad fifo type");
        }
@@ -1496,10 +1518,13 @@ com_attach_subr(struct com_softc *sc)
        }
 
        /* clear and disable fifo */
-       com_write_reg(sc, com_fifo, FIFO_RCV_RST | FIFO_XMT_RST);
+       /* DW-APB UART cannot turn off FIFO here (ddb will not work) */
+       fifo = (sc->sc_uarttype == COM_UART_DW_APB) ?
+               (FIFO_ENABLE | FIFO_TRIGGER_1) : 0;
+       com_write_reg(sc, com_fifo, fifo | FIFO_RCV_RST | FIFO_XMT_RST);
        if (ISSET(com_read_reg(sc, com_lsr), LSR_RXRDY))
                (void)com_read_reg(sc, com_data);
-       com_write_reg(sc, com_fifo, 0);
+       com_write_reg(sc, com_fifo, fifo);
 
        sc->sc_mcr = 0;
        com_write_reg(sc, com_mcr, sc->sc_mcr);
index 627f382..c49cbbe 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: comreg.h,v 1.20 2020/08/14 18:14:11 jcs Exp $ */
+/*     $OpenBSD: comreg.h,v 1.21 2022/01/11 11:51:14 uaa Exp $ */
 /*     $NetBSD: comreg.h,v 1.8 1996/02/05 23:01:50 scottr Exp $        */
 
 /*
 #define ISR_TXPL       0x08    /* negative transmit data polarity */
 #define ISR_RXPL       0x10    /* negative receive data polarity */
 
+/* component parameter register (Synopsys DesignWare APB UART) */
+#define        CPR_FIFO_MODE(x)        (((x) >> 16) & 0xff)
+
 #define        COM_NPORTS      8
 
 /* Exar XR17V35X */
index c1a15f5..8641a97 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: comvar.h,v 1.58 2020/08/14 18:14:11 jcs Exp $ */
+/*     $OpenBSD: comvar.h,v 1.59 2022/01/11 11:51:14 uaa Exp $ */
 /*     $NetBSD: comvar.h,v 1.5 1996/05/05 19:50:47 christos Exp $      */
 
 /*
@@ -104,6 +104,7 @@ struct com_softc {
 #define        COM_UART_XR16850        0x10            /* 128 byte fifo */
 #define        COM_UART_OX16C950       0x11            /* 128 byte fifo */
 #define        COM_UART_XR17V35X       0x12            /* 256 byte fifo */
+#define        COM_UART_DW_APB         0x13            /* configurable */
 
        u_char sc_hwflags;
 #define        COM_HW_NOIEN    0x01
index 5db1a27..d9f2d58 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ns16550reg.h,v 1.5 2003/06/02 23:28:02 millert Exp $  */
+/*     $OpenBSD: ns16550reg.h,v 1.6 2022/01/11 11:51:14 uaa Exp $      */
 /*     $NetBSD: ns16550reg.h,v 1.4 1994/10/27 04:18:43 cgd Exp $       */
 
 /*-
@@ -50,3 +50,9 @@
 #define        com_lsr         5       /* line status register (R/W) */
 #define        com_msr         6       /* modem status register (R/W) */
 #define com_scratch    7       /* scratch register (R/W) */
+
+/*
+ * Synopsys DesignWare APB UART additional registers
+ */
+#define        com_usr         31      /* UART status register (R) */
+#define        com_cpr         61      /* component parameter register (R) */