Received: by 2002:a05:7412:d8a:b0:e2:908c:2ebd with SMTP id b10csp512566rdg; Thu, 12 Oct 2023 12:05:28 -0700 (PDT) X-Google-Smtp-Source: AGHT+IECCKqcMTCOs+Qo72tRXexjIRc0GEtkwm2QaP4yvmE2vdlclm5JCUDvGyLOfpnB2DjMOGBs X-Received: by 2002:a17:902:e194:b0:1c9:e508:ad43 with SMTP id y20-20020a170902e19400b001c9e508ad43mr1671359pla.8.1697137528393; Thu, 12 Oct 2023 12:05:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1697137528; cv=none; d=google.com; s=arc-20160816; b=TqSnldjjRMatXeJ48ypOnm7zPZoVpT0G2IgdftJ6YzcEa+MB2YPlZuqe0M+AwKP2WL VfRR3ymb9lkrscjqsX4wgDIxtMeGaY7Hl6evaliRilTZOfVAXjS+7SPPcVrE828eqw5I CfrbsGMahB+wJQ+5zPUCPthjho0/XYgq61uWpohYx7C151n3bhfOAhKdqzCRGFF6wxlp lvmaizgieimYzy7mFLdFGkchsjTr6gAFt/eJMykUX+04QI1xQPIoy1LLE7xiLf1eTLFN zZoWpd1RD/Yp2PQa0Zg8sv7TsZ+uwgDQ4tQlMdzd5x7kABytsAhISlEzgI5AlIudkDJU 7dpQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:message-id:references :in-reply-to:subject:cc:to:from:date:mime-version; bh=BkiKQ86PN0ObIqcwfBS5gluYW73JwQql2T6M59T0LrU=; fh=kIKSXYqsb8/ShL1tUChtNnhp5lV3pnhORsO3H88Nx4o=; b=xtFPjtQyf3mqfFWZAhrWHFhMXHNQ+eHrc5d5Eqx3b16XAcEBqickmfnqRRhe+hW9X7 1fPGiuETVgNdXy1Ug8oSxWq4dLb5TGofr/0EsxpxGxAhSv6fLL1Vy5dC0szREYGoKBFt pZDea2gIC8133xLKn7rL7Jiha1HLPKOc8O1x+OZ/FYjcVNRW+nRTKszSTIgEuMtt8VjR LiJrYRwlT3iQOyIcVf5gTW9p4f0y16+1PhOWUU4cGE6R7rkX4lwemh8pTj20ZD2S+bfX 9VK1+3AxA7CcgZrCq+/lHa2I01ysFP6R2fygWIjW/BgfE7yKywYkG2orndmSPUf8YDRD VcWg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.31 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from morse.vger.email (morse.vger.email. [23.128.96.31]) by mx.google.com with ESMTPS id w8-20020a170902d70800b001c754e83e06si2810139ply.164.2023.10.12.12.05.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 12 Oct 2023 12:05:28 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.31 as permitted sender) client-ip=23.128.96.31; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.31 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by morse.vger.email (Postfix) with ESMTP id 29C4E83F6992; Thu, 12 Oct 2023 12:05:25 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at morse.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1441912AbjJLTFM (ORCPT + 99 others); Thu, 12 Oct 2023 15:05:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58032 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229576AbjJLTFL (ORCPT ); Thu, 12 Oct 2023 15:05:11 -0400 Received: from connect.vanmierlo.com (fieber.vanmierlo.com [84.243.197.177]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5DFEABE; Thu, 12 Oct 2023 12:05:09 -0700 (PDT) X-Footer: dmFubWllcmxvLmNvbQ== Received: from roundcube.vanmierlo.com ([192.168.37.37]) (authenticated user m.brock@vanmierlo.com) by connect.vanmierlo.com (Kerio Connect 9.4.2) with ESMTPA; Thu, 12 Oct 2023 21:05:02 +0200 MIME-Version: 1.0 Date: Thu, 12 Oct 2023 21:05:02 +0200 From: m.brock@vanmierlo.com To: Manikanta Guntupalli Cc: git@amd.com, michal.simek@amd.com, gregkh@linuxfoundation.org, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org, linux-serial@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, jirislaby@kernel.org, linux-arm-kernel@lists.infradead.org, radhey.shyam.pandey@amd.com, srinivas.goud@amd.com, shubhrajyoti.datta@amd.com, manion05gk@gmail.com Subject: Re: [PATCH V2 2/2] tty: serial: uartps: Add rs485 support to uartps driver In-Reply-To: <20231011145602.3619616-3-manikanta.guntupalli@amd.com> References: <20231011145602.3619616-1-manikanta.guntupalli@amd.com> <20231011145602.3619616-3-manikanta.guntupalli@amd.com> Message-ID: <47fcf873a011291d06740ee9af3a45e4@vanmierlo.com> X-Sender: m.brock@vanmierlo.com Content-Type: text/plain; charset=US-ASCII; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-0.8 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on morse.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (morse.vger.email [0.0.0.0]); Thu, 12 Oct 2023 12:05:25 -0700 (PDT) Manikanta Guntupalli wrote on 2023-10-11 16:56: > In RS485 half duplex configuration, DriverEnable and ReceiverEnable > shorted to each other, and at a time, any node acts as either a driver > or a receiver. Use either xlnx,phy-ctrl-gpios or RTS to control > RS485 phy as driver or a receiver. > > Signed-off-by: Manikanta Guntupalli > --- > Changes for V2: > Modify optional gpio name to xlnx,phy-ctrl-gpios. > Update commit description. > Add support for RTS, delay_rts_before_send and delay_rts_after_send in > RS485 mode. > --- > drivers/tty/serial/xilinx_uartps.c | 116 ++++++++++++++++++++++++++++- > 1 file changed, 115 insertions(+), 1 deletion(-) > > diff --git a/drivers/tty/serial/xilinx_uartps.c > b/drivers/tty/serial/xilinx_uartps.c > index 8e521c69a959..abddcf1a8bf4 100644 > --- a/drivers/tty/serial/xilinx_uartps.c > +++ b/drivers/tty/serial/xilinx_uartps.c > @@ -23,6 +23,7 @@ > #include > #include > #include > +#include > > #define CDNS_UART_TTY_NAME "ttyPS" > #define CDNS_UART_NAME "xuartps" > @@ -193,6 +194,7 @@ MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255"); > * @clk_rate_change_nb: Notifier block for clock changes > * @quirks: Flags for RXBS support. > * @cts_override: Modem control state override > + * @gpiod: Pointer to the gpio descriptor > */ > struct cdns_uart { > struct uart_port *port; > @@ -203,10 +205,19 @@ struct cdns_uart { > struct notifier_block clk_rate_change_nb; > u32 quirks; > bool cts_override; > + struct gpio_desc *gpiod; > }; > struct cdns_platform_data { > u32 quirks; > }; > + > +struct serial_rs485 cdns_rs485_supported = { > + .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | > + SER_RS485_RTS_AFTER_SEND, You promise here to support both RTS-on-send and RTS-after-send, but... > + .delay_rts_before_send = 1, > + .delay_rts_after_send = 1, > +}; > + > #define to_cdns_uart(_nb) container_of(_nb, struct cdns_uart, \ > clk_rate_change_nb) > > @@ -305,6 +316,42 @@ static void cdns_uart_handle_rx(void *dev_id, > unsigned int isrstatus) > tty_flip_buffer_push(&port->state->port); > } > > +/** > + * cdns_rs485_tx_setup - Tx setup specific to rs485 > + * @cdns_uart: Handle to the cdns_uart > + */ > +static void cdns_rs485_tx_setup(struct cdns_uart *cdns_uart) > +{ > + u32 val; > + > + if (cdns_uart->gpiod) { > + gpiod_set_value(cdns_uart->gpiod, 1); > + } else { > + val = readl(cdns_uart->port->membase + CDNS_UART_MODEMCR); > + val &= ~CDNS_UART_MODEMCR_RTS; > + writel(val, cdns_uart->port->membase + CDNS_UART_MODEMCR); Here you don't care about RTS-on-send or RTS-after-send anymore. And neither do you btw. in the if clause. > + } > +} > + > +/** > + * cdns_rs485_rx_setup - Rx setup specific to rs485 > + * @cdns_uart: Handle to the cdns_uart > + */ > +static void cdns_rs485_rx_setup(struct cdns_uart *cdns_uart) > +{ > + u32 val; > + > + if (cdns_uart->gpiod) { > + gpiod_set_value(cdns_uart->gpiod, 0); > + } else { > + val = readl(cdns_uart->port->membase + CDNS_UART_MODEMCR); > + val |= CDNS_UART_MODEMCR_RTS; > + writel(val, cdns_uart->port->membase + CDNS_UART_MODEMCR); > + } Same here. > +} > + > +static unsigned int cdns_uart_tx_empty(struct uart_port *port); > + I think it's better to move up the implementation than to use a forward declaration. > /** > * cdns_uart_handle_tx - Handle the bytes to be Txed. > * @dev_id: Id of the UART port > @@ -313,12 +360,20 @@ static void cdns_uart_handle_rx(void *dev_id, > unsigned int isrstatus) > static void cdns_uart_handle_tx(void *dev_id) > { > struct uart_port *port = (struct uart_port *)dev_id; > + struct cdns_uart *cdns_uart = port->private_data; > struct circ_buf *xmit = &port->state->xmit; > + unsigned long time_out; > unsigned int numbytes; > > + if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED) { > + cdns_rs485_tx_setup(cdns_uart); > + if (cdns_uart->port->rs485.delay_rts_before_send) > + mdelay(cdns_uart->port->rs485.delay_rts_before_send); mdelay? https://www.kernel.org/doc/html/latest/timers/timers-howto.html "In general, use of mdelay is discouraged and code should be refactored to allow for the use of msleep." Furthermore, you're delaying before every burst of bytes here! Every TXEMPTY interrupt! > + } > + > if (uart_circ_empty(xmit)) { > writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IDR); > - return; > + goto rs485_rx_setup; And when there was nothing more to send you waited for nothing. > } > > numbytes = port->fifosize; > @@ -332,6 +387,23 @@ static void cdns_uart_handle_tx(void *dev_id) > > if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) > uart_write_wakeup(port); > + > +rs485_rx_setup: > + if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED) { > + time_out = jiffies + usecs_to_jiffies(TX_TIMEOUT); > + /* Wait for tx completion */ > + while ((cdns_uart_tx_empty(cdns_uart->port) != TIOCSER_TEMT) && > + time_before(jiffies, time_out)) > + cpu_relax(); > + > + /* > + * Default Rx should be setup, because RX signaling path > + * need to enable to receive data. > + */ > + cdns_rs485_rx_setup(cdns_uart); > + if (cdns_uart->port->rs485.delay_rts_after_send) > + mdelay(cdns_uart->port->rs485.delay_rts_after_send); This is not delaying rts after send. You must keep RTS aka DE active for a little longer so even the last stop bit(s) are transmitted correctly. So this delay must happen before cdns_rs485_rx_setup(). > + } > } > > /** > @@ -829,6 +901,9 @@ static int cdns_uart_startup(struct uart_port > *port) > (CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST)) > cpu_relax(); > > + if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED) > + cdns_rs485_rx_setup(cdns_uart); > + > /* > * Clear the RX disable bit and then set the RX enable bit to enable > * the receiver. > @@ -1455,6 +1530,25 @@ MODULE_DEVICE_TABLE(of, cdns_uart_of_match); > /* Temporary variable for storing number of instances */ > static int instances; > > +/** > + * cdns_rs485_config - Called when an application calls TIOCSRS485 > ioctl. > + * @port: Pointer to the uart_port structure > + * @termios: Pointer to the ktermios structure > + * @rs485: Pointer to the serial_rs485 structure > + * > + * Return: 0 > + */ > +static int cdns_rs485_config(struct uart_port *port, struct ktermios > *termios, > + struct serial_rs485 *rs485) > +{ > + port->rs485 = *rs485; > + > + if (rs485->flags & SER_RS485_ENABLED) > + dev_dbg(port->dev, "Setting UART to RS485\n"); > + > + return 0; > +} > + > /** > * cdns_uart_probe - Platform driver probe > * @pdev: Pointer to the platform device structure > @@ -1597,9 +1691,28 @@ static int cdns_uart_probe(struct > platform_device *pdev) > port->private_data = cdns_uart_data; > port->read_status_mask = CDNS_UART_IXR_TXEMPTY | CDNS_UART_IXR_RXTRIG > | > CDNS_UART_IXR_OVERRUN | CDNS_UART_IXR_TOUT; > + port->rs485_config = cdns_rs485_config; > + port->rs485_supported = cdns_rs485_supported; > cdns_uart_data->port = port; > platform_set_drvdata(pdev, port); > > + rc = uart_get_rs485_mode(port); > + if (rc) > + goto err_out_clk_notifier; > + > + cdns_uart_data->gpiod = devm_gpiod_get_optional(&pdev->dev, > "xlnx,phy-ctrl", > + GPIOD_OUT_LOW); > + if (IS_ERR(cdns_uart_data->gpiod)) { > + rc = PTR_ERR(cdns_uart_data->gpiod); > + dev_err(port->dev, "xuartps: devm_gpiod_get_optional failed\n"); > + goto err_out_clk_notifier; > + } > + > + if (cdns_uart_data->gpiod) { > + gpiod_direction_output(cdns_uart_data->gpiod, GPIOD_OUT_LOW); > + gpiod_set_value(cdns_uart_data->gpiod, 0); > + } > + > pm_runtime_use_autosuspend(&pdev->dev); > pm_runtime_set_autosuspend_delay(&pdev->dev, > UART_AUTOSUSPEND_TIMEOUT); > pm_runtime_set_active(&pdev->dev); > @@ -1646,6 +1759,7 @@ static int cdns_uart_probe(struct platform_device > *pdev) > pm_runtime_disable(&pdev->dev); > pm_runtime_set_suspended(&pdev->dev); > pm_runtime_dont_use_autosuspend(&pdev->dev); > +err_out_clk_notifier: > #ifdef CONFIG_COMMON_CLK > clk_notifier_unregister(cdns_uart_data->uartclk, > &cdns_uart_data->clk_rate_change_nb); Maarten