From patchwork Mon Apr 4 08:29:01 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: 556467 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 A210DC433EF for ; Mon, 4 Apr 2022 08:29:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235548AbiDDIbg (ORCPT ); Mon, 4 Apr 2022 04:31:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43736 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235038AbiDDIbf (ORCPT ); Mon, 4 Apr 2022 04:31:35 -0400 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 76964220C5 for ; Mon, 4 Apr 2022 01:29:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1649060979; x=1680596979; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=aEQDCTG965JKg0vtyx56wV9VxW6CjI19u0rSutPHh/8=; b=E4k0Fw2XwHQ7gSEVsya2ga+jiyhbTWcN0zspOIlQ/1yIbSr0au/F5eXF qPe3smBRF/CgJe7Xf4NfE0ooiNdNmbJhnLFNbz2qu2zbgO9WS4lDPURLe zxTWPhY+J+wi1oBSkubZAZt/M3VQQ7VrRwaF+3QzV+BJ1NauQMXJZc+yF x3W0bTa70oC/ze/4IX65K2YgrfkFjyVKcKLNiLNDXGzaF7oCzVy4OVyCZ 3eF6xtNQAF4vK6HQx+5kyHPM3X4bCmw7Vox/J1JA5mW+uVpqPNCMvnxzd dOu/knAP3IJMQQd78514lIfSBrM/HXTwmvRtniTv0x0kfpBZpr7vGXc6/ w==; X-IronPort-AV: E=McAfee;i="6200,9189,10306"; a="241052768" X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="241052768" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:29:39 -0700 X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="569293325" Received: from rhamza-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.251.211.126]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:29:35 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Lukas Wunner , Andy Shevchenko Cc: Johan Hovold , heiko@sntech.de, giulio.benetti@micronovasrl.com, Heikki Krogerus , =?utf-8?q?Uwe_Kleine-K?= =?utf-8?q?=C3=B6nig?= , =?utf-8?q?Ilpo_J?= =?utf-8?q?=C3=A4rvinen?= Subject: [PATCH v2 01/12] serial: Store character timing information to uart_port Date: Mon, 4 Apr 2022 11:29:01 +0300 Message-Id: <20220404082912.6885-2-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> References: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org Struct uart_port currently stores FIFO timeout. Having character timing information readily available is useful. Even serial core itself determines char_time from port->timeout using inverse calculation. Store frame_time directly into uart_port. Character time is stored in nanoseconds to have reasonable precision with high rates. To avoid overflow, 64-bit math is necessary. It might be possible to determine timeout from frame_time by multiplying it with fifosize as needed but only part of the users seem to be protected by a lock. Thus, this patch does not pursue storing only frame_time in uart_port. Signed-off-by: Ilpo Järvinen --- drivers/tty/serial/serial_core.c | 14 ++++++++------ include/linux/serial_core.h | 1 + 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 846192a7b4bf..c6ac91033e38 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -333,15 +334,18 @@ void uart_update_timeout(struct uart_port *port, unsigned int cflag, unsigned int baud) { - unsigned int size; + unsigned int size = tty_get_frame_size(cflag); + u64 frame_time; - size = tty_get_frame_size(cflag) * port->fifosize; + frame_time = (u64)size * NSEC_PER_SEC; + size *= port->fifosize; /* * Figure the timeout to send the above number of bits. * Add .02 seconds of slop */ port->timeout = (HZ * size) / baud + HZ/50; + port->frame_time = DIV64_U64_ROUND_UP(frame_time, baud); } EXPORT_SYMBOL(uart_update_timeout); @@ -1596,10 +1600,8 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) * Note: we have to use pretty tight timings here to satisfy * the NIST-PCTS. */ - char_time = (port->timeout - HZ/50) / port->fifosize; - char_time = char_time / 5; - if (char_time == 0) - char_time = 1; + char_time = max(nsecs_to_jiffies(port->frame_time / 5), 1UL); + if (timeout && timeout < char_time) char_time = timeout; diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 31f7fe527395..504d365e2803 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -232,6 +232,7 @@ struct uart_port { int hw_stopped; /* sw-assisted CTS flow state */ unsigned int mctrl; /* current modem ctrl settings */ unsigned int timeout; /* character-based timeout */ + unsigned int frame_time; /* frame timing in ns */ unsigned int type; /* port type */ const struct uart_ops *ops; unsigned int custom_divisor; From patchwork Mon Apr 4 08:29:02 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: 556138 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 B0CEBC433F5 for ; Mon, 4 Apr 2022 08:29:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236134AbiDDIbo (ORCPT ); Mon, 4 Apr 2022 04:31:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44304 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234882AbiDDIbn (ORCPT ); Mon, 4 Apr 2022 04:31:43 -0400 Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3C93E17074 for ; Mon, 4 Apr 2022 01:29:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1649060988; x=1680596988; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=iiViPJh7xyl0ZYx9FXtQ45zmuxrCc/q2T88su1wZEE0=; b=BHygCWsbVhsPmhfGHwvh8K6ByauqHwKFKLINorNm4gpNDHEu1kX/P+6V xC1RQFFbmXCkz6icziIvTwff67nsL7JJmrYe6pyfNgPykoGD7eYRcfGxj xXFJSQjzuPKtBeYzUDlHBDhKaT9SERWayLgf7CJ4pUsbVpSxnkwjaqvN/ qbrgxpOpQ8ZELqnAF3fuX3vOhPktv47wU0C2VnEbLfZ2dM1804Cn5bNPR UmVboV5/xfX3i8Qd7zyv9aqX4cuLAeAC+7SdN+sH2xbiO4gL26Zy+qzXS 5IQ7K71m6lgfOnRq+K8CtDq4XFlnfUKW6lwUCnAjLDpuRlWAeTzhlxNCv A==; X-IronPort-AV: E=McAfee;i="6200,9189,10306"; a="240402970" X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="240402970" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:29:47 -0700 X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="569293343" Received: from rhamza-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.251.211.126]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:29:44 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Lukas Wunner , Andy Shevchenko Cc: Johan Hovold , heiko@sntech.de, giulio.benetti@micronovasrl.com, Heikki Krogerus , =?utf-8?q?Uwe_Kleine-K?= =?utf-8?q?=C3=B6nig?= , =?utf-8?q?Ilpo_J?= =?utf-8?q?=C3=A4rvinen?= , Eric Tremblay Subject: [PATCH v2 02/12] serial: 8250: Handle UART without interrupt on TEMT Date: Mon, 4 Apr 2022 11:29:02 +0300 Message-Id: <20220404082912.6885-3-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> References: <20220404082912.6885-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. Suggested-by: Uwe Kleine-König Cc: Eric Tremblay Signed-off-by: Ilpo Järvinen --- drivers/tty/serial/8250/8250.h | 1 + drivers/tty/serial/8250/8250_port.c | 28 +++++++++++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index db784ace25d8..100426cd2335 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -83,6 +83,7 @@ struct serial8250_config { #define UART_CAP_MINI BIT(17) /* Mini UART on BCM283X family lacks: * STOP PARITY EPAR SPAR WLEN5 WLEN6 */ +#define UART_CAP_NOTEMT BIT(18) /* UART cannot interrupt on TEMT */ #define UART_BUG_QUOT BIT(0) /* UART has buggy quot LSB */ #define UART_BUG_TXEN BIT(1) /* UART has buggy TX IIR status */ diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index d30a6c1c4c20..276c5281aaa0 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_USEC; + /* * 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,25 @@ 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; + stop_delay = p->port.frame_time; + } - __stop_tx_rs485(p); + __stop_tx_rs485(p, stop_delay); } __do_stop_tx(p); } From patchwork Mon Apr 4 08:29: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: 556466 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 705AFC433F5 for ; Mon, 4 Apr 2022 08:29:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236151AbiDDIbv (ORCPT ); Mon, 4 Apr 2022 04:31:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44824 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234882AbiDDIbu (ORCPT ); Mon, 4 Apr 2022 04:31:50 -0400 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2E06717074 for ; Mon, 4 Apr 2022 01:29:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1649060995; x=1680596995; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=0kH8vIyFENGtdjuxSU+mU/Y72tpjY+qAd1ZW1CvDfVE=; b=oBUMCS4JF0M3diYpwOAlvJgKJJy88piHNT+fhKtJvLcK1w4sUzoTweo9 JrfekWdad3NTzrhmlFaurJPFe1J/haxUADL0rdfDKd28VN4ys+acyxdx5 M0oDUBdxsNmHf0vvqqlCoH94k5dohBRdV+JO0Y4NsR5yl4T3icCF8Rwpy cQVDfMR/xvypa2jLrG3n5vtGhIXpOEVBye4SQ0us4cS/Cd35Zet0KeY/x ani6R29YJAJwckDr5VjDxERpqQ1qVhS3hTFAQ33C51WutYAYV1N3D9FWg cQzLfzVpHciTcFPp63rsJ/Rq2Jv8wfM+BaVSYyl/vGxpx78SFZiA3bU/w w==; X-IronPort-AV: E=McAfee;i="6200,9189,10306"; a="346904498" X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="346904498" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:29:54 -0700 X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="569293379" Received: from rhamza-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.251.211.126]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:29:50 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Lukas Wunner , Andy Shevchenko Cc: Johan Hovold , heiko@sntech.de, giulio.benetti@micronovasrl.com, Heikki Krogerus , =?utf-8?q?Uwe_Kleine-K?= =?utf-8?q?=C3=B6nig?= , =?utf-8?q?Ilpo_J?= =?utf-8?q?=C3=A4rvinen?= , Raymond Tan Subject: [PATCH v2 03/12] serial: 8250_dwlib: RS485 HW half & full duplex support Date: Mon, 4 Apr 2022 11:29:03 +0300 Message-Id: <20220404082912.6885-4-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> References: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org The Synopsys DesignWare UART can be configured to have HW support for the RS485 protocol from IP version 4.0 onward. Add support for hardware-controlled half duplex and full duplex modes. HW will take care of managing DE and RE, the driver just gives it permission to use either by setting both to 1. To ask for full duplex mode, userspace sets SER_RS485_RX_DURING_TX flag and HW will take care of the rest. Set delay_rts_before_send and delay_rts_after_send to zero for now. The granularity of that ABI is too coarse to be useful. Co-developed-by: Heikki Krogerus Signed-off-by: Heikki Krogerus Co-developed-by: Raymond Tan Signed-off-by: Raymond Tan Co-developed-by: Andy Shevchenko Signed-off-by: Andy Shevchenko Signed-off-by: Ilpo Järvinen --- drivers/tty/serial/8250/8250_dwlib.c | 85 +++++++++++++++++++++++++++- drivers/tty/serial/8250/8250_dwlib.h | 3 + 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c index 622d3b0d89e7..08432e2fe511 100644 --- a/drivers/tty/serial/8250/8250_dwlib.c +++ b/drivers/tty/serial/8250/8250_dwlib.c @@ -2,19 +2,33 @@ /* Synopsys DesignWare 8250 library. */ #include +#include #include #include #include +#include #include #include #include "8250_dwlib.h" /* Offsets for the DesignWare specific registers */ +#define DW_UART_TCR 0xac /* Transceiver Control Register (RS485) */ +#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_CPR 0xf4 /* Component Parameter Register */ #define DW_UART_UCV 0xf8 /* UART Component Version */ +/* Transceiver Control Register bits */ +#define DW_UART_TCR_RS485_EN BIT(0) +#define DW_UART_TCR_RE_POL BIT(1) +#define DW_UART_TCR_DE_POL BIT(2) +#define DW_UART_TCR_XFER_MODE GENMASK(4, 3) +#define DW_UART_TCR_XFER_MODE_DE_DURING_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 0) +#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) + /* Component Parameter Register bits */ #define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0) #define DW_UART_CPR_AFCE_MODE (1 << 4) @@ -87,11 +101,80 @@ void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct } EXPORT_SYMBOL_GPL(dw8250_do_set_termios); +static int dw8250_rs485_config(struct uart_port *p, struct serial_rs485 *rs485) +{ + u32 tcr; + + tcr = dw8250_readl_ext(p, DW_UART_TCR); + tcr &= ~DW_UART_TCR_XFER_MODE; + + if (rs485->flags & SER_RS485_ENABLED) { + /* Clear unsupported flags. */ + rs485->flags &= SER_RS485_ENABLED | SER_RS485_RX_DURING_TX | + SER_RS485_RTS_ON_SEND | SER_RS485_RTS_AFTER_SEND; + tcr |= DW_UART_TCR_RS485_EN; + + if (rs485->flags & SER_RS485_RX_DURING_TX) { + tcr |= DW_UART_TCR_XFER_MODE_DE_DURING_RE; + } else { + /* HW does not support same DE level for tx and rx */ + if (!(rs485->flags & SER_RS485_RTS_ON_SEND) == + !(rs485->flags & SER_RS485_RTS_AFTER_SEND)) + return -EINVAL; + + tcr |= DW_UART_TCR_XFER_MODE_DE_OR_RE; + } + dw8250_writel_ext(p, DW_UART_DE_EN, 1); + dw8250_writel_ext(p, DW_UART_RE_EN, 1); + } else { + rs485->flags = 0; + + tcr &= ~DW_UART_TCR_RS485_EN; + } + + /* Reset to default polarity */ + tcr |= DW_UART_TCR_DE_POL; + tcr &= ~DW_UART_TCR_RE_POL; + + if (!(rs485->flags & SER_RS485_RTS_ON_SEND)) + tcr &= ~DW_UART_TCR_DE_POL; + if (device_property_read_bool(p->dev, "rs485-rx-active-high")) + tcr |= DW_UART_TCR_RE_POL; + + dw8250_writel_ext(p, DW_UART_TCR, tcr); + + rs485->delay_rts_before_send = 0; + rs485->delay_rts_after_send = 0; + + p->rs485 = *rs485; + + return 0; +} + +/* + * Tests if RE_EN register can have non-zero value to see if RS-485 HW support + * is present. + */ +static bool dw8250_detect_rs485_hw(struct uart_port *p) +{ + u32 reg; + + dw8250_writel_ext(p, DW_UART_RE_EN, 1); + reg = dw8250_readl_ext(p, DW_UART_RE_EN); + dw8250_writel_ext(p, DW_UART_RE_EN, 0); + return reg; +} + void dw8250_setup_port(struct uart_port *p) { + struct dw8250_port_data *d = p->private_data; struct uart_8250_port *up = up_to_u8250p(p); u32 reg; + d->hw_rs485_support = dw8250_detect_rs485_hw(p); + if (d->hw_rs485_support) + p->rs485_config = dw8250_rs485_config; + /* * If the Component Version Register returns zero, we know that * ADDITIONAL_FEATURES are not enabled. No need to go any further. @@ -108,8 +191,6 @@ void dw8250_setup_port(struct uart_port *p) dw8250_writel_ext(p, DW_UART_DLF, 0); if (reg) { - struct dw8250_port_data *d = p->private_data; - d->dlf_size = fls(reg); p->get_divisor = dw8250_get_divisor; p->set_divisor = dw8250_set_divisor; diff --git a/drivers/tty/serial/8250/8250_dwlib.h b/drivers/tty/serial/8250/8250_dwlib.h index 83d528e5cc21..a8fa020ca544 100644 --- a/drivers/tty/serial/8250/8250_dwlib.h +++ b/drivers/tty/serial/8250/8250_dwlib.h @@ -14,6 +14,9 @@ struct dw8250_port_data { /* Hardware configuration */ u8 dlf_size; + + /* RS485 variables */ + bool hw_rs485_support; }; void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old); From patchwork Mon Apr 4 08:29: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: 556137 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 7247CC433F5 for ; Mon, 4 Apr 2022 08:30:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237099AbiDDIb7 (ORCPT ); Mon, 4 Apr 2022 04:31:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45134 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234882AbiDDIbz (ORCPT ); Mon, 4 Apr 2022 04:31:55 -0400 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1F46417074 for ; Mon, 4 Apr 2022 01:29:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1649060999; x=1680596999; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=5o3LEXeILoa4JLM7OW7RxK9qJcKIH2zr+YNp1daYRhM=; b=WPvhYuIjYBKtERCygFmqJf1Sx4VFPQhqkMOk/l815qdASUxjG6yD4mdA +s5JRaSvy1dBGgqvYjnvvbFgGsKz9cmPY+Zv9NTZifCdhESm49ZQvEZt8 JJLtJXU1ukwoAGEDj84/2ePei9/Wgnbdt+LeVPoCVmb6iaFMdfTlKfO1e llsD+Cl2THePbi1Udz3Kjhwbdzpc3gmNhpG9dFhW3/+6WbzQSaM1PmTPU 3g0gY5toAShkxOPen3vfhQLD7C/IqBJCMqtdIHSS7/8tT/CBnWseOG2gT xcd36R97AforSNJDEbm8J8BglYaNTm7PDzt/4MZzoblqzkZh0LB6XS7t2 A==; X-IronPort-AV: E=McAfee;i="6200,9189,10306"; a="346904508" X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="346904508" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:29:58 -0700 X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="569293383" Received: from rhamza-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.251.211.126]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:29:55 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Lukas Wunner , Andy Shevchenko Cc: Johan Hovold , heiko@sntech.de, giulio.benetti@micronovasrl.com, Heikki Krogerus , =?utf-8?q?Uwe_Kleine-K?= =?utf-8?q?=C3=B6nig?= , =?utf-8?q?Ilpo_J?= =?utf-8?q?=C3=A4rvinen?= , Eric Tremblay Subject: [PATCH v2 04/12] serial: 8250_dwlib: Implement SW half duplex support Date: Mon, 4 Apr 2022 11:29:04 +0300 Message-Id: <20220404082912.6885-5-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> References: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org This patch enables support for SW half-duplex mode using em485. Cc: Eric Tremblay Cc: Uwe Kleine-König Signed-off-by: Ilpo Järvinen --- drivers/tty/serial/8250/8250_dwlib.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c index 08432e2fe511..04852af4c024 100644 --- a/drivers/tty/serial/8250/8250_dwlib.c +++ b/drivers/tty/serial/8250/8250_dwlib.c @@ -172,8 +172,14 @@ void dw8250_setup_port(struct uart_port *p) u32 reg; d->hw_rs485_support = dw8250_detect_rs485_hw(p); - if (d->hw_rs485_support) + if (d->hw_rs485_support) { p->rs485_config = dw8250_rs485_config; + } else { + p->rs485_config = serial8250_em485_config; + up->rs485_start_tx = serial8250_em485_start_tx; + up->rs485_stop_tx = serial8250_em485_stop_tx; + } + up->capabilities |= UART_CAP_NOTEMT; /* * If the Component Version Register returns zero, we know that @@ -205,7 +211,7 @@ void dw8250_setup_port(struct uart_port *p) p->type = PORT_16550A; p->flags |= UPF_FIXED_TYPE; p->fifosize = DW_UART_CPR_FIFO_SIZE(reg); - up->capabilities = UART_CAP_FIFO; + up->capabilities = UART_CAP_FIFO | UART_CAP_NOTEMT; } if (reg & DW_UART_CPR_AFCE_MODE) From patchwork Mon Apr 4 08:29:05 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: 556465 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 3A92DC433F5 for ; Mon, 4 Apr 2022 08:30:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237610AbiDDIcC (ORCPT ); Mon, 4 Apr 2022 04:32:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45610 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237445AbiDDIcA (ORCPT ); Mon, 4 Apr 2022 04:32:00 -0400 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 39E8B17074; Mon, 4 Apr 2022 01:30:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1649061005; x=1680597005; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+6nfPvqmO8X54BLq371zwzoCjgOCeVVDag0cH5KXjvY=; b=jIJ0BVnftt9DTPbXTwdqpsso2+JDs/GKSQNqFjFIm5b1h9857x5qrnpP ivKbFz4GFkPlDEBj/8sSLlSR5OrZP+kywy6QDgf0/ljFhIziJxWw7qnE6 OM8WX6qN0kxI8O1O/v2T6R8wLviVkh4DJl3G/KWAkN1yd7Y4TK/6x1sCa /d5Z0HW49ZpxT8zQQ2j5n7UjTH28gce7Qpof9varqOKPN7gX5wXovGs0f Qj7T4lHyqxBjIYe5vHLXj+qeJAamsFTNsSqQxBZZGyMGJ3uC+s0NFeg2B Vgi42BYIM6TWR/8gvKEzGgvsZxEPMmXgWHiXDZm8mtqsE2Q4l7F8ZYtxi g==; X-IronPort-AV: E=McAfee;i="6200,9189,10306"; a="258046448" X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="258046448" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:30:04 -0700 X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="569293413" Received: from rhamza-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.251.211.126]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:30:00 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Lukas Wunner , Andy Shevchenko Cc: Johan Hovold , heiko@sntech.de, giulio.benetti@micronovasrl.com, Heikki Krogerus , =?utf-8?q?Uwe_Kleine-K?= =?utf-8?q?=C3=B6nig?= , =?utf-8?q?Ilpo_J?= =?utf-8?q?=C3=A4rvinen?= , Rob Herring , devicetree@vger.kernel.org Subject: [PATCH v2 05/12] dt_bindings: rs485: Add receiver enable polarity Date: Mon, 4 Apr 2022 11:29:05 +0300 Message-Id: <20220404082912.6885-6-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> References: <20220404082912.6885-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: Rob Herring Cc: devicetree@vger.kernel.org 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 4 08:29: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: 556136 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 40E58C433EF for ; Mon, 4 Apr 2022 08:30:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237817AbiDDIcJ (ORCPT ); Mon, 4 Apr 2022 04:32:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45890 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236697AbiDDIcE (ORCPT ); Mon, 4 Apr 2022 04:32:04 -0400 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 411A820F57 for ; Mon, 4 Apr 2022 01:30:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1649061009; x=1680597009; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=jjjQqIuN0yiQ90X0T0tHHZtNLdFkRX4uHBf0A3DdG+8=; b=G1iugGTe0mHF9GIcQM7TuVFIb+YxmIrueMXD75ZKtzlrX5etHG8Iauyw N3zYFiALDA74PHJU+PrbbH6ZKdhXaba1CeszppG3us2+mZ4k6TSxfCK+S HNaxydu+DvQzF8gFykmK08f7f+4iMELIxkBIB1cXa1gv2QCGVyP1eSusC GW9vxh/0Uo2rzKY2+pVPQAghxmWfiHTyo+4ahGrDm9mCtdnmhkk1j4wB+ VVF/lC0EIjlmzEo4WavOc/zQifg46hvFDkA9b5TZnx1KFAN+2bZqkwM3C stxFNag0/W4JFtZC7reR+uHzL2Y5xfXVfC8lud+caURL2MOSnv/2pth20 A==; X-IronPort-AV: E=McAfee;i="6200,9189,10306"; a="258046471" X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="258046471" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:30:09 -0700 X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="569293485" Received: from rhamza-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.251.211.126]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:30:05 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Lukas Wunner , Andy Shevchenko Cc: Johan Hovold , heiko@sntech.de, giulio.benetti@micronovasrl.com, Heikki Krogerus , =?utf-8?q?Uwe_Kleine-K?= =?utf-8?q?=C3=B6nig?= , =?utf-8?q?Ilpo_J?= =?utf-8?q?=C3=A4rvinen?= Subject: [PATCH v2 06/12] ACPI / property: Document RS485 _DSD properties Date: Mon, 4 Apr 2022 11:29:06 +0300 Message-Id: <20220404082912.6885-7-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> References: <20220404082912.6885-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 4 08:29:07 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: 556464 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 B0794C4167B for ; Mon, 4 Apr 2022 08:30:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238088AbiDDIcS (ORCPT ); Mon, 4 Apr 2022 04:32:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46722 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237592AbiDDIcQ (ORCPT ); Mon, 4 Apr 2022 04:32:16 -0400 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3047325590; Mon, 4 Apr 2022 01:30:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1649061020; x=1680597020; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ABizxv2oeYO2wwl4Dd5x36/ryIakHx/dr6Yh5+l52KI=; b=J91TomdTbrFgF+3NZ+k6Rqf9lTNSN9eW0jIXrPQlh9ytH5lXzaHai3mj 7v8u/DMKnrm9kJn/r3H6qhTyCcI7gX6CfOHN1VQY0ZIbgqL4UVUtzJSv+ EEDRQUwAl5Brg/8et5SHRuALN4fICWUlU0+g0Pn96mbRmm/VtDMYKN2Xn 21T7KYwR5cIDA7+VxKjuQV7RHqcVD36rJVVm84N9/QsrJkeVbaAXKGAjA /UUqJYA/l3mN6SeQ3BaVMWa1VSDJhzcq8vq2f4SxRR4d19kS9j7FfXI26 NJS508qoMnesTz5LjYhirai0/iokO1kESF//ZUCFbpgh9YbBegWQT9cgc w==; X-IronPort-AV: E=McAfee;i="6200,9189,10306"; a="323639795" X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="323639795" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:30:19 -0700 X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="569293542" Received: from rhamza-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.251.211.126]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:30:10 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Lukas Wunner , Andy Shevchenko Cc: Johan Hovold , heiko@sntech.de, giulio.benetti@micronovasrl.com, Heikki Krogerus , =?utf-8?q?Uwe_Kleine-K?= =?utf-8?q?=C3=B6nig?= , =?utf-8?q?Ilpo_J?= =?utf-8?q?=C3=A4rvinen?= , 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, "David S. Miller" , sparclinux@vger.kernel.org, Arnd Bergmann , linux-arch@vger.kernel.org, linux-usb@vger.kernel.org Subject: [PATCH v2 07/12] serial: termbits: ADDRB to indicate 9th bit addressing mode Date: Mon, 4 Apr 2022 11:29:07 +0300 Message-Id: <20220404082912.6885-8-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> References: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org Add ADDRB to termbits to indicate 9th bit addressing mode. This change is necessary for supporting devices with RS485 multipoint addressing [*]. A later 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 an earlier patch. [*] 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: "David S. Miller" Cc: sparclinux@vger.kernel.org Cc: Arnd Bergmann Cc: linux-arch@vger.kernel.org Cc: linux-usb@vger.kernel.org Signed-off-by: Ilpo Järvinen --- arch/alpha/include/uapi/asm/termbits.h | 1 + arch/mips/include/uapi/asm/termbits.h | 1 + arch/parisc/include/uapi/asm/termbits.h | 1 + arch/powerpc/include/uapi/asm/termbits.h | 1 + arch/sparc/include/uapi/asm/termbits.h | 1 + drivers/char/pcmcia/synclink_cs.c | 2 ++ drivers/ipack/devices/ipoctal.c | 2 ++ drivers/mmc/core/sdio_uart.c | 2 ++ drivers/net/usb/hso.c | 3 ++- drivers/s390/char/tty3270.c | 3 +++ drivers/staging/greybus/uart.c | 2 ++ drivers/tty/amiserial.c | 6 +++++- drivers/tty/moxa.c | 1 + drivers/tty/mxser.c | 1 + drivers/tty/serial/serial_core.c | 2 ++ drivers/tty/synclink_gt.c | 2 ++ drivers/tty/tty_ioctl.c | 2 ++ drivers/usb/class/cdc-acm.c | 2 ++ drivers/usb/serial/usb-serial.c | 6 ++++-- include/uapi/asm-generic/termbits.h | 1 + net/bluetooth/rfcomm/tty.c | 2 ++ 21 files changed, 40 insertions(+), 4 deletions(-) diff --git a/arch/alpha/include/uapi/asm/termbits.h b/arch/alpha/include/uapi/asm/termbits.h index 4575ba34a0ea..285169c794ec 100644 --- a/arch/alpha/include/uapi/asm/termbits.h +++ b/arch/alpha/include/uapi/asm/termbits.h @@ -180,6 +180,7 @@ struct ktermios { #define HUPCL 00040000 #define CLOCAL 00100000 +#define ADDRB 010000000 /* address bit */ #define CMSPAR 010000000000 /* mark or space (stick) parity */ #define CRTSCTS 020000000000 /* flow control */ diff --git a/arch/mips/include/uapi/asm/termbits.h b/arch/mips/include/uapi/asm/termbits.h index dfeffba729b7..e7ea31cfec78 100644 --- a/arch/mips/include/uapi/asm/termbits.h +++ b/arch/mips/include/uapi/asm/termbits.h @@ -181,6 +181,7 @@ struct ktermios { #define B3000000 0010015 #define B3500000 0010016 #define B4000000 0010017 +#define ADDRB 0020000 /* address bit */ #define CIBAUD 002003600000 /* input baud rate */ #define CMSPAR 010000000000 /* mark or space (stick) parity */ #define CRTSCTS 020000000000 /* flow control */ diff --git a/arch/parisc/include/uapi/asm/termbits.h b/arch/parisc/include/uapi/asm/termbits.h index 40e920f8d683..629be061f5d5 100644 --- a/arch/parisc/include/uapi/asm/termbits.h +++ b/arch/parisc/include/uapi/asm/termbits.h @@ -158,6 +158,7 @@ struct ktermios { #define B3000000 0010015 #define B3500000 0010016 #define B4000000 0010017 +#define ADDRB 0020000 /* address bit */ #define CIBAUD 002003600000 /* input baud rate */ #define CMSPAR 010000000000 /* mark or space (stick) parity */ #define CRTSCTS 020000000000 /* flow control */ diff --git a/arch/powerpc/include/uapi/asm/termbits.h b/arch/powerpc/include/uapi/asm/termbits.h index ed18bc61f63d..1b778ac562a4 100644 --- a/arch/powerpc/include/uapi/asm/termbits.h +++ b/arch/powerpc/include/uapi/asm/termbits.h @@ -171,6 +171,7 @@ struct ktermios { #define HUPCL 00040000 #define CLOCAL 00100000 +#define ADDRB 00200000 /* address bit */ #define CMSPAR 010000000000 /* mark or space (stick) parity */ #define CRTSCTS 020000000000 /* flow control */ diff --git a/arch/sparc/include/uapi/asm/termbits.h b/arch/sparc/include/uapi/asm/termbits.h index ce5ad5d0f105..4ad60c4acf65 100644 --- a/arch/sparc/include/uapi/asm/termbits.h +++ b/arch/sparc/include/uapi/asm/termbits.h @@ -200,6 +200,7 @@ struct ktermios { #define B3000000 0x00001011 #define B3500000 0x00001012 #define B4000000 0x00001013 */ +#define ADDRB 0x00002000 /* address bit */ #define CIBAUD 0x100f0000 /* input baud rate (not used) */ #define CMSPAR 0x40000000 /* mark or space (stick) parity */ #define CRTSCTS 0x80000000 /* flow control */ diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 78baba55a8b5..d179b9b57a25 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -2287,6 +2287,8 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term == RELEVANT_IFLAG(old_termios->c_iflag))) return; + tty->termios.c_cflag &= ~ADDRB; + mgslpc_change_params(info, tty); /* Handle transition to B0 status */ diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c index 20d2b9ec1227..d66cc9683ebc 100644 --- a/drivers/ipack/devices/ipoctal.c +++ b/drivers/ipack/devices/ipoctal.c @@ -506,6 +506,8 @@ static void ipoctal_set_termios(struct tty_struct *tty, struct ipoctal_channel *channel = tty->driver_data; speed_t baud; + tty->termios.c_cflag &= ~ADDRB; + cflag = tty->termios.c_cflag; /* Disable and reset everything before change the setup */ diff --git a/drivers/mmc/core/sdio_uart.c b/drivers/mmc/core/sdio_uart.c index 04c0823e0359..7432b01379ef 100644 --- a/drivers/mmc/core/sdio_uart.c +++ b/drivers/mmc/core/sdio_uart.c @@ -880,6 +880,8 @@ static void sdio_uart_set_termios(struct tty_struct *tty, if (sdio_uart_claim_func(port) != 0) return; + tty->termios.c_cflag &= ~ADDRB; + sdio_uart_change_speed(port, &tty->termios, old_termios); /* Handle transition to B0 status */ diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index f97813a4e8d1..b687327bc7b1 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -1099,7 +1099,8 @@ static void _hso_serial_set_termios(struct tty_struct *tty) ~(CSIZE /* no size */ | PARENB /* disable parity bit */ | CBAUD /* clear current baud rate */ - | CBAUDEX); /* clear current buad rate */ + | CBAUDEX /* clear current baud rate */ + | ADDRB); /* disable 9th (addr) bit */ tty->termios.c_cflag |= CS8; /* character size 8 bits */ diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index 5c83f71c1d0e..253d2997a1d3 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c @@ -1768,6 +1768,9 @@ tty3270_set_termios(struct tty_struct *tty, struct ktermios *old) tp = tty->driver_data; if (!tp) return; + + tty->termios.c_cflag &= ~ADDRB; + spin_lock_bh(&tp->view.lock); if (L_ICANON(tty)) { new = L_ECHO(tty) ? TF_INPUT: TF_INPUTN; diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index dc4ed0ff1ae2..83e73aefde0f 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -487,6 +487,8 @@ static void gb_tty_set_termios(struct tty_struct *tty, struct ktermios *termios = &tty->termios; u8 newctrl = gb_tty->ctrlout; + termios->c_cflag &= ~ADDRB; + newline.rate = cpu_to_le32(tty_get_baud_rate(tty)); newline.format = termios->c_cflag & CSTOPB ? GB_SERIAL_2_STOP_BITS : GB_SERIAL_1_STOP_BITS; diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 533d02b38e02..3ca97007bd6e 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -1175,7 +1175,11 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct serial_state *info = tty->driver_data; unsigned long flags; - unsigned int cflag = tty->termios.c_cflag; + unsigned int cflag; + + tty->termios.c_cflag &= ~ADDRB; + + cflag = tty->termios.c_cflag; change_speed(tty, info, old_termios); diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c index f3c72ab1476c..07cd88152d58 100644 --- a/drivers/tty/moxa.c +++ b/drivers/tty/moxa.c @@ -2050,6 +2050,7 @@ static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio, ofsAddr = port->tableAddr; + termio->c_cflag &= ~ADDRB; mode = termio->c_cflag & CSIZE; if (mode == CS5) mode = MX_CS5; diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 836c9eca2946..220676363a07 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -577,6 +577,7 @@ static void mxser_change_speed(struct tty_struct *tty, struct ktermios *old_term struct mxser_port *info = tty->driver_data; unsigned cflag, cval; + tty->termios.c_cflag &= ~ADDRB; cflag = tty->termios.c_cflag; if (mxser_set_baud(tty, tty_get_baud_rate(tty))) { diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index c6ac91033e38..de198c2acefe 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1493,6 +1493,8 @@ static void uart_set_termios(struct tty_struct *tty, goto out; } + tty->termios.c_cflag &= ~ADDRB; + uart_change_speed(tty, state, old_termios); /* reload cflag from termios; port driver may have overridden flags */ cflag = tty->termios.c_cflag; diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index 25c558e65ece..ee767cea18ed 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c @@ -714,6 +714,8 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) DBGINFO(("%s set_termios\n", tty->driver->name)); + tty->termios.c_cflag &= ~ADDRB; + change_params(info); /* Handle transition to B0 status */ diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index 63181925ec1a..934037d78868 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -319,6 +319,8 @@ unsigned char tty_get_frame_size(unsigned int cflag) bits++; if (cflag & PARENB) bits++; + if (cflag & ADDRB) + bits++; return bits; } diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 9b9aea24d58c..fd246ec70da8 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1056,6 +1056,8 @@ static void acm_tty_set_termios(struct tty_struct *tty, struct usb_cdc_line_coding newline; int newctrl = acm->ctrlout; + termios->c_cflag &= ~ADDRB; + newline.dwDTERate = cpu_to_le32(tty_get_baud_rate(tty)); newline.bCharFormat = termios->c_cflag & CSTOPB ? 2 : 0; newline.bParityType = termios->c_cflag & PARENB ? diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 24101bd7fcad..8d1d170eb7e6 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -525,10 +525,12 @@ static void serial_set_termios(struct tty_struct *tty, struct ktermios *old) dev_dbg(&port->dev, "%s\n", __func__); - if (port->serial->type->set_termios) + if (port->serial->type->set_termios) { + tty->termios.c_cflag &= ~ADDRB; port->serial->type->set_termios(tty, port, old); - else + } else { tty_termios_copy_hw(&tty->termios, old); + } } static int serial_break(struct tty_struct *tty, int break_state) diff --git a/include/uapi/asm-generic/termbits.h b/include/uapi/asm-generic/termbits.h index 2fbaf9ae89dd..5f5228329d45 100644 --- a/include/uapi/asm-generic/termbits.h +++ b/include/uapi/asm-generic/termbits.h @@ -157,6 +157,7 @@ struct ktermios { #define B3000000 0010015 #define B3500000 0010016 #define B4000000 0010017 +#define ADDRB 0020000 /* address bit */ #define CIBAUD 002003600000 /* input baud rate */ #define CMSPAR 010000000000 /* mark or space (stick) parity */ #define CRTSCTS 020000000000 /* flow control */ diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index ebd78fdbd6e8..832e725f23ab 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -871,6 +871,8 @@ static void rfcomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old) if (!dev || !dev->dlc || !dev->dlc->session) return; + new->c_cflag &= ~ADDRB; + /* Handle turning off CRTSCTS */ if ((old->c_cflag & CRTSCTS) && !(new->c_cflag & CRTSCTS)) BT_DBG("Turning off CRTSCTS unsupported"); From patchwork Mon Apr 4 08:29: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: 556134 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 B531DC4167B for ; Mon, 4 Apr 2022 08:30:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238728AbiDDIcg (ORCPT ); Mon, 4 Apr 2022 04:32:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47688 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238460AbiDDIc2 (ORCPT ); Mon, 4 Apr 2022 04:32:28 -0400 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AF2F331937; Mon, 4 Apr 2022 01:30:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1649061030; x=1680597030; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=maSL2cxRqazwpa1HcB3zULcND5265JQwoKkKrstAzyI=; b=XsgUyjLL7lS/rQA4FlMSwpHSUheSIGViHu6RFDBG5F1wlnnFSuTjt9mS Qgaw/XR91l7XebFA3qP/B2+CGEBj/TaWqJKICwSA1n0syhYC0GAU5Dnur lHnoADPBlFOpha9dgt4cZw8VP5ywNkr+UzWblpOos2q4FOcsVaYapbHE3 Q0cjTHYzZoR/9c/qta2ptn1hgcCn11KIV7xHCZFyZodJb7V4qfqA0t5z6 0no/Qm+Vd/TBzwbcXkAsL95TLQSO2aUHMpaaRSJ0C7YO37ik7W5KSI15R HMaESRyhC5g3i/5Qk9SgHIWe23IBd5xID2Uc0lyySV9oodUch+4ay2ZME w==; X-IronPort-AV: E=McAfee;i="6200,9189,10306"; a="241052980" X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="241052980" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:30:30 -0700 X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="569293625" Received: from rhamza-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.251.211.126]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:30:20 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Lukas Wunner , Andy Shevchenko Cc: Johan Hovold , heiko@sntech.de, giulio.benetti@micronovasrl.com, Heikki Krogerus , =?utf-8?q?Uwe_Kleine-K?= =?utf-8?q?=C3=B6nig?= , =?utf-8?q?Ilpo_J?= =?utf-8?q?=C3=A4rvinen?= , 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 v2 08/12] serial: General support for multipoint addresses Date: Mon, 4 Apr 2022 11:29:08 +0300 Message-Id: <20220404082912.6885-9-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> References: <20220404082912.6885-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 ++++++++++++++++++- include/linux/serial_core.h | 6 ++ include/uapi/asm-generic/ioctls.h | 3 + include/uapi/linux/serial.h | 8 +++ 13 files changed, 123 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/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 4 08:29:09 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: 556463 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 95206C4167E for ; Mon, 4 Apr 2022 08:30:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229678AbiDDIcg (ORCPT ); Mon, 4 Apr 2022 04:32:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47818 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238597AbiDDIca (ORCPT ); Mon, 4 Apr 2022 04:32:30 -0400 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 767AE344F4 for ; Mon, 4 Apr 2022 01:30: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=1649061034; x=1680597034; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=bLfpST78W5acINQtiR37FmtdEkwFx1MA1jfZ9QhhVZk=; b=FR0e1RInrgwo0KSBfbI2xWV6UI5JzUkrJKQaDtv9jgUPr5AEj7lKCDFh QI9qcRrCpqDJIKAWVmcrUEERdIyz0ay2ak7EUdob45pULHHLfMm9K5+n3 tfc9T7+xEmlFDcouB2TkNxtFZ4pPS5Aiia9R9+09vhuH+P84/DPct3uXm eL3IMQHSUolfs8TFkWAeQZfSlkaLKOcGz+Qn29TU58qPZoBBSE98vDav9 B+TwfLHVHpWhPisOLB27dXe+LOHuimpWgGa+7PqIw6UClYleAOM40HJkx wEGgO1Rgipv5VEkUjIMABJafdLtWiDN5xtje39NMEietNkcZIxZtjGNdz Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10306"; a="241053003" X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="241053003" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:30:34 -0700 X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="569293760" Received: from rhamza-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.251.211.126]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:30:30 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Lukas Wunner , Andy Shevchenko Cc: Johan Hovold , heiko@sntech.de, giulio.benetti@micronovasrl.com, Heikki Krogerus , =?utf-8?q?Uwe_Kleine-K?= =?utf-8?q?=C3=B6nig?= , =?utf-8?q?Ilpo_J?= =?utf-8?q?=C3=A4rvinen?= Subject: [PATCH v2 09/12] serial: 8250: make saved LSR larger Date: Mon, 4 Apr 2022 11:29:09 +0300 Message-Id: <20220404082912.6885-10-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> References: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org DW flags address received as BIT(8) in LSR. In order to not lose that on read, enlarge lsr_saved_flags and adjust related call chains which passed chars previously. Signed-off-by: Ilpo Järvinen --- drivers/tty/serial/8250/8250_port.c | 8 ++++---- include/linux/serial_8250.h | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 276c5281aaa0..6e85ad0fade6 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1585,7 +1585,7 @@ static inline void __start_tx(struct uart_port *port) if (serial8250_set_THRI(up)) { if (up->bugs & UART_BUG_TXEN) { - unsigned char lsr; + unsigned int lsr; lsr = serial_in(up, UART_LSR); up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; @@ -1741,7 +1741,7 @@ static void serial8250_enable_ms(struct uart_port *port) serial8250_rpm_put(up); } -void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr) +void serial8250_read_char(struct uart_8250_port *up, unsigned int lsr) { struct uart_port *port = &up->port; unsigned char ch; @@ -1808,7 +1808,7 @@ EXPORT_SYMBOL_GPL(serial8250_read_char); * value, and returns the remaining LSR bits not handled * by this Rx routine. */ -unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) +unsigned int serial8250_rx_chars(struct uart_8250_port *up, unsigned int lsr) { struct uart_port *port = &up->port; int max_count = 256; @@ -1930,7 +1930,7 @@ static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir) */ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) { - unsigned char status; + unsigned int status; struct uart_8250_port *up = up_to_u8250p(port); bool skip_rx = false; unsigned long flags; diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index ff84a3ed10ea..921df4c60062 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -119,7 +119,7 @@ struct uart_8250_port { * be immediately processed. */ #define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS - unsigned char lsr_saved_flags; + u16 lsr_saved_flags; #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA unsigned char msr_saved_flags; @@ -170,8 +170,8 @@ extern void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud, unsigned int quot_frac); extern int fsl8250_handle_irq(struct uart_port *port); int serial8250_handle_irq(struct uart_port *port, unsigned int iir); -unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr); -void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr); +unsigned int serial8250_rx_chars(struct uart_8250_port *up, unsigned int lsr); +void serial8250_read_char(struct uart_8250_port *up, unsigned int lsr); void serial8250_tx_chars(struct uart_8250_port *up); unsigned int serial8250_modem_status(struct uart_8250_port *up); void serial8250_init_port(struct uart_8250_port *up); From patchwork Mon Apr 4 08:29: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: 556135 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 00502C433EF for ; Mon, 4 Apr 2022 08:30:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230464AbiDDIcf (ORCPT ); Mon, 4 Apr 2022 04:32:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48190 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234768AbiDDIce (ORCPT ); Mon, 4 Apr 2022 04:32:34 -0400 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CF9C534BBE for ; Mon, 4 Apr 2022 01:30:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1649061038; x=1680597038; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=s3dHyn4uqNAAp01ksOGaMh6nU3W65jOhukVGVTf+wL8=; b=oK2HN9aq/2gEqgVCXuhAPAUXjztn7xgK+nk13VdslFiyku4q2L8KQYey RlFgw2hO4cLFtatHIpK4dxU/P41oDHnG3Gjlk1s74mBQJQVev79WTytky iP026MuRZ3QWMKkhrXwuLTZzjLqHCc1aO1yjKFF5wbsRBVt3HEfIjNQJu FOdw1SVzyySCsAoYwQkRh/mYzKdt61uCRRrAux64EbhmCkzryEV0nJQ7d fDl14oS6PrMPeycqdzV9g8Ezd2B5FqVEf1Z9T8Rs1e/JsE7tx9kO9vwBI B1UIhEFbcSbv1i9OwW7Ucdiv0AUxapqvTZSxJbWG8170RAV7OF2ygIfdl A==; X-IronPort-AV: E=McAfee;i="6200,9189,10306"; a="241053024" X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="241053024" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:30:38 -0700 X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="569293785" Received: from rhamza-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.251.211.126]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:30:35 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Lukas Wunner , Andy Shevchenko Cc: Johan Hovold , heiko@sntech.de, giulio.benetti@micronovasrl.com, Heikki Krogerus , =?utf-8?q?Uwe_Kleine-K?= =?utf-8?q?=C3=B6nig?= , =?utf-8?q?Ilpo_J?= =?utf-8?q?=C3=A4rvinen?= Subject: [PATCH v2 10/12] serial: 8250: create lsr_save_mask Date: Mon, 4 Apr 2022 11:29:10 +0300 Message-Id: <20220404082912.6885-11-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> References: <20220404082912.6885-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 6e85ad0fade6..b3289ef117d1 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1588,7 +1588,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); } @@ -2019,7 +2019,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); @@ -2100,7 +2100,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 4 08:29:11 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: 556133 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 2833DC433F5 for ; Mon, 4 Apr 2022 08:31:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231741AbiDDIc5 (ORCPT ); Mon, 4 Apr 2022 04:32:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48536 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238460AbiDDIck (ORCPT ); Mon, 4 Apr 2022 04:32:40 -0400 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DD5A935AA4 for ; Mon, 4 Apr 2022 01:30: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=1649061043; x=1680597043; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=RoHbAwM38hUlTpoJ3Pktnqw41Zoe+0jl6/0G7fo9OQI=; b=TdOtpHXT1cxrMGHSn76XHmf/j+Yqe1iMUJBZmxP34KUf5bDp5QiUlcgo KmUrH0AFL7A1Ny7unnFG5trjEOdHWv6km3WWOu7mC7lMlLWFfbM4VlPiJ u7+/KB7DjP9Ex9PMN4j5+GGUzrvxteoqfhoV2W/aiT3SjiDLC1KwngWJl Xh2LdZKhbSARAn3pOIgbGjHzAf0IE0uvjTVuCUGEkFx+F1MxJDwkZXsZQ f4fzKepY4MIOFbMoIus0iVv8VkJIf5uh3bl6QFBcEW7MR/d83i3AKBXq0 u4QXIYHWk07YTE38gD3k2Kriow7t3T5auzY6nq+11zLanBWLTRwK9pwuf w==; X-IronPort-AV: E=McAfee;i="6200,9189,10306"; a="241053050" X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="241053050" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:30:43 -0700 X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="569293806" Received: from rhamza-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.251.211.126]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:30:39 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Lukas Wunner , Andy Shevchenko Cc: Johan Hovold , heiko@sntech.de, giulio.benetti@micronovasrl.com, Heikki Krogerus , =?utf-8?q?Uwe_Kleine-K?= =?utf-8?q?=C3=B6nig?= , =?utf-8?q?Ilpo_J?= =?utf-8?q?=C3=A4rvinen?= Subject: [PATCH v2 11/12] serial: 8250_lpss: Use 32-bit reads Date: Mon, 4 Apr 2022 11:29:11 +0300 Message-Id: <20220404082912.6885-12-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> References: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org Use 32-bit reads in order to not lose higher bits of DW UART regs. Signed-off-by: Ilpo Järvinen --- drivers/tty/serial/8250/8250_lpss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c index 0f5af061e0b4..4ba43bef9933 100644 --- a/drivers/tty/serial/8250/8250_lpss.c +++ b/drivers/tty/serial/8250/8250_lpss.c @@ -330,7 +330,7 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id) uart.port.irq = pci_irq_vector(pdev, 0); uart.port.private_data = &lpss->data; uart.port.type = PORT_16550A; - uart.port.iotype = UPIO_MEM; + uart.port.iotype = UPIO_MEM32; uart.port.regshift = 2; uart.port.uartclk = lpss->board->base_baud * 16; uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE; From patchwork Mon Apr 4 08:29:12 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: 556462 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 980B4C433FE for ; Mon, 4 Apr 2022 08:31:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239990AbiDDIc4 (ORCPT ); Mon, 4 Apr 2022 04:32:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48916 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232387AbiDDIco (ORCPT ); Mon, 4 Apr 2022 04:32:44 -0400 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A19F835AB2 for ; Mon, 4 Apr 2022 01:30:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1649061048; x=1680597048; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=uZIUA3FLTXk2bZJ4FTB/dKVWpi0ewCYFs8poRjjVkcE=; b=VHhOzQQeyPZ/LK/0wtYE4mvS/4ExZMZiVnGoy/jHwL8ocLbGwdcrE3kq +qZXwWFcGqlFxSSTC6MPjyMKHU1y3xxmK7TB7OOMX3ZYphqvwII/RUDlD 6vdu+RsZU6wyaheolQG0YGXvdvDHTJGw8HyBNewO+tpI/bIIbVWRFLwNR h9OePvO8WJnzsLt71M6G/LJoQDzSnNIc1WwNKlH9EJYCeW14TfRAmv7pj zXweMo+u+5STVOBkcxCPPmGV2GZI84Cd5vmC55wMnS0EjCK2718RFNj5t hxYQ4CYeDdcSANdxmMCuE/HyBMipbXoOsmxWXGfnR9ECLoBSgXdDBHk9J g==; X-IronPort-AV: E=McAfee;i="6200,9189,10306"; a="241053072" X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="241053072" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:30:48 -0700 X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="569293844" Received: from rhamza-mobl.ger.corp.intel.com (HELO ijarvine-MOBL2.ger.corp.intel.com) ([10.251.211.126]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Apr 2022 01:30:44 -0700 From: =?utf-8?q?Ilpo_J=C3=A4rvinen?= To: linux-serial@vger.kernel.org, Greg KH , Jiri Slaby , Lukas Wunner , Andy Shevchenko Cc: Johan Hovold , heiko@sntech.de, giulio.benetti@micronovasrl.com, Heikki Krogerus , =?utf-8?q?Uwe_Kleine-K?= =?utf-8?q?=C3=B6nig?= , =?utf-8?q?Ilpo_J?= =?utf-8?q?=C3=A4rvinen?= , Raymond Tan , Lakshmi Sowjanya Subject: [PATCH v2 12/12] serial: 8250_dwlib: Support for 9th bit multipoint addressing Date: Mon, 4 Apr 2022 11:29:12 +0300 Message-Id: <20220404082912.6885-13-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220404082912.6885-1-ilpo.jarvinen@linux.intel.com> References: <20220404082912.6885-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 | 139 +++++++++++++++++++++++++++ drivers/tty/serial/8250/8250_dwlib.h | 2 + 2 files changed, 141 insertions(+) diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c index 04852af4c024..ab4b42cdeb03 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,15 @@ #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 */ +/* 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 +37,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 +105,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 & 0xff); + 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 & 0xff); + 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) & 0xff; + 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) & 0xff; + } + + 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 +255,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 +310,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);