summaryrefslogtreecommitdiff
path: root/sys/arch/octeon/dev/com_oct.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/octeon/dev/com_oct.c')
-rw-r--r--sys/arch/octeon/dev/com_oct.c108
1 files changed, 99 insertions, 9 deletions
diff --git a/sys/arch/octeon/dev/com_oct.c b/sys/arch/octeon/dev/com_oct.c
index b6ee0513a8d..49615e64301 100644
--- a/sys/arch/octeon/dev/com_oct.c
+++ b/sys/arch/octeon/dev/com_oct.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: com_oct.c,v 1.1 2010/09/20 06:32:30 syuu Exp $ */
+/* $OpenBSD: com_oct.c,v 1.2 2010/10/01 16:13:59 syuu Exp $ */
/*
* Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -30,14 +30,17 @@
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/tty.h>
+#include <sys/conf.h>
#include <machine/autoconf.h>
#include <machine/bus.h>
#include <dev/ic/comreg.h>
#include <dev/ic/comvar.h>
+#include <dev/cons.h>
#include <octeon/dev/obiovar.h>
+#include <octeon/dev/combusvar.h>
#include <octeon/dev/octeonreg.h>
int com_oct_probe(struct device *, void *, void *);
@@ -49,23 +52,38 @@ struct cfattach com_oct_ca = {
extern struct cfdriver com_cd;
+cons_decl(com_oct);
+
+#define OCTEON_MIO_UART0 0x8001180000000800ull
+#define OCTEON_MIO_UART0_LSR 0x8001180000000828ull
+#define OCTEON_MIO_UART0_RBR 0x8001180000000800ull
+#define OCTEON_MIO_UART0_USR 0x8001180000000938ull
+#define OCTEON_MIO_UART0_LCR 0x8001180000000818ull
+#define OCTEON_MIO_UART0_DLL 0x8001180000000880ull
+#define OCTEON_MIO_UART0_DLH 0x8001180000000888ull
+#define USR_TXFIFO_NOTFULL 2
+
+static int delay_changed = 1;
+int com_oct_delay(void);
+void com_oct_wait_txhr_empty(int);
+
int
com_oct_probe(struct device *parent, void *match, void *aux)
{
struct cfdata *cf = match;
- struct obio_attach_args *oba = aux;
- bus_space_tag_t iot = oba->oba_memt;
+ struct combus_attach_args *cba = aux;
+ bus_space_tag_t iot = cba->cba_memt;
bus_space_handle_t ioh;
int rv = 0, console;
- if (strcmp(oba->oba_name, com_cd.cd_name) != 0)
+ if (strcmp(cba->cba_name, com_cd.cd_name) != 0)
return 0;
console = 1;
/* if it's in use as console, it's there. */
if (!(console && !comconsattached)) {
- if (bus_space_map(iot, oba->oba_baseaddr, COM_NPORTS, 0, &ioh)) {
+ if (bus_space_map(iot, cba->cba_baseaddr, COM_NPORTS, 0, &ioh)) {
printf(": can't map uart registers\n");
return 1;
}
@@ -84,13 +102,13 @@ void
com_oct_attach(struct device *parent, struct device *self, void *aux)
{
struct com_softc *sc = (void *)self;
- struct obio_attach_args *oba = aux;
+ struct combus_attach_args *cba = aux;
int console;
console = 1;
- sc->sc_iot = oba->oba_memt;
- sc->sc_iobase = oba->oba_baseaddr;
+ sc->sc_iot = cba->cba_memt;
+ sc->sc_iobase = cba->cba_baseaddr;
sc->sc_hwflags = 0;
sc->sc_swflags = 0;
sc->sc_frequency = curcpu()->ci_hw.clock;
@@ -116,6 +134,78 @@ com_oct_attach(struct device *parent, struct device *self, void *aux)
com_attach_subr(sc);
- obio_intr_establish(oba->oba_intr, IPL_TTY, comintr,
+ obio_intr_establish(cba->cba_intr, IPL_TTY, comintr,
(void *)sc, sc->sc_dev.dv_xname);
}
+
+/*
+ * Early console routines.
+ */
+int
+com_oct_delay(void)
+{
+ int divisor;
+ u_char lcr;
+ static int d = 0;
+
+ if (!delay_changed) return d;
+ delay_changed = 0;
+ lcr = (u_char)*(uint64_t*)OCTEON_MIO_UART0_LCR;
+ *(uint64_t*)OCTEON_MIO_UART0_LCR = lcr | LCR_DLAB;
+ divisor = (int)(*(uint64_t*)OCTEON_MIO_UART0_DLL |
+ *(uint64_t*)OCTEON_MIO_UART0_DLH << 8);
+ *(uint64_t*)OCTEON_MIO_UART0_LCR = lcr;
+
+ return 10; /* return an approx delay value */
+}
+
+void
+com_oct_wait_txhr_empty(int d)
+{
+ while (((*(uint64_t*)OCTEON_MIO_UART0_LSR & LSR_TXRDY) == 0) &&
+ ((*(uint64_t*)OCTEON_MIO_UART0_USR & USR_TXFIFO_NOTFULL) == 0))
+ delay(d);
+}
+
+void
+com_octcninit(struct consdev *consdev)
+{
+}
+
+void
+com_octcnprobe(struct consdev *consdev)
+{
+}
+
+void
+com_octcnpollc(dev_t dev, int c)
+{
+}
+
+void
+com_octcnputc (dev_t dev, int c)
+{
+ int d;
+
+ /* 1/10th the time to transmit 1 character (estimate). */
+ d = com_oct_delay();
+ com_oct_wait_txhr_empty(d);
+ *(uint64_t*)OCTEON_MIO_UART0_RBR = (uint8_t)c;
+ com_oct_wait_txhr_empty(d);
+}
+
+int
+com_octcngetc (dev_t dev)
+{
+ int c, d;
+
+ /* 1/10th the time to transmit 1 character (estimate). */
+ d = com_oct_delay();
+
+ while ((*(uint64_t*)OCTEON_MIO_UART0_LSR & LSR_RXRDY) == 0)
+ delay(d);
+
+ c = (uint8_t)*(uint64_t*)OCTEON_MIO_UART0_RBR;
+
+ return (c);
+}