From 1fefc7192e3be2315a2c2e7060c4b78bbb66824c Mon Sep 17 00:00:00 2001 From: Martin Aberg Date: Thu, 9 Mar 2017 18:51:47 +0100 Subject: leon, apbuart: RX delayed interrupt Utilize the APBUART RX delayed interrupt if available. It also enables RX FIFO interrupt when used. The APBUART RX delayed interrupt is supported by the GR740. --- c/src/lib/libbsp/sparc/shared/uart/apbuart_cons.c | 44 +++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/c/src/lib/libbsp/sparc/shared/uart/apbuart_cons.c b/c/src/lib/libbsp/sparc/shared/uart/apbuart_cons.c index 27558e1848..ffec63dea4 100644 --- a/c/src/lib/libbsp/sparc/shared/uart/apbuart_cons.c +++ b/c/src/lib/libbsp/sparc/shared/uart/apbuart_cons.c @@ -50,6 +50,11 @@ extern void apbuart_outbyte_polled( extern int apbuart_inbyte_nonblocking(struct apbuart_regs *regs); extern struct apbuart_regs *dbg_uart; /* The debug UART */ +/* Probed hardware capabilities */ +enum { + CAP_FIFO = 0x01, /* FIFO available */ + CAP_DI = 0x02, /* RX delayed interrupt available */ +}; struct apbuart_priv { struct console_dev condev; struct drvmgr_dev *dev; @@ -58,6 +63,7 @@ struct apbuart_priv { char devName[32]; volatile int sending; int mode; + int cap; }; /* Getters for different interfaces. It happens to be just casting which we do @@ -186,6 +192,30 @@ static const rtems_termios_device_handler handler_polled = { .mode = TERMIOS_POLLED }; +/* + * APBUART hardware instantiation is flexible. Probe features here and driver + * can select appropriate routines for the hardware. probecap() return value + * is a CAP_ bitmask. + */ +static int probecap(struct apbuart_regs *regs) +{ + int cap = 0; + + /* Probe FIFO */ + if (regs->ctrl & APBUART_CTRL_FA) { + cap |= CAP_FIFO; + + /* Probe RX delayed interrupt */ + regs->ctrl |= APBUART_CTRL_DI; + if (regs->ctrl & APBUART_CTRL_DI) { + regs->ctrl &= ~APBUART_CTRL_DI; + cap |= CAP_DI; + } + } + + return cap; +} + int apbuart_init1(struct drvmgr_dev *dev) { struct apbuart_priv *priv; @@ -254,6 +284,8 @@ int apbuart_init1(struct drvmgr_dev *dev) priv->regs->ctrl = db; + priv->cap = probecap(priv->regs); + /* The system console and Debug console may depend on this device, so * initialize it straight away. * @@ -417,6 +449,7 @@ static bool first_open( if (uart->mode != TERMIOS_POLLED) { int ret; + uint32_t ctrl; /* Register interrupt and enable it */ ret = drvmgr_interrupt_register( @@ -427,8 +460,15 @@ static bool first_open( } uart->sending = 0; + /* Turn on RX interrupts */ - uart->regs->ctrl |= APBUART_CTRL_RI; + ctrl = uart->regs->ctrl; + ctrl |= APBUART_CTRL_RI; + if (uart->cap & CAP_DI) { + /* Use RX FIFO interrupt only if delayed interrupt available. */ + ctrl |= (APBUART_CTRL_DI | APBUART_CTRL_RF); + } + uart->regs->ctrl = ctrl; } return true; @@ -446,7 +486,7 @@ static void last_close( if (uart->mode != TERMIOS_POLLED) { /* Turn off RX interrupts */ rtems_termios_device_lock_acquire(base, &lock_context); - uart->regs->ctrl &= ~(APBUART_CTRL_RI); + uart->regs->ctrl &= ~(APBUART_CTRL_RI | APBUART_CTRL_RF); rtems_termios_device_lock_release(base, &lock_context); /**** Flush device ****/ -- cgit v1.2.3