Current-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

com(4) over 115200 bps support



Hi! all,


I want tester for attached patch.
(This patch defines COM_16950 at head forcely. ;-)

  16650 supports max 460800 bps.  (perhaps ;-)
  16950 supports max 921600 bps.


It support over 115200 bps with 16650 and 16950.
I tested on hpcsh with Bluetooth PCMCIA card included 16950.  My card
establish for 921600bps to me.

I am not convinced of 16650 correctly supporting it.  And, this patch
was did not work with 'st16650 broken fifo' on my sandpoint(KURO-BOX:
MPC8241 SoC).

I would test on my some machines at tonight.  ;-)

Thanks,
--
kiyohara

Index: com.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/com.c,v
retrieving revision 1.295
diff -u -r1.295 com.c
--- com.c       24 Feb 2010 22:37:58 -0000      1.295
+++ com.c       1 Mar 2010 05:38:10 -0000
@@ -1,3 +1,4 @@
+#define COM_16950
 /* $NetBSD: com.c,v 1.295 2010/02/24 22:37:58 dyoung Exp $ */
 
 /*-
@@ -84,6 +85,10 @@
 #ifdef COM16650
 #error Obsolete COM16650 option; use COM_16650 instead.
 #endif
+#ifdef COM_16950
+/* 16950 include 16650 */
+#define COM_16650
+#endif
 
 /*
  * Override cnmagic(9) macro before including <sys/systm.h>.
@@ -122,6 +127,7 @@
 #include <dev/ic/comvar.h>
 #include <dev/ic/ns16550reg.h>
 #include <dev/ic/st16650reg.h>
+#include <dev/ic/ox16c950reg.h>
 #ifdef COM_HAYESP
 #include <dev/ic/hayespreg.h>
 #endif
@@ -263,6 +269,42 @@
 #define COM_BARRIER(r, f) \
        bus_space_barrier((r)->cr_iot, (r)->cr_ioh, 0, (r)->cr_nports, (f))
 
+#ifdef COM_16950
+static uint8_t com_16950reg_read(struct com_softc *, int);
+static __inline void com_16950reg_write(struct com_softc *, int, uint8_t);
+
+/*
+ * Caller must ensure that the last value written to LCR was not 
LCR_EERS(0xBF).
+ */
+
+static uint8_t
+com_16950reg_read(struct com_softc *sc, int offset)
+{
+       struct com_regs *regsp = &sc->sc_regs;
+       uint8_t val;
+
+       /* Set ACR_ICRRE of ACR (ICR read enable) */
+       com_16950reg_write(sc, COM_ACR, sc->sc_acr | ACR_ICRRE);
+
+       CSR_WRITE_1(regsp, COM_REG_TLR, offset);
+       val = CSR_READ_1(regsp, COM_REG_ICR);
+
+       /* Clear ACR_ICRRE of ACR (ICR read disable) */
+       com_16950reg_write(sc, COM_ACR, sc->sc_acr);
+
+       return val;
+}
+
+static __inline void
+com_16950reg_write(struct com_softc *sc, int offset, uint8_t val)
+{
+       struct com_regs *regsp = &sc->sc_regs;
+
+       CSR_WRITE_1(regsp, COM_REG_TLR, offset);
+       CSR_WRITE_1(regsp, COM_REG_ICR, val);
+}
+#endif
+
 /*ARGSUSED*/
 int
 comspeed(long speed, long frequency, int type)
@@ -374,9 +416,6 @@
 {
        struct com_regs *regsp = &sc->sc_regs;
        struct tty *tp;
-#ifdef COM_16650
-       u_int8_t lcr;
-#endif
        const char *fifo_msg = NULL;
 
        aprint_naive("\n");
@@ -440,9 +479,9 @@
            == IIR_FIFO_MASK)
                if (ISSET(CSR_READ_1(regsp, COM_REG_FIFO), FIFO_TRIGGER_14)
                    == FIFO_TRIGGER_14) {
-                       SET(sc->sc_hwflags, COM_HW_FIFO);
-
 #ifdef COM_16650
+                       uint8_t lcr;
+
                        /*
                         * IIR changes into the EFR if LCR is set to LCR_EERS
                         * on 16650s. We also know IIR != 0 at this point.
@@ -458,18 +497,47 @@
                        CSR_WRITE_1(regsp, COM_REG_LCR, LCR_EERS);
                        CSR_WRITE_1(regsp, COM_REG_EFR, 0);
                        if (CSR_READ_1(regsp, COM_REG_EFR) == 0) {
-                               CSR_WRITE_1(regsp, COM_REG_LCR,
-                                   lcr | LCR_DLAB);
-                               if (CSR_READ_1(regsp, COM_REG_EFR) == 0) {
-                                       CLR(sc->sc_hwflags, COM_HW_FIFO);
+                               CSR_WRITE_1(regsp, COM_REG_LCR, lcr | LCR_DLAB);
+                               if (CSR_READ_1(regsp, COM_REG_EFR) == 0)
                                        sc->sc_fifolen = 0;
-                               } else {
+                               else {
+#ifdef COM_16950
+                                       uint32_t id;
+                                       uint8_t id1, id2, id3;
+
+                                       id1 = com_16950reg_read(sc, COM_ID1);
+                                       id2 = com_16950reg_read(sc, COM_ID2);
+                                       id3 = com_16950reg_read(sc, COM_ID3);
+                                       id = id1 << 24 | id2 << 16 | id3 << 8;
+                                       if (id == COM_ID_16C950) {
+                                               sc->sc_fifolen = 128;
+                                               /*
+                                                * Always enable prescaler for
+                                                * support 921600bps.  However
+                                                * we possible more higher rate.
+                                                */
+                                               SET(sc->sc_mcr, MCR_PRESCALE);
+                                               sc->sc_frequency *= 8;
+                                       } else
+#endif
+                                       {
+                                               sc->sc_fifolen = 32;
+
+                                               /*
+                                                * 16c650 use divide-by-1 logic,
+                                                * not by-4.  max 460800bps.
+                                                */
+                                               sc->sc_frequency *= 4;
+                                       }
+                                       /* Also possible HW flow control */
                                        SET(sc->sc_hwflags, COM_HW_FLOW);
-                                       sc->sc_fifolen = 32;
+                                       sc->sc_efr |= EFR_EFCR;
                                }
                        } else
 #endif
                                sc->sc_fifolen = 16;
+                       if (sc->sc_fifolen > 0)
+                               SET(sc->sc_hwflags, COM_HW_FIFO);
 
 #ifdef COM_16650
                        CSR_WRITE_1(regsp, COM_REG_LCR, lcr);
@@ -477,6 +545,10 @@
                                fifo_msg = "st16650, broken fifo";
                        else if (sc->sc_fifolen == 32)
                                fifo_msg = "st16650a, working fifo";
+#ifdef COM_16950
+                       else if (sc->sc_fifolen == 128)
+                               fifo_msg = "ox16950, working fifo";
+#endif
                        else
 #endif
                                fifo_msg = "ns16550a, working fifo";
@@ -1314,7 +1386,7 @@
                sc->sc_mcr_dtr = MCR_DTR;
                sc->sc_mcr_rts = MCR_RTS;
                sc->sc_msr_cts = MSR_CTS;
-               sc->sc_efr = EFR_AUTORTS | EFR_AUTOCTS;
+               sc->sc_efr |= EFR_AUTORTS | EFR_AUTOCTS;
        } else if (ISSET(t->c_cflag, MDMBUF)) {
                /*
                 * For DTR/DCD flow control, make sure we don't toggle DTR for
@@ -1323,7 +1395,7 @@
                sc->sc_mcr_dtr = 0;
                sc->sc_mcr_rts = MCR_DTR;
                sc->sc_msr_cts = MSR_DCD;
-               sc->sc_efr = 0;
+               sc->sc_efr &= ~(EFR_AUTORTS | EFR_AUTOCTS);
        } else {
                /*
                 * If no flow control, then always set RTS.  This will make
@@ -1333,7 +1405,7 @@
                sc->sc_mcr_dtr = MCR_DTR | MCR_RTS;
                sc->sc_mcr_rts = 0;
                sc->sc_msr_cts = 0;
-               sc->sc_efr = 0;
+               sc->sc_efr &= ~(EFR_AUTORTS | EFR_AUTOCTS);
                if (ISSET(sc->sc_mcr, MCR_DTR))
                        SET(sc->sc_mcr, MCR_RTS);
                else
@@ -1473,12 +1545,24 @@
                CSR_WRITE_1(regsp, COM_REG_MDR1, MDR1_MODE_DISABLE);
        }
 
+       if (ISSET(sc->sc_mcr, MCR_PRESCALE)) {
+#ifdef COM_16950
+               /*
+                * Set prescaler divide by 1 and sampling clock 8.
+                *   TCR: 0-3 -> 16, 4-15 -> 4-15
+                *   XXX: possible more higher rate.
+                */
+               com_16950reg_write(sc, COM_CPR, CPR_CPR(1));
+               com_16950reg_write(sc, COM_TCR, 8);
+#endif
+       }
+
        if (ISSET(sc->sc_hwflags, COM_HW_FLOW)) {
                KASSERT(sc->sc_type != COM_TYPE_AU1x00);
                KASSERT(sc->sc_type != COM_TYPE_16550_NOERS);
                /* no EFR on alchemy */
-               CSR_WRITE_1(regsp, COM_REG_EFR, sc->sc_efr);
                CSR_WRITE_1(regsp, COM_REG_LCR, LCR_EERS);
+               CSR_WRITE_1(regsp, COM_REG_EFR, sc->sc_efr);
        }
        if (sc->sc_type == COM_TYPE_AU1x00) {
                /* alchemy has single separate 16-bit clock divisor register */
Index: comreg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/comreg.h,v
retrieving revision 1.15
diff -u -r1.15 comreg.h
--- comreg.h    28 Apr 2008 22:00:01 -0000      1.15
+++ comreg.h    1 Mar 2010 05:38:10 -0000
@@ -98,6 +98,7 @@
 #define        LCR_5BITS       0x00    /* 5 bits */
 
 /* modem control register */
+#define MCR_PRESCALE   0x80    /* 16650/16950: Baud rate prescaler select */
 #define MCR_TCR_TLR    0x40    /* OMAP: enables access to the TCR & TLR regs */
 #define MCR_XONENABLE  0x20    /* OMAP XON_EN */
 #define        MCR_LOOPBACK    0x10    /* Loop test: echos from TX to RX */
Index: comvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/comvar.h,v
retrieving revision 1.70
diff -u -r1.70 comvar.h
--- comvar.h    24 Feb 2010 22:37:58 -0000      1.70
+++ comvar.h    1 Mar 2010 05:38:10 -0000
@@ -122,6 +122,7 @@
 #define        COM_REG_LCR             com_lctl
 #define        COM_REG_MCR             com_mcr
 #define        COM_REG_LSR             com_lsr
+#define        COM_REG_ICR             com_icr
 #define        COM_REG_MSR             com_msr
 #define        COM_REG_TCR             com_msr
 #define        COM_REG_TLR             com_scratch
@@ -199,7 +200,8 @@
 
        volatile u_char sc_heldchange;
        volatile u_char sc_msr, sc_msr_delta, sc_msr_mask, sc_mcr,
-           sc_mcr_active, sc_lcr, sc_ier, sc_fifo, sc_dlbl, sc_dlbh, sc_efr;
+           sc_mcr_active, sc_lcr, sc_ier, sc_fifo, sc_dlbl, sc_dlbh, sc_efr,
+           sc_acr;
        u_char sc_mcr_dtr, sc_mcr_rts, sc_msr_cts, sc_msr_dcd;
 
 #ifdef COM_HAYESP


Home | Main Index | Thread Index | Old Index