Hi,

the Synopsys Designware UART, which is used on a bunch of SoCs, is
mostly compatible to com(4).  Currently we use sxiuart, a driver based
on another driver, modified to work on sunxi.  I would like to replace
sxiuart with com(4).  This diff disables sxiuart and implements the
Allwinner and Synopsys specific code in the existing com(4) wrapper
for OMAP.  In a follow up diff we can remove sxiuart completely.  Also,
we might want to move it to some other folder and/or rename it.  That
should be part of a follow up diff.

There's only a slight twist:  The controller has a busy interrupt we
need to handle.  Otherwise we will get flooded with interrupts.
mglocker@ is currently experiencing that issue with the sxiuart driver
as well.  This diff also implements this busy indicator in com(4).

I guess the com(4) and the armv7 changes should be committed separately.
This diff combines both to show what it will be used for.

I tested it on BBB and Lamobo R1.  mglocker@ reported success on his
sunxi-based CHIP.

ok?  Comments?

Patrick


diff --git a/sys/arch/armv7/armv7/platform.c b/sys/arch/armv7/armv7/platform.c
index f122c1f..390d907 100644
--- a/sys/arch/armv7/armv7/platform.c
+++ b/sys/arch/armv7/armv7/platform.c
@@ -37,7 +37,6 @@ static struct armv7_platform *platform;
 void   exuart_init_cons(void);
 void   imxuart_init_cons(void);
 void   omapuart_init_cons(void);
-void   sxiuart_init_cons(void);
 void   pl011_init_cons(void);
 
 struct armv7_platform *imx_platform_match(void);
@@ -102,7 +101,6 @@ platform_init_cons(void)
        exuart_init_cons();
        imxuart_init_cons();
        omapuart_init_cons();
-       sxiuart_init_cons();
        pl011_init_cons();
 }
 
diff --git a/sys/arch/armv7/conf/GENERIC b/sys/arch/armv7/conf/GENERIC
index c3f0311..5ddaea7 100644
--- a/sys/arch/armv7/conf/GENERIC
+++ b/sys/arch/armv7/conf/GENERIC
@@ -91,7 +91,7 @@ sxiccmu*      at sunxi?               # Clock Control 
Module/Unit
 sxitimer*      at sunxi?
 sxidog*                at sunxi?               # watchdog timer
 sxirtc*                at sunxi?               # Real Time Clock
-sxiuart*       at fdt?                 # onboard UARTs
+#sxiuart*      at fdt?                 # onboard UARTs
 sxie*          at fdt?
 ahci*          at sunxi?               # AHCI/SATA (shim)
 ehci*          at sunxi?               # EHCI (shim)
diff --git a/sys/arch/armv7/conf/RAMDISK b/sys/arch/armv7/conf/RAMDISK
index 4a3c53e..36fb0dc 100644
--- a/sys/arch/armv7/conf/RAMDISK
+++ b/sys/arch/armv7/conf/RAMDISK
@@ -90,7 +90,7 @@ sxiccmu*      at sunxi?               # Clock Control 
Module/Unit
 sxitimer*      at sunxi?
 sxidog*                at sunxi?               # watchdog timer
 sxirtc*                at sunxi?               # Real Time Clock
-sxiuart*       at fdt?                 # onboard UARTs
+#sxiuart*      at fdt?                 # onboard UARTs
 sxie*          at fdt?
 ahci*          at sunxi?               # AHCI/SATA (shim)
 ehci*          at sunxi?               # EHCI (shim)
diff --git a/sys/arch/armv7/omap/omap_com.c b/sys/arch/armv7/omap/omap_com.c
index 20a51b4..5aa82f7 100644
--- a/sys/arch/armv7/omap/omap_com.c
+++ b/sys/arch/armv7/omap/omap_com.c
@@ -76,14 +76,23 @@ omapuart_init_cons(void)
 {
        struct fdt_reg reg;
        void *node;
+       int freq = 48000000;
 
-       if ((node = fdt_find_cons("ti,omap3-uart")) == NULL)
-               if ((node = fdt_find_cons("ti,omap4-uart")) == NULL)
+       if ((node = fdt_find_cons("ti,omap3-uart")) == NULL &&
+           (node = fdt_find_cons("ti,omap4-uart")) == NULL &&
+           (node = fdt_find_cons("snps,dw-apb-uart")) == NULL)
                        return;
        if (fdt_get_reg(node, 0, &reg))
                return;
 
-       comcnattach(&armv7_a4x_bs_tag, reg.addr, comcnspeed, 48000000,
+       if ((node = fdt_find_node("/")) != NULL &&
+           (fdt_is_compatible(node, "allwinner,sun4i-a10") ||
+           fdt_is_compatible(node, "allwinner,sun5i-a10s") ||
+           fdt_is_compatible(node, "allwinner,sun5i-r8") ||
+           fdt_is_compatible(node, "allwinner,sun7i-a20")))
+               freq = 24000000;
+
+       comcnattach(&armv7_a4x_bs_tag, reg.addr, comcnspeed, freq,
            comcnmode);
        comdefaultrate = comcnspeed;
 }
@@ -94,7 +103,8 @@ omapuart_match(struct device *parent, void *match, void *aux)
        struct fdt_attach_args *faa = aux;
 
        return (OF_is_compatible(faa->fa_node, "ti,omap3-uart") ||
-           OF_is_compatible(faa->fa_node, "ti,omap4-uart"));
+           OF_is_compatible(faa->fa_node, "ti,omap4-uart") ||
+           OF_is_compatible(faa->fa_node, "snps,dw-apb-uart"));
 }
 
 void
@@ -102,7 +112,7 @@ omapuart_attach(struct device *parent, struct device *self, 
void *aux)
 {
        struct com_softc *sc = (struct com_softc *)self;
        struct fdt_attach_args *faa = aux;
-       int irq;
+       int irq, node;
 
        if (faa->fa_nreg != 1 || (faa->fa_nintr != 1 && faa->fa_nintr != 3))
                return;
@@ -123,7 +133,21 @@ omapuart_attach(struct device *parent, struct device 
*self, void *aux)
                return;
        }
 
-       sitara_cm_pinctrlbyname(faa->fa_node, "default");
+       if (OF_is_compatible(faa->fa_node, "ti,omap3-uart") ||
+           OF_is_compatible(faa->fa_node, "ti,omap4-uart"))
+               sitara_cm_pinctrlbyname(faa->fa_node, "default");
+
+       if (OF_is_compatible(faa->fa_node, "snps,dw-apb-uart")) {
+               sc->sc_hwflags |= COM_HW_IIR_BUSY;
+               sc->sc_uarttype = COM_UART_16550;
+       }
+
+       if ((node = OF_finddevice("/")) != 0 &&
+           (OF_is_compatible(node, "allwinner,sun4i-a10") ||
+           OF_is_compatible(node, "allwinner,sun5i-a10s") ||
+           OF_is_compatible(node, "allwinner,sun5i-r8") ||
+           OF_is_compatible(node, "allwinner,sun7i-a20")))
+               sc->sc_frequency = 24000000;
 
        com_attach_subr(sc);
 
diff --git a/sys/dev/ic/com.c b/sys/dev/ic/com.c
index 000eea3..0bf7181 100644
--- a/sys/dev/ic/com.c
+++ b/sys/dev/ic/com.c
@@ -1219,12 +1219,30 @@ comintr(void *arg)
        bus_space_tag_t iot = sc->sc_iot;
        bus_space_handle_t ioh = sc->sc_ioh;
        struct tty *tp;
-       u_char lsr, data, msr, delta;
+       u_char iir, lsr, data, msr, delta;
+       int timeout;
+
+       iir = bus_space_read_1(iot, ioh, com_iir);
+
+       /* Handle ns16750-specific busy interrupt. */
+       if (ISSET(sc->sc_hwflags, COM_HW_IIR_BUSY) &&
+           (iir & IIR_BUSY) == IIR_BUSY) {
+               for (timeout = 10000;
+                   (bus_space_read_1(iot, ioh, com_usr) & 0x1) != 0;
+                   timeout--)
+                       if (timeout <= 0) {
+                               printf("%s: timeout while waiting for BUSY "
+                                   "interrupt acknowledge\n",
+                                   sc->sc_dev.dv_xname);
+                               return (0);
+                       }
+               iir = bus_space_read_1(iot, ioh, com_iir);
+       }
 
        if (!sc->sc_tty)
                return (0);             /* Can't do squat. */
 
-       if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND))
+       if (ISSET(iir, IIR_NOPEND))
                return (0);
 
        tp = sc->sc_tty;
diff --git a/sys/dev/ic/comreg.h b/sys/dev/ic/comreg.h
index 6084698..d2e52a0 100644
--- a/sys/dev/ic/comreg.h
+++ b/sys/dev/ic/comreg.h
@@ -82,6 +82,7 @@
 #define        IIR_MLSC        0x0     /* Modem status */
 #define        IIR_NOPEND      0x1     /* No pending interrupts */
 #define        IIR_FIFO_MASK   0xc0    /* set if FIFOs are enabled */
+#define        IIR_BUSY        0x7     /* NS16750: Busy indicator */
 
 /* fifo control register */
 #define        FIFO_ENABLE     0x01    /* Turn the FIFO on */
diff --git a/sys/dev/ic/comvar.h b/sys/dev/ic/comvar.h
index 893ffde..5f7e5fe 100644
--- a/sys/dev/ic/comvar.h
+++ b/sys/dev/ic/comvar.h
@@ -106,6 +106,7 @@ struct com_softc {
        u_char sc_hwflags;
 #define        COM_HW_NOIEN    0x01
 #define        COM_HW_FIFO     0x02
+#define        COM_HW_IIR_BUSY 0x04
 #define        COM_HW_SIR      0x20
 #define        COM_HW_CONSOLE  0x40
 #define        COM_HW_KGDB     0x80
@@ -117,7 +118,7 @@ struct com_softc {
 #define        COM_SW_PPS      0x10
 #define        COM_SW_DEAD     0x20
        int     sc_fifolen;
-       u_char sc_msr, sc_mcr, sc_lcr, sc_ier;
+       u_char sc_msr, sc_mcr, sc_lcr, sc_ier, sc_iir;
        u_char sc_dtr;
 
        u_char  sc_cua;
diff --git a/sys/dev/ic/ns16550reg.h b/sys/dev/ic/ns16550reg.h
index 5db1a27..d8eb8b3 100644
--- a/sys/dev/ic/ns16550reg.h
+++ b/sys/dev/ic/ns16550reg.h
@@ -50,3 +50,4 @@
 #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) */
+#define com_usr                31      /* NS16750: status register (R) */

Reply via email to