From 63b93a9fbad66e1e538aa75c10952d9c3f0c54c2 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 18 Oct 2017 09:17:08 -0600 Subject: [PATCH] BCM2708: Add framework for a Mini-UART driver (incomplete) --- arch/arm/src/bcm2708/Make.defs | 4 + arch/arm/src/bcm2708/bcm_lowputc.c | 6 + arch/arm/src/bcm2708/bcm_lowputc.h | 8 +- arch/arm/src/bcm2708/bcm_miniuart.c | 823 ++++++++++++++++++++++++ arch/arm/src/bcm2708/chip/bcm2708_aux.h | 144 +++-- 5 files changed, 913 insertions(+), 72 deletions(-) create mode 100644 arch/arm/src/bcm2708/bcm_miniuart.c diff --git a/arch/arm/src/bcm2708/Make.defs b/arch/arm/src/bcm2708/Make.defs index b788a9bf783..f1124f02973 100644 --- a/arch/arm/src/bcm2708/Make.defs +++ b/arch/arm/src/bcm2708/Make.defs @@ -77,3 +77,7 @@ CHIP_CSRCS += bcm_tickless.c bcm_gpio.c bcm_aux.c bcm_lowputc.c bcm_serial.c ifeq ($(CONFIG_BCM2708_GPIO_IRQ),y) CHIP_CSRCS += bcm_gpioint.c endif + +ifeq ($(CONFIG_BCM2708_MINI_UART),y) +CHIP_CSRCS += bcm_miniuart.c +endif diff --git a/arch/arm/src/bcm2708/bcm_lowputc.c b/arch/arm/src/bcm2708/bcm_lowputc.c index a65abc0dbb4..29e638bdc6c 100644 --- a/arch/arm/src/bcm2708/bcm_lowputc.c +++ b/arch/arm/src/bcm2708/bcm_lowputc.c @@ -80,6 +80,12 @@ static const struct uart_config_s g_console_config = .parity = BCM_CONSOLE_PARITY, /* 0=none, 1=odd, 2=even */ .bits = BCM_CONSOLE_BITS, /* Number of bits (5-9) */ .stopbits2 = BCM_CONSOLE_2STOP, /* true: Configure with 2 stop bits instead of 1 */ +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .iflow = false; /* true: Input flow control enabled */ +#endif +#ifdef CONFIG_SERIAL_OFLOWCONTROL + .oflow = false; /* true: Output flow control enabled. */ +#endif }; #endif diff --git a/arch/arm/src/bcm2708/bcm_lowputc.h b/arch/arm/src/bcm2708/bcm_lowputc.h index aa0db7eef36..d419bc16804 100644 --- a/arch/arm/src/bcm2708/bcm_lowputc.h +++ b/arch/arm/src/bcm2708/bcm_lowputc.h @@ -54,7 +54,6 @@ * Public Types ****************************************************************************/ -#ifdef BCM_HAVE_UART /* This structure describes the configuration of an UART */ struct uart_config_s @@ -63,8 +62,13 @@ struct uart_config_s uint8_t parity; /* 0=none, 1=odd, 2=even */ uint8_t bits; /* Number of bits (5-9) */ bool stopbits2; /* true: Configure with 2 stop bits instead of 1 */ -}; +#ifdef CONFIG_SERIAL_IFLOWCONTROL + bool iflow; /* true: Input flow control enabled */ #endif +#ifdef CONFIG_SERIAL_OFLOWCONTROL + bool oflow; /* true: Output flow control enabled. */ +#endif +}; /**************************************************************************** * Public Function Prototypes diff --git a/arch/arm/src/bcm2708/bcm_miniuart.c b/arch/arm/src/bcm2708/bcm_miniuart.c new file mode 100644 index 00000000000..f2eb8fa6e15 --- /dev/null +++ b/arch/arm/src/bcm2708/bcm_miniuart.c @@ -0,0 +1,823 @@ +/**************************************************************************** + * arch/arm/src/bcm2708/bcm_miniuart.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_SERIAL_TERMIOS +# include +#endif + +#include +#include + +#include "up_arch.h" +#include "up_internal.h" + +#include "chip/bcm2708_aux.h" +#include "bcm_lowputc.h" +#include "bcm_aux.h" + +#ifdef CONFIG_BCM2708_MINI_UART + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* If we are not using the serial driver for the console, then we still must + * provide some minimal implementation of up_putc. + */ + +#ifdef USE_SERIALDRIVER + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct bcm_dev_s +{ + uint32_t baud; /* Configured baud */ + uint8_t parity; /* 0=none, 1=odd, 2=even */ + uint8_t bits; /* Number of bits (8 or 9) */ + uint8_t stop2; /* Use 2 stop bits */ + uint8_t ier; /* Interrupts enabled */ +#ifdef CONFIG_SERIAL_IFLOWCONTROL + bool iflow; /* input flow control (RTS) enabled */ +#endif +#ifdef CONFIG_SERIAL_OFLOWCONTROL + bool oflow; /* output flow control (CTS) enabled */ +#endif +#ifdef CONFIG_SERIAL_IFLOWCONTROL + gpio_pinset_t rts_gpio; /* UART RTS GPIO pin configuration */ +#endif +#ifdef CONFIG_SERIAL_OFLOWCONTROL + gpio_pinset_t cts_gpio; /* UART CTS GPIO pin configuration */ +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int bcm_setup(struct uart_dev_s *dev); +static void bcm_shutdown(struct uart_dev_s *dev); +static int bcm_attach(struct uart_dev_s *dev); +static void bcm_detach(struct uart_dev_s *dev); +static int bcm_ioctl(struct file *filep, int cmd, unsigned long arg); +static int bcm_receive(struct uart_dev_s *dev, uint32_t *status); +static void bcm_rxint(struct uart_dev_s *dev, bool enable); +static bool bcm_rxavailable(struct uart_dev_s *dev); +#ifdef CONFIG_SERIAL_IFLOWCONTROL +static bool bcm_rxflowcontrol(struct uart_dev_s *dev, unsigned int nbuffered, + bool upper); +#endif +static void bcm_send(struct uart_dev_s *dev, int ch); +static void bcm_txint(struct uart_dev_s *dev, bool enable); +static bool bcm_txready(struct uart_dev_s *dev); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct uart_ops_s g_miniuart_ops = +{ + .setup = bcm_setup, + .shutdown = bcm_shutdown, + .attach = bcm_attach, + .detach = bcm_detach, + .ioctl = bcm_ioctl, + .receive = bcm_receive, + .rxint = bcm_rxint, + .rxavailable = bcm_rxavailable, +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .rxflowcontrol = bcm_rxflowcontrol, +#endif + .send = bcm_send, + .txint = bcm_txint, + .txready = bcm_txready, + .txempty = bcm_txready, +}; + +/* I/O buffers */ + +static char g_miniuart_rxbuffer[CONFIG_BCM2708_MINI_UART_RXBUFSIZE]; +static char g_miniuart_txbuffer[CONFIG_BCM2708_MINI_UART_TXBUFSIZE]; + +/* This describes the state of the Kinetis Mini-UART0 port. */ + +static struct bcm_dev_s g_miniuart_priv = +{ + .baud = CONFIG_BCM2708_MINI_UART_BAUD, + .parity = CONFIG_BCM2708_MINI_UART_BITS, + .bits = CONFIG_BCM2708_MINI_UART_PARITY, + .stop2 = CONFIG_BCM2708_MINI_UART_2STOP, +#if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(BCM2708_MINI_UART_OFLOWCONTROL) + .oflow = true, + .cts_gpio = xxxx, +#endif +#if defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(BCM2708_MINI_UART_IFLOWCONTROL) + .iflow = true, + .rts_gpio = xxxx, +#endif +}; + +static uart_dev_t g_miniuart_port = +{ + .recv = + { + .size = CONFIG_BCM2708_MINI_UART_RXBUFSIZE, + .buffer = g_miniuart_rxbuffer, + }, + .xmit = + { + .size = CONFIG_BCM2708_MINI_UART_TXBUFSIZE, + .buffer = g_miniuart_txbuffer, + }, + .ops = &g_miniuart_ops, + .priv = &g_miniuart_priv, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bcm_setuartint + ****************************************************************************/ + +static void bcm_setuartint(struct bcm_dev_s *priv) +{ + modifyreg8(BCM_AUX_MU_IER, BCM_AUX_MU_IO_TXD | BCM_AUX_MU_IO_RXD, priv->ier); +} + +/**************************************************************************** + * Name: bcm_restoreuartint + ****************************************************************************/ + +static void bcm_restoreuartint(struct bcm_dev_s *priv, uint8_t ier) +{ + irqstate_t flags; + + /* Re-enable/re-disable interrupts corresponding to the state of bits in ie */ + + flags = enter_critical_section(); + priv->ier = ier & (BCM_AUX_MU_IO_TXD | BCM_AUX_MU_IO_RXD); + bcm_setuartint(priv); + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: bcm_disableuartint + ****************************************************************************/ + +static void bcm_disableuartint(struct bcm_dev_s *priv, uint8_t *ier) +{ + irqstate_t flags; + + flags = enter_critical_section(); + if (ier != NULL) + { + *ier = priv->ier; + } + + bcm_restoreuartint(priv, 0); + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: bcm_setup + * + * Description: + * Configure the Mini-UART baud, bits, parity, etc. This method is called the + * first time that the serial port is opened. + * + ****************************************************************************/ + +static int bcm_setup(struct uart_dev_s *dev) +{ +#ifndef CONFIG_SUPPRESS_UART_CONFIG + struct bcm_dev_s *priv = (struct bcm_dev_s *)dev->priv; + struct uart_config_s config; +#endif + + /* Enable Mini-UART register access */ + + bcm_aux_disable(BCM_AUX_MINI_UART); + + /* Make sure that all interrupts are disabled */ + + bcm_restoreuartint(priv, 0); + +#ifndef CONFIG_SUPPRESS_UART_CONFIG + /* Configure the Mini-UART */ + + config.baud = priv->baud; + config.parity = priv->parity; + config.bits = priv->bits; + config.stopbits2 = priv->stop2; +#ifdef CONFIG_SERIAL_IFLOWCONTROL + config.iflow = priv->iflow; +#endif +#ifdef CONFIG_SERIAL_OFLOWCONTROL + config.oflow = priv->oflow; +#endif + + bcm_miniuart_configure(&config); +#endif + + return OK; +} + +/**************************************************************************** + * Name: bcm_shutdown + * + * Description: + * Disable the Mini-UART. This method is called when the serial + * port is closed + * + ****************************************************************************/ + +static void bcm_shutdown(struct uart_dev_s *dev) +{ + struct bcm_dev_s *priv = (struct bcm_dev_s *)dev->priv; + + /* Disable interrupts */ + + bcm_restoreuartint(priv, 0); + + /* Disable the Mini-UART */ + + bcm_aux_disable(BCM_AUX_MINI_UART); +} + +/**************************************************************************** + * Name: bcm_attach + * + * Description: + * Configure the Mini-UART to operation in interrupt driven mode. This + * method is called when the serial port is opened. Normally, this is + * just after the setup() method is called, however, the serial + * console may operate in a non-interrupt driven mode during the boot phase. + * + * RX and TX interrupts are not enabled when by the attach method (unless + * the hardware supports multiple levels of interrupt enabling). The RX + * and TX interrupts are not enabled until the txint() and rxint() methods + * are called. + * + ****************************************************************************/ + +static int bcm_attach(struct uart_dev_s *dev) +{ + /* Nothing to do here... this is all handled in bcm_aux.c */ + + return OK; +} + +/**************************************************************************** + * Name: bcm_detach + * + * Description: + * Detach Mini-UART interrupts. This method is called when the serial port + * is closed normally just before the shutdown method is called. The + * exception is the serial console which is never shutdown. + * + ****************************************************************************/ + +static void bcm_detach(struct uart_dev_s *dev) +{ + struct bcm_dev_s *priv = (struct bcm_dev_s *)dev->priv; + + /* There is not much to do here. Interrupt related logic is handled in + * handled in bcm_aux.c. + */ + + /* Disable Mini-UART interrupts */ + + bcm_restoreuartint(priv, 0); +} + +/**************************************************************************** + * Name: bcm_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * + ****************************************************************************/ + +static int bcm_ioctl(struct file *filep, int cmd, unsigned long arg) +{ +#if defined(CONFIG_SERIAL_TERMIOS) || defined(CONFIG_SERIAL_TIOCSERGSTRUCT) || \ + defined(CONFIG_KINETIS_SERIALBRK_BSDCOMPAT) + struct inode *inode; + struct uart_dev_s *dev; + uint8_t regval; +#endif +#if defined(CONFIG_SERIAL_TERMIOS) || defined(CONFIG_KINETIS_SERIALBRK_BSDCOMPAT) + struct bcm_dev_s *priv; + bool iflow = false; + bool oflow = false; +#endif + int ret = OK; + +#if defined(CONFIG_SERIAL_TERMIOS) || defined(CONFIG_SERIAL_TIOCSERGSTRUCT) || \ + defined(CONFIG_KINETIS_SERIALBRK_BSDCOMPAT) + DEBUGASSERT(filep != NULL && filep->f_inode != NULL); + inode = filep->f_inode; + dev = inode->i_private; + DEBUGASSERT(dev != NULL && dev->priv != NULL); +#endif + +#if defined(CONFIG_SERIAL_TERMIOS) || defined(CONFIG_KINETIS_SERIALBRK_BSDCOMPAT) + priv = (struct bcm_dev_s *)dev->priv; +#endif + + switch (cmd) + { +#ifdef CONFIG_SERIAL_TIOCSERGSTRUCT + case TIOCSERGSTRUCT: + { + struct bcm_dev_s *user = (struct bcm_dev_s *)arg; + if (!user) + { + ret = -EINVAL; + } + else + { + memcpy(user, dev, sizeof(struct bcm_dev_s)); + } + } + break; +#endif + +#ifdef CONFIG_SERIAL_TERMIOS + case TCGETS: + { + struct termios *termiosp = (struct termios *)arg; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + cfsetispeed(termiosp, priv->baud); + + /* Note: CSIZE only supports 5-8 bits. The driver only support 8/9 bit + * modes and therefore is no way to report 9-bit mode, we always claim + * 8 bit mode. + */ + + termiosp->c_cflag = + ((priv->parity != 0) ? PARENB : 0) | + ((priv->parity == 1) ? PARODD : 0) | + ((priv->stop2) ? CSTOPB : 0) | +# ifdef CONFIG_SERIAL_OFLOWCONTROL + ((priv->oflow) ? CCTS_OFLOW : 0) | +# endif +# ifdef CONFIG_SERIAL_IFLOWCONTROL + ((priv->iflow) ? CRTS_IFLOW : 0) | +# endif + CS8; + + /* TODO: CCTS_IFLOW, CCTS_OFLOW */ + } + break; + + case TCSETS: + { + struct termios *termiosp = (struct termios *)arg; + struct uart_config_s config; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + /* Perform some sanity checks before accepting any changes */ + + if (((termiosp->c_cflag & CSIZE) != CS8) +# ifdef CONFIG_SERIAL_IFLOWCONTROL + || ((termiosp->c_cflag & CCTS_OFLOW) && (priv->cts_gpio == 0)) +# endif +# ifdef CONFIG_SERIAL_IFLOWCONTROL + || ((termiosp->c_cflag & CRTS_IFLOW) && (priv->rts_gpio == 0)) +# endif + ) + { + ret = -EINVAL; + break; + } + + if (termiosp->c_cflag & PARENB) + { + priv->parity = (termiosp->c_cflag & PARODD) ? 1 : 2; + } + else + { + priv->parity = 0; + } + + priv->stop2 = (termiosp->c_cflag & CSTOPB) != 0; +# ifdef CONFIG_SERIAL_OFLOWCONTROL + priv->oflow = (termiosp->c_cflag & CCTS_OFLOW) != 0; + oflow = priv->oflow; +# endif +# ifdef CONFIG_SERIAL_IFLOWCONTROL + priv->iflow = (termiosp->c_cflag & CRTS_IFLOW) != 0; + iflow = priv->iflow; +# endif + + /* Note that since there is no way to request 9-bit mode + * and no way to support 5/6/7-bit modes, we ignore them + * all here. + */ + + /* Note that only cfgetispeed is used because we have knowledge + * that only one speed is supported. + */ + + priv->baud = cfgetispeed(termiosp); + + /* Effect the changes immediately - note that we do not implement + * TCSADRAIN / TCSAFLUSH + */ + + config.baud = priv->baud; + config.parity = priv->parity; + config.bits = priv->bits; + config.stopbits2 = priv->stop2; +#ifdef CONFIG_SERIAL_IFLOWCONTROL + config.iflow = priv->iflow; +#endif +#ifdef CONFIG_SERIAL_OFLOWCONTROL + config.oflow = priv->oflow; +#endif + bcm_miniuart_configure(&config); + } + break; +#endif /* CONFIG_SERIAL_TERMIOS */ + + default: + ret = -ENOTTY; + break; + } + + return ret; +} + +/**************************************************************************** + * Name: bcm_receive + * + * Description: + * Called (usually) from the interrupt level to receive one + * character from the Mini-UART. Error bits associated with the + * receipt are provided in the return 'status'. + * + ****************************************************************************/ + +static int bcm_receive(struct uart_dev_s *dev, uint32_t *status) +{ + struct bcm_dev_s *priv = (struct bcm_dev_s *)dev->priv; + +#warning Missing logic + return 0; +} + +/**************************************************************************** + * Name: bcm_rxint + * + * Description: + * Call to enable or disable RX interrupts + * + ****************************************************************************/ + +static void bcm_rxint(struct uart_dev_s *dev, bool enable) +{ + struct bcm_dev_s *priv = (struct bcm_dev_s *)dev->priv; + irqstate_t flags; + + flags = enter_critical_section(); + if (enable) + { + /* Receive an interrupt when their is anything in the Rx data register + * (or an Rx related error occurs). + */ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + priv->ier |= BCM_AUX_MU_IER_RXD; + bcm_setuartint(priv); +#endif + } + else + { + priv->ier &= ~BCM_AUX_MU_IER_RXD; + bcm_setuartint(priv); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: bcm_rxavailable + * + * Description: + * Return true if the receive register is not empty + * + ****************************************************************************/ + +static bool bcm_rxavailable(struct uart_dev_s *dev) +{ + struct bcm_dev_s *priv = (struct bcm_dev_s *)dev->priv; +#warning Missing logic + return false; +} + +/**************************************************************************** + * Name: bcm_rxflowcontrol + * + * Description: + * Called when Rx buffer is full (or exceeds configured watermark levels + * if CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS is defined). + * Return true if UART activated RX flow control to block more incoming + * data + * + * Input parameters: + * dev - UART device instance + * nbuffered - the number of characters currently buffered + * (if CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS is + * not defined the value will be 0 for an empty buffer or the + * defined buffer size for a full buffer) + * upper - true indicates the upper watermark was crossed where + * false indicates the lower watermark has been crossed + * + * Returned Value: + * true if RX flow control activated. + * + ****************************************************************************/ + +#ifdef CONFIG_SERIAL_IFLOWCONTROL +static bool bcm_rxflowcontrol(struct uart_dev_s *dev, + unsigned int nbuffered, bool upper) +{ +#warning Missing logic + return false; +} +#endif + +/**************************************************************************** + * Name: bcm_send + * + * Description: + * This method will send one byte on the Mini-UART. + * + ****************************************************************************/ + +static void bcm_send(struct uart_dev_s *dev, int ch) +{ + struct bcm_dev_s *priv = (struct bcm_dev_s *)dev->priv; +#warning Missing logic +} + +/**************************************************************************** + * Name: bcm_txint + * + * Description: + * Call to enable or disable TX interrupts + * + ****************************************************************************/ + +static void bcm_txint(struct uart_dev_s *dev, bool enable) +{ + struct bcm_dev_s *priv = (struct bcm_dev_s *)dev->priv; + irqstate_t flags; + + flags = enter_critical_section(); + if (enable) + { + /* Enable the TX interrupt */ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + priv->ier |= BCM_AUX_MU_IER_TXD; + bcm_setuartint(priv); + + /* Fake a TX interrupt here by just calling uart_xmitchars() with + * interrupts disabled (note this may recurse). + */ + + uart_xmitchars(dev); +#endif + } + else + { + /* Disable the TX interrupt */ + + priv->ier &= ~BCM_AUX_MU_IER_TXD; + bcm_setuartint(priv); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: bcm_txready + * + * Description: + * Return true if the transmit data register is empty + * + ****************************************************************************/ + +static bool bcm_txready(struct uart_dev_s *dev) +{ + struct bcm_dev_s *priv = (struct bcm_dev_s *)dev->priv; +#warning Missing logic + return false; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bcm_mu_interrupt + * + * Description: + * This is the Mini-UART status interrupt handler. It will be invoked by + * logic in bcm_aux.c when the common AUX interrupt interupt is received + * and a pending Mini-UART interrupt is pending. + * + * Then interrupt handler should call uart_transmitchars() or + * uart_receivechar() to perform the appropriate data transfers.\ + * + ****************************************************************************/ + +int bcm_mu_interrupt(int irq, void *context, void *arg) +{ +#warning Missing logic + return OK; +} + +/**************************************************************************** + * Name: bcm_lpuart_earlyserialinit + * + * Description: + * Performs the low level Mini-UART initialization early in debug so that the + * serial console will be available during bootup. This must be called + * before up_serialinit. NOTE: This function depends on GPIO pin + * configuration performed in bcm_lowsetup() and main clock initialization + * performed in up_clkinitialize(). + * + ****************************************************************************/ + +void bcm_lpuart_earlyserialinit(void) +{ + /* Disable interrupts from all Mini-UARTS. The console is enabled in + * bcm_setup() + */ + + bcm_restoreuartint(g_miniuart_port.priv, 0); + +#ifdef CONFIG_BCM2708_MINI_UART_SERIAL_CONSOLE + /* Configure the Mini-USAR console */ + + g_miniuart_port.isconsole = true; + bcm_setup(&g_miniuart_port); +#endif +} + +/**************************************************************************** + * Name: bcm_miniuart_serialinit + * + * Description: + * Register the Mini-UART serial console and serial port. This assumes + * that up_earlyserialinit was called previously. + * + * Input Parameters: + * + * Returned Value: + * None + * + ****************************************************************************/ + +void bcm_miniuart_serialinit(void) +{ +/* Register Mini-UART the console */ + +#ifdef CONFIG_BCM2708_MINI_UART_SERIAL_CONSOLE + (void)uart_register("/dev/console", &g_miniuart_port); +#endif + + /* Register the Mini-UART as /dev/ttyS0 */ + + (void)uart_register("/dev/ttyS0", &g_miniuart_port); +} + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ +#ifdef CONFIG_BCM2708_MINI_UART_SERIAL_CONSOLE + struct bcm_dev_s *priv = (struct bcm_dev_s *)g_miniuart_port.priv; + uint8_t ier; + + bcm_disableuartint(priv, &ier); + + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + up_lowputc('\r'); + } + + up_lowputc(ch); + bcm_restoreuartint(priv, ier); +#endif + return ch; +} + +#else /* USE_SERIALDRIVER */ + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ +#ifdef CONFIG_BCM2708_MINI_UART_SERIAL_CONSOLE + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + up_lowputc('\r'); + } + + up_lowputc(ch); +#endif + + return ch; +} + +#endif /* USE_SERIALDRIVER */ +#endif /* CONFIG_BCM2708_MINI_UART */ diff --git a/arch/arm/src/bcm2708/chip/bcm2708_aux.h b/arch/arm/src/bcm2708/chip/bcm2708_aux.h index 3e97f79fb79..097076c5635 100644 --- a/arch/arm/src/bcm2708/chip/bcm2708_aux.h +++ b/arch/arm/src/bcm2708/chip/bcm2708_aux.h @@ -33,15 +33,16 @@ * ************************************************************************************/ -#ifndef __ARCH_ARM_SRC_BCM_CHIP_BCM_AUX_H -#define __ARCH_ARM_SRC_BCM_CHIP_BCM_AUX_H +#ifndef __ARCH_ARM_SRC_BCM2708_CHIP_BCM2708_AUX_H +#define __ARCH_ARM_SRC_BCM2708_CHIP_BCM2708_AUX_H /************************************************************************************ * Included Files ************************************************************************************/ #include -#include "chip.h" + +#include "chip/bcm2708_memorymap.h" /************************************************************************************ * Pre-processor Definitions @@ -103,80 +104,83 @@ /* UART Register Bit Definitions ****************************************************/ -#define BCM_AUX_IRQ_MU (1 << 0) /* Mini UART IRQ pending */ -#define BCM_AUX_IRQ_SPI1 (1 << 1) /* SPI 1 IRQ pending */ -#define BCM_AUX_IRQ_SPI2 (1 << 2) /* SPI 2 IRQ pending */ +#define BCM_AUX_IRQ_MU (1 << 0) /* Mini UART IRQ pending */ +#define BCM_AUX_IRQ_SPI1 (1 << 1) /* SPI 1 IRQ pending */ +#define BCM_AUX_IRQ_SPI2 (1 << 2) /* SPI 2 IRQ pending */ -#define BCM_AUX_ENB_MU (1 << 0) /* Mini UART Enable */ -#define BCM_AUX_ENB_SPI1 (1 << 1) /* SPI 1 Enable */ -#define BCM_AUX_ENB_SPI2 (1 << 2) /* SPI 2 Enable */ +#define BCM_AUX_ENB_MU (1 << 0) /* Mini UART Enable */ +#define BCM_AUX_ENB_SPI1 (1 << 1) /* SPI 1 Enable */ +#define BCM_AUX_ENB_SPI2 (1 << 2) /* SPI 2 Enable */ -#define BCM_AUX_MU_IO_SHIFT 0 /* LSB 8-bit of baudrate or TXD/RXD */ -#define BCM_AUX_MU_IO_BAUDRATE (0xff << BCM_AUX_MU_IO_SHIFT) /* If DLAB = 1 */ -#define BCM_AUX_MU_IO_TXD (0xff << BCM_AUX_MU_IO_SHIFT) /* If DLAB = 0 */ -#define BCM_AUX_MU_IO_RXD (0xff << BCM_AUX_MU_IO_SHIFT) /* If DLAB = 0 */ +#define BCM_AUX_MU_IO_SHIFT 0 /* LSB 8-bit of baudrate or TXD/RXD */ +#define BCM_AUX_MU_IO_BAUDRATE (0xff << BCM_AUX_MU_IO_SHIFT) /* If DLAB = 1 */ +#define BCM_AUX_MU_IO_TXD (0 << BCM_AUX_MU_IO_SHIFT) /* If DLAB = 0 */ +#define BCM_AUX_MU_IO_RXD (1 << BCM_AUX_MU_IO_SHIFT) /* If DLAB = 0 */ -#define BCM_AUX_MU_IER_SHIFT 0 /* MSB 8-bit of baudrate or IRQTXE/IRQRXE */ -#define BCM_AUX_MU_IER_BAUDRATE (0xff << BCM_AUX_MU_IIR_SHIFT) /* If DLAB = 1 */ -#define BCM_AUX_MU_IER_TXD (1 << 0) /* Enable Transmit Interruption */ -#define BCM_AUX_MU_IER_RXD (1 << 1) /* Enable Receive Interruption */ +#define BCM_AUX_MU_IER_SHIFT 0 /* MSB 8-bit of baudrate or IRQTXE/IRQRXE */ +#define BCM_AUX_MU_IER_BAUDRATE (0xff << BCM_AUX_MU_IER_SHIFT) /* If DLAB = 1 */ +#define BCM_AUX_MU_IER_TXD (1 << 0) /* Enable Transmit Interrupt */ +#define BCM_AUX_MU_IER_RXD (1 << 1) /* Enable Receive Interrupt */ -#define BCM_AUX_MU_IIR_PEND (1 << 0) /* This bit is clear whenever an IRQ is pending */ -#define BCM_AUX_MU_IIR_SHIFT 1 /* On read this register shows the interrupt ID bit */ -# define BCM_AUX_MU_IIR_NONE (0 << BCM_AUX_MU_IIR_SHIFT) /* No ints */ -# define BCM_AUX_MU_IIR_TXEMPTY (1 << BCM_AUX_MU_IIR_SHIFT) /* TX FIFO empty */ -# define BCM_AUX_MU_IIR_RXDATA (2 << BCM_AUX_MU_IIR_SHIFT) /* Data in TX FIFO */ +#define BCM_AUX_MU_IIR_PEND (1 << 0) /* This bit is clear whenever an IRQ is pending */ +#define BCM_AUX_MU_IIR_SHIFT 1 /* On read this register shows the interrupt ID bit */ +#define BCM_AUX_MU_IIR_MASK (3 << BCM_AUX_MU_IIR_SHIFT) +# define BCM_AUX_MU_IIR_NONE (0 << BCM_AUX_MU_IIR_SHIFT) /* No interrupts */ +# define BCM_AUX_MU_IIR_TXEMPTY (1 << BCM_AUX_MU_IIR_SHIFT) /* TX FIFO empty (read) */ +# define BCM_AUX_MU_IIR_RXDATA (2 << BCM_AUX_MU_IIR_SHIFT) /* Data in RX FIFO (read) */ +# define BCM_AUX_MU_IIR_TXCLEAR (1 << BCM_AUX_MU_IIR_SHIFT) /* Clear RX FIFO (write) */ +# define BCM_AUX_MU_IIR_RXCLEAR (2 << BCM_AUX_MU_IIR_SHIFT) /* Clear TX FIFO (write) */ -#define BCM_AUX_MU_LCR_DATA8BIT (1 << 0) /* 1 = UART 8-bit 0 = UART 7-bit */ -#define BCM_AUX_MU_LCR_BREAK (1 << 6) /* Set UART TX line to low, breaks if at least 12 bits times */ -#define BCM_AUX_MU_LCR_DLAB (1 << 7) /* If set access Baudrate register */ +#define BCM_AUX_MU_LCR_DATA8BIT (1 << 0) /* 1 = UART 8-bit 0 = UART 7-bit */ +#define BCM_AUX_MU_LCR_BREAK (1 << 6) /* Set UART TX line to low, breaks if at least 12 bits times */ +#define BCM_AUX_MU_LCR_DLAB (1 << 7) /* If set access Baudrate register */ -#define BCM_AUX_MU_MCR_RTS (1 << 1) /* if set RTS line is low */ +#define BCM_AUX_MU_MCR_RTS (1 << 1) /* if set RTS line is low */ -#define BCM_AUX_MU_LSR_DTREADY (1 << 0) /* This bit is set if FIFO has data */ -#define BCM_AUX_MU_LSR_RXOVR (1 << 1) /* Receiver Overrun */ -#define BCM_AUX_MU_LSR_TXEMPTY (1 << 5) /* TX FIFO can accept at least 1 byte */ -#define BCM_AUX_MU_LSR_TXIDLE (1 << 6) /* TX FIFO empty and transmitter idle */ +#define BCM_AUX_MU_LSR_DTREADY (1 << 0) /* This bit is set if FIFO has data */ +#define BCM_AUX_MU_LSR_RXOVR (1 << 1) /* Receiver Overrun */ +#define BCM_AUX_MU_LSR_TXEMPTY (1 << 5) /* TX FIFO can accept at least 1 byte */ +#define BCM_AUX_MU_LSR_TXIDLE (1 << 6) /* TX FIFO empty and transmitter idle */ -#define BCM_AUX_MU_MSR_CTS (1 << 5) /* Holds the inverse of UART CTS status */ +#define BCM_AUX_MU_MSR_CTS (1 << 5) /* Holds the inverse of UART CTS status */ -#define BCM_AUX_MU_CNTL_RXEN (1 << 0) /* Receiver Enable */ -#define BCM_AUX_MU_CNTL_TXEN (1 << 1) /* Transmitter Enable */ -#define BCM_AUX_MU_CNTL_RXAUTOFLOW (1 << 2) /* Enable RXD Auto-flow using RTS */ -#define BCM_AUX_MU_CNTL_TXAUTOFLOW (1 << 3) /* Enable TXD Auto-flow using CTS */ -#define BCM_AUX_MU_CNTL_RTSLEVEL_SHIFT 4 /* RX FIFO level to deassert RTS */ +#define BCM_AUX_MU_CNTL_RXEN (1 << 0) /* Receiver Enable */ +#define BCM_AUX_MU_CNTL_TXEN (1 << 1) /* Transmitter Enable */ +#define BCM_AUX_MU_CNTL_RXAUTOFLOW (1 << 2) /* Enable RXD Auto-flow using RTS */ +#define BCM_AUX_MU_CNTL_TXAUTOFLOW (1 << 3) /* Enable TXD Auto-flow using CTS */ +#define BCM_AUX_MU_CNTL_RTSLEVEL_SHIFT 4 /* RX FIFO level to deassert RTS */ #define BCM_AUX_MU_CNTL_RTSLEVEL_MASK (3 << BCM_AUX_MU_CNTL_RTSLEVEL_SHIFT) # define BCM_AUX_MU_CNTL_RTSLEVEL_3 (0 << BCM_AUX_MU_CNTL_RTSLEVEL_SHIFT) # define BCM_AUX_MU_CNTL_RTSLEVEL_2 (1 << BCM_AUX_MU_CNTL_RTSLEVEL_SHIFT) # define BCM_AUX_MU_CNTL_RTSLEVEL_1 (2 << BCM_AUX_MU_CNTL_RTSLEVEL_SHIFT) # define BCM_AUX_MU_CNTL_RTSLEVEL_4 (3 << BCM_AUX_MU_CNTL_RTSLEVEL_SHIFT) -#define BCM_AUX_MU_CNTL_RTS_ASSERT (1 << 6) /* Invert RTS auto-flow polarity */ -#define BCM_AUX_MU_CNTL_CTS_ASSERT (1 << 7) /* Invert CTS auto-flow polarity */ +#define BCM_AUX_MU_CNTL_RTS_ASSERT (1 << 6) /* Invert RTS auto-flow polarity */ +#define BCM_AUX_MU_CNTL_CTS_ASSERT (1 << 7) /* Invert CTS auto-flow polarity */ -#define BCM_AUX_MU_STAT_SYM_AVAIL (1 << 0) /* There is at least one symbol in the RX FIFO */ -#define BCM_AUX_MU_STAT_SPC_AVAIL (1 << 1) /* There is at least one free position in the TX FIFO */ -#define BCM_AUX_MU_STAT_RX_IDLE (1 << 2) /* The RX is Idle */ -#define BCM_AUX_MU_STAT_TX_IDLE (1 << 3) /* The TX is Idle */ -#define BCM_AUX_MU_STAT_RX_OVR (1 << 4) /* Receiver overrun */ -#define BCM_AUX_MU_STAT_TX_FULL (1 << 5) /* This is the inverse of bit 1 */ -#define BCM_AUX_MU_STAT_RTS_STAT (1 << 6) /* Status of RTS line */ -#define BCM_AUX_MU_STAT_CTS_STAT (1 << 7) /* Status of CTS line */ -#define BCM_AUX_MU_STAT_TX_EMPTY (1 << 8) /* TX FIFO is Empty */ -#define BCM_AUX_MU_STAT_TX_DONE (1 << 9) /* TX is Idle and FIFO is Empty */ -#define BCM_AUX_MU_STAT_RX_LEVEL_SHIFT 16 /* Bits 19-16: how many symbols in RX FIFO */ +#define BCM_AUX_MU_STAT_SYM_AVAIL (1 << 0) /* There is at least one symbol in the RX FIFO */ +#define BCM_AUX_MU_STAT_SPC_AVAIL (1 << 1) /* There is at least one free position in the TX FIFO */ +#define BCM_AUX_MU_STAT_RX_IDLE (1 << 2) /* The RX is Idle */ +#define BCM_AUX_MU_STAT_TX_IDLE (1 << 3) /* The TX is Idle */ +#define BCM_AUX_MU_STAT_RX_OVR (1 << 4) /* Receiver overrun */ +#define BCM_AUX_MU_STAT_TX_FULL (1 << 5) /* This is the inverse of bit 1 */ +#define BCM_AUX_MU_STAT_RTS_STAT (1 << 6) /* Status of RTS line */ +#define BCM_AUX_MU_STAT_CTS_STAT (1 << 7) /* Status of CTS line */ +#define BCM_AUX_MU_STAT_TX_EMPTY (1 << 8) /* TX FIFO is Empty */ +#define BCM_AUX_MU_STAT_TX_DONE (1 << 9) /* TX is Idle and FIFO is Empty */ +#define BCM_AUX_MU_STAT_RX_LEVEL_SHIFT 16 /* Bits 19-16: how many symbols in RX FIFO */ #define BCM_AUX_MU_STAT_RX_LEVEL_MASK (0xf << BCM_AUX_MU_STAT_RX_LEVEL_SHIFT) -#define BCM_AUX_MU_STAT_TX_LEVEL_SHIFT 24 /* Bits 27-24: how many symbols in TX FIFO */ +#define BCM_AUX_MU_STAT_TX_LEVEL_SHIFT 24 /* Bits 27-24: how many symbols in TX FIFO */ #define BCM_AUX_MU_STAT_TX_LEVEL_MASK (0xf << BCM_AUX_MU_STAT_TX_LEVEL_SHIFT) -#define BCM_AUX_SPI_CNTL0_SFT_LEN_SHIFT 0 /* Specifies the number of bits to shift */ +#define BCM_AUX_SPI_CNTL0_SFT_LEN_SHIFT 0 /* Specifies the number of bits to shift */ #define BCM_AUX_SPI_CNTL0_SFT_LEN_MASK (0x3f << BCM_AUX_SPI_CNTL0_SFT_LEN_SHIFT) -#define BCM_AUX_SPI_CNTL0_MSB_FIRST (1 << 6) /* If 1 the data is shifted out starting with the MS bit */ -#define BCM_AUX_SPI_CNTL0_INV_SPICLK (1 << 7) /* If 1 the 'idle' clock line state is high */ -#define BCM_AUX_SPI_CNTL0_OUT_RISING (1 << 8) /* if 1 data is clocked out on the rising edge of the SPI clock */ -#define BCM_AUX_SPI_CNTL0_CLR_FIFO (1 << 9) /* Clear RX and TX FIFOs */ +#define BCM_AUX_SPI_CNTL0_MSB_FIRST (1 << 6) /* If 1 the data is shifted out starting with the MS bit */ +#define BCM_AUX_SPI_CNTL0_INV_SPICLK (1 << 7) /* If 1 the 'idle' clock line state is high */ +#define BCM_AUX_SPI_CNTL0_OUT_RISING (1 << 8) /* if 1 data is clocked out on the rising edge of the SPI clock */ +#define BCM_AUX_SPI_CNTL0_CLR_FIFO (1 << 9) /* Clear RX and TX FIFOs */ #define BCM_AUX_SPI_CNTL0_IN_RISING (1 << 10) /* If 1 data is clocked in on the rising edge of the SPI clock */ #define BCM_AUX_SPI_CNTL0_ENABLE (1 << 11) /* Enables the SPI interface. */ -#define BCM_AUX_SPI_CNTL0_DOHT_SHIFT 12 /* Bit 13-12: DOUT Hold Time */ +#define BCM_AUX_SPI_CNTL0_DOHT_SHIFT 12 /* Bit 13-12: DOUT Hold Time */ #define BCM_AUX_SPI_CNTL0_DOHT_MASK (3 << BCM_AUX_SPI_CNTL0_DOHT_SHIFT) # define BCM_AUX_SPI_CNTL0_DOHT_NONE (0 << BCM_AUX_SPI_CNTL0_DOHT_SHIFT) # define BCM_AUX_SPI_CNTL0_DOHT_1CLK (1 << BCM_AUX_SPI_CNTL0_DOHT_SHIFT) @@ -185,27 +189,27 @@ #define BCM_AUX_SPI_CNTL0_VAR_WIDTH (1 << 14) /* Variable Width based on TX FIFO */ #define BCM_AUX_SPI_CNTL0_VAR_CS (1 << 15) /* CS pattern and data from TX FIFO */ #define BCM_AUX_SPI_CNTL0_PIM (1 << 16) /* Post Input Mode */ -#define BCM_AUX_SPI_CNTL0_CS_SHIFT 17 /* The pattern output on the CS pins when active */ +#define BCM_AUX_SPI_CNTL0_CS_SHIFT 17 /* The pattern output on the CS pins when active */ #define BCM_AUX_SPI_CNTL0_CS_MASK (7 << BCM_AUX_SPI_CNTL0_CS_SHIFT) #define BCM_AUX_SPI_CNTL0_SPEED_SHIFT 20 #define BCM_AUX_SPI_CNTL0_SPEED_MASK (0xfff << BCM_AUX_SPI_CNTL0_SPEED_SHIFT) -#define BCM_AUX_SPI_CNTL1_KEEP_IN (1 << 0) /* Keep input, shift register is not cleared */ -#define BCM_AUX_SPI_CNTL1_MSB_FIRST (1 << 1) /* Shift data from MSB */ -#define BCM_AUX_SPI_CNTL1_DONE_IRQ (1 << 6) /* If 1 the interrupt line is high when the interface is idle */ -#define BCM_AUX_SPI_CNTL1_TXEMPTY_IRQ (1 << 7) /* Enable IRQ Line when FIFO is Empty */ -#define BCM_AUX_SPI_CNTL1_CSHT_SHIFT 8 /* Bits 10-8: Additional CS High Time */ +#define BCM_AUX_SPI_CNTL1_KEEP_IN (1 << 0) /* Keep input, shift register is not cleared */ +#define BCM_AUX_SPI_CNTL1_MSB_FIRST (1 << 1) /* Shift data from MSB */ +#define BCM_AUX_SPI_CNTL1_DONE_IRQ (1 << 6) /* If 1 the interrupt line is high when the interface is idle */ +#define BCM_AUX_SPI_CNTL1_TXEMPTY_IRQ (1 << 7) /* Enable IRQ Line when FIFO is Empty */ +#define BCM_AUX_SPI_CNTL1_CSHT_SHIFT 8 /* Bits 10-8: Additional CS High Time */ #define BCM_AUX_SPI_CNTL1_CSHT_MASK (7 << BCM_AUX_SPI_CNTL1_CSHT_SHIFT) -#define BCM_AUX_SPI_STAT_BITCNT_SHIFT 0 /* Bits 5-0: The number of bits still to be processed */ +#define BCM_AUX_SPI_STAT_BITCNT_SHIFT 0 /* Bits 5-0: The number of bits still to be processed */ #define BCM_AUX_SPI_STAT_BITCNT_MASK (0x3f << BCM_AUX_SPI_STAT_BITCNT_SHIFT) -#define BCM_AUX_SPI_STAT_BUSY (1 << 6) /* The module is busy transferring data */ -#define BCM_AUX_SPI_STAT_RXEMPTY (1 << 7) /* RX FIFO is empty */ -#define BCM_AUX_SPI_STAT_TXEMPTY (1 << 8) /* TX FIFO is empty */ -#define BCM_AUX_SPI_STAT_TXFULL (1 << 9) /* TX FIFO is full */ -#define BCM_AUX_SPI_STAT_RXLEVEL_SHIFT 12 /* Data units in the RX FIFO */ +#define BCM_AUX_SPI_STAT_BUSY (1 << 6) /* The module is busy transferring data */ +#define BCM_AUX_SPI_STAT_RXEMPTY (1 << 7) /* RX FIFO is empty */ +#define BCM_AUX_SPI_STAT_TXEMPTY (1 << 8) /* TX FIFO is empty */ +#define BCM_AUX_SPI_STAT_TXFULL (1 << 9) /* TX FIFO is full */ +#define BCM_AUX_SPI_STAT_RXLEVEL_SHIFT 12 /* Data units in the RX FIFO */ #define BCM_AUX_SPI_STAT_RXLEVEL_MASK (0xfff << BCM_AUX_SPI_STAT_RXLEVEL_SHIFT) -#define BCM_AUX_SPI_STAT_TXLEVEL_SHIFT 24 /* Data units in the FX FIFO */ +#define BCM_AUX_SPI_STAT_TXLEVEL_SHIFT 24 /* Data units in the FX FIFO */ #define BCM_AUX_SPI_STAT_TXLEVEL_MASK (0xff << BCM_AUX_SPI_STAT_TXLEVEL_SHIFT) -#endif /* __ARCH_ARM_SRC_BCM_CHIP_BCM_AUX_H */ +#endif /* __ARCH_ARM_SRC_BCM2708_CHIP_BCM2708_AUX_H */