diff --git a/drivers/serial/CMakeLists.txt b/drivers/serial/CMakeLists.txt index 74f9f9d6415..ba039446bf3 100644 --- a/drivers/serial/CMakeLists.txt +++ b/drivers/serial/CMakeLists.txt @@ -46,6 +46,10 @@ if(CONFIG_UART_PL011) list(APPEND SRCS uart_pl011.c) endif() +if(CONFIG_UART_XLNXPS) + list(APPEND SRCS uart_xlnx_ps.c) +endif() + if(CONFIG_RPMSG_UART) list(APPEND SRCS uart_rpmsg.c) endif() diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index def241f7934..84090d53a2b 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -114,6 +114,14 @@ if UART_PL011 source "drivers/serial/Kconfig-pl011" endif +menuconfig UART_XLNXPS + bool "Xilinx UART Peripheral System (XUARTPS) Chip support" + default n + +if UART_XLNXPS +source "drivers/serial/Kconfig-xlnxps" +endif # UART_XLNXPS + menuconfig CMSDK_UART bool "CMSDK UART Chip support" select ARCH_HAVE_SERIAL_TERMIOS diff --git a/drivers/serial/Kconfig-xlnxps b/drivers/serial/Kconfig-xlnxps new file mode 100644 index 00000000000..3de1f212ce6 --- /dev/null +++ b/drivers/serial/Kconfig-xlnxps @@ -0,0 +1,128 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if UART_XLNXPS + +config XLNXPS_SERIAL_DISABLE_REORDERING + bool "Disable reordering of ttySx devices." + default n + ---help--- + NuttX per default reorders the serial ports (/dev/ttySx) so that the + console is always on /dev/ttyS0. If more than one UART is in use this + can, however, have the side-effect that all port mappings + (hardware USART1 -> /dev/ttyS0) change if the console is moved to another + UART. This option disables that re-ordering for XLNXPS UARTs. + +config UART_XLNXPS0 + bool "XLNXPS UART0" + default n + +if UART_XLNXPS0 + +config UART_XLNXPS0_BASE + hex "XLNXPS UART0 base address" + default 0x0 + +config UART_XLNXPS0_CLOCK + int "XLNXPS UART0 clock" + default 0 + +config UART_XLNXPS0_IRQ + int "XLNXPS UART0 IRQ number" + default 0 + +config UART_XLNXPS0_BAUD + int "XLNXPS UART0 BAUD" + default 115200 + +config UART_XLNXPS0_PARITY + int "XLNXPS UART0 parity" + default 0 + range 0 2 + ---help--- + XLNXPS UART0 parity. 0=None, 1=Odd, 2=Even. Default: None + +config UART_XLNXPS0_BITS + int "XLNXPS UART0 number of bits" + default 8 + ---help--- + XLNXPS UART0 number of bits. Default: 8 + +config UART_XLNXPS0_2STOP + int "XLNXPS UART0 two stop bits" + default 0 + ---help--- + 0=1 stop bit, 1=Two stop bits. Default: 1 stop bit + +config UART_XLNXPS0_RX_TRIGGER + int "XLNXPS UART0 RX interrupt trigger level" + default 2 + range 0 3 + +config UART_XLNXPS0_RXBUFSIZE + int "XLNXPS UART0 Rx buffer size" + default 256 + ---help--- + XLNXPS UART0 Rx buffer size. Default: 256 + +config UART_XLNXPS0_TXBUFSIZE + int "XLNXPS UART0 Tx buffer size" + default 256 + ---help--- + XLNXPS UART0 Tx buffer size. Default: 256 + +config UART_XLNXPS0_IFLOWCONTROL + bool "XLNXPS UART0 RTS flow control" + default n + select SERIAL_IFLOWCONTROL + ---help--- + Enable XLNXPS UART0 RTS flow control + +config UART_XLNXPS0_OFLOWCONTROL + bool "XLNXPS UART0 CTS flow control" + default n + select SERIAL_OFLOWCONTROL + ---help--- + Enable XLNXPS UART0 CTS flow control + +endif # UART_XLNXPS0 + +choice + prompt "XLNXPS Serial Console" + default XLNXPS_NO_SERIAL_CONSOLE + depends on DEV_CONSOLE + +config UART_XLNXPS0_SERIAL_CONSOLE + bool "XLNXPS UART0 serial console" + depends on UART_XLNXPS0 + select SERIAL_CONSOLE + +config XLNXPS_NO_SERIAL_CONSOLE + bool "No XLNXPS serial console" + +endchoice # XLNXPS Serial Console + +config XLNXPS_SUPRESS_CONFIG + bool "Suppress XLNXPS configuration" + default n + +config XLNXPS_SUPRESS_INITIAL_CONFIG + bool "Suppress initial XLNXPS configuration" + depends on !XLNXPS_SUPRESS_CONFIG + default n + ---help--- + This option is useful, for example, if you are using a bootloader + that configures the UART_XLNXPS. In that case, you may want to + just leave the existing console configuration in place. Default: n + +config SERIAL_UART_ARCH_MMIO + bool "Platform access register through the memory mapping" + default n + +config SERIAL_UART_ARCH_IOCTL + bool "Platform has own custom IOCTL" + default n + +endif # UART_XLNXPS diff --git a/drivers/serial/Make.defs b/drivers/serial/Make.defs index b9ca98dbff8..22845e16959 100644 --- a/drivers/serial/Make.defs +++ b/drivers/serial/Make.defs @@ -58,6 +58,10 @@ ifeq ($(CONFIG_UART_HOSTFS),y) CSRCS += uart_hostfs.c endif +ifeq ($(CONFIG_UART_XLNXPS),y) + CSRCS += uart_xlnx_ps.c +endif + # Pseudo-terminal support ifeq ($(CONFIG_PSEUDOTERM),y) diff --git a/drivers/serial/uart_xlnx_ps.c b/drivers/serial/uart_xlnx_ps.c new file mode 100644 index 00000000000..6257d36ba4f --- /dev/null +++ b/drivers/serial/uart_xlnx_ps.c @@ -0,0 +1,1281 @@ +/*************************************************************************** + * drivers/serial/uart_xlnx_ps.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ***************************************************************************/ + +/*************************************************************************** + * Included Files + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_SERIAL_TERMIOS +# include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_UART_XLNXPS + +/*************************************************************************** + * Pre-processor Definitions + ***************************************************************************/ + +#define getreg8(a) (*(volatile uint8_t *)(a)) +#define putreg8(v,a) (*(volatile uint8_t *)(a) = (v)) +#define getreg16(a) (*(volatile uint16_t *)(a)) +#define putreg16(v,a) (*(volatile uint16_t *)(a) = (v)) +#define getreg32(a) (*(volatile uint32_t *)(a)) +#define putreg32(v,a) (*(volatile uint32_t *)(a) = (v)) +#define getreg64(a) (*(volatile uint64_t *)(a)) +#define putreg64(v,a) (*(volatile uint64_t *)(a) = (v)) + +/* Non-atomic, but more effective modification of registers */ + +#define modreg8(v,m,a) putreg8((getreg8(a) & ~(m)) | ((v) & (m)), (a)) +#define modreg16(v,m,a) putreg16((getreg16(a) & ~(m)) | ((v) & (m)), (a)) +#define modreg32(v,m,a) putreg32((getreg32(a) & ~(m)) | ((v) & (m)), (a)) +#define modreg64(v,m,a) putreg64((getreg64(a) & ~(m)) | ((v) & (m)), (a)) + +/* UART0 is console and ttyS0 */ + +#define CONSOLE_DEV g_uart0port /* UART0 is console */ +#define TTYS0_DEV g_uart0port /* UART0 is ttyS0 */ +#define UART0_ASSIGNED 1 + +/*************************************************************************** + * UART_XLNXPS UART Registers and Bit Definitions + * + * Register Map + * + * Register offsets for the UART. + ***************************************************************************/ + +#define XUARTPS_CR_OFFSET 0x0000U /* Control Register [8:0] */ +#define XUARTPS_MR_OFFSET 0x0004U /* Mode Register [9:0] */ +#define XUARTPS_IER_OFFSET 0x0008U /* Interrupt Enable [12:0] */ +#define XUARTPS_IDR_OFFSET 0x000CU /* Interrupt Disable [12:0] */ +#define XUARTPS_IMR_OFFSET 0x0010U /* Interrupt Mask [12:0] */ +#define XUARTPS_ISR_OFFSET 0x0014U /* Interrupt Status [12:0]*/ +#define XUARTPS_BAUDGEN_OFFSET 0x0018U /* Baud Rate Generator [15:0] */ +#define XUARTPS_RXTOUT_OFFSET 0x001CU /* RX Timeout [7:0] */ +#define XUARTPS_RXWM_OFFSET 0x0020U /* RX FIFO Trigger Level [5:0] */ +#define XUARTPS_MODEMCR_OFFSET 0x0024U /* Modem Control [5:0] */ +#define XUARTPS_MODEMSR_OFFSET 0x0028U /* Modem Status [8:0] */ +#define XUARTPS_SR_OFFSET 0x002CU /* Channel Status [14:0] */ +#define XUARTPS_FIFO_OFFSET 0x0030U /* FIFO [7:0] */ +#define XUARTPS_BAUDDIV_OFFSET 0x0034U /* Baud Rate Divider [7:0] */ +#define XUARTPS_FLOWDEL_OFFSET 0x0038U /* Flow Delay [5:0] */ +#define XUARTPS_TXWM_OFFSET 0x0044U /* TX FIFO Trigger Level [5:0] */ +#define XUARTPS_RXBS_OFFSET 0x0048U /* RX FIFO Byte Status [11:0] */ + +/*************************************************************************** + * Control Register + * + * The Control register (CR) controls the major functions of the device. + * + * Control Register Bit Definition + ***************************************************************************/ + +#define XUARTPS_CR_STOPBRK 0x00000100U /* Stop transmission of break */ +#define XUARTPS_CR_STARTBRK 0x00000080U /* Set break */ +#define XUARTPS_CR_TORST 0x00000040U /* RX timeout counter restart */ +#define XUARTPS_CR_TX_DIS 0x00000020U /* TX disabled. */ +#define XUARTPS_CR_TX_EN 0x00000010U /* TX enabled */ +#define XUARTPS_CR_RX_DIS 0x00000008U /* RX disabled. */ +#define XUARTPS_CR_RX_EN 0x00000004U /* RX enabled */ +#define XUARTPS_CR_EN_DIS_MASK 0x0000003CU /* Enable/disable Mask */ +#define XUARTPS_CR_TXRST 0x00000002U /* TX logic reset */ +#define XUARTPS_CR_RXRST 0x00000001U /* RX logic reset */ + +/*************************************************************************** + * Mode Register + * + * The mode register (MR) defines the mode of transfer as well as the data + * format. If this register is modified during transmission or reception, + * data validity cannot be guaranteed. + * + * Mode Register Bit Definition + * + ***************************************************************************/ +#define XUARTPS_MR_CCLK 0x00000400U /* Input clock selection */ +#define XUARTPS_MR_CHMODE_R_LOOP 0x00000300U /* Remote loopback mode */ +#define XUARTPS_MR_CHMODE_L_LOOP 0x00000200U /* Local loopback mode */ +#define XUARTPS_MR_CHMODE_ECHO 0x00000100U /* Auto echo mode */ +#define XUARTPS_MR_CHMODE_NORM 0x00000000U /* Normal mode */ +#define XUARTPS_MR_CHMODE_SHIFT 8U /* Mode shift */ +#define XUARTPS_MR_CHMODE_MASK 0x00000300U /* Mode mask */ +#define XUARTPS_MR_STOPMODE_2_BIT 0x00000080U /* 2 stop bits */ +#define XUARTPS_MR_STOPMODE_1_5_BIT 0x00000040U /* 1.5 stop bits */ +#define XUARTPS_MR_STOPMODE_1_BIT 0x00000000U /* 1 stop bit */ +#define XUARTPS_MR_STOPMODE_SHIFT 6U /* Stop bits shift */ +#define XUARTPS_MR_STOPMODE_MASK 0x000000A0U /* Stop bits mask */ +#define XUARTPS_MR_PARITY_NONE 0x00000020U /* No parity mode */ +#define XUARTPS_MR_PARITY_MARK 0x00000018U /* Mark parity mode */ +#define XUARTPS_MR_PARITY_SPACE 0x00000010U /* Space parity mode */ +#define XUARTPS_MR_PARITY_ODD 0x00000008U /* Odd parity mode */ +#define XUARTPS_MR_PARITY_EVEN 0x00000000U /* Even parity mode */ +#define XUARTPS_MR_PARITY_SHIFT 3U /* Parity setting shift */ +#define XUARTPS_MR_PARITY_MASK 0x00000038U /* Parity mask */ +#define XUARTPS_MR_CHARLEN_6_BIT 0x00000006U /* 6 bits data */ +#define XUARTPS_MR_CHARLEN_7_BIT 0x00000004U /* 7 bits data */ +#define XUARTPS_MR_CHARLEN_8_BIT 0x00000000U /* 8 bits data */ +#define XUARTPS_MR_CHARLEN_SHIFT 1U /* Data Length shift */ +#define XUARTPS_MR_CHARLEN_MASK 0x00000006U /* Data length mask */ +#define XUARTPS_MR_CLKSEL 0x00000001U /* Input clock selection */ + +#define UART_DEFAULT_MODE XUARTPS_MR_CHMODE_NORM | \ + XUARTPS_MR_STOPMODE_1_BIT | \ + XUARTPS_MR_PARITY_NONE | \ + XUARTPS_MR_CHARLEN_8_BIT + +/*************************************************************************** + * Interrupt Registers + * + * Interrupt control logic uses the interrupt enable register (IER) and the + * interrupt disable register (IDR) to set the value of the bits in the + * interrupt mask register (IMR). The IMR determines whether to pass an + * interrupt to the interrupt status register (ISR). + * Writing a 1 to IER Enbables an interrupt, writing a 1 to IDR disables an + * interrupt. IMR and ISR are read only, and IER and IDR are write only. + * Reading either IER or IDR returns 0x00. + * + * All four registers have the same bit definitions. + * + ***************************************************************************/ + +#define XUARTPS_IXR_RBRK 0x00002000U /* Rx FIFO break detect interrupt */ +#define XUARTPS_IXR_TOVR 0x00001000U /* Tx FIFO Overflow interrupt */ +#define XUARTPS_IXR_TNFUL 0x00000800U /* Tx FIFO Nearly Full interrupt */ +#define XUARTPS_IXR_TTRIG 0x00000400U /* Tx Trig interrupt */ +#define XUARTPS_IXR_DMS 0x00000200U /* Modem status change interrupt */ +#define XUARTPS_IXR_TOUT 0x00000100U /* Timeout error interrupt */ +#define XUARTPS_IXR_PARITY 0x00000080U /* Parity error interrupt */ +#define XUARTPS_IXR_FRAMING 0x00000040U /* Framing error interrupt */ +#define XUARTPS_IXR_OVER 0x00000020U /* Overrun error interrupt */ +#define XUARTPS_IXR_TXFULL 0x00000010U /* TX FIFO full interrupt. */ +#define XUARTPS_IXR_TXEMPTY 0x00000008U /* TX FIFO empty interrupt. */ +#define XUARTPS_IXR_RXFULL 0x00000004U /* RX FIFO full interrupt. */ +#define XUARTPS_IXR_RXEMPTY 0x00000002U /* RX FIFO empty interrupt. */ +#define XUARTPS_IXR_RXOVR 0x00000001U /* RX FIFO trigger interrupt. */ +#define XUARTPS_IXR_MASK 0x00003FFFU /* Valid bit mask */ + +/*************************************************************************** + * Baud Rate Generator Register + * + * The baud rate generator control register (BRGR) is a 16 bit register that + * controls the receiver bit sample clock and baud rate. + * Valid values are 1 - 65535. + * + * Bit Sample Rate = CCLK / BRGR, where the CCLK is selected by the MR_CCLK + * bit in the MR register. + * + ***************************************************************************/ + +#define XUARTPS_BAUDGEN_DISABLE 0x00000000U /* Disable clock */ +#define XUARTPS_BAUDGEN_MASK 0x0000FFFFU /* Valid bits mask */ +#define XUARTPS_BAUDGEN_RESET_VAL 0x0000028BU /* Reset value */ + +/*************************************************************************** + * Baud Divisor Rate register + * + * The baud rate divider register (BDIV) controls how much the bit sample + * rate is divided by. It sets the baud rate. + * Valid values are 0x04 to 0xFF. Writing a value less than 4 will be + * ignored. + * + * Baud rate = CCLK / ((BAUDDIV + 1) x BRGR), where the CCLK is selected by + * the MR_CCLK bit in the MR register. + * + ***************************************************************************/ + +#define XUARTPS_BAUDDIV_MASK 0x000000FFU /* 8 bit baud divider mask */ +#define XUARTPS_BAUDDIV_RESET_VAL 0x0000000FU /* Reset value */ + +/*************************************************************************** + * The following constant defines the amount of error that is allowed for + * a specified baud rate. This error is the difference between the actual + * baud rate that will be generated using the specified clock and the + * desired baud rate. + ***************************************************************************/ + +#define XUARTPS_MAX_BAUD_ERROR_RATE 3U /* max % error allowed */ + +/*************************************************************************** + * The following constants indicate the max and min baud rates and these + * numbers are based only on the testing that has been done. The hardware + * is capable of other baud rates. + ***************************************************************************/ + +#define XUARTPS_MAX_RATE 6240000U +#define XUARTPS_MIN_RATE 110U + +/*************************************************************************** + * Receiver Timeout Register + * + * Use the receiver timeout register (RTR) to detect an idle condition on + * the receiver data line. + * + ***************************************************************************/ + +#define XUARTPS_RXTOUT_DISABLE 0x00000000U /* Disable time out */ +#define XUARTPS_RXTOUT_MASK 0x000000FFU /* Valid bits mask */ + +/*************************************************************************** + * Receiver FIFO Trigger Level Register + * + * Use the Receiver FIFO Trigger Level Register (RTRIG) to set the value at + * which the RX FIFO triggers an interrupt event. + * + ***************************************************************************/ + +#define XUARTPS_RXWM_DISABLE 0x00000000U /* Disable RX trigger interrupt */ +#define XUARTPS_RXWM_MASK 0x0000003FU /* Valid bits mask */ +#define XUARTPS_RXWM_RESET_VAL 0x00000020U /* Reset value */ + +/*************************************************************************** + * Transmit FIFO Trigger Level Register + * + * Use the Transmit FIFO Trigger Level Register (TTRIG) to set the value at + * which the TX FIFO triggers an interrupt event. + * + ***************************************************************************/ + +#define XUARTPS_TXWM_MASK 0x0000003FU /* Valid bits mask */ +#define XUARTPS_TXWM_RESET_VAL 0x00000020U /* Reset value */ + +/*************************************************************************** + * Modem Control Register + * + * This register (MODEMCR) controls the interface with the modem or data + * set, or a peripheral device emulating a modem. + * + ***************************************************************************/ + +#define XUARTPS_MODEMCR_FCM 0x00000020U /* Flow control mode */ +#define XUARTPS_MODEMCR_RTS 0x00000002U /* Request to send */ +#define XUARTPS_MODEMCR_DTR 0x00000001U /* Data terminal ready */ + +/*************************************************************************** + * Modem Status Register + * + * This register (MODEMSR) indicates the current state of the control lines + * from a modem, or another peripheral device, to the CPU. In addition, four + * bits of the modem status register provide change information. These bits + * are set to a logic 1 whenever a control input from the modem changes + * state. + * + * Note: Whenever the DCTS, DDSR, TERI, or DDCD bit is set to logic 1, a + * modem status interrupt is generated and this is reflected in the modem + * status register. + * + ***************************************************************************/ + +#define XUARTPS_MODEMSR_FCMS 0x00000100U /* Flow control mode (FCMS) */ +#define XUARTPS_MODEMSR_DCD 0x00000080U /* Complement of DCD input */ +#define XUARTPS_MODEMSR_RI 0x00000040U /* Complement of RI input */ +#define XUARTPS_MODEMSR_DSR 0x00000020U /* Complement of DSR input */ +#define XUARTPS_MODEMSR_CTS 0x00000010U /* Complement of CTS input */ +#define XUARTPS_MODEMSR_DDCD 0x00000008U /* Delta DCD indicator */ +#define XUARTPS_MODEMSR_TERI 0x00000004U /* Trailing Edge Ring Indicator */ +#define XUARTPS_MODEMSR_DDSR 0x00000002U /* Change of DSR */ +#define XUARTPS_MODEMSR_DCTS 0x00000001U /* Change of CTS */ + +/*************************************************************************** + * Channel Status Register + * + * The channel status register (CSR) is provided to enable the control logic + * to monitor the status of bits in the channel interrupt status register, + * even if these are masked out by the interrupt mask register. + * + ***************************************************************************/ + +#define XUARTPS_SR_TNFUL 0x00004000U /* TX FIFO Nearly Full Status */ +#define XUARTPS_SR_TTRIG 0x00002000U /* TX FIFO Trigger Status */ +#define XUARTPS_SR_FLOWDEL 0x00001000U /* RX FIFO fill over flow delay */ +#define XUARTPS_SR_TACTIVE 0x00000800U /* TX active */ +#define XUARTPS_SR_RACTIVE 0x00000400U /* RX active */ +#define XUARTPS_SR_TXFULL 0x00000010U /* TX FIFO full */ +#define XUARTPS_SR_TXEMPTY 0x00000008U /* TX FIFO empty */ +#define XUARTPS_SR_RXFULL 0x00000004U /* RX FIFO full */ +#define XUARTPS_SR_RXEMPTY 0x00000002U /* RX FIFO empty */ +#define XUARTPS_SR_RXOVR 0x00000001U /* RX FIFO fill over trigger */ + +/*************************************************************************** + * Flow Delay Register + * + * Operation of the flow delay register (FLOWDEL) is very similar to the + * receive FIFO trigger register. An internal trigger signal activates when + * the FIFO is filled to the level set by this register. This trigger will + * not cause an interrupt, although it can be read through the channel + * status register. In hardware flow control mode, RTS is deactivated when + * the trigger becomes active. RTS only resets when the FIFO level is four + * less than the level of the flow delay trigger and the flow delay trigger + * is not activated. A value less than 4 disables the flow delay. + * + ***************************************************************************/ + +#define XUARTPS_FLOWDEL_MASK XUARTPS_RXWM_MASK /* Valid bit mask */ + +/*************************************************************************** + * Receiver FIFO Byte Status Register + * + * The Receiver FIFO Status register is used to have a continuous + * monitoring of the raw unmasked byte status information. The register + * contains frame, parity and break status information for the top + * four bytes in the RX FIFO. + * + * Receiver FIFO Byte Status Register Bit Definition + * + ***************************************************************************/ + +#define XUARTPS_RXBS_BYTE3_BRKE 0x00000800U /* Byte3 Break Error */ +#define XUARTPS_RXBS_BYTE3_FRME 0x00000400U /* Byte3 Frame Error */ +#define XUARTPS_RXBS_BYTE3_PARE 0x00000200U /* Byte3 Parity Error */ +#define XUARTPS_RXBS_BYTE2_BRKE 0x00000100U /* Byte2 Break Error */ +#define XUARTPS_RXBS_BYTE2_FRME 0x00000080U /* Byte2 Frame Error */ +#define XUARTPS_RXBS_BYTE2_PARE 0x00000040U /* Byte2 Parity Error */ +#define XUARTPS_RXBS_BYTE1_BRKE 0x00000020U /* Byte1 Break Error */ +#define XUARTPS_RXBS_BYTE1_FRME 0x00000010U /* Byte1 Frame Error */ +#define XUARTPS_RXBS_BYTE1_PARE 0x00000008U /* Byte1 Parity Error */ +#define XUARTPS_RXBS_BYTE0_BRKE 0x00000004U /* Byte0 Break Error */ +#define XUARTPS_RXBS_BYTE0_FRME 0x00000002U /* Byte0 Frame Error */ +#define XUARTPS_RXBS_BYTE0_PARE 0x00000001U /* Byte0 Parity Error */ +#define XUARTPS_RXBS_MASK 0x00000007U /* 3 bit RX byte status mask */ + +/*************************************************************************** + * Private Types + ***************************************************************************/ + +/* UART_XLNXPS UART Configuration */ + +struct xlnxps_config +{ + unsigned long uart; /* UART Base Address */ +}; + +/* UART_XLNXPS UART Device Data */ + +struct xlnxps_data +{ + uint32_t baud_rate; /* UART Baud Rate */ + uint32_t uartclk; /* UART clock frequency */ + uint32_t ier; /* Saved IER value */ + 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 */ +}; + +/* UART_XLNXPS UART Port */ + +struct xlnxps_port_s +{ + struct xlnxps_data data; /* UART Device Data */ + struct xlnxps_config config; /* UART Configuration */ + unsigned int irq_num; /* UART IRQ Number */ + bool is_console; /* 1 if this UART is console */ +}; + +/*************************************************************************** + * Private Function Prototypes + ***************************************************************************/ + +static void xlnxps_rxint(struct uart_dev_s *dev, bool enable); +static void xlnxps_txint(struct uart_dev_s *dev, bool enable); + +/*************************************************************************** + * Private Functions + ***************************************************************************/ + +/*************************************************************************** + * Name: xlnxps_irq_handler + * + * Description: + * This is the common UART interrupt handler. It should call + * uart_xmitchars or uart_recvchars to perform the appropriate data + * transfers. + * + * Input Parameters: + * irq - IRQ Number + * context - Interrupt Context + * arg - UART Device + * + * Returned Value: + * OK is always returned at present. + * + ***************************************************************************/ + +static int xlnxps_irq_handler(int irq, void *context, void *arg) +{ + struct uart_dev_s *dev = (struct uart_dev_s *)arg; + struct xlnxps_port_s *port = (struct xlnxps_port_s *)dev->priv; + struct xlnxps_config *config = &port->config; + uint32_t status; + + DEBUGASSERT(dev != NULL && dev->priv != NULL); + + status = getreg32(config->uart + XUARTPS_ISR_OFFSET); + putreg32(status, (config->uart + XUARTPS_ISR_OFFSET)); + + if (status & XUARTPS_IXR_FRAMING) + { + while (!(getreg32(config->uart + XUARTPS_SR_OFFSET) & + XUARTPS_SR_RXEMPTY)) + { + if (!getreg8(config->uart + XUARTPS_FIFO_OFFSET)) + { + status &= ~XUARTPS_IXR_FRAMING; + } + } + + putreg32(XUARTPS_IXR_FRAMING, (config->uart + XUARTPS_ISR_OFFSET)); + } + + if (status & XUARTPS_IXR_TXEMPTY) + { + uart_xmitchars(dev); + } + + if (status & (XUARTPS_IXR_RXOVR | XUARTPS_IXR_TOUT | XUARTPS_IXR_RXFULL)) + { + while (1) + { + if ((getreg32(config->uart + XUARTPS_SR_OFFSET) & + XUARTPS_SR_RXEMPTY) == XUARTPS_SR_RXEMPTY) + { + break; + } + else + { + uart_recvchars(dev); + } + } + } + + return OK; +} + +static int xlnxps_baudrate(struct uart_dev_s *dev) +{ + struct xlnxps_port_s *port = (struct xlnxps_port_s *)dev->priv; + const struct xlnxps_config *config = &port->config; + struct xlnxps_data *data = &port->data; + uint32_t iter_baud_div; /* Iterator for available baud divisor values */ + uint32_t brgr_value; /* Calculated value for baud rate generator */ + uint32_t calc_baudrate; /* Calculated baud rate */ + uint32_t baud_error; /* Diff between calculated and requested baud rate */ + uint32_t best_brgr = 0U; /* Best value for baud rate generator */ + uint8_t best_baud_div = 0U; /* Best value for baud divisor */ + uint32_t best_error = 0xffffffff; + uint32_t percent_error; + uint32_t reg; + uint32_t input_clk = data->uartclk; + uint32_t temp_reg; + + /* Asserts validate the input arguments */ + + DEBUGASSERT(data->baud_rate <= (uint32_t)XUARTPS_MAX_RATE); + DEBUGASSERT(data->baud_rate >= (uint32_t)XUARTPS_MIN_RATE); + + /* Make sure the baud rate is not impossilby large. + * Fastest possible baud rate is Input Clock / 2. + */ + + if ((data->baud_rate * 2) > input_clk) + { + return ERROR; + } + + /* Check whether the input clock is divided by 8 */ + + reg = getreg32(config->uart + XUARTPS_MR_OFFSET); + + if (reg & XUARTPS_MR_CLKSEL) + { + input_clk = input_clk / 8; + } + + /* Determine the Baud divider. It can be 4to 254. + * Loop through all possible combinations + */ + + for (iter_baud_div = 4; iter_baud_div < 255; iter_baud_div++) + { + /* Calculate the value for BRGR register */ + + brgr_value = input_clk / (data->baud_rate * (iter_baud_div + 1)); + + /* Calculate the baud rate from the BRGR value */ + + calc_baudrate = input_clk / (brgr_value * (iter_baud_div + 1)); + + /* Avoid unsigned integer underflow */ + + if (data->baud_rate > calc_baudrate) + { + baud_error = data->baud_rate - calc_baudrate; + } + else + { + baud_error = calc_baudrate - data->baud_rate; + } + + /* Find the calculated baud rate closest to requested baud rate. */ + + if (best_error > baud_error) + { + best_brgr = brgr_value; + best_baud_div = iter_baud_div; + best_error = baud_error; + } + } + + /* Make sure the best error is not too large. */ + + percent_error = (best_error * 100) / data->baud_rate; + if (XUARTPS_MAX_BAUD_ERROR_RATE < percent_error) + { + return ERROR; + } + + /* Disable TX and RX to avoid glitches when setting the baud rate. */ + + temp_reg = (((getreg32(config->uart + XUARTPS_CR_OFFSET)) & + ((uint32_t)(~XUARTPS_CR_EN_DIS_MASK))) | + ((uint32_t)XUARTPS_CR_RX_DIS | (uint32_t)XUARTPS_CR_TX_DIS)); + putreg32(temp_reg, config->uart + XUARTPS_CR_OFFSET); + + /* Set the baud rate divisor */ + + putreg32(best_brgr, config->uart + XUARTPS_BAUDGEN_OFFSET); + putreg32(best_baud_div, config->uart + XUARTPS_BAUDDIV_OFFSET); + + /* RX and TX SW reset */ + + putreg32(XUARTPS_CR_TXRST | XUARTPS_CR_RXRST, + config->uart + XUARTPS_CR_OFFSET); + + /* Enable device */ + + temp_reg = (((getreg32(config->uart + XUARTPS_CR_OFFSET)) & + ((uint32_t)(~XUARTPS_CR_EN_DIS_MASK))) | + ((uint32_t)XUARTPS_CR_RX_EN | (uint32_t)XUARTPS_CR_TX_EN)); + putreg32(temp_reg, config->uart + XUARTPS_CR_OFFSET); + + return OK; +} + +/*************************************************************************** + * Name: xlnxps_setup + * + * Description: + * Configure the UART baud, bits, parity, fifos, etc. This method is + * called the first time that the serial port is opened. + * + * Input Parameters: + * dev - UART Device + * + * Returned Value: + * Zero (OK) on success; a negated errno value is returned on any failure. + * + ***************************************************************************/ + +static int xlnxps_setup(struct uart_dev_s *dev) +{ +#ifndef CONFIG_SUPPRESS_UART_CONFIG + struct xlnxps_port_s *port = (struct xlnxps_port_s *)dev->priv; + const struct xlnxps_config *config = &port->config; + struct xlnxps_data *data = &port->data; + uint32_t reg = 0U; + + DEBUGASSERT(data != NULL); + + if (xlnxps_baudrate(dev) != OK) + { + return ERROR; + } + + /* Set the parity mode */ + + reg = getreg32(config->uart + XUARTPS_MR_OFFSET); + + /* Mask off what's already there */ + + reg &= (~((uint32_t)XUARTPS_MR_CHARLEN_MASK | + (uint32_t)XUARTPS_MR_STOPMODE_MASK | + (uint32_t)XUARTPS_MR_PARITY_MASK)); + + switch (data->bits) + { + case 6: + reg |= (uint32_t)XUARTPS_MR_CHARLEN_6_BIT; + break; + case 7: + reg |= (uint32_t)XUARTPS_MR_CHARLEN_7_BIT; + break; + case 8: + reg |= (uint32_t)XUARTPS_MR_CHARLEN_8_BIT; + break; + default: + reg |= (uint32_t)XUARTPS_MR_CHARLEN_8_BIT; + break; + } + + if (data->stopbits2) + { + reg |= (uint32_t)XUARTPS_MR_STOPMODE_2_BIT; + } + else + { + reg |= (uint32_t)XUARTPS_MR_STOPMODE_1_BIT; + } + + switch (data->parity) + { + case 0: + reg |= (uint32_t)XUARTPS_MR_PARITY_NONE; + break; + case 1: + reg |= (uint32_t)XUARTPS_MR_PARITY_ODD; + break; + case 2: + reg |= (uint32_t)XUARTPS_MR_PARITY_EVEN; + break; + default: + reg |= (uint32_t)XUARTPS_MR_PARITY_NONE; + break; + } + + /* Write the mode register out */ + + putreg32(reg, config->uart + XUARTPS_MR_OFFSET); + + /* Set the RX FIFO trigger at 8 data bytes. */ + + putreg32(0x08, config->uart + XUARTPS_RXWM_OFFSET); + + /* Set the RX timeout to 1, which will be 4 character time */ + + putreg32(0x01, config->uart + XUARTPS_RXTOUT_OFFSET); + + /* Disable all interrupts, polled mode is the default */ + + putreg32(XUARTPS_IXR_MASK, config->uart + XUARTPS_IDR_OFFSET); + +#endif /* CONFIG_SUPPRESS_UART_CONFIG */ + return OK; +} + +/*************************************************************************** + * Name: xlnxps_shutdown + * + * Description: + * Disable the UART Port. This method is called when the serial + * port is closed. + * + * Input Parameters: + * dev - UART Device + * + * Returned Value: + * None + * + ***************************************************************************/ + +static void xlnxps_shutdown(struct uart_dev_s *dev) +{ + /* Disable the Receive and Transmit Interrupts */ + + xlnxps_rxint(dev, false); + xlnxps_txint(dev, false); +} + +/*************************************************************************** + * Name: xlnxps_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 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. + * + * Input Parameters: + * dev - UART Device + * + * Returned Value: + * Zero (OK) on success; a negated errno value is returned on any failure. + * + ***************************************************************************/ + +static int xlnxps_attach(struct uart_dev_s *dev) +{ + int ret; + struct xlnxps_port_s *port = (struct xlnxps_port_s *)dev->priv; + + DEBUGASSERT(port != NULL); + + /* Attach UART Interrupt Handler */ + + ret = irq_attach(port->irq_num, xlnxps_irq_handler, dev); + + /* Enable UART Interrupt */ + + if (ret == OK) + { + up_enable_irq(port->irq_num); + } + else + { + _err("IRQ attach failed, ret=%d\n", ret); + } + + return ret; +} + +/*************************************************************************** + * Name: xlnxps_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. + * + * Input Parameters: + * dev - UART Device + * + * Returned Value: + * None + * + ***************************************************************************/ + +static void xlnxps_detach(struct uart_dev_s *dev) +{ + struct xlnxps_port_s *port = (struct xlnxps_port_s *)dev->priv; + + DEBUGASSERT(port != NULL); + + /* Disable UART Interrupt */ + + up_disable_irq(port->irq_num); + + /* Detach UART Interrupt Handler */ + + irq_detach(port->irq_num); +} + +/*************************************************************************** + * Name: xlnxps_ioctl + * + * Description: + * All ioctl calls will be routed through this method. + * + * Input Parameters: + * filep - File Struct + * cmd - ioctl Command + * arg - ioctl Argument + * + * Returned Value: + * Zero (OK) on success; a negated errno value is returned on any failure. + * + ***************************************************************************/ + +static int xlnxps_ioctl(struct file *filep, int cmd, unsigned long arg) +{ + int ret = OK; + + UNUSED(filep); + UNUSED(arg); + + switch (cmd) + { + case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */ + case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */ + default: + { + ret = -ENOTTY; + break; + } + } + + return ret; +} + +/*************************************************************************** + * Name: xlnxps_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'. + * + * Input Parameters: + * dev - UART Device + * status - Return status, zero on success + * + * Returned Value: + * Received character + * + ***************************************************************************/ + +static int xlnxps_receive(struct uart_dev_s *dev, unsigned int *status) +{ + struct xlnxps_port_s *port = (struct xlnxps_port_s *)dev->priv; + const struct xlnxps_config *config = &port->config; + uint32_t rbr; + + *status = getreg8(config->uart + XUARTPS_SR_OFFSET) & XUARTPS_SR_RXEMPTY; + + /* Wait until there is data */ + + if (*status) + { + return -1; + } + + rbr = getreg8(config->uart + XUARTPS_FIFO_OFFSET); + return rbr; +} + +/*************************************************************************** + * Name: xlnxps_rxint + * + * Description: + * Call to enable or disable RX interrupts + * + * Input Parameters: + * dev - UART Device + * enable - True to enable RX interrupts; false to disable + * + * Returned Value: + * None + * + ***************************************************************************/ + +static void xlnxps_rxint(struct uart_dev_s *dev, bool enable) +{ + struct xlnxps_port_s *port = (struct xlnxps_port_s *)dev->priv; + struct xlnxps_config *config = &port->config; + + /* Write to Interrupt Enable Register (UART_IER) */ + + if (enable) + { + /* Write the new value for the FIFO control register to it such that + * the threshold is changed + */ + + putreg32(1, config->uart + XUARTPS_RXWM_OFFSET); + + /* Set XUARTPS_IXR_RXOVR bit (Enable Rx Data Available Interrupt) */ + + modreg32(XUARTPS_IXR_RXOVR, XUARTPS_IXR_RXOVR, + config->uart + XUARTPS_IER_OFFSET); + + modreg32(0, XUARTPS_IXR_RXOVR, config->uart + XUARTPS_IDR_OFFSET); + + /* Set XUARTPS_IXR_RXFULL bit (Enable RxFifo full Interrupt) */ + + modreg32(XUARTPS_IXR_RXFULL, XUARTPS_IXR_RXFULL, + config->uart + XUARTPS_IER_OFFSET); + + modreg32(0, XUARTPS_IXR_RXFULL, config->uart + XUARTPS_IDR_OFFSET); + } + else + { + /* Set XUARTPS_IXR_RXOVR bit (Enable Rx Data Available Interrupt) */ + + modreg32(0, XUARTPS_IXR_RXOVR, config->uart + XUARTPS_IER_OFFSET); + modreg32(XUARTPS_IXR_RXOVR, XUARTPS_IXR_RXOVR, + config->uart + XUARTPS_IDR_OFFSET); + + /* Set XUARTPS_IXR_RXFULL bit (Enable RxFifo full Interrupt) */ + + modreg32(0, XUARTPS_IXR_RXFULL, config->uart + XUARTPS_IER_OFFSET); + modreg32(XUARTPS_IXR_RXFULL, XUARTPS_IXR_RXFULL, + config->uart + XUARTPS_IDR_OFFSET); + } +} + +/*************************************************************************** + * Name: xlnxps_rxavailable + * + * Description: + * Return true if the Receive FIFO is not empty + * + * Input Parameters: + * dev - UART Device + * + * Returned Value: + * True if the Receive FIFO is not empty; false otherwise + * + ***************************************************************************/ + +static bool xlnxps_rxavailable(struct uart_dev_s *dev) +{ + struct xlnxps_port_s *port = (struct xlnxps_port_s *)dev->priv; + struct xlnxps_config *config = &port->config; + + /* RxFifo empty bit is 1 if Rx Data is unavailable */ + + return ((getreg8(config->uart + XUARTPS_SR_OFFSET) & + XUARTPS_SR_RXEMPTY) == 0); +} + +/*************************************************************************** + * Name: xlnxps_send + * + * Description: + * This method will send one byte on the UART + * + * Input Parameters: + * dev - UART Device + * ch - Character to be sent + * + * Returned Value: + * None + * + ***************************************************************************/ + +static void xlnxps_send(struct uart_dev_s *dev, int ch) +{ + struct xlnxps_port_s *port = (struct xlnxps_port_s *)dev->priv; + struct xlnxps_config *config = &port->config; + + /* Write char to Transmit FIFO Register */ + + putreg8(ch, config->uart + XUARTPS_FIFO_OFFSET); +} + +/*************************************************************************** + * Name: xlnxps_txint + * + * Description: + * Call to enable or disable TX interrupts + * + * Input Parameters: + * dev - UART Device + * enable - True to enable TX interrupts; false to disable + * + * Returned Value: + * None + * + ***************************************************************************/ + +static void xlnxps_txint(struct uart_dev_s *dev, bool enable) +{ + struct xlnxps_port_s *port = (struct xlnxps_port_s *)dev->priv; + struct xlnxps_config *config = &port->config; + irqstate_t flags; + + flags = enter_critical_section(); + + /* Write to Interrupt Enable Register (UART_IER) */ + + if (enable) + { + /* Set XUARTPS_IXR_TXEMPTY bit (Enable Tx Fifo Empty Interrupt) */ + + modreg32(XUARTPS_IXR_TXEMPTY, XUARTPS_IXR_TXEMPTY, + config->uart + XUARTPS_IER_OFFSET); + + modreg32(0, XUARTPS_IXR_TXEMPTY, config->uart + XUARTPS_IDR_OFFSET); + + /* Fake a TX interrupt */ + + uart_xmitchars(dev); + } + else + { + /* Clear XUARTPS_IXR_TXEMPTY bit (Disable Tx Fifo Empty Interrupt) */ + + modreg32(0, XUARTPS_IXR_TXEMPTY, config->uart + XUARTPS_IER_OFFSET); + modreg32(XUARTPS_IXR_TXEMPTY, XUARTPS_IXR_TXEMPTY, + config->uart + XUARTPS_IDR_OFFSET); + } + + leave_critical_section(flags); +} + +/*************************************************************************** + * Name: xlnxps_txready + * + * Description: + * Return true if the Transmit FIFO is not full + * + * Input Parameters: + * dev - UART Device + * + * Returned Value: + * True if the Transmit FIFO is not full; false otherwise + * + ***************************************************************************/ + +static bool xlnxps_txready(struct uart_dev_s *dev) +{ + struct xlnxps_port_s *port = (struct xlnxps_port_s *)dev->priv; + struct xlnxps_config *config = &port->config; + + /* Tx FIFO is ready if THRE Bit is 1 (Tx Holding Register Empty) */ + + return (getreg8(config->uart + XUARTPS_SR_OFFSET) + & XUARTPS_SR_TXFULL) == 0; +} + +/*************************************************************************** + * Name: xlnxps_txempty + * + * Description: + * Return true if the Transmit FIFO is empty + * + * Input Parameters: + * dev - UART Device + * + * Returned Value: + * True if the Transmit FIFO is empty; false otherwise + * + ***************************************************************************/ + +static bool xlnxps_txempty(struct uart_dev_s *dev) +{ + /* Tx FIFO is empty if Tx FIFO is not full (for now) */ + + return xlnxps_txready(dev); +} + +/*************************************************************************** + * Name: xlnxps_wait_send + * + * Description: + * Wait for Transmit FIFO until it is not full, then transmit the + * character over UART. + * + * Input Parameters: + * dev - UART Device + * ch - Character to be sent + * + * Returned Value: + * None + * + ***************************************************************************/ + +static void xlnxps_wait_send(struct uart_dev_s *dev, int ch) +{ + DEBUGASSERT(dev != NULL); + while (!xlnxps_txready(dev)); + xlnxps_send(dev, ch); +} + +/*************************************************************************** + * Private Data + ***************************************************************************/ + +/* UART Operations for Serial Driver */ + +static const struct uart_ops_s g_uart_ops = +{ + .setup = xlnxps_setup, + .shutdown = xlnxps_shutdown, + .attach = xlnxps_attach, + .detach = xlnxps_detach, + .ioctl = xlnxps_ioctl, + .receive = xlnxps_receive, + .rxint = xlnxps_rxint, + .rxavailable = xlnxps_rxavailable, +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .rxflowcontrol = NULL, +#endif + .send = xlnxps_send, + .txint = xlnxps_txint, + .txready = xlnxps_txready, + .txempty = xlnxps_txempty, +}; + +#ifdef CONFIG_UART_XLNXPS0 + +/* UART0 Port State (Console) */ + +static struct xlnxps_port_s g_uart0priv = +{ + .data = + { + .baud_rate = CONFIG_UART_XLNXPS0_BAUD, + .uartclk = CONFIG_UART_XLNXPS0_CLOCK, + .parity = CONFIG_UART_XLNXPS0_PARITY, + .bits = CONFIG_UART_XLNXPS0_BITS, + .stopbits2 = CONFIG_UART_XLNXPS0_2STOP + }, + + .config = + { + .uart = CONFIG_UART_XLNXPS0_BASE + }, + + .irq_num = CONFIG_UART_XLNXPS0_IRQ, + .is_console = 1 +}; + +/* UART0 I/O Buffers (Console) */ + +static char g_uart0rxbuffer[CONFIG_UART_XLNXPS0_RXBUFSIZE]; +static char g_uart0txbuffer[CONFIG_UART_XLNXPS0_TXBUFSIZE]; + +/* UART0 Port Definition (Console) */ + +static struct uart_dev_s g_uart0port = +{ + .recv = + { + .size = CONFIG_UART_XLNXPS0_RXBUFSIZE, + .buffer = g_uart0rxbuffer, + }, + + .xmit = + { + .size = CONFIG_UART_XLNXPS0_TXBUFSIZE, + .buffer = g_uart0txbuffer, + }, + + .ops = &g_uart_ops, + .priv = &g_uart0priv, +}; + +#endif /* CONFIG_UART_XLNXPS_UART */ + +/*************************************************************************** + * Public Functions + ***************************************************************************/ + +/*************************************************************************** + * Name: arm64_earlyserialinit + * + * Description: + * Performs the low level UART initialization early in + * debug so that the serial console will be available + * during boot up. This must be called before arm64_serialinit. + * + * Returned Value: + * None + * + ***************************************************************************/ + +void xlnxps_earlyserialinit(void) +{ + int ret; + + /* NOTE: This function assumes that UART0 low level hardware configuration + * -- including all clocking and pin configuration + */ + +#ifdef CONSOLE_DEV + /* Enable the console at UART0 */ + + CONSOLE_DEV.isconsole = true; + xlnxps_setup(&CONSOLE_DEV); +#endif + + UNUSED(ret); +} + +/*************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug + * writes + * + * Input Parameters: + * ch - Character to be transmitted over UART + * + * Returned Value: + * Character that was transmitted + * + ***************************************************************************/ + +void up_putc(int ch) +{ +#ifdef CONSOLE_DEV + struct uart_dev_s *dev = &CONSOLE_DEV; + + xlnxps_wait_send(dev, ch); +#endif +} + +/*************************************************************************** + * Name: arm64_serialinit + * + * Description: + * Register serial console and serial ports. This assumes + * that zynq_earlyserialinit was called previously. + * + * Returned Value: + * None + * + ***************************************************************************/ + +void xlnxps_serialinit(void) +{ +#ifdef CONSOLE_DEV + int ret; + + ret = uart_register("/dev/console", &CONSOLE_DEV); + if (ret < 0) + { + _err("Register /dev/console failed, ret=%d\n", ret); + } + + ret = uart_register("/dev/ttyS0", &TTYS0_DEV); + + if (ret < 0) + { + _err("Register /dev/ttyS0 failed, ret=%d\n", ret); + } + +#ifdef TTYS1_DEV + ret = uart_register("/dev/ttyS1", &TTYS1_DEV); + + if (ret < 0) + { + _err("Register /dev/ttyS1 failed, ret=%d\n", ret); + } +#endif /* TTYS1_DEV */ + +#endif +} + +#endif /* CONFIG_UART_XLNXPS */ diff --git a/include/nuttx/serial/uart_xlnx_ps.h b/include/nuttx/serial/uart_xlnx_ps.h new file mode 100644 index 00000000000..07a620db4e6 --- /dev/null +++ b/include/nuttx/serial/uart_xlnx_ps.h @@ -0,0 +1,48 @@ +/**************************************************************************** + * include/nuttx/serial/uart_xlnx_ps.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_SERIAL_UART_XLNXPS_H +#define __INCLUDE_NUTTX_SERIAL_UART_XLNXPS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_UART_XLNXPS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +void xlnxps_earlyserialinit(void); + +void xlnxps_serialinit(void); + +#endif /* CONFIG_UART_XLNXPS */ + +#endif /* __INCLUDE_NUTTX_SERIAL_UART_XLNXPS_H */