summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorUwe Stuehler <uwe@cvs.openbsd.org>2005-05-27 18:42:16 +0000
committerUwe Stuehler <uwe@cvs.openbsd.org>2005-05-27 18:42:16 +0000
commitf67b3bbdf1c56ea614530171e6913535cc38d998 (patch)
tree0de55f92e1f96d92742640227ae243e08185de31 /sys/dev
parent12e63c2ae624606153e87d0007aaacb9b142a48d (diff)
- Merge changes from pxacom back into the common com driver.
Changes to the common com driver (partly from NetBSD): - Multiply before divide in comspeed() to avoid overflow (from NetBSD). - Don't call getc() and send -1 if the output queue is empty. - Take UART clock frequency as a parameter instead of using COM_FREQ. ok deraadt@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/com.c161
-rw-r--r--sys/dev/ic/comreg.h16
-rw-r--r--sys/dev/ic/comvar.h9
3 files changed, 165 insertions, 21 deletions
diff --git a/sys/dev/ic/com.c b/sys/dev/ic/com.c
index decf4d058ee..5c4528d30a0 100644
--- a/sys/dev/ic/com.c
+++ b/sys/dev/ic/com.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: com.c,v 1.99 2004/10/20 12:40:14 pefo Exp $ */
+/* $OpenBSD: com.c,v 1.100 2005/05/27 18:42:15 uwe Exp $ */
/* $NetBSD: com.c,v 1.82.4.1 1996/06/02 09:08:00 mrg Exp $ */
/*
@@ -74,7 +74,6 @@
#include <sys/uio.h>
#include <sys/kernel.h>
#include <sys/syslog.h>
-#include <sys/types.h>
#include <sys/device.h>
#include <sys/vnode.h>
#ifdef DDB
@@ -91,6 +90,16 @@
#include <dev/ic/ns16550reg.h>
#define com_lcr com_cfcr
+#ifdef COM_PXA2X0
+#define com_isr 8
+#define ISR_SEND (ISR_RXPL | ISR_XMODE | ISR_XMITIR)
+#define ISR_RECV (ISR_RXPL | ISR_XMODE | ISR_RCVEIR)
+#endif
+
+#ifdef __zaurus__
+#include <arch/zaurus/dev/zaurus_scoopvar.h>
+#endif
+
#include "com.h"
/* XXX: These belong elsewhere */
@@ -100,14 +109,20 @@ static u_char tiocm_xxx2mcr(int);
void compwroff(struct com_softc *);
void com_enable_debugport(struct com_softc *);
+void cominit(bus_space_tag_t, bus_space_handle_t, int, int);
+int com_is_console(bus_space_tag_t, bus_addr_t);
struct cfdriver com_cd = {
NULL, "com", DV_TTY
};
int comdefaultrate = TTYDEF_SPEED;
+int comconsfreq;
int comconsinit;
bus_addr_t comconsaddr;
+#ifdef COM_PXA2X0
+bus_addr_t comsiraddr;
+#endif
int comconsattached;
bus_space_tag_t comconsiot;
bus_space_handle_t comconsioh;
@@ -145,7 +160,7 @@ comspeed(freq, speed)
x = divrnd((freq / 16), speed);
if (x <= 0)
return -1;
- err = divrnd((freq / 16) * 1000, speed * x) - 1000;
+ err = divrnd((quad_t)freq * 1000 / 16, speed * x) - 1000;
if (err < 0)
err = -err;
if (err > COM_TOLERANCE)
@@ -187,6 +202,10 @@ com_attach_subr(sc)
u_int8_t lcr;
sc->sc_ier = 0;
+#ifdef COM_PXA2X0
+ if (sc->sc_uarttype == COM_UART_PXA2X0)
+ sc->sc_ier |= IER_EUART;
+#endif
/* disable interrupts */
bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
@@ -213,6 +232,10 @@ com_attach_subr(sc)
bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE);
delay(100);
+#ifdef COM_PXA2X0
+ /* Attachment driver presets COM_UART_PXA2X0. */
+ if (sc->sc_uarttype != COM_UART_PXA2X0)
+#endif
switch(bus_space_read_1(iot, ioh, com_iir) >> 6) {
case 0:
sc->sc_uarttype = COM_UART_16450;
@@ -289,6 +312,18 @@ com_attach_subr(sc)
SET(sc->sc_hwflags, COM_HW_FIFO);
sc->sc_fifolen = 16;
break;
+#ifdef COM_PXA2X0
+ case COM_UART_PXA2X0:
+ printf(": pxa2x0, 16 byte fifo");
+ SET(sc->sc_hwflags, COM_HW_FIFO);
+ sc->sc_fifolen = 16;
+ if (sc->sc_iobase == comsiraddr) {
+ SET(sc->sc_hwflags, COM_HW_SIR);
+ printf(" (SIR)");
+ }
+ printf("\n");
+ break;
+#endif
case COM_UART_ST16650:
printf(": st16650, no working fifo\n");
break;
@@ -372,6 +407,10 @@ com_enable_debugport(sc)
s = splhigh();
#ifdef KGDB
SET(sc->sc_ier, IER_ERXRDY);
+#ifdef COM_PXA2X0
+ if (sc->sc_uarttype == COM_UART_PXA2X0)
+ sc->sc_ier |= IER_EUART | IER_ERXTOUT;
+#endif
bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_ier, sc->sc_ier);
#endif
SET(sc->sc_mcr, MCR_DTR | MCR_RTS | MCR_IENABLE);
@@ -591,6 +630,10 @@ comopen(dev, flag, mode, p)
SET(sc->sc_mcr, MCR_IENABLE);
bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC;
+#ifdef COM_PXA2X0
+ if (sc->sc_uarttype == COM_UART_PXA2X0)
+ sc->sc_ier |= IER_EUART | IER_ERXTOUT;
+#endif
bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
sc->sc_msr = bus_space_read_1(iot, ioh, com_msr);
@@ -599,6 +642,15 @@ comopen(dev, flag, mode, p)
SET(tp->t_state, TS_CARR_ON);
else
CLR(tp->t_state, TS_CARR_ON);
+#ifdef COM_PXA2X0
+ if (sc->sc_uarttype == COM_UART_PXA2X0 &&
+ ISSET(sc->sc_hwflags, COM_HW_SIR)) {
+ bus_space_write_1(iot, ioh, com_isr, ISR_RECV);
+#ifdef __zaurus__
+ scoop_set_irled(1);
+#endif
+ }
+#endif
} else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0)
return EBUSY;
else
@@ -730,6 +782,12 @@ compwroff(sc)
bus_space_write_1(iot, ioh, com_ier, IER_SLEEP);
break;
}
+
+#if defined(COM_PXA2X0) && defined(__zaurus__)
+ if (sc->sc_uarttype == COM_UART_PXA2X0 &&
+ ISSET(sc->sc_hwflags, COM_HW_SIR))
+ scoop_set_irled(0);
+#endif
}
void
@@ -1078,6 +1136,13 @@ comstart(tp)
}
SET(tp->t_state, TS_BUSY);
+#ifdef COM_PXA2X0
+ /* Enable transmitter slow infrared mode. */
+ if (sc->sc_uarttype == COM_UART_PXA2X0 &&
+ ISSET(sc->sc_hwflags, COM_HW_SIR))
+ bus_space_write_1(iot, ioh, com_isr, ISR_SEND);
+#endif
+
/* Enable transmit completion interrupts. */
if (!ISSET(sc->sc_ier, IER_ETXRDY)) {
SET(sc->sc_ier, IER_ETXRDY);
@@ -1093,7 +1158,7 @@ comstart(tp)
for (i = 0; i < n; i++) {
bus_space_write_1(iot, ioh, com_data, buffer[i]);
}
- } else
+ } else if (tp->t_outq.c_cc != 0)
bus_space_write_1(iot, ioh, com_data, getc(&tp->t_outq));
out:
splx(s);
@@ -1102,6 +1167,21 @@ stopped:
if (ISSET(sc->sc_ier, IER_ETXRDY)) {
CLR(sc->sc_ier, IER_ETXRDY);
bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
+#ifdef COM_PXA2X0
+ if (sc->sc_uarttype == COM_UART_PXA2X0 &&
+ ISSET(sc->sc_hwflags, COM_HW_SIR)) {
+ int timo;
+
+ /* Wait for empty transmit shift register. */
+ timo = 20000;
+ while (!ISSET(bus_space_read_1(iot, ioh, com_lsr),
+ LSR_TSRE) && --timo)
+ delay(1);
+
+ /* Enable receiver slow infrared mode. */
+ bus_space_write_1(iot, ioh, com_isr, ISR_RECV);
+ }
+#endif
}
splx(s);
}
@@ -1362,6 +1442,12 @@ comintr(arg)
(*linesw[tp->t_line].l_start)(tp);
}
+#ifdef COM_PXA2X0
+ if (sc->sc_uarttype == COM_UART_PXA2X0 &&
+ ISSET(lsr, LSR_TXRDY) && ISSET(lsr, LSR_TSRE))
+ bus_space_write_1(iot, ioh, com_isr, ISR_RECV);
+#endif
+
if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND))
return (1);
}
@@ -1374,10 +1460,9 @@ comintr(arg)
#if defined(__sgi__)
#undef CONADDR
#undef COM_FREQ
-#include "machine/autoconf.h"
+#include <machine/autoconf.h>
#endif
-
/*
* The following functions are polled getc and putc routines, shared
* by the console and kgdb glue.
@@ -1391,6 +1476,11 @@ com_common_getc(iot, ioh)
int s = splhigh();
u_char stat, c;
+#ifdef COM_PXA2X0
+ if (com_is_console(iot, comsiraddr))
+ bus_space_write_1(iot, ioh, com_isr, ISR_RECV);
+#endif
+
/* block until a character becomes available */
while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY))
continue;
@@ -1416,7 +1506,11 @@ com_common_putc(iot, ioh, c)
while (!ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY) && --timo)
delay(1);
- bus_space_write_1(iot, ioh, com_data, c);
+#ifdef COM_PXA2X0
+ if (com_is_console(iot, comsiraddr))
+ bus_space_write_1(iot, ioh, com_isr, ISR_SEND);
+#endif
+ bus_space_write_1(iot, ioh, com_data, (u_int8_t)(c & 0xff));
bus_space_barrier(iot, ioh, 0, COM_NPORTS,
(BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE));
@@ -1425,28 +1519,42 @@ com_common_putc(iot, ioh, c)
while (!ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY) && --timo)
delay(1);
+#ifdef COM_PXA2X0
+ if (com_is_console(iot, comsiraddr)) {
+ /* wait for transmit shift register to become empty */
+ timo = 20000;
+ while (!ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_TSRE)
+ && --timo)
+ delay(1);
+
+ bus_space_write_1(iot, ioh, com_isr, ISR_RECV);
+ }
+#endif
+
splx(s);
}
-/*
- * Following are all routines needed for COM to act as console
- */
void
-cominit(iot, ioh, rate)
+cominit(iot, ioh, rate, frequency)
bus_space_tag_t iot;
bus_space_handle_t ioh;
- int rate;
+ int rate, frequency;
{
int s = splhigh();
u_char stat;
bus_space_write_1(iot, ioh, com_lcr, LCR_DLAB);
- rate = comspeed(COM_FREQ, rate); /* XXX not comdefaultrate? */
+ rate = comspeed(frequency, rate); /* XXX not comdefaultrate? */
bus_space_write_1(iot, ioh, com_dlbl, rate);
bus_space_write_1(iot, ioh, com_dlbh, rate >> 8);
bus_space_write_1(iot, ioh, com_lcr, LCR_8BITS);
bus_space_write_1(iot, ioh, com_mcr, MCR_DTR | MCR_RTS);
+#ifdef COM_PXA2X0
+ /* XXX */
+ bus_space_write_1(iot, ioh, com_ier, IER_EUART); /* Make sure they are off */
+#else
bus_space_write_1(iot, ioh, com_ier, 0); /* Make sure they are off */
+#endif
bus_space_write_1(iot, ioh, com_fifo,
FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1);
stat = bus_space_read_1(iot, ioh, com_iir);
@@ -1458,7 +1566,9 @@ comcnprobe(cp)
struct consdev *cp;
{
/* XXX NEEDS TO BE FIXED XXX */
-#if defined(__sgi__)
+#ifdef MD_ISA_IOT
+ bus_space_tag_t iot = MD_ISA_IOT;
+#elif defined(__sgi__)
bus_space_tag_t iot = sys_config.cons_iot;
#elif defined(hppa)
bus_space_tag_t iot = &hppa_bustag;
@@ -1512,7 +1622,10 @@ comcninit(cp)
if (bus_space_map(comconsiot, comconsaddr, COM_NPORTS, 0, &comconsioh))
panic("comcninit: mapping failed");
- cominit(comconsiot, comconsioh, comdefaultrate);
+ if (comconsfreq == 0)
+ comconsfreq = COM_FREQ;
+
+ cominit(comconsiot, comconsioh, comdefaultrate, comconsfreq);
comconsinit = 0;
}
@@ -1534,13 +1647,14 @@ comcnattach(iot, iobase, rate, frequency, cflag)
return ENOMEM;
#endif
- cominit(iot, comconsioh, rate);
+ cominit(iot, comconsioh, rate, frequency);
cn_tab = &comcons;
comconsiot = iot;
comconsaddr = iobase;
comconscflag = cflag;
+ comconsfreq = frequency;
return (0);
}
@@ -1591,7 +1705,7 @@ com_kgdb_attach(iot, iobase, rate, frequency, cflag)
panic("com_kgdb_attach: mapping failed");
/* XXX We currently don't respect KGDBMODE? */
- cominit(com_kgdb_iot, com_kgdb_ioh, rate);
+ cominit(com_kgdb_iot, com_kgdb_ioh, rate, frequency);
kgdb_attach(com_kgdb_getc, com_kgdb_putc, NULL);
kgdb_dev = 123; /* unneeded, only to satisfy some tests */
@@ -1618,3 +1732,16 @@ com_kgdb_putc(arg, c)
return (com_common_putc(com_kgdb_iot, com_kgdb_ioh, c));
}
#endif /* KGDB */
+
+int
+com_is_console(bus_space_tag_t iot, bus_addr_t iobase)
+{
+
+ if (comconsiot == iot && comconsaddr == iobase)
+ return (1);
+#ifdef KGDB
+ else if (com_kgdb_iot == iot && com_kgdb_addr == iobase)
+ return (1);
+#endif
+ return (0);
+}
diff --git a/sys/dev/ic/comreg.h b/sys/dev/ic/comreg.h
index 4d778fd42f0..7f7b65a8fdf 100644
--- a/sys/dev/ic/comreg.h
+++ b/sys/dev/ic/comreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: comreg.h,v 1.12 2004/12/23 17:50:24 markus Exp $ */
+/* $OpenBSD: comreg.h,v 1.13 2005/05/27 18:42:15 uwe Exp $ */
/* $NetBSD: comreg.h,v 1.8 1996/02/05 23:01:50 scottr Exp $ */
/*
@@ -69,6 +69,9 @@
#define IER_ERLS 0x4 /* Enable line status interrupt */
#define IER_EMSC 0x8 /* Enable modem status interrupt */
#define IER_SLEEP 0x10 /* Enable sleep mode */
+/* PXA2X0's ns16550 ports have extra bits in this register */
+#define IER_ERXTOUT 0x10 /* Enable rx timeout interrupt */
+#define IER_EUART 0x40 /* Enable UART */
/* interrupt identification register */
#define IIR_IMASK 0xf
@@ -169,7 +172,18 @@
#define FCTL_TRIGGER2 0x10
#define FCTL_TRIGGER3 0x20
+/* infrared selection register */
+#define ISR_XMITIR 0x01 /* transmitter SIR enable */
+#define ISR_RCVEIR 0x02 /* receiver SIR enable */
+#define ISR_XMODE 0x04 /* 1.6us transmit pulse width */
+#define ISR_TXPL 0x08 /* negative transmit data polarity */
+#define ISR_RXPL 0x10 /* negative receive data polarity */
+
+#ifdef COM_PXA2X0
+#define COM_NPORTS 9
+#else
#define COM_NPORTS 8
+#endif
/*
* WARNING: Serial console is assumed to be at COM1 address
diff --git a/sys/dev/ic/comvar.h b/sys/dev/ic/comvar.h
index 10f3a6dda85..e54172dda18 100644
--- a/sys/dev/ic/comvar.h
+++ b/sys/dev/ic/comvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: comvar.h,v 1.35 2004/10/20 12:40:14 pefo Exp $ */
+/* $OpenBSD: comvar.h,v 1.36 2005/05/27 18:42:15 uwe Exp $ */
/* $NetBSD: comvar.h,v 1.5 1996/05/05 19:50:47 christos Exp $ */
/*
@@ -103,10 +103,12 @@ struct com_softc {
#define COM_UART_ST16650V2 0x06 /* 32 byte fifo */
#define COM_UART_TI16750 0x07 /* 64 byte fifo */
#define COM_UART_XR16850 0x10 /* 128 byte fifo */
+#define COM_UART_PXA2X0 0x11 /* 16 byte fifo */
u_char sc_hwflags;
#define COM_HW_NOIEN 0x01
#define COM_HW_FIFO 0x02
+#define COM_HW_SIR 0x20
#define COM_HW_CONSOLE 0x40
#define COM_HW_KGDB 0x80
u_char sc_swflags;
@@ -133,7 +135,6 @@ struct com_softc {
};
int comprobe1(bus_space_tag_t, bus_space_handle_t);
-void cominit(bus_space_tag_t, bus_space_handle_t, int);
int comstop(struct tty *, int);
int comintr(void *);
int com_detach(struct device *, int);
@@ -141,7 +142,7 @@ int com_activate(struct device *, enum devact);
void comdiag(void *);
int comspeed(long, long);
-u_char com_cflag2lcr(tcflag_t);
+u_char com_cflag2lcr(tcflag_t); /* XXX undefined */
int comparam(struct tty *, struct termios *);
void comstart(struct tty *);
void comsoft(void *);
@@ -165,7 +166,9 @@ int kgdbintr(void *);
void com_attach_subr(struct com_softc *);
extern int comdefaultrate;
+extern int comconsfreq;
extern bus_addr_t comconsaddr;
+extern bus_addr_t comsiraddr;
extern int comconsinit;
extern int comconsattached;
extern bus_space_tag_t comconsiot;