> Date: Wed, 3 Aug 2016 22:36:02 +0200
> From: Patrick Wildt <patr...@blueri.se>
> 
> 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).
>
> ok?  Comments?

Documentation for the Designware IP can be found at:

http://read.pudn.com/downloads163/doc/741013/dw_apb_uart_db.pdf

I don't think the com(4) part of the diff is quite right.  This busy
indicator feature seems to be specific to the Designware core.  I
can't find the original NS16750 datasheet (was there ever one?), but
it isn't present on any of the true 16750 clones.  So I think that
instead of adding a COM_HW_IIR_BUSY flag, we should add a
COM_UART_DWAPB type and use that to signal the presence of this
feature.  The comments should certainly not mention the NS16750.

But I'd also like to look at the documentation to see if there way to
work around this issue.  It seems that the interrupt handlers is
simply waiting for the FIFO to drain.  It would really surprise me if
that is really necessary.

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