From patchwork Mon Apr 25 14:33:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ilpo_J=C3=A4rvinen?= X-Patchwork-Id: 565984 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E75ACC4332F for ; Mon, 25 Apr 2022 14:34:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238160AbiDYOhw (ORCPT ); Mon, 25 Apr 2022 10:37:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35458 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242554AbiDYOhr (ORCPT ); Mon, 25 Apr 2022 10:37:47 -0400 Received: from mga06.intel.com (mga06b.intel.com [134.134.136.31]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2593C119EC2 for ; Mon, 25 Apr 2022 07:34:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1650897284; x=1682433284; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ahf6luvamXfjWySFVgd1FO4nQOJsxLim3rn4ggOMvVA=; b=g2UMjzUke58ekocNJG8UiMEI5weEqOJvHN0siltU4BF8Ro59ShJdpv5J A7+3ALVitjXVA37NZqPjVkwtTAbT6JwNtlZs2xKyMZoo6ZHbC6hftnnaH KDVOkvvjp0FPur6Q2GzuKOyhe4y56bv37vYk3TARjFqCaC0wlblHomfwl JKUvkfm4ME/sypHRgIesgFCsnIH81A1GYj2QkpeHOu7yANO5dpIat/wsq Fqdcqlj26vtM7IFV/Vg0CC7n8GL6S0bxDLobRfyS/cveOrjflyTvkgVrP Fyj2Jx81IFved16sV6LxIxRt1X1OEb9fCgm9w9KGlaKLzB+KLpiIPnMsL Q==; X-IronPort-AV: E=McAfee;i="6400,9594,10328"; a="325752059" X-IronPort-AV: E=Sophos;i="5.90,288,1643702400"; d="scan'208";a="325752059" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Apr 2022 07:34:43 -0700 X-IronPort-AV: E=Sophos;i="5.90,288,1643702400"; d="scan'208";a="579315628" Received: from lpuglia-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.251.217.93]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Apr 2022 07:34:38 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Lukas Wunner , Andy Shevchenko , Vicente Bergas , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= Cc: Johan Hovold , heiko@sntech.de, giulio.benetti@micronovasrl.com, Heikki Krogerus , =?utf-8?q?Ilpo_J=C3=A4rv?= =?utf-8?q?inen?= Subject: [PATCH v4 02/13] serial: 8250: use THRE & __stop_tx also with DMA Date: Mon, 25 Apr 2022 17:33:59 +0300 Message-Id: <20220425143410.12703-3-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220425143410.12703-1-ilpo.jarvinen@linux.intel.com> References: <20220425143410.12703-1-ilpo.jarvinen@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org 8250 DMA tx complete path lacks calls to normal 8250 stop handling. It does not use THRE to detect true completion of the tx and also doesn't call __stop_tx. This leads to problems with em485 that needs to handle RTS timing. Instead of handling tx stop internally within 8250 dma code, enable THRE when tx'able data runs out and tweak serial8250_handle_irq to call only __stop_tx when uart is using DMA. It also seems bit early to call serial8250_rpm_put_tx from there while tx is still underway(?). Tested-by: Vicente Bergas Signed-off-by: Ilpo Järvinen --- drivers/tty/serial/8250/8250_dma.c | 3 +-- drivers/tty/serial/8250/8250_port.c | 9 ++++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c index 890fa7ddaa7f..e1625a73ce57 100644 --- a/drivers/tty/serial/8250/8250_dma.c +++ b/drivers/tty/serial/8250/8250_dma.c @@ -34,7 +34,7 @@ static void __dma_tx_complete(void *param) uart_write_wakeup(&p->port); ret = serial8250_tx_dma(p); - if (ret) + if (ret || !dma->tx_running) serial8250_set_THRI(p); spin_unlock_irqrestore(&p->port.lock, flags); @@ -71,7 +71,6 @@ int serial8250_tx_dma(struct uart_8250_port *p) if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) { /* We have been called from __dma_tx_complete() */ - serial8250_rpm_put_tx(p); return 0; } diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index d30a6c1c4c20..40b62126c1ca 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1950,9 +1950,12 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) status = serial8250_rx_chars(up, status); } serial8250_modem_status(up); - if ((!up->dma || up->dma->tx_err) && (status & UART_LSR_THRE) && - (up->ier & UART_IER_THRI)) - serial8250_tx_chars(up); + if ((status & UART_LSR_THRE) && (up->ier & UART_IER_THRI)) { + if (!up->dma || up->dma->tx_err) + serial8250_tx_chars(up); + else + __stop_tx(up); + } uart_unlock_and_check_sysrq_irqrestore(port, flags); From patchwork Mon Apr 25 14:34:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ilpo_J=C3=A4rvinen?= X-Patchwork-Id: 565983 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8D4FAC433F5 for ; Mon, 25 Apr 2022 14:35:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242186AbiDYOiA (ORCPT ); Mon, 25 Apr 2022 10:38:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36228 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231672AbiDYOh6 (ORCPT ); Mon, 25 Apr 2022 10:37:58 -0400 Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A5AF0119EC2 for ; Mon, 25 Apr 2022 07:34:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1650897294; x=1682433294; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=tXbTqRELZAeyhHo9dP/WkW4MMsShDVptDNpHd/BBQKc=; b=gUP1/XqC56D7sNdMAuijOC0HrGwsroLS5QR5+0kHXWz9+0HRkw0w+/UC GzuI4Z5zQTtJpN5cN1bRSU82Aecmg2AZyA+4nSQg+GwdChU2eLI8MFr5J B3ROPfE7yN1pXtvxmCDRIZhr++PXSJDGRY0Gc04CPiVoaa+Q7hxmqGuVy d9TbVk6OpNFLBtYn2xWBrub7iDT4WVFw8bAYzsr7hygtiioc1iV9Je8l1 Np/BT6mUCQAtXvHhk5tV28oc7ifaMZUMLlYp8Ci/8A+OwqmXxo6TRfx1T yziF2V0JO3YRip5x91LiYWx8s0sGoR/KWTwZwbdlvOo/NX1epf5YNlt8d g==; X-IronPort-AV: E=McAfee;i="6400,9594,10328"; a="264112909" X-IronPort-AV: E=Sophos;i="5.90,288,1643702400"; d="scan'208";a="264112909" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Apr 2022 07:34:54 -0700 X-IronPort-AV: E=Sophos;i="5.90,288,1643702400"; d="scan'208";a="579315682" Received: from lpuglia-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.251.217.93]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Apr 2022 07:34:49 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Lukas Wunner , Andy Shevchenko , Vicente Bergas , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= Cc: Johan Hovold , heiko@sntech.de, giulio.benetti@micronovasrl.com, Heikki Krogerus , =?utf-8?q?Ilpo_J=C3=A4rv?= =?utf-8?q?inen?= , Eric Tremblay Subject: [PATCH v4 03/13] serial: 8250: Handle UART without interrupt on TEMT Date: Mon, 25 Apr 2022 17:34:00 +0300 Message-Id: <20220425143410.12703-4-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220425143410.12703-1-ilpo.jarvinen@linux.intel.com> References: <20220425143410.12703-1-ilpo.jarvinen@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org Add UART_CAP_NOTEMT for UARTs that lack interrupt on TEMT but want to use em485. Em485 framework needs to ensure not only FIFO is empty but also that tx shift register is empty. This approach uses Uwe Kleine-König's suggestion on simply using/incrementing stop_tx timer rather than adding another timer. When UART_CAP_NOTEMT is set and THRE is present w/o TEMT, stop tx timer is reused to wait for the emptying of the shift register. This change does not add the UART_CAP_NOTEMT define as it already exist but is currently no-op. See 7a107b2c6b81 (Revert "serial: 8250: Handle UART without interrupt on TEMT using em485") for further details. Vicente Bergas reported that RTS is deasserted roughly one bit too early losing stop bit tx. To address this problem, stop_delay now accounts for one extra bit using rough formula /7 (assumes worst-case of 2+5 bits). I suspect this glitch had to do with when THRE is getting asserted. If FIFO is emptied already during the tx of the stop bit, perhaps it leads to HW asserting THRE early for the normal frame time formula to work accurately. Suggested-by: Uwe Kleine-König Cc: Eric Tremblay Tested-by: Vicente Bergas Signed-off-by: Ilpo Järvinen --- drivers/tty/serial/8250/8250_port.c | 35 +++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 40b62126c1ca..da78a7fa763f 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1504,18 +1504,19 @@ static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec) hrtimer_start(hrt, ms_to_ktime(msec), HRTIMER_MODE_REL); } -static void __stop_tx_rs485(struct uart_8250_port *p) +static void __stop_tx_rs485(struct uart_8250_port *p, u64 stop_delay) { struct uart_8250_em485 *em485 = p->em485; + stop_delay += (u64)p->port.rs485.delay_rts_after_send * NSEC_PER_MSEC; + /* * rs485_stop_tx() is going to set RTS according to config * AND flush RX FIFO if required. */ - if (p->port.rs485.delay_rts_after_send > 0) { + if (stop_delay > 0) { em485->active_timer = &em485->stop_tx_timer; - start_hrtimer_ms(&em485->stop_tx_timer, - p->port.rs485.delay_rts_after_send); + hrtimer_start(&em485->stop_tx_timer, ns_to_ktime(stop_delay), HRTIMER_MODE_REL); } else { p->rs485_stop_tx(p); em485->active_timer = NULL; @@ -1535,16 +1536,32 @@ static inline void __stop_tx(struct uart_8250_port *p) if (em485) { unsigned char lsr = serial_in(p, UART_LSR); + u64 stop_delay = 0; + + if (!(lsr & UART_LSR_THRE)) + return; /* * To provide required timeing and allow FIFO transfer, * __stop_tx_rs485() must be called only when both FIFO and - * shift register are empty. It is for device driver to enable - * interrupt on TEMT. + * shift register are empty. The device driver should either + * enable interrupt on TEMT or set UART_CAP_NOTEMT that will + * enlarge stop_tx_timer by the tx time of one frame to cover + * for emptying of the shift register. */ - if ((lsr & BOTH_EMPTY) != BOTH_EMPTY) - return; + if (!(lsr & UART_LSR_TEMT)) { + if (!(p->capabilities & UART_CAP_NOTEMT)) + return; + /* + * RTS might get deasserted too early with the normal + * frame timing formula. It seems to suggest THRE might + * get asserted already during tx of the stop bit + * rather than after it is fully sent. + * Roughly estimate 1 extra bit here with / 7. + */ + stop_delay = p->port.frame_time + DIV_ROUND_UP(p->port.frame_time, 7); + } - __stop_tx_rs485(p); + __stop_tx_rs485(p, stop_delay); } __do_stop_tx(p); } From patchwork Mon Apr 25 14:34:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ilpo_J=C3=A4rvinen?= X-Patchwork-Id: 565982 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E5BBEC433EF for ; Mon, 25 Apr 2022 14:35:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238535AbiDYOib (ORCPT ); Mon, 25 Apr 2022 10:38:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37968 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242532AbiDYOi3 (ORCPT ); Mon, 25 Apr 2022 10:38:29 -0400 Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E7DCF167D2; Mon, 25 Apr 2022 07:35:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1650897325; x=1682433325; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=dWJ3/7cdmA0pgFsitZuEUw3jz9OX5cH4BT7oF2UsM8c=; b=lW3suoFzqymKfFfHM0N/QyxjKep/lxCcKWZA4xmxRFYucCiAQaXEoIyC DqeVvOhC9rerYB8AbQLj8xW8fC7tLUUUGNkApDOTyt8sYD3FHPGTM1Yzc 39s9swz25pJ0IhZdgx/LiEMnYyQF4WK9fxBwz0xNiri6UeWpkkKgXGPz1 vBqvZHHtCJNozEajO32ysdc+3beAClqQLLLlPS/YiJagVnDXy1cy8I+z4 zHkFr64FIJA3KcpSVrgxH29QWDfe5VTvixXeqKXQEU2ik1oGmUL2Nh1D3 7gkmzwB/plvPtf2agWvvATNFOX3l97VpeCpRwhO8f4DxAfFkDZIEz3pkX Q==; X-IronPort-AV: E=McAfee;i="6400,9594,10328"; a="247191890" X-IronPort-AV: E=Sophos;i="5.90,288,1643702400"; d="scan'208";a="247191890" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Apr 2022 07:35:24 -0700 X-IronPort-AV: E=Sophos;i="5.90,288,1643702400"; d="scan'208";a="579315891" Received: from lpuglia-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.251.217.93]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Apr 2022 07:35:19 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Lukas Wunner , Andy Shevchenko , Vicente Bergas , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= Cc: Johan Hovold , heiko@sntech.de, giulio.benetti@micronovasrl.com, Heikki Krogerus , =?utf-8?q?Ilpo_J=C3=A4rv?= =?utf-8?q?inen?= , devicetree@vger.kernel.org, Rob Herring Subject: [PATCH v4 06/13] dt_bindings: rs485: Add receiver enable polarity Date: Mon, 25 Apr 2022 17:34:03 +0300 Message-Id: <20220425143410.12703-7-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220425143410.12703-1-ilpo.jarvinen@linux.intel.com> References: <20220425143410.12703-1-ilpo.jarvinen@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org Add polarity property for receiver enable. Some UARTs have separate enable pins for tx (RTS or DE) and rx (RE). As most RS485 transceivers have !RE pin, the default is active low in contrast to rs485-rts-active-low that defaults to active high. Cc: devicetree@vger.kernel.org Reviewed-by: Rob Herring Signed-off-by: Ilpo Järvinen --- Documentation/devicetree/bindings/serial/rs485.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/serial/rs485.yaml b/Documentation/devicetree/bindings/serial/rs485.yaml index 0c9fa694f85c..f2c9c9fe6aa7 100644 --- a/Documentation/devicetree/bindings/serial/rs485.yaml +++ b/Documentation/devicetree/bindings/serial/rs485.yaml @@ -33,6 +33,11 @@ properties: description: drive RTS low when sending (default is high). $ref: /schemas/types.yaml#/definitions/flag + rs485-rx-active-high: + description: Polarity of receiver enable signal (when separate from RTS). + True indicates active high (default is low). + $ref: /schemas/types.yaml#/definitions/flag + linux,rs485-enabled-at-boot-time: description: enables the rs485 feature at boot time. It can be disabled later with proper ioctl. From patchwork Mon Apr 25 14:34:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ilpo_J=C3=A4rvinen?= X-Patchwork-Id: 565981 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C082FC433F5 for ; Mon, 25 Apr 2022 14:35:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242462AbiDYOiv (ORCPT ); Mon, 25 Apr 2022 10:38:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39370 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242546AbiDYOis (ORCPT ); Mon, 25 Apr 2022 10:38:48 -0400 Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 869D339177 for ; Mon, 25 Apr 2022 07:35:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1650897335; x=1682433335; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=M20JHKJiXZAMJNMAVPefCnaIxwHFCR/rpkPdlb+OK2c=; b=RBlWGGcUT1RUKCgj+OVtWQKy2GTrRBZGHPLNjKBsKKYF7qHhTDAq55gy eFGayMEEdyzNW1bDeinLln/N+r9htAW9urM+NN5Zgqx9QeaRJ/GU4AClI 3jCGTBKUfCfrhrezLmbxi9zGlpINryOWI20parv1g1yN2QZZBdErvWDCa 8YN6NDtln+k25azuO9XJ59HmzVT9LwpCyTl9ZkZbzRv8CU5Aq7wl6V2k4 wGoIY5OD544YSAr6Q9qgLB8Nz8w5BGGEE4XxUL19aHlDFeU9AcnXDqy73 4ouoq8Il72Ae4KcGYrt0BkLcmXPT8/BkatiwaINbLLRW4rLWwXO2iGg/o Q==; X-IronPort-AV: E=McAfee;i="6400,9594,10328"; a="247191930" X-IronPort-AV: E=Sophos;i="5.90,288,1643702400"; d="scan'208";a="247191930" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Apr 2022 07:35:34 -0700 X-IronPort-AV: E=Sophos;i="5.90,288,1643702400"; d="scan'208";a="579315954" Received: from lpuglia-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.251.217.93]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Apr 2022 07:35:29 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Lukas Wunner , Andy Shevchenko , Vicente Bergas , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= Cc: Johan Hovold , heiko@sntech.de, giulio.benetti@micronovasrl.com, Heikki Krogerus , =?utf-8?q?Ilpo_J=C3=A4rv?= =?utf-8?q?inen?= Subject: [PATCH v4 07/13] ACPI / property: Document RS485 _DSD properties Date: Mon, 25 Apr 2022 17:34:04 +0300 Message-Id: <20220425143410.12703-8-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220425143410.12703-1-ilpo.jarvinen@linux.intel.com> References: <20220425143410.12703-1-ilpo.jarvinen@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org Document RS485 related properties returned from ACPI _DSD as device properties. Signed-off-by: Ilpo Järvinen --- .../firmware-guide/acpi/enumeration.rst | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Documentation/firmware-guide/acpi/enumeration.rst b/Documentation/firmware-guide/acpi/enumeration.rst index 74b830b2fd59..b42017bf789e 100644 --- a/Documentation/firmware-guide/acpi/enumeration.rst +++ b/Documentation/firmware-guide/acpi/enumeration.rst @@ -374,6 +374,31 @@ descriptors once the device is released. See Documentation/firmware-guide/acpi/gpio-properties.rst for more information about the _DSD binding related to GPIOs. +RS-485 support +============== + +ACPI _DSD (Device Specific Data) can be used to describe RS-485 capability +of UART. + +For example:: + + Device (DEV) + { + ... + + // ACPI 5.1 _DSD used for RS-485 capabilities + Name (_DSD, Package () + { + ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), + Package () + { + Package () {"rs485-rts-active-low", Zero}, + Package () {"rs485-rx-active-high", Zero}, + Package () {"rs485-rx-during-tx", Zero}, + } + }) + ... + MFD devices =========== From patchwork Mon Apr 25 14:34:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ilpo_J=C3=A4rvinen?= X-Patchwork-Id: 565980 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 147DBC43217 for ; Mon, 25 Apr 2022 14:36:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231502AbiDYOjV (ORCPT ); Mon, 25 Apr 2022 10:39:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41340 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242555AbiDYOjS (ORCPT ); Mon, 25 Apr 2022 10:39:18 -0400 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 264B137AA9; Mon, 25 Apr 2022 07:36:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1650897371; x=1682433371; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=09yRLDdukF2NqScy5FEXRNekxsijnB9E2xteSASuYuI=; b=PkUT8tIgqaLz+O+/umRLKBbu2fFD0tm4L9SdooNgLG3ejoL5bSNWEvWG nAR25rE8NeJbhtp1Bgv88MIj/BNjTp3UkbustQ209nC/uRFR5wIj87xJJ C6YdnbZQ8TtOcjeTIf/9i5pCY0Pi2KBbyOLw1NgtpEUF0jtE+bUfiPqFt IBlRHmZHx802ZSb7FnScCprfXcHyPUtK3SFIPHu6qfIJuES1lF0jLHuH4 KOeNEFm8zYmOfOlhru118JZQoG4QOEfAMs/yW3e6f2MIMkGC6YQrtTgFZ ebtkXogSmRxfzSXrpM5Jqyl5MIhvH28DJsUNQG+u3IC2Fm9sTcXT0wxx9 w==; X-IronPort-AV: E=McAfee;i="6400,9594,10328"; a="351710872" X-IronPort-AV: E=Sophos;i="5.90,288,1643702400"; d="scan'208";a="351710872" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Apr 2022 07:36:10 -0700 X-IronPort-AV: E=Sophos;i="5.90,288,1643702400"; d="scan'208";a="579316136" Received: from lpuglia-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.251.217.93]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Apr 2022 07:35:58 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Lukas Wunner , Andy Shevchenko , Vicente Bergas , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= Cc: Johan Hovold , heiko@sntech.de, giulio.benetti@micronovasrl.com, Heikki Krogerus , =?utf-8?q?Ilpo_J=C3=A4rv?= =?utf-8?q?inen?= , linux-api@vger.kernel.org, Ivan Kokshaysky , Matt Turner , linux-alpha@vger.kernel.org, Thomas Bogendoerfer , linux-mips@vger.kernel.org, "James E.J. Bottomley" , Helge Deller , linux-parisc@vger.kernel.org, Michael Ellerman , Benjamin Herrenschmidt , Paul Mackerras , linuxppc-dev@lists.ozlabs.org, Yoshinori Sato , Rich Felker , linux-sh@vger.kernel.org, "David S. Miller" , sparclinux@vger.kernel.org, Chris Zankel , Max Filippov , linux-xtensa@linux-xtensa.org, Arnd Bergmann , linux-arch@vger.kernel.org, linux-doc@vger.kernel.org Subject: [PATCH v4 09/13] serial: General support for multipoint addresses Date: Mon, 25 Apr 2022 17:34:06 +0300 Message-Id: <20220425143410.12703-10-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220425143410.12703-1-ilpo.jarvinen@linux.intel.com> References: <20220425143410.12703-1-ilpo.jarvinen@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org Add generic support for serial multipoint addressing. Two new ioctls are added. TIOCSADDR is used to indicate the destination/receive address. TIOCGADDR returns the current address in use. The driver should implement set_addr and get_addr to support addressing mode. Adjust ADDRB clearing to happen only if driver does not provide set_addr (=the driver doesn't support address mode). This change is necessary for supporting devices with RS485 multipoint addressing [*]. A following patch in the patch series adds support for Synopsys Designware UART capable for 9th bit addressing mode. In this mode, 9th bit is used to indicate an address (byte) within the communication line. The 9th bit addressing mode is selected using ADDRB introduced by the previous patch. Transmit addresses / receiver filter are specified by setting the flags SER_ADDR_DEST and/or SER_ADDR_RECV. When the user supplies the transmit address, in the 9bit addressing mode it is sent out immediately with the 9th bit set to 1. After that, the subsequent normal data bytes are sent with 9th bit as 0 and they are intended to the device with the given address. It is up to receiver to enforce the filter using SER_ADDR_RECV. When userspace has supplied the receive address, the driver is expected to handle the matching of the address and only data with that address is forwarded to the user. Both SER_ADDR_DEST and SER_ADDR_RECV can be given at the same time in a single call if the addresses are the same. The user can clear the receive filter with SER_ADDR_RECV_CLEAR. [*] Technically, RS485 is just an electronic spec and does not itself specify the 9th bit addressing mode but 9th bit seems at least "semi-standard" way to do addressing with RS485. Cc: linux-api@vger.kernel.org Cc: Ivan Kokshaysky Cc: Matt Turner Cc: linux-alpha@vger.kernel.org Cc: Thomas Bogendoerfer Cc: linux-mips@vger.kernel.org Cc: "James E.J. Bottomley" Cc: Helge Deller Cc: linux-parisc@vger.kernel.org Cc: Michael Ellerman Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org Cc: Yoshinori Sato Cc: Rich Felker Cc: linux-sh@vger.kernel.org Cc: "David S. Miller" Cc: sparclinux@vger.kernel.org Cc: Chris Zankel Cc: Max Filippov Cc: linux-xtensa@linux-xtensa.org Cc: Arnd Bergmann Cc: linux-arch@vger.kernel.org Cc: linux-doc@vger.kernel.org Signed-off-by: Ilpo Järvinen --- .../driver-api/serial/serial-rs485.rst | 23 ++++++- arch/alpha/include/uapi/asm/ioctls.h | 3 + arch/mips/include/uapi/asm/ioctls.h | 3 + arch/parisc/include/uapi/asm/ioctls.h | 3 + arch/powerpc/include/uapi/asm/ioctls.h | 3 + arch/sh/include/uapi/asm/ioctls.h | 3 + arch/sparc/include/uapi/asm/ioctls.h | 3 + arch/xtensa/include/uapi/asm/ioctls.h | 3 + drivers/tty/serial/8250/8250_core.c | 2 + drivers/tty/serial/serial_core.c | 62 ++++++++++++++++++- drivers/tty/tty_io.c | 2 + include/linux/serial_core.h | 6 ++ include/uapi/asm-generic/ioctls.h | 3 + include/uapi/linux/serial.h | 8 +++ 14 files changed, 125 insertions(+), 2 deletions(-) diff --git a/Documentation/driver-api/serial/serial-rs485.rst b/Documentation/driver-api/serial/serial-rs485.rst index 6bc824f948f9..2f45f007fa5b 100644 --- a/Documentation/driver-api/serial/serial-rs485.rst +++ b/Documentation/driver-api/serial/serial-rs485.rst @@ -95,7 +95,28 @@ RS485 Serial Communications /* Error handling. See errno. */ } -5. References +5. Multipoint Addressing +======================== + + The Linux kernel provides serial_addr structure to handle addressing within + multipoint serial communications line such as RS485. 9th bit addressiong mode + is enabled by adding ADDRB flag in termios c_cflag. + + Serial core calls device specific set/get_addr in response to TIOCSADDR and + TIOCGADDR ioctls with a pointer to serial_addr. Destination and receive + address can be specified using serial_addr flags field. Receive address may + also be cleared using flags. Once an address is set, the communication + can occur only with the particular device and other peers are filtered out. + It is left up to the receiver side to enforce the filtering. + + Address flags: + - SER_ADDR_RECV: Receive (filter) address. + - SER_ADDR_RECV_CLEAR: Clear receive filter (only for TIOCSADDR). + - SER_ADDR_DEST: Destination address. + + Note: not all devices supporting RS485 support multipoint addressing. + +6. References ============= [1] include/uapi/linux/serial.h diff --git a/arch/alpha/include/uapi/asm/ioctls.h b/arch/alpha/include/uapi/asm/ioctls.h index 971311605288..500cab3e1d6b 100644 --- a/arch/alpha/include/uapi/asm/ioctls.h +++ b/arch/alpha/include/uapi/asm/ioctls.h @@ -125,4 +125,7 @@ #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +#define TIOCSADDR _IOWR('T', 0x63, struct serial_addr) +#define TIOCGADDR _IOWR('T', 0x64, struct serial_addr) + #endif /* _ASM_ALPHA_IOCTLS_H */ diff --git a/arch/mips/include/uapi/asm/ioctls.h b/arch/mips/include/uapi/asm/ioctls.h index 16aa8a766aec..3859dc46857e 100644 --- a/arch/mips/include/uapi/asm/ioctls.h +++ b/arch/mips/include/uapi/asm/ioctls.h @@ -96,6 +96,9 @@ #define TIOCGISO7816 _IOR('T', 0x42, struct serial_iso7816) #define TIOCSISO7816 _IOWR('T', 0x43, struct serial_iso7816) +#define TIOCSADDR _IOWR('T', 0x63, struct serial_addr) +#define TIOCGADDR _IOWR('T', 0x64, struct serial_addr) + /* I hope the range from 0x5480 on is free ... */ #define TIOCSCTTY 0x5480 /* become controlling tty */ #define TIOCGSOFTCAR 0x5481 diff --git a/arch/parisc/include/uapi/asm/ioctls.h b/arch/parisc/include/uapi/asm/ioctls.h index 82d1148c6379..62337743db64 100644 --- a/arch/parisc/include/uapi/asm/ioctls.h +++ b/arch/parisc/include/uapi/asm/ioctls.h @@ -86,6 +86,9 @@ #define TIOCSTOP 0x5462 #define TIOCSLTC 0x5462 +#define TIOCSADDR _IOWR('T', 0x63, struct serial_addr) +#define TIOCGADDR _IOWR('T', 0x64, struct serial_addr) + /* Used for packet mode */ #define TIOCPKT_DATA 0 #define TIOCPKT_FLUSHREAD 1 diff --git a/arch/powerpc/include/uapi/asm/ioctls.h b/arch/powerpc/include/uapi/asm/ioctls.h index 2c145da3b774..84fd69ac366a 100644 --- a/arch/powerpc/include/uapi/asm/ioctls.h +++ b/arch/powerpc/include/uapi/asm/ioctls.h @@ -120,4 +120,7 @@ #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +#define TIOCSADDR _IOWR('T', 0x63, struct serial_addr) +#define TIOCGADDR _IOWR('T', 0x64, struct serial_addr) + #endif /* _ASM_POWERPC_IOCTLS_H */ diff --git a/arch/sh/include/uapi/asm/ioctls.h b/arch/sh/include/uapi/asm/ioctls.h index 11866d4f60e1..f82966b7dba2 100644 --- a/arch/sh/include/uapi/asm/ioctls.h +++ b/arch/sh/include/uapi/asm/ioctls.h @@ -113,4 +113,7 @@ #define TIOCMIWAIT _IO('T', 92) /* 0x545C */ /* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +#define TIOCSADDR _IOWR('T', 0x63, struct serial_addr) +#define TIOCGADDR _IOWR('T', 0x64, struct serial_addr) + #endif /* __ASM_SH_IOCTLS_H */ diff --git a/arch/sparc/include/uapi/asm/ioctls.h b/arch/sparc/include/uapi/asm/ioctls.h index 7fd2f5873c9e..e44624c67c79 100644 --- a/arch/sparc/include/uapi/asm/ioctls.h +++ b/arch/sparc/include/uapi/asm/ioctls.h @@ -125,6 +125,9 @@ #define TIOCMIWAIT 0x545C /* Wait for change on serial input line(s) */ #define TIOCGICOUNT 0x545D /* Read serial port inline interrupt counts */ +#define TIOCSADDR _IOWR('T', 0x63, struct serial_addr) +#define TIOCGADDR _IOWR('T', 0x64, struct serial_addr) + /* Kernel definitions */ /* Used for packet mode */ diff --git a/arch/xtensa/include/uapi/asm/ioctls.h b/arch/xtensa/include/uapi/asm/ioctls.h index 6d4a87296c95..759ca9377f2a 100644 --- a/arch/xtensa/include/uapi/asm/ioctls.h +++ b/arch/xtensa/include/uapi/asm/ioctls.h @@ -127,4 +127,7 @@ #define TIOCMIWAIT _IO('T', 92) /* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +#define TIOCSADDR _IOWR('T', 0x63, struct serial_addr) +#define TIOCGADDR _IOWR('T', 0x64, struct serial_addr) + #endif /* _XTENSA_IOCTLS_H */ diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 01d30f6ed8fb..f67bc3b76f65 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -1008,6 +1008,8 @@ int serial8250_register_8250_port(const struct uart_8250_port *up) uart->port.rs485 = up->port.rs485; uart->rs485_start_tx = up->rs485_start_tx; uart->rs485_stop_tx = up->rs485_stop_tx; + uart->port.set_addr = up->port.set_addr; + uart->port.get_addr = up->port.get_addr; uart->dma = up->dma; /* Take tx_loadsz from fifosize if it wasn't set separately */ diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index de198c2acefe..2cd129c78ef6 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1350,6 +1350,56 @@ static int uart_set_iso7816_config(struct uart_port *port, return 0; } +static int uart_set_addr(struct uart_port *port, + struct serial_addr __user *serial_addr_user) +{ + struct serial_addr addr; + unsigned long flags; + int ret; + + if (!port->set_addr) + return -ENOTTY; + + if (copy_from_user(&addr, serial_addr_user, sizeof(*serial_addr_user))) + return -EFAULT; + + spin_lock_irqsave(&port->lock, flags); + ret = port->set_addr(port, &addr); + spin_unlock_irqrestore(&port->lock, flags); + if (ret) + return ret; + + if (copy_to_user(serial_addr_user, &addr, sizeof(addr))) + return -EFAULT; + + return 0; +} + +static int uart_get_addr(struct uart_port *port, + struct serial_addr __user *serial_addr_user) +{ + struct serial_addr addr; + unsigned long flags; + int ret; + + if (!port->get_addr) + return -ENOTTY; + + if (copy_from_user(&addr, serial_addr_user, sizeof(*serial_addr_user))) + return -EFAULT; + + spin_lock_irqsave(&port->lock, flags); + ret = port->get_addr(port, &addr); + spin_unlock_irqrestore(&port->lock, flags); + if (ret) + return ret; + + if (copy_to_user(serial_addr_user, &addr, sizeof(addr))) + return -EFAULT; + + return 0; +} + /* * Called via sys_ioctl. We can use spin_lock_irq() here. */ @@ -1427,6 +1477,15 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) case TIOCGISO7816: ret = uart_get_iso7816_config(state->uart_port, uarg); break; + + case TIOCSADDR: + ret = uart_set_addr(uport, uarg); + break; + + case TIOCGADDR: + ret = uart_get_addr(uport, uarg); + break; + default: if (uport->ops->ioctl) ret = uport->ops->ioctl(uport, cmd, arg); @@ -1493,7 +1552,8 @@ static void uart_set_termios(struct tty_struct *tty, goto out; } - tty->termios.c_cflag &= ~ADDRB; + if (!uport->set_addr) + tty->termios.c_cflag &= ~ADDRB; uart_change_speed(tty, state, old_termios); /* reload cflag from termios; port driver may have overridden flags */ diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 7e8b3bd59c7b..93d8609e88aa 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2885,6 +2885,8 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, case TIOCSERGETLSR: case TIOCGRS485: case TIOCSRS485: + case TIOCSADDR: + case TIOCGADDR: #ifdef TIOCGETP case TIOCGETP: case TIOCSETP: diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 504d365e2803..a2efd3fe2635 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -135,6 +135,12 @@ struct uart_port { struct serial_rs485 *rs485); int (*iso7816_config)(struct uart_port *, struct serial_iso7816 *iso7816); + + int (*set_addr)(struct uart_port *p, + struct serial_addr *addr); + int (*get_addr)(struct uart_port *p, + struct serial_addr *addr); + unsigned int irq; /* irq number */ unsigned long irqflags; /* irq flags */ unsigned int uartclk; /* base uart clock */ diff --git a/include/uapi/asm-generic/ioctls.h b/include/uapi/asm-generic/ioctls.h index cdc9f4ca8c27..689743366091 100644 --- a/include/uapi/asm-generic/ioctls.h +++ b/include/uapi/asm-generic/ioctls.h @@ -106,6 +106,9 @@ # define FIOQSIZE 0x5460 #endif +#define TIOCSADDR _IOWR('T', 0x63, struct serial_addr) +#define TIOCGADDR _IOWR('T', 0x64, struct serial_addr) + /* Used for packet mode */ #define TIOCPKT_DATA 0 #define TIOCPKT_FLUSHREAD 1 diff --git a/include/uapi/linux/serial.h b/include/uapi/linux/serial.h index fa6b16e5fdd8..8cb785ea7087 100644 --- a/include/uapi/linux/serial.h +++ b/include/uapi/linux/serial.h @@ -149,4 +149,12 @@ struct serial_iso7816 { __u32 reserved[5]; }; +struct serial_addr { + __u32 flags; +#define SER_ADDR_RECV (1 << 0) +#define SER_ADDR_RECV_CLEAR (1 << 1) +#define SER_ADDR_DEST (1 << 2) + __u32 addr; +}; + #endif /* _UAPI_LINUX_SERIAL_H */ From patchwork Mon Apr 25 14:34:08 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ilpo_J=C3=A4rvinen?= X-Patchwork-Id: 565979 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 24818C433EF for ; Mon, 25 Apr 2022 14:36:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236905AbiDYOjr (ORCPT ); Mon, 25 Apr 2022 10:39:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43420 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229542AbiDYOjq (ORCPT ); Mon, 25 Apr 2022 10:39:46 -0400 Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1FAABBF6B for ; Mon, 25 Apr 2022 07:36:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1650897403; x=1682433403; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=RIP+HzW6zgvdmDzKjfv3XpeZ9y85V/peQTNSRMVO3Kg=; b=L7sRdlRnxVHrTCvsZNKzuI/c3dxA5OCUpvckeqmcuyzVfMt+3hIzzcOF puwAZgobCYvvhjoJopbi85p5VZ2ahSz4YP7cXB4YEIZOEzAKbtnBwntNH WfJsHQ9rMM5ho+F+MS98z+PDQVg66j7p5VQb1gSIVMZDDsIGR5KCnRQDL ugmFQ5lHwoCTYIlqdZBYiW3O1LHttj3Bb1BoO9TLdxB+zzOCYpI4F4NVL jswC3ggqO8Er+MEsdqyWBs6iQHNX9bRl/uU4qO8ff5OYDvEPazrg66xw2 Y6GtvV/vWHMl48ilWFi9Ku82JUWT4UR+12bMYGqhlbeAWFvowlMVodyQz w==; X-IronPort-AV: E=McAfee;i="6400,9594,10328"; a="264783234" X-IronPort-AV: E=Sophos;i="5.90,288,1643702400"; d="scan'208";a="264783234" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Apr 2022 07:36:42 -0700 X-IronPort-AV: E=Sophos;i="5.90,288,1643702400"; d="scan'208";a="579316331" Received: from lpuglia-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.251.217.93]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Apr 2022 07:36:32 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Lukas Wunner , Andy Shevchenko , Vicente Bergas , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= Cc: Johan Hovold , heiko@sntech.de, giulio.benetti@micronovasrl.com, Heikki Krogerus , =?utf-8?q?Ilpo_J=C3=A4rv?= =?utf-8?q?inen?= Subject: [PATCH v4 11/13] serial: 8250: create lsr_save_mask Date: Mon, 25 Apr 2022 17:34:08 +0300 Message-Id: <20220425143410.12703-12-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220425143410.12703-1-ilpo.jarvinen@linux.intel.com> References: <20220425143410.12703-1-ilpo.jarvinen@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org Allow drivers to alter LSR save mask. Signed-off-by: Ilpo Järvinen --- drivers/tty/serial/8250/8250_core.c | 4 +++- drivers/tty/serial/8250/8250_port.c | 6 +++--- include/linux/serial_8250.h | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index f67bc3b76f65..7cb1267559d4 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -278,7 +278,7 @@ static void serial8250_backup_timeout(struct timer_list *t) * ia64 and parisc boxes. */ lsr = serial_in(up, UART_LSR); - up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; + up->lsr_saved_flags |= lsr & up->lsr_save_mask; if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) && (!uart_circ_empty(&up->port.state->xmit) || up->port.x_char) && (lsr & UART_LSR_THRE)) { @@ -1097,6 +1097,8 @@ int serial8250_register_8250_port(const struct uart_8250_port *up) ret = 0; } + uart->lsr_save_mask = up->lsr_save_mask ?: LSR_SAVE_FLAGS; + /* Initialise interrupt backoff work if required */ if (up->overrun_backoff_time_ms > 0) { uart->overrun_backoff_time_ms = diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index c2492b91b0cd..3be95e861f21 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1595,7 +1595,7 @@ static inline void __start_tx(struct uart_port *port) unsigned int lsr; lsr = serial_in(up, UART_LSR); - up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; + up->lsr_saved_flags |= lsr & up->lsr_save_mask; if (lsr & UART_LSR_THRE) serial8250_tx_chars(up); } @@ -2029,7 +2029,7 @@ static unsigned int serial8250_tx_empty(struct uart_port *port) spin_lock_irqsave(&port->lock, flags); lsr = serial_port_in(port, UART_LSR); - up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; + up->lsr_saved_flags |= lsr & up->lsr_save_mask; spin_unlock_irqrestore(&port->lock, flags); serial8250_rpm_put(up); @@ -2110,7 +2110,7 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits) for (;;) { status = serial_in(up, UART_LSR); - up->lsr_saved_flags |= status & LSR_SAVE_FLAGS; + up->lsr_saved_flags |= status & up->lsr_save_mask; if ((status & bits) == bits) break; diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index 921df4c60062..aff76ea22287 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -120,6 +120,7 @@ struct uart_8250_port { */ #define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS u16 lsr_saved_flags; + u16 lsr_save_mask; #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA unsigned char msr_saved_flags; From patchwork Mon Apr 25 14:34:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ilpo_J=C3=A4rvinen?= X-Patchwork-Id: 565978 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 11DE9C433F5 for ; Mon, 25 Apr 2022 14:37:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229542AbiDYOkD (ORCPT ); Mon, 25 Apr 2022 10:40:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44614 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242419AbiDYOkC (ORCPT ); Mon, 25 Apr 2022 10:40:02 -0400 Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 94C5713EA1 for ; Mon, 25 Apr 2022 07:36:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1650897418; x=1682433418; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=His87S4+EY/T/CrgooNywg5mDe55vTpZc1+L5cNp40k=; b=XV+oUo72jy1h+BrYd63oQdA/HDnpKjU51mPCIy+clqU5xELBB0niuVF7 BZBQ2g4Wdr1iKkqZY6a9ogSnOLxoT4NaF8l9XpnOXghVyttHzZfmVF6on 7eiNqqI6iwbG1prIgmAIFKQ9rtQHIFSf0IMcUdpRfqMk060Pe3TpnKBR+ 1eFrt9wxbBwG7rbGXxxgC9IOiP/hZX1YSE5Pjo26bV9xEqcGb/T5bMYBX qKzIFil5kkfX7HOWGk4x1OTIRoqaeP8x4zEpR9MM1CXDe0mqlEAjPpIJ8 600+12zoFiEqfari2manG2zB5FfA9LFQsuVl8PVtnj2QHjxPyTqa9Qh/M A==; X-IronPort-AV: E=McAfee;i="6400,9594,10328"; a="264113468" X-IronPort-AV: E=Sophos;i="5.90,288,1643702400"; d="scan'208";a="264113468" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Apr 2022 07:36:58 -0700 X-IronPort-AV: E=Sophos;i="5.90,288,1643702400"; d="scan'208";a="579316516" Received: from lpuglia-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.251.217.93]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Apr 2022 07:36:51 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Lukas Wunner , Andy Shevchenko , Vicente Bergas , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= Cc: Johan Hovold , heiko@sntech.de, giulio.benetti@micronovasrl.com, Heikki Krogerus , =?utf-8?q?Ilpo_J=C3=A4rv?= =?utf-8?q?inen?= , Raymond Tan , Lakshmi Sowjanya Subject: [PATCH v4 13/13] serial: 8250_dwlib: Support for 9th bit multipoint addressing Date: Mon, 25 Apr 2022 17:34:10 +0300 Message-Id: <20220425143410.12703-14-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220425143410.12703-1-ilpo.jarvinen@linux.intel.com> References: <20220425143410.12703-1-ilpo.jarvinen@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org This change adds 9th bit multipoint addressing mode for DW UART using the new ioctls introduced in the previous change. 9th bit addressing can be used only when HW RS485 is available. Updating RAR (receive address register) is bit tricky because busy indication is not be available when DW UART is strictly 16550 compatible, which is the case with the hardware I was testing with. RAR should not be updated while receive is in progress which is now achieved by deasserting RE and waiting for one frame (in case rx would be in progress, the driver seems to have no way of knowing it w/o busy indication). Co-developed-by: Heikki Krogerus Signed-off-by: Heikki Krogerus Co-developed-by: Andy Shevchenko Signed-off-by: Andy Shevchenko Co-developed-by: Raymond Tan Signed-off-by: Raymond Tan Co-developed-by: Lakshmi Sowjanya Signed-off-by: Lakshmi Sowjanya Signed-off-by: Ilpo Järvinen --- drivers/tty/serial/8250/8250_dwlib.c | 142 +++++++++++++++++++++++++++ drivers/tty/serial/8250/8250_dwlib.h | 2 + 2 files changed, 144 insertions(+) diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c index 04852af4c024..413cdb426536 100644 --- a/drivers/tty/serial/8250/8250_dwlib.c +++ b/drivers/tty/serial/8250/8250_dwlib.c @@ -3,9 +3,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -17,9 +19,18 @@ #define DW_UART_DE_EN 0xb0 /* Driver Output Enable Register */ #define DW_UART_RE_EN 0xb4 /* Receiver Output Enable Register */ #define DW_UART_DLF 0xc0 /* Divisor Latch Fraction Register */ +#define DW_UART_RAR 0xc4 /* Receive Address Register */ +#define DW_UART_TAR 0xc8 /* Transmit Address Register */ +#define DW_UART_LCR_EXT 0xcc /* Line Extended Control Register */ #define DW_UART_CPR 0xf4 /* Component Parameter Register */ #define DW_UART_UCV 0xf8 /* UART Component Version */ +/* Receive / Transmit Address Register bits */ +#define DW_UART_ADDR_MASK GENMASK(7, 0) + +/* Line Status Register bits */ +#define DW_UART_LSR_ADDR_RCVD BIT(8) + /* Transceiver Control Register bits */ #define DW_UART_TCR_RS485_EN BIT(0) #define DW_UART_TCR_RE_POL BIT(1) @@ -29,6 +40,12 @@ #define DW_UART_TCR_XFER_MODE_SW_DE_OR_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 1) #define DW_UART_TCR_XFER_MODE_DE_OR_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 2) +/* Line Extended Control Register bits */ +#define DW_UART_LCR_EXT_DLS_E BIT(0) +#define DW_UART_LCR_EXT_ADDR_MATCH BIT(1) +#define DW_UART_LCR_EXT_SEND_ADDR BIT(2) +#define DW_UART_LCR_EXT_TRANSMIT_MODE BIT(3) + /* Component Parameter Register bits */ #define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0) #define DW_UART_CPR_AFCE_MODE (1 << 4) @@ -91,18 +108,132 @@ static void dw8250_set_divisor(struct uart_port *p, unsigned int baud, serial8250_do_set_divisor(p, baud, quot, quot_frac); } +/* + * Wait until re is de-asserted for sure. An ongoing receive will keep + * re asserted until end of frame. Without BUSY indication available, + * only available course of action is to wait for the time it takes to + * receive one frame (there might nothing to receive but w/o BUSY the + * driver cannot know). + */ +static void dw8250_wait_re_deassert(struct uart_port *p) +{ + udelay(p->frame_time); +} + +static void dw8250_update_rar(struct uart_port *p, u32 addr) +{ + u32 re_en = dw8250_readl_ext(p, DW_UART_RE_EN); + + /* + * RAR shouldn't be changed while receiving. Thus, de-assert RE_EN + * if asserted and wait. + */ + if (re_en) + dw8250_writel_ext(p, DW_UART_RE_EN, 0); + dw8250_wait_re_deassert(p); + dw8250_writel_ext(p, DW_UART_RAR, addr); + if (re_en) + dw8250_writel_ext(p, DW_UART_RE_EN, re_en); +} + +static void dw8250_addrmode_setup(struct uart_port *p, bool enable_addrmode) +{ + struct dw8250_port_data *d = p->private_data; + + if (enable_addrmode) { + /* Clear RAR & TAR of any previous values */ + dw8250_writel_ext(p, DW_UART_RAR, 0); + dw8250_writel_ext(p, DW_UART_TAR, 0); + dw8250_writel_ext(p, DW_UART_LCR_EXT, DW_UART_LCR_EXT_DLS_E); + } else { + dw8250_writel_ext(p, DW_UART_LCR_EXT, 0); + } + + d->addrmode = enable_addrmode; +} + void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old) { + struct dw8250_port_data *d = p->private_data; + p->status &= ~UPSTAT_AUTOCTS; if (termios->c_cflag & CRTSCTS) p->status |= UPSTAT_AUTOCTS; + if (!(p->rs485.flags & SER_RS485_ENABLED) || !d->hw_rs485_support) + termios->c_cflag &= ~ADDRB; + + if (!old || (termios->c_cflag ^ old->c_cflag) & ADDRB) + dw8250_addrmode_setup(p, termios->c_cflag & ADDRB); + serial8250_do_set_termios(p, termios, old); + + if (d->addrmode) { + p->ignore_status_mask |= DW_UART_LSR_ADDR_RCVD; + p->read_status_mask |= DW_UART_LSR_ADDR_RCVD; + } } EXPORT_SYMBOL_GPL(dw8250_do_set_termios); +static int dw8250_rs485_set_addr(struct uart_port *p, struct serial_addr *addr) +{ + struct dw8250_port_data *d = p->private_data; + u32 lcr; + + if (!(p->rs485.flags & SER_RS485_ENABLED) || !d->addrmode) + return -EINVAL; + + addr->flags &= SER_ADDR_RECV | SER_ADDR_RECV_CLEAR | SER_ADDR_DEST; + if (!addr->flags) + return -EINVAL; + + lcr = dw8250_readl_ext(p, DW_UART_LCR_EXT); + if (addr->flags & SER_ADDR_RECV) { + dw8250_update_rar(p, addr->addr & DW_UART_ADDR_MASK); + lcr |= DW_UART_LCR_EXT_ADDR_MATCH; + addr->flags &= ~SER_ADDR_RECV_CLEAR; + } else if (addr->flags & SER_ADDR_RECV_CLEAR) { + lcr &= DW_UART_LCR_EXT_ADDR_MATCH; + } + if (addr->flags & SER_ADDR_DEST) { + dw8250_writel_ext(p, DW_UART_TAR, addr->addr & DW_UART_ADDR_MASK); + lcr |= DW_UART_LCR_EXT_SEND_ADDR; + } + dw8250_writel_ext(p, DW_UART_LCR_EXT, lcr); + + return 0; +} + +static int dw8250_rs485_get_addr(struct uart_port *p, struct serial_addr *addr) +{ + struct dw8250_port_data *d = p->private_data; + + if (!(p->rs485.flags & SER_RS485_ENABLED) || !d->addrmode) + return -EINVAL; + + if (addr->flags == SER_ADDR_DEST) { + addr->addr = dw8250_readl_ext(p, DW_UART_TAR) & DW_UART_ADDR_MASK; + return 0; + } + if (addr->flags == SER_ADDR_RECV) { + u32 lcr = dw8250_readl_ext(p, DW_UART_LCR_EXT); + + if (!(lcr & DW_UART_LCR_EXT_ADDR_MATCH)) { + addr->flags = SER_ADDR_RECV_CLEAR; + addr->addr = 0; + } else { + addr->addr = dw8250_readl_ext(p, DW_UART_RAR) & DW_UART_ADDR_MASK; + } + + return 0; + } + + return -EINVAL; +} + static int dw8250_rs485_config(struct uart_port *p, struct serial_rs485 *rs485) { + struct dw8250_port_data *d = p->private_data; u32 tcr; tcr = dw8250_readl_ext(p, DW_UART_TCR); @@ -127,6 +258,14 @@ static int dw8250_rs485_config(struct uart_port *p, struct serial_rs485 *rs485) dw8250_writel_ext(p, DW_UART_DE_EN, 1); dw8250_writel_ext(p, DW_UART_RE_EN, 1); } else { + /* + * Don't allow disabling RS485 when address mode is enabled. + * Clearing address mode would require clearing ADDRB in + * termios. + */ + if (d->addrmode) + return -EINVAL; + rs485->flags = 0; tcr &= ~DW_UART_TCR_RS485_EN; @@ -174,6 +313,9 @@ void dw8250_setup_port(struct uart_port *p) d->hw_rs485_support = dw8250_detect_rs485_hw(p); if (d->hw_rs485_support) { p->rs485_config = dw8250_rs485_config; + p->set_addr = dw8250_rs485_set_addr; + p->get_addr = dw8250_rs485_get_addr; + up->lsr_save_mask = LSR_SAVE_FLAGS | DW_UART_LSR_ADDR_RCVD; } else { p->rs485_config = serial8250_em485_config; up->rs485_start_tx = serial8250_em485_start_tx; diff --git a/drivers/tty/serial/8250/8250_dwlib.h b/drivers/tty/serial/8250/8250_dwlib.h index a8fa020ca544..c616d5b29f66 100644 --- a/drivers/tty/serial/8250/8250_dwlib.h +++ b/drivers/tty/serial/8250/8250_dwlib.h @@ -17,6 +17,8 @@ struct dw8250_port_data { /* RS485 variables */ bool hw_rs485_support; + /* 9-bit framing (9th bit is address indicator) */ + bool addrmode; }; void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old);