On Sun, 2022-10-16 at 10:02 +0200, Lukas Wunner wrote: > Recent TI Sitara SoCs such as AM64/AM65 have gained the ability to > automatically assert RTS when data is transmitted, obviating the need > to emulate this functionality in software. > > The feature is controlled through new DIR_EN and DIR_POL bits in the > Mode Definition Register 3. For details see page 8783 and 8890 of the > AM65 TRM: > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.ti.com%2Flit%2Fug%2Fspruid7e%2Fspruid7e.pdf&data=05%7C01%7Cbaocheng.su%40ad011.siemens.com%7Ce23a8a66efb546fac6c608daaf4cb3dd%7C38ae3bcd95794fd4addab42e1495d55a%7C1%7C0%7C638015041558171363%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=YHG2%2F82aqVxQMqAgSjVlonkPdy%2FTtt34LC97U1%2F%2F1%2BQ%3D&reserved=0 > > Signed-off-by: Lukas Wunner <lukas@xxxxxxxxx> > Cc: Ilpo Järvinen <ilpo.jarvinen@xxxxxxxxxxxxxxx> > Cc: Su Bao Cheng <baocheng.su@xxxxxxxxxxx> My colleague has tested this patch on Siemens IOT2050, it works. Tested-by: Zeng Chao <chao.zeng@xxxxxxxxxxx> - Baocheng Su > Cc: Vignesh Raghavendra <vigneshr@xxxxxx> > Cc: Jan Kiszka <jan.kiszka@xxxxxxxxxxx> > Cc: Bin Liu <b-liu@xxxxxx> > --- > Changes v1 -> v2: > > * Fall back to RS485 software emulation if RTS GPIO is used or > user-requested delays exceed fixed hardware delays (Bin Liu, > Vignesh Raghavendra) > > * Set fixed hardware delay upon RTS assertion to 1 clock cycle > instead of 0 previously > > * Add code comment to clarify that rs485_supported is the same > for software emulation and native RS485 (Ilpo Järvinen) > > drivers/tty/serial/8250/8250_omap.c | 85 > ++++++++++++++++++++++++++++- > 1 file changed, 82 insertions(+), 3 deletions(-) > > diff --git a/drivers/tty/serial/8250/8250_omap.c > b/drivers/tty/serial/8250/8250_omap.c > index 68f5a167377f..0648e858a7cd 100644 > --- a/drivers/tty/serial/8250/8250_omap.c > +++ b/drivers/tty/serial/8250/8250_omap.c > @@ -44,6 +44,7 @@ > #define UART_HAS_EFR2 BIT(4) > #define UART_HAS_RHR_IT_DIS BIT(5) > #define UART_RX_TIMEOUT_QUIRK BIT(6) > +#define UART_HAS_NATIVE_RS485 BIT(7) > > #define OMAP_UART_FCR_RX_TRIG 6 > #define OMAP_UART_FCR_TX_TRIG 4 > @@ -101,6 +102,11 @@ > #define UART_OMAP_IER2 0x1B > #define UART_OMAP_IER2_RHR_IT_DIS BIT(2) > > +/* Mode Definition Register 3 */ > +#define UART_OMAP_MDR3 0x20 > +#define UART_OMAP_MDR3_DIR_POL BIT(3) > +#define UART_OMAP_MDR3_DIR_EN BIT(4) > + > /* Enhanced features register 2 */ > #define UART_OMAP_EFR2 0x23 > #define UART_OMAP_EFR2_TIMEOUT_BEHAVE BIT(6) > @@ -112,6 +118,7 @@ struct omap8250_priv { > int line; > u8 habit; > u8 mdr1; > + u8 mdr3; > u8 efr; > u8 scr; > u8 wer; > @@ -345,7 +352,10 @@ static void omap8250_restore_regs(struct > uart_8250_port *up) > > up->port.ops->set_mctrl(&up->port, up->port.mctrl); > > - if (up->port.rs485.flags & SER_RS485_ENABLED) > + serial_out(up, UART_OMAP_MDR3, priv->mdr3); > + > + if (up->port.rs485.flags & SER_RS485_ENABLED && > + up->port.rs485_config == serial8250_em485_config) > serial8250_em485_stop_tx(up); > } > > @@ -793,6 +803,74 @@ static void omap_8250_unthrottle(struct uart_port > *port) > pm_runtime_put_autosuspend(port->dev); > } > > +static int omap8250_rs485_config(struct uart_port *port, > + struct ktermios *termios, > + struct serial_rs485 *rs485) > +{ > + struct omap8250_priv *priv = port->private_data; > + struct uart_8250_port *up = up_to_u8250p(port); > + u32 fixed_delay_rts_before_send = 0; > + u32 fixed_delay_rts_after_send = 0; > + unsigned int baud; > + > + /* > + * There is a fixed delay of 3 bit clock cycles after the TX > shift > + * register is going empty to allow time for the stop bit to > transition > + * through the transceiver before direction is changed to > receive. > + * > + * Additionally there appears to be a 1 bit clock delay > between writing > + * to the THR register and transmission of the start bit, per > page 8783 > + * of the AM65 TRM: > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.ti.com%2Flit%2Fug%2Fspruid7e%2Fspruid7e.pdf&data=05%7C01%7Cbaocheng.su%40ad011.siemens.com%7Ce23a8a66efb546fac6c608daaf4cb3dd%7C38ae3bcd95794fd4addab42e1495d55a%7C1%7C0%7C638015041558171363%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=YHG2%2F82aqVxQMqAgSjVlonkPdy%2FTtt34LC97U1%2F%2F1%2BQ%3D&reserved=0 > + */ > + if (priv->quot) { > + if (priv->mdr1 & UART_OMAP_MDR1_16X_MODE) > + baud = port->uartclk / (16 * priv->quot); > + else > + baud = port->uartclk / (13 * priv->quot); > + > + fixed_delay_rts_after_send = 3 * MSEC_PER_SEC / baud; > + fixed_delay_rts_before_send = 1 * MSEC_PER_SEC / baud; > + } > + > + /* > + * Fall back to RS485 software emulation if the UART is > missing > + * hardware support, if the device tree specifies an > mctrl_gpio > + * (indicates that RTS is unavailable due to a pinmux > conflict) > + * or if the requested delays exceed the fixed hardware > delays. > + */ > + if (!(priv->habit & UART_HAS_NATIVE_RS485) || > + mctrl_gpio_to_gpiod(up->gpios, UART_GPIO_RTS) || > + rs485->delay_rts_after_send > fixed_delay_rts_after_send > || > + rs485->delay_rts_before_send > > fixed_delay_rts_before_send) { > + priv->mdr3 &= ~UART_OMAP_MDR3_DIR_EN; > + serial_out(up, UART_OMAP_MDR3, priv->mdr3); > + > + port->rs485_config = serial8250_em485_config; > + return serial8250_em485_config(port, termios, rs485); > + } > + > + rs485->delay_rts_after_send = fixed_delay_rts_after_send; > + rs485->delay_rts_before_send = fixed_delay_rts_before_send; > + > + if (rs485->flags & SER_RS485_ENABLED) > + priv->mdr3 |= UART_OMAP_MDR3_DIR_EN; > + else > + priv->mdr3 &= ~UART_OMAP_MDR3_DIR_EN; > + > + /* > + * Retain same polarity semantics as RS485 software emulation, > + * i.e. SER_RS485_RTS_ON_SEND means driving RTS low on send. > + */ > + if (rs485->flags & SER_RS485_RTS_ON_SEND) > + priv->mdr3 &= ~UART_OMAP_MDR3_DIR_POL; > + else > + priv->mdr3 |= UART_OMAP_MDR3_DIR_POL; > + > + serial_out(up, UART_OMAP_MDR3, priv->mdr3); > + > + return 0; > +} > + > #ifdef CONFIG_SERIAL_8250_DMA > static int omap_8250_rx_dma(struct uart_8250_port *p); > > @@ -1242,7 +1320,7 @@ static struct omap8250_dma_params am33xx_dma = { > static struct omap8250_platdata am654_platdata = { > .dma_params = &am654_dma, > .habit = UART_HAS_EFR2 | UART_HAS_RHR_IT_DIS | > - UART_RX_TIMEOUT_QUIRK, > + UART_RX_TIMEOUT_QUIRK | > UART_HAS_NATIVE_RS485, > }; > > static struct omap8250_platdata am33xx_platdata = { > @@ -1335,7 +1413,8 @@ static int omap8250_probe(struct platform_device > *pdev) > up.port.shutdown = omap_8250_shutdown; > up.port.throttle = omap_8250_throttle; > up.port.unthrottle = omap_8250_unthrottle; > - up.port.rs485_config = serial8250_em485_config; > + up.port.rs485_config = omap8250_rs485_config; > + /* same rs485_supported for software emulation and native > RS485 */ > up.port.rs485_supported = serial8250_em485_supported; > up.rs485_start_tx = serial8250_em485_start_tx; > up.rs485_stop_tx = serial8250_em485_stop_tx;