Add 16650 hardware flowcontrol support. Basically PR 3844 from
Dave Huang <khym@bga.com>, with added check for broken early versions of the 16650, taken from the Linux driver. This should be extended to use, for example, higher trigger levels for the bigger 16650 FIFO, and its capability for using a smaller divisor and thus higher speeds. But this patch is very useful for 16650 users already.
This commit is contained in:
parent
985cca83b6
commit
961e39030d
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: com.c,v 1.115 1997/10/19 11:45:33 explorer Exp $ */
|
||||
/* $NetBSD: com.c,v 1.116 1997/10/19 14:26:16 fvdl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993, 1994, 1995, 1996, 1997
|
||||
@ -70,6 +70,7 @@
|
||||
|
||||
/*
|
||||
* COM driver, uses National Semiconductor NS16450/NS16550AF UART
|
||||
* Supports automatic hardware flow control on StarTech ST16C650A UART
|
||||
*/
|
||||
|
||||
#include "rnd.h"
|
||||
@ -98,6 +99,7 @@
|
||||
#include <dev/ic/comreg.h>
|
||||
#include <dev/ic/comvar.h>
|
||||
#include <dev/ic/ns16550reg.h>
|
||||
#include <dev/ic/st16650reg.h>
|
||||
#ifdef COM_HAYESP
|
||||
#include <dev/ic/hayespreg.h>
|
||||
#endif
|
||||
@ -348,6 +350,7 @@ com_attach_subr(sc)
|
||||
int iobase = sc->sc_iobase;
|
||||
bus_space_tag_t iot = sc->sc_iot;
|
||||
bus_space_handle_t ioh = sc->sc_ioh;
|
||||
u_int8_t lcr;
|
||||
#ifdef COM_HAYESP
|
||||
int hayesp_ports[] = { 0x140, 0x180, 0x280, 0x300, 0 };
|
||||
int *hayespp;
|
||||
@ -403,7 +406,6 @@ com_attach_subr(sc)
|
||||
/* No ESP; look for other things. */
|
||||
if (*hayespp == 0) {
|
||||
#endif
|
||||
|
||||
sc->sc_fifolen = 1;
|
||||
/* look for a NS 16550AF UART with FIFOs */
|
||||
bus_space_write_1(iot, ioh, com_fifo,
|
||||
@ -414,8 +416,39 @@ com_attach_subr(sc)
|
||||
if (ISSET(bus_space_read_1(iot, ioh, com_fifo), FIFO_TRIGGER_14)
|
||||
== FIFO_TRIGGER_14) {
|
||||
SET(sc->sc_hwflags, COM_HW_FIFO);
|
||||
printf(": ns16550a, working fifo\n");
|
||||
sc->sc_fifolen = 16;
|
||||
|
||||
/*
|
||||
* IIR changes into the EFR if LCR is set to LCR_EERS
|
||||
* on 16650s. We also know IIR != 0 at this point.
|
||||
* Write 0 into the EFR, and read it. If the result
|
||||
* is 0, we have a 16650.
|
||||
*
|
||||
* Older 16650s were broken; the test to detect them
|
||||
* is taken from the Linux driver. Apparently
|
||||
* setting DLAB enable gives access to the EFR on
|
||||
* these chips.
|
||||
*/
|
||||
lcr = bus_space_read_1(iot, ioh, com_lcr);
|
||||
bus_space_write_1(iot, ioh, com_lcr, LCR_EERS);
|
||||
bus_space_write_1(iot, ioh, com_efr, 0);
|
||||
if (bus_space_read_1(iot, ioh, com_efr) == 0) {
|
||||
bus_space_write_1(iot, ioh, com_lcr,
|
||||
lcr | LCR_DLAB);
|
||||
if (bus_space_read_1(iot, ioh, com_efr) == 0) {
|
||||
CLR(sc->sc_hwflags, COM_HW_FIFO);
|
||||
sc->sc_fifolen = 0;
|
||||
printf(": st16650, broken fifo\n");
|
||||
} else {
|
||||
SET(sc->sc_hwflags, COM_HW_FLOW);
|
||||
printf(": st16650a, working fifo\n");
|
||||
sc->sc_fifolen = 32;
|
||||
}
|
||||
} else {
|
||||
printf(": ns16550a, working fifo\n");
|
||||
sc->sc_fifolen = 16;
|
||||
}
|
||||
|
||||
bus_space_write_1(iot, ioh, com_lcr, LCR_8BITS);
|
||||
} else
|
||||
printf(": ns16550, broken fifo\n");
|
||||
else
|
||||
@ -950,6 +983,7 @@ comparam(tp, t)
|
||||
sc->sc_msr_cts = MSR_CTS;
|
||||
sc->sc_r_hiwat = RXHIWAT;
|
||||
sc->sc_r_lowat = RXLOWAT;
|
||||
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
|
||||
@ -960,6 +994,7 @@ comparam(tp, t)
|
||||
sc->sc_msr_cts = MSR_DCD;
|
||||
sc->sc_r_hiwat = RXHIWAT;
|
||||
sc->sc_r_lowat = RXLOWAT;
|
||||
sc->sc_efr = 0;
|
||||
} else {
|
||||
/*
|
||||
* If no flow control, then always set RTS. This will make
|
||||
@ -971,6 +1006,7 @@ comparam(tp, t)
|
||||
sc->sc_msr_cts = 0;
|
||||
sc->sc_r_hiwat = 0;
|
||||
sc->sc_r_lowat = 0;
|
||||
sc->sc_efr = 0;
|
||||
if (ISSET(sc->sc_mcr, MCR_DTR))
|
||||
SET(sc->sc_mcr, MCR_RTS);
|
||||
else
|
||||
@ -1082,6 +1118,10 @@ com_loadchannelregs(sc)
|
||||
|
||||
bus_space_write_1(iot, ioh, com_ier, 0);
|
||||
|
||||
if (ISSET(sc->sc_hwflags, COM_HW_FLOW)) {
|
||||
bus_space_write_1(iot, ioh, com_lcr, LCR_EERS);
|
||||
bus_space_write_1(iot, ioh, com_efr, sc->sc_efr);
|
||||
}
|
||||
bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr | LCR_DLAB);
|
||||
bus_space_write_1(iot, ioh, com_dlbl, sc->sc_dlbl);
|
||||
bus_space_write_1(iot, ioh, com_dlbh, sc->sc_dlbh);
|
||||
@ -1689,6 +1729,8 @@ cominit(iot, iobase, rate, frequency, cflag, iohp)
|
||||
if (bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh))
|
||||
return (ENOMEM); /* ??? */
|
||||
|
||||
bus_space_write_1(iot, ioh, com_lcr, LCR_EERS);
|
||||
bus_space_write_1(iot, ioh, com_efr, 0);
|
||||
bus_space_write_1(iot, ioh, com_lcr, LCR_DLAB);
|
||||
rate = comspeed(rate, frequency);
|
||||
bus_space_write_1(iot, ioh, com_dlbl, rate);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: comreg.h,v 1.10 1997/10/15 21:13:36 thorpej Exp $ */
|
||||
/* $NetBSD: comreg.h,v 1.11 1997/10/19 14:26:21 fvdl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
@ -45,6 +45,8 @@
|
||||
#define IER_ETXRDY 0x2 /* Enable transmitter empty interrupt */
|
||||
#define IER_ERLS 0x4 /* Enable line status interrupt */
|
||||
#define IER_EMSC 0x8 /* Enable modem status interrupt */
|
||||
#define IER_ERTS 0x40 /* Enable RTS interrupt */
|
||||
#define IER_ECTS 0x80 /* Enable CTS interrupt */
|
||||
|
||||
/* interrupt identification register */
|
||||
#define IIR_IMASK 0xf
|
||||
@ -66,7 +68,22 @@
|
||||
#define FIFO_TRIGGER_8 0x80 /* ibid 8 */
|
||||
#define FIFO_TRIGGER_14 0xc0 /* ibid 14 */
|
||||
|
||||
/* enhanced feature register */
|
||||
#define EFR_AUTOCTS 0x80 /* Automatic CTS flow control */
|
||||
#define EFR_AUTORTS 0x40 /* Automatic RTS flow control */
|
||||
#define EFR_SPECIAL 0x20 /* Special char detect */
|
||||
#define EFR_EFCR 0x10 /* Enhanced function control bit */
|
||||
#define EFR_TXFLOWBOTH 0x0c /* Automatic transmit XON/XOFF 1 and 2 */
|
||||
#define EFR_TXFLOW1 0x08 /* Automatic transmit XON/XOFF 1 */
|
||||
#define EFR_TXFLOW2 0x04 /* Automatic transmit XON/XOFF 2 */
|
||||
#define EFR_TXFLOWNONE 0x00 /* No automatic XON/XOFF transmit */
|
||||
#define EFR_RXFLOWBOTH 0x03 /* Automatic receive XON/XOFF 1 and 2 */
|
||||
#define EFR_RXFLOW1 0x02 /* Automatic receive XON/XOFF 1 */
|
||||
#define EFR_RXFLOW2 0x01 /* Automatic receive XON/XOFF 2 */
|
||||
#define EFR_RXFLOWNONE 0x00 /* No automatic XON/XOFF receive */
|
||||
|
||||
/* line control register */
|
||||
#define LCR_EERS 0xBF /* Enable access to Enhanced Register Set */
|
||||
#define LCR_DLAB 0x80 /* Divisor latch access enable */
|
||||
#define LCR_SBREAK 0x40 /* Break Control */
|
||||
#define LCR_PZERO 0x38 /* Space parity */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: comvar.h,v 1.17 1997/10/19 11:45:45 explorer Exp $ */
|
||||
/* $NetBSD: comvar.h,v 1.18 1997/10/19 14:26:23 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
|
||||
@ -47,6 +47,7 @@ int com_is_console __P((bus_space_tag_t, int, bus_space_handle_t *));
|
||||
#define COM_HW_NOIEN 0x01
|
||||
#define COM_HW_FIFO 0x02
|
||||
#define COM_HW_HAYESP 0x04
|
||||
#define COM_HW_FLOW 0x08
|
||||
#define COM_HW_CONSOLE 0x40
|
||||
#define COM_HW_KGDB 0x80
|
||||
|
||||
@ -77,7 +78,7 @@ struct com_softc {
|
||||
int sc_fifolen;
|
||||
|
||||
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_ier, sc_fifo, sc_dlbl, sc_dlbh, sc_efr;
|
||||
u_char sc_mcr_dtr, sc_mcr_rts, sc_msr_cts, sc_msr_dcd;
|
||||
|
||||
int sc_r_hiwat;
|
||||
|
Loading…
Reference in New Issue
Block a user