summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/uart/uart_core.c27
-rw-r--r--sys/dev/uart/uart_cpu.h30
-rw-r--r--sys/dev/uart/uart_dev_imx.c40
-rw-r--r--sys/dev/uart/uart_dev_lpc.c35
-rw-r--r--sys/dev/uart/uart_dev_ns8250.c33
-rw-r--r--sys/dev/uart/uart_dev_ns8250.h2
-rw-r--r--sys/dev/uart/uart_dev_pl011.c29
-rw-r--r--sys/dev/uart/uart_dev_quicc.c35
-rw-r--r--sys/dev/uart/uart_dev_sab82532.c33
-rw-r--r--sys/dev/uart/uart_dev_z8530.c28
-rw-r--r--sys/dev/uart/uart_if.m16
11 files changed, 271 insertions, 37 deletions
diff --git a/sys/dev/uart/uart_core.c b/sys/dev/uart/uart_core.c
index 17dabd7..08ac576 100644
--- a/sys/dev/uart/uart_core.c
+++ b/sys/dev/uart/uart_core.c
@@ -412,6 +412,13 @@ uart_bus_attach(device_t dev)
sc = sc0;
/*
+ * Now that we know the softc for this device, connect the back
+ * pointer from the sysdev for this device, if any
+ */
+ if (sc->sc_sysdev != NULL)
+ sc->sc_sysdev->sc = sc;
+
+ /*
* Protect ourselves against interrupts while we're not completely
* finished attaching and initializing. We don't expect interrupts
* until after UART_ATTACH() though.
@@ -617,3 +624,23 @@ uart_bus_resume(device_t dev)
sc = device_get_softc(dev);
return (UART_ATTACH(sc));
}
+
+void
+uart_grab(struct uart_devinfo *di)
+{
+
+ uart_lock(di->hwmtx);
+ if (di->sc)
+ UART_GRAB(di->sc);
+ uart_unlock(di->hwmtx);
+}
+
+void
+uart_ungrab(struct uart_devinfo *di)
+{
+
+ uart_lock(di->hwmtx);
+ if (di->sc)
+ UART_UNGRAB(di->sc);
+ uart_unlock(di->hwmtx);
+}
diff --git a/sys/dev/uart/uart_cpu.h b/sys/dev/uart/uart_cpu.h
index 99ced1a..2db0412 100644
--- a/sys/dev/uart/uart_cpu.h
+++ b/sys/dev/uart/uart_cpu.h
@@ -33,6 +33,8 @@
#include <sys/lock.h>
#include <sys/mutex.h>
+struct uart_softc;
+
/*
* Low-level operations for use by console and/or debug port support.
*/
@@ -43,8 +45,6 @@ struct uart_ops {
void (*putc)(struct uart_bas *, int);
int (*rxready)(struct uart_bas *);
int (*getc)(struct uart_bas *, struct mtx *);
- void (*grab)(struct uart_bas *);
- void (*ungrab)(struct uart_bas *);
};
extern bus_space_tag_t uart_bus_space_io;
@@ -53,7 +53,6 @@ extern bus_space_tag_t uart_bus_space_mem;
/*
* Console and debug port device info.
*/
-struct uart_softc;
struct uart_devinfo {
SLIST_ENTRY(uart_devinfo) next;
struct uart_ops *ops;
@@ -70,6 +69,7 @@ struct uart_devinfo {
int (*detach)(struct uart_softc*);
void *cookie; /* Type dependent use. */
struct mtx *hwmtx;
+ struct uart_softc *sc; /* valid only from start of attach */
};
int uart_cpu_eqres(struct uart_bas *, struct uart_bas *);
@@ -137,27 +137,6 @@ uart_putc(struct uart_devinfo *di, int c)
uart_unlock(di->hwmtx);
}
-static __inline void
-uart_grab(struct uart_devinfo *di)
-{
-
- uart_lock(di->hwmtx);
- if (di->ops->grab)
- di->ops->grab(&di->bas);
- uart_unlock(di->hwmtx);
-}
-
-static __inline void
-uart_ungrab(struct uart_devinfo *di)
-{
-
- uart_lock(di->hwmtx);
- if (di->ops->ungrab)
- di->ops->ungrab(&di->bas);
- uart_unlock(di->hwmtx);
-}
-
-
static __inline int
uart_rxready(struct uart_devinfo *di)
{
@@ -190,4 +169,7 @@ uart_getc(struct uart_devinfo *di)
return (di->ops->getc(&di->bas, di->hwmtx));
}
+void uart_grab(struct uart_devinfo *di);
+void uart_ungrab(struct uart_devinfo *di);
+
#endif /* _DEV_UART_CPU_H_ */
diff --git a/sys/dev/uart/uart_dev_imx.c b/sys/dev/uart/uart_dev_imx.c
index 22ee8cc..e99cf77 100644
--- a/sys/dev/uart/uart_dev_imx.c
+++ b/sys/dev/uart/uart_dev_imx.c
@@ -140,6 +140,8 @@ static int imx_uart_bus_probe(struct uart_softc *);
static int imx_uart_bus_receive(struct uart_softc *);
static int imx_uart_bus_setsig(struct uart_softc *, int);
static int imx_uart_bus_transmit(struct uart_softc *);
+static void imx_uart_bus_grab(struct uart_softc *);
+static void imx_uart_bus_ungrab(struct uart_softc *);
static kobj_method_t imx_uart_methods[] = {
KOBJMETHOD(uart_attach, imx_uart_bus_attach),
@@ -153,6 +155,8 @@ static kobj_method_t imx_uart_methods[] = {
KOBJMETHOD(uart_receive, imx_uart_bus_receive),
KOBJMETHOD(uart_setsig, imx_uart_bus_setsig),
KOBJMETHOD(uart_transmit, imx_uart_bus_transmit),
+ KOBJMETHOD(uart_grab, imx_uart_bus_grab),
+ KOBJMETHOD(uart_ungrab, imx_uart_bus_ungrab),
{ 0, 0 }
};
@@ -189,12 +193,7 @@ imx_uart_bus_attach(struct uart_softc *sc)
(void)imx_uart_bus_getsig(sc);
- /* XXX workaround to have working console on mount prompt */
- if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE){
- DIS(bas, UCR4, DREN);
- } else {
- ENA(bas, UCR4, DREN);
- }
+ ENA(bas, UCR4, DREN);
DIS(bas, UCR1, RRDYEN);
DIS(bas, UCR1, IDEN);
DIS(bas, UCR3, RXDSEN);
@@ -402,13 +401,6 @@ static int
imx_uart_bus_setsig(struct uart_softc *sc, int sig)
{
- /* TODO: implement (?) */
-
- /* XXX workaround to have working console on mount prompt */
- /* Enable RX interrupt */
- if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE)
- if (!IS(&sc->sc_bas, UCR4, DREN))
- ENA(&sc->sc_bas, UCR4, DREN);
return (0);
}
@@ -434,3 +426,25 @@ imx_uart_bus_transmit(struct uart_softc *sc)
return (0);
}
+
+static void
+imx_uart_bus_grab(struct uart_softc *sc)
+{
+ struct uart_bas *bas = &sc->sc_bas;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ DIS(bas, UCR4, DREN);
+ uart_unlock(sc->sc_hwmtx);
+}
+
+static void
+imx_uart_bus_ungrab(struct uart_softc *sc)
+{
+ struct uart_bas *bas = &sc->sc_bas;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ ENA(bas, UCR4, DREN);
+ uart_unlock(sc->sc_hwmtx);
+}
diff --git a/sys/dev/uart/uart_dev_lpc.c b/sys/dev/uart/uart_dev_lpc.c
index 708d343..08cebc9 100644
--- a/sys/dev/uart/uart_dev_lpc.c
+++ b/sys/dev/uart/uart_dev_lpc.c
@@ -401,6 +401,8 @@ static int lpc_ns8250_bus_probe(struct uart_softc *);
static int lpc_ns8250_bus_receive(struct uart_softc *);
static int lpc_ns8250_bus_setsig(struct uart_softc *, int);
static int lpc_ns8250_bus_transmit(struct uart_softc *);
+static void lpc_ns8250_bus_grab(struct uart_softc *);
+static void lpc_ns8250_bus_ungrab(struct uart_softc *);
static kobj_method_t lpc_ns8250_methods[] = {
KOBJMETHOD(uart_attach, lpc_ns8250_bus_attach),
@@ -414,6 +416,8 @@ static kobj_method_t lpc_ns8250_methods[] = {
KOBJMETHOD(uart_receive, lpc_ns8250_bus_receive),
KOBJMETHOD(uart_setsig, lpc_ns8250_bus_setsig),
KOBJMETHOD(uart_transmit, lpc_ns8250_bus_transmit),
+ KOBJMETHOD(uart_grab, lpc_ns8250_bus_grab),
+ KOBJMETHOD(uart_ungrab, lpc_ns8250_bus_ungrab),
{ 0, 0 }
};
@@ -890,3 +894,34 @@ lpc_ns8250_bus_transmit(struct uart_softc *sc)
uart_unlock(sc->sc_hwmtx);
return (0);
}
+
+void
+lpc_ns8250_bus_grab(struct uart_softc *sc)
+{
+ struct uart_bas *bas = &sc->sc_bas;
+
+ /*
+ * turn off all interrupts to enter polling mode. Leave the
+ * saved mask alone. We'll restore whatever it was in ungrab.
+ * All pending interupt signals are reset when IER is set to 0.
+ */
+ uart_lock(sc->sc_hwmtx);
+ uart_setreg(bas, REG_IER, 0);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+}
+
+void
+lpc_ns8250_bus_ungrab(struct uart_softc *sc)
+{
+ struct lpc_ns8250_softc *lpc_ns8250 = (struct lpc_ns8250_softc*)sc;
+ struct uart_bas *bas = &sc->sc_bas;
+
+ /*
+ * Restore previous interrupt mask
+ */
+ uart_lock(sc->sc_hwmtx);
+ uart_setreg(bas, REG_IER, lpc_ns8250->ier);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+}
diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c
index 249be4c..47a61bf 100644
--- a/sys/dev/uart/uart_dev_ns8250.c
+++ b/sys/dev/uart/uart_dev_ns8250.c
@@ -365,6 +365,8 @@ static kobj_method_t ns8250_methods[] = {
KOBJMETHOD(uart_receive, ns8250_bus_receive),
KOBJMETHOD(uart_setsig, ns8250_bus_setsig),
KOBJMETHOD(uart_transmit, ns8250_bus_transmit),
+ KOBJMETHOD(uart_grab, ns8250_bus_grab),
+ KOBJMETHOD(uart_ungrab, ns8250_bus_ungrab),
{ 0, 0 }
};
@@ -922,3 +924,34 @@ ns8250_bus_transmit(struct uart_softc *sc)
uart_sched_softih(sc, SER_INT_TXIDLE);
return (0);
}
+
+void
+ns8250_bus_grab(struct uart_softc *sc)
+{
+ struct uart_bas *bas = &sc->sc_bas;
+
+ /*
+ * turn off all interrupts to enter polling mode. Leave the
+ * saved mask alone. We'll restore whatever it was in ungrab.
+ * All pending interupt signals are reset when IER is set to 0.
+ */
+ uart_lock(sc->sc_hwmtx);
+ uart_setreg(bas, REG_IER, 0);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+}
+
+void
+ns8250_bus_ungrab(struct uart_softc *sc)
+{
+ struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc;
+ struct uart_bas *bas = &sc->sc_bas;
+
+ /*
+ * Restore previous interrupt mask
+ */
+ uart_lock(sc->sc_hwmtx);
+ uart_setreg(bas, REG_IER, ns8250->ier);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+}
diff --git a/sys/dev/uart/uart_dev_ns8250.h b/sys/dev/uart/uart_dev_ns8250.h
index 39f4a0f..0046dfe 100644
--- a/sys/dev/uart/uart_dev_ns8250.h
+++ b/sys/dev/uart/uart_dev_ns8250.h
@@ -56,5 +56,7 @@ int ns8250_bus_probe(struct uart_softc *);
int ns8250_bus_receive(struct uart_softc *);
int ns8250_bus_setsig(struct uart_softc *, int);
int ns8250_bus_transmit(struct uart_softc *);
+void ns8250_bus_grab(struct uart_softc *);
+void ns8250_bus_ungrab(struct uart_softc *);
#endif /* _DEV_UART_DEV_NS8250_H_ */
diff --git a/sys/dev/uart/uart_dev_pl011.c b/sys/dev/uart/uart_dev_pl011.c
index 82e8b03..3253cd1 100644
--- a/sys/dev/uart/uart_dev_pl011.c
+++ b/sys/dev/uart/uart_dev_pl011.c
@@ -242,6 +242,8 @@ static int uart_pl011_bus_probe(struct uart_softc *);
static int uart_pl011_bus_receive(struct uart_softc *);
static int uart_pl011_bus_setsig(struct uart_softc *, int);
static int uart_pl011_bus_transmit(struct uart_softc *);
+static void uart_pl011_bus_grab(struct uart_softc *);
+static void uart_pl011_bus_ungrab(struct uart_softc *);
static kobj_method_t uart_pl011_methods[] = {
KOBJMETHOD(uart_attach, uart_pl011_bus_attach),
@@ -255,6 +257,9 @@ static kobj_method_t uart_pl011_methods[] = {
KOBJMETHOD(uart_receive, uart_pl011_bus_receive),
KOBJMETHOD(uart_setsig, uart_pl011_bus_setsig),
KOBJMETHOD(uart_transmit, uart_pl011_bus_transmit),
+ KOBJMETHOD(uart_grab, uart_pl011_bus_grab),
+ KOBJMETHOD(uart_ungrab, uart_pl011_bus_ungrab),
+
{ 0, 0 }
};
@@ -441,3 +446,27 @@ uart_pl011_bus_transmit(struct uart_softc *sc)
return (0);
}
+
+static void
+uart_pl011_bus_grab(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ __uart_setreg(bas, UART_IMSC, /* Switch to RX polling while grabbed */
+ ~UART_RXREADY & __uart_getreg(bas, UART_IMSC));
+ uart_unlock(sc->sc_hwmtx);
+}
+
+static void
+uart_pl011_bus_ungrab(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ __uart_setreg(bas, UART_IMSC, /* Switch to RX interrupts while not grabbed */
+ UART_RXREADY | __uart_getreg(bas, UART_IMSC));
+ uart_unlock(sc->sc_hwmtx);
+}
diff --git a/sys/dev/uart/uart_dev_quicc.c b/sys/dev/uart/uart_dev_quicc.c
index 337591e..bbbc3bd 100644
--- a/sys/dev/uart/uart_dev_quicc.c
+++ b/sys/dev/uart/uart_dev_quicc.c
@@ -245,6 +245,8 @@ static int quicc_bus_probe(struct uart_softc *);
static int quicc_bus_receive(struct uart_softc *);
static int quicc_bus_setsig(struct uart_softc *, int);
static int quicc_bus_transmit(struct uart_softc *);
+static void quicc_bus_grab(struct uart_softc *);
+static void quicc_bus_ungrab(struct uart_softc *);
static kobj_method_t quicc_methods[] = {
KOBJMETHOD(uart_attach, quicc_bus_attach),
@@ -258,6 +260,8 @@ static kobj_method_t quicc_methods[] = {
KOBJMETHOD(uart_receive, quicc_bus_receive),
KOBJMETHOD(uart_setsig, quicc_bus_setsig),
KOBJMETHOD(uart_transmit, quicc_bus_transmit),
+ KOBJMETHOD(uart_grab, quicc_bus_grab),
+ KOBJMETHOD(uart_ungrab, quicc_bus_ungrab),
{ 0, 0 }
};
@@ -485,3 +489,34 @@ quicc_bus_transmit(struct uart_softc *sc)
uart_unlock(sc->sc_hwmtx);
return (0);
}
+
+static void
+quicc_bus_grab(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ uint16_t st, rb;
+
+ /* Disable interrupts on the receive buffer. */
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1));
+ st = quicc_read2(bas, rb);
+ quicc_write2(bas, rb, st & ~0x9000);
+ uart_unlock(sc->sc_hwmtx);
+}
+
+static void
+quicc_bus_ungrab(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ uint16_t st, rb;
+
+ /* Enable interrupts on the receive buffer. */
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1));
+ st = quicc_read2(bas, rb);
+ quicc_write2(bas, rb, st | 0x9000);
+ uart_unlock(sc->sc_hwmtx);
+}
+
diff --git a/sys/dev/uart/uart_dev_sab82532.c b/sys/dev/uart/uart_dev_sab82532.c
index e2ec227..8caa7a7 100644
--- a/sys/dev/uart/uart_dev_sab82532.c
+++ b/sys/dev/uart/uart_dev_sab82532.c
@@ -365,6 +365,8 @@ static int sab82532_bus_probe(struct uart_softc *);
static int sab82532_bus_receive(struct uart_softc *);
static int sab82532_bus_setsig(struct uart_softc *, int);
static int sab82532_bus_transmit(struct uart_softc *);
+static void sab82532_bus_grab(struct uart_softc *);
+static void sab82532_bus_ungrab(struct uart_softc *);
static kobj_method_t sab82532_methods[] = {
KOBJMETHOD(uart_attach, sab82532_bus_attach),
@@ -378,6 +380,8 @@ static kobj_method_t sab82532_methods[] = {
KOBJMETHOD(uart_receive, sab82532_bus_receive),
KOBJMETHOD(uart_setsig, sab82532_bus_setsig),
KOBJMETHOD(uart_transmit, sab82532_bus_transmit),
+ KOBJMETHOD(uart_grab, sab82532_bus_grab),
+ KOBJMETHOD(uart_ungrab, sab82532_bus_ungrab),
{ 0, 0 }
};
@@ -724,3 +728,32 @@ sab82532_bus_transmit(struct uart_softc *sc)
uart_unlock(sc->sc_hwmtx);
return (0);
}
+
+static void
+sab82532_bus_grab(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ uint8_t imr0;
+
+ bas = &sc->sc_bas;
+ imr0 = SAB_IMR0_TIME|SAB_IMR0_CDSC|SAB_IMR0_RFO; /* No TCD or RPF */
+ uart_lock(sc->sc_hwmtx);
+ uart_setreg(bas, SAB_IMR0, 0xff & ~imr0);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+}
+
+static void
+sab82532_bus_ungrab(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ uint8_t imr0;
+
+ bas = &sc->sc_bas;
+ imr0 = SAB_IMR0_TCD|SAB_IMR0_TIME|SAB_IMR0_CDSC|SAB_IMR0_RFO|
+ SAB_IMR0_RPF;
+ uart_lock(sc->sc_hwmtx);
+ uart_setreg(bas, SAB_IMR0, 0xff & ~imr0);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+}
diff --git a/sys/dev/uart/uart_dev_z8530.c b/sys/dev/uart/uart_dev_z8530.c
index f948b26..5cc24a8 100644
--- a/sys/dev/uart/uart_dev_z8530.c
+++ b/sys/dev/uart/uart_dev_z8530.c
@@ -281,6 +281,8 @@ static int z8530_bus_probe(struct uart_softc *);
static int z8530_bus_receive(struct uart_softc *);
static int z8530_bus_setsig(struct uart_softc *, int);
static int z8530_bus_transmit(struct uart_softc *);
+static void z8530_bus_grab(struct uart_softc *);
+static void z8530_bus_ungrab(struct uart_softc *);
static kobj_method_t z8530_methods[] = {
KOBJMETHOD(uart_attach, z8530_bus_attach),
@@ -294,6 +296,8 @@ static kobj_method_t z8530_methods[] = {
KOBJMETHOD(uart_receive, z8530_bus_receive),
KOBJMETHOD(uart_setsig, z8530_bus_setsig),
KOBJMETHOD(uart_transmit, z8530_bus_transmit),
+ KOBJMETHOD(uart_grab, z8530_bus_grab),
+ KOBJMETHOD(uart_ungrab, z8530_bus_ungrab),
{ 0, 0 }
};
@@ -621,3 +625,27 @@ z8530_bus_transmit(struct uart_softc *sc)
uart_unlock(sc->sc_hwmtx);
return (0);
}
+
+static void
+z8530_bus_grab(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ uart_setmreg(bas, WR_IDT, IDT_XIE | IDT_TIE);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+}
+
+static void
+z8530_bus_ungrab(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ uart_setmreg(bas, WR_IDT, IDT_XIE | IDT_TIE | IDT_RIA);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+}
diff --git a/sys/dev/uart/uart_if.m b/sys/dev/uart/uart_if.m
index bfac071..aab7771 100644
--- a/sys/dev/uart/uart_if.m
+++ b/sys/dev/uart/uart_if.m
@@ -141,3 +141,19 @@ METHOD int setsig {
METHOD int transmit {
struct uart_softc *this;
};
+
+# grab() - Up call from the console to the upper layers of the driver when
+# the kernel asks to grab the console. This is valid only for console
+# drivers. This method is responsible for transitioning the hardware
+# from an interrupt driven state to a polled state that works with the
+# low-level console interface defined for this device. The kernel
+# currently only calls this when it wants to grab input from the
+# console. Output can still happen asyncrhonously to these calls.
+METHOD void grab {
+ struct uart_softc *this;
+};
+
+# ungrab() - Undoes the effects of grab().
+METHOD void ungrab {
+ struct uart_softc *this;
+};
OpenPOWER on IntegriCloud