diff --git a/arch/arm/src/imxrt/Kconfig b/arch/arm/src/imxrt/Kconfig index c2657bbd8bc..4783121cd5a 100644 --- a/arch/arm/src/imxrt/Kconfig +++ b/arch/arm/src/imxrt/Kconfig @@ -419,6 +419,14 @@ config IMXRT_LPUART_INVERT Enable signal inversion UART support. The option enables support for the TIOCSINVERT ioctl in the IMXRT serial driver. +config IMXRT_LPUART_SINGLEWIRE + bool "Single Wire Support" + default n + depends on IMXRT_HAVE_LPUART + ---help--- + Enable single wire UART support. The option enables support for the + TIOCSSINGLEWIRE ioctl in the IMXRT serial driver. + endmenu # LPUART Configuration menu "FLEXCAN Peripherals" diff --git a/arch/arm/src/imxrt/imxrt_serial.c b/arch/arm/src/imxrt/imxrt_serial.c index 1d713abd2cd..2074c47ab1e 100644 --- a/arch/arm/src/imxrt/imxrt_serial.c +++ b/arch/arm/src/imxrt/imxrt_serial.c @@ -1,35 +1,20 @@ /**************************************************************************** * arch/arm/src/imxrt/imxrt_serial.c * - * Copyright (C) 2018, 2019 Gregory Nutt. All rights reserved. - * Author: Ivan Ucherdzhiev + * 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 * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * http://www.apache.org/licenses/LICENSE-2.0 * - * 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. + * 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. * ****************************************************************************/ @@ -334,6 +319,9 @@ struct imxrt_uart_s #ifdef CONFIG_SERIAL_OFLOWCONTROL const uint32_t cts_gpio; /* U[S]ART CTS GPIO pin configuration */ #endif +#ifdef CONFIG_IMXRT_LPUART_SINGLEWIRE + const uint32_t tx_gpio; /* TX GPIO pin configuration */ +#endif uint8_t stopbits2:1; /* 1: Configure with 2 stop bits vs 1 */ #ifdef CONFIG_SERIAL_IFLOWCONTROL @@ -470,6 +458,9 @@ static struct imxrt_uart_s g_uart1priv = || (defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_LPUART1_IFLOWCONTROL))) .rts_gpio = GPIO_LPUART1_RTS, #endif +#ifdef CONFIG_IMXRT_LPUART_SINGLEWIRE + .tx_gpio = GPIO_LPUART1_TX, +#endif #if (((defined(CONFIG_SERIAL_RS485CONTROL) || defined(CONFIG_SERIAL_IFLOWCONTROL))) \ && defined(CONFIG_LPUART1_INVERTIFLOWCONTROL)) @@ -520,6 +511,9 @@ static struct imxrt_uart_s g_uart2priv = || (defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_LPUART2_IFLOWCONTROL))) .rts_gpio = GPIO_LPUART2_RTS, #endif +#ifdef CONFIG_IMXRT_LPUART_SINGLEWIRE + .tx_gpio = GPIO_LPUART2_TX, +#endif #if (((defined(CONFIG_SERIAL_RS485CONTROL) || defined(CONFIG_SERIAL_IFLOWCONTROL))) \ && defined(CONFIG_LPUART2_INVERTIFLOWCONTROL)) .inviflow = 1, @@ -567,6 +561,9 @@ static struct imxrt_uart_s g_uart3priv = || (defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_LPUART3_IFLOWCONTROL))) .rts_gpio = GPIO_LPUART3_RTS, #endif +#ifdef CONFIG_IMXRT_LPUART_SINGLEWIRE + .tx_gpio = GPIO_LPUART3_TX, +#endif #if (((defined(CONFIG_SERIAL_RS485CONTROL) || defined(CONFIG_SERIAL_IFLOWCONTROL))) \ && defined(CONFIG_LPUART3_INVERTIFLOWCONTROL)) .inviflow = 1, @@ -614,6 +611,9 @@ static struct imxrt_uart_s g_uart4priv = || (defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_LPUART4_IFLOWCONTROL))) .rts_gpio = GPIO_LPUART4_RTS, #endif +#ifdef CONFIG_IMXRT_LPUART_SINGLEWIRE + .tx_gpio = GPIO_LPUART4_TX, +#endif #if (((defined(CONFIG_SERIAL_RS485CONTROL) || defined(CONFIG_SERIAL_IFLOWCONTROL))) \ && defined(CONFIG_LPUART4_INVERTIFLOWCONTROL)) .inviflow = 1, @@ -661,6 +661,9 @@ static struct imxrt_uart_s g_uart5priv = || (defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_LPUART5_IFLOWCONTROL))) .rts_gpio = GPIO_LPUART5_RTS, #endif +#ifdef CONFIG_IMXRT_LPUART_SINGLEWIRE + .tx_gpio = GPIO_LPUART5_TX, +#endif #if (((defined(CONFIG_SERIAL_RS485CONTROL) || defined(CONFIG_SERIAL_IFLOWCONTROL))) \ && defined(CONFIG_LPUART5_INVERTIFLOWCONTROL)) .inviflow = 1, @@ -708,6 +711,9 @@ static struct imxrt_uart_s g_uart6priv = || (defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_LPUART6_IFLOWCONTROL))) .rts_gpio = GPIO_LPUART6_RTS, #endif +#ifdef CONFIG_IMXRT_LPUART_SINGLEWIRE + .tx_gpio = GPIO_LPUART6_TX, +#endif #if (((defined(CONFIG_SERIAL_RS485CONTROL) || defined(CONFIG_SERIAL_IFLOWCONTROL))) \ && defined(CONFIG_LPUART6_INVERTIFLOWCONTROL)) .inviflow = 1, @@ -755,6 +761,9 @@ static struct imxrt_uart_s g_uart7priv = || (defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_LPUART7_IFLOWCONTROL))) .rts_gpio = GPIO_LPUART7_RTS, #endif +#ifdef CONFIG_IMXRT_LPUART_SINGLEWIRE + .tx_gpio = GPIO_LPUART7_TX, +#endif #if (((defined(CONFIG_SERIAL_RS485CONTROL) || defined(CONFIG_SERIAL_IFLOWCONTROL))) \ && defined(CONFIG_LPUART7_INVERTIFLOWCONTROL)) .inviflow = 1, @@ -802,6 +811,9 @@ static struct imxrt_uart_s g_uart8priv = || (defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_LPUART8_IFLOWCONTROL))) .rts_gpio = GPIO_LPUART8_RTS, #endif +#ifdef CONFIG_IMXRT_LPUART_SINGLEWIRE + .tx_gpio = GPIO_LPUART8_TX, +#endif #if (((defined(CONFIG_SERIAL_RS485CONTROL) || defined(CONFIG_SERIAL_IFLOWCONTROL))) \ && defined(CONFIG_LPUART8_INVERTIFLOWCONTROL)) .inviflow = 1, @@ -1315,6 +1327,44 @@ static int imxrt_ioctl(struct file *filep, int cmd, unsigned long arg) break; #endif /* CONFIG_SERIAL_TERMIOS */ +#ifdef CONFIG_IMXRT_LPUART_SINGLEWIRE + case TIOCSSINGLEWIRE: + { + uint32_t regval; + irqstate_t flags; + struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev->priv; + + flags = spin_lock_irqsave(); + regval = imxrt_serialin(priv, IMXRT_LPUART_CTRL_OFFSET); + + if ((arg & SER_SINGLEWIRE_ENABLED) != 0) + { + uint32_t gpio_val = IOMUX_OPENDRAIN; + gpio_val |= (arg & SER_SINGLEWIRE_PULL_MASK) == + SER_SINGLEWIRE_PULLUP ? + IOMUX_PULL_UP_47K : IOMUX_PULL_NONE; + gpio_val |= (arg & SER_SINGLEWIRE_PULL_MASK) == + SER_SINGLEWIRE_PULLDOWN ? + IOMUX_PULL_DOWN_100K : IOMUX_PULL_NONE; + imxrt_config_gpio((priv->tx_gpio & + ~(IOMUX_PULL_MASK | IOMUX_OPENDRAIN)) | gpio_val); + regval |= LPUART_CTRL_LOOPS | LPUART_CTRL_RSRC; + } + else + { + imxrt_config_gpio((priv->tx_gpio & ~(IOMUX_PULL_MASK | + IOMUX_OPENDRAIN)) | + IOMUX_PULL_NONE); + regval &= ~(LPUART_CTRL_LOOPS | LPUART_CTRL_RSRC); + } + + imxrt_serialout(priv, IMXRT_LPUART_CTRL_OFFSET, regval); + + spin_unlock_irqrestore(flags); + } + break; +#endif + #ifdef CONFIG_IMXRT_LPUART_INVERT case TIOCSINVERT: {