nuttx/arch/arm/src/am335x/am335x_serial.c
Gregory Nutt 2aa85fd17e arch/arm, board/arm: Rename all up_* functions to arm_*
Summary

The naming standard at https://cwiki.apache.org/confluence/display/NUTTX/Naming+FAQ requires that all MCU-private functions begin with the name of the architecture, not up_.

This PR addresses only these name changes for the ARM-private functions prototyped in arm_internal.h

This change to the files only modifies the name of called functions.  nxstyle fixes were made for all core architecture files.  However, there are well over 5000 additional complaints from MCU drivers and board logic that are unrelated to to this change but were affected by the name change.  It is not humanly possible to fix all of these.   I ask that this change be treated like other cosmetic changes that we have done which do not require full nxstyle compliance.

Impact

There should be not impact of this change (other that one step toward more consistent naming).
Testing

stm32f4discovery:netnsh
2020-05-01 18:28:13 +01:00

1435 lines
39 KiB
C

/****************************************************************************
* arch/arm/src/am335x/am335x_serial.c
*
* Copyright (C) 2018 Petro Karashchenko. All rights reserved.
* Author: Petro Karashchenko <petro.karashchneko@gmail.com>
*
* 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 <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <debug.h>
#ifdef CONFIG_SERIAL_TERMIOS
# include <termios.h>
#endif
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/fs/ioctl.h>
#include <nuttx/serial/serial.h>
#include <arch/board/board.h>
#include "arm_arch.h"
#include "arm_internal.h"
#include "chip.h"
#include "hardware/am335x_uart.h"
#include "am335x_gpio.h"
#include "am335x_pinmux.h"
#include "am335x_serial.h"
/****************************************************************************
* 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.
*/
#if defined(USE_SERIALDRIVER) && defined(HAVE_UART_DEVICE)
/* SCLK is the UART input clock.
*
* Through experimentation, it has been found that the serial clock is
* OSC24M
*/
#define AM335X_SCLK 48000000
/****************************************************************************
* Private Types
****************************************************************************/
struct up_dev_s
{
uint32_t uartbase; /* Base address of UART registers */
uint32_t baud; /* Configured baud */
uint32_t ier; /* Saved IER value */
uint8_t irq; /* IRQ associated with this UART */
uint8_t parity; /* 0=none, 1=odd, 2=even */
uint8_t bits; /* Number of bits (7 or 8) */
bool stopbits2; /* true: Configure with 2 stop bits instead of 1 */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int up_setup(struct uart_dev_s *dev);
static void up_shutdown(struct uart_dev_s *dev);
static int up_attach(struct uart_dev_s *dev);
static void up_detach(struct uart_dev_s *dev);
static int uart_interrupt(int irq, void *context, void *arg);
static int up_ioctl(struct file *filep, int cmd, unsigned long arg);
static int up_receive(struct uart_dev_s *dev, uint32_t *status);
static void up_rxint(struct uart_dev_s *dev, bool enable);
static bool up_rxavailable(struct uart_dev_s *dev);
static void up_send(struct uart_dev_s *dev, int ch);
static void up_txint(struct uart_dev_s *dev, bool enable);
static bool up_txready(struct uart_dev_s *dev);
static bool up_txempty(struct uart_dev_s *dev);
/****************************************************************************
* Private Data
****************************************************************************/
static const struct uart_ops_s g_uart_ops =
{
.setup = up_setup,
.shutdown = up_shutdown,
.attach = up_attach,
.detach = up_detach,
.ioctl = up_ioctl,
.receive = up_receive,
.rxint = up_rxint,
.rxavailable = up_rxavailable,
#ifdef CONFIG_SERIAL_IFLOWCONTROL
.rxflowcontrol = NULL,
#endif
.send = up_send,
.txint = up_txint,
.txready = up_txready,
.txempty = up_txempty,
};
/* I/O buffers */
#ifdef CONFIG_AM335X_UART0
static char g_uart0rxbuffer[CONFIG_UART0_RXBUFSIZE];
static char g_uart0txbuffer[CONFIG_UART0_TXBUFSIZE];
#endif
#ifdef CONFIG_AM335X_UART1
static char g_uart1rxbuffer[CONFIG_UART1_RXBUFSIZE];
static char g_uart1txbuffer[CONFIG_UART1_TXBUFSIZE];
#endif
#ifdef CONFIG_AM335X_UART2
static char g_uart2rxbuffer[CONFIG_UART2_RXBUFSIZE];
static char g_uart2txbuffer[CONFIG_UART2_TXBUFSIZE];
#endif
#ifdef CONFIG_AM335X_UART3
static char g_uart3rxbuffer[CONFIG_UART3_RXBUFSIZE];
static char g_uart3txbuffer[CONFIG_UART3_TXBUFSIZE];
#endif
#ifdef CONFIG_AM335X_UART4
static char g_uart4rxbuffer[CONFIG_UART4_RXBUFSIZE];
static char g_uart4txbuffer[CONFIG_UART4_TXBUFSIZE];
#endif
#ifdef CONFIG_AM335X_UART5
static char g_uart5rxbuffer[CONFIG_UART5_RXBUFSIZE];
static char g_uart5txbuffer[CONFIG_UART5_TXBUFSIZE];
#endif
/* This describes the state of the AM335X UART0 port. */
#ifdef CONFIG_AM335X_UART0
static struct up_dev_s g_uart0priv =
{
.uartbase = AM335X_UART0_VADDR,
.baud = CONFIG_UART0_BAUD,
.irq = AM335X_IRQ_UART0,
.parity = CONFIG_UART0_PARITY,
.bits = CONFIG_UART0_BITS,
.stopbits2 = CONFIG_UART0_2STOP,
};
static uart_dev_t g_uart0port =
{
.recv =
{
.size = CONFIG_UART0_RXBUFSIZE,
.buffer = g_uart0rxbuffer,
},
.xmit =
{
.size = CONFIG_UART0_TXBUFSIZE,
.buffer = g_uart0txbuffer,
},
.ops = &g_uart_ops,
.priv = &g_uart0priv,
};
#endif
/* This describes the state of the AM335X UART1 port. */
#ifdef CONFIG_AM335X_UART1
static struct up_dev_s g_uart1priv =
{
.uartbase = AM335X_UART1_VADDR,
.baud = CONFIG_UART1_BAUD,
.handler = uart1_interrupt,
.irq = AM335X_IRQ_UART1,
.parity = CONFIG_UART1_PARITY,
.bits = CONFIG_UART1_BITS,
.stopbits2 = CONFIG_UART1_2STOP,
};
static uart_dev_t g_uart1port =
{
.recv =
{
.size = CONFIG_UART1_RXBUFSIZE,
.buffer = g_uart1rxbuffer,
},
.xmit =
{
.size = CONFIG_UART1_TXBUFSIZE,
.buffer = g_uart1txbuffer,
},
.ops = &g_uart_ops,
.priv = &g_uart1priv,
};
#endif
/* This describes the state of the AM335X UART2 port. */
#ifdef CONFIG_AM335X_UART2
static struct up_dev_s g_uart2priv =
{
.uartbase = AM335X_UART2_VADDR,
.baud = CONFIG_UART2_BAUD,
.irq = AM335X_IRQ_UART2,
.parity = CONFIG_UART2_PARITY,
.bits = CONFIG_UART2_BITS,
.stopbits2 = CONFIG_UART2_2STOP,
};
static uart_dev_t g_uart2port =
{
.recv =
{
.size = CONFIG_UART2_RXBUFSIZE,
.buffer = g_uart2rxbuffer,
},
.xmit =
{
.size = CONFIG_UART2_TXBUFSIZE,
.buffer = g_uart2txbuffer,
},
.ops = &g_uart_ops,
.priv = &g_uart2priv,
};
#endif
/* This describes the state of the AM335X UART3 port. */
#ifdef CONFIG_AM335X_UART3
static struct up_dev_s g_uart3priv =
{
.uartbase = AM335X_UART3_VADDR,
.baud = CONFIG_UART3_BAUD,
.irq = AM335X_IRQ_UART3,
.parity = CONFIG_UART3_PARITY,
.bits = CONFIG_UART3_BITS,
.stopbits2 = CONFIG_UART3_2STOP,
};
static uart_dev_t g_uart3port =
{
.recv =
{
.size = CONFIG_UART3_RXBUFSIZE,
.buffer = g_uart3rxbuffer,
},
.xmit =
{
.size = CONFIG_UART3_TXBUFSIZE,
.buffer = g_uart3txbuffer,
},
.ops = &g_uart_ops,
.priv = &g_uart3priv,
};
#endif
/* This describes the state of the AM335X UART4 port. */
#ifdef CONFIG_AM335X_UART4
static struct up_dev_s g_uart4priv =
{
.uartbase = AM335X_UART4_VADDR,
.baud = CONFIG_UART4_BAUD,
.irq = AM335X_IRQ_UART4,
.parity = CONFIG_UART4_PARITY,
.bits = CONFIG_UART4_BITS,
.stopbits2 = CONFIG_UART4_2STOP,
};
static uart_dev_t g_uart4port =
{
.recv =
{
.size = CONFIG_UART4_RXBUFSIZE,
.buffer = g_uart4rxbuffer,
},
.xmit =
{
.size = CONFIG_UART4_TXBUFSIZE,
.buffer = g_uart4txbuffer,
},
.ops = &g_uart_ops,
.priv = &g_uart4priv,
};
#endif
/* This describes the state of the AM335X UART5 port. */
#ifdef CONFIG_AM335X_UART5
static struct up_dev_s g_uart5priv =
{
.uartbase = AM335X_UART5_VADDR,
.baud = CONFIG_UART5_BAUD,
.irq = AM335X_IRQ_UART5,
.parity = CONFIG_UART5_PARITY,
.bits = CONFIG_UART5_BITS,
.stopbits2 = CONFIG_UART5_2STOP,
};
static uart_dev_t g_uart5port =
{
.recv =
{
.size = CONFIG_UART5_RXBUFSIZE,
.buffer = g_uart5rxbuffer,
},
.xmit =
{
.size = CONFIG_UART5_TXBUFSIZE,
.buffer = g_uart5txbuffer,
},
.ops = &g_uart_ops,
.priv = &g_uart5priv,
};
#endif
/* Which UART with be tty0/console and which tty1-5? The console will always
* be ttyS0. If there is no console then will use the lowest numbered UART.
*/
/* First pick the console and ttys0. This could be any of UART0-5 */
#if defined(CONFIG_UART0_SERIAL_CONSOLE)
# define CONSOLE_DEV g_uart0port /* UART0 is console */
# define TTYS0_DEV g_uart0port /* UART0 is ttyS0 */
# define UART0_ASSIGNED 1
#elif defined(CONFIG_UART1_SERIAL_CONSOLE)
# define CONSOLE_DEV g_uart1port /* UART1 is console */
# define TTYS0_DEV g_uart1port /* UART1 is ttyS0 */
# define UART1_ASSIGNED 1
#elif defined(CONFIG_UART2_SERIAL_CONSOLE)
# define CONSOLE_DEV g_uart2port /* UART2 is console */
# define TTYS0_DEV g_uart2port /* UART2 is ttyS0 */
# define UART2_ASSIGNED 1
#elif defined(CONFIG_UART3_SERIAL_CONSOLE)
# define CONSOLE_DEV g_uart3port /* UART3 is console */
# define TTYS0_DEV g_uart3port /* UART3 is ttyS0 */
# define UART3_ASSIGNED 1
#elif defined(CONFIG_UART4_SERIAL_CONSOLE)
# define CONSOLE_DEV g_uart4port /* UART4 is console */
# define TTYS0_DEV g_uart4port /* UART4 is ttyS0 */
# define UART4_ASSIGNED 1
#elif defined(CONFIG_UART5_SERIAL_CONSOLE)
# define CONSOLE_DEV g_uart5port /* UART5 is console */
# define TTYS5_DEV g_uart5port /* UART5 is ttyS0 */
# define UART5_ASSIGNED 1
#else
# undef CONSOLE_DEV /* No console */
# if defined(CONFIG_AM335X_UART0)
# define TTYS0_DEV g_uart0port /* UART0 is ttyS0 */
# define UART0_ASSIGNED 1
# elif defined(CONFIG_AM335X_UART1)
# define TTYS0_DEV g_uart1port /* UART1 is ttyS0 */
# define UART1_ASSIGNED 1
# elif defined(CONFIG_AM335X_UART2)
# define TTYS0_DEV g_uart2port /* UART2 is ttyS0 */
# define UART2_ASSIGNED 1
# elif defined(CONFIG_AM335X_UART3)
# define TTYS0_DEV g_uart3port /* UART3 is ttyS0 */
# define UART3_ASSIGNED 1
# elif defined(CONFIG_AM335X_UART4)
# define TTYS0_DEV g_uart4port /* UART4 is ttyS0 */
# define UART4_ASSIGNED 1
# elif defined(CONFIG_AM335X_UART5)
# define TTYS0_DEV g_uart5port /* UART5 is ttyS0 */
# define UART5_ASSIGNED 1
# endif
#endif
/* Pick ttys1. This could be any of UART0-5 excluding the console UART. */
#if defined(CONFIG_AM335X_UART0) && !defined(UART0_ASSIGNED)
# define TTYS1_DEV g_uart0port /* UART0 is ttyS1 */
# define UART0_ASSIGNED 1
#elif defined(CONFIG_AM335X_UART1) && !defined(UART1_ASSIGNED)
# define TTYS1_DEV g_uart1port /* UART1 is ttyS1 */
# define UART1_ASSIGNED 1
#elif defined(CONFIG_AM335X_UART2) && !defined(UART2_ASSIGNED)
# define TTYS1_DEV g_uart2port /* UART2 is ttyS1 */
# define UART2_ASSIGNED 1
#elif defined(CONFIG_AM335X_UART3) && !defined(UART3_ASSIGNED)
# define TTYS1_DEV g_uart3port /* UART3 is ttyS1 */
# define UART3_ASSIGNED 1
#elif defined(CONFIG_AM335X_UART4) && !defined(UART4_ASSIGNED)
# define TTYS1_DEV g_uart4port /* UART4 is ttyS1 */
# define UART4_ASSIGNED 1
#elif defined(CONFIG_AM335X_UART5) && !defined(UART5_ASSIGNED)
# define TTYS1_DEV g_uart5port /* UART5 is ttyS1 */
# define UART5_ASSIGNED 1
#endif
/* Pick ttys2. This could be one of UART1-5. It can't be UART0 because that
* was either assigned as ttyS0 or ttys1. One of UART 1-5 could also be the
* console.
*/
#if defined(CONFIG_AM335X_UART1) && !defined(UART1_ASSIGNED)
# define TTYS2_DEV g_uart1port /* UART1 is ttyS2 */
# define UART1_ASSIGNED 1
#elif defined(CONFIG_AM335X_UART2) && !defined(UART2_ASSIGNED)
# define TTYS2_DEV g_uart2port /* UART2 is ttyS2 */
# define UART2_ASSIGNED 1
#elif defined(CONFIG_AM335X_UART3) && !defined(UART3_ASSIGNED)
# define TTYS2_DEV g_uart3port /* UART3 is ttyS2 */
# define UART3_ASSIGNED 1
#elif defined(CONFIG_AM335X_UART4) && !defined(UART4_ASSIGNED)
# define TTYS2_DEV g_uart4port /* UART4 is ttyS2 */
# define UART4_ASSIGNED 1
#elif defined(CONFIG_AM335X_UART5) && !defined(UART5_ASSIGNED)
# define TTYS2_DEV g_uart5port /* UART5 is ttyS2 */
# define UART5_ASSIGNED 1
#endif
/* Pick ttys3. This could be one of UART2-5. It can't be UART0-1 because
* those have already been assigned to ttsyS0, 1, or 2. One of
* UART 2-5 could also be the console.
*/
#if defined(CONFIG_AM335X_UART2) && !defined(UART2_ASSIGNED)
# define TTYS3_DEV g_uart2port /* UART2 is ttyS3 */
# define UART2_ASSIGNED 1
#elif defined(CONFIG_AM335X_UART3) && !defined(UART3_ASSIGNED)
# define TTYS3_DEV g_uart3port /* UART3 is ttyS3 */
# define UART3_ASSIGNED 1
#elif defined(CONFIG_AM335X_UART4) && !defined(UART4_ASSIGNED)
# define TTYS3_DEV g_uart4port /* UART4 is ttyS3 */
# define UART4_ASSIGNED 1
#elif defined(CONFIG_AM335X_UART5) && !defined(UART5_ASSIGNED)
# define TTYS3_DEV g_uart5port /* UART5 is ttyS3 */
# define UART5_ASSIGNED 1
#endif
/* Pick ttys4. This could be one of UART3-5. It can't be UART0-2 because
* those have already been assigned to ttsyS0, 1, 2 or 3. One of
* UART 3-5 could also be the console.
*/
#if defined(CONFIG_AM335X_UART3) && !defined(UART3_ASSIGNED)
# define TTYS4_DEV g_uart3port /* UART3 is ttyS4 */
# define UART3_ASSIGNED 1
#elif defined(CONFIG_AM335X_UART4) && !defined(UART4_ASSIGNED)
# define TTYS4_DEV g_uart4port /* UART4 is ttyS4 */
# define UART4_ASSIGNED 1
#elif defined(CONFIG_AM335X_UART5) && !defined(UART5_ASSIGNED)
# define TTYS4_DEV g_uart5port /* UART5 is ttyS4 */
# define UART5_ASSIGNED 1
#endif
/* Pick ttys5. This could be one of UART4-5. It can't be UART0-3 because
* those have already been assigned to ttsyS0, 1, 2, 3 or 4. One of
* UART 4-5 could also be the console.
*/
#if defined(CONFIG_AM335X_UART4) && !defined(UART4_ASSIGNED)
# define TTYS5_DEV g_uart4port /* UART4 is ttyS5 */
# define UART4_ASSIGNED 1
#elif defined(CONFIG_AM335X_UART5) && !defined(UART5_ASSIGNED)
# define TTYS5_DEV g_uart5port /* UART5 is ttyS5 */
# define UART5_ASSIGNED 1
#endif
/****************************************************************************
* Inline Functions
****************************************************************************/
/****************************************************************************
* Name: up_serialin
****************************************************************************/
static inline uint32_t up_serialin(struct up_dev_s *priv, int offset)
{
return getreg32(priv->uartbase + offset);
}
/****************************************************************************
* Name: up_serialout
****************************************************************************/
static inline void up_serialout(struct up_dev_s *priv, int offset, uint32_t value)
{
putreg32(value, priv->uartbase + offset);
}
/****************************************************************************
* Name: up_disableuartint
****************************************************************************/
static inline void up_disableuartint(struct up_dev_s *priv, uint32_t *ier)
{
if (ier != NULL)
{
*ier = priv->ier & UART_IER_ALLIE;
}
priv->ier &= ~UART_IER_ALLIE;
up_serialout(priv, AM335X_UART_IER_OFFSET, priv->ier);
}
/****************************************************************************
* Name: up_restoreuartint
****************************************************************************/
static inline void up_restoreuartint(struct up_dev_s *priv, uint32_t ier)
{
priv->ier |= ier & UART_IER_ALLIE;
up_serialout(priv, AM335X_UART_IER_OFFSET, priv->ier);
}
/****************************************************************************
* Name: up_enablebreaks
****************************************************************************/
static inline void up_enablebreaks(struct up_dev_s *priv, bool enable)
{
uint32_t lcr = up_serialin(priv, AM335X_UART_LCR_OFFSET);
if (enable)
{
lcr |= UART_LCR_BC;
}
else
{
lcr &= ~UART_LCR_BC;
}
up_serialout(priv, AM335X_UART_LCR_OFFSET, lcr);
}
/************************************************************************************
* Name: am335x_uart0config, uart1config, uart2config, ..., uart5config
*
* Descrption:
* Configure the UART
*
************************************************************************************/
#ifdef CONFIG_AM335X_UART0
static inline void am335x_uart0config(void)
{
irqstate_t flags;
/* Step 1: Enable power to UART0 */
flags = enter_critical_section();
#warning Missing logic
/* Step 2: Enable clocking to UART0 */
#warning Missing logic
/* Step 3: Configure I/O pins */
am335x_gpio_config(GPIO_UART0_TXD);
am335x_gpio_config(GPIO_UART0_RXD);
leave_critical_section(flags);
};
#endif
#ifdef CONFIG_AM335X_UART1
static inline void am335x_uart1config(void)
{
irqstate_t flags;
/* Step 1: Enable power to UART1 */
flags = enter_critical_section();
#warning Missing logic
/* Step 2: Enable clocking to UART1 */
#warning Missing logic
/* Step 3: Configure I/O pins */
am335x_gpio_config(GPIO_UART1_TXD);
am335x_gpio_config(GPIO_UART1_RXD);
leave_critical_section(flags);
};
#endif
#ifdef CONFIG_AM335X_UART2
static inline void am335x_uart2config(void)
{
irqstate_t flags;
/* Step 1: Enable power to UART2 */
flags = enter_critical_section();
#warning Missing logic
/* Step 2: Enable clocking on UART2 */
#warning Missing logic
/* Step 3: Configure I/O pins */
am335x_gpio_config(GPIO_UART2_TXD);
am335x_gpio_config(GPIO_UART2_RXD);
leave_critical_section(flags);
};
#endif
#ifdef CONFIG_AM335X_UART3
static inline void am335x_uart3config(void)
{
irqstate_t flags;
/* Step 1: Enable power to UART3 */
flags = enter_critical_section();
#warning Missing logic
/* Step 2: Enable clocking to UART3 */
#warning Missing logic
/* Step 3: Configure I/O pins */
am335x_gpio_config(GPIO_UART3_TXD);
am335x_gpio_config(GPIO_UART3_RXD);
leave_critical_section(flags);
};
#endif
#ifdef CONFIG_AM335X_UART4
static inline void am335x_uart4config(void)
{
irqstate_t flags;
/* Step 1: Enable power to UART4 */
flags = enter_critical_section();
#warning Missing logic
/* Step 2: Enable clocking to UART4 */
#warning Missing logic
/* Step 3: Configure I/O pins */
am335x_gpio_config(GPIO_UART4_TXD);
am335x_gpio_config(GPIO_UART4_RXD);
leave_critical_section(flags);
};
#endif
#ifdef CONFIG_AM335X_UART5
static inline void am335x_uart5config(void)
{
irqstate_t flags;
/* Step 1: Enable power to UART5 */
flags = enter_critical_section();
#warning Missing logic
/* Step 2: Enable clocking to UART5 */
#warning Missing logic
/* Step 3: Configure I/O pins */
am335x_gpio_config(GPIO_UART5_TXD);
am335x_gpio_config(GPIO_UART5_RXD);
leave_critical_section(flags);
};
#endif
/************************************************************************************
* Name: am335x_uartdl
*
* Description:
* Select a divider to produce the BAUD from the UART PCLK.
*
* BAUD = PCLK / (16 * DL), or
* DL = PCLK / BAUD / 16
*
************************************************************************************/
static inline uint32_t am335x_uartdl(uint32_t baud)
{
return AM335X_SCLK / (baud << 4);
}
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: up_setup
*
* Description:
* Configure the UART baud, bits, parity, fifos, etc. This method is
* called the first time that the serial port is opened.
*
****************************************************************************/
static int up_setup(struct uart_dev_s *dev)
{
#ifndef CONFIG_SUPPRESS_UART_CONFIG
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
uint16_t dl;
uint32_t lcr;
/* Put UART to disabled mode */
up_serialout(priv, AM335X_UART_MDR1_OFFSET, UART_MDR1_MODE_DISABLE);
/* Enter configuration mode and enable access to Latch Divisor DLAB=1 */
up_serialout(priv, AM335X_UART_LCR_OFFSET, UART_LCR_CONFIG_MODE_B);
/* Set Divisor values to zero to be able to write FCR correctly */
up_serialout(priv, AM335X_UART_DLH_OFFSET, 0);
up_serialout(priv, AM335X_UART_DLL_OFFSET, 0);
/* Enable writing FCR[5:4] */
up_serialout(priv, AM335X_UART_EFR_OFFSET, UART_EFR_ENHANCEDEN);
/* Exit configuration mode and enable access to Latch Divisor DLAB=1 */
up_serialout(priv, AM335X_UART_LCR_OFFSET, UART_LCR_CONFIG_MODE_A);
/* Clear FIFOs */
up_serialout(priv, AM335X_UART_FCR_OFFSET, (UART_FCR_RFIFO_CLEAR | UART_FCR_TFIFO_CLEAR));
/* Configure the FIFOs */
up_serialout(priv, AM335X_UART_FCR_OFFSET, (UART_FCR_FIFO_EN | UART_FCR_RFT_60CHAR | UART_FCR_TFT_56CHAR));
/* Set up the IER */
priv->ier = up_serialin(priv, AM335X_UART_IER_OFFSET);
/* Set up the LCR */
lcr = 0;
switch (priv->bits)
{
case 5:
lcr |= UART_LCR_DLS_5BITS;
break;
case 6:
lcr |= UART_LCR_DLS_6BITS;
break;
case 7:
lcr |= UART_LCR_DLS_7BITS;
break;
case 8:
default:
lcr |= UART_LCR_DLS_8BITS;
break;
}
if (priv->stopbits2)
{
lcr |= UART_LCR_STOP_2BITS;
}
if (priv->parity == 1)
{
lcr |= UART_LCR_PARITY_ODD;
}
else if (priv->parity == 2)
{
lcr |= UART_LCR_PARITY_EVEN;
}
/* Set the BAUD divisor */
dl = am335x_uartdl(priv->baud);
up_serialout(priv, AM335X_UART_DLH_OFFSET, (dl >> 8) & UART_DLH_MASK);
up_serialout(priv, AM335X_UART_DLL_OFFSET, dl & UART_DLL_MASK);
/* Clear DLAB */
up_serialout(priv, AM335X_UART_LCR_OFFSET, lcr);
/* Enable Auto-Flow Control in the Modem Control Register */
#if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL)
# warning Missing logic
#endif
up_serialout(priv, AM335X_UART_MDR1_OFFSET, UART_MDR1_MODE_16X);
#endif
return OK;
}
/****************************************************************************
* Name: up_shutdown
*
* Description:
* Disable the UART. This method is called when the serial port is closed
*
****************************************************************************/
static void up_shutdown(struct uart_dev_s *dev)
{
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
up_disableuartint(priv, NULL);
}
/****************************************************************************
* Name: up_attach
*
* Description:
* Configure the UART to operation in interrupt driven mode. This method is
* called when the serial port is opened. Normally, this is just after the
* 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 up_attach(struct uart_dev_s *dev)
{
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
int ret;
/* Attach and enable the IRQ */
ret = irq_attach(priv->irq, uart_interrupt, dev);
if (ret == OK)
{
/* Enable the interrupt (RX and TX interrupts are still disabled
* in the UART
*/
up_enable_irq(priv->irq);
}
return ret;
}
/****************************************************************************
* Name: up_detach
*
* Description:
* Detach 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 up_detach(struct uart_dev_s *dev)
{
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
up_disable_irq(priv->irq);
irq_detach(priv->irq);
}
/****************************************************************************
* Name: uartN_interrupt and uart_interrupt
*
* Description:
* This is the UART interrupt handler. It will be invoked when an
* interrupt received on the 'irq' It should call uart_transmitchars or
* uart_receivechar to perform the appropriate data transfers. The
* interrupt handling logic must be able to map the 'irq' number into the
* appropriate uart_dev_s structure in order to call these functions.
*
****************************************************************************/
static int uart_interrupt(int irq, void *context, void *arg)
{
struct uart_dev_s *dev = (struct uart_dev_s *)arg;
struct up_dev_s *priv;
uint32_t status;
int passes;
DEBUGASSERT(dev != NULL && dev->priv != NULL);
priv = (struct up_dev_s *)dev->priv;
/* Loop until there are no characters to be transferred or,
* until we have been looping for a long time.
*/
for (passes = 0; passes < 256; passes++)
{
/* Get the current UART status */
status = up_serialin(priv, AM335X_UART_IIR_OFFSET);
/* Handle the interrupt by its interrupt ID field */
switch (status & UART_IIR_IID_MASK)
{
/* Handle incoming, receive bytes (with or without timeout) */
case UART_IIR_IID_RHR:
case UART_IIR_IID_RXTIMEOUT:
{
uart_recvchars(dev);
break;
}
/* Handle outgoing, transmit bytes */
case UART_IIR_IID_THR:
{
uart_xmitchars(dev);
break;
}
/* Just clear modem status interrupts (UART1 only) */
case UART_IIR_IID_MODEM:
{
/* Read the modem status register (MSR) to clear */
status = up_serialin(priv, AM335X_UART_MSR_OFFSET);
UNUSED(status);
break;
}
/* Just clear any line status interrupts */
case UART_IIR_IID_RXSTATUS:
{
/* Read the line status register (LSR) to clear */
status = up_serialin(priv, AM335X_UART_LSR_OFFSET);
UNUSED(status);
break;
}
/* Just ignore */
case UART_IIR_IID_XOFF:
{
break;
}
/* Just ignore */
case UART_IIR_IID_STATECHANGE:
{
break;
}
/* No further interrupts pending... return now */
case UART_IIR_IID_NONE:
{
return OK;
}
/* Otherwise we have received an interrupt that we cannot handle */
default:
{
break;
}
}
}
return OK;
}
/****************************************************************************
* Name: up_ioctl
*
* Description:
* All ioctl calls will be routed through this method
*
****************************************************************************/
static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
{
struct inode *inode = filep->f_inode;
struct uart_dev_s *dev = inode->i_private;
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
int ret = OK;
switch (cmd)
{
#ifdef CONFIG_SERIAL_TIOCSERGSTRUCT
case TIOCSERGSTRUCT:
{
struct up_dev_s *user = (struct up_dev_s *)arg;
if (!user)
{
ret = -EINVAL;
}
else
{
memcpy(user, dev, sizeof(struct up_dev_s));
}
}
break;
#endif
case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */
{
irqstate_t flags = enter_critical_section();
up_enablebreaks(priv, true);
leave_critical_section(flags);
}
break;
case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */
{
irqstate_t flags;
flags = enter_critical_section();
up_enablebreaks(priv, false);
leave_critical_section(flags);
}
break;
#ifdef CONFIG_SERIAL_TERMIOS
case TCGETS:
{
struct termios *termiosp = (struct termios *)arg;
if (!termiosp)
{
ret = -EINVAL;
break;
}
/* TODO: Other termios fields are not yet returned.
* Note that cfsetospeed is not necessary because we have
* knowledge that only one speed is supported.
* Both cfset(i|o)speed() translate to cfsetspeed.
*/
cfsetispeed(termiosp, priv->baud);
}
break;
case TCSETS:
{
struct termios *termiosp = (struct termios *)arg;
uint32_t lcr; /* Holds current values of line control register */
uint16_t dl; /* Divisor latch */
if (!termiosp)
{
ret = -EINVAL;
break;
}
/* TODO: Handle other termios settings.
* Note that only cfgetispeed is used because we have knowledge
* that only one speed is supported.
*/
/* Get the c_speed field in the termios struct */
priv->baud = cfgetispeed(termiosp);
/* TODO: Re-calculate the optimal CCLK divisor for the new baud and
* and reset the divider in the CLKSEL0/1 register.
*/
/* DLAB open latch */
/* REVISIT: Shouldn't we just call up_setup() to do all of the following? */
lcr = up_serialin(priv, AM335X_UART_LCR_OFFSET);
up_serialout(priv, AM335X_UART_LCR_OFFSET, (lcr | UART_LCR_DLAB));
/* Set the BAUD divisor */
dl = am335x_uartdl(priv->baud);
up_serialout(priv, AM335X_UART_DLH_OFFSET, (dl >> 8) & UART_DLH_MASK);
up_serialout(priv, AM335X_UART_DLL_OFFSET, dl & UART_DLL_MASK);
/* Clear DLAB */
up_serialout(priv, AM335X_UART_LCR_OFFSET, lcr);
}
break;
#endif
default:
ret = -ENOTTY;
break;
}
return ret;
}
/****************************************************************************
* Name: up_receive
*
* Description:
* Called (usually) from the interrupt level to receive one
* character from the UART. Error bits associated with the
* receipt are provided in the return 'status'.
*
****************************************************************************/
static int up_receive(struct uart_dev_s *dev, uint32_t *status)
{
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
uint32_t rbr;
*status = up_serialin(priv, AM335X_UART_LSR_OFFSET);
rbr = up_serialin(priv, AM335X_UART_RBR_OFFSET);
return rbr;
}
/****************************************************************************
* Name: up_rxint
*
* Description:
* Call to enable or disable RX interrupts
*
****************************************************************************/
static void up_rxint(struct uart_dev_s *dev, bool enable)
{
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
if (enable)
{
#ifndef CONFIG_SUPPRESS_SERIAL_INTS
priv->ier |= UART_IER_RHR_CTI;
#endif
}
else
{
priv->ier &= ~UART_IER_RHR_CTI;
}
up_serialout(priv, AM335X_UART_IER_OFFSET, priv->ier);
}
/****************************************************************************
* Name: up_rxavailable
*
* Description:
* Return true if the receive fifo is not empty
*
****************************************************************************/
static bool up_rxavailable(struct uart_dev_s *dev)
{
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
return ((up_serialin(priv, AM335X_UART_LSR_OFFSET) & UART_LSR_DR) != 0);
}
/****************************************************************************
* Name: up_send
*
* Description:
* This method will send one byte on the UART
*
****************************************************************************/
static void up_send(struct uart_dev_s *dev, int ch)
{
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
up_serialout(priv, AM335X_UART_THR_OFFSET, (uint32_t)ch);
}
/****************************************************************************
* Name: up_txint
*
* Description:
* Call to enable or disable TX interrupts
*
****************************************************************************/
static void up_txint(struct uart_dev_s *dev, bool enable)
{
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
irqstate_t flags;
flags = enter_critical_section();
if (enable)
{
#ifndef CONFIG_SUPPRESS_SERIAL_INTS
priv->ier |= UART_IER_THR;
up_serialout(priv, AM335X_UART_IER_OFFSET, priv->ier);
/* Fake a TX interrupt here by just calling uart_xmitchars() with
* interrupts disabled (note this may recurse).
*/
uart_xmitchars(dev);
#endif
}
else
{
priv->ier &= ~UART_IER_THR;
up_serialout(priv, AM335X_UART_IER_OFFSET, priv->ier);
}
leave_critical_section(flags);
}
/****************************************************************************
* Name: up_txready
*
* Description:
* Return true if the tranmsit fifo is not full
*
****************************************************************************/
static bool up_txready(struct uart_dev_s *dev)
{
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
return ((up_serialin(priv, AM335X_UART_LSR_OFFSET) & UART_LSR_THRE) != 0);
}
/****************************************************************************
* Name: up_txempty
*
* Description:
* Return true if the transmit fifo is empty
*
****************************************************************************/
static bool up_txempty(struct uart_dev_s *dev)
{
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
return ((up_serialin(priv, AM335X_UART_LSR_OFFSET) & UART_LSR_TEMT) != 0);
}
/****************************************************************************
* Public Functions
****************************************************************************/
#ifdef USE_EARLYSERIALINIT
/****************************************************************************
* Name: arm_earlyserialinit
*
* Description:
* Performs the low level UART initialization early in debug so that the
* serial console will be available during bootup. This must be called
* before arm_serialinit.
*
* NOTE: Configuration of the CONSOLE UART was performed by up_lowsetup()
* very early in the boot sequence.
*
****************************************************************************/
void arm_earlyserialinit(void)
{
/* Configure all UARTs (except the CONSOLE UART) and disable interrupts */
#ifdef CONFIG_AM335X_UART0
#ifndef CONFIG_UART0_SERIAL_CONSOLE
am335x_uart0config();
#endif
up_disableuartint(&g_uart0priv, NULL);
#endif
#ifdef CONFIG_AM335X_UART1
#ifndef CONFIG_UART1_SERIAL_CONSOLE
am335x_uart1config();
#else
#endif
up_disableuartint(&g_uart1priv, NULL);
#endif
#ifdef CONFIG_AM335X_UART2
#ifndef CONFIG_UART2_SERIAL_CONSOLE
am335x_uart2config();
#endif
up_disableuartint(&g_uart2priv, NULL);
#endif
#ifdef CONFIG_AM335X_UART3
#ifndef CONFIG_UART3_SERIAL_CONSOLE
am335x_uart3config();
#endif
up_disableuartint(&g_uart3priv, NULL);
#endif
#ifdef CONFIG_AM335X_UART4
#ifndef CONFIG_UART4_SERIAL_CONSOLE
am335x_uart4config();
#endif
up_disableuartint(&g_uart4priv, NULL);
#endif
#ifdef CONFIG_AM335X_UART5
#ifndef CONFIG_UART5_SERIAL_CONSOLE
am335x_uart5config();
#endif
up_disableuartint(&g_uart5priv, NULL);
#endif
/* Configuration whichever one is the console */
#ifdef CONSOLE_DEV
CONSOLE_DEV.isconsole = true;
up_setup(&CONSOLE_DEV);
#endif
}
#endif
/****************************************************************************
* Name: arm_serialinit
*
* Description:
* Register serial console and serial ports. This assumes that
* arm_earlyserialinit was called previously.
*
****************************************************************************/
void arm_serialinit(void)
{
#ifdef CONSOLE_DEV
uart_register("/dev/console", &CONSOLE_DEV);
#endif
#ifdef TTYS0_DEV
uart_register("/dev/ttyS0", &TTYS0_DEV);
#endif
#ifdef TTYS1_DEV
uart_register("/dev/ttyS1", &TTYS1_DEV);
#endif
#ifdef TTYS2_DEV
uart_register("/dev/ttyS2", &TTYS2_DEV);
#endif
#ifdef TTYS3_DEV
uart_register("/dev/ttyS3", &TTYS3_DEV);
#endif
#ifdef TTYS4_DEV
uart_register("/dev/ttyS4", &TTYS4_DEV);
#endif
#ifdef TTYS5_DEV
uart_register("/dev/ttyS5", &TTYS5_DEV);
#endif
}
/****************************************************************************
* Name: up_putc
*
* Description:
* Provide priority, low-level access to support OS debug writes
*
****************************************************************************/
int up_putc(int ch)
{
#ifdef HAVE_SERIAL_CONSOLE
struct up_dev_s *priv = (struct up_dev_s *)CONSOLE_DEV.priv;
uint32_t ier;
up_disableuartint(priv, &ier);
#endif
/* Check for LF */
if (ch == '\n')
{
/* Add CR */
arm_lowputc('\r');
}
arm_lowputc(ch);
#ifdef HAVE_SERIAL_CONSOLE
up_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 HAVE_UART_DEVICE
/* Check for LF */
if (ch == '\n')
{
/* Add CR */
arm_lowputc('\r');
}
arm_lowputc(ch);
#endif
return ch;
}
#endif /* USE_SERIALDRIVER */