summaryrefslogtreecommitdiff
path: root/sys/dev/ic/com.c
diff options
context:
space:
mode:
authorrkujawa <rkujawa@NetBSD.org>2013-04-20 11:52:40 +0000
committerrkujawa <rkujawa@NetBSD.org>2013-04-20 11:52:40 +0000
commitb60110e705ec304fb7b78abd1c4e7fbadd698665 (patch)
treeda3024e2a752625b3bba3320b1d590121142cc5c /sys/dev/ic/com.c
parentec1fc9525168a8def5e67ecc8383c8b15f29ee69 (diff)
Add support for 16750 style UARTs. Activated by defining COM_16750.
Obtained from Marvell, Semihalf.
Diffstat (limited to 'sys/dev/ic/com.c')
-rw-r--r--sys/dev/ic/com.c50
1 files changed, 47 insertions, 3 deletions
diff --git a/sys/dev/ic/com.c b/sys/dev/ic/com.c
index 0124650712b..8b2478169a1 100644
--- a/sys/dev/ic/com.c
+++ b/sys/dev/ic/com.c
@@ -1,4 +1,4 @@
-/* $NetBSD: com.c,v 1.308 2013/02/24 06:21:36 matt Exp $ */
+/* $NetBSD: com.c,v 1.309 2013/04/20 11:52:40 rkujawa Exp $ */
/*-
* Copyright (c) 1998, 1999, 2004, 2008 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: com.c,v 1.308 2013/02/24 06:21:36 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: com.c,v 1.309 2013/04/20 11:52:40 rkujawa Exp $");
#include "opt_com.h"
#include "opt_ddb.h"
@@ -246,8 +246,17 @@ void com_kgdb_putc(void *, int);
#define COM_REG_16550 { \
com_data, com_data, com_dlbl, com_dlbh, com_ier, com_iir, com_fifo, \
com_efr, com_lcr, com_mcr, com_lsr, com_msr }
-
+/* 16750-specific register set, additional UART status register */
+#define COM_REG_16750 { \
+ com_data, com_data, com_dlbl, com_dlbh, com_ier, com_iir, com_fifo, \
+ com_efr, com_lcr, com_mcr, com_lsr, com_msr, 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, com_usr }
+
+#ifdef COM_16750
+const bus_size_t com_std_map[32] = COM_REG_16750;
+#else
const bus_size_t com_std_map[16] = COM_REG_16550;
+#endif /* COM_16750 */
#endif /* COM_REGMAP */
#define COMUNIT_MASK 0x7ffff
@@ -1466,6 +1475,20 @@ com_iflush(struct com_softc *sc)
if (!timo)
aprint_error_dev(sc->sc_dev, "com_iflush timeout %02x\n", reg);
#endif
+
+#ifdef COM_16750
+ uint8_t fifo;
+ /*
+ * Reset all Rx/Tx FIFO, preserve current FIFO length.
+ * This should prevent triggering busy interrupt while
+ * manipulating divisors.
+ */
+ fifo = CSR_READ_1(regsp, COM_REG_FIFO) & (FIFO_TRIGGER_1 |
+ FIFO_TRIGGER_4 | FIFO_TRIGGER_8 | FIFO_TRIGGER_14);
+ CSR_WRITE_1(regsp, COM_REG_FIFO, fifo | FIFO_ENABLE | FIFO_RCV_RST |
+ FIFO_XMT_RST);
+ delay(100);
+#endif
}
void
@@ -1892,6 +1915,27 @@ comintr(void *arg)
mutex_spin_enter(&sc->sc_lock);
iir = CSR_READ_1(regsp, COM_REG_IIR);
+
+ /* Handle ns16750-specific busy interrupt. */
+#ifdef COM_16750
+ int timeout;
+ if ((iir & IIR_BUSY) == IIR_BUSY) {
+ for (timeout = 10000;
+ (CSR_READ_1(regsp, COM_REG_USR) & 0x1) != 0; timeout--)
+ if (timeout <= 0) {
+ aprint_error_dev(sc->sc_dev,
+ "timeout while waiting for BUSY interrupt "
+ "acknowledge\n");
+ mutex_spin_exit(&sc->sc_lock);
+ return (0);
+ }
+
+ CSR_WRITE_1(regsp, COM_REG_LCR, sc->sc_lcr);
+ iir = CSR_READ_1(regsp, COM_REG_IIR);
+ }
+#endif /* COM_16750 */
+
+
if (ISSET(iir, IIR_NOPEND)) {
mutex_spin_exit(&sc->sc_lock);
return (0);